diff options
author | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
---|---|---|
committer | Jef <jef@targetspot.com> | 2024-09-24 08:54:57 -0400 |
commit | 20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch) | |
tree | 12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/mp4v/mkv_mp4v_decoder.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/mp4v/mkv_mp4v_decoder.cpp')
-rw-r--r-- | Src/mp4v/mkv_mp4v_decoder.cpp | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/Src/mp4v/mkv_mp4v_decoder.cpp b/Src/mp4v/mkv_mp4v_decoder.cpp new file mode 100644 index 00000000..eedd7e88 --- /dev/null +++ b/Src/mp4v/mkv_mp4v_decoder.cpp @@ -0,0 +1,163 @@ +#include "mkv_mp4v_decoder.h" +#include "../Winamp/wa_ipc.h" // for YV12_PLANES +#include <mmsystem.h> +#include <assert.h> + +int MKVDecoderCreator::CreateVideoDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::VideoData *video_data, ifc_mkvvideodecoder **decoder) +{ + if (!strcmp(codec_id, "V_MPEG4/ISO/ASP") + || !strcmp(codec_id, "V_MPEG4/ISO/SP")) + { + VIDEOINFOHEADER header = {0, }; + + header.bmiHeader.biHeight = (LONG)video_data->pixel_height; + header.bmiHeader.biWidth = (LONG)video_data->pixel_width; + header.bmiHeader.biCompression = 'v4pm'; + + MFTDecoder *ctx = new MFTDecoder; + if (!ctx) { + return CREATEDECODER_FAILURE; + } + HRESULT hr = ctx->Open(&header); + if (FAILED(hr)) { + delete ctx; + return CREATEDECODER_FAILURE; + } + + if (ctx) + { + if (track_entry_data->codec_private && track_entry_data->codec_private_len) { + // mkv stores headers up to first VOP in codec_private + hr = ctx->Feed(track_entry_data->codec_private, track_entry_data->codec_private_len, 0); + if (FAILED(hr)) { + delete ctx; + return CREATEDECODER_FAILURE; + } + } + *decoder = new MKVMP4V(ctx, video_data); + return CREATEDECODER_SUCCESS; + } + else + { + return CREATEDECODER_FAILURE; + } + } + else if (!strcmp(codec_id, "V_MS/VFW/FOURCC")) + { + if (track_entry_data->codec_private && track_entry_data->codec_private_len) + { + const BITMAPINFOHEADER *header = (const BITMAPINFOHEADER *)track_entry_data->codec_private; + if (header->biCompression == 'DIVX' + || header->biCompression == '05XD') + { + if (track_entry_data->codec_private_len < 40) { + return CREATEDECODER_FAILURE; + } + + VIDEOINFOHEADER video_header = {0, }; + memcpy(&video_header.bmiHeader, header, 40); + assert(track_entry_data->codec_private_len == 40); + + MFTDecoder *ctx = new MFTDecoder; + if (!ctx) { + return CREATEDECODER_FAILURE; + } + if (FAILED(ctx->Open(&video_header))) { + delete ctx; + return CREATEDECODER_FAILURE; + } + + *decoder = new MKVMP4V(ctx, video_data); + return CREATEDECODER_SUCCESS; + } + } + return CREATEDECODER_NOT_MINE; + } + else + { + return CREATEDECODER_NOT_MINE; + } +} + + +#define CBCLASS MKVDecoderCreator +START_DISPATCH; +CB(CREATE_VIDEO_DECODER, CreateVideoDecoder) +END_DISPATCH; +#undef CBCLASS + +MKVMP4V::MKVMP4V(MFTDecoder *decoder, const nsmkv::VideoData *video_data) : decoder(decoder), video_data(video_data) +{ + +} + +MKVMP4V::~MKVMP4V() +{ + delete decoder; +} + +int MKVMP4V::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio) +{ + UINT width, height; + bool local_flip=false; + if (SUCCEEDED(decoder->GetOutputFormat(&width, &height, &local_flip, aspect_ratio))) { + *x = width; + *y = height; + *color_format = '21VY'; + return MKV_SUCCESS; + } + return MKV_FAILURE; +} + +int MKVMP4V::DecodeBlock(const void *inputBuffer, size_t inputBufferBytes, uint64_t timestamp) +{ + HRESULT hr; + hr=decoder->Feed(inputBuffer, inputBufferBytes, timestamp); + return MKV_SUCCESS; +} + +void MKVMP4V::Flush() +{ + if (decoder) { + decoder->Flush(); + } +} + +int MKVMP4V::GetPicture(void **data, void **decoder_data, uint64_t *timestamp) +{ + if (SUCCEEDED(decoder->GetFrame((YV12_PLANES **)data, decoder_data, timestamp))) { + return MKV_SUCCESS; + } else { + return MKV_FAILURE; + } +} + +void MKVMP4V::FreePicture(void *data, void *decoder_data) +{ + if (decoder) { + decoder->FreeFrame((YV12_PLANES *)data, decoder_data); + } +} + +void MKVMP4V::HurryUp(int state) +{ +// if (decoder) +// MPEG4Video_HurryUp(decoder, state); +} + +void MKVMP4V::Close() +{ + delete this; +} + +#define CBCLASS MKVMP4V +START_DISPATCH; +CB(GET_OUTPUT_PROPERTIES, GetOutputProperties) +CB(DECODE_BLOCK, DecodeBlock) +VCB(FLUSH, Flush) +CB(GET_PICTURE, GetPicture) +VCB(FREE_PICTURE, FreePicture) +VCB(HURRY_UP, HurryUp) +VCB(CLOSE, Close) +END_DISPATCH; +#undef CBCLASS |