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.
17 //#define LOG_NDEBUG 0
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>
30 static int decoder_reorder_pts = -1;
35 static void InitOMXParams(T *params) {
36 params->nSize = sizeof(T);
37 params->nVersion.s.nVersionMajor = 1;
38 params->nVersion.s.nVersionMinor = 0;
39 params->nVersion.s.nRevision = 0;
40 params->nVersion.s.nStep = 0;
43 void SoftFFmpegVideo::setMode(const char *name) {
44 if (!strcmp(name, "OMX.ffmpeg.mpeg2.decoder")) {
46 } else if (!strcmp(name, "OMX.ffmpeg.h263.decoder")) {
48 } else if (!strcmp(name, "OMX.ffmpeg.mpeg4.decoder")) {
50 } else if (!strcmp(name, "OMX.ffmpeg.wmv.decoder")) {
52 } else if (!strcmp(name, "OMX.ffmpeg.rv.decoder")) {
54 } else if (!strcmp(name, "OMX.ffmpeg.h264.decoder")) {
56 } else if (!strcmp(name, "OMX.ffmpeg.vp8.decoder")) {
58 } else if (!strcmp(name, "OMX.ffmpeg.vp9.decoder")) {
60 } else if (!strcmp(name, "OMX.ffmpeg.vc1.decoder")) {
62 } else if (!strcmp(name, "OMX.ffmpeg.flv1.decoder")) {
64 } else if (!strcmp(name, "OMX.ffmpeg.divx.decoder")) {
66 } else if (!strcmp(name, "OMX.ffmpeg.hevc.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 mPendingSettingChangeEvent(false),
85 mPendingFrameAsSettingChanged(false),
89 mEOSStatus(INPUT_DATA_AVAILABLE),
90 mExtradataReady(false),
91 mIgnoreExtradata(false),
92 mSignalledError(false),
97 mOutputPortSettingsChange(NONE) {
99 ALOGD("SoftFFmpegVideo component: %s mMode: %d appData: %p", name, mMode, appData);
104 CHECK_EQ(initDecoder(), (status_t)OK);
107 SoftFFmpegVideo::~SoftFFmpegVideo() {
108 ALOGV("~SoftFFmpegVideo");
110 if (mFFmpegAlreadyInited) {
115 void SoftFFmpegVideo::initInputFormat(uint32_t mode,
116 OMX_PARAM_PORTDEFINITIONTYPE &def) {
119 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG2);
120 def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2;
123 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
124 def.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
127 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4);
128 def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
131 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_WMV);
132 def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
135 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RV);
136 def.format.video.eCompressionFormat = OMX_VIDEO_CodingRV;
139 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC);
140 def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
143 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VP8);
144 def.format.video.eCompressionFormat = OMX_VIDEO_CodingVP8;
147 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VP9);
148 def.format.video.eCompressionFormat = OMX_VIDEO_CodingVP9;
151 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VC1);
152 def.format.video.eCompressionFormat = OMX_VIDEO_CodingVC1;
155 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_FLV1);
156 def.format.video.eCompressionFormat = OMX_VIDEO_CodingFLV1;
159 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_DIVX);
160 def.format.video.eCompressionFormat = OMX_VIDEO_CodingDIVX;
163 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_HEVC);
164 def.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC;
167 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_FFMPEG);
168 def.format.video.eCompressionFormat = OMX_VIDEO_CodingAutoDetect;
171 CHECK(!"Should not be here. Unsupported mime type and compression format");
175 def.format.video.pNativeRender = NULL;
176 def.format.video.nFrameWidth = mWidth;
177 def.format.video.nFrameHeight = mHeight;
178 def.format.video.nStride = def.format.video.nFrameWidth;
179 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
180 def.format.video.nBitrate = 0;
181 def.format.video.xFramerate = 0;
182 def.format.video.bFlagErrorConcealment = OMX_FALSE;
183 def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
184 def.format.video.pNativeWindow = NULL;
187 void SoftFFmpegVideo::initPorts() {
188 OMX_PARAM_PORTDEFINITIONTYPE def;
192 def.eDir = OMX_DirInput;
193 def.nBufferCountMin = kNumInputBuffers;
194 def.nBufferCountActual = def.nBufferCountMin;
195 def.nBufferSize = 1280 * 720 * 3 / 2; // 256 * 1024?
196 def.bEnabled = OMX_TRUE;
197 def.bPopulated = OMX_FALSE;
198 def.eDomain = OMX_PortDomainVideo;
199 def.bBuffersContiguous = OMX_FALSE;
200 def.nBufferAlignment = 1;
202 initInputFormat(mMode, def);
207 def.eDir = OMX_DirOutput;
208 def.nBufferCountMin = kNumOutputBuffers;
209 def.nBufferCountActual = def.nBufferCountMin;
210 def.bEnabled = OMX_TRUE;
211 def.bPopulated = OMX_FALSE;
212 def.eDomain = OMX_PortDomainVideo;
213 def.bBuffersContiguous = OMX_FALSE;
214 def.nBufferAlignment = 2;
216 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
217 def.format.video.pNativeRender = NULL;
218 def.format.video.nFrameWidth = mWidth;
219 def.format.video.nFrameHeight = mHeight;
220 def.format.video.nStride = def.format.video.nFrameWidth;
221 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
222 def.format.video.nBitrate = 0;
223 def.format.video.xFramerate = 0;
224 def.format.video.bFlagErrorConcealment = OMX_FALSE;
225 def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
226 def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
227 def.format.video.pNativeWindow = NULL;
230 (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
235 void SoftFFmpegVideo::setDefaultCtx(AVCodecContext *avctx, const AVCodec *codec) {
238 avctx->workaround_bugs = 1;
240 if(avctx->lowres > codec->max_lowres){
241 ALOGW("The maximum value for lowres supported by the decoder is %d",
243 avctx->lowres= codec->max_lowres;
245 avctx->idct_algo = 0;
246 avctx->skip_frame = AVDISCARD_DEFAULT;
247 avctx->skip_idct = AVDISCARD_DEFAULT;
248 avctx->skip_loop_filter = AVDISCARD_DEFAULT;
249 avctx->error_concealment = 3;
251 if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
252 if (fast) avctx->flags2 |= CODEC_FLAG2_FAST;
253 if(codec->capabilities & CODEC_CAP_DR1)
254 avctx->flags |= CODEC_FLAG_EMU_EDGE;
257 status_t SoftFFmpegVideo::initDecoder() {
260 status = initFFmpeg();
264 mFFmpegAlreadyInited = true;
266 mCtx = avcodec_alloc_context3(NULL);
269 ALOGE("avcodec_alloc_context failed.");
273 mCtx->codec_type = AVMEDIA_TYPE_VIDEO;
276 mCtx->codec_id = AV_CODEC_ID_MPEG2VIDEO;
279 mCtx->codec_id = AV_CODEC_ID_H263;
281 //mCtx->codec_id = AV_CODEC_ID_H263P;
282 //mCtx->codec_id = AV_CODEC_ID_H263I;
285 mCtx->codec_id = AV_CODEC_ID_MPEG4;
288 mCtx->codec_id = AV_CODEC_ID_WMV2; // default, adjust in "internalSetParameter" fxn
291 mCtx->codec_id = AV_CODEC_ID_RV40; // default, adjust in "internalSetParameter" fxn
294 mCtx->codec_id = AV_CODEC_ID_H264;
297 mCtx->codec_id = AV_CODEC_ID_VP8;
300 mCtx->codec_id = AV_CODEC_ID_VP9;
303 mCtx->codec_id = AV_CODEC_ID_VC1;
306 mCtx->codec_id = AV_CODEC_ID_FLV1;
309 mCtx->codec_id = AV_CODEC_ID_MPEG4;
312 mCtx->codec_id = AV_CODEC_ID_HEVC;
315 mCtx->codec_id = AV_CODEC_ID_NONE;
318 CHECK(!"Should not be here. Unsupported codec");
322 mCtx->extradata_size = 0;
323 mCtx->extradata = NULL;
324 mCtx->width = mWidth;
325 mCtx->height = mHeight;
330 void SoftFFmpegVideo::deInitDecoder() {
332 if (avcodec_is_open(mCtx)) {
333 avcodec_flush_buffers(mCtx);
335 if (mCtx->extradata) {
336 av_free(mCtx->extradata);
337 mCtx->extradata = NULL;
338 mCtx->extradata_size = 0;
340 if (mCodecAlreadyOpened) {
350 if (mImgConvertCtx) {
351 sws_freeContext(mImgConvertCtx);
352 mImgConvertCtx = NULL;
356 void SoftFFmpegVideo::getInputFormat(uint32_t mode,
357 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams) {
360 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG2;
363 formatParams->eCompressionFormat = OMX_VIDEO_CodingH263;
366 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG4;
369 formatParams->eCompressionFormat = OMX_VIDEO_CodingWMV;
372 formatParams->eCompressionFormat = OMX_VIDEO_CodingRV;
375 formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
378 formatParams->eCompressionFormat = OMX_VIDEO_CodingVP8;
381 formatParams->eCompressionFormat = OMX_VIDEO_CodingVP9;
384 formatParams->eCompressionFormat = OMX_VIDEO_CodingVC1;
387 formatParams->eCompressionFormat = OMX_VIDEO_CodingFLV1;
390 formatParams->eCompressionFormat = OMX_VIDEO_CodingDIVX;
393 formatParams->eCompressionFormat = OMX_VIDEO_CodingHEVC;
396 formatParams->eCompressionFormat = OMX_VIDEO_CodingAutoDetect;
399 CHECK(!"Should not be here. Unsupported compression format.");
402 formatParams->eColorFormat = OMX_COLOR_FormatUnused;
403 formatParams->xFramerate = 0;
406 OMX_ERRORTYPE SoftFFmpegVideo::internalGetParameter(
407 OMX_INDEXTYPE index, OMX_PTR params) {
408 //ALOGV("internalGetParameter index:0x%x", index);
410 case OMX_IndexParamVideoPortFormat:
412 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
413 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
415 if (formatParams->nPortIndex > kOutputPortIndex) {
416 return OMX_ErrorUndefined;
419 if (formatParams->nIndex != 0) {
420 return OMX_ErrorNoMore;
423 if (formatParams->nPortIndex == kInputPortIndex) {
424 getInputFormat(mMode, formatParams);
426 CHECK_EQ(formatParams->nPortIndex, kOutputPortIndex);
428 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
429 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
430 formatParams->xFramerate = 0;
433 return OMX_ErrorNone;
436 case OMX_IndexParamVideoWmv:
438 OMX_VIDEO_PARAM_WMVTYPE *profile =
439 (OMX_VIDEO_PARAM_WMVTYPE *)params;
441 if (profile->nPortIndex != kInputPortIndex) {
442 return OMX_ErrorUndefined;
445 profile->eFormat = OMX_VIDEO_WMVFormatUnused;
447 return OMX_ErrorNone;
450 case OMX_IndexParamVideoRv:
452 OMX_VIDEO_PARAM_RVTYPE *profile =
453 (OMX_VIDEO_PARAM_RVTYPE *)params;
455 if (profile->nPortIndex != kInputPortIndex) {
456 return OMX_ErrorUndefined;
459 profile->eFormat = OMX_VIDEO_RVFormatUnused;
461 return OMX_ErrorNone;
464 case OMX_IndexParamVideoFFmpeg:
466 OMX_VIDEO_PARAM_FFMPEGTYPE *profile =
467 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
469 if (profile->nPortIndex != kInputPortIndex) {
470 return OMX_ErrorUndefined;
473 profile->eCodecId = AV_CODEC_ID_NONE;
475 profile->nHeight = 0;
477 return OMX_ErrorNone;
482 return SimpleSoftOMXComponent::internalGetParameter(index, params);
486 OMX_ERRORTYPE SoftFFmpegVideo::isRoleSupported(
487 const OMX_PARAM_COMPONENTROLETYPE *roleParams) {
488 bool supported = true;
492 if (strncmp((const char *)roleParams->cRole,
493 "video_decoder.mpeg2", OMX_MAX_STRINGNAME_SIZE - 1))
497 if (strncmp((const char *)roleParams->cRole,
498 "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE - 1))
502 if (strncmp((const char *)roleParams->cRole,
503 "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE - 1))
507 if (strncmp((const char *)roleParams->cRole,
508 "video_decoder.wmv", OMX_MAX_STRINGNAME_SIZE - 1))
512 if (strncmp((const char *)roleParams->cRole,
513 "video_decoder.rv", OMX_MAX_STRINGNAME_SIZE - 1))
517 if (strncmp((const char *)roleParams->cRole,
518 "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE - 1))
522 if (strncmp((const char *)roleParams->cRole,
523 "video_decoder.vp8", OMX_MAX_STRINGNAME_SIZE - 1))
527 if (strncmp((const char *)roleParams->cRole,
528 "video_decoder.vp9", OMX_MAX_STRINGNAME_SIZE - 1))
532 if (strncmp((const char *)roleParams->cRole,
533 "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE - 1))
537 if (strncmp((const char *)roleParams->cRole,
538 "video_decoder.flv1", OMX_MAX_STRINGNAME_SIZE - 1))
542 if (strncmp((const char *)roleParams->cRole,
543 "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE - 1))
547 if (strncmp((const char *)roleParams->cRole,
548 "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE - 1))
552 if (strncmp((const char *)roleParams->cRole,
553 "video_decoder.trial", OMX_MAX_STRINGNAME_SIZE - 1))
557 CHECK(!"Should not be here. Unsupported role.");
562 ALOGE("unsupported role: %s", (const char *)roleParams->cRole);
563 return OMX_ErrorUndefined;
565 return OMX_ErrorNone;
568 OMX_ERRORTYPE SoftFFmpegVideo::internalSetParameter(
569 OMX_INDEXTYPE index, const OMX_PTR params) {
570 //ALOGV("internalSetParameter index:0x%x", index);
572 case OMX_IndexParamStandardComponentRole:
574 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
575 (const OMX_PARAM_COMPONENTROLETYPE *)params;
576 return isRoleSupported(roleParams);
579 case OMX_IndexParamVideoPortFormat:
581 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
582 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
584 if (formatParams->nPortIndex > kOutputPortIndex) {
585 return OMX_ErrorUndefined;
588 if (formatParams->nIndex != 0) {
589 return OMX_ErrorNoMore;
592 return OMX_ErrorNone;
595 case OMX_IndexParamPortDefinition:
597 OMX_PARAM_PORTDEFINITIONTYPE *defParams =
598 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
600 if (defParams->nPortIndex > kOutputPortIndex ||
601 defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
602 return OMX_ErrorUndefined;
605 CHECK_EQ((int)defParams->eDomain, (int)OMX_PortDomainVideo);
607 //only care about input port
608 if (defParams->nPortIndex == kOutputPortIndex) {
609 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &defParams->format.video;
610 mCtx->width = video_def->nFrameWidth;
611 mCtx->height = video_def->nFrameHeight;
612 ALOGV("got OMX_IndexParamPortDefinition, width: %lu, height: %lu",
613 video_def->nFrameWidth, video_def->nFrameHeight);
614 return OMX_ErrorNone;
617 return OMX_ErrorNone;
620 case OMX_IndexParamVideoWmv:
622 OMX_VIDEO_PARAM_WMVTYPE *profile =
623 (OMX_VIDEO_PARAM_WMVTYPE *)params;
625 if (profile->nPortIndex != kInputPortIndex) {
626 return OMX_ErrorUndefined;
629 if (profile->eFormat == OMX_VIDEO_WMVFormat7) {
630 mCtx->codec_id = AV_CODEC_ID_WMV1;
631 } else if (profile->eFormat == OMX_VIDEO_WMVFormat8) {
632 mCtx->codec_id = AV_CODEC_ID_WMV2;
633 } else if (profile->eFormat == OMX_VIDEO_WMVFormat9) {
634 mCtx->codec_id = AV_CODEC_ID_WMV3;
636 ALOGE("unsupported wmv codec: 0x%x", profile->eFormat);
637 return OMX_ErrorUndefined;
640 return OMX_ErrorNone;
643 case OMX_IndexParamVideoRv:
645 OMX_VIDEO_PARAM_RVTYPE *profile =
646 (OMX_VIDEO_PARAM_RVTYPE *)params;
648 if (profile->nPortIndex != kInputPortIndex) {
649 return OMX_ErrorUndefined;
652 if (profile->eFormat == OMX_VIDEO_RVFormatG2) {
653 mCtx->codec_id = AV_CODEC_ID_RV20;
654 } else if (profile->eFormat == OMX_VIDEO_RVFormat8) {
655 mCtx->codec_id = AV_CODEC_ID_RV30;
656 } else if (profile->eFormat == OMX_VIDEO_RVFormat9) {
657 mCtx->codec_id = AV_CODEC_ID_RV40;
659 ALOGE("unsupported rv codec: 0x%x", profile->eFormat);
660 return OMX_ErrorUndefined;
663 return OMX_ErrorNone;
666 case OMX_IndexParamVideoFFmpeg:
668 OMX_VIDEO_PARAM_FFMPEGTYPE *profile =
669 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
671 if (profile->nPortIndex != kInputPortIndex) {
672 return OMX_ErrorUndefined;
675 mCtx->codec_id = (enum AVCodecID)profile->eCodecId;
676 mCtx->width = profile->nWidth;
677 mCtx->height = profile->nHeight;
679 ALOGD("got OMX_IndexParamVideoFFmpeg, "
680 "eCodecId:%ld(%s), width:%lu, height:%lu",
682 avcodec_get_name(mCtx->codec_id),
686 return OMX_ErrorNone;
691 return SimpleSoftOMXComponent::internalSetParameter(index, params);
695 bool SoftFFmpegVideo::isPortSettingChanged() {
696 return (mCtx->width != mWidth || mCtx->height != mHeight);
699 bool SoftFFmpegVideo::handlePortSettingChangeEvent() {
700 if (mCtx->width != mWidth || mCtx->height != mHeight) {
701 ALOGI("ffmpeg video port setting change event(%dx%d)->(%dx%d).",
702 mWidth, mHeight, mCtx->width, mCtx->height);
704 mWidth = mCtx->width;
705 mHeight = mCtx->height;
708 updatePortDefinitions();
709 notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
710 mOutputPortSettingsChange = AWAITING_DISABLED;
717 int32_t SoftFFmpegVideo::handleExtradata() {
718 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
719 BufferInfo *inInfo = *inQueue.begin();
720 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
722 ALOGI("got extradata, ignore: %d, size: %lu",
723 mIgnoreExtradata, inHeader->nFilledLen);
724 hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
726 if (mIgnoreExtradata) {
727 ALOGI("got extradata, size: %lu, but ignore it", inHeader->nFilledLen);
729 if (!mExtradataReady) {
730 //if (mMode == MODE_H264)
731 //it is possible to receive multiple input buffer with OMX_BUFFERFLAG_CODECCONFIG flag.
732 //for example, H264, the first input buffer is SPS, and another is PPS!
733 int orig_extradata_size = mCtx->extradata_size;
734 mCtx->extradata_size += inHeader->nFilledLen;
735 mCtx->extradata = (uint8_t *)realloc(mCtx->extradata,
736 mCtx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
737 if (!mCtx->extradata) {
738 ALOGE("ffmpeg video decoder failed to alloc extradata memory.");
742 memcpy(mCtx->extradata + orig_extradata_size,
743 inHeader->pBuffer + inHeader->nOffset,
744 inHeader->nFilledLen);
745 memset(mCtx->extradata + mCtx->extradata_size, 0,
746 FF_INPUT_BUFFER_PADDING_SIZE);
750 inQueue.erase(inQueue.begin());
751 inInfo->mOwnedByUs = false;
752 notifyEmptyBufferDone(inHeader);
757 int32_t SoftFFmpegVideo::openDecoder() {
758 if (mCodecAlreadyOpened) {
762 if (!mExtradataReady) {
763 ALOGI("extradata is ready, size: %d", mCtx->extradata_size);
764 hexdump(mCtx->extradata, mCtx->extradata_size);
765 mExtradataReady = true;
768 //find decoder again as codec_id may have changed
769 mCtx->codec = avcodec_find_decoder(mCtx->codec_id);
771 ALOGE("ffmpeg video decoder failed to find codec");
772 return ERR_CODEC_NOT_FOUND;
775 setDefaultCtx(mCtx, mCtx->codec);
777 ALOGD("begin to open ffmpeg decoder(%s) now",
778 avcodec_get_name(mCtx->codec_id));
780 int err = avcodec_open2(mCtx, mCtx->codec, NULL);
782 ALOGE("ffmpeg video decoder failed to initialize. (%s)", av_err2str(err));
783 return ERR_DECODER_OPEN_FAILED;
785 mCodecAlreadyOpened = true;
787 ALOGD("open ffmpeg video decoder(%s) success",
788 avcodec_get_name(mCtx->codec_id));
790 mFrame = avcodec_alloc_frame();
792 ALOGE("oom for video frame");
799 void SoftFFmpegVideo::initPacket(AVPacket *pkt,
800 OMX_BUFFERHEADERTYPE *inHeader) {
801 memset(pkt, 0, sizeof(AVPacket));
805 pkt->data = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
806 pkt->size = inHeader->nFilledLen;
807 pkt->pts = inHeader->nTimeStamp;
811 pkt->pts = AV_NOPTS_VALUE;
815 if (pkt->pts != AV_NOPTS_VALUE)
817 ALOGV("pkt size:%d, pts:%lld", pkt->size, pkt->pts);
819 ALOGV("pkt size:%d, pts:N/A", pkt->size);
824 int32_t SoftFFmpegVideo::decodeVideo() {
827 int32_t ret = ERR_OK;
828 bool is_flush = (mEOSStatus != INPUT_DATA_AVAILABLE);
829 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
830 BufferInfo *inInfo = NULL;
831 OMX_BUFFERHEADERTYPE *inHeader = NULL;
834 inInfo = *inQueue.begin();
835 CHECK(inInfo != NULL);
836 inHeader = inInfo->mHeader;
840 initPacket(&pkt, inHeader);
841 //av_frame_unref(mFrame); //Don't unref mFrame!!!
842 avcodec_get_frame_defaults(mFrame);
844 int err = avcodec_decode_video2(mCtx, mFrame, &gotPic, &pkt);
846 ALOGE("ffmpeg video decoder failed to decode frame. (%d)", err);
847 //don't send error to OMXCodec, skip!
850 mPendingSettingChangeEvent = isPortSettingChanged();
853 ALOGI("ffmpeg video decoder failed to get frame.");
854 //stop sending empty packets if the decoder is finished
855 if (is_flush && mCtx->codec->capabilities & CODEC_CAP_DELAY) {
861 if (mPendingSettingChangeEvent) {
862 mPendingFrameAsSettingChanged = true;
869 inQueue.erase(inQueue.begin());
870 inInfo->mOwnedByUs = false;
871 notifyEmptyBufferDone(inHeader);
877 int32_t SoftFFmpegVideo::preProcessVideoFrame(AVPicture *picture, void **bufp) {
879 AVPicture picture_tmp;
882 //deinterlace : must be done before any resize
883 if (mDoDeinterlace) {
886 //create temporary picture
887 size = avpicture_get_size(mCtx->pix_fmt, mCtx->width, mCtx->height);
888 buf = (uint8_t *)av_malloc(size);
890 ALOGE("oom for temporary picture");
894 picture2 = &picture_tmp;
895 avpicture_fill(picture2, buf, mCtx->pix_fmt, mCtx->width, mCtx->height);
897 if (avpicture_deinterlace(picture2, picture,
898 mCtx->pix_fmt, mCtx->width, mCtx->height) < 0) {
899 //if error, do not deinterlace
900 ALOGE("Deinterlacing failed");
909 if (picture != picture2)
910 *picture = *picture2;
916 int32_t SoftFFmpegVideo::drainOneOutputBuffer() {
917 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
918 BufferInfo *outInfo = *outQueue.begin();
919 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
922 void *buffer_to_free = NULL;
923 int64_t pts = AV_NOPTS_VALUE;
924 uint8_t *dst = outHeader->pBuffer;
926 //do deinterlace if necessary. for example, your TV is progressive
927 int32_t err = preProcessVideoFrame((AVPicture *)mFrame, &buffer_to_free);
929 ALOGE("preProcessVideoFrame failed");
933 memset(&pict, 0, sizeof(AVPicture));
935 pict.data[1] = dst + mStride * mHeight;
936 pict.data[2] = pict.data[1] + (mStride / 2 * mHeight / 2);
937 pict.linesize[0] = mStride;
938 pict.linesize[1] = mStride / 2;
939 pict.linesize[2] = mStride / 2;
941 int sws_flags = SWS_BICUBIC;
942 mImgConvertCtx = sws_getCachedContext(mImgConvertCtx,
943 mWidth, mHeight, (AVPixelFormat)mFrame->format, mWidth, mHeight,
944 PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
945 if (mImgConvertCtx == NULL) {
946 ALOGE("Cannot initialize the conversion context");
947 av_free(buffer_to_free);
948 return ERR_SWS_FAILED;
950 sws_scale(mImgConvertCtx, mFrame->data, mFrame->linesize,
951 0, mHeight, pict.data, pict.linesize);
953 outHeader->nOffset = 0;
954 outHeader->nFilledLen = (mStride * mHeight * 3) / 2;
955 outHeader->nFlags = 0;
956 if (mFrame->key_frame) {
957 outHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
961 if (decoder_reorder_pts == -1) {
962 pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
963 mFrame, "best_effort_timestamp");
964 } else if (decoder_reorder_pts) {
965 pts = mFrame->pkt_pts;
967 pts = mFrame->pkt_dts;
970 if (pts == AV_NOPTS_VALUE) {
973 outHeader->nTimeStamp = pts; //FIXME pts is right???
976 ALOGV("mFrame pts: %lld", pts);
979 outQueue.erase(outQueue.begin());
980 outInfo->mOwnedByUs = false;
981 notifyFillBufferDone(outHeader);
983 av_free(buffer_to_free);
988 void SoftFFmpegVideo::drainEOSOutputBuffer() {
989 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
990 BufferInfo *outInfo = *outQueue.begin();
991 CHECK(outInfo != NULL);
992 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
994 ALOGD("ffmpeg video decoder fill eos outbuf");
996 outHeader->nTimeStamp = 0;
997 outHeader->nFilledLen = 0;
998 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
1000 outQueue.erase(outQueue.begin());
1001 outInfo->mOwnedByUs = false;
1002 notifyFillBufferDone(outHeader);
1004 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
1007 void SoftFFmpegVideo::drainAllOutputBuffers() {
1008 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
1009 if (!mCodecAlreadyOpened) {
1010 drainEOSOutputBuffer();
1011 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
1015 if(!(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
1016 drainEOSOutputBuffer();
1017 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
1021 while (!outQueue.empty()) {
1022 if (!mPendingFrameAsSettingChanged) {
1023 int32_t err = decodeVideo();
1025 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1026 mSignalledError = true;
1028 } else if (err == ERR_FLUSHED) {
1029 drainEOSOutputBuffer();
1032 CHECK_EQ(err, ERR_OK);
1033 if (mPendingSettingChangeEvent) {
1039 if (drainOneOutputBuffer() != ERR_OK) {
1040 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1041 mSignalledError = true;
1045 if (mPendingFrameAsSettingChanged) {
1046 mPendingFrameAsSettingChanged = false;
1051 void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex) {
1052 BufferInfo *inInfo = NULL;
1053 OMX_BUFFERHEADERTYPE *inHeader = NULL;
1054 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
1055 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
1057 if (mSignalledError || mOutputPortSettingsChange != NONE) {
1061 if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
1065 while (((mEOSStatus != INPUT_DATA_AVAILABLE) || !inQueue.empty())
1066 && !outQueue.empty()) {
1067 if (mPendingSettingChangeEvent) {
1068 //fix crash! We don't notify event until wait for all output buffers
1069 if (outQueue.size() == kNumOutputBuffers) {
1070 CHECK(handlePortSettingChangeEvent() == true);
1071 mPendingSettingChangeEvent = false;
1076 if (mEOSStatus == INPUT_EOS_SEEN) {
1077 drainAllOutputBuffers();
1081 inInfo = *inQueue.begin();
1082 inHeader = inInfo->mHeader;
1084 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
1085 ALOGD("ffmpeg video decoder empty eos inbuf");
1086 inQueue.erase(inQueue.begin());
1087 inInfo->mOwnedByUs = false;
1088 notifyEmptyBufferDone(inHeader);
1089 mEOSStatus = INPUT_EOS_SEEN;
1093 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1094 if (handleExtradata() != ERR_OK) {
1095 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1096 mSignalledError = true;
1101 if (!mCodecAlreadyOpened) {
1102 if (openDecoder() != ERR_OK) {
1103 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1104 mSignalledError = true;
1109 if (!mPendingFrameAsSettingChanged) {
1110 int32_t err = decodeVideo();
1112 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1113 mSignalledError = true;
1115 } else if (err == ERR_NO_FRM) {
1118 CHECK_EQ(err, ERR_OK);
1119 if (mPendingSettingChangeEvent) {
1125 if (drainOneOutputBuffer() != ERR_OK) {
1126 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1127 mSignalledError = true;
1131 if (mPendingFrameAsSettingChanged) {
1132 mPendingFrameAsSettingChanged = false;
1137 void SoftFFmpegVideo::onPortFlushCompleted(OMX_U32 portIndex) {
1138 ALOGV("ffmpeg video decoder flush port(%lu)", portIndex);
1139 if (portIndex == kInputPortIndex && mCtx) {
1141 //Make sure that the next buffer output does not still
1142 //depend on fragments from the last one decoded.
1143 avcodec_flush_buffers(mCtx);
1145 mEOSStatus = INPUT_DATA_AVAILABLE;
1149 void SoftFFmpegVideo::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
1150 if (portIndex != kOutputPortIndex) {
1154 switch (mOutputPortSettingsChange) {
1158 case AWAITING_DISABLED:
1161 mOutputPortSettingsChange = AWAITING_ENABLED;
1167 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
1169 mOutputPortSettingsChange = NONE;
1175 void SoftFFmpegVideo::updatePortDefinitions() {
1176 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
1177 def->format.video.nFrameWidth = mWidth;
1178 def->format.video.nFrameHeight = mHeight;
1179 def->format.video.nStride = def->format.video.nFrameWidth;
1180 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
1182 (def->format.video.nFrameWidth
1183 * def->format.video.nFrameHeight * 3) / 2;
1185 def = &editPortInfo(1)->mDef;
1186 def->format.video.nFrameWidth = mWidth;
1187 def->format.video.nFrameHeight = mHeight;
1188 def->format.video.nStride = def->format.video.nFrameWidth;
1189 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
1192 (def->format.video.nFrameWidth
1193 * def->format.video.nFrameHeight * 3) / 2;
1196 (((def->format.video.nFrameWidth + 15) & -16)
1197 * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
1201 } // namespace android
1203 android::SoftOMXComponent *createSoftOMXComponent(
1204 const char *name, const OMX_CALLBACKTYPE *callbacks,
1205 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
1206 return new android::SoftFFmpegVideo(name, callbacks, appData, component);