OSDN Git Service

set wma and wmv format to distinguish WMV1, WMV2, WMV3, WMAV1, WMAV2...
[android-x86/external-stagefright-plugins.git] / libstagefright / codecs / ffmpegdec / vdec / SoftFFmpegVideo.cpp
1 /*
2  * Copyright 2012 Michael Chen <omxcodec@gmail.com>
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "SoftFFmpegVideo"
19 #include <utils/Log.h>
20
21 #include "SoftFFmpegVideo.h"
22
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/hexdump.h>
25 #include <media/stagefright/MediaDefs.h>
26
27 #include "utils/common_utils.h"
28 #include "utils/ffmpeg_utils.h"
29
30 #undef realloc
31 #include <stdlib.h>
32
33 #define DEBUG_PKT 0
34 #define DEBUG_FRM 0
35
36 static int decoder_reorder_pts = -1;
37
38 namespace android {
39
40 template<class T>
41 static void InitOMXParams(T *params) {
42     params->nSize = sizeof(T);
43     params->nVersion.s.nVersionMajor = 1;
44     params->nVersion.s.nVersionMinor = 0;
45     params->nVersion.s.nRevision = 0;
46     params->nVersion.s.nStep = 0;
47 }
48
49 SoftFFmpegVideo::SoftFFmpegVideo(
50         const char *name,
51         const OMX_CALLBACKTYPE *callbacks,
52         OMX_PTR appData,
53         OMX_COMPONENTTYPE **component)
54     : SimpleSoftOMXComponent(name, callbacks, appData, component),
55       mMode(MODE_H264),
56       mCtx(NULL),
57       mImgConvertCtx(NULL),
58       mExtradataReady(false),
59       mIgnoreExtradata(false),
60       mSignalledError(false),
61       mDoDeinterlace(true),
62       mWidth(320),
63       mHeight(240),
64       mStride(320),
65       mOutputPortSettingsChange(NONE) {
66     if (!strcmp(name, "OMX.ffmpeg.mpeg4.decoder")) {
67         mMode = MODE_MPEG4;
68     } else if (!strcmp(name, "OMX.ffmpeg.mpeg2v.decoder")) {
69         mMode = MODE_MPEG2;
70     } else if (!strcmp(name, "OMX.ffmpeg.h263.decoder")) {
71         mMode = MODE_H263;
72     } else if (!strcmp(name, "OMX.ffmpeg.vpx.decoder")) {
73         mMode = MODE_VPX;
74     } else if (!strcmp(name, "OMX.ffmpeg.vc1.decoder")) {
75         mMode = MODE_VC1;
76     } else if (!strcmp(name, "OMX.ffmpeg.divx.decoder")) {
77         mMode = MODE_DIVX;
78     } else if (!strcmp(name, "OMX.ffmpeg.wmv.decoder")) {
79         mMode = MODE_WMV;
80     } else if (!strcmp(name, "OMX.ffmpeg.flv.decoder")) {
81         mMode = MODE_FLV;
82     } else if (!strcmp(name, "OMX.ffmpeg.rv.decoder")) {
83         mMode = MODE_RV;
84     } else {
85         CHECK(!strcmp(name, "OMX.ffmpeg.h264.decoder"));
86     }
87
88     LOGV("SoftFFmpegVideo component: %s", name);
89
90     initPorts();
91     CHECK_EQ(initDecoder(), (status_t)OK);
92 }
93
94 SoftFFmpegVideo::~SoftFFmpegVideo() {
95     LOGV("~SoftFFmpegVideo");
96     deInitDecoder();
97     deInitFFmpeg();
98 }
99
100 void SoftFFmpegVideo::initPorts() {
101     OMX_PARAM_PORTDEFINITIONTYPE def;
102     InitOMXParams(&def);
103
104     def.nPortIndex = 0;
105     def.eDir = OMX_DirInput;
106     def.nBufferCountMin = kNumInputBuffers;
107     def.nBufferCountActual = def.nBufferCountMin;
108     def.nBufferSize = 1280 * 720; // 256 * 1024?
109     def.bEnabled = OMX_TRUE;
110     def.bPopulated = OMX_FALSE;
111     def.eDomain = OMX_PortDomainVideo;
112     def.bBuffersContiguous = OMX_FALSE;
113     def.nBufferAlignment = 1;
114
115     switch (mMode) {
116     case MODE_H264:
117         def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC);
118         def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
119         break;
120     case MODE_MPEG4:
121         def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4);
122         def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
123         break;
124     case MODE_MPEG2:
125         def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG2);
126         def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2;
127         break;
128     case MODE_H263:
129         def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
130         def.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
131         break;
132     case MODE_VC1:
133         def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VC1);
134         def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
135         break;
136     case MODE_WMV:
137         def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_WMV);
138         def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
139         break;
140     default:
141         CHECK(!"Should not be here. Unsupported mime type and compression format");
142         break;
143     }
144
145     def.format.video.pNativeRender = NULL;
146     def.format.video.nFrameWidth = mWidth;
147     def.format.video.nFrameHeight = mHeight;
148     def.format.video.nStride = def.format.video.nFrameWidth;
149     def.format.video.nSliceHeight = def.format.video.nFrameHeight;
150     def.format.video.nBitrate = 0;
151     def.format.video.xFramerate = 0;
152     def.format.video.bFlagErrorConcealment = OMX_FALSE;
153     def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
154     def.format.video.pNativeWindow = NULL;
155
156     addPort(def);
157
158     def.nPortIndex = 1;
159     def.eDir = OMX_DirOutput;
160     def.nBufferCountMin = kNumOutputBuffers;
161     def.nBufferCountActual = def.nBufferCountMin;
162     def.bEnabled = OMX_TRUE;
163     def.bPopulated = OMX_FALSE;
164     def.eDomain = OMX_PortDomainVideo;
165     def.bBuffersContiguous = OMX_FALSE;
166     def.nBufferAlignment = 2;
167
168     def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
169     def.format.video.pNativeRender = NULL;
170     def.format.video.nFrameWidth = mWidth;
171     def.format.video.nFrameHeight = mHeight;
172     def.format.video.nStride = def.format.video.nFrameWidth;
173     def.format.video.nSliceHeight = def.format.video.nFrameHeight;
174     def.format.video.nBitrate = 0;
175     def.format.video.xFramerate = 0;
176     def.format.video.bFlagErrorConcealment = OMX_FALSE;
177     def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
178     def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
179     def.format.video.pNativeWindow = NULL;
180
181     def.nBufferSize =
182         (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
183
184     addPort(def);
185 }
186
187 void SoftFFmpegVideo::setAVCtxToDefault(AVCodecContext *avctx, const AVCodec *codec) {
188     int fast = 0;
189
190     avctx->workaround_bugs   = 1;
191     avctx->lowres            = 0;
192     if(avctx->lowres > codec->max_lowres){
193         LOGW("The maximum value for lowres supported by the decoder is %d",
194                 codec->max_lowres);
195         avctx->lowres= codec->max_lowres;
196     }
197     avctx->idct_algo         = 0;
198     avctx->skip_frame        = AVDISCARD_DEFAULT;
199     avctx->skip_idct         = AVDISCARD_DEFAULT;
200     avctx->skip_loop_filter  = AVDISCARD_DEFAULT;
201     avctx->error_concealment = 3;
202
203     if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
204     if (fast)   avctx->flags2 |= CODEC_FLAG2_FAST;
205     if(codec->capabilities & CODEC_CAP_DR1)
206         avctx->flags |= CODEC_FLAG_EMU_EDGE;
207 }
208
209 status_t SoftFFmpegVideo::initDecoder() {
210     status_t status;
211     
212     status = initFFmpeg();
213     if (status != OK)
214         return NO_INIT;
215
216     mCtx = avcodec_alloc_context3(NULL);
217     if (!mCtx)
218     {
219         LOGE("avcodec_alloc_context failed.");
220         return NO_MEMORY;
221     }
222
223     mCtx->codec_type = AVMEDIA_TYPE_VIDEO;
224     switch (mMode) {
225     case MODE_H264:
226         mCtx->codec_id = CODEC_ID_H264;
227         break;
228     case MODE_MPEG4:
229         mCtx->codec_id = CODEC_ID_MPEG4;
230         break;
231     case MODE_MPEG2:
232         mCtx->codec_id = CODEC_ID_MPEG2VIDEO;
233         break;
234     case MODE_H263:
235         mCtx->codec_id = CODEC_ID_H263;
236         // TODO, which?
237         //mCtx->codec_id = CODEC_ID_H263P;
238         //mCtx->codec_id = CODEC_ID_H263I;
239         break;
240     case MODE_VC1:
241         mCtx->codec_id = CODEC_ID_VC1;
242         break;
243     case MODE_WMV:
244         mCtx->codec_id = CODEC_ID_WMV2; // default, adjust in "internalSetParameter" fxn
245         break;
246     default:
247         CHECK(!"Should not be here. Unsupported codec");
248         break;
249     }
250
251     mCtx->codec = avcodec_find_decoder(mCtx->codec_id);
252     if (!mCtx->codec)
253     {
254         LOGE("find codec failed");
255         return BAD_TYPE;
256     }
257
258     setAVCtxToDefault(mCtx, mCtx->codec);
259
260     mCtx->extradata_size = 0;
261     mCtx->extradata = NULL;
262     mCtx->width = mWidth;
263     mCtx->height = mHeight;
264
265     return OK;
266 }
267
268 void SoftFFmpegVideo::deInitDecoder() {
269     if (mCtx) {
270         avcodec_flush_buffers(mCtx);
271         if (!mCtx->extradata) {
272             av_free(mCtx->extradata);
273             mCtx->extradata = NULL;
274             mCtx->extradata_size = 0;
275         }
276         avcodec_close(mCtx);
277         av_free(mCtx);
278         mCtx = NULL;
279     }
280
281     if (mImgConvertCtx) {
282         sws_freeContext(mImgConvertCtx);
283         mImgConvertCtx = NULL;
284     }
285 }
286
287 void SoftFFmpegVideo::preProcessVideoFrame(AVPicture *picture, void **bufp)
288 {
289     AVPicture *picture2;
290     AVPicture picture_tmp;
291     uint8_t *buf = NULL;
292
293     /* deinterlace : must be done before any resize */
294     if (mDoDeinterlace) {
295         int size;
296
297         /* create temporary picture */
298         size = avpicture_get_size(mCtx->pix_fmt, mCtx->width, mCtx->height);
299         buf  = (uint8_t *)av_malloc(size);
300         if (!buf)
301             return;
302
303         picture2 = &picture_tmp;
304         avpicture_fill(picture2, buf, mCtx->pix_fmt, mCtx->width, mCtx->height);
305
306         if (avpicture_deinterlace(picture2, picture,
307                                  mCtx->pix_fmt, mCtx->width, mCtx->height) < 0) {
308             /* if error, do not deinterlace */
309             LOGE("Deinterlacing failed");
310             av_free(buf);
311             buf = NULL;
312             picture2 = picture;
313         }
314     } else {
315         picture2 = picture;
316     }
317
318     if (picture != picture2)
319         *picture = *picture2;
320     *bufp = buf;
321 }
322
323 OMX_ERRORTYPE SoftFFmpegVideo::internalGetParameter(
324         OMX_INDEXTYPE index, OMX_PTR params) {
325     switch (index) {
326         case OMX_IndexParamVideoPortFormat:
327         {
328             OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
329                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
330
331             if (formatParams->nPortIndex > 1) {
332                 return OMX_ErrorUndefined;
333             }
334
335             if (formatParams->nIndex != 0) {
336                 return OMX_ErrorNoMore;
337             }
338
339             if (formatParams->nPortIndex == 0) {
340                 switch (mMode) {
341                 case MODE_H264:
342                     formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
343                     break;
344                 case MODE_MPEG4:
345                     formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG4;
346                     break;
347                 case MODE_MPEG2:
348                     formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG2;
349                     break;
350                 case MODE_H263:
351                     formatParams->eCompressionFormat = OMX_VIDEO_CodingH263;
352                     break;
353                 case MODE_VC1:
354                     formatParams->eCompressionFormat = OMX_VIDEO_CodingWMV;
355                     break;
356                 case MODE_WMV:
357                     formatParams->eCompressionFormat = OMX_VIDEO_CodingWMV;
358                     break;
359                 default:
360                     CHECK(!"Should not be here. Unsupported compression format.");
361                     break;
362                 }
363                 formatParams->eColorFormat = OMX_COLOR_FormatUnused;
364                 formatParams->xFramerate = 0;
365             } else {
366                 CHECK_EQ(formatParams->nPortIndex, 1u);
367
368                 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
369                 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
370                 formatParams->xFramerate = 0;
371             }
372
373             return OMX_ErrorNone;
374         }
375
376         case OMX_IndexParamVideoWmv:
377         {
378             OMX_VIDEO_PARAM_WMVTYPE *wmvParams =
379                 (OMX_VIDEO_PARAM_WMVTYPE *)params;
380
381             if (wmvParams->nPortIndex != 0) {
382                 return OMX_ErrorUndefined;
383             }
384
385             wmvParams->eFormat = OMX_VIDEO_WMVFormatUnused;
386
387             return OMX_ErrorNone;
388         }
389
390         default:
391             return SimpleSoftOMXComponent::internalGetParameter(index, params);
392     }
393 }
394
395 OMX_ERRORTYPE SoftFFmpegVideo::internalSetParameter(
396         OMX_INDEXTYPE index, const OMX_PTR params) {
397     switch (index) {
398         case OMX_IndexParamStandardComponentRole:
399         {
400             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
401                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
402
403             bool supported = true;
404             switch (mMode) {
405             case MODE_H264:
406                 if (strncmp((const char *)roleParams->cRole,
407                         "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE - 1))
408                     supported =  false;
409                 break;
410             case MODE_MPEG4:
411                 if (strncmp((const char *)roleParams->cRole,
412                         "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE - 1))
413                     supported =  false;
414                 break;
415             case MODE_MPEG2:
416                 if (strncmp((const char *)roleParams->cRole,
417                         "video_decoder.mpeg2v", OMX_MAX_STRINGNAME_SIZE - 1))
418                     supported =  false;
419                 break;
420             case MODE_H263:
421                 if (strncmp((const char *)roleParams->cRole,
422                         "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE - 1))
423                     supported =  false;
424                 break;
425             case MODE_VC1:
426                 if (strncmp((const char *)roleParams->cRole,
427                         "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE - 1))
428                     supported =  false;
429                 break;
430             case MODE_WMV:
431                 if (strncmp((const char *)roleParams->cRole,
432                         "video_decoder.wmv", OMX_MAX_STRINGNAME_SIZE - 1))
433                     supported =  false;
434                 break;
435             default:
436                 CHECK(!"Should not be here. Unsupported role.");
437                 break;
438             }
439             if (!supported) {
440                 LOGE("unsupported role: %s", (const char *)roleParams->cRole);
441                 return OMX_ErrorUndefined;
442             }
443
444             return OMX_ErrorNone;
445         }
446
447         case OMX_IndexParamVideoPortFormat:
448         {
449             OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
450                 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
451
452             if (formatParams->nPortIndex > 1) {
453                 return OMX_ErrorUndefined;
454             }
455
456             if (formatParams->nIndex != 0) {
457                 return OMX_ErrorNoMore;
458             }
459
460             return OMX_ErrorNone;
461         }
462
463         case OMX_IndexParamPortDefinition:
464         {
465             OMX_PARAM_PORTDEFINITIONTYPE *defParams =
466                 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
467
468             if (defParams->nPortIndex > 1 ||
469                     defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
470                 return OMX_ErrorUndefined;
471             }
472
473             CHECK_EQ((int)defParams->eDomain, (int)OMX_PortDomainVideo);
474
475             // only care about input port
476             if (defParams->nPortIndex == kPortIndexOutput) {
477                 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &defParams->format.video;
478                 mWidth = video_def->nFrameWidth;
479                 mHeight = video_def->nFrameHeight;
480                 LOGV("got OMX_IndexParamPortDefinition, mWidth: %d, mHeight: %d",
481                         mWidth, mHeight);
482                 return OMX_ErrorNone;
483             }
484
485             return OMX_ErrorNone;
486         }
487
488         case OMX_IndexParamVideoWmv:
489         {
490             OMX_VIDEO_PARAM_WMVTYPE *wmvParams =
491                 (OMX_VIDEO_PARAM_WMVTYPE *)params;
492
493             if (wmvParams->nPortIndex != 0) {
494                 return OMX_ErrorUndefined;
495             }
496
497             if (wmvParams->eFormat == OMX_VIDEO_WMVFormat7) {
498                 mCtx->codec_id = CODEC_ID_WMV1;
499             } else if (wmvParams->eFormat == OMX_VIDEO_WMVFormat8) {
500                 mCtx->codec_id = CODEC_ID_WMV2;
501             } else if (wmvParams->eFormat == OMX_VIDEO_WMVFormat9) {
502                 mCtx->codec_id = CODEC_ID_WMV3;
503             } else {
504                 LOGE("unsupported wmv codec: 0x%x", wmvParams->eFormat);
505                 return OMX_ErrorUndefined;
506             }
507
508             return OMX_ErrorNone;
509         }
510
511         default:
512             return SimpleSoftOMXComponent::internalSetParameter(index, params);
513     }
514 }
515
516 void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex) {
517     int err = 0;
518
519     if (mSignalledError || mOutputPortSettingsChange != NONE) {
520         return;
521     }
522
523     List<BufferInfo *> &inQueue = getPortQueue(0);
524     List<BufferInfo *> &outQueue = getPortQueue(1);
525
526     while (!inQueue.empty() && !outQueue.empty()) {
527         BufferInfo *inInfo = *inQueue.begin();
528         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
529
530         BufferInfo *outInfo = *outQueue.begin();
531         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
532
533         if (mCtx->width != mWidth || mCtx->height != mHeight) {
534             mCtx->width = mWidth;
535             mCtx->height = mHeight;
536             mStride = mWidth;
537
538             updatePortDefinitions();
539
540             notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
541             mOutputPortSettingsChange = AWAITING_DISABLED;
542             return;
543         }
544
545         if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
546             inQueue.erase(inQueue.begin());
547             inInfo->mOwnedByUs = false;
548             notifyEmptyBufferDone(inHeader);
549
550             outHeader->nFilledLen = 0;
551             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
552
553             outQueue.erase(outQueue.begin());
554             outInfo->mOwnedByUs = false;
555             notifyFillBufferDone(outHeader);
556             return;
557         }
558
559         if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
560             LOGI("got extradata, ignore: %d, size: %lu", mIgnoreExtradata, inHeader->nFilledLen);
561             hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
562             if (!mExtradataReady && !mIgnoreExtradata) {
563                 //if (mMode == MODE_H264)
564                 // it is possible to receive multiple input buffer with OMX_BUFFERFLAG_CODECCONFIG flag.
565                 // for example, H264, the first input buffer is SPS, and another is PPS!
566                 int orig_extradata_size = mCtx->extradata_size;
567                 mCtx->extradata_size += inHeader->nFilledLen;
568                 mCtx->extradata = (uint8_t *)realloc(mCtx->extradata,
569                         mCtx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
570                 if (!mCtx->extradata) {
571                     LOGE("ffmpeg video decoder failed to alloc extradata memory.");
572                     notify(OMX_EventError, OMX_ErrorInsufficientResources, 0, NULL);
573                     mSignalledError = true;
574                     return;
575                 }
576
577                 memcpy(mCtx->extradata + orig_extradata_size,
578                         inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
579                 memset(mCtx->extradata + mCtx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
580
581                 inInfo->mOwnedByUs = false;
582                 inQueue.erase(inQueue.begin());
583                 inInfo = NULL;
584                 notifyEmptyBufferDone(inHeader);
585                 inHeader = NULL;
586
587                 continue;
588             }
589
590             if (mIgnoreExtradata) {
591                 LOGI("got extradata, size: %lu, but ignore it", inHeader->nFilledLen);
592                 inInfo->mOwnedByUs = false;
593                 inQueue.erase(inQueue.begin());
594                 inInfo = NULL;
595                 notifyEmptyBufferDone(inHeader);
596                 inHeader = NULL;
597
598                 continue;
599             }
600         }
601
602         AVPacket pkt;
603         av_init_packet(&pkt);
604         pkt.data = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
605         pkt.size = inHeader->nFilledLen;
606         pkt.pts = inHeader->nTimeStamp;
607 #if DEBUG_PKT
608         LOGV("pkt size: %d, pts: %lld", pkt.size, pkt.pts);
609 #endif
610         if (!mExtradataReady) {
611             LOGI("extradata is ready");
612             hexdump(mCtx->extradata, mCtx->extradata_size);
613             mExtradataReady = true;
614
615             // find decoder again as codec_id may have changed
616             mCtx->codec = avcodec_find_decoder(mCtx->codec_id);
617             if (!mCtx->codec) {
618                 LOGE("ffmpeg video decoder failed to find codec");
619                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
620                 mSignalledError = true;
621                 return;
622             }
623
624             setAVCtxToDefault(mCtx, mCtx->codec);
625
626             LOGI("open ffmpeg decoder now");
627             err = avcodec_open2(mCtx, mCtx->codec, NULL);
628             if (err < 0) {
629                 LOGE("ffmpeg video decoder failed to initialize. (%d)", err);
630                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
631                 mSignalledError = true;
632                 return;
633             }
634         }
635
636         int gotPic = false;
637         AVFrame *frame = avcodec_alloc_frame();
638         err = avcodec_decode_video2(mCtx, frame, &gotPic, &pkt);
639         if (err < 0) {
640             LOGE("ffmpeg video decoder failed to decode frame. (%d)", err);
641             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
642             mSignalledError = true;
643             av_free(frame);
644             return;
645         }
646
647         if (gotPic) {
648             AVPicture pict;
649             void *buffer_to_free = NULL;
650             int64_t pts = AV_NOPTS_VALUE;
651             uint8_t *dst = outHeader->pBuffer;
652
653             // do deinterlace if necessary. for example, your TV is progressive
654             preProcessVideoFrame((AVPicture *)frame, &buffer_to_free);
655
656             memset(&pict, 0, sizeof(AVPicture));
657             pict.data[0] = dst;
658             pict.data[1] = dst + mStride * mHeight;
659             pict.data[2] = pict.data[1] + (mStride / 2  * mHeight / 2);
660             pict.linesize[0] = mStride;
661             pict.linesize[1] = mStride / 2;
662             pict.linesize[2] = mStride / 2;
663
664             int sws_flags = SWS_BICUBIC;
665             mImgConvertCtx = sws_getCachedContext(mImgConvertCtx,
666                    mWidth, mHeight, mCtx->pix_fmt, mWidth, mHeight,
667                    PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
668             if (mImgConvertCtx == NULL) {
669                 LOGE("Cannot initialize the conversion context");
670                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
671                 mSignalledError = true;
672                 av_free(frame);
673                 return;
674             }
675             sws_scale(mImgConvertCtx, frame->data, frame->linesize,
676                   0, mHeight, pict.data, pict.linesize);
677
678             outHeader->nOffset = 0;
679             outHeader->nFilledLen = (mStride * mHeight * 3) / 2;
680             outHeader->nFlags = 0;
681             if (frame->key_frame)
682                 outHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
683
684             // process timestamps
685             if (decoder_reorder_pts == -1) {
686                 pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
687                         frame, "best_effort_timestamp");
688             } else if (decoder_reorder_pts) {
689                 pts = frame->pkt_pts;
690             } else {
691                 pts = frame->pkt_dts;
692             }
693
694             if (pts == AV_NOPTS_VALUE) {
695                 pts = 0;
696             }
697             outHeader->nTimeStamp = pts;
698
699 #if DEBUG_FRM
700             LOGV("frame pts: %lld", pts);
701 #endif
702
703             outInfo->mOwnedByUs = false;
704             outQueue.erase(outQueue.begin());
705             outInfo = NULL;
706             notifyFillBufferDone(outHeader);
707             outHeader = NULL;
708
709             av_free(buffer_to_free);
710         }
711
712         inInfo->mOwnedByUs = false;
713         inQueue.erase(inQueue.begin());
714         inInfo = NULL;
715         notifyEmptyBufferDone(inHeader);
716         inHeader = NULL;
717         av_free(frame);
718     }
719 }
720
721 void SoftFFmpegVideo::onPortFlushCompleted(OMX_U32 portIndex) {
722     if (portIndex == 0 && mCtx) {
723         // Make sure that the next buffer output does not still
724         // depend on fragments from the last one decoded.
725         avcodec_flush_buffers(mCtx);
726     }
727 }
728
729 void SoftFFmpegVideo::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
730     if (portIndex != 1) {
731         return;
732     }
733
734     switch (mOutputPortSettingsChange) {
735         case NONE:
736             break;
737
738         case AWAITING_DISABLED:
739         {
740             CHECK(!enabled);
741             mOutputPortSettingsChange = AWAITING_ENABLED;
742             break;
743         }
744
745         default:
746         {
747             CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
748             CHECK(enabled);
749             mOutputPortSettingsChange = NONE;
750             break;
751         }
752     }
753 }
754
755 void SoftFFmpegVideo::updatePortDefinitions() {
756     OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
757     def->format.video.nFrameWidth = mWidth;
758     def->format.video.nFrameHeight = mHeight;
759     def->format.video.nStride = def->format.video.nFrameWidth;
760     def->format.video.nSliceHeight = def->format.video.nFrameHeight;
761     def->nBufferSize =
762             def->format.video.nFrameWidth * def->format.video.nFrameHeight;
763
764     def = &editPortInfo(1)->mDef;
765     def->format.video.nFrameWidth = mWidth;
766     def->format.video.nFrameHeight = mHeight;
767     def->format.video.nStride = def->format.video.nFrameWidth;
768     def->format.video.nSliceHeight = def->format.video.nFrameHeight;
769 #if 0
770     def->nBufferSize =
771         (def->format.video.nFrameWidth
772             * def->format.video.nFrameHeight * 3) / 2;
773 #else
774     def->nBufferSize =
775         (((def->format.video.nFrameWidth + 15) & -16)
776             * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
777 #endif
778 }
779
780 }  // namespace android
781
782 android::SoftOMXComponent *createSoftOMXComponent(
783         const char *name, const OMX_CALLBACKTYPE *callbacks,
784         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
785     return new android::SoftFFmpegVideo(name, callbacks, appData, component);
786 }
787