OSDN Git Service

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