123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- #include "mpeg4vid_api.h"
- #include "mp4def.h"
- #include "mp4dec.h"
- /* TODO: we havn't implemented "end of stream" yet, but when we do
- we need to flush out the buffered frames
- m_decInfo->VisualObject.vFrame = m_decInfo->VisualObject.VideoObject.prevPlaneIsB ?
- &m_decInfo->VisualObject.nFrame : &m_decInfo->VisualObject.cFrame;
- */
- // disable post processing for now, doesn't seem to be working out too well
- //#define MP4V_DO_POST_PROCESS
- #define MAX_CODED_FRAME 8000000 // TODO: benski> verify
- typedef struct
- {
- mp4_Info dec;
- int initted;
- int resetting;
- int skip_b_frames;
- #ifdef MP4V_DO_POST_PROCESS
- mp4_Frame ppFrame0, ppFrame1;
- #endif
- __declspec(align(32)) uint8_t buffer[MAX_CODED_FRAME];
- } MPEG4VideoDecoder;
- static int FreeBuffers(MPEG4VideoDecoder *decoder);
- void mp4_Error(const char *str)
- {
- puts(str);
- }
- mpeg4vid_decoder_t MPEG4Video_CreateDecoder(int filetype, int codec)
- {
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)malloc(sizeof(MPEG4VideoDecoder));
- memset(decoder, 0, sizeof(MPEG4VideoDecoder));
- // set configuration stuff
- decoder->dec.stopOnErr = 0;
- decoder->dec.strictSyntaxCheck = 0;
- decoder->dec.VisualObject.verid = 1;
- decoder->dec.ftype = filetype;
- decoder->dec.ftype_f = codec;
- return decoder;
- }
- void MPEG4Video_DestroyDecoder(mpeg4vid_decoder_t d)
- {
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- if (decoder)
- {
- #ifdef MP4V_DO_POST_PROCESS
- free(decoder->ppFrame0.mid);
- free(decoder->ppFrame1.mid);
- #endif
- FreeBuffers(decoder);
- free(decoder);
- }
- }
- void MPEG4Video_Flush(mpeg4vid_decoder_t d)
- {
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- if (decoder && decoder->initted)
- {
- mp4_ResetVOL(&decoder->dec);
- decoder->resetting = 1;
- }
- }
- static int AllocateInitFrame(mp4_Frame* pFrame)
- {
- int32_t w, h;
- w = (pFrame->mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
- h = (pFrame->mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
- pFrame->mid = malloc(w * h + (w * h >> 1));
- if (!pFrame->mid)
- return 1; // out of memory
- ippsSet_8u(0, pFrame->mid, w * h);
- ippsSet_8u(128, pFrame->mid + w * h, w * h >> 1);
- pFrame->stepY = w;
- pFrame->stepCb = w >> 1;
- pFrame->stepCr = w >> 1;
- /* benski> stuff from LockFrame... */
- pFrame->apY = pFrame->mid;
- pFrame->pY = pFrame->apY + w * 16 + 16;
- pFrame->apCb = pFrame->apY + w * h;
- w >>= 1;
- h >>= 1;
- pFrame->pCb = pFrame->apCb + w * 8 + 8;
- pFrame->apCr = pFrame->apCb + w * h;
- pFrame->pCr = pFrame->apCr + w * 8 + 8;
- return 0;
- }
- static int AllocateBuffers(MPEG4VideoDecoder *decoder)
- {
- if (mp4_InitVOL(&decoder->dec) != MP4_STATUS_OK)
- {
- mp4_Error("Error: No memory to allocate internal buffers\n");
- return 1;//UMC_ERR_ALLOC;
- }
- return 0;
- }
- static int InsideInit(MPEG4VideoDecoder *decoder)
- {
- int status;
- uint32_t code;
- int h_vo_found = 0, h_vos_found = 0;
- for (;;)
- {
- if (!mp4_SeekStartCodeOrShortPtr(&decoder->dec))
- {
- mp4_Error("Error: Can't find Visual Object or Video Object start codes or short_video_start_marker\n");
- return 1;//UMC_ERR_SYNC;
- }
- // check short_video_start_marker
- if (mp4_IsShortCode(&decoder->dec))
- {
- if ((mp4_Parse_VideoObject(&decoder->dec)) != MP4_STATUS_OK)
- return 1;//UMC_ERR_INVALID_STREAM;
- break;
- }
- code = mp4_GetBits(&decoder->dec, 8);
- if (!h_vos_found && code == MP4_VISUAL_OBJECT_SEQUENCE_SC)
- {
- h_vos_found = 1;
- if ((mp4_Parse_VisualObjectSequence(&decoder->dec)) != MP4_STATUS_OK)
- return 1;//UMC_ERR_INVALID_STREAM;
- }
- if (!h_vo_found && code == MP4_VISUAL_OBJECT_SC)
- {
- h_vo_found = 1;
- if ((mp4_Parse_VisualObject(&decoder->dec)) != MP4_STATUS_OK)
- return 1;//UMC_ERR_INVALID_STREAM;
- }
- // some streams can start with video_object_layer
- if ((int32_t)code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC) {
- decoder->dec.bufptr -= 4;
- if ((mp4_Parse_VideoObject(&decoder->dec)) != MP4_STATUS_OK)
- return 1;//UMC_ERR_INVALID_STREAM;
- break;
- }
- }
- status = AllocateBuffers(decoder);
- if (status)
- return status;
- #if 0 // don't really care about this, but might be useful code for later?
- // set profile/level info
- decoder->profile = decoder->dec.profile_and_level_indication >> 4;
- decoder->level = decoder->dec.profile_and_level_indication & 15;
- if (decoder->profile == MPEG4_PROFILE_SIMPLE)
- if (decoder->level == 8)
- decoder->level = MPEG4_LEVEL_0;
- if (decoder->profile == MPEG4_PROFILE_ADVANCED_SIMPLE) {
- if (decoder->level == 7)
- decoder->level = MPEG4_LEVEL_3B;
- if (decoder->level > 7) {
- decoder->profile = MPEG4_PROFILE_FGS;
- decoder->level -= 8;
- }
- }
- #endif
- decoder->initted = 1;
- return 0;
- }
- static int FreeBuffers(MPEG4VideoDecoder *decoder)
- {
- int status = 0;
- ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.cFrame);
- decoder->dec.VisualObject.cFrame=0;
- ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.rFrame);
- decoder->dec.VisualObject.rFrame=0;
- ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.nFrame);
- decoder->dec.VisualObject.nFrame=0;
- ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.sFrame);
- decoder->dec.VisualObject.sFrame=0;
- FreeCache(&decoder->dec.VisualObject);
-
- mp4_FreeVOL(&decoder->dec);
- return status;
- }
- static int PostProcess(MPEG4VideoDecoder *decoder, mp4_Frame *inout)
- {
- #ifdef MP4V_DO_POST_PROCESS
- int w, h, i, j, k, QP, width, height;
- IppiSize size;
- Ipp8u *pSrc[3], *pDst[3];
- int srcPitch[3], dstPitch[3], threshold[6];
- int m_DeblockingProcPlane[3] = {1,1,1}; // TODO: configurable
- int m_DeringingProcPlane[3] = {1,1,1}; // TODO: configurable
- int32_t m_DeblockingTHR1 = 2; // TODO
- int32_t m_DeblockingTHR2 = 6; // TODO
- QP = inout->QP;
- width = (decoder->dec.VisualObject.VideoObject.width + 7) & (~7);
- height = (decoder->dec.VisualObject.VideoObject.height + 7) & (~7);
- if (m_DeblockingProcPlane[0] || m_DeblockingProcPlane[1] || m_DeblockingProcPlane[2]) {
- pSrc[0] = inout->pY;
- srcPitch[0] = inout->stepY;
- pDst[0] = decoder->ppFrame0.pY;
- dstPitch[0] = decoder->ppFrame0.stepY;
- pSrc[1] = inout->pCb;
- srcPitch[1] = inout->stepCb;
- pDst[1] = decoder->ppFrame0.pCb;
- dstPitch[1] = decoder->ppFrame0.stepCb;
- pSrc[2] = inout->pCr;
- srcPitch[2] = inout->stepCr;
- pDst[2] = decoder->ppFrame0.pCr;
- dstPitch[2] = decoder->ppFrame0.stepCr;
- for (k = 0; k < 3; k ++) {
- if (m_DeblockingProcPlane[k]) {
- size.height = 8;
- if (k == 0) {
- size.width = width;
- h = height >> 3;
- w = width >> 3;
- } else {
- size.width = width >> 1;
- h = height >> 4;
- w = width >> 4;
- }
- for (i = 0; i < h; i ++) {
- ippiCopy_8u_C1R(pSrc[k], srcPitch[k], pDst[k], dstPitch[k], size);
- if (i > 0) {
- for (j = 0; j < w; j ++)
- ippiFilterDeblocking8x8HorEdge_MPEG4_8u_C1IR(pDst[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
- for (j = 1; j < w; j ++)
- ippiFilterDeblocking8x8VerEdge_MPEG4_8u_C1IR(pDst[k] - 8 * dstPitch[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
- }
- if (i == h - 1) {
- for (j = 1; j < w; j ++)
- ippiFilterDeblocking8x8VerEdge_MPEG4_8u_C1IR(pDst[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
- }
- pSrc[k] += srcPitch[k] * 8;
- pDst[k] += dstPitch[k] * 8;
- }
- } else {
- if (k == 0) {
- size.width = width;
- size.height = height;
- } else {
- size.width = width >> 1;
- size.height = height >> 1;
- }
- ippiCopy_8u_C1R(pSrc[k], srcPitch[k], pDst[k], dstPitch[k], size);
- }
- }
- *inout = decoder->ppFrame0;
- }
- if (m_DeringingProcPlane[0] || m_DeringingProcPlane[1] || m_DeringingProcPlane[2]) {
- pSrc[0] = inout->pY;
- srcPitch[0] = inout->stepY;
- pDst[0] = decoder->ppFrame1.pY;
- dstPitch[0] = decoder->ppFrame1.stepY;
- if (!m_DeringingProcPlane[0]) {
- size.width = width;
- size.height = height;
- ippiCopy_8u_C1R(pSrc[0], srcPitch[0], pDst[0], dstPitch[0], size);
- }
- pSrc[1] = inout->pCb;
- srcPitch[1] = inout->stepCb;
- pDst[1] = decoder->ppFrame1.pCb;
- dstPitch[1] = decoder->ppFrame1.stepCb;
- if (!m_DeringingProcPlane[1]) {
- size.width = width >> 1;
- size.height = height >> 1;
- ippiCopy_8u_C1R(pSrc[1], srcPitch[1], pDst[1], dstPitch[1], size);
- }
- pSrc[2] = inout->pCr;
- srcPitch[2] = inout->stepCr;
- pDst[2] = decoder->ppFrame1.pCr;
- dstPitch[2] = decoder->ppFrame1.stepCr;
- if (!m_DeringingProcPlane[2]) {
- size.width = width >> 1;
- size.height = height >> 1;
- ippiCopy_8u_C1R(pSrc[2], srcPitch[2], pDst[2], dstPitch[2], size);
- }
- h = inout->mbPerCol;
- w = inout->mbPerRow;
- for (i = 0; i < h; i ++) {
- for (j = 0; j < w; j ++) {
- ippiFilterDeringingThreshold_MPEG4_8u_P3R(pSrc[0]+ 16 * j, srcPitch[0], pSrc[1] + 8 * j, srcPitch[1], pSrc[2] + 8 * j, srcPitch[2], threshold);
- // copy border macroblocks
- if (i == 0 || i == h - 1 || j == 0 || j == w - 1) {
- if (m_DeringingProcPlane[0])
- ippiCopy16x16_8u_C1R(pSrc[0] + 16 * j, srcPitch[0], pDst[0] + 16 * j, dstPitch[0]);
- if (m_DeringingProcPlane[1])
- ippiCopy8x8_8u_C1R(pSrc[1] + 8 * j, srcPitch[1], pDst[1] + 8 * j, dstPitch[1]);
- if (m_DeringingProcPlane[2])
- ippiCopy8x8_8u_C1R(pSrc[2] + 8 * j, srcPitch[2], pDst[2] + 8 * j, dstPitch[2]);
- }
- if (m_DeringingProcPlane[0]) {
- if (i != 0 && j != 0)
- ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j, srcPitch[0], pDst[0] + 16 * j, dstPitch[0], QP, threshold[0]);
- if (i != 0 && j != w - 1)
- ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j + 8, srcPitch[0], pDst[0] + 16 * j + 8, dstPitch[0], QP, threshold[1]);
- if (i != h - 1 && j != 0)
- ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j + 8 * srcPitch[0], srcPitch[0], pDst[0] + 16 * j + 8 * dstPitch[0], dstPitch[0], QP, threshold[2]);
- if (i != h - 1 && j != w - 1)
- ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j + 8 * srcPitch[0] + 8, srcPitch[0], pDst[0] + 16 * j + 8 * dstPitch[0] + 8, dstPitch[0], QP, threshold[3]);
- }
- if (i != 0 && j != 0 && i != h - 1 && j != w - 1) {
- if (m_DeringingProcPlane[1])
- ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[1] + 8 * j, srcPitch[1], pDst[1] + 8 * j, dstPitch[1], QP, threshold[4]);
- if (m_DeringingProcPlane[2])
- ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[2] + 8 * j, srcPitch[2], pDst[2] + 8 * j, dstPitch[2], QP, threshold[5]);
- }
- }
- pSrc[0] += srcPitch[0] * 16;
- pDst[0] += dstPitch[0] * 16;
- pSrc[1] += srcPitch[1] * 8;
- pDst[1] += dstPitch[1] * 8;
- pSrc[2] += srcPitch[2] * 8;
- pDst[2] += dstPitch[2] * 8;
- }
- *inout = decoder->ppFrame1;
- }
- #endif
- return 0;
- }
- void MPEG4Video_DecodeFrame(mpeg4vid_decoder_t d, const void *buffer, size_t bufferlen, uint64_t time_code)
- {
- int status=0;
- int code;
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- if (bufferlen > (MAX_CODED_FRAME-32))
- return;
- if (buffer)
- {
- memcpy(decoder->buffer, buffer, bufferlen);
- memset(decoder->buffer+bufferlen, 0, 32);
- decoder->dec.bitoff = 0;
- decoder->dec.bufptr = decoder->dec.buffer = (uint8_t *)decoder->buffer;
- decoder->dec.buflen = bufferlen;
- }
- if (!decoder->initted) // initialize off the first packet
- {
- status = InsideInit(decoder);
- if (status)
- return;
- }
- for (;;)
- {
- // Seeking the VOP start_code, and then begin the vop decoding
- if (decoder->dec.VisualObject.VideoObject.short_video_header)
- {
- if (!mp4_SeekShortVideoStartMarker(&decoder->dec))
- {
- mp4_Error("Error: Failed seeking short_video_start_marker\n");
- status = 1;//UMC_ERR_SYNC;
- break;
- }
- }
- else
- {
- for (;;)
- {
- if (!mp4_SeekStartCodePtr(&decoder->dec)) {
- mp4_Error("Error: Failed seeking GOV or VOP Start Code");
- status = 1;//UMC_ERR_SYNC;
- break;
- }
- code = decoder->dec.bufptr[0];
- decoder->dec.bufptr++;
- // parse repeated VOS, VO and VOL headers because stream may be glued from different streams
- if (code == MP4_VISUAL_OBJECT_SEQUENCE_SC)
- {
- if (mp4_Parse_VisualObjectSequence(&decoder->dec) != MP4_STATUS_OK)
- {
- status = 1;//UMC_ERR_INVALID_STREAM;
- break;
- }
- }
- else if (code == MP4_VISUAL_OBJECT_SC)
- {
- if (mp4_Parse_VisualObject(&decoder->dec) != MP4_STATUS_OK)
- {
- status = 1;//UMC_ERR_INVALID_STREAM;
- break;
- }
- }
- else if (code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC)
- {
- // save parameters which can affect on reinit
- Ipp32s interlaced = decoder->dec.VisualObject.VideoObject.interlaced;
- Ipp32s data_partitioned = decoder->dec.VisualObject.VideoObject.data_partitioned;
- Ipp32s sprite_enable = decoder->dec.VisualObject.VideoObject.sprite_enable;
- Ipp32s width = decoder->dec.VisualObject.VideoObject.width;
- Ipp32s height = decoder->dec.VisualObject.VideoObject.height;
- // in repeated headers check only VOL header
- decoder->dec.bufptr -= 4;
- if (mp4_Parse_VideoObject(&decoder->dec) != MP4_STATUS_OK) {
- status = 1;//UMC_ERR_INVALID_STREAM;
- break;
- }
- // realloc if something was changed
- if (interlaced != decoder->dec.VisualObject.VideoObject.interlaced ||
- data_partitioned != decoder->dec.VisualObject.VideoObject.data_partitioned ||
- sprite_enable != decoder->dec.VisualObject.VideoObject.sprite_enable ||
- width != decoder->dec.VisualObject.VideoObject.width ||
- height != decoder->dec.VisualObject.VideoObject.height)
- {
- // TODO: return a code so we can return MP4_VIDEO_OUTPUT_FORMAT_CHANGED
- if (decoder->dec.strictSyntaxCheck)
- {
- mp4_Error("Error: Repeated VOL header is different from previous");
- status = 1;//UMC_ERR_INVALID_STREAM;
- break;
- }
- // UnlockBuffers();
- status = FreeBuffers(decoder);
- if (status)
- break;
- status = AllocateBuffers(decoder);
- if (status)
- break;
- // free buffers for MPEG-4 post-processing
- #ifdef MP4V_DO_POST_PROCESS
- free(decoder->ppFrame0.mid);
- decoder->ppFrame0.mid = 0;
- free(decoder->ppFrame1.mid);
- decoder->ppFrame1.mid = 0;
- #endif
- // TODO: clear cache and display frames
- }
- // reinit quant matrix
- ippiQuantInvIntraInit_MPEG4(decoder->dec.VisualObject.VideoObject.quant_type ? decoder->dec.VisualObject.VideoObject.intra_quant_mat : NULL, decoder->dec.VisualObject.VideoObject.QuantInvIntraSpec, 8);
- ippiQuantInvInterInit_MPEG4(decoder->dec.VisualObject.VideoObject.quant_type ? decoder->dec.VisualObject.VideoObject.nonintra_quant_mat : NULL, decoder->dec.VisualObject.VideoObject.QuantInvInterSpec, 8);
- }
- else if (code == MP4_GROUP_OF_VOP_SC)
- {
- if (mp4_Parse_GroupOfVideoObjectPlane(&decoder->dec) != MP4_STATUS_OK)
- {
- status = 1;//UMC_ERR_INVALID_STREAM;
- break;
- }
- }
- else if (decoder->dec.bufptr[-1] == MP4_VIDEO_OBJECT_PLANE_SC)
- {
- break;
- }
- }
- if (status)
- break;
- }
- // parse VOP header
- if ((mp4_Parse_VideoObjectPlane(&decoder->dec)) != MP4_STATUS_OK)
- {
- //status = UMC_WRN_INVALID_STREAM;
- status = 0;
- break;
- }
- if (decoder->resetting && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type != MP4_VOP_TYPE_I)
- {
- //UnlockBuffers();
- //return UMC_ERR_NOT_ENOUGH_DATA;
- // decoder->dec.VisualObject.vFrame = NULL;
- status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
- break;
- }
- if (decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
- {
- if (decoder->skip_b_frames)
- {
- decoder->dec.bufptr = decoder->dec.buffer+ decoder->dec.buflen;
- status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
- break;
- }
- }
- // decode VOP
- if ((mp4_DecodeVideoObjectPlane(&decoder->dec)) != MP4_STATUS_OK)
- {
- status = 1;//UMC_WRN_INVALID_STREAM;
- }
- if (decoder->dec.VisualObject.cFrame)
- {
- decoder->dec.VisualObject.cFrame->timestamp = time_code;
- decoder->dec.VisualObject.cFrame->QP = decoder->dec.VisualObject.VideoObject.short_video_header ? decoder->dec.VisualObject.VideoObject.VideoObjectPlaneH263.vop_quant : decoder->dec.VisualObject.VideoObject.VideoObjectPlane.quant;
- }
- // after reset it is need to skip first B-frames
- if (decoder->dec.VisualObject.VideoObject.VOPindex < 2 && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
- {
- status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
- break;
- }
- // do not count not_coded P frames with same vop_time as reference (in AVI)
- if (decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coded ||
- (
- decoder->dec.VisualObject.cFrame &&
- (!decoder->dec.VisualObject.rFrame || (decoder->dec.VisualObject.rFrame->time != decoder->dec.VisualObject.cFrame->time)) &&
- (!decoder->dec.VisualObject.nFrame || (decoder->dec.VisualObject.nFrame->time != decoder->dec.VisualObject.cFrame->time))
- )
- )
- {
- decoder->dec.VisualObject.VideoObject.VOPindex++;
- }
- else
- {
- status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
- break;
- }
- if (decoder->resetting && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_I)
- {
- // TODO: ???m_time_reset = (Ipp32s)decoder->dec.VisualObject.cFrame.time;
- //decoder->dec.VisualObject.vFrame = NULL;
- decoder->resetting = 0;
- }
- }
- // return status;
- }
- void MPEG4Video_GetPicture(mpeg4vid_decoder_t d, mp4_Frame **frame)
- {
- int status = 0;
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- mp4_Frame *rendFrame = GetDisplayFrame(&decoder->dec.VisualObject);
- if (rendFrame)
- {
- uint64_t timestamp = rendFrame->timestamp;
- #ifdef MP4V_DO_POST_PROCESS
- if (1 /* TODO: disable deblocking and deringing on request*/)
- {
- if (!decoder->ppFrame0.mid)
- {
- decoder->ppFrame0.mbPerRow = decoder->dec.VisualObject.vFrame->mbPerRow;
- decoder->ppFrame0.mbPerCol = decoder->dec.VisualObject.vFrame->mbPerCol;
- status = AllocateInitFrame(&decoder->ppFrame0);
- if (status)
- return ;
- }
- if (!decoder->ppFrame1.mid)
- {
- decoder->ppFrame1.mbPerRow = decoder->dec.VisualObject.vFrame->mbPerRow;
- decoder->ppFrame1.mbPerCol = decoder->dec.VisualObject.vFrame->mbPerCol;
- status = AllocateInitFrame(&decoder->ppFrame1);
- if (status)
- return ;
- }
- PostProcess(decoder, rendFrame);
- }
- #endif
- //if (m_LastDecodedFrame.GetColorFormat() != YUV420) {
- // m_LastDecodedFrame.Init(decoder->dec.VisualObject.VideoObject.width, decoder->dec.VisualObject.VideoObject.height, YUV420);
- //}
- // TODO ??? m_LastDecodedFrame.SetTime(pts);
- *frame = rendFrame;
- rendFrame->timestamp = timestamp;
- }
- else
- *frame = 0;
- }
- void MPEG4Video_ReleaseFrame(mpeg4vid_decoder_t d, mp4_Frame *frame)
- {
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- ReleaseFrame(&decoder->dec.VisualObject, frame);
- }
- static double GetAspectRatio(mp4_VideoObject *video_object)
- {
- int aspect_ratio_width=1, aspect_ratio_height=1;
- switch (video_object->aspect_ratio_info)
- {
- case MP4_ASPECT_RATIO_FORBIDDEN:
- case MP4_ASPECT_RATIO_1_1:
- aspect_ratio_width = 1;
- aspect_ratio_height = 1;
- break;
- case MP4_ASPECT_RATIO_12_11:
- aspect_ratio_width = 12;
- aspect_ratio_height = 11;
- break;
- case MP4_ASPECT_RATIO_10_11:
- aspect_ratio_width = 10;
- aspect_ratio_height = 11;
- break;
- case MP4_ASPECT_RATIO_16_11:
- aspect_ratio_width = 16;
- aspect_ratio_height = 11;
- break;
- case MP4_ASPECT_RATIO_40_33:
- aspect_ratio_width = 40;
- aspect_ratio_height = 33;
- break;
- default:
- aspect_ratio_width = video_object->aspect_ratio_info_par_width;
- aspect_ratio_height = video_object->aspect_ratio_info_par_height;
- break;
- }
- return (double)aspect_ratio_width / (double)aspect_ratio_height;
- }
- int MPEG4Video_GetOutputFormat(mpeg4vid_decoder_t d, int *width, int *height, double *aspect_ratio)
- {
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- if (decoder && decoder->initted)
- {
- *width = decoder->dec.VisualObject.VideoObject.width;
- *height = decoder->dec.VisualObject.VideoObject.height;
- *aspect_ratio = GetAspectRatio(&decoder->dec.VisualObject.VideoObject);
- return 0;
- }
- return 1;
- }
- void MPEG4Video_HurryUp(mpeg4vid_decoder_t d, int state)
- {
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- if (decoder)
- {
- decoder->skip_b_frames = state;
- }
- }
- void MPEG4Video_EndOfStream(mpeg4vid_decoder_t d)
- {
- MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
- if (decoder)
- {
- // TODO
- }
- }
|