OSDN Git Service

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