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 "utils/ffmpeg_utils.h"
32 static int decoder_reorder_pts = -1;
37 static void InitOMXParams(T *params) {
38 params->nSize = sizeof(T);
39 params->nVersion.s.nVersionMajor = 1;
40 params->nVersion.s.nVersionMinor = 0;
41 params->nVersion.s.nRevision = 0;
42 params->nVersion.s.nStep = 0;
45 void SoftFFmpegVideo::setMode(const char *name) {
46 if (!strcmp(name, "OMX.ffmpeg.mpeg2v.decoder")) {
48 } else if (!strcmp(name, "OMX.ffmpeg.h263.decoder")) {
50 } else if (!strcmp(name, "OMX.ffmpeg.mpeg4.decoder")) {
52 } else if (!strcmp(name, "OMX.ffmpeg.wmv.decoder")) {
54 } else if (!strcmp(name, "OMX.ffmpeg.rv.decoder")) {
56 } else if (!strcmp(name, "OMX.ffmpeg.h264.decoder")) {
58 } else if (!strcmp(name, "OMX.ffmpeg.vpx.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 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_HEVC);
159 def.format.video.eCompressionFormat = OMX_VIDEO_CodingHEVC;
162 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_FFMPEG);
163 def.format.video.eCompressionFormat = OMX_VIDEO_CodingAutoDetect;
166 CHECK(!"Should not be here. Unsupported mime type and compression format");
170 def.format.video.pNativeRender = NULL;
171 def.format.video.nFrameWidth = mWidth;
172 def.format.video.nFrameHeight = mHeight;
173 def.format.video.nStride = def.format.video.nFrameWidth;
174 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
175 def.format.video.nBitrate = 0;
176 def.format.video.xFramerate = 0;
177 def.format.video.bFlagErrorConcealment = OMX_FALSE;
178 def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
179 def.format.video.pNativeWindow = NULL;
182 void SoftFFmpegVideo::initPorts() {
183 OMX_PARAM_PORTDEFINITIONTYPE def;
187 def.eDir = OMX_DirInput;
188 def.nBufferCountMin = kNumInputBuffers;
189 def.nBufferCountActual = def.nBufferCountMin;
190 def.nBufferSize = 1280 * 720; // 256 * 1024?
191 def.bEnabled = OMX_TRUE;
192 def.bPopulated = OMX_FALSE;
193 def.eDomain = OMX_PortDomainVideo;
194 def.bBuffersContiguous = OMX_FALSE;
195 def.nBufferAlignment = 1;
197 initInputFormat(mMode, def);
202 def.eDir = OMX_DirOutput;
203 def.nBufferCountMin = kNumOutputBuffers;
204 def.nBufferCountActual = def.nBufferCountMin;
205 def.bEnabled = OMX_TRUE;
206 def.bPopulated = OMX_FALSE;
207 def.eDomain = OMX_PortDomainVideo;
208 def.bBuffersContiguous = OMX_FALSE;
209 def.nBufferAlignment = 2;
211 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
212 def.format.video.pNativeRender = NULL;
213 def.format.video.nFrameWidth = mWidth;
214 def.format.video.nFrameHeight = mHeight;
215 def.format.video.nStride = def.format.video.nFrameWidth;
216 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
217 def.format.video.nBitrate = 0;
218 def.format.video.xFramerate = 0;
219 def.format.video.bFlagErrorConcealment = OMX_FALSE;
220 def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
221 def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
222 def.format.video.pNativeWindow = NULL;
225 (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
230 void SoftFFmpegVideo::setDefaultCtx(AVCodecContext *avctx, const AVCodec *codec) {
233 avctx->workaround_bugs = 1;
235 if(avctx->lowres > codec->max_lowres){
236 ALOGW("The maximum value for lowres supported by the decoder is %d",
238 avctx->lowres= codec->max_lowres;
240 avctx->idct_algo = 0;
241 avctx->skip_frame = AVDISCARD_DEFAULT;
242 avctx->skip_idct = AVDISCARD_DEFAULT;
243 avctx->skip_loop_filter = AVDISCARD_DEFAULT;
244 avctx->error_concealment = 3;
246 if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
247 if (fast) avctx->flags2 |= CODEC_FLAG2_FAST;
248 if(codec->capabilities & CODEC_CAP_DR1)
249 avctx->flags |= CODEC_FLAG_EMU_EDGE;
252 status_t SoftFFmpegVideo::initDecoder() {
255 status = initFFmpeg();
259 mFFmpegAlreadyInited = true;
261 mCtx = avcodec_alloc_context3(NULL);
264 ALOGE("avcodec_alloc_context failed.");
268 mCtx->codec_type = AVMEDIA_TYPE_VIDEO;
271 mCtx->codec_id = AV_CODEC_ID_MPEG2VIDEO;
274 mCtx->codec_id = AV_CODEC_ID_H263;
276 //mCtx->codec_id = AV_CODEC_ID_H263P;
277 //mCtx->codec_id = AV_CODEC_ID_H263I;
280 mCtx->codec_id = AV_CODEC_ID_MPEG4;
283 mCtx->codec_id = AV_CODEC_ID_WMV2; // default, adjust in "internalSetParameter" fxn
286 mCtx->codec_id = AV_CODEC_ID_RV40; // default, adjust in "internalSetParameter" fxn
289 mCtx->codec_id = AV_CODEC_ID_H264;
292 mCtx->codec_id = AV_CODEC_ID_VP8;
295 mCtx->codec_id = AV_CODEC_ID_VC1;
298 mCtx->codec_id = AV_CODEC_ID_FLV1;
301 mCtx->codec_id = AV_CODEC_ID_MPEG4;
304 mCtx->codec_id = AV_CODEC_ID_HEVC;
307 mCtx->codec_id = AV_CODEC_ID_NONE;
310 CHECK(!"Should not be here. Unsupported codec");
314 mCtx->extradata_size = 0;
315 mCtx->extradata = NULL;
316 mCtx->width = mWidth;
317 mCtx->height = mHeight;
322 void SoftFFmpegVideo::deInitDecoder() {
324 if (avcodec_is_open(mCtx)) {
325 avcodec_flush_buffers(mCtx);
327 if (mCtx->extradata) {
328 av_free(mCtx->extradata);
329 mCtx->extradata = NULL;
330 mCtx->extradata_size = 0;
332 if (mCodecAlreadyOpened) {
342 if (mImgConvertCtx) {
343 sws_freeContext(mImgConvertCtx);
344 mImgConvertCtx = NULL;
348 void SoftFFmpegVideo::getInputFormat(uint32_t mode,
349 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams) {
352 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG2;
355 formatParams->eCompressionFormat = OMX_VIDEO_CodingH263;
358 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG4;
361 formatParams->eCompressionFormat = OMX_VIDEO_CodingWMV;
364 formatParams->eCompressionFormat = OMX_VIDEO_CodingRV;
367 formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
370 formatParams->eCompressionFormat = OMX_VIDEO_CodingVPX;
373 formatParams->eCompressionFormat = OMX_VIDEO_CodingVC1;
376 formatParams->eCompressionFormat = OMX_VIDEO_CodingFLV1;
379 formatParams->eCompressionFormat = OMX_VIDEO_CodingDIVX;
382 formatParams->eCompressionFormat = OMX_VIDEO_CodingHEVC;
385 formatParams->eCompressionFormat = OMX_VIDEO_CodingAutoDetect;
388 CHECK(!"Should not be here. Unsupported compression format.");
391 formatParams->eColorFormat = OMX_COLOR_FormatUnused;
392 formatParams->xFramerate = 0;
395 OMX_ERRORTYPE SoftFFmpegVideo::internalGetParameter(
396 OMX_INDEXTYPE index, OMX_PTR params) {
397 //ALOGV("internalGetParameter index:0x%x", index);
399 case OMX_IndexParamVideoPortFormat:
401 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
402 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
404 if (formatParams->nPortIndex > kOutputPortIndex) {
405 return OMX_ErrorUndefined;
408 if (formatParams->nIndex != 0) {
409 return OMX_ErrorNoMore;
412 if (formatParams->nPortIndex == kInputPortIndex) {
413 getInputFormat(mMode, formatParams);
415 CHECK_EQ(formatParams->nPortIndex, kOutputPortIndex);
417 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
418 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
419 formatParams->xFramerate = 0;
422 return OMX_ErrorNone;
425 case OMX_IndexParamVideoWmv:
427 OMX_VIDEO_PARAM_WMVTYPE *profile =
428 (OMX_VIDEO_PARAM_WMVTYPE *)params;
430 if (profile->nPortIndex != kInputPortIndex) {
431 return OMX_ErrorUndefined;
434 profile->eFormat = OMX_VIDEO_WMVFormatUnused;
436 return OMX_ErrorNone;
439 case OMX_IndexParamVideoRv:
441 OMX_VIDEO_PARAM_RVTYPE *profile =
442 (OMX_VIDEO_PARAM_RVTYPE *)params;
444 if (profile->nPortIndex != kInputPortIndex) {
445 return OMX_ErrorUndefined;
448 profile->eFormat = OMX_VIDEO_RVFormatUnused;
450 return OMX_ErrorNone;
453 case OMX_IndexParamVideoFFmpeg:
455 OMX_VIDEO_PARAM_FFMPEGTYPE *profile =
456 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
458 if (profile->nPortIndex != kInputPortIndex) {
459 return OMX_ErrorUndefined;
462 profile->eCodecId = AV_CODEC_ID_NONE;
464 profile->nHeight = 0;
466 return OMX_ErrorNone;
471 return SimpleSoftOMXComponent::internalGetParameter(index, params);
475 OMX_ERRORTYPE SoftFFmpegVideo::isRoleSupported(
476 const OMX_PARAM_COMPONENTROLETYPE *roleParams) {
477 bool supported = true;
481 if (strncmp((const char *)roleParams->cRole,
482 "video_decoder.mpeg2v", OMX_MAX_STRINGNAME_SIZE - 1))
486 if (strncmp((const char *)roleParams->cRole,
487 "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE - 1))
491 if (strncmp((const char *)roleParams->cRole,
492 "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE - 1))
496 if (strncmp((const char *)roleParams->cRole,
497 "video_decoder.wmv", OMX_MAX_STRINGNAME_SIZE - 1))
501 if (strncmp((const char *)roleParams->cRole,
502 "video_decoder.rv", OMX_MAX_STRINGNAME_SIZE - 1))
506 if (strncmp((const char *)roleParams->cRole,
507 "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE - 1))
511 if (strncmp((const char *)roleParams->cRole,
512 "video_decoder.vpx", OMX_MAX_STRINGNAME_SIZE - 1))
516 if (strncmp((const char *)roleParams->cRole,
517 "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE - 1))
521 if (strncmp((const char *)roleParams->cRole,
522 "video_decoder.flv1", OMX_MAX_STRINGNAME_SIZE - 1))
526 if (strncmp((const char *)roleParams->cRole,
527 "video_decoder.divx", OMX_MAX_STRINGNAME_SIZE - 1))
531 if (strncmp((const char *)roleParams->cRole,
532 "video_decoder.hevc", OMX_MAX_STRINGNAME_SIZE - 1))
536 if (strncmp((const char *)roleParams->cRole,
537 "video_decoder.trial", OMX_MAX_STRINGNAME_SIZE - 1))
541 CHECK(!"Should not be here. Unsupported role.");
546 ALOGE("unsupported role: %s", (const char *)roleParams->cRole);
547 return OMX_ErrorUndefined;
549 return OMX_ErrorNone;
552 OMX_ERRORTYPE SoftFFmpegVideo::internalSetParameter(
553 OMX_INDEXTYPE index, const OMX_PTR params) {
554 //ALOGV("internalSetParameter index:0x%x", index);
556 case OMX_IndexParamStandardComponentRole:
558 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
559 (const OMX_PARAM_COMPONENTROLETYPE *)params;
560 return isRoleSupported(roleParams);
563 case OMX_IndexParamVideoPortFormat:
565 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
566 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
568 if (formatParams->nPortIndex > kOutputPortIndex) {
569 return OMX_ErrorUndefined;
572 if (formatParams->nIndex != 0) {
573 return OMX_ErrorNoMore;
576 return OMX_ErrorNone;
579 case OMX_IndexParamPortDefinition:
581 OMX_PARAM_PORTDEFINITIONTYPE *defParams =
582 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
584 if (defParams->nPortIndex > kOutputPortIndex ||
585 defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
586 return OMX_ErrorUndefined;
589 CHECK_EQ((int)defParams->eDomain, (int)OMX_PortDomainVideo);
591 //only care about input port
592 if (defParams->nPortIndex == kOutputPortIndex) {
593 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &defParams->format.video;
594 mCtx->width = video_def->nFrameWidth;
595 mCtx->height = video_def->nFrameHeight;
596 ALOGV("got OMX_IndexParamPortDefinition, width: %lu, height: %lu",
597 video_def->nFrameWidth, video_def->nFrameHeight);
598 return OMX_ErrorNone;
601 return OMX_ErrorNone;
604 case OMX_IndexParamVideoWmv:
606 OMX_VIDEO_PARAM_WMVTYPE *profile =
607 (OMX_VIDEO_PARAM_WMVTYPE *)params;
609 if (profile->nPortIndex != kInputPortIndex) {
610 return OMX_ErrorUndefined;
613 if (profile->eFormat == OMX_VIDEO_WMVFormat7) {
614 mCtx->codec_id = AV_CODEC_ID_WMV1;
615 } else if (profile->eFormat == OMX_VIDEO_WMVFormat8) {
616 mCtx->codec_id = AV_CODEC_ID_WMV2;
617 } else if (profile->eFormat == OMX_VIDEO_WMVFormat9) {
618 mCtx->codec_id = AV_CODEC_ID_WMV3;
620 ALOGE("unsupported wmv codec: 0x%x", profile->eFormat);
621 return OMX_ErrorUndefined;
624 return OMX_ErrorNone;
627 case OMX_IndexParamVideoRv:
629 OMX_VIDEO_PARAM_RVTYPE *profile =
630 (OMX_VIDEO_PARAM_RVTYPE *)params;
632 if (profile->nPortIndex != kInputPortIndex) {
633 return OMX_ErrorUndefined;
636 if (profile->eFormat == OMX_VIDEO_RVFormatG2) {
637 mCtx->codec_id = AV_CODEC_ID_RV20;
638 } else if (profile->eFormat == OMX_VIDEO_RVFormat8) {
639 mCtx->codec_id = AV_CODEC_ID_RV30;
640 } else if (profile->eFormat == OMX_VIDEO_RVFormat9) {
641 mCtx->codec_id = AV_CODEC_ID_RV40;
643 ALOGE("unsupported rv codec: 0x%x", profile->eFormat);
644 return OMX_ErrorUndefined;
647 return OMX_ErrorNone;
650 case OMX_IndexParamVideoFFmpeg:
652 OMX_VIDEO_PARAM_FFMPEGTYPE *profile =
653 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
655 if (profile->nPortIndex != kInputPortIndex) {
656 return OMX_ErrorUndefined;
659 mCtx->codec_id = (enum AVCodecID)profile->eCodecId;
660 mCtx->width = profile->nWidth;
661 mCtx->height = profile->nHeight;
663 ALOGD("got OMX_IndexParamVideoFFmpeg, "
664 "eCodecId:%ld(%s), width:%lu, height:%lu",
666 avcodec_get_name(mCtx->codec_id),
670 return OMX_ErrorNone;
675 return SimpleSoftOMXComponent::internalSetParameter(index, params);
679 bool SoftFFmpegVideo::handlePortSettingChangeEvent() {
680 if (mCtx->width != mWidth || mCtx->height != mHeight) {
681 ALOGI("ffmpeg video port setting change event(%dx%d)->(%dx%d).",
682 mWidth, mHeight, mCtx->width, mCtx->height);
684 mWidth = mCtx->width;
685 mHeight = mCtx->height;
688 updatePortDefinitions();
689 notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
690 mOutputPortSettingsChange = AWAITING_DISABLED;
697 int32_t SoftFFmpegVideo::handleExtradata() {
698 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
699 BufferInfo *inInfo = *inQueue.begin();
700 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
702 ALOGI("got extradata, ignore: %d, size: %lu",
703 mIgnoreExtradata, inHeader->nFilledLen);
704 hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
706 if (mIgnoreExtradata) {
707 ALOGI("got extradata, size: %lu, but ignore it", inHeader->nFilledLen);
709 if (!mExtradataReady) {
710 //if (mMode == MODE_H264)
711 //it is possible to receive multiple input buffer with OMX_BUFFERFLAG_CODECCONFIG flag.
712 //for example, H264, the first input buffer is SPS, and another is PPS!
713 int orig_extradata_size = mCtx->extradata_size;
714 mCtx->extradata_size += inHeader->nFilledLen;
715 mCtx->extradata = (uint8_t *)realloc(mCtx->extradata,
716 mCtx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
717 if (!mCtx->extradata) {
718 ALOGE("ffmpeg video decoder failed to alloc extradata memory.");
722 memcpy(mCtx->extradata + orig_extradata_size,
723 inHeader->pBuffer + inHeader->nOffset,
724 inHeader->nFilledLen);
725 memset(mCtx->extradata + mCtx->extradata_size, 0,
726 FF_INPUT_BUFFER_PADDING_SIZE);
730 inQueue.erase(inQueue.begin());
731 inInfo->mOwnedByUs = false;
732 notifyEmptyBufferDone(inHeader);
737 int32_t SoftFFmpegVideo::openDecoder() {
738 if (mCodecAlreadyOpened) {
742 if (!mExtradataReady) {
743 ALOGI("extradata is ready, size: %d", mCtx->extradata_size);
744 hexdump(mCtx->extradata, mCtx->extradata_size);
745 mExtradataReady = true;
748 //find decoder again as codec_id may have changed
749 mCtx->codec = avcodec_find_decoder(mCtx->codec_id);
751 ALOGE("ffmpeg video decoder failed to find codec");
752 return ERR_CODEC_NOT_FOUND;
755 setDefaultCtx(mCtx, mCtx->codec);
757 ALOGD("begin to open ffmpeg decoder(%s) now",
758 avcodec_get_name(mCtx->codec_id));
760 int err = avcodec_open2(mCtx, mCtx->codec, NULL);
762 ALOGE("ffmpeg video decoder failed to initialize. (%s)", av_err2str(err));
763 return ERR_DECODER_OPEN_FAILED;
765 mCodecAlreadyOpened = true;
767 ALOGD("open ffmpeg video decoder(%s) success",
768 avcodec_get_name(mCtx->codec_id));
770 mFrame = avcodec_alloc_frame();
772 ALOGE("oom for video frame");
779 void SoftFFmpegVideo::initPacket(AVPacket *pkt,
780 OMX_BUFFERHEADERTYPE *inHeader) {
781 memset(pkt, 0, sizeof(AVPacket));
785 pkt->data = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
786 pkt->size = inHeader->nFilledLen;
787 pkt->pts = inHeader->nTimeStamp;
791 pkt->pts = AV_NOPTS_VALUE;
795 if (pkt->pts != AV_NOPTS_VALUE)
797 ALOGV("pkt size:%d, pts:%lld", pkt->size, pkt->pts);
799 ALOGV("pkt size:%d, pts:N/A", pkt->size);
804 int32_t SoftFFmpegVideo::decodeVideo() {
807 int32_t ret = ERR_OK;
808 bool is_flush = (mEOSStatus != INPUT_DATA_AVAILABLE);
809 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
810 BufferInfo *inInfo = NULL;
811 OMX_BUFFERHEADERTYPE *inHeader = NULL;
814 inInfo = *inQueue.begin();
815 CHECK(inInfo != NULL);
816 inHeader = inInfo->mHeader;
820 initPacket(&pkt, inHeader);
821 //av_frame_unref(mFrame); //Don't unref mFrame!!!
822 avcodec_get_frame_defaults(mFrame);
824 int err = avcodec_decode_video2(mCtx, mFrame, &gotPic, &pkt);
826 ALOGE("ffmpeg video decoder failed to decode frame. (%d)", err);
827 //don't send error to OMXCodec, skip!
831 ALOGI("ffmpeg video decoder failed to get frame.");
832 //stop sending empty packets if the decoder is finished
833 if (is_flush && mCtx->codec->capabilities & CODEC_CAP_DELAY) {
839 if (handlePortSettingChangeEvent()) {
840 mPendingFrameAsSettingChanged = true;
847 inQueue.erase(inQueue.begin());
848 inInfo->mOwnedByUs = false;
849 notifyEmptyBufferDone(inHeader);
855 int32_t SoftFFmpegVideo::preProcessVideoFrame(AVPicture *picture, void **bufp) {
857 AVPicture picture_tmp;
860 //deinterlace : must be done before any resize
861 if (mDoDeinterlace) {
864 //create temporary picture
865 size = avpicture_get_size(mCtx->pix_fmt, mCtx->width, mCtx->height);
866 buf = (uint8_t *)av_malloc(size);
868 ALOGE("oom for temporary picture");
872 picture2 = &picture_tmp;
873 avpicture_fill(picture2, buf, mCtx->pix_fmt, mCtx->width, mCtx->height);
875 if (avpicture_deinterlace(picture2, picture,
876 mCtx->pix_fmt, mCtx->width, mCtx->height) < 0) {
877 //if error, do not deinterlace
878 ALOGE("Deinterlacing failed");
887 if (picture != picture2)
888 *picture = *picture2;
894 int32_t SoftFFmpegVideo::drainOneOutputBuffer() {
895 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
896 BufferInfo *outInfo = *outQueue.begin();
897 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
900 void *buffer_to_free = NULL;
901 int64_t pts = AV_NOPTS_VALUE;
902 uint8_t *dst = outHeader->pBuffer;
904 //do deinterlace if necessary. for example, your TV is progressive
905 int32_t err = preProcessVideoFrame((AVPicture *)mFrame, &buffer_to_free);
907 ALOGE("preProcessVideoFrame failed");
911 memset(&pict, 0, sizeof(AVPicture));
913 pict.data[1] = dst + mStride * mHeight;
914 pict.data[2] = pict.data[1] + (mStride / 2 * mHeight / 2);
915 pict.linesize[0] = mStride;
916 pict.linesize[1] = mStride / 2;
917 pict.linesize[2] = mStride / 2;
919 int sws_flags = SWS_BICUBIC;
920 mImgConvertCtx = sws_getCachedContext(mImgConvertCtx,
921 mWidth, mHeight, mCtx->pix_fmt, mWidth, mHeight,
922 PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
923 if (mImgConvertCtx == NULL) {
924 ALOGE("Cannot initialize the conversion context");
925 av_free(buffer_to_free);
926 return ERR_SWS_FAILED;
928 sws_scale(mImgConvertCtx, mFrame->data, mFrame->linesize,
929 0, mHeight, pict.data, pict.linesize);
931 outHeader->nOffset = 0;
932 outHeader->nFilledLen = (mStride * mHeight * 3) / 2;
933 outHeader->nFlags = 0;
934 if (mFrame->key_frame) {
935 outHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
939 if (decoder_reorder_pts == -1) {
940 pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
941 mFrame, "best_effort_timestamp");
942 } else if (decoder_reorder_pts) {
943 pts = mFrame->pkt_pts;
945 pts = mFrame->pkt_dts;
948 if (pts == AV_NOPTS_VALUE) {
951 outHeader->nTimeStamp = pts;
954 ALOGV("mFrame pts: %lld", pts);
957 outQueue.erase(outQueue.begin());
958 outInfo->mOwnedByUs = false;
959 notifyFillBufferDone(outHeader);
961 av_free(buffer_to_free);
966 void SoftFFmpegVideo::drainEOSOutputBuffer() {
967 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
968 BufferInfo *outInfo = *outQueue.begin();
969 CHECK(outInfo != NULL);
970 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
972 ALOGD("ffmpeg video decoder fill eos outbuf");
974 outHeader->nTimeStamp = 0;
975 outHeader->nFilledLen = 0;
976 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
978 outQueue.erase(outQueue.begin());
979 outInfo->mOwnedByUs = false;
980 notifyFillBufferDone(outHeader);
982 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
985 void SoftFFmpegVideo::drainAllOutputBuffers() {
986 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
987 if (!mCodecAlreadyOpened) {
988 drainEOSOutputBuffer();
989 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
993 if(!(mCtx->codec->capabilities & CODEC_CAP_DELAY)) {
994 drainEOSOutputBuffer();
995 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
999 while (!outQueue.empty()) {
1000 if (!mPendingFrameAsSettingChanged) {
1001 int32_t err = decodeVideo();
1003 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1004 mSignalledError = true;
1006 } else if (err == ERR_FLUSHED) {
1007 drainEOSOutputBuffer();
1010 CHECK_EQ(err, ERR_OK);
1011 if (mPendingFrameAsSettingChanged) {
1017 if (drainOneOutputBuffer() != ERR_OK) {
1018 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1019 mSignalledError = true;
1023 if (mPendingFrameAsSettingChanged) {
1024 mPendingFrameAsSettingChanged = false;
1029 void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex) {
1030 BufferInfo *inInfo = NULL;
1031 OMX_BUFFERHEADERTYPE *inHeader = NULL;
1032 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
1033 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
1035 if (mSignalledError || mOutputPortSettingsChange != NONE) {
1039 if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
1043 while (((mEOSStatus != INPUT_DATA_AVAILABLE) || !inQueue.empty())
1044 && !outQueue.empty()) {
1045 if (mEOSStatus == INPUT_EOS_SEEN) {
1046 drainAllOutputBuffers();
1050 inInfo = *inQueue.begin();
1051 inHeader = inInfo->mHeader;
1053 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
1054 ALOGD("ffmpeg video decoder empty eos inbuf");
1055 inQueue.erase(inQueue.begin());
1056 inInfo->mOwnedByUs = false;
1057 notifyEmptyBufferDone(inHeader);
1058 mEOSStatus = INPUT_EOS_SEEN;
1062 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
1063 if (handleExtradata() != ERR_OK) {
1064 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1065 mSignalledError = true;
1070 if (!mCodecAlreadyOpened) {
1071 if (openDecoder() != ERR_OK) {
1072 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1073 mSignalledError = true;
1078 if (!mPendingFrameAsSettingChanged) {
1079 int32_t err = decodeVideo();
1081 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1082 mSignalledError = true;
1084 } else if (err == ERR_NO_FRM) {
1087 CHECK_EQ(err, ERR_OK);
1088 if (mPendingFrameAsSettingChanged) {
1094 if (drainOneOutputBuffer() != ERR_OK) {
1095 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
1096 mSignalledError = true;
1100 if (mPendingFrameAsSettingChanged) {
1101 mPendingFrameAsSettingChanged = false;
1106 void SoftFFmpegVideo::onPortFlushCompleted(OMX_U32 portIndex) {
1107 ALOGV("ffmpeg video decoder flush port(%lu)", portIndex);
1108 if (portIndex == kInputPortIndex && mCtx) {
1110 //Make sure that the next buffer output does not still
1111 //depend on fragments from the last one decoded.
1112 avcodec_flush_buffers(mCtx);
1114 mEOSStatus = INPUT_DATA_AVAILABLE;
1118 void SoftFFmpegVideo::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
1119 if (portIndex != kOutputPortIndex) {
1123 switch (mOutputPortSettingsChange) {
1127 case AWAITING_DISABLED:
1130 mOutputPortSettingsChange = AWAITING_ENABLED;
1136 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
1138 mOutputPortSettingsChange = NONE;
1144 void SoftFFmpegVideo::updatePortDefinitions() {
1145 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
1146 def->format.video.nFrameWidth = mWidth;
1147 def->format.video.nFrameHeight = mHeight;
1148 def->format.video.nStride = def->format.video.nFrameWidth;
1149 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
1151 def->format.video.nFrameWidth * def->format.video.nFrameHeight;
1153 def = &editPortInfo(1)->mDef;
1154 def->format.video.nFrameWidth = mWidth;
1155 def->format.video.nFrameHeight = mHeight;
1156 def->format.video.nStride = def->format.video.nFrameWidth;
1157 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
1160 (def->format.video.nFrameWidth
1161 * def->format.video.nFrameHeight * 3) / 2;
1164 (((def->format.video.nFrameWidth + 15) & -16)
1165 * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
1169 } // namespace android
1171 android::SoftOMXComponent *createSoftOMXComponent(
1172 const char *name, const OMX_CALLBACKTYPE *callbacks,
1173 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
1174 return new android::SoftFFmpegVideo(name, callbacks, appData, component);