avi_h264_decoder.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. #include "avi_h264_decoder.h"
  2. #include "../Winamp/wa_ipc.h"
  3. #include <mmsystem.h>
  4. #include <assert.h>
  5. #include <Mferror.h>
  6. 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)
  7. {
  8. nsavi::video_format *format = (nsavi::video_format *)stream_format;
  9. if (format)
  10. {
  11. if (format->compression == '462H')
  12. {
  13. MFTDecoder *ctx = new MFTDecoder();
  14. if (!ctx)
  15. return CREATEDECODER_FAILURE;
  16. if (FAILED(ctx->Open())) {
  17. delete ctx;
  18. return CREATEDECODER_FAILURE;
  19. }
  20. *decoder = new AVIH264(ctx, stream_header);
  21. return CREATEDECODER_SUCCESS;
  22. }
  23. }
  24. return CREATEDECODER_NOT_MINE;
  25. }
  26. #define CBCLASS AVIDecoderCreator
  27. START_DISPATCH;
  28. CB(CREATE_VIDEO_DECODER, CreateVideoDecoder)
  29. END_DISPATCH;
  30. #undef CBCLASS
  31. AVIH264::AVIH264(MFTDecoder *ctx, const nsavi::STRH *stream_header) : decoder(ctx), stream_header(stream_header)
  32. {
  33. }
  34. AVIH264::~AVIH264()
  35. {
  36. for ( size_t i = 0; i < buffered_frames.size(); i++ )
  37. {
  38. nullsoft_h264_frame_data frame_data = buffered_frames[ i ];
  39. decoder->FreeFrame( (YV12_PLANES *)frame_data.data, frame_data.decoder_data );
  40. }
  41. delete decoder;
  42. }
  43. int AVIH264::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio, int *flip)
  44. {
  45. UINT width, height;
  46. bool local_flip=false;
  47. if (SUCCEEDED(decoder->GetOutputFormat(&width, &height, &local_flip, aspect_ratio))) {
  48. *x = width;
  49. *y = height;
  50. *color_format = '21VY';
  51. *flip = local_flip;
  52. return AVI_SUCCESS;
  53. }
  54. return AVI_FAILURE;
  55. }
  56. int AVIH264::DecodeChunk(uint16_t type, const void *inputBuffer, size_t inputBufferBytes)
  57. {
  58. for (;;) {
  59. HRESULT hr = decoder->FeedRaw(inputBuffer, inputBufferBytes, 0);
  60. if (hr == MF_E_NOTACCEPTING) {
  61. nullsoft_h264_frame_data frame_data;
  62. if (FAILED(decoder->GetFrame((YV12_PLANES **)&frame_data.data, &frame_data.decoder_data, &frame_data.local_timestamp))) {
  63. continue;
  64. }
  65. buffered_frames.push_back(frame_data);
  66. } else if (FAILED(hr)) {
  67. return AVI_FAILURE;
  68. } else {
  69. break;
  70. }
  71. }
  72. return AVI_SUCCESS;
  73. }
  74. void AVIH264::Flush()
  75. {
  76. for (size_t i=0;i<buffered_frames.size();i++) {
  77. nullsoft_h264_frame_data frame_data = buffered_frames[i];
  78. decoder->FreeFrame((YV12_PLANES *)frame_data.data, frame_data.decoder_data);
  79. }
  80. decoder->Flush();
  81. }
  82. int AVIH264::GetPicture(void **data, void **decoder_data)
  83. {
  84. if (!buffered_frames.empty()) {
  85. nullsoft_h264_frame_data frame_data = buffered_frames[0];
  86. buffered_frames.erase(buffered_frames.begin());
  87. *data = frame_data.data;
  88. *decoder_data = frame_data.decoder_data;
  89. return AVI_SUCCESS;
  90. }
  91. if (SUCCEEDED(decoder->GetFrame((YV12_PLANES **)data, decoder_data, 0))) {
  92. return AVI_SUCCESS;
  93. } else {
  94. return AVI_FAILURE;
  95. }
  96. }
  97. void AVIH264::FreePicture(void *data, void *decoder_data)
  98. {
  99. decoder->FreeFrame((YV12_PLANES *)data, decoder_data);
  100. }
  101. void AVIH264::EndOfStream()
  102. {
  103. decoder->Drain();
  104. }
  105. void AVIH264::HurryUp(int state)
  106. {
  107. // TODO(benski)
  108. //if (decoder)
  109. // H264_HurryUp(decoder, state);
  110. }
  111. void AVIH264::Close()
  112. {
  113. delete this;
  114. }
  115. #define CBCLASS AVIH264
  116. START_DISPATCH;
  117. CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
  118. CB(DECODE_CHUNK, DecodeChunk)
  119. VCB(FLUSH, Flush)
  120. VCB(CLOSE, Close)
  121. CB(GET_PICTURE, GetPicture)
  122. VCB(FREE_PICTURE, FreePicture)
  123. VCB(END_OF_STREAM, EndOfStream)
  124. VCB(HURRY_UP, HurryUp)
  125. END_DISPATCH;
  126. #undef CBCLASS