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>
27 #include "ffmpeg_utils/ffmpeg_utils.h"
35 static int decoder_reorder_pts = -1;
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;
48 SoftFFmpegVideo::SoftFFmpegVideo(
50 const OMX_CALLBACKTYPE *callbacks,
52 OMX_COMPONENTTYPE **component)
53 : SimpleSoftOMXComponent(name, callbacks, appData, component),
57 mExtradataReady(false),
58 mIgnoreExtradata(false),
59 mSignalledError(false),
64 mOutputPortSettingsChange(NONE) {
65 if (!strcmp(name, "OMX.ffmpeg.mpeg4.decoder")) {
67 } else if (!strcmp(name, "OMX.ffmpeg.mpeg2v.decoder")) {
69 } else if (!strcmp(name, "OMX.ffmpeg.h263.decoder")) {
71 } else if (!strcmp(name, "OMX.ffmpeg.vc1.decoder")) {
74 CHECK(!strcmp(name, "OMX.ffmpeg.h264.decoder"));
75 //mIgnoreExtradata = true;
78 LOGV("SoftFFmpegVideo component: %s", name);
81 CHECK_EQ(initDecoder(), (status_t)OK);
84 SoftFFmpegVideo::~SoftFFmpegVideo() {
85 LOGV("~SoftFFmpegVideo");
90 void SoftFFmpegVideo::initPorts() {
91 OMX_PARAM_PORTDEFINITIONTYPE def;
95 def.eDir = OMX_DirInput;
96 def.nBufferCountMin = kNumInputBuffers;
97 def.nBufferCountActual = def.nBufferCountMin;
98 def.nBufferSize = 1280 * 720; // 256 * 1024?
99 def.bEnabled = OMX_TRUE;
100 def.bPopulated = OMX_FALSE;
101 def.eDomain = OMX_PortDomainVideo;
102 def.bBuffersContiguous = OMX_FALSE;
103 def.nBufferAlignment = 1;
107 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_AVC);
108 def.format.video.eCompressionFormat = OMX_VIDEO_CodingAVC;
111 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG4);
112 def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG4;
115 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_MPEG2);
116 def.format.video.eCompressionFormat = OMX_VIDEO_CodingMPEG2;
119 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_H263);
120 def.format.video.eCompressionFormat = OMX_VIDEO_CodingH263;
123 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_VC1);
124 def.format.video.eCompressionFormat = OMX_VIDEO_CodingWMV;
127 CHECK(!"Should not be here. Unsupported mime type and compression format");
131 def.format.video.pNativeRender = NULL;
132 def.format.video.nFrameWidth = mWidth;
133 def.format.video.nFrameHeight = mHeight;
134 def.format.video.nStride = def.format.video.nFrameWidth;
135 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
136 def.format.video.nBitrate = 0;
137 def.format.video.xFramerate = 0;
138 def.format.video.bFlagErrorConcealment = OMX_FALSE;
139 def.format.video.eColorFormat = OMX_COLOR_FormatUnused;
140 def.format.video.pNativeWindow = NULL;
145 def.eDir = OMX_DirOutput;
146 def.nBufferCountMin = kNumOutputBuffers;
147 def.nBufferCountActual = def.nBufferCountMin;
148 def.bEnabled = OMX_TRUE;
149 def.bPopulated = OMX_FALSE;
150 def.eDomain = OMX_PortDomainVideo;
151 def.bBuffersContiguous = OMX_FALSE;
152 def.nBufferAlignment = 2;
154 def.format.video.cMIMEType = const_cast<char *>(MEDIA_MIMETYPE_VIDEO_RAW);
155 def.format.video.pNativeRender = NULL;
156 def.format.video.nFrameWidth = mWidth;
157 def.format.video.nFrameHeight = mHeight;
158 def.format.video.nStride = def.format.video.nFrameWidth;
159 def.format.video.nSliceHeight = def.format.video.nFrameHeight;
160 def.format.video.nBitrate = 0;
161 def.format.video.xFramerate = 0;
162 def.format.video.bFlagErrorConcealment = OMX_FALSE;
163 def.format.video.eCompressionFormat = OMX_VIDEO_CodingUnused;
164 def.format.video.eColorFormat = OMX_COLOR_FormatYUV420Planar;
165 def.format.video.pNativeWindow = NULL;
168 (def.format.video.nFrameWidth * def.format.video.nFrameHeight * 3) / 2;
173 static int lockmgr(void **mtx, enum AVLockOp op) {
176 *mtx = (void *)SDL_CreateMutex();
181 return !!SDL_LockMutex((SDL_mutex *)*mtx);
182 case AV_LOCK_RELEASE:
183 return !!SDL_UnlockMutex((SDL_mutex *)*mtx);
184 case AV_LOCK_DESTROY:
185 SDL_DestroyMutex((SDL_mutex *)*mtx);
191 void SoftFFmpegVideo::setAVCtxToDefault(AVCodecContext *avctx, const AVCodec *codec) {
194 avctx->workaround_bugs = 1;
196 if(avctx->lowres > codec->max_lowres){
197 LOGW("The maximum value for lowres supported by the decoder is %d",
199 avctx->lowres= codec->max_lowres;
201 avctx->idct_algo = 0;
202 avctx->skip_frame = AVDISCARD_DEFAULT;
203 avctx->skip_idct = AVDISCARD_DEFAULT;
204 avctx->skip_loop_filter = AVDISCARD_DEFAULT;
205 avctx->error_concealment = 3;
207 if(avctx->lowres) avctx->flags |= CODEC_FLAG_EMU_EDGE;
208 if (fast) avctx->flags2 |= CODEC_FLAG2_FAST;
209 if(codec->capabilities & CODEC_CAP_DR1)
210 avctx->flags |= CODEC_FLAG_EMU_EDGE;
213 status_t SoftFFmpegVideo::initDecoder() {
216 status = initFFmpeg();
220 mCtx = avcodec_alloc_context3(NULL);
223 LOGE("avcodec_alloc_context failed.");
227 mCtx->codec_type = AVMEDIA_TYPE_VIDEO;
230 mCtx->codec_id = CODEC_ID_H264;
233 mCtx->codec_id = CODEC_ID_MPEG4;
236 mCtx->codec_id = CODEC_ID_MPEG2VIDEO;
239 mCtx->codec_id = CODEC_ID_H263;
241 //mCtx->codec_id = CODEC_ID_H263P;
242 //mCtx->codec_id = CODEC_ID_H263I;
245 mCtx->codec_id = CODEC_ID_VC1;
248 CHECK(!"Should not be here. Unsupported codec");
252 mCtx->codec = avcodec_find_decoder(mCtx->codec_id);
255 LOGE("find codec failed");
259 setAVCtxToDefault(mCtx, mCtx->codec);
261 mCtx->extradata_size = 0;
262 mCtx->extradata = NULL;
263 mCtx->width = mWidth;
264 mCtx->height = mHeight;
269 void SoftFFmpegVideo::deInitDecoder() {
271 avcodec_flush_buffers(mCtx);
272 if (!mCtx->extradata) {
273 av_free(mCtx->extradata);
274 mCtx->extradata = NULL;
275 mCtx->extradata_size = 0;
282 if (mImgConvertCtx) {
283 sws_freeContext(mImgConvertCtx);
284 mImgConvertCtx = NULL;
288 void SoftFFmpegVideo::preProcessVideoFrame(AVPicture *picture, void **bufp)
291 AVPicture picture_tmp;
294 /* deinterlace : must be done before any resize */
295 if (mDoDeinterlace) {
298 /* create temporary picture */
299 size = avpicture_get_size(mCtx->pix_fmt, mCtx->width, mCtx->height);
300 buf = (uint8_t *)av_malloc(size);
304 picture2 = &picture_tmp;
305 avpicture_fill(picture2, buf, mCtx->pix_fmt, mCtx->width, mCtx->height);
307 if (avpicture_deinterlace(picture2, picture,
308 mCtx->pix_fmt, mCtx->width, mCtx->height) < 0) {
309 /* if error, do not deinterlace */
310 LOGE("Deinterlacing failed");
319 if (picture != picture2)
320 *picture = *picture2;
324 OMX_ERRORTYPE SoftFFmpegVideo::internalGetParameter(
325 OMX_INDEXTYPE index, OMX_PTR params) {
327 case OMX_IndexParamVideoPortFormat:
329 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
330 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
332 if (formatParams->nPortIndex > 1) {
333 return OMX_ErrorUndefined;
336 if (formatParams->nIndex != 0) {
337 return OMX_ErrorNoMore;
340 if (formatParams->nPortIndex == 0) {
343 formatParams->eCompressionFormat = OMX_VIDEO_CodingAVC;
346 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG4;
349 formatParams->eCompressionFormat = OMX_VIDEO_CodingMPEG2;
352 formatParams->eCompressionFormat = OMX_VIDEO_CodingH263;
355 formatParams->eCompressionFormat = OMX_VIDEO_CodingWMV;
358 CHECK(!"Should not be here. Unsupported compression format.");
361 formatParams->eColorFormat = OMX_COLOR_FormatUnused;
362 formatParams->xFramerate = 0;
364 CHECK_EQ(formatParams->nPortIndex, 1u);
366 formatParams->eCompressionFormat = OMX_VIDEO_CodingUnused;
367 formatParams->eColorFormat = OMX_COLOR_FormatYUV420Planar;
368 formatParams->xFramerate = 0;
371 return OMX_ErrorNone;
375 return SimpleSoftOMXComponent::internalGetParameter(index, params);
379 OMX_ERRORTYPE SoftFFmpegVideo::internalSetParameter(
380 OMX_INDEXTYPE index, const OMX_PTR params) {
382 case OMX_IndexParamStandardComponentRole:
384 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
385 (const OMX_PARAM_COMPONENTROLETYPE *)params;
387 bool supported = true;
390 if (strncmp((const char *)roleParams->cRole,
391 "video_decoder.avc", OMX_MAX_STRINGNAME_SIZE - 1))
395 if (strncmp((const char *)roleParams->cRole,
396 "video_decoder.mpeg4", OMX_MAX_STRINGNAME_SIZE - 1))
400 if (strncmp((const char *)roleParams->cRole,
401 "video_decoder.mpeg2v", OMX_MAX_STRINGNAME_SIZE - 1))
405 if (strncmp((const char *)roleParams->cRole,
406 "video_decoder.h263", OMX_MAX_STRINGNAME_SIZE - 1))
410 if (strncmp((const char *)roleParams->cRole,
411 "video_decoder.vc1", OMX_MAX_STRINGNAME_SIZE - 1))
415 CHECK(!"Should not be here. Unsupported role.");
419 LOGE("unsupported role: %s", (const char *)roleParams->cRole);
420 return OMX_ErrorUndefined;
423 return OMX_ErrorNone;
426 case OMX_IndexParamVideoPortFormat:
428 OMX_VIDEO_PARAM_PORTFORMATTYPE *formatParams =
429 (OMX_VIDEO_PARAM_PORTFORMATTYPE *)params;
431 if (formatParams->nPortIndex > 1) {
432 return OMX_ErrorUndefined;
435 if (formatParams->nIndex != 0) {
436 return OMX_ErrorNoMore;
439 return OMX_ErrorNone;
442 case OMX_IndexParamPortDefinition:
444 OMX_PARAM_PORTDEFINITIONTYPE *defParams =
445 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
447 if (defParams->nPortIndex > 1 ||
448 defParams->nSize != sizeof(OMX_PARAM_PORTDEFINITIONTYPE)) {
449 return OMX_ErrorUndefined;
452 CHECK_EQ((int)defParams->eDomain, (int)OMX_PortDomainVideo);
454 // only care about input port
455 if (defParams->nPortIndex == kPortIndexOutput) {
456 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &defParams->format.video;
457 mWidth = video_def->nFrameWidth;
458 mHeight = video_def->nFrameHeight;
459 LOGV("got OMX_IndexParamPortDefinition, mWidth: %d, mHeight: %d",
461 return OMX_ErrorNone;
466 return SimpleSoftOMXComponent::internalSetParameter(index, params);
470 void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex) {
473 if (mSignalledError || mOutputPortSettingsChange != NONE) {
477 List<BufferInfo *> &inQueue = getPortQueue(0);
478 List<BufferInfo *> &outQueue = getPortQueue(1);
480 while (!inQueue.empty() && !outQueue.empty()) {
481 BufferInfo *inInfo = *inQueue.begin();
482 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
484 BufferInfo *outInfo = *outQueue.begin();
485 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
487 if (mCtx->width != mWidth || mCtx->height != mHeight) {
488 mCtx->width = mWidth;
489 mCtx->height = mHeight;
492 updatePortDefinitions();
494 notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
495 mOutputPortSettingsChange = AWAITING_DISABLED;
499 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
500 inQueue.erase(inQueue.begin());
501 inInfo->mOwnedByUs = false;
502 notifyEmptyBufferDone(inHeader);
504 outHeader->nFilledLen = 0;
505 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
507 outQueue.erase(outQueue.begin());
508 outInfo->mOwnedByUs = false;
509 notifyFillBufferDone(outHeader);
513 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
514 LOGI("got extradata, ignore: %d, size: %lu", mIgnoreExtradata, inHeader->nFilledLen);
515 hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
516 if (!mExtradataReady && !mIgnoreExtradata) {
517 //if (mMode == MODE_H264)
518 // it is possible to receive multiple input buffer with OMX_BUFFERFLAG_CODECCONFIG flag.
519 // for example, H264, the first input buffer is SPS, and another is PPS!
520 int orig_extradata_size = mCtx->extradata_size;
521 mCtx->extradata_size += inHeader->nFilledLen;
522 mCtx->extradata = (uint8_t *)realloc(mCtx->extradata,
523 mCtx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
524 if (!mCtx->extradata) {
525 LOGE("ffmpeg video decoder failed to alloc extradata memory.");
526 notify(OMX_EventError, OMX_ErrorInsufficientResources, 0, NULL);
527 mSignalledError = true;
531 memcpy(mCtx->extradata + orig_extradata_size,
532 inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
533 memset(mCtx->extradata + mCtx->extradata_size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
535 inInfo->mOwnedByUs = false;
536 inQueue.erase(inQueue.begin());
538 notifyEmptyBufferDone(inHeader);
544 if (mIgnoreExtradata) {
545 LOGI("got extradata, size: %lu, but ignore it", inHeader->nFilledLen);
546 inInfo->mOwnedByUs = false;
547 inQueue.erase(inQueue.begin());
549 notifyEmptyBufferDone(inHeader);
557 av_init_packet(&pkt);
558 pkt.data = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
559 pkt.size = inHeader->nFilledLen;
560 pkt.pts = inHeader->nTimeStamp;
562 LOGV("pkt size: %d, pts: %lld", pkt.size, pkt.pts);
564 if (!mExtradataReady) {
565 LOGI("extradata is ready");
566 hexdump(mCtx->extradata, mCtx->extradata_size);
567 LOGI("open ffmpeg decoder now");
568 mExtradataReady = true;
570 err = avcodec_open2(mCtx, mCtx->codec, NULL);
572 LOGE("ffmpeg video decoder failed to initialize. (%d)", err);
573 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
574 mSignalledError = true;
580 AVFrame *frame = avcodec_alloc_frame();
581 err = avcodec_decode_video2(mCtx, frame, &gotPic, &pkt);
583 LOGE("ffmpeg video decoder failed to decode frame. (%d)", err);
584 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
585 mSignalledError = true;
592 void *buffer_to_free = NULL;
593 int64_t pts = AV_NOPTS_VALUE;
594 uint8_t *dst = outHeader->pBuffer;
596 // do deinterlace if necessary. for example, your TV is progressive
597 preProcessVideoFrame((AVPicture *)frame, &buffer_to_free);
599 memset(&pict, 0, sizeof(AVPicture));
601 pict.data[1] = dst + mStride * mHeight;
602 pict.data[2] = pict.data[1] + (mStride / 2 * mHeight / 2);
603 pict.linesize[0] = mStride;
604 pict.linesize[1] = mStride / 2;
605 pict.linesize[2] = mStride / 2;
607 int sws_flags = SWS_BICUBIC;
608 mImgConvertCtx = sws_getCachedContext(mImgConvertCtx,
609 mWidth, mHeight, mCtx->pix_fmt, mWidth, mHeight,
610 PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
611 if (mImgConvertCtx == NULL) {
612 LOGE("Cannot initialize the conversion context");
613 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
614 mSignalledError = true;
618 sws_scale(mImgConvertCtx, frame->data, frame->linesize,
619 0, mHeight, pict.data, pict.linesize);
621 outHeader->nOffset = 0;
622 outHeader->nFilledLen = (mStride * mHeight * 3) / 2;
623 outHeader->nFlags = 0;
624 if (frame->key_frame)
625 outHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
627 // process timestamps
628 if (decoder_reorder_pts == -1) {
629 pts = *(int64_t*)av_opt_ptr(avcodec_get_frame_class(),
630 frame, "best_effort_timestamp");
631 } else if (decoder_reorder_pts) {
632 pts = frame->pkt_pts;
634 pts = frame->pkt_dts;
637 if (pts == AV_NOPTS_VALUE) {
640 outHeader->nTimeStamp = pts;
643 LOGV("frame pts: %lld", pts);
646 outInfo->mOwnedByUs = false;
647 outQueue.erase(outQueue.begin());
649 notifyFillBufferDone(outHeader);
652 av_free(buffer_to_free);
655 inInfo->mOwnedByUs = false;
656 inQueue.erase(inQueue.begin());
658 notifyEmptyBufferDone(inHeader);
664 void SoftFFmpegVideo::onPortFlushCompleted(OMX_U32 portIndex) {
665 if (portIndex == 0 && mCtx) {
666 // Make sure that the next buffer output does not still
667 // depend on fragments from the last one decoded.
668 avcodec_flush_buffers(mCtx);
672 void SoftFFmpegVideo::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
673 if (portIndex != 1) {
677 switch (mOutputPortSettingsChange) {
681 case AWAITING_DISABLED:
684 mOutputPortSettingsChange = AWAITING_ENABLED;
690 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
692 mOutputPortSettingsChange = NONE;
698 void SoftFFmpegVideo::updatePortDefinitions() {
699 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(0)->mDef;
700 def->format.video.nFrameWidth = mWidth;
701 def->format.video.nFrameHeight = mHeight;
702 def->format.video.nStride = def->format.video.nFrameWidth;
703 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
705 def->format.video.nFrameWidth * def->format.video.nFrameHeight;
707 def = &editPortInfo(1)->mDef;
708 def->format.video.nFrameWidth = mWidth;
709 def->format.video.nFrameHeight = mHeight;
710 def->format.video.nStride = def->format.video.nFrameWidth;
711 def->format.video.nSliceHeight = def->format.video.nFrameHeight;
714 (def->format.video.nFrameWidth
715 * def->format.video.nFrameHeight * 3) / 2;
718 (((def->format.video.nFrameWidth + 15) & -16)
719 * ((def->format.video.nFrameHeight + 15) & -16) * 3) / 2;
723 } // namespace android
725 android::SoftOMXComponent *createSoftOMXComponent(
726 const char *name, const OMX_CALLBACKTYPE *callbacks,
727 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
728 return new android::SoftFFmpegVideo(name, callbacks, appData, component);