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/h264/avi_h264_decoder.cpp | |
parent | 537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff) | |
download | winamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz |
Initial community commit
Diffstat (limited to 'Src/h264/avi_h264_decoder.cpp')
-rw-r--r-- | Src/h264/avi_h264_decoder.cpp | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/Src/h264/avi_h264_decoder.cpp b/Src/h264/avi_h264_decoder.cpp new file mode 100644 index 00000000..7411ead7 --- /dev/null +++ b/Src/h264/avi_h264_decoder.cpp @@ -0,0 +1,144 @@ +#include "avi_h264_decoder.h" +#include "../Winamp/wa_ipc.h" +#include <mmsystem.h> +#include <assert.h> +#include <Mferror.h> + + +int AVIDecoderCreator::CreateVideoDecoder(const nsavi::AVIH *avi_header, const nsavi::STRH *stream_header, const nsavi::STRF *stream_format, const nsavi::STRD *stream_data, ifc_avivideodecoder **decoder) +{ + nsavi::video_format *format = (nsavi::video_format *)stream_format; + if (format) + { + if (format->compression == '462H') + { + MFTDecoder *ctx = new MFTDecoder(); + if (!ctx) + return CREATEDECODER_FAILURE; + + if (FAILED(ctx->Open())) { + delete ctx; + return CREATEDECODER_FAILURE; + } + *decoder = new AVIH264(ctx, stream_header); + return CREATEDECODER_SUCCESS; + } + } + return CREATEDECODER_NOT_MINE; +} + + +#define CBCLASS AVIDecoderCreator +START_DISPATCH; +CB(CREATE_VIDEO_DECODER, CreateVideoDecoder) +END_DISPATCH; +#undef CBCLASS + +AVIH264::AVIH264(MFTDecoder *ctx, const nsavi::STRH *stream_header) : decoder(ctx), stream_header(stream_header) +{ +} + +AVIH264::~AVIH264() +{ + for ( size_t i = 0; i < buffered_frames.size(); i++ ) + { + nullsoft_h264_frame_data frame_data = buffered_frames[ i ]; + decoder->FreeFrame( (YV12_PLANES *)frame_data.data, frame_data.decoder_data ); + } + + delete decoder; +} + +int AVIH264::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio, int *flip) +{ + UINT width, height; + bool local_flip=false; + if (SUCCEEDED(decoder->GetOutputFormat(&width, &height, &local_flip, aspect_ratio))) { + *x = width; + *y = height; + *color_format = '21VY'; + *flip = local_flip; + return AVI_SUCCESS; + } + return AVI_FAILURE; +} + +int AVIH264::DecodeChunk(uint16_t type, const void *inputBuffer, size_t inputBufferBytes) +{ + for (;;) { + HRESULT hr = decoder->FeedRaw(inputBuffer, inputBufferBytes, 0); + if (hr == MF_E_NOTACCEPTING) { + nullsoft_h264_frame_data frame_data; + if (FAILED(decoder->GetFrame((YV12_PLANES **)&frame_data.data, &frame_data.decoder_data, &frame_data.local_timestamp))) { + continue; + } + buffered_frames.push_back(frame_data); + } else if (FAILED(hr)) { + return AVI_FAILURE; + } else { + break; + } + } + return AVI_SUCCESS; +} + +void AVIH264::Flush() +{ + for (size_t i=0;i<buffered_frames.size();i++) { + nullsoft_h264_frame_data frame_data = buffered_frames[i]; + decoder->FreeFrame((YV12_PLANES *)frame_data.data, frame_data.decoder_data); + } + decoder->Flush(); +} + +int AVIH264::GetPicture(void **data, void **decoder_data) +{ + if (!buffered_frames.empty()) { + nullsoft_h264_frame_data frame_data = buffered_frames[0]; + buffered_frames.erase(buffered_frames.begin()); + *data = frame_data.data; + *decoder_data = frame_data.decoder_data; + return AVI_SUCCESS; + } + + if (SUCCEEDED(decoder->GetFrame((YV12_PLANES **)data, decoder_data, 0))) { + return AVI_SUCCESS; + } else { + return AVI_FAILURE; + } +} + +void AVIH264::FreePicture(void *data, void *decoder_data) +{ + decoder->FreeFrame((YV12_PLANES *)data, decoder_data); +} + +void AVIH264::EndOfStream() +{ + decoder->Drain(); +} + +void AVIH264::HurryUp(int state) +{ + // TODO(benski) + //if (decoder) +// H264_HurryUp(decoder, state); +} + +void AVIH264::Close() +{ + delete this; +} + +#define CBCLASS AVIH264 +START_DISPATCH; +CB(GET_OUTPUT_PROPERTIES, GetOutputProperties) +CB(DECODE_CHUNK, DecodeChunk) +VCB(FLUSH, Flush) +VCB(CLOSE, Close) +CB(GET_PICTURE, GetPicture) +VCB(FREE_PICTURE, FreePicture) +VCB(END_OF_STREAM, EndOfStream) +VCB(HURRY_UP, HurryUp) +END_DISPATCH; +#undef CBCLASS |