2 * Copyright 2012 Michael Chen <omxcodec@gmail.com>
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #define LOG_TAG "SoftFFmpegVideo"
19 #include <utils/Log.h>
21 #include "SoftFFmpegVideo.h"
23 #include <media/stagefright/foundation/ADebug.h>
24 #include <media/stagefright/foundation/hexdump.h>
25 #include <media/stagefright/MediaDefs.h>
27 #include <OMX_FFExt.h>
29 #include "utils/ffmpeg_utils.h"
34 static int decoder_reorder_pts = -1;
39 static void InitOMXParams(T *params) {
40 params->nSize = sizeof(T);
41 params->nVersion.s.nVersionMajor = 1;
42 params->nVersion.s.nVersionMinor = 0;
43 params->nVersion.s.nRevision = 0;
44 params->nVersion.s.nStep = 0;
47 void SoftFFmpegVideo::setMode(const char *name) {
48 if (!strcmp(name, "OMX.ffmpeg.mpeg2v.decoder")) {
50 } else if (!strcmp(name, "OMX.ffmpeg.h263.decoder")) {
52 } else if (!strcmp(name, "OMX.ffmpeg.mpeg4.decoder")) {
54 } else if (!strcmp(name, "OMX.ffmpeg.wmv.decoder")) {
56 } else if (!strcmp(name, "OMX.ffmpeg.rv.decoder")) {
58 } else if (!strcmp(name, "OMX.ffmpeg.h264.decoder")) {
60 } else if (!strcmp(name, "OMX.ffmpeg.vpx.decoder")) {
62 } else if (!strcmp(name, "OMX.ffmpeg.vc1.decoder")) {
64 } else if (!strcmp(name, "OMX.ffmpeg.flv1.decoder")) {
66 } else if (!strcmp(name, "OMX.ffmpeg.divx.decoder")) {
68 } else if (!strcmp(name, "OMX.ffmpeg.vtrial.decoder")) {
75 SoftFFmpegVideo::SoftFFmpegVideo(
77 const OMX_CALLBACKTYPE *callbacks,
79 OMX_COMPONENTTYPE **component)
80 : SimpleSoftOMXComponent(name, callbacks, appData, component),
82 mFFmpegAlreadyInited(false),
83 mCodecAlreadyOpened(false),
84 mPendingFrameAsSettingChanged(false),
88 mEOSStatus(INPUT_DATA_AVAILABLE),
89 mExtradataReady(false),
90 mIgnoreExtradata(false),
91 mSignalledError(false),
96 mOutputPortSettingsChange(NONE) {
100 ALOGD("SoftFFmpegVideo component: %s mMode: %d", name, mMode);
103 CHECK_EQ(initDecoder(), (status_t)OK);
106 SoftFFmpegVideo::~SoftFFmpegVideo() {
107 ALOGV("~SoftFFmpegVideo");
109 if (mFFmpegAlreadyInited) {
114 void SoftFFmpegVideo::initInputFormat(uint32_t mode,
115 OMX_PARAM_PORTDEFINITIONTYPE &def) {
118 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG2);
119 def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2;
122 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
123 def.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
126 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4);
127 def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
130 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_WMV);
131 def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
134 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RV);
135 def.format.video.eCompressionFormat = OMX_VIDEO_CodingRV;
138 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC);
139 def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
142 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VPX);
143 def.format.video.eCompressionFormat = OMX_VIDEO_CodingVPX;
146 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VC1);
147 def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
150 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_FLV1);
151 def.format.video.eCompressionFormat = OMX_VIDEO_CodingFLV1;
154 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_DIVX);
155 def.format.video.eCompressionFormat = OMX_VIDEO_CodingDIVX;
158 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_FFMPEG);
159 def.format.video.eCompressionFormat = OMX_VIDEO_CodingAutoDetect;
162 CHECK(!"Should not be here. Unsupported mime type and compression format");
166 def.format.video.pNativeRender = NULL;
167 def.format.video.nFrameWidth = mWidth;
168 def.format.video.nFrameHeight = mHeight;
169 def.format.video.nStride = def.format.video.nFrameWidth;
170 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
171 def.format.video.nBitrate = 0;
172 def.format.video.xFramerate = 0;
173 def.format.video.bFlagErrorConcealment = OMX_FALSE;
174 def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
175 def.format.video.pNativeWindow = NULL;
178 void SoftFFmpegVideo::initPorts() {
179 OMX_PARAM_PORTDEFINITIONTYPE def;
183 def.eDir = OMX_DirInput;
184 def.nBufferCountMin = kNumInputBuffers;
185 def.nBufferCountActual = def.nBufferCountMin;
186 def.nBufferSize = 1280 * 720; // 256 * 1024?
187 def.bEnabled = OMX_TRUE;
188 def.bPopulated = OMX_FALSE;
189 def.eDomain = OMX_PortDomainVideo;
190 def.bBuffersContiguous = OMX_FALSE;
191 def.nBufferAlignment = 1;
193 initInputFormat(mMode, def);
198 def.eDir = OMX_DirOutput;
199 def.nBufferCountMin = kNumOutputBuffers;
200 def.nBufferCountActual = def.nBufferCountMin;
201 def.bEnabled = OMX_TRUE;
202 def.bPopulated = OMX_FALSE;
203 def.eDomain = OMX_PortDomainVideo;
204 def.bBuffersContiguous = OMX_FALSE;
205 def.nBufferAlignment = 2;
207 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
208 def.format.video.pNativeRender = NULL;
209 def.format.video.nFrameWidth = mWidth;
210 def.format.video.nFrameHeight = mHeight;
211 def.format.video.nStride = def.format.video.nFrameWidth;
212 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
213 def.format.video.nBitrate = 0;
214 def.format.video.xFramerate = 0;
215 def.format.video.bFlagErrorConcealment = OMX_FALSE;
216 def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
217 def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
218 def.format.video.pNativeWindow = NULL;
221 (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
226 void SoftFFmpegVideo::setDefaultCtx(AVCodecContext *avctx, const AVCodec *codec) {
229 avctx->workaround_bugs = 1;
231 if(avctx->lowres > codec->max_lowres){
232 ALOGW("The maximum value for lowres supported by the decoder is %d",
234 avctx->lowres= codec->max_lowres;
236 avctx->idct_algo = 0;
237 avctx->skip_frame = AVDISCARD_DEFAULT;
238 avctx->skip_idct = AVDISCARD_DEFAULT;
239 avctx->skip_loop_filter = AVDISCARD_DEFAULT;
240 avctx->error_concealment = 3;
242 if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
243 if (fast) avctx->flags2 |= CODEC_FLAG2_FAST;
244 if(codec->capabilities & CODEC_CAP_DR1)
245 avctx->flags |= CODEC_FLAG_EMU_EDGE;
248 status_t SoftFFmpegVideo::initDecoder() {
251 status = initFFmpeg();
255 mFFmpegAlreadyInited = true;
257 mCtx = avcodec_alloc_context3(NULL);
260 ALOGE("avcodec_alloc_context failed.");
264 mCtx->codec_type = AVMEDIA_TYPE_VIDEO;
267 mCtx->codec_id = CODEC_ID_MPEG2VIDEO;
270 mCtx->codec_id = CODEC_ID_H263;
272 //mCtx->codec_id = CODEC_ID_H263P;
273 //mCtx->codec_id = CODEC_ID_H263I;
276 mCtx->codec_id = CODEC_ID_MPEG4;
279 mCtx->codec_id = CODEC_ID_WMV2; // default, adjust in "internalSetParameter" fxn
282 mCtx->codec_id = CODEC_ID_RV40; // default, adjust in "internalSetParameter" fxn
285 mCtx->codec_id = CODEC_ID_H264;
288 mCtx->codec_id = CODEC_ID_VP8;
291 mCtx->codec_id = CODEC_ID_VC1;
294 mCtx->codec_id = CODEC_ID_FLV1;
297 mCtx->codec_id = CODEC_ID_MPEG4;
300 mCtx->codec_id = CODEC_ID_NONE;
303 CHECK(!"Should not be here. Unsupported codec");
307 mCtx->extradata_size = 0;
308 mCtx->extradata = NULL;
309 mCtx->width = mWidth;
310 mCtx->height = mHeight;
315 void SoftFFmpegVideo::deInitDecoder() {
317 if (avcodec_is_open(mCtx)) {
318 avcodec_flush_buffers(mCtx);
320 if (mCtx->extradata) {
321 av_free(mCtx->extradata);
322 mCtx->extradata = NULL;
323 mCtx->extradata_size = 0;
325 if (mCodecAlreadyOpened) {
335 if (mImgConvertCtx) {
336 sws_freeContext(mImgConvertCtx);
337 mImgConvertCtx = NULL;
341 void SoftFFmpegVideo::getInputFormat(uint32_t mode,
342 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams) {
345 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG2;
348 formatParams->eCompressionFormat = OMX_VIDEO_CodingH263;
351 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG4;
354 formatParams->eCompressionFormat = OMX_VIDEO_CodingWMV;
357 formatParams->eCompressionFormat = OMX_VIDEO_CodingRV;
360 formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
363 formatParams->eCompressionFormat = OMX_VIDEO_CodingVPX;
366 formatParams->eCompressionFormat = OMX_VIDEO_CodingVC1;
369 formatParams->eCompressionFormat = OMX_VIDEO_CodingFLV1;
372 formatParams->eCompressionFormat = OMX_VIDEO_CodingDIVX;
375 formatParams->eCompressionFormat = OMX_VIDEO_CodingAutoDetect;
378 CHECK(!"Should not be here. Unsupported compression format.");
381 formatParams->eColorFormat = OMX_COLOR_FormatUnused;
382 formatParams->xFramerate = 0;
385 OMX_ERRORTYPE SoftFFmpegVideo::internalGetParameter(
386 OMX_INDEXTYPE index, OMX_PTR params) {
387 //ALOGV("internalGetParameter index:0x%x", index);
389 case OMX_IndexParamVideoPortFormat:
391 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
392 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
394 if (formatParams->nPortIndex > kOutputPortIndex) {
395 return OMX_ErrorUndefined;
398 if (formatParams->nIndex != 0) {
399 return OMX_ErrorNoMore;
402 if (formatParams->nPortIndex == kInputPortIndex) {
403 getInputFormat(mMode, formatParams);
405 CHECK_EQ(formatParams->nPortIndex, kOutputPortIndex);
407 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
408 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
409 formatParams->xFramerate = 0;
412 return OMX_ErrorNone;
415 case OMX_IndexParamVideoWmv:
417 OMX_VIDEO_PARAM_WMVTYPE *profile =
418 (OMX_VIDEO_PARAM_WMVTYPE *)params;
420 if (profile->nPortIndex != kInputPortIndex) {
421 return OMX_ErrorUndefined;
424 profile->eFormat = OMX_VIDEO_WMVFormatUnused;
426 return OMX_ErrorNone;
429 case OMX_IndexParamVideoRv:
431 OMX_VIDEO_PARAM_RVTYPE *profile =
432 (OMX_VIDEO_PARAM_RVTYPE *)params;
434 if (profile->nPortIndex != kInputPortIndex) {
435 return OMX_ErrorUndefined;
438 profile->eFormat = OMX_VIDEO_RVFormatUnused;
440 return OMX_ErrorNone;
444 if ((OMX_FF_INDEXTYPE)index == OMX_IndexParamVideoFFmpeg)
446 OMX_VIDEO_PARAM_FFMPEGTYPE *ffmpegParams =
447 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
449 if (ffmpegParams->nPortIndex != kInputPortIndex) {
450 return OMX_ErrorUndefined;
453 ffmpegParams->eCodecId = CODEC_ID_NONE;
454 ffmpegParams->nWidth = 0;
455 ffmpegParams->nHeight = 0;
457 return OMX_ErrorNone;
460 return SimpleSoftOMXComponent::internalGetParameter(index, params);
464 OMX_ERRORTYPE SoftFFmpegVideo::isRoleSupported(
465 const OMX_PARAM_COMPONENTROLETYPE *roleParams) {
466 bool supported = true;
470 if (strncmp((const char *)roleParams->cRole,
471 "video_decoder.mpeg2v", OMX_MAX_STRINGNAME_SIZE - 1))
475 if (strncmp((const char *)roleParams->cRole,
476 "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE - 1))
480 if (strncmp((const char *)roleParams->cRole,
481 "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE - 1))
485 if (strncmp((const char *)roleParams->cRole,
486 "video_decoder.wmv", OMX_MAX_STRINGNAME_SIZE - 1))
490 if (strncmp((const char *)roleParams->cRole,
491 "video_decoder.rv", OMX_MAX_STRINGNAME_SIZE - 1))
495 if (strncmp((const char *)roleParams->cRole,
496 "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE - 1))
500 if (strncmp((const char *)roleParams->cRole,
501 "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE - 1))
505 if (strncmp((const char *)roleParams->cRole,
506 "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE - 1))
510 if (strncmp((const char *)roleParams->cRole,
511 "video_decoder.flv1", OMX_MAX_STRINGNAME_SIZE - 1))
515 if (strncmp((const char *)roleParams->cRole,
516 "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE - 1))
520 if (strncmp((const char *)roleParams->cRole,
521 "video_decoder.trial", OMX_MAX_STRINGNAME_SIZE - 1))
525 CHECK(!"Should not be here. Unsupported role.");
530 ALOGE("unsupported role: %s", (const char *)roleParams->cRole);
531 return OMX_ErrorUndefined;
533 return OMX_ErrorNone;
536 OMX_ERRORTYPE SoftFFmpegVideo::internalSetParameter(
537 OMX_INDEXTYPE index, const OMX_PTR params) {
538 //ALOGV("internalSetParameter index:0x%x", index);
540 case OMX_IndexParamStandardComponentRole:
542 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
543 (const OMX_PARAM_COMPONENTROLETYPE *)params;
544 return isRoleSupported(roleParams);
547 case OMX_IndexParamVideoPortFormat:
549 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
550 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
552 if (formatParams->nPortIndex > kOutputPortIndex) {
553 return OMX_ErrorUndefined;
556 if (formatParams->nIndex != 0) {
557 return OMX_ErrorNoMore;
560 return OMX_ErrorNone;
563 case OMX_IndexParamPortDefinition:
565 OMX_PARAM_PORTDEFINITIONTYPE *defParams =
566 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
568 if (defParams->nPortIndex > kOutputPortIndex ||
569 defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
570 return OMX_ErrorUndefined;
573 CHECK_EQ((int)defParams->eDomain, (int)OMX_PortDomainVideo);
575 //only care about input port
576 if (defParams->nPortIndex == kOutputPortIndex) {
577 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &defParams->format.video;
578 mCtx->width = video_def->nFrameWidth;
579 mCtx->height = video_def->nFrameHeight;
580 ALOGV("got OMX_IndexParamPortDefinition, width: %lu, height: %lu",
581 video_def->nFrameWidth, video_def->nFrameHeight);
582 return OMX_ErrorNone;
585 return OMX_ErrorNone;
588 case OMX_IndexParamVideoWmv:
590 OMX_VIDEO_PARAM_WMVTYPE *profile =
591 (OMX_VIDEO_PARAM_WMVTYPE *)params;
593 if (profile->nPortIndex != kInputPortIndex) {
594 return OMX_ErrorUndefined;
597 if (profile->eFormat == OMX_VIDEO_WMVFormat7) {
598 mCtx->codec_id = CODEC_ID_WMV1;
599 } else if (profile->eFormat == OMX_VIDEO_WMVFormat8) {
600 mCtx->codec_id = CODEC_ID_WMV2;
601 } else if (profile->eFormat == OMX_VIDEO_WMVFormat9) {
602 mCtx->codec_id = CODEC_ID_WMV3;
604 ALOGE("unsupported wmv codec: 0x%x", profile->eFormat);
605 return OMX_ErrorUndefined;
608 return OMX_ErrorNone;
611 case OMX_IndexParamVideoRv:
613 OMX_VIDEO_PARAM_RVTYPE *profile =
614 (OMX_VIDEO_PARAM_RVTYPE *)params;
616 if (profile->nPortIndex != kInputPortIndex) {
617 return OMX_ErrorUndefined;
620 if (profile->eFormat == OMX_VIDEO_RVFormatG2) {
621 mCtx->codec_id = CODEC_ID_RV20;
622 } else if (profile->eFormat == OMX_VIDEO_RVFormat8) {
623 mCtx->codec_id = CODEC_ID_RV30;
624 } else if (profile->eFormat == OMX_VIDEO_RVFormat9) {
625 mCtx->codec_id = CODEC_ID_RV40;
627 ALOGE("unsupported rv codec: 0x%x", profile->eFormat);
628 return OMX_ErrorUndefined;
631 return OMX_ErrorNone;
635 if ((OMX_FF_INDEXTYPE)index == OMX_IndexParamVideoFFmpeg)
637 OMX_VIDEO_PARAM_FFMPEGTYPE *ffmpegParams =
638 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
640 if (ffmpegParams->nPortIndex != kInputPortIndex) {
641 return OMX_ErrorUndefined;
644 mCtx->codec_id = (enum AVCodecID)ffmpegParams->eCodecId;
645 mCtx->width = ffmpegParams->nWidth;
646 mCtx->height = ffmpegParams->nHeight;
648 ALOGD("got OMX_IndexParamVideoFFmpeg, "
649 "eCodecId:%ld(%s), width:%lu, height:%lu",
650 ffmpegParams->eCodecId,
651 avcodec_get_name(mCtx->codec_id),
652 ffmpegParams->nWidth,
653 ffmpegParams->nHeight);
655 return OMX_ErrorNone;
658 return SimpleSoftOMXComponent::internalSetParameter(index, params);
662 bool SoftFFmpegVideo::handlePortSettingChangeEvent() {
663 if (mCtx->width != mWidth || mCtx->height != mHeight) {
664 ALOGI("ffmpeg video port setting change event(%dx%d)->(%dx%d).",
665 mWidth, mHeight, mCtx->width, mCtx->height);
667 mWidth = mCtx->width;
668 mHeight = mCtx->height;
671 updatePortDefinitions();
672 notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
673 mOutputPortSettingsChange = AWAITING_DISABLED;
680 int32_t SoftFFmpegVideo::handleExtradata() {
681 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
682 BufferInfo *inInfo = *inQueue.begin();
683 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
685 ALOGI("got extradata, ignore: %d, size: %lu",
686 mIgnoreExtradata, inHeader->nFilledLen);
687 hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
689 if (mIgnoreExtradata) {
690 ALOGI("got extradata, size: %lu, but ignore it", inHeader->nFilledLen);
692 if (!mExtradataReady) {
693 //if (mMode == MODE_H264)
694 //it is possible to receive multiple input buffer with OMX_BUFFERFLAG_CODECCONFIG flag.
695 //for example, H264, the first input buffer is SPS, and another is PPS!
696 int orig_extradata_size = mCtx->extradata_size;
697 mCtx->extradata_size += inHeader->nFilledLen;
698 mCtx->extradata = (uint8_t *)realloc(mCtx->extradata,
699 mCtx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
700 if (!mCtx->extradata) {
701 ALOGE("ffmpeg video decoder failed to alloc extradata memory.");
705 memcpy(mCtx->extradata + orig_extradata_size,
706 inHeader->pBuffer + inHeader->nOffset,
707 inHeader->nFilledLen);
708 memset(mCtx->extradata + mCtx->extradata_size, 0,
709 FF_INPUT_BUFFER_PADDING_SIZE);
713 inQueue.erase(inQueue.begin());
714 inInfo->mOwnedByUs = false;
715 notifyEmptyBufferDone(inHeader);
720 int32_t SoftFFmpegVideo::openDecoder() {
721 if (mCodecAlreadyOpened) {
725 if (!mExtradataReady) {
726 ALOGI("extradata is ready, size: %d", mCtx->extradata_size);
727 hexdump(mCtx->extradata, mCtx->extradata_size);
728 mExtradataReady = true;
731 //find decoder again as codec_id may have changed
732 mCtx->codec = avcodec_find_decoder(mCtx->codec_id);
734 ALOGE("ffmpeg video decoder failed to find codec");
735 return ERR_CODEC_NOT_FOUND;
738 setDefaultCtx(mCtx, mCtx->codec);
740 ALOGD("begin to open ffmpeg decoder(%s) now",
741 avcodec_get_name(mCtx->codec_id));
743 int err = avcodec_open2(mCtx, mCtx->codec, NULL);
745 ALOGE("ffmpeg video decoder failed to initialize. (%s)", av_err2str(err));
746 return ERR_DECODER_OPEN_FAILED;
748 mCodecAlreadyOpened = true;
750 ALOGD("open ffmpeg video decoder(%s) success",
751 avcodec_get_name(mCtx->codec_id));
753 mFrame = avcodec_alloc_frame();
755 ALOGE("oom for video frame");
762 void SoftFFmpegVideo::initPacket(AVPacket *pkt,
763 OMX_BUFFERHEADERTYPE *inHeader) {
764 memset(pkt, 0, sizeof(AVPacket));
768 pkt->data = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
769 pkt->size = inHeader->nFilledLen;
770 pkt->pts = inHeader->nTimeStamp;
774 pkt->pts = AV_NOPTS_VALUE;
778 if (pkt->pts != AV_NOPTS_VALUE)
780 ALOGV("pkt size:%d, pts:%lld", pkt->size, pkt->pts);
782 ALOGV("pkt size:%d, pts:N/A", pkt->size);
787 int32_t SoftFFmpegVideo::decodeVideo() {
790 int32_t ret = ERR_OK;
791 bool is_flush = (mEOSStatus != INPUT_DATA_AVAILABLE);
792 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
793 BufferInfo *inInfo = NULL;
794 OMX_BUFFERHEADERTYPE *inHeader = NULL;
797 inInfo = *inQueue.begin();
798 CHECK(inInfo != NULL);
799 inHeader = inInfo->mHeader;
803 initPacket(&pkt, inHeader);
804 //av_frame_unref(mFrame); //Don't unref mFrame!!!
805 avcodec_get_frame_defaults(mFrame);
807 int err = avcodec_decode_video2(mCtx, mFrame, &gotPic, &pkt);
809 ALOGE("ffmpeg video decoder failed to decode frame. (%d)", err);
810 //don't send error to OMXCodec, skip!
814 ALOGI("ffmpeg video decoder failed to get frame.");
815 //stop sending empty packets if the decoder is finished
816 if (is_flush && mCtx->codec->capabilities & CODEC_CAP_DELAY) {
822 if (handlePortSettingChangeEvent()) {
823 mPendingFrameAsSettingChanged = true;
830 inQueue.erase(inQueue.begin());
831 inInfo->mOwnedByUs = false;
832 notifyEmptyBufferDone(inHeader);
838 int32_t SoftFFmpegVideo::preProcessVideoFrame(AVPicture *picture, void **bufp) {
840 AVPicture picture_tmp;
843 //deinterlace : must be done before any resize
844 if (mDoDeinterlace) {
847 //create temporary picture
848 size = avpicture_get_size(mCtx->pix_fmt, mCtx->width, mCtx->height);
849 buf = (uint8_t *)av_malloc(size);
851 ALOGE("oom for temporary picture");
855 picture2 = &picture_tmp;
856 avpicture_fill(picture2, buf, mCtx->pix_fmt, mCtx->width, mCtx->height);
858 if (avpicture_deinterlace(picture2, picture,
859 mCtx->pix_fmt, mCtx->width, mCtx->height) < 0) {
860 //if error, do not deinterlace
861 ALOGE("Deinterlacing failed");
870 if (picture != picture2)
871 *picture = *picture2;
877 int32_t SoftFFmpegVideo::drainOneOutputBuffer() {
878 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
879 BufferInfo *outInfo = *outQueue.begin();
880 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
883 void *buffer_to_free = NULL;
884 int64_t pts = AV_NOPTS_VALUE;
885 uint8_t *dst = outHeader->pBuffer;
887 //do deinterlace if necessary. for example, your TV is progressive
888 int32_t err = preProcessVideoFrame((AVPicture *)mFrame, &buffer_to_free);
890 ALOGE("preProcessVideoFrame failed");
894 memset(&pict, 0, sizeof(AVPicture));
896 pict.data[1] = dst + mStride * mHeight;
897 pict.data[2] = pict.data[1] + (mStride / 2 * mHeight / 2);
898 pict.linesize[0] = mStride;
899 pict.linesize[1] = mStride / 2;
900 pict.linesize[2] = mStride / 2;
902 int sws_flags = SWS_BICUBIC;
903 mImgConvertCtx = sws_getCachedContext(mImgConvertCtx,
904 mWidth, mHeight, mCtx->pix_fmt, mWidth, mHeight,
905 PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
906 if (mImgConvertCtx == NULL) {
907 ALOGE("Cannot initialize the conversion context");
908 av_free(buffer_to_free);
909 return ERR_SWS_FAILED;
911 sws_scale(mImgConvertCtx, mFrame->data, mFrame->linesize,
912 0, mHeight, pict.data, pict.linesize);
914 outHeader->nOffset = 0;
915 outHeader->nFilledLen = (mStride * mHeight * 3) / 2;
916 outHeader->nFlags = 0;
917 if (mFrame->key_frame) {
918 outHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
922 if (decoder_reorder_pts == -1) {
923 pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
924 mFrame, "best_effort_timestamp");
925 } else if (decoder_reorder_pts) {
926 pts = mFrame->pkt_pts;
928 pts = mFrame->pkt_dts;
931 if (pts == AV_NOPTS_VALUE) {
934 outHeader->nTimeStamp = pts;
937 ALOGV("mFrame pts: %lld", pts);
940 outQueue.erase(outQueue.begin());
941 outInfo->mOwnedByUs = false;
942 notifyFillBufferDone(outHeader);
944 av_free(buffer_to_free);
949 void SoftFFmpegVideo::drainEOSOutputBuffer() {
950 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
951 BufferInfo *outInfo = *outQueue.begin();
952 CHECK(outInfo != NULL);
953 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
955 ALOGD("ffmpeg video decoder fill eos outbuf");
957 outHeader->nTimeStamp = 0;
958 outHeader->nFilledLen = 0;
959 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
961 outQueue.erase(outQueue.begin());
962 outInfo->mOwnedByUs = false;
963 notifyFillBufferDone(outHeader);
965 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
968 void SoftFFmpegVideo::drainAllOutputBuffers() {
969 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
970 if (!mCodecAlreadyOpened) {
971 drainEOSOutputBuffer();
972 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
976 if(!(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
977 drainEOSOutputBuffer();
978 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
982 while (!outQueue.empty()) {
983 if (!mPendingFrameAsSettingChanged) {
984 int32_t err = decodeVideo();
986 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
987 mSignalledError = true;
989 } else if (err == ERR_FLUSHED) {
990 drainEOSOutputBuffer();
993 CHECK_EQ(err, ERR_OK);
994 if (mPendingFrameAsSettingChanged) {
1000 if (drainOneOutputBuffer() != ERR_OK) {
1001 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1002 mSignalledError = true;
1006 if (mPendingFrameAsSettingChanged) {
1007 mPendingFrameAsSettingChanged = false;
1012 void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex) {
1013 BufferInfo *inInfo = NULL;
1014 OMX_BUFFERHEADERTYPE *inHeader = NULL;
1015 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
1016 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
1018 if (mSignalledError || mOutputPortSettingsChange != NONE) {
1022 if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
1026 while (((mEOSStatus != INPUT_DATA_AVAILABLE) || !inQueue.empty())
1027 && !outQueue.empty()) {
1028 if (mEOSStatus == INPUT_EOS_SEEN) {
1029 drainAllOutputBuffers();
1033 inInfo = *inQueue.begin();
1034 inHeader = inInfo->mHeader;
1036 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
1037 ALOGD("ffmpeg video decoder empty eos inbuf");
1038 inQueue.erase(inQueue.begin());
1039 inInfo->mOwnedByUs = false;
1040 notifyEmptyBufferDone(inHeader);
1041 mEOSStatus = INPUT_EOS_SEEN;
1045 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1046 if (handleExtradata() != ERR_OK) {
1047 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1048 mSignalledError = true;
1053 if (!mCodecAlreadyOpened) {
1054 if (openDecoder() != ERR_OK) {
1055 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1056 mSignalledError = true;
1061 if (!mPendingFrameAsSettingChanged) {
1062 int32_t err = decodeVideo();
1064 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1065 mSignalledError = true;
1067 } else if (err == ERR_NO_FRM) {
1070 CHECK_EQ(err, ERR_OK);
1071 if (mPendingFrameAsSettingChanged) {
1077 if (drainOneOutputBuffer() != ERR_OK) {
1078 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1079 mSignalledError = true;
1083 if (mPendingFrameAsSettingChanged) {
1084 mPendingFrameAsSettingChanged = false;
1089 void SoftFFmpegVideo::onPortFlushCompleted(OMX_U32 portIndex) {
1090 ALOGV("ffmpeg video decoder flush port(%lu)", portIndex);
1091 if (portIndex == kInputPortIndex && mCtx) {
1093 //Make sure that the next buffer output does not still
1094 //depend on fragments from the last one decoded.
1095 avcodec_flush_buffers(mCtx);
1097 mEOSStatus = INPUT_DATA_AVAILABLE;
1101 void SoftFFmpegVideo::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
1102 if (portIndex != kOutputPortIndex) {
1106 switch (mOutputPortSettingsChange) {
1110 case AWAITING_DISABLED:
1113 mOutputPortSettingsChange = AWAITING_ENABLED;
1119 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
1121 mOutputPortSettingsChange = NONE;
1127 void SoftFFmpegVideo::updatePortDefinitions() {
1128 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
1129 def->format.video.nFrameWidth = mWidth;
1130 def->format.video.nFrameHeight = mHeight;
1131 def->format.video.nStride = def->format.video.nFrameWidth;
1132 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
1134 def->format.video.nFrameWidth * def->format.video.nFrameHeight;
1136 def = &editPortInfo(1)->mDef;
1137 def->format.video.nFrameWidth = mWidth;
1138 def->format.video.nFrameHeight = mHeight;
1139 def->format.video.nStride = def->format.video.nFrameWidth;
1140 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
1143 (def->format.video.nFrameWidth
1144 * def->format.video.nFrameHeight * 3) / 2;
1147 (((def->format.video.nFrameWidth + 15) & -16)
1148 * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
1152 } // namespace android
1154 android::SoftOMXComponent *createSoftOMXComponent(
1155 const char *name, const OMX_CALLBACKTYPE *callbacks,
1156 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
1157 return new android::SoftFFmpegVideo(name, callbacks, appData, component);