123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- #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
|