1
0

mpeg4vid_api.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. #include "mpeg4vid_api.h"
  2. #include "mp4def.h"
  3. #include "mp4dec.h"
  4. /* TODO: we havn't implemented "end of stream" yet, but when we do
  5. we need to flush out the buffered frames
  6. m_decInfo->VisualObject.vFrame = m_decInfo->VisualObject.VideoObject.prevPlaneIsB ?
  7. &m_decInfo->VisualObject.nFrame : &m_decInfo->VisualObject.cFrame;
  8. */
  9. // disable post processing for now, doesn't seem to be working out too well
  10. //#define MP4V_DO_POST_PROCESS
  11. #define MAX_CODED_FRAME 8000000 // TODO: benski> verify
  12. typedef struct
  13. {
  14. mp4_Info dec;
  15. int initted;
  16. int resetting;
  17. int skip_b_frames;
  18. #ifdef MP4V_DO_POST_PROCESS
  19. mp4_Frame ppFrame0, ppFrame1;
  20. #endif
  21. __declspec(align(32)) uint8_t buffer[MAX_CODED_FRAME];
  22. } MPEG4VideoDecoder;
  23. static int FreeBuffers(MPEG4VideoDecoder *decoder);
  24. void mp4_Error(const char *str)
  25. {
  26. puts(str);
  27. }
  28. mpeg4vid_decoder_t MPEG4Video_CreateDecoder(int filetype, int codec)
  29. {
  30. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)malloc(sizeof(MPEG4VideoDecoder));
  31. memset(decoder, 0, sizeof(MPEG4VideoDecoder));
  32. // set configuration stuff
  33. decoder->dec.stopOnErr = 0;
  34. decoder->dec.strictSyntaxCheck = 0;
  35. decoder->dec.VisualObject.verid = 1;
  36. decoder->dec.ftype = filetype;
  37. decoder->dec.ftype_f = codec;
  38. return decoder;
  39. }
  40. void MPEG4Video_DestroyDecoder(mpeg4vid_decoder_t d)
  41. {
  42. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  43. if (decoder)
  44. {
  45. #ifdef MP4V_DO_POST_PROCESS
  46. free(decoder->ppFrame0.mid);
  47. free(decoder->ppFrame1.mid);
  48. #endif
  49. FreeBuffers(decoder);
  50. free(decoder);
  51. }
  52. }
  53. void MPEG4Video_Flush(mpeg4vid_decoder_t d)
  54. {
  55. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  56. if (decoder && decoder->initted)
  57. {
  58. mp4_ResetVOL(&decoder->dec);
  59. decoder->resetting = 1;
  60. }
  61. }
  62. static int AllocateInitFrame(mp4_Frame* pFrame)
  63. {
  64. int32_t w, h;
  65. w = (pFrame->mbPerRow + 2 * MP4_NUM_EXT_MB) << 4;
  66. h = (pFrame->mbPerCol + 2 * MP4_NUM_EXT_MB) << 4;
  67. pFrame->mid = malloc(w * h + (w * h >> 1));
  68. if (!pFrame->mid)
  69. return 1; // out of memory
  70. ippsSet_8u(0, pFrame->mid, w * h);
  71. ippsSet_8u(128, pFrame->mid + w * h, w * h >> 1);
  72. pFrame->stepY = w;
  73. pFrame->stepCb = w >> 1;
  74. pFrame->stepCr = w >> 1;
  75. /* benski> stuff from LockFrame... */
  76. pFrame->apY = pFrame->mid;
  77. pFrame->pY = pFrame->apY + w * 16 + 16;
  78. pFrame->apCb = pFrame->apY + w * h;
  79. w >>= 1;
  80. h >>= 1;
  81. pFrame->pCb = pFrame->apCb + w * 8 + 8;
  82. pFrame->apCr = pFrame->apCb + w * h;
  83. pFrame->pCr = pFrame->apCr + w * 8 + 8;
  84. return 0;
  85. }
  86. static int AllocateBuffers(MPEG4VideoDecoder *decoder)
  87. {
  88. if (mp4_InitVOL(&decoder->dec) != MP4_STATUS_OK)
  89. {
  90. mp4_Error("Error: No memory to allocate internal buffers\n");
  91. return 1;//UMC_ERR_ALLOC;
  92. }
  93. return 0;
  94. }
  95. static int InsideInit(MPEG4VideoDecoder *decoder)
  96. {
  97. int status;
  98. uint32_t code;
  99. int h_vo_found = 0, h_vos_found = 0;
  100. for (;;)
  101. {
  102. if (!mp4_SeekStartCodeOrShortPtr(&decoder->dec))
  103. {
  104. mp4_Error("Error: Can't find Visual Object or Video Object start codes or short_video_start_marker\n");
  105. return 1;//UMC_ERR_SYNC;
  106. }
  107. // check short_video_start_marker
  108. if (mp4_IsShortCode(&decoder->dec))
  109. {
  110. if ((mp4_Parse_VideoObject(&decoder->dec)) != MP4_STATUS_OK)
  111. return 1;//UMC_ERR_INVALID_STREAM;
  112. break;
  113. }
  114. code = mp4_GetBits(&decoder->dec, 8);
  115. if (!h_vos_found && code == MP4_VISUAL_OBJECT_SEQUENCE_SC)
  116. {
  117. h_vos_found = 1;
  118. if ((mp4_Parse_VisualObjectSequence(&decoder->dec)) != MP4_STATUS_OK)
  119. return 1;//UMC_ERR_INVALID_STREAM;
  120. }
  121. if (!h_vo_found && code == MP4_VISUAL_OBJECT_SC)
  122. {
  123. h_vo_found = 1;
  124. if ((mp4_Parse_VisualObject(&decoder->dec)) != MP4_STATUS_OK)
  125. return 1;//UMC_ERR_INVALID_STREAM;
  126. }
  127. // some streams can start with video_object_layer
  128. if ((int32_t)code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC) {
  129. decoder->dec.bufptr -= 4;
  130. if ((mp4_Parse_VideoObject(&decoder->dec)) != MP4_STATUS_OK)
  131. return 1;//UMC_ERR_INVALID_STREAM;
  132. break;
  133. }
  134. }
  135. status = AllocateBuffers(decoder);
  136. if (status)
  137. return status;
  138. #if 0 // don't really care about this, but might be useful code for later?
  139. // set profile/level info
  140. decoder->profile = decoder->dec.profile_and_level_indication >> 4;
  141. decoder->level = decoder->dec.profile_and_level_indication & 15;
  142. if (decoder->profile == MPEG4_PROFILE_SIMPLE)
  143. if (decoder->level == 8)
  144. decoder->level = MPEG4_LEVEL_0;
  145. if (decoder->profile == MPEG4_PROFILE_ADVANCED_SIMPLE) {
  146. if (decoder->level == 7)
  147. decoder->level = MPEG4_LEVEL_3B;
  148. if (decoder->level > 7) {
  149. decoder->profile = MPEG4_PROFILE_FGS;
  150. decoder->level -= 8;
  151. }
  152. }
  153. #endif
  154. decoder->initted = 1;
  155. return 0;
  156. }
  157. static int FreeBuffers(MPEG4VideoDecoder *decoder)
  158. {
  159. int status = 0;
  160. ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.cFrame);
  161. decoder->dec.VisualObject.cFrame=0;
  162. ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.rFrame);
  163. decoder->dec.VisualObject.rFrame=0;
  164. ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.nFrame);
  165. decoder->dec.VisualObject.nFrame=0;
  166. ReleaseFrame(&decoder->dec.VisualObject, decoder->dec.VisualObject.sFrame);
  167. decoder->dec.VisualObject.sFrame=0;
  168. FreeCache(&decoder->dec.VisualObject);
  169. mp4_FreeVOL(&decoder->dec);
  170. return status;
  171. }
  172. static int PostProcess(MPEG4VideoDecoder *decoder, mp4_Frame *inout)
  173. {
  174. #ifdef MP4V_DO_POST_PROCESS
  175. int w, h, i, j, k, QP, width, height;
  176. IppiSize size;
  177. Ipp8u *pSrc[3], *pDst[3];
  178. int srcPitch[3], dstPitch[3], threshold[6];
  179. int m_DeblockingProcPlane[3] = {1,1,1}; // TODO: configurable
  180. int m_DeringingProcPlane[3] = {1,1,1}; // TODO: configurable
  181. int32_t m_DeblockingTHR1 = 2; // TODO
  182. int32_t m_DeblockingTHR2 = 6; // TODO
  183. QP = inout->QP;
  184. width = (decoder->dec.VisualObject.VideoObject.width + 7) & (~7);
  185. height = (decoder->dec.VisualObject.VideoObject.height + 7) & (~7);
  186. if (m_DeblockingProcPlane[0] || m_DeblockingProcPlane[1] || m_DeblockingProcPlane[2]) {
  187. pSrc[0] = inout->pY;
  188. srcPitch[0] = inout->stepY;
  189. pDst[0] = decoder->ppFrame0.pY;
  190. dstPitch[0] = decoder->ppFrame0.stepY;
  191. pSrc[1] = inout->pCb;
  192. srcPitch[1] = inout->stepCb;
  193. pDst[1] = decoder->ppFrame0.pCb;
  194. dstPitch[1] = decoder->ppFrame0.stepCb;
  195. pSrc[2] = inout->pCr;
  196. srcPitch[2] = inout->stepCr;
  197. pDst[2] = decoder->ppFrame0.pCr;
  198. dstPitch[2] = decoder->ppFrame0.stepCr;
  199. for (k = 0; k < 3; k ++) {
  200. if (m_DeblockingProcPlane[k]) {
  201. size.height = 8;
  202. if (k == 0) {
  203. size.width = width;
  204. h = height >> 3;
  205. w = width >> 3;
  206. } else {
  207. size.width = width >> 1;
  208. h = height >> 4;
  209. w = width >> 4;
  210. }
  211. for (i = 0; i < h; i ++) {
  212. ippiCopy_8u_C1R(pSrc[k], srcPitch[k], pDst[k], dstPitch[k], size);
  213. if (i > 0) {
  214. for (j = 0; j < w; j ++)
  215. ippiFilterDeblocking8x8HorEdge_MPEG4_8u_C1IR(pDst[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
  216. for (j = 1; j < w; j ++)
  217. ippiFilterDeblocking8x8VerEdge_MPEG4_8u_C1IR(pDst[k] - 8 * dstPitch[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
  218. }
  219. if (i == h - 1) {
  220. for (j = 1; j < w; j ++)
  221. ippiFilterDeblocking8x8VerEdge_MPEG4_8u_C1IR(pDst[k] + 8 * j, dstPitch[k], QP, m_DeblockingTHR1, m_DeblockingTHR2);
  222. }
  223. pSrc[k] += srcPitch[k] * 8;
  224. pDst[k] += dstPitch[k] * 8;
  225. }
  226. } else {
  227. if (k == 0) {
  228. size.width = width;
  229. size.height = height;
  230. } else {
  231. size.width = width >> 1;
  232. size.height = height >> 1;
  233. }
  234. ippiCopy_8u_C1R(pSrc[k], srcPitch[k], pDst[k], dstPitch[k], size);
  235. }
  236. }
  237. *inout = decoder->ppFrame0;
  238. }
  239. if (m_DeringingProcPlane[0] || m_DeringingProcPlane[1] || m_DeringingProcPlane[2]) {
  240. pSrc[0] = inout->pY;
  241. srcPitch[0] = inout->stepY;
  242. pDst[0] = decoder->ppFrame1.pY;
  243. dstPitch[0] = decoder->ppFrame1.stepY;
  244. if (!m_DeringingProcPlane[0]) {
  245. size.width = width;
  246. size.height = height;
  247. ippiCopy_8u_C1R(pSrc[0], srcPitch[0], pDst[0], dstPitch[0], size);
  248. }
  249. pSrc[1] = inout->pCb;
  250. srcPitch[1] = inout->stepCb;
  251. pDst[1] = decoder->ppFrame1.pCb;
  252. dstPitch[1] = decoder->ppFrame1.stepCb;
  253. if (!m_DeringingProcPlane[1]) {
  254. size.width = width >> 1;
  255. size.height = height >> 1;
  256. ippiCopy_8u_C1R(pSrc[1], srcPitch[1], pDst[1], dstPitch[1], size);
  257. }
  258. pSrc[2] = inout->pCr;
  259. srcPitch[2] = inout->stepCr;
  260. pDst[2] = decoder->ppFrame1.pCr;
  261. dstPitch[2] = decoder->ppFrame1.stepCr;
  262. if (!m_DeringingProcPlane[2]) {
  263. size.width = width >> 1;
  264. size.height = height >> 1;
  265. ippiCopy_8u_C1R(pSrc[2], srcPitch[2], pDst[2], dstPitch[2], size);
  266. }
  267. h = inout->mbPerCol;
  268. w = inout->mbPerRow;
  269. for (i = 0; i < h; i ++) {
  270. for (j = 0; j < w; j ++) {
  271. ippiFilterDeringingThreshold_MPEG4_8u_P3R(pSrc[0]+ 16 * j, srcPitch[0], pSrc[1] + 8 * j, srcPitch[1], pSrc[2] + 8 * j, srcPitch[2], threshold);
  272. // copy border macroblocks
  273. if (i == 0 || i == h - 1 || j == 0 || j == w - 1) {
  274. if (m_DeringingProcPlane[0])
  275. ippiCopy16x16_8u_C1R(pSrc[0] + 16 * j, srcPitch[0], pDst[0] + 16 * j, dstPitch[0]);
  276. if (m_DeringingProcPlane[1])
  277. ippiCopy8x8_8u_C1R(pSrc[1] + 8 * j, srcPitch[1], pDst[1] + 8 * j, dstPitch[1]);
  278. if (m_DeringingProcPlane[2])
  279. ippiCopy8x8_8u_C1R(pSrc[2] + 8 * j, srcPitch[2], pDst[2] + 8 * j, dstPitch[2]);
  280. }
  281. if (m_DeringingProcPlane[0]) {
  282. if (i != 0 && j != 0)
  283. ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j, srcPitch[0], pDst[0] + 16 * j, dstPitch[0], QP, threshold[0]);
  284. if (i != 0 && j != w - 1)
  285. ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[0] + 16 * j + 8, srcPitch[0], pDst[0] + 16 * j + 8, dstPitch[0], QP, threshold[1]);
  286. if (i != h - 1 && j != 0)
  287. 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]);
  288. if (i != h - 1 && j != w - 1)
  289. 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]);
  290. }
  291. if (i != 0 && j != 0 && i != h - 1 && j != w - 1) {
  292. if (m_DeringingProcPlane[1])
  293. ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[1] + 8 * j, srcPitch[1], pDst[1] + 8 * j, dstPitch[1], QP, threshold[4]);
  294. if (m_DeringingProcPlane[2])
  295. ippiFilterDeringingSmooth8x8_MPEG4_8u_C1R(pSrc[2] + 8 * j, srcPitch[2], pDst[2] + 8 * j, dstPitch[2], QP, threshold[5]);
  296. }
  297. }
  298. pSrc[0] += srcPitch[0] * 16;
  299. pDst[0] += dstPitch[0] * 16;
  300. pSrc[1] += srcPitch[1] * 8;
  301. pDst[1] += dstPitch[1] * 8;
  302. pSrc[2] += srcPitch[2] * 8;
  303. pDst[2] += dstPitch[2] * 8;
  304. }
  305. *inout = decoder->ppFrame1;
  306. }
  307. #endif
  308. return 0;
  309. }
  310. void MPEG4Video_DecodeFrame(mpeg4vid_decoder_t d, const void *buffer, size_t bufferlen, uint64_t time_code)
  311. {
  312. int status=0;
  313. int code;
  314. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  315. if (bufferlen > (MAX_CODED_FRAME-32))
  316. return;
  317. if (buffer)
  318. {
  319. memcpy(decoder->buffer, buffer, bufferlen);
  320. memset(decoder->buffer+bufferlen, 0, 32);
  321. decoder->dec.bitoff = 0;
  322. decoder->dec.bufptr = decoder->dec.buffer = (uint8_t *)decoder->buffer;
  323. decoder->dec.buflen = bufferlen;
  324. }
  325. if (!decoder->initted) // initialize off the first packet
  326. {
  327. status = InsideInit(decoder);
  328. if (status)
  329. return;
  330. }
  331. for (;;)
  332. {
  333. // Seeking the VOP start_code, and then begin the vop decoding
  334. if (decoder->dec.VisualObject.VideoObject.short_video_header)
  335. {
  336. if (!mp4_SeekShortVideoStartMarker(&decoder->dec))
  337. {
  338. mp4_Error("Error: Failed seeking short_video_start_marker\n");
  339. status = 1;//UMC_ERR_SYNC;
  340. break;
  341. }
  342. }
  343. else
  344. {
  345. for (;;)
  346. {
  347. if (!mp4_SeekStartCodePtr(&decoder->dec)) {
  348. mp4_Error("Error: Failed seeking GOV or VOP Start Code");
  349. status = 1;//UMC_ERR_SYNC;
  350. break;
  351. }
  352. code = decoder->dec.bufptr[0];
  353. decoder->dec.bufptr++;
  354. // parse repeated VOS, VO and VOL headers because stream may be glued from different streams
  355. if (code == MP4_VISUAL_OBJECT_SEQUENCE_SC)
  356. {
  357. if (mp4_Parse_VisualObjectSequence(&decoder->dec) != MP4_STATUS_OK)
  358. {
  359. status = 1;//UMC_ERR_INVALID_STREAM;
  360. break;
  361. }
  362. }
  363. else if (code == MP4_VISUAL_OBJECT_SC)
  364. {
  365. if (mp4_Parse_VisualObject(&decoder->dec) != MP4_STATUS_OK)
  366. {
  367. status = 1;//UMC_ERR_INVALID_STREAM;
  368. break;
  369. }
  370. }
  371. else if (code >= MP4_VIDEO_OBJECT_LAYER_MIN_SC && code <= MP4_VIDEO_OBJECT_LAYER_MAX_SC)
  372. {
  373. // save parameters which can affect on reinit
  374. Ipp32s interlaced = decoder->dec.VisualObject.VideoObject.interlaced;
  375. Ipp32s data_partitioned = decoder->dec.VisualObject.VideoObject.data_partitioned;
  376. Ipp32s sprite_enable = decoder->dec.VisualObject.VideoObject.sprite_enable;
  377. Ipp32s width = decoder->dec.VisualObject.VideoObject.width;
  378. Ipp32s height = decoder->dec.VisualObject.VideoObject.height;
  379. // in repeated headers check only VOL header
  380. decoder->dec.bufptr -= 4;
  381. if (mp4_Parse_VideoObject(&decoder->dec) != MP4_STATUS_OK) {
  382. status = 1;//UMC_ERR_INVALID_STREAM;
  383. break;
  384. }
  385. // realloc if something was changed
  386. if (interlaced != decoder->dec.VisualObject.VideoObject.interlaced ||
  387. data_partitioned != decoder->dec.VisualObject.VideoObject.data_partitioned ||
  388. sprite_enable != decoder->dec.VisualObject.VideoObject.sprite_enable ||
  389. width != decoder->dec.VisualObject.VideoObject.width ||
  390. height != decoder->dec.VisualObject.VideoObject.height)
  391. {
  392. // TODO: return a code so we can return MP4_VIDEO_OUTPUT_FORMAT_CHANGED
  393. if (decoder->dec.strictSyntaxCheck)
  394. {
  395. mp4_Error("Error: Repeated VOL header is different from previous");
  396. status = 1;//UMC_ERR_INVALID_STREAM;
  397. break;
  398. }
  399. // UnlockBuffers();
  400. status = FreeBuffers(decoder);
  401. if (status)
  402. break;
  403. status = AllocateBuffers(decoder);
  404. if (status)
  405. break;
  406. // free buffers for MPEG-4 post-processing
  407. #ifdef MP4V_DO_POST_PROCESS
  408. free(decoder->ppFrame0.mid);
  409. decoder->ppFrame0.mid = 0;
  410. free(decoder->ppFrame1.mid);
  411. decoder->ppFrame1.mid = 0;
  412. #endif
  413. // TODO: clear cache and display frames
  414. }
  415. // reinit quant matrix
  416. ippiQuantInvIntraInit_MPEG4(decoder->dec.VisualObject.VideoObject.quant_type ? decoder->dec.VisualObject.VideoObject.intra_quant_mat : NULL, decoder->dec.VisualObject.VideoObject.QuantInvIntraSpec, 8);
  417. ippiQuantInvInterInit_MPEG4(decoder->dec.VisualObject.VideoObject.quant_type ? decoder->dec.VisualObject.VideoObject.nonintra_quant_mat : NULL, decoder->dec.VisualObject.VideoObject.QuantInvInterSpec, 8);
  418. }
  419. else if (code == MP4_GROUP_OF_VOP_SC)
  420. {
  421. if (mp4_Parse_GroupOfVideoObjectPlane(&decoder->dec) != MP4_STATUS_OK)
  422. {
  423. status = 1;//UMC_ERR_INVALID_STREAM;
  424. break;
  425. }
  426. }
  427. else if (decoder->dec.bufptr[-1] == MP4_VIDEO_OBJECT_PLANE_SC)
  428. {
  429. break;
  430. }
  431. }
  432. if (status)
  433. break;
  434. }
  435. // parse VOP header
  436. if ((mp4_Parse_VideoObjectPlane(&decoder->dec)) != MP4_STATUS_OK)
  437. {
  438. //status = UMC_WRN_INVALID_STREAM;
  439. status = 0;
  440. break;
  441. }
  442. if (decoder->resetting && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type != MP4_VOP_TYPE_I)
  443. {
  444. //UnlockBuffers();
  445. //return UMC_ERR_NOT_ENOUGH_DATA;
  446. // decoder->dec.VisualObject.vFrame = NULL;
  447. status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
  448. break;
  449. }
  450. if (decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
  451. {
  452. if (decoder->skip_b_frames)
  453. {
  454. decoder->dec.bufptr = decoder->dec.buffer+ decoder->dec.buflen;
  455. status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
  456. break;
  457. }
  458. }
  459. // decode VOP
  460. if ((mp4_DecodeVideoObjectPlane(&decoder->dec)) != MP4_STATUS_OK)
  461. {
  462. status = 1;//UMC_WRN_INVALID_STREAM;
  463. }
  464. if (decoder->dec.VisualObject.cFrame)
  465. {
  466. decoder->dec.VisualObject.cFrame->timestamp = time_code;
  467. 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;
  468. }
  469. // after reset it is need to skip first B-frames
  470. if (decoder->dec.VisualObject.VideoObject.VOPindex < 2 && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_B)
  471. {
  472. status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
  473. break;
  474. }
  475. // do not count not_coded P frames with same vop_time as reference (in AVI)
  476. if (decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coded ||
  477. (
  478. decoder->dec.VisualObject.cFrame &&
  479. (!decoder->dec.VisualObject.rFrame || (decoder->dec.VisualObject.rFrame->time != decoder->dec.VisualObject.cFrame->time)) &&
  480. (!decoder->dec.VisualObject.nFrame || (decoder->dec.VisualObject.nFrame->time != decoder->dec.VisualObject.cFrame->time))
  481. )
  482. )
  483. {
  484. decoder->dec.VisualObject.VideoObject.VOPindex++;
  485. }
  486. else
  487. {
  488. status = 1;//UMC_ERR_NOT_ENOUGH_DATA;
  489. break;
  490. }
  491. if (decoder->resetting && decoder->dec.VisualObject.VideoObject.VideoObjectPlane.coding_type == MP4_VOP_TYPE_I)
  492. {
  493. // TODO: ???m_time_reset = (Ipp32s)decoder->dec.VisualObject.cFrame.time;
  494. //decoder->dec.VisualObject.vFrame = NULL;
  495. decoder->resetting = 0;
  496. }
  497. }
  498. // return status;
  499. }
  500. void MPEG4Video_GetPicture(mpeg4vid_decoder_t d, mp4_Frame **frame)
  501. {
  502. int status = 0;
  503. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  504. mp4_Frame *rendFrame = GetDisplayFrame(&decoder->dec.VisualObject);
  505. if (rendFrame)
  506. {
  507. uint64_t timestamp = rendFrame->timestamp;
  508. #ifdef MP4V_DO_POST_PROCESS
  509. if (1 /* TODO: disable deblocking and deringing on request*/)
  510. {
  511. if (!decoder->ppFrame0.mid)
  512. {
  513. decoder->ppFrame0.mbPerRow = decoder->dec.VisualObject.vFrame->mbPerRow;
  514. decoder->ppFrame0.mbPerCol = decoder->dec.VisualObject.vFrame->mbPerCol;
  515. status = AllocateInitFrame(&decoder->ppFrame0);
  516. if (status)
  517. return ;
  518. }
  519. if (!decoder->ppFrame1.mid)
  520. {
  521. decoder->ppFrame1.mbPerRow = decoder->dec.VisualObject.vFrame->mbPerRow;
  522. decoder->ppFrame1.mbPerCol = decoder->dec.VisualObject.vFrame->mbPerCol;
  523. status = AllocateInitFrame(&decoder->ppFrame1);
  524. if (status)
  525. return ;
  526. }
  527. PostProcess(decoder, rendFrame);
  528. }
  529. #endif
  530. //if (m_LastDecodedFrame.GetColorFormat() != YUV420) {
  531. // m_LastDecodedFrame.Init(decoder->dec.VisualObject.VideoObject.width, decoder->dec.VisualObject.VideoObject.height, YUV420);
  532. //}
  533. // TODO ??? m_LastDecodedFrame.SetTime(pts);
  534. *frame = rendFrame;
  535. rendFrame->timestamp = timestamp;
  536. }
  537. else
  538. *frame = 0;
  539. }
  540. void MPEG4Video_ReleaseFrame(mpeg4vid_decoder_t d, mp4_Frame *frame)
  541. {
  542. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  543. ReleaseFrame(&decoder->dec.VisualObject, frame);
  544. }
  545. static double GetAspectRatio(mp4_VideoObject *video_object)
  546. {
  547. int aspect_ratio_width=1, aspect_ratio_height=1;
  548. switch (video_object->aspect_ratio_info)
  549. {
  550. case MP4_ASPECT_RATIO_FORBIDDEN:
  551. case MP4_ASPECT_RATIO_1_1:
  552. aspect_ratio_width = 1;
  553. aspect_ratio_height = 1;
  554. break;
  555. case MP4_ASPECT_RATIO_12_11:
  556. aspect_ratio_width = 12;
  557. aspect_ratio_height = 11;
  558. break;
  559. case MP4_ASPECT_RATIO_10_11:
  560. aspect_ratio_width = 10;
  561. aspect_ratio_height = 11;
  562. break;
  563. case MP4_ASPECT_RATIO_16_11:
  564. aspect_ratio_width = 16;
  565. aspect_ratio_height = 11;
  566. break;
  567. case MP4_ASPECT_RATIO_40_33:
  568. aspect_ratio_width = 40;
  569. aspect_ratio_height = 33;
  570. break;
  571. default:
  572. aspect_ratio_width = video_object->aspect_ratio_info_par_width;
  573. aspect_ratio_height = video_object->aspect_ratio_info_par_height;
  574. break;
  575. }
  576. return (double)aspect_ratio_width / (double)aspect_ratio_height;
  577. }
  578. int MPEG4Video_GetOutputFormat(mpeg4vid_decoder_t d, int *width, int *height, double *aspect_ratio)
  579. {
  580. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  581. if (decoder && decoder->initted)
  582. {
  583. *width = decoder->dec.VisualObject.VideoObject.width;
  584. *height = decoder->dec.VisualObject.VideoObject.height;
  585. *aspect_ratio = GetAspectRatio(&decoder->dec.VisualObject.VideoObject);
  586. return 0;
  587. }
  588. return 1;
  589. }
  590. void MPEG4Video_HurryUp(mpeg4vid_decoder_t d, int state)
  591. {
  592. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  593. if (decoder)
  594. {
  595. decoder->skip_b_frames = state;
  596. }
  597. }
  598. void MPEG4Video_EndOfStream(mpeg4vid_decoder_t d)
  599. {
  600. MPEG4VideoDecoder *decoder = (MPEG4VideoDecoder *)d;
  601. if (decoder)
  602. {
  603. // TODO
  604. }
  605. }