summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/ACodec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/ACodec.cpp')
-rw-r--r--media/libstagefright/ACodec.cpp410
1 files changed, 354 insertions, 56 deletions
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 6399b79..e00e673 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -44,6 +44,9 @@
#include <media/stagefright/OMXCodec.h>
#include <media/stagefright/PersistentSurface.h>
#include <media/stagefright/SurfaceUtils.h>
+#include <media/stagefright/FFMPEGSoftCodec.h>
+#include <media/stagefright/Utils.h>
+
#include <media/hardware/HardwareAPI.h>
#include <OMX_AudioExt.h>
@@ -52,8 +55,14 @@
#include <OMX_IndexExt.h>
#include <OMX_AsString.h>
+#ifdef USE_SAMSUNG_COLORFORMAT
+#include <sec_format.h>
+#endif
+
#include "include/avc_utils.h"
+#include <stagefright/AVExtensions.h>
+
namespace android {
// OMX errors are directly mapped into status_t range if
@@ -497,6 +506,8 @@ ACodec::ACodec()
mSentFormat(false),
mIsVideo(false),
mIsEncoder(false),
+ mEncoderComponent(false),
+ mComponentAllocByName(false),
mFatalError(false),
mShutdownInProgress(false),
mExplicitShutdown(false),
@@ -539,6 +550,10 @@ ACodec::ACodec()
ACodec::~ACodec() {
}
+status_t ACodec::setupCustomCodec(status_t err, const char * /*mime*/, const sp<AMessage> &/*msg*/) {
+ return err;
+}
+
void ACodec::setNotificationMessage(const sp<AMessage> &msg) {
mNotify = msg;
}
@@ -613,8 +628,8 @@ void ACodec::initiateShutdown(bool keepComponentAllocated) {
msg->setInt32("keepComponentAllocated", keepComponentAllocated);
msg->post();
if (!keepComponentAllocated) {
- // ensure shutdown completes in 3 seconds
- (new AMessage(kWhatReleaseCodecInstance, this))->post(3000000);
+ // ensure shutdown completes in 30 seconds
+ (new AMessage(kWhatReleaseCodecInstance, this))->post(30000000);
}
}
@@ -716,7 +731,7 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
if (storingMetadataInDecodedBuffers()
&& !mLegacyAdaptiveExperiment
&& info.mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
- ALOGV("skipping buffer %p", info.mGraphicBuffer->getNativeBuffer());
+ ALOGV("skipping buffer %p", info.mGraphicBuffer.get() ? info.mGraphicBuffer->getNativeBuffer() : 0x0);
continue;
}
ALOGV("attaching buffer %p", info.mGraphicBuffer->getNativeBuffer());
@@ -752,7 +767,8 @@ status_t ACodec::handleSetSurface(const sp<Surface> &surface) {
}
// push blank buffers to previous window if requested
- if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown) {
+ if (mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown ||
+ mFlags & kFlagPushBlankBuffersToNativeWindowOnSwitch) {
pushBlankBuffersToNativeWindow(mNativeWindow.get());
}
@@ -828,15 +844,11 @@ status_t ACodec::allocateBuffersOnPort(OMX_U32 portIndex) {
: OMXCodec::kRequiresAllocateBufferOnOutputPorts;
if ((portIndex == kPortIndexInput && (mFlags & kFlagIsSecure))
- || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())) {
+ || (portIndex == kPortIndexOutput && usingMetadataOnEncoderOutput())
+ || canAllocateBuffer(portIndex)) {
mem.clear();
- void *ptr;
- err = mOMX->allocateBuffer(
- mNode, portIndex, bufSize, &info.mBufferID,
- &ptr);
-
- info.mData = new ABuffer(ptr, bufSize);
+ err = allocateBuffer(portIndex, bufSize, info);
} else if (mQuirks & requiresAllocateBufferBit) {
err = mOMX->allocateBufferWithBackup(
mNode, portIndex, mem, &info.mBufferID, allottedSize);
@@ -908,14 +920,57 @@ status_t ACodec::setupNativeWindowSizeFormatAndUsage(
usage |= kVideoGrallocUsage;
*finalUsage = usage;
+#ifdef USE_SAMSUNG_COLORFORMAT
+ OMX_COLOR_FORMATTYPE eNativeColorFormat = def.format.video.eColorFormat;
+ setNativeWindowColorFormat(eNativeColorFormat);
+#endif
+
ALOGV("gralloc usage: %#x(OMX) => %#x(ACodec)", omxUsage, usage);
- return setNativeWindowSizeFormatAndUsage(
+ int32_t width = 0, height = 0;
+ int32_t isAdaptivePlayback = 0;
+
+ if (mInputFormat->findInt32("adaptive-playback", &isAdaptivePlayback)
+ && isAdaptivePlayback
+ && mInputFormat->findInt32("max-width", &width)
+ && mInputFormat->findInt32("max-height", &height)) {
+ width = max(width, (int32_t)def.format.video.nFrameWidth);
+ height = max(height, (int32_t)def.format.video.nFrameHeight);
+ ALOGV("Adaptive playback width = %d, height = %d", width, height);
+ } else {
+ width = def.format.video.nFrameWidth;
+ height = def.format.video.nFrameHeight;
+ }
+ err = setNativeWindowSizeFormatAndUsage(
nativeWindow,
- def.format.video.nFrameWidth,
- def.format.video.nFrameHeight,
+ width,
+ height,
+#ifdef USE_SAMSUNG_COLORFORMAT
+ eNativeColorFormat,
+#else
def.format.video.eColorFormat,
+#endif
mRotationDegrees,
usage);
+#ifdef QCOM_HARDWARE
+ if (err == OK) {
+ OMX_CONFIG_RECTTYPE rect;
+ InitOMXParams(&rect);
+ rect.nPortIndex = kPortIndexOutput;
+ err = mOMX->getConfig(
+ mNode, OMX_IndexConfigCommonOutputCrop, &rect, sizeof(rect));
+ if (err == OK) {
+ ALOGV("rect size = %d, %d, %d, %d", rect.nLeft, rect.nTop, rect.nWidth, rect.nHeight);
+ android_native_rect_t crop;
+ crop.left = rect.nLeft;
+ crop.top = rect.nTop;
+ crop.right = rect.nLeft + rect.nWidth - 1;
+ crop.bottom = rect.nTop + rect.nHeight - 1;
+ ALOGV("crop update (%d, %d), (%d, %d)", crop.left, crop.top, crop.right, crop.bottom);
+ err = native_window_set_crop(nativeWindow, &crop);
+ }
+ }
+#endif
+ return err;
}
status_t ACodec::configureOutputBuffersFromNativeWindow(
@@ -974,6 +1029,12 @@ status_t ACodec::configureOutputBuffersFromNativeWindow(
// 2. try to allocate two (2) additional buffers to reduce starvation from
// the consumer
// plus an extra buffer to account for incorrect minUndequeuedBufs
+#ifdef BOARD_CANT_REALLOCATE_OMX_BUFFERS
+ // Some devices don't like to set OMX_IndexParamPortDefinition at this
+ // point (even with an unmodified def), so skip it if possible.
+ // This check was present in KitKat.
+ if (def.nBufferCountActual < def.nBufferCountMin + *minUndequeuedBuffers) {
+#endif
for (OMX_U32 extraBuffers = 2 + 1; /* condition inside loop */; extraBuffers--) {
OMX_U32 newBufferCount =
def.nBufferCountMin + *minUndequeuedBuffers + extraBuffers;
@@ -993,6 +1054,9 @@ status_t ACodec::configureOutputBuffersFromNativeWindow(
return err;
}
}
+#ifdef BOARD_CANT_REALLOCATE_OMX_BUFFERS
+ }
+#endif
err = native_window_set_buffer_count(
mNativeWindow.get(), def.nBufferCountActual);
@@ -1244,6 +1308,27 @@ void ACodec::dumpBuffers(OMX_U32 portIndex) {
}
}
+#ifdef USE_SAMSUNG_COLORFORMAT
+void ACodec::setNativeWindowColorFormat(OMX_COLOR_FORMATTYPE &eNativeColorFormat)
+{
+ // In case of Samsung decoders, we set proper native color format for the Native Window
+ if (!strcasecmp(mComponentName.c_str(), "OMX.SEC.AVC.Decoder")
+ || !strcasecmp(mComponentName.c_str(), "OMX.SEC.FP.AVC.Decoder")
+ || !strcasecmp(mComponentName.c_str(), "OMX.SEC.MPEG4.Decoder")
+ || !strcasecmp(mComponentName.c_str(), "OMX.Exynos.AVC.Decoder")) {
+ switch (eNativeColorFormat) {
+ case OMX_COLOR_FormatYUV420SemiPlanar:
+ eNativeColorFormat = (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YCbCr_420_SP;
+ break;
+ case OMX_COLOR_FormatYUV420Planar:
+ default:
+ eNativeColorFormat = (OMX_COLOR_FORMATTYPE)HAL_PIXEL_FORMAT_YCbCr_420_P;
+ break;
+ }
+ }
+}
+#endif
+
status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
@@ -1327,7 +1412,8 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
}
bool stale = false;
- for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
+ for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
+ i--;
BufferInfo *info = &mBuffers[kPortIndexOutput].editItemAt(i);
if (info->mGraphicBuffer != NULL &&
@@ -1370,7 +1456,8 @@ ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
// get oldest undequeued buffer
BufferInfo *oldest = NULL;
- for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
+ for (size_t i = mBuffers[kPortIndexOutput].size(); i > 0;) {
+ i--;
BufferInfo *info =
&mBuffers[kPortIndexOutput].editItemAt(i);
if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW &&
@@ -1574,6 +1661,8 @@ status_t ACodec::setComponentRole(
"audio_decoder.ac3", "audio_encoder.ac3" },
{ MEDIA_MIMETYPE_AUDIO_EAC3,
"audio_decoder.eac3", "audio_encoder.eac3" },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4_DP,
+ "video_decoder.mpeg4", NULL },
};
static const size_t kNumMimeToRole =
@@ -1587,7 +1676,7 @@ status_t ACodec::setComponentRole(
}
if (i == kNumMimeToRole) {
- return ERROR_UNSUPPORTED;
+ return FFMPEGSoftCodec::setSupportedRole(mOMX, mNode, isEncoder, mime);
}
const char *role =
@@ -1639,6 +1728,8 @@ status_t ACodec::configureCodec(
return err;
}
+ enableCustomAllocationMode(msg);
+
int32_t bitRate = 0;
// FLAC encoder doesn't need a bitrate, other encoders do
if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
@@ -1893,6 +1984,12 @@ status_t ACodec::configureCodec(
&& push != 0) {
mFlags |= kFlagPushBlankBuffersToNativeWindowOnShutdown;
}
+
+ int32_t val;
+ if (msg->findInt32("push-blank-buffers-on-switch", &val)
+ && val != 0) {
+ mFlags |= kFlagPushBlankBuffersToNativeWindowOnSwitch;
+ }
}
int32_t rotationDegrees;
@@ -1906,7 +2003,8 @@ status_t ACodec::configureCodec(
if (video) {
// determine need for software renderer
bool usingSwRenderer = false;
- if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
+ if (haveNativeWindow && (mComponentName.startsWith("OMX.google.") ||
+ mComponentName.startsWith("OMX.ffmpeg."))) {
usingSwRenderer = true;
haveNativeWindow = false;
}
@@ -1991,10 +2089,12 @@ status_t ACodec::configureCodec(
// and have the decoder figure it all out.
err = OK;
} else {
- err = setupRawAudioFormat(
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bits-per-sample", &bitsPerSample);
+ err = setupRawAudioFormatInternal(
encoder ? kPortIndexInput : kPortIndexOutput,
sampleRate,
- numChannels);
+ numChannels, bitsPerSample);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
int32_t numChannels, sampleRate;
@@ -2006,6 +2106,7 @@ status_t ACodec::configureCodec(
int32_t sbrMode;
int32_t maxOutputChannelCount;
int32_t pcmLimiterEnable;
+ int32_t bitsPerSample = 16;
drcParams_t drc;
if (!msg->findInt32("is-adts", &isADTS)) {
isADTS = 0;
@@ -2044,11 +2145,12 @@ status_t ACodec::configureCodec(
// value is unknown
drc.targetRefLevel = -1;
}
+ msg->findInt32("bits-per-sample", &bitsPerSample);
err = setupAACCodec(
encoder, numChannels, sampleRate, bitRate, aacProfile,
isADTS != 0, sbrMode, maxOutputChannelCount, drc,
- pcmLimiterEnable);
+ pcmLimiterEnable, bitsPerSample);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
@@ -2069,7 +2171,7 @@ status_t ACodec::configureCodec(
}
err = setupG711Codec(encoder, sampleRate, numChannels);
}
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) {
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC) && encoder) {
int32_t numChannels = 0, sampleRate = 0, compressionLevel = -1;
if (encoder &&
(!msg->findInt32("channel-count", &numChannels)
@@ -2105,16 +2207,21 @@ status_t ACodec::configureCodec(
|| !msg->findInt32("sample-rate", &sampleRate)) {
err = INVALID_OPERATION;
} else {
- err = setupRawAudioFormat(kPortIndexInput, sampleRate, numChannels);
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bits-per-sample", &bitsPerSample);
+ err = setupRawAudioFormatInternal(kPortIndexInput, sampleRate, numChannels, bitsPerSample);
}
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
+ } else if (!strncmp(mComponentName.c_str(), "OMX.google.", 11)
+ && !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AC3)) {
int32_t numChannels;
int32_t sampleRate;
if (!msg->findInt32("channel-count", &numChannels)
|| !msg->findInt32("sample-rate", &sampleRate)) {
err = INVALID_OPERATION;
} else {
- err = setupAC3Codec(encoder, numChannels, sampleRate);
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bits-per-sample", &bitsPerSample);
+ err = setupAC3Codec(encoder, numChannels, sampleRate, bitsPerSample);
}
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_EAC3)) {
int32_t numChannels;
@@ -2123,7 +2230,16 @@ status_t ACodec::configureCodec(
|| !msg->findInt32("sample-rate", &sampleRate)) {
err = INVALID_OPERATION;
} else {
- err = setupEAC3Codec(encoder, numChannels, sampleRate);
+ int32_t bitsPerSample = 16;
+ msg->findInt32("bits-per-sample", &bitsPerSample);
+ err = setupEAC3Codec(encoder, numChannels, sampleRate, bitsPerSample);
+ }
+ } else {
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11) && !mIsEncoder) {
+ err = FFMPEGSoftCodec::setAudioFormat(
+ msg, mime, mOMX, mNode);
+ } else {
+ err = setupCustomCodec(err, mime, msg);
}
}
@@ -2294,15 +2410,16 @@ status_t ACodec::setupAACCodec(
bool encoder, int32_t numChannels, int32_t sampleRate,
int32_t bitRate, int32_t aacProfile, bool isADTS, int32_t sbrMode,
int32_t maxOutputChannelCount, const drcParams_t& drc,
- int32_t pcmLimiterEnable) {
+ int32_t pcmLimiterEnable, int32_t bitsPerSample) {
if (encoder && isADTS) {
return -EINVAL;
}
- status_t err = setupRawAudioFormat(
+ status_t err = setupRawAudioFormatInternal(
encoder ? kPortIndexInput : kPortIndexOutput,
sampleRate,
- numChannels);
+ numChannels,
+ bitsPerSample);
if (err != OK) {
return err;
@@ -2439,9 +2556,9 @@ status_t ACodec::setupAACCodec(
}
status_t ACodec::setupAC3Codec(
- bool encoder, int32_t numChannels, int32_t sampleRate) {
- status_t err = setupRawAudioFormat(
- encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t bitsPerSample) {
+ status_t err = setupRawAudioFormatInternal(
+ encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels, bitsPerSample);
if (err != OK) {
return err;
@@ -2477,9 +2594,9 @@ status_t ACodec::setupAC3Codec(
}
status_t ACodec::setupEAC3Codec(
- bool encoder, int32_t numChannels, int32_t sampleRate) {
- status_t err = setupRawAudioFormat(
- encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels);
+ bool encoder, int32_t numChannels, int32_t sampleRate, int32_t bitsPerSample) {
+ status_t err = setupRawAudioFormatInternal(
+ encoder ? kPortIndexInput : kPortIndexOutput, sampleRate, numChannels, bitsPerSample);
if (err != OK) {
return err;
@@ -2626,6 +2743,11 @@ status_t ACodec::setupFlacCodec(
status_t ACodec::setupRawAudioFormat(
OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels) {
+ return setupRawAudioFormatInternal(portIndex, sampleRate, numChannels, 16);
+}
+
+status_t ACodec::setupRawAudioFormatInternal(
+ OMX_U32 portIndex, int32_t sampleRate, int32_t numChannels, int32_t bitsPerSample) {
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = portIndex;
@@ -2660,7 +2782,7 @@ status_t ACodec::setupRawAudioFormat(
pcmParams.nChannels = numChannels;
pcmParams.eNumData = OMX_NumericalDataSigned;
pcmParams.bInterleaved = OMX_TRUE;
- pcmParams.nBitPerSample = 16;
+ pcmParams.nBitPerSample = bitsPerSample;
pcmParams.nSamplingRate = sampleRate;
pcmParams.ePCMMode = OMX_AUDIO_PCMModeLinear;
@@ -2836,13 +2958,14 @@ static const struct VideoCodingMapEntry {
{ MEDIA_MIMETYPE_VIDEO_AVC, OMX_VIDEO_CodingAVC },
{ MEDIA_MIMETYPE_VIDEO_HEVC, OMX_VIDEO_CodingHEVC },
{ MEDIA_MIMETYPE_VIDEO_MPEG4, OMX_VIDEO_CodingMPEG4 },
+ { MEDIA_MIMETYPE_VIDEO_MPEG4_DP, OMX_VIDEO_CodingMPEG4 },
{ MEDIA_MIMETYPE_VIDEO_H263, OMX_VIDEO_CodingH263 },
{ MEDIA_MIMETYPE_VIDEO_MPEG2, OMX_VIDEO_CodingMPEG2 },
{ MEDIA_MIMETYPE_VIDEO_VP8, OMX_VIDEO_CodingVP8 },
{ MEDIA_MIMETYPE_VIDEO_VP9, OMX_VIDEO_CodingVP9 },
};
-static status_t GetVideoCodingTypeFromMime(
+status_t ACodec::GetVideoCodingTypeFromMime(
const char *mime, OMX_VIDEO_CODINGTYPE *codingType) {
for (size_t i = 0;
i < sizeof(kVideoCodingMapEntry) / sizeof(kVideoCodingMapEntry[0]);
@@ -2885,6 +3008,9 @@ status_t ACodec::setupVideoDecoder(
OMX_VIDEO_CODINGTYPE compressionFormat;
status_t err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
+ err = FFMPEGSoftCodec::setVideoFormat(err,
+ msg, mime, mOMX, mNode, mIsEncoder, &compressionFormat,
+ mComponentName.c_str());
if (err != OK) {
return err;
}
@@ -3035,7 +3161,11 @@ status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
OMX_VIDEO_CODINGTYPE compressionFormat;
err = GetVideoCodingTypeFromMime(mime, &compressionFormat);
+ err = FFMPEGSoftCodec::setVideoFormat(err,
+ msg, mime, mOMX, mNode, mIsEncoder, &compressionFormat,
+ mComponentName.c_str());
if (err != OK) {
+ ALOGE("Not a supported video mime type: %s", mime);
return err;
}
@@ -3229,6 +3359,7 @@ status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
mpeg4type.eLevel = static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level);
}
+ setBFrames(&mpeg4type);
err = mOMX->setParameter(
mNode, OMX_IndexParamVideoMpeg4, &mpeg4type, sizeof(mpeg4type));
@@ -3426,6 +3557,8 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
err = verifySupportForProfileAndLevel(profile, level);
if (err != OK) {
+ ALOGE("%s does not support profile %x @ level %x",
+ mComponentName.c_str(), profile, level);
return err;
}
@@ -3434,11 +3567,14 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
}
// XXX
+ // Allow higher profiles to be set since the encoder seems to support
+#if 0
if (h264type.eProfile != OMX_VIDEO_AVCProfileBaseline) {
ALOGW("Use baseline profile instead of %d for AVC recording",
h264type.eProfile);
h264type.eProfile = OMX_VIDEO_AVCProfileBaseline;
}
+#endif
if (h264type.eProfile == OMX_VIDEO_AVCProfileBaseline) {
h264type.nSliceHeaderSpacing = 0;
@@ -3459,6 +3595,7 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
h264type.nCabacInitIdc = 0;
}
+ setBFrames(&h264type, iFrameInterval, frameRate);
if (h264type.nBFrames != 0) {
h264type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
}
@@ -3499,6 +3636,8 @@ status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
frameRate = (float)tmp;
}
+ AVUtils::get()->setIntraPeriod(setPFramesSpacing(iFrameInterval, frameRate), 0, mOMX, mNode);
+
OMX_VIDEO_PARAM_HEVCTYPE hevcType;
InitOMXParams(&hevcType);
hevcType.nPortIndex = kPortIndexOutput;
@@ -3680,7 +3819,7 @@ status_t ACodec::setupErrorCorrectionParameters() {
errorCorrectionType.bEnableHEC = OMX_FALSE;
errorCorrectionType.bEnableResync = OMX_TRUE;
- errorCorrectionType.nResynchMarkerSpacing = 256;
+ errorCorrectionType.nResynchMarkerSpacing = 0;
errorCorrectionType.bEnableDataPartitioning = OMX_FALSE;
errorCorrectionType.bEnableRVLC = OMX_FALSE;
@@ -3839,6 +3978,7 @@ bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
fmt != OMX_COLOR_FormatYUV420PackedPlanar &&
fmt != OMX_COLOR_FormatYUV420SemiPlanar &&
fmt != OMX_COLOR_FormatYUV420PackedSemiPlanar &&
+ fmt != OMX_TI_COLOR_FormatYUV420PackedSemiPlanar &&
fmt != HAL_PIXEL_FORMAT_YV12) {
ALOGW("do not know color format 0x%x = %d", fmt, fmt);
return false;
@@ -3911,6 +4051,7 @@ bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams &params) {
case OMX_COLOR_FormatYUV420SemiPlanar:
// FIXME: NV21 for sw-encoder, NV12 for decoder and hw-encoder
case OMX_COLOR_FormatYUV420PackedSemiPlanar:
+ case OMX_TI_COLOR_FormatYUV420PackedSemiPlanar:
// NV12
image.mPlane[image.U].mOffset = params.nStride * params.nSliceHeight;
image.mPlane[image.U].mColInc = 2;
@@ -4068,6 +4209,16 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
rect.nWidth = videoDef->nFrameWidth;
rect.nHeight = videoDef->nFrameHeight;
}
+#ifdef MTK_HARDWARE
+ if (!strncmp(mComponentName.c_str(), "OMX.MTK.", 8) && mOMX->getConfig(
+ mNode, (OMX_INDEXTYPE) 0x7f00001c /* OMX_IndexVendorMtkOmxVdecGetCropInfo */,
+ &rect, sizeof(rect)) != OK) {
+ rect.nLeft = 0;
+ rect.nTop = 0;
+ rect.nWidth = videoDef->nFrameWidth;
+ rect.nHeight = videoDef->nFrameHeight;
+ }
+#endif
if (rect.nLeft < 0 ||
rect.nTop < 0 ||
@@ -4135,6 +4286,14 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
default:
{
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::getVideoPortFormat(portIndex,
+ (int)videoDef->eCompressionFormat, notify, mOMX, mNode);
+ if (err == OK) {
+ break;
+ }
+ }
+
if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
// should be CodingUnused
ALOGE("Raw port video compression format is %s(%d)",
@@ -4180,7 +4339,10 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
if (params.nChannels <= 0
|| (params.nChannels != 1 && !params.bInterleaved)
- || params.nBitPerSample != 16u
+ || (params.nBitPerSample != 16u
+ && params.nBitPerSample != 24u
+ && params.nBitPerSample != 32u
+ && params.nBitPerSample != 8u)// we support 8/16/24/32 bit s/w decoding
|| params.eNumData != OMX_NumericalDataSigned
|| params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
@@ -4195,6 +4357,8 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
notify->setInt32("channel-count", params.nChannels);
notify->setInt32("sample-rate", params.nSamplingRate);
+ notify->setInt32("bits-per-sample", params.nBitPerSample);
+ notify->setInt32("pcm-format", getPCMFormat(notify));
if (mChannelMaskPresent) {
notify->setInt32("channel-mask", mChannelMask);
@@ -4245,6 +4409,13 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
case OMX_AUDIO_CodingFLAC:
{
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::getAudioPortFormat(portIndex,
+ (int)audioDef->eEncoding, notify, mOMX, mNode);
+ if (err != OK) {
+ return err;
+ }
+ } else {
OMX_AUDIO_PARAM_FLACTYPE params;
InitOMXParams(&params);
params.nPortIndex = portIndex;
@@ -4258,6 +4429,7 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
notify->setInt32("channel-count", params.nChannels);
notify->setInt32("sample-rate", params.nSampleRate);
+ }
break;
}
@@ -4399,6 +4571,14 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
}
default:
+ if (!strncmp(mComponentName.c_str(), "OMX.ffmpeg.", 11)) {
+ err = FFMPEGSoftCodec::getAudioPortFormat(portIndex,
+ (int)audioDef->eEncoding, notify, mOMX, mNode);
+ }
+ if (err == OK) {
+ break;
+ }
+
ALOGE("Unsupported audio coding: %s(%d)\n",
asString(audioDef->eEncoding), audioDef->eEncoding);
return BAD_TYPE;
@@ -4437,18 +4617,17 @@ void ACodec::sendFormatChange(const sp<AMessage> &reply) {
(mEncoderDelay || mEncoderPadding)) {
int32_t channelCount;
CHECK(notify->findInt32("channel-count", &channelCount));
- size_t frameSize = channelCount * sizeof(int16_t);
if (mSkipCutBuffer != NULL) {
size_t prevbufsize = mSkipCutBuffer->size();
if (prevbufsize != 0) {
ALOGW("Replacing SkipCutBuffer holding %zu bytes", prevbufsize);
}
}
- mSkipCutBuffer = new SkipCutBuffer(
- mEncoderDelay * frameSize,
- mEncoderPadding * frameSize);
+ mSkipCutBuffer = new SkipCutBuffer(mEncoderDelay, mEncoderPadding, channelCount);
}
+ getVQZIPInfo(notify);
+
notify->post();
mSentFormat = true;
@@ -4597,6 +4776,7 @@ bool ACodec::BaseState::onMessageReceived(const sp<AMessage> &msg) {
ALOGI("[%s] forcing the release of codec",
mCodec->mComponentName.c_str());
status_t err = mCodec->mOMX->freeNode(mCodec->mNode);
+ mCodec->changeState(mCodec->mUninitializedState);
ALOGE_IF("[%s] failed to release codec instance: err=%d",
mCodec->mComponentName.c_str(), err);
sp<AMessage> notify = mCodec->mNotify->dup();
@@ -5181,6 +5361,7 @@ bool ACodec::BaseState::onOMXFillBufferDone(
mCodec->mSkipCutBuffer->submit(info->mData);
}
info->mData->meta()->setInt64("timeUs", timeUs);
+ info->mData->meta()->setObject("graphic-buffer", info->mGraphicBuffer);
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatDrainThisBuffer);
@@ -5190,6 +5371,8 @@ bool ACodec::BaseState::onOMXFillBufferDone(
reply->setInt32("buffer-id", info->mBufferID);
+ (void)mCodec->setDSModeHint(reply, flags, timeUs);
+
notify->setMessage("reply", reply);
notify->post();
@@ -5244,8 +5427,9 @@ void ACodec::BaseState::onOutputBufferDrained(const sp<AMessage> &msg) {
ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
}
+ bool skip = mCodec->getDSModeHint(msg);
int32_t render;
- if (mCodec->mNativeWindow != NULL
+ if (!skip && mCodec->mNativeWindow != NULL
&& msg->findInt32("render", &render) && render != 0
&& info->mData != NULL && info->mData->size() != 0) {
ATRACE_NAME("render");
@@ -5373,6 +5557,8 @@ void ACodec::UninitializedState::stateEntered() {
mCodec->mOMX.clear();
mCodec->mQuirks = 0;
mCodec->mFlags = 0;
+ mCodec->mEncoderComponent = 0;
+ mCodec->mComponentAllocByName = 0;
mCodec->mInputMetadataType = kMetadataBufferTypeInvalid;
mCodec->mOutputMetadataType = kMetadataBufferTypeInvalid;
mCodec->mComponentName.clear();
@@ -5478,6 +5664,7 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
ssize_t index = matchingCodecs.add();
OMXCodec::CodecNameAndQuirks *entry = &matchingCodecs.editItemAt(index);
entry->mName = String8(componentName.c_str());
+ mCodec->mComponentAllocByName = true;
if (!OMXCodec::findCodecQuirks(
componentName.c_str(), &entry->mQuirks)) {
@@ -5490,6 +5677,10 @@ bool ACodec::UninitializedState::onAllocateComponent(const sp<AMessage> &msg) {
encoder = false;
}
+ if (encoder == true) {
+ mCodec->mEncoderComponent = true;
+ }
+
OMXCodec::findMatchingCodecs(
mime.c_str(),
encoder, // createEncoder
@@ -5682,6 +5873,7 @@ bool ACodec::LoadedState::onConfigureComponent(
status_t err = OK;
AString mime;
+
if (!msg->findString("mime", &mime)) {
err = BAD_VALUE;
} else {
@@ -5691,13 +5883,80 @@ bool ACodec::LoadedState::onConfigureComponent(
ALOGE("[%s] configureCodec returning error %d",
mCodec->mComponentName.c_str(), err);
- mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
- return false;
+ if (!mCodec->mEncoderComponent && !mCodec->mComponentAllocByName &&
+ !strncmp(mime.c_str(), "video/", strlen("video/"))) {
+ Vector<OMXCodec::CodecNameAndQuirks> matchingCodecs;
+
+ OMXCodec::findMatchingCodecs(
+ mime.c_str(),
+ false, // createEncoder
+ NULL, // matchComponentName
+ 0, // flags
+ &matchingCodecs);
+
+ err = mCodec->mOMX->freeNode(mCodec->mNode);
+
+ if (err != OK) {
+ ALOGE("Failed to freeNode");
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ return false;
+ }
+
+ mCodec->mNode = 0;
+ AString componentName;
+ sp<CodecObserver> observer = new CodecObserver;
+
+ err = NAME_NOT_FOUND;
+ for (size_t matchIndex = 0; matchIndex < matchingCodecs.size();
+ ++matchIndex) {
+ componentName = matchingCodecs.itemAt(matchIndex).mName.string();
+ if (!strcmp(mCodec->mComponentName.c_str(), componentName.c_str())) {
+ continue;
+ }
+
+ pid_t tid = gettid();
+ int prevPriority = androidGetThreadPriority(tid);
+ androidSetThreadPriority(tid, ANDROID_PRIORITY_FOREGROUND);
+ err = mCodec->mOMX->allocateNode(componentName.c_str(), observer, &mCodec->mNode);
+ androidSetThreadPriority(tid, prevPriority);
+
+ if (err == OK) {
+ break;
+ } else {
+ ALOGW("Allocating component '%s' failed, try next one.", componentName.c_str());
+ }
+
+ mCodec->mNode = 0;
+ }
+
+ if (mCodec->mNode == 0) {
+ if (!mime.empty()) {
+ ALOGE("Unable to instantiate a decoder for type '%s'", mime.c_str());
+ } else {
+ ALOGE("Unable to instantiate codec '%s' with err %#x.", componentName.c_str(), err);
+ }
+
+ mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
+ return false;
+ }
+
+ sp<AMessage> notify = new AMessage(kWhatOMXMessageList, mCodec);
+ observer->setNotificationMessage(notify);
+ mCodec->mComponentName = componentName;
+
+ err = mCodec->configureCodec(mime.c_str(), msg);
+ }
+
+ if (err != OK) {
+ mCodec->signalError((OMX_ERRORTYPE)err, makeNoSideEffectStatus(err));
+ return false;
+ }
}
{
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatComponentConfigured);
+ notify->setString("componentName", mCodec->mComponentName.c_str());
notify->setMessage("input-format", mCodec->mInputFormat);
notify->setMessage("output-format", mCodec->mOutputFormat);
notify->post();
@@ -6360,6 +6619,23 @@ void ACodec::onSignalEndOfInputStream() {
notify->post();
}
+sp<IOMXObserver> ACodec::createObserver() {
+ sp<CodecObserver> observer = new CodecObserver;
+ sp<AMessage> notify = new AMessage(kWhatOMXMessageList, this);
+ observer->setNotificationMessage(notify);
+ return observer;
+}
+
+status_t ACodec::allocateBuffer(
+ OMX_U32 portIndex, size_t bufSize, BufferInfo &info) {
+ void *ptr;
+ status_t err = mOMX->allocateBuffer(
+ mNode, portIndex, bufSize, &info.mBufferID, &ptr);
+
+ info.mData = new ABuffer(ptr, bufSize);
+ return err;
+}
+
bool ACodec::ExecutingState::onOMXFrameRendered(int64_t mediaTimeUs, nsecs_t systemNano) {
mCodec->onFrameRendered(mediaTimeUs, systemNano);
return true;
@@ -6430,8 +6706,34 @@ bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
bool handled = false;
switch (msg->what()) {
- case kWhatFlush:
case kWhatShutdown:
+ {
+ int32_t keepComponentAllocated;
+ CHECK(msg->findInt32(
+ "keepComponentAllocated", &keepComponentAllocated));
+
+ mCodec->mShutdownInProgress = true;
+ mCodec->mExplicitShutdown = true;
+ mCodec->mKeepComponentAllocated = keepComponentAllocated;
+
+ status_t err = mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+ if (err != OK) {
+ if (keepComponentAllocated) {
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ }
+ // TODO: do some recovery here.
+ } else {
+ // This is technically not correct, but appears to be
+ // the only way to free the component instance using
+ // ExectingToIdleState.
+ mCodec->changeState(mCodec->mExecutingToIdleState);
+ }
+
+ handled = true;
+ break;
+ }
+ case kWhatFlush:
case kWhatResume:
case kWhatSetParameters:
{
@@ -6490,6 +6792,11 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
}
+ /* Clear the RenderQueue in which queued GraphicBuffers hold the
+ * actual buffer references in order to free them early.
+ */
+ mCodec->mRenderTracker.clear(systemTime(CLOCK_MONOTONIC));
+
if (err == OK) {
err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
@@ -6498,15 +6805,6 @@ bool ACodec::OutputPortSettingsChangedState::onOMXEvent(
if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
-
- // This is technically not correct, but appears to be
- // the only way to free the component instance.
- // Controlled transitioning from excecuting->idle
- // and idle->loaded seem impossible probably because
- // the output port never finishes re-enabling.
- mCodec->mShutdownInProgress = true;
- mCodec->mKeepComponentAllocated = false;
- mCodec->changeState(mCodec->mLoadedState);
}
return true;