2 * Copyright 2012 Michael Chen <omxcodec@gmail.com>
3 * Copyright 2015 The CyanogenMod Project
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #define LOG_TAG "SoftFFmpegVideo"
19 #include <utils/Log.h>
20 #include <cutils/properties.h>
22 #include "SoftFFmpegVideo.h"
23 #include "FFmpegComponents.h"
24 #include "ffmpeg_hwaccel.h"
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/foundation/AUtils.h>
28 #include <media/stagefright/foundation/hexdump.h>
29 #include <media/stagefright/MediaDefs.h>
33 #define DEBUG_EXTRADATA 0
35 static int decoder_reorder_pts = -1;
39 static const CodecProfileLevel kM4VProfileLevels[] = {
40 { OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4Level5 },
41 { OMX_VIDEO_MPEG4ProfileAdvancedSimple, OMX_VIDEO_MPEG4Level5 },
44 static const CodecProfileLevel kAVCProfileLevels[] = {
45 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1 },
46 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel1b },
47 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel11 },
48 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel12 },
49 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel13 },
50 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel2 },
51 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel21 },
52 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel22 },
53 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel3 },
54 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel31 },
55 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel32 },
56 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel4 },
57 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel41 },
58 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel42 },
59 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel5 },
60 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel51 },
61 { OMX_VIDEO_AVCProfileBaseline, OMX_VIDEO_AVCLevel52 },
63 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1 },
64 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel1b },
65 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel11 },
66 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel12 },
67 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel13 },
68 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel2 },
69 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel21 },
70 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel22 },
71 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel3 },
72 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel31 },
73 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel32 },
74 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel4 },
75 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel41 },
76 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel42 },
77 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel5 },
78 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel51 },
79 { OMX_VIDEO_AVCProfileMain, OMX_VIDEO_AVCLevel52 },
81 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1 },
82 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel1b },
83 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel11 },
84 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel12 },
85 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel13 },
86 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel2 },
87 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel21 },
88 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel22 },
89 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel3 },
90 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel31 },
91 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel32 },
92 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel4 },
93 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel41 },
94 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel42 },
95 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel5 },
96 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel51 },
97 { OMX_VIDEO_AVCProfileHigh, OMX_VIDEO_AVCLevel52 },
100 SoftFFmpegVideo::SoftFFmpegVideo(
102 const char *componentRole,
103 OMX_VIDEO_CODINGTYPE codingType,
104 const CodecProfileLevel *profileLevels,
105 size_t numProfileLevels,
106 const OMX_CALLBACKTYPE *callbacks,
108 OMX_COMPONENTTYPE **component,
109 enum AVCodecID codecID)
110 : SoftVideoDecoderOMXComponent(name, componentRole, codingType,
111 profileLevels, numProfileLevels, 352, 288, callbacks, appData, component),
112 mCodingType(codingType),
113 mFFmpegAlreadyInited(false),
114 mCodecAlreadyOpened(false),
116 mImgConvertCtx(NULL),
118 mEOSStatus(INPUT_DATA_AVAILABLE),
119 mExtradataReady(false),
120 mIgnoreExtradata(false),
122 mSignalledError(false) {
124 ALOGD("SoftFFmpegVideo component: %s codingType=%d appData: %p", name, codingType, appData);
128 1024 * 1024 /* inputBufferSize */,
132 CHECK_EQ(initDecoder(codecID), (status_t)OK);
135 SoftFFmpegVideo::~SoftFFmpegVideo() {
136 ALOGV("~SoftFFmpegVideo");
138 if (mFFmpegAlreadyInited) {
143 void SoftFFmpegVideo::setDefaultCtx(AVCodecContext *avctx, const AVCodec *codec) {
146 avctx->workaround_bugs = 1;
147 avctx->idct_algo = 0;
148 avctx->skip_frame = AVDISCARD_DEFAULT;
149 avctx->skip_idct = AVDISCARD_DEFAULT;
150 avctx->skip_loop_filter = AVDISCARD_DEFAULT;
151 avctx->error_concealment = 3;
153 if (fast) avctx->flags2 |= AV_CODEC_FLAG2_FAST;
154 #ifdef CODEC_FLAG_EMU_EDGE
155 if (codec->capabilities & AV_CODEC_CAP_DR1)
156 avctx->flags |= CODEC_FLAG_EMU_EDGE;
160 status_t SoftFFmpegVideo::initDecoder(enum AVCodecID codecID) {
163 status = initFFmpeg();
167 mFFmpegAlreadyInited = true;
169 mCtx = avcodec_alloc_context3(NULL);
172 ALOGE("avcodec_alloc_context failed.");
176 mCtx->codec_type = AVMEDIA_TYPE_VIDEO;
177 mCtx->codec_id = codecID;
178 mCtx->extradata_size = 0;
179 mCtx->extradata = NULL;
180 mCtx->width = mWidth;
181 mCtx->height = mHeight;
182 ffmpeg_hwaccel_init(mCtx);
183 ALOGD("%p initDecoder: %p", this, mCtx);
187 void SoftFFmpegVideo::deInitDecoder() {
188 ALOGD("%p deInitDecoder: %p", this, mCtx);
190 if (avcodec_is_open(mCtx)) {
191 avcodec_flush_buffers(mCtx);
193 if (mCtx->extradata) {
194 av_free(mCtx->extradata);
195 mCtx->extradata = NULL;
196 mCtx->extradata_size = 0;
198 if (mCodecAlreadyOpened) {
200 mCodecAlreadyOpened = false;
202 ffmpeg_hwaccel_deinit(mCtx);
206 av_frame_free(&mFrame);
209 if (mImgConvertCtx) {
210 sws_freeContext(mImgConvertCtx);
211 mImgConvertCtx = NULL;
215 OMX_ERRORTYPE SoftFFmpegVideo::internalGetParameter(
216 OMX_INDEXTYPE index, OMX_PTR params) {
217 //ALOGV("internalGetParameter index:0x%x", index);
219 case OMX_IndexParamVideoWmv:
221 OMX_VIDEO_PARAM_WMVTYPE *profile =
222 (OMX_VIDEO_PARAM_WMVTYPE *)params;
224 if (profile->nPortIndex != kInputPortIndex) {
225 return OMX_ErrorUndefined;
228 profile->eFormat = OMX_VIDEO_WMVFormatUnused;
230 return OMX_ErrorNone;
233 case OMX_IndexParamVideoRv:
235 OMX_VIDEO_PARAM_RVTYPE *profile =
236 (OMX_VIDEO_PARAM_RVTYPE *)params;
238 if (profile->nPortIndex != kInputPortIndex) {
239 return OMX_ErrorUndefined;
242 profile->eFormat = OMX_VIDEO_RVFormatUnused;
244 return OMX_ErrorNone;
249 if (index != (OMX_INDEXTYPE)OMX_IndexParamVideoFFmpeg) {
250 return SoftVideoDecoderOMXComponent::internalGetParameter(index, params);
253 OMX_VIDEO_PARAM_FFMPEGTYPE *profile =
254 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
256 if (profile->nPortIndex != kInputPortIndex) {
257 return OMX_ErrorUndefined;
260 profile->eCodecId = AV_CODEC_ID_NONE;
262 profile->nHeight = 0;
264 return OMX_ErrorNone;
269 OMX_ERRORTYPE SoftFFmpegVideo::isRoleSupported(
270 const OMX_PARAM_COMPONENTROLETYPE *roleParams) {
272 i < sizeof(kVideoComponents) / sizeof(kVideoComponents[0]);
274 if (strncmp((const char *)roleParams->cRole,
275 kVideoComponents[i].mRole, OMX_MAX_STRINGNAME_SIZE - 1) == 0) {
276 return OMX_ErrorNone;
279 ALOGE("unsupported role: %s", (const char *)roleParams->cRole);
280 return OMX_ErrorUndefined;
283 OMX_ERRORTYPE SoftFFmpegVideo::internalSetParameter(
284 OMX_INDEXTYPE index, const OMX_PTR params) {
285 //ALOGV("internalSetParameter index:0x%x", index);
287 case OMX_IndexParamStandardComponentRole:
289 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
290 (const OMX_PARAM_COMPONENTROLETYPE *)params;
291 return isRoleSupported(roleParams);
294 case OMX_IndexParamPortDefinition:
296 OMX_PARAM_PORTDEFINITIONTYPE *newParams =
297 (OMX_PARAM_PORTDEFINITIONTYPE *)params;
298 OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &newParams->format.video;
299 OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(newParams->nPortIndex)->mDef;
301 uint32_t oldWidth = def->format.video.nFrameWidth;
302 uint32_t oldHeight = def->format.video.nFrameHeight;
303 uint32_t newWidth = video_def->nFrameWidth;
304 uint32_t newHeight = video_def->nFrameHeight;
305 if (newWidth != oldWidth || newHeight != oldHeight) {
306 bool outputPort = (newParams->nPortIndex == kOutputPortIndex);
308 ALOGI("OMX_IndexParamPortDefinition (output) width=%d height=%d", newWidth, newHeight);
310 // only update (essentially crop) if size changes
314 updatePortDefinitions(true, true);
315 // reset buffer size based on frame size
316 newParams->nBufferSize = def->nBufferSize;
318 // For input port, we only set nFrameWidth and nFrameHeight. Buffer size
319 // is updated when configuring the output port using the max-frame-size,
320 // though client can still request a larger size.
321 ALOGI("OMX_IndexParamPortDefinition (input) width=%d height=%d", newWidth, newHeight);
322 def->format.video.nFrameWidth = newWidth;
323 def->format.video.nFrameHeight = newHeight;
324 mCtx->width = newWidth;
325 mCtx->height = newHeight;
328 return SoftVideoDecoderOMXComponent::internalSetParameter(index, params);
331 case OMX_IndexParamVideoWmv:
333 OMX_VIDEO_PARAM_WMVTYPE *profile =
334 (OMX_VIDEO_PARAM_WMVTYPE *)params;
336 if (profile->nPortIndex != kInputPortIndex) {
337 return OMX_ErrorUndefined;
340 if (profile->eFormat == OMX_VIDEO_WMVFormat7) {
341 mCtx->codec_id = AV_CODEC_ID_WMV1;
342 } else if (profile->eFormat == OMX_VIDEO_WMVFormat8) {
343 mCtx->codec_id = AV_CODEC_ID_WMV2;
344 } else if (profile->eFormat == OMX_VIDEO_WMVFormat9) {
345 mCtx->codec_id = AV_CODEC_ID_WMV3;
347 mCtx->codec_id = AV_CODEC_ID_VC1;
350 return OMX_ErrorNone;
353 case OMX_IndexParamVideoRv:
355 OMX_VIDEO_PARAM_RVTYPE *profile =
356 (OMX_VIDEO_PARAM_RVTYPE *)params;
358 if (profile->nPortIndex != kInputPortIndex) {
359 return OMX_ErrorUndefined;
362 if (profile->eFormat == OMX_VIDEO_RVFormatG2) {
363 mCtx->codec_id = AV_CODEC_ID_RV20;
364 } else if (profile->eFormat == OMX_VIDEO_RVFormat8) {
365 mCtx->codec_id = AV_CODEC_ID_RV30;
366 } else if (profile->eFormat == OMX_VIDEO_RVFormat9) {
367 mCtx->codec_id = AV_CODEC_ID_RV40;
369 ALOGE("unsupported rv codec: 0x%x", profile->eFormat);
370 return OMX_ErrorUndefined;
373 return OMX_ErrorNone;
378 if (index != (OMX_INDEXTYPE)OMX_IndexParamVideoFFmpeg) {
379 return SoftVideoDecoderOMXComponent::internalSetParameter(index, params);
382 OMX_VIDEO_PARAM_FFMPEGTYPE *profile =
383 (OMX_VIDEO_PARAM_FFMPEGTYPE *)params;
385 if (profile->nPortIndex != kInputPortIndex) {
386 return OMX_ErrorUndefined;
389 mCtx->codec_id = (enum AVCodecID)profile->eCodecId;
390 mCtx->width = profile->nWidth;
391 mCtx->height = profile->nHeight;
393 ALOGD("got OMX_IndexParamVideoFFmpeg, "
394 "eCodecId:%d(%s), width:%u, height:%u",
396 avcodec_get_name(mCtx->codec_id),
400 return OMX_ErrorNone;
405 int32_t SoftFFmpegVideo::handleExtradata() {
406 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
407 BufferInfo *inInfo = *inQueue.begin();
408 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
411 ALOGI("got extradata, ignore: %d, size: %u",
412 mIgnoreExtradata, inHeader->nFilledLen);
413 hexdump(inHeader->pBuffer + inHeader->nOffset, inHeader->nFilledLen);
416 if (mIgnoreExtradata) {
417 ALOGI("got extradata, size: %u, but ignore it", inHeader->nFilledLen);
419 if (!mExtradataReady) {
420 //if (mMode == MODE_H264)
421 //it is possible to receive multiple input buffer with OMX_BUFFERFLAG_CODECCONFIG flag.
422 //for example, H264, the first input buffer is SPS, and another is PPS!
423 int orig_extradata_size = mCtx->extradata_size;
424 mCtx->extradata_size += inHeader->nFilledLen;
425 mCtx->extradata = (uint8_t *)realloc(mCtx->extradata,
426 mCtx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
427 if (!mCtx->extradata) {
428 ALOGE("ffmpeg video decoder failed to alloc extradata memory.");
432 memcpy(mCtx->extradata + orig_extradata_size,
433 inHeader->pBuffer + inHeader->nOffset,
434 inHeader->nFilledLen);
435 memset(mCtx->extradata + mCtx->extradata_size, 0,
436 AV_INPUT_BUFFER_PADDING_SIZE);
440 inQueue.erase(inQueue.begin());
441 inInfo->mOwnedByUs = false;
442 notifyEmptyBufferDone(inHeader);
447 int32_t SoftFFmpegVideo::openDecoder() {
448 if (mCodecAlreadyOpened) {
452 if (!mExtradataReady) {
454 ALOGI("extradata is ready, size: %d", mCtx->extradata_size);
455 hexdump(mCtx->extradata, mCtx->extradata_size);
457 mExtradataReady = true;
460 //find decoder again as codec_id may have changed
461 mCtx->codec = avcodec_find_decoder(mCtx->codec_id);
463 ALOGE("ffmpeg video decoder failed to find codec");
464 return ERR_CODEC_NOT_FOUND;
467 setDefaultCtx(mCtx, mCtx->codec);
469 ALOGD("begin to open ffmpeg decoder(%s) now",
470 avcodec_get_name(mCtx->codec_id));
472 int err = avcodec_open2(mCtx, mCtx->codec, NULL);
474 ALOGE("ffmpeg video decoder failed to initialize. (%s)", av_err2str(err));
475 return ERR_DECODER_OPEN_FAILED;
477 mCodecAlreadyOpened = true;
479 ALOGD("open ffmpeg video decoder(%s) success",
480 avcodec_get_name(mCtx->codec_id));
482 mFrame = av_frame_alloc();
484 ALOGE("oom for video frame");
491 void SoftFFmpegVideo::initPacket(AVPacket *pkt,
492 OMX_BUFFERHEADERTYPE *inHeader) {
493 memset(pkt, 0, sizeof(AVPacket));
497 pkt->data = (uint8_t *)inHeader->pBuffer + inHeader->nOffset;
498 pkt->size = inHeader->nFilledLen;
499 pkt->pts = inHeader->nTimeStamp;
500 pkt->dts = inHeader->nTimeStamp;
504 pkt->pts = AV_NOPTS_VALUE;
508 if (pkt->pts != AV_NOPTS_VALUE)
510 ALOGV("pkt size:%d, pts:%lld", pkt->size, pkt->pts);
512 ALOGV("pkt size:%d, pts:N/A", pkt->size);
517 int32_t SoftFFmpegVideo::decodeVideo() {
518 int len = 0, err = 0;
520 int32_t ret = ERR_OK;
521 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
522 BufferInfo *inInfo = NULL;
523 OMX_BUFFERHEADERTYPE *inHeader = NULL;
525 if (!inQueue.empty()) {
526 inInfo = *inQueue.begin();
527 if (inInfo != NULL) {
528 inHeader = inInfo->mHeader;
532 if (mEOSStatus == INPUT_EOS_SEEN && (!inHeader || inHeader->nFilledLen == 0)
533 && !(mCtx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
538 initPacket(&pkt, inHeader);
540 err = avcodec_decode_video2(mCtx, mFrame, &gotPic, &pkt);
541 av_packet_unref(&pkt);
544 ALOGE("ffmpeg video decoder failed to decode frame. (%d)", err);
545 //don't send error to OMXCodec, skip!
549 //stop sending empty packets if the decoder is finished
550 if ((mEOSStatus != INPUT_DATA_AVAILABLE && (mCtx->codec->capabilities & AV_CODEC_CAP_DELAY) &&
551 !inHeader) || inHeader->nFilledLen == 0) {
552 ALOGD("ffmpeg video decoder flushed.");
555 ALOGV("ffmpeg video decoder failed to get frame.");
559 err = ffmpeg_hwaccel_get_frame(mCtx, mFrame);
561 ALOGE("ffmpeg HW video decoder failed to decode frame. (%d)", err);
562 //don't send error to OMXCodec, skip!
570 if (!inQueue.empty()) {
571 inQueue.erase(inQueue.begin());
573 inInfo->mOwnedByUs = false;
574 notifyEmptyBufferDone(inHeader);
581 int32_t SoftFFmpegVideo::drainOneOutputBuffer() {
582 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
583 BufferInfo *outInfo = *outQueue.begin();
584 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
589 int64_t pts = AV_NOPTS_VALUE;
590 uint8_t *dst = outHeader->pBuffer;
592 uint32_t width = outputBufferWidth();
593 uint32_t height = outputBufferHeight();
596 data[1] = dst + width * height;
597 data[2] = data[1] + (width / 2 * height / 2);
599 linesize[1] = width / 2;
600 linesize[2] = width / 2;
602 ALOGV("drainOneOutputBuffer: frame_width=%d frame_height=%d width=%d height=%d ctx_width=%d ctx_height=%d", mFrame->width, mFrame->height, width, height, mCtx->width, mCtx->height);
604 int sws_flags = SWS_BICUBIC;
605 mImgConvertCtx = sws_getCachedContext(mImgConvertCtx,
606 mFrame->width, mFrame->height, (AVPixelFormat)mFrame->format, width, height,
607 AV_PIX_FMT_YUV420P, sws_flags, NULL, NULL, NULL);
608 if (mImgConvertCtx == NULL) {
609 ALOGE("Cannot initialize the conversion context");
610 return ERR_SWS_FAILED;
612 sws_scale(mImgConvertCtx, mFrame->data, mFrame->linesize,
613 0, mFrame->height, data, linesize);
615 outHeader->nOffset = 0;
616 outHeader->nFilledLen = (outputBufferWidth() * outputBufferHeight() * 3) / 2;
617 outHeader->nFlags = 0;
618 if (mFrame->key_frame) {
619 outHeader->nFlags |= OMX_BUFFERFLAG_SYNCFRAME;
623 #ifndef LIBAV_CONFIG_H
624 if (decoder_reorder_pts == -1) {
625 pts = av_frame_get_best_effort_timestamp(mFrame);
628 if (decoder_reorder_pts) {
629 pts = mFrame->pkt_pts;
631 pts = mFrame->pkt_dts;
634 if (pts == AV_NOPTS_VALUE) {
637 outHeader->nTimeStamp = pts; //FIXME pts is right???
640 ALOGV("mFrame pkt_pts: %lld pkt_dts: %lld used %lld", mFrame->pkt_pts, mFrame->pkt_dts, pts);
643 outQueue.erase(outQueue.begin());
644 outInfo->mOwnedByUs = false;
645 notifyFillBufferDone(outHeader);
650 void SoftFFmpegVideo::drainEOSOutputBuffer() {
651 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
652 BufferInfo *outInfo = *outQueue.begin();
653 CHECK(outInfo != NULL);
654 outQueue.erase(outQueue.begin());
655 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
657 ALOGD("ffmpeg video decoder fill eos outbuf");
659 outHeader->nTimeStamp = 0;
660 outHeader->nFilledLen = 0;
661 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
663 outInfo->mOwnedByUs = false;
664 notifyFillBufferDone(outHeader);
666 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
669 void SoftFFmpegVideo::drainAllOutputBuffers() {
670 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
671 if (!mCodecAlreadyOpened) {
672 drainEOSOutputBuffer();
673 mEOSStatus = OUTPUT_FRAMES_FLUSHED;
677 while (!outQueue.empty()) {
678 int32_t err = decodeVideo();
680 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
681 mSignalledError = true;
683 } else if (err == ERR_FLUSHED) {
684 drainEOSOutputBuffer();
686 } else if (err == ERR_NO_FRM) {
689 CHECK_EQ(err, (int32_t)ERR_OK);
691 if (drainOneOutputBuffer() != ERR_OK) {
692 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
693 mSignalledError = true;
699 bool SoftFFmpegVideo::handlePortSettingsChange() {
700 CropSettingsMode crop = kCropUnSet;
701 uint32_t width = outputBufferWidth();
702 uint32_t height = outputBufferHeight();
703 if (width != (uint32_t)mCtx->width || height != (uint32_t)mCtx->height) {
705 if (mCropWidth != width || mCropHeight != height) {
709 mCropHeight = height;
714 bool portWillReset = false;
715 SoftVideoDecoderOMXComponent::handlePortSettingsChange(
716 &portWillReset, mCtx->width, mCtx->height, crop);
717 return portWillReset;
720 void SoftFFmpegVideo::onQueueFilled(OMX_U32 portIndex __unused) {
721 if (mSignalledError || mOutputPortSettingsChange != NONE) {
725 if (mEOSStatus == OUTPUT_FRAMES_FLUSHED) {
729 List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
730 List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
732 while (((mEOSStatus != INPUT_DATA_AVAILABLE) || !inQueue.empty())
733 && !outQueue.empty()) {
735 if (mEOSStatus == INPUT_EOS_SEEN) {
736 drainAllOutputBuffers();
740 BufferInfo *inInfo = *inQueue.begin();
741 if (inInfo == NULL) {
744 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
745 if (inHeader == NULL) {
749 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
750 mEOSStatus = INPUT_EOS_SEEN;
754 if (inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
755 ALOGD("ffmpeg got codecconfig buffer");
756 if (handleExtradata() != ERR_OK) {
757 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
758 mSignalledError = true;
763 if (!mCodecAlreadyOpened) {
764 if (openDecoder() != ERR_OK) {
765 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
766 mSignalledError = true;
771 int32_t err = decodeVideo();
773 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
774 mSignalledError = true;
776 } else if (err == ERR_FLUSHED) {
777 drainEOSOutputBuffer();
779 } else if (err == ERR_NO_FRM) {
782 CHECK_EQ(err, (int32_t)ERR_OK);
785 if (handlePortSettingsChange()) {
786 ALOGV("PORT RESET w=%d h=%d", mCtx->width, mCtx->height);
790 if (drainOneOutputBuffer() != ERR_OK) {
791 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
792 mSignalledError = true;
798 void SoftFFmpegVideo::onPortFlushCompleted(OMX_U32 portIndex) {
799 ALOGV("ffmpeg video decoder flush port(%u)", portIndex);
800 if (portIndex == kInputPortIndex) {
801 if (mCtx && avcodec_is_open(mCtx)) {
802 //Make sure that the next buffer output does not still
803 //depend on fragments from the last one decoded.
804 avcodec_flush_buffers(mCtx);
806 mEOSStatus = INPUT_DATA_AVAILABLE;
810 void SoftFFmpegVideo::onReset() {
812 enum AVCodecID codecID = mCtx->codec_id;
814 initDecoder(codecID);
815 SoftVideoDecoderOMXComponent::onReset();
816 mSignalledError = false;
817 mExtradataReady = false;
818 mEOSStatus = INPUT_DATA_AVAILABLE;
821 SoftOMXComponent* SoftFFmpegVideo::createSoftOMXComponent(
822 const char *name, const OMX_CALLBACKTYPE *callbacks,
823 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
825 if (!property_get_bool("media.sf.hwaccel", 1))
828 OMX_VIDEO_CODINGTYPE codingType = OMX_VIDEO_CodingAutoDetect;
829 char *componentRole = NULL;
830 enum AVCodecID codecID = AV_CODEC_ID_NONE;
832 for (size_t i = 0; i < kNumVideoComponents; ++i) {
833 if (!strcasecmp(name, kVideoComponents[i].mName)) {
834 componentRole = strdup(kVideoComponents[i].mRole);
835 codingType = kVideoComponents[i].mVideoCodingType;
836 codecID = kVideoComponents[i].mCodecID;
841 if (componentRole == NULL) {
845 const CodecProfileLevel *codec_profile_levels;
846 size_t codec_array_size;
847 if (!strcmp(name, "OMX.ffmpeg.mpeg4.decoder")) {
848 codec_profile_levels = kM4VProfileLevels;
849 codec_array_size = ARRAY_SIZE(kM4VProfileLevels);
850 } else if (!strcmp(name, "OMX.ffmpeg.h264.decoder")) {
851 codec_profile_levels = kAVCProfileLevels;
852 codec_array_size = ARRAY_SIZE(kAVCProfileLevels);
854 codec_profile_levels = NULL;
855 codec_array_size = 0;
858 return new SoftFFmpegVideo(name, componentRole, codingType,
859 codec_profile_levels, codec_array_size,
860 callbacks, appData, component, codecID);
863 } // namespace android