summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorSteve Kondik <shade@chemlab.org>2012-02-13 09:30:48 -0800
committerSteve Kondik <shade@chemlab.org>2012-05-19 21:22:42 -0700
commit7a5f54ef07a928f5db5da5c0eab1f0cfcb1e0d76 (patch)
tree138c8adc10b33e6e43af45801813a63e327692f3 /media
parent3ae2087388a72fefcb3240d653cd3f3bd700dc65 (diff)
downloadframeworks_base-7a5f54ef07a928f5db5da5c0eab1f0cfcb1e0d76.zip
frameworks_base-7a5f54ef07a928f5db5da5c0eab1f0cfcb1e0d76.tar.gz
frameworks_base-7a5f54ef07a928f5db5da5c0eab1f0cfcb1e0d76.tar.bz2
libstagefright: Squashed commit of updates from CodeAurora
libstagefright: Secure o/p buffers only when i/p buffers are secure ION allocation fails on o/p buffers when i/p buffers are not secure. Disabling secure allocation of o/p buffers when i/p buffers are not secure. (cherry picked from commit ea10201ece24a3c61b79202b93e440eddb624d65) Change-Id: I329c8428d3e528f7d177a64b8605090357f34035 CRs-Fixed: 336727 libstagefright: Synchronize access to OMX class member variables - Protect mLiveNodes KeyedVector member variable in freeNode function - This variable might be accessed concurrently if two OMXNodeInstance objects are freed. (cherry picked from commit 796ea3f006ccac48a1fa1eae904667238c0ebbf6) Change-Id: I01b12da57f44c1dfa978763c19de0041dc231b2b CRs-Fixed: 332651 libstagefright: Fix HFR crash in MPEG4Writer From ICS, for video kkeyframerate is used instead of kkeysamplerate. This needed correction in MPEG4Writer. kkeydecoding timestamp is used for sending the decoding timestamp. The decoding timestamp had to updated for HFR. Change-Id: I194a218b00ffcd41b1646a0c29c26a7a8f87e819 libstagefright: Increase bit rate for HFR recording Increase bit rate for high frame rate (HFR) recording feature to reflect the corresponding increase in frame rate CRs-Fixed: 334201 (cherry picked from commit a5118e46646210f9e174c5d5db8c2cfa13e5bd65) Change-Id: I1d77206e43d93ceef75a69113b124e2feb159663 libstagefright: Fix bitrate and I frame interval values for HFR mode CRs-Fixed: 341667 (cherry picked from commit 331cf5e8dffb1bbd96a92a275730fd90d7d49b2c) Change-Id: Icfd92689752951dbe6c2b659c9c4891ca30b8d62 libstagefright: Fix video encode I-frame interval setting The i-frame interval setting is not configured properly when b-frames are enabled. Fixes the calculation for the i-frame interval setting when b-frames are enabled. CRs-Fixed: 348669 (cherry picked from commit 3fed07eac060215748b67e9d641f84bd684e6a2b) Change-Id: Idbbeb1df638635336dd54dc2fe227d06a367ea79 libstagefright: Fix for b-frame encode and decode - fix timestamp calculation during encode and playback for clips with b-frames Change-Id: Ibe6658475c8bf9ceca05015b81536f6bac737da6 libstagefright: OMXCodec error handling fix - Drop messages in OMXCodec ERROR state only for s/w OMX component Change-Id: If9940f1f1429821587938fe005c526ab7559ff8e libstagefright: Fix ANR issue for recording timelapse and b-frames videos. CRs-Fixed: 340493 (cherry picked from commit 2f46989491d8f7f8ac480a39620803736101fd80) Change-Id: I41ae8296fbc4cc480e7ad8ce4451c6fd5753d4b7 libstagefright: Free all video decoder output buffers on an error - OMXCodec calls dequeueBuffer on the NativeWindow in a loop and registers output buffers with the OMX component - If a dequeueBuffer fails, the buffers already registered with the OMX component were not getting freed laeding to a memory leak. Change-Id: I56abc7577b10e7540bdd6488708ae6830b9d907b CRs-Fixed: 351388 (cherry picked from commit 0d4e06d9a53240e0e7aca05a64faea353babb029) libstagefright: Reset buffer size value with SurfaceTexture - OMXCodec explicitly sets the decoder output buffer size using the native window perform API. (to accomodate extra-data) - This size is reset only when the SurfaceTexture is destroyed. - Unless reset, this size will be assumed for all output buffers if the SurfaceTexture is re-used. CRs-Fixed: 337660 Change-Id: I28aed12ad02adeac61caffbb00e3082640a5f6d4 (cherry picked from commit 031e95469b897680670a2480e55be727d00bbd82) libstagefright: Fix version and flag values for ctts box atom - Write proper value for version 1 of ctts atom in MPEG4Writer - Check against proper value for version 1 of ctts atom in SampleTable CRs-Fixed: 340309 (cherry picked from commit 86de95c33ed597dc3b2f9b8db95c4115dfeb1c4b) Change-Id: Iaa924870cadca501550d5ef838f4265a81c53d50 libstagefright: Add member variable to save arbitrary mode value - Add member variable in OMXCodec to save aribtrary mode value. (default: true) - Avoid overwriting the value of key kKeyUseArbitraryMode in track metadata. OMXCodec::Create gets a const pointer to the track metadata. Change-Id: I94dd24933f112109a1469b2b2a24f0b82b19a104 CRs-Fixed: 340148 (cherry picked from commit e4c000bad2e669d156c82887070c5f37f7b1c00c) libstagefright: Pass width and height in android_native_rect - android_native_rect expects four fields; top, left, bottom, right. - Contrary to what it looks like, the bottom and right fields are to be used as width & height (instead of co-ordinates) - Fixing use of native_window_set_crop to use the adjusted values (cherry picked from commit d1050e76b966a405e539a89a1aa2aee4c972b6ca) Change-Id: I80f0de1c1e73d979f3499fcd0a7289e6ab00332b libstagefright: Crop the native window with display resolution We provide the native window with the display width and height in set_geometry. On the surfaceflinger side, they assume that this is aligned, which causes problems for HDMI. Instead we'll now pass in the aligned stride and slice in native_window_set_geometry, then specify the desired display width and height and call native_window_set_crop. CRs-fixed: 332778 Change-Id: Iecfe11ded743715ea2eabad4a3fddbc1b04b5005 (cherry picked from commit 51b550aa2f6049a71261e2a5a76ae8a1450cd96b) Conflicts: media/libstagefright/ACodec.cpp libstagefright: Enable suspension policy -ADSP did not enter suspend state after audio playback. -No support for suspension policy in stagefright. -Enable suspension policy for the OMX component to take care of the power collapse in stagefright. -Merged the three gingerbread changes 50118, 62031 and 89989 for this Change-Id: I92f545d2684dddb9ef398c93b8c941a6c842a9f9 Conflicts: media/libstagefright/OMXCodec.cpp libstagefright: Encoder state check before calling OMX_FreeBuffer - Add state check based on OMX IL specification before calling OMX_FreeBuffer. CRs-Fixed: 337484 (cherry picked from commit d652e076b06bc6eb1a654e83e5229ffb09320668) Change-Id: Ic958682fa792aa144774d71f34a182a00cb10efd libstagefright: Fix for playback error during multiple play and pause - When H/W decoder is used, in pause state empty this buffer is not called from drainInputBuffer which blocks sending input buffers to the omx component. - When all the input buffers are processed by the omx component, it keeps waiting for the new input buffers after resume. - As the input buffers are not sent after resume, omx component do not sent output since it does not have any input buffers to decode. This is resulting in timeout on the output port. - Modified IL client to fill all the empty input buffers at omx start in case of H/W decoder. CRs-Fixed: 340761 (cherry picked from commit 1ecd319917b0197c23fc53968065aac9380bad6b) Change-Id: I530a4a91d91c01dd98fe6b818fe458dedb2ac9e0 libstagefright: Release output buffer when file limit is reached in recording There is a memory leak in video recording when the file size or duration limits are reached. The output buffer copy is not released before exiting the track thread in the mpeg4 writer. To avoid the memory leak, the buffer copy is released when a limit condition is detected in the mpeg4 writer. Change-Id: Idfde2083fdd9997b3025c7c12e00f3ae4665b8da CRs-Fixed: 315255
Diffstat (limited to 'media')
-rwxr-xr-xmedia/libstagefright/ACodec.cpp6
-rw-r--r--media/libstagefright/AudioPlayer.cpp24
-rwxr-xr-xmedia/libstagefright/MPEG4Writer.cpp59
-rwxr-xr-xmedia/libstagefright/OMXCodec.cpp256
-rw-r--r--media/libstagefright/SampleIterator.cpp2
-rw-r--r--media/libstagefright/SampleTable.cpp7
-rw-r--r--media/libstagefright/omx/OMX.cpp12
7 files changed, 286 insertions, 80 deletions
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 155dc9c..0ad13b6 100755
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
/*--------------------------------------------------------------------------
-Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
--------------------------------------------------------------------------*/
//#define LOG_NDEBUG 0
@@ -548,11 +548,13 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() {
#else
err = native_window_set_buffers_geometry(
mNativeWindow.get(),
+#ifdef QCOM_HARDWARE
def.format.video.nFrameWidth,
def.format.video.nFrameHeight,
-#ifdef QCOM_HARDWARE
format);
#else
+ def.format.video.nStride,
+ def.format.video.nSliceHeight,
def.format.video.eColorFormat);
#endif
#endif
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index f4fb556..ea04288 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -50,6 +50,9 @@ AudioPlayer::AudioPlayer(
mFirstBufferResult(OK),
mFirstBuffer(NULL),
mAudioSink(audioSink),
+#ifdef QCOM_HARDWARE
+ mSourcePaused(false),
+#endif
mObserver(observer) {
}
@@ -70,6 +73,9 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
status_t err;
if (!sourceAlreadyStarted) {
+#ifdef QCOM_HARDWARE
+ mSourcePaused = false;
+#endif
err = mSource->start();
if (err != OK) {
@@ -189,11 +195,23 @@ void AudioPlayer::pause(bool playPendingSamples) {
mAudioTrack->pause();
}
}
+#ifdef QCOM_HARDWARE
+ CHECK(mSource != NULL);
+ if (mSource->pause() == OK) {
+ mSourcePaused = true;
+ }
+#endif
}
void AudioPlayer::resume() {
CHECK(mStarted);
-
+#ifdef QCOM_HARDWARE
+ CHECK(mSource != NULL);
+ if (mSourcePaused == true) {
+ mSourcePaused = false;
+ mSource->start();
+ }
+#endif
if (mAudioSink.get() != NULL) {
mAudioSink->start();
} else {
@@ -228,7 +246,9 @@ void AudioPlayer::reset() {
mInputBuffer->release();
mInputBuffer = NULL;
}
-
+#ifdef QCOM_HARDWARE
+ mSourcePaused = false;
+#endif
mSource->stop();
// The following hack is necessary to ensure that the OMX
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 1ea524a..b4c0524 100755
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -1840,7 +1840,7 @@ status_t MPEG4Writer::Track::threadEntry() {
int32_t sampleCount = 1; // Sample count in the current stts table entry
int64_t currCttsDurTicks = 0; // Timescale based ticks
int64_t lastCttsDurTicks = 0; // Timescale based ticks
- int32_t cttsSampleCount = 1; // Sample count in the current ctts table entry
+ int32_t cttsSampleCount = 0; // Sample count in the current ctts table entry
uint32_t previousSampleSize = 0; // Size of the previous sample
int64_t previousPausedDurationUs = 0;
int64_t timestampUs = 0;
@@ -1944,10 +1944,14 @@ status_t MPEG4Writer::Track::threadEntry() {
if (mOwner->exceedsFileSizeLimit()) {
mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
+ copy->release();
+ copy = NULL;
break;
}
if (mOwner->exceedsFileDurationLimit()) {
mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
+ copy->release();
+ copy = NULL;
break;
}
@@ -1959,7 +1963,7 @@ status_t MPEG4Writer::Track::threadEntry() {
#ifdef QCOM_HARDWARE
if(!mIsAudio) {
int32_t frameRate, hfr, multiple;
- bool success = mMeta->findInt32(kKeySampleRate, &frameRate);
+ bool success = mMeta->findInt32(kKeyFrameRate, &frameRate);
CHECK(success);
success = mMeta->findInt32(kKeyHFR, &hfr);
if (!success) {
@@ -2000,6 +2004,17 @@ status_t MPEG4Writer::Track::threadEntry() {
*/
int64_t decodingTimeUs;
CHECK(meta_data->findInt64(kKeyDecodingTime, &decodingTimeUs));
+#ifdef QCOM_HARDWARE
+ {
+ int32_t frameRate, hfr, multiple;
+ bool success = mMeta->findInt32(kKeyHFR, &hfr);
+ CHECK(success);
+ success = mMeta->findInt32(kKeyFrameRate, &frameRate);
+ CHECK(success);
+ multiple = hfr?(hfr/frameRate):1;
+ decodingTimeUs = multiple * decodingTimeUs;
+ }
+#endif
decodingTimeUs -= previousPausedDurationUs;
int64_t timeUs = decodingTimeUs;
cttsDeltaTimeUs = timestampUs - decodingTimeUs;
@@ -2045,18 +2060,23 @@ status_t MPEG4Writer::Track::threadEntry() {
++sampleCount;
}
- if (!mIsAudio) {
- currCttsDurTicks =
- ((cttsDeltaTimeUs * mTimeScale + 500000LL) / 1000000LL -
- (lastCttsTimeUs * mTimeScale + 500000LL) / 1000000LL);
- if (currCttsDurTicks != lastCttsDurTicks) {
- addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
- cttsSampleCount = 1;
- } else {
- ++cttsSampleCount;
- }
+ }
+
+ if (!mIsAudio && hasBFrames && (mNumSamples >= 2)) {
+ currCttsDurTicks = (cttsDeltaTimeUs * mTimeScale) / 1000000LL;
+ ++cttsSampleCount;
+ if (currCttsDurTicks != lastCttsDurTicks) {
+ LOGV("currCttsDurTicks (%lld) != lastCttsDurTicks (%lld) (%d), add one",
+ currCttsDurTicks, lastCttsDurTicks, cttsSampleCount);
+ addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
+ cttsSampleCount = 0;
}
+
+ lastCttsDurTicks = currCttsDurTicks;
+ lastCttsTimeUs = cttsDeltaTimeUs;
}
+
+
if (mSamplesHaveSameSize) {
if (mNumSamples >= 2 && previousSampleSize != sampleSize) {
mSamplesHaveSameSize = false;
@@ -2069,11 +2089,6 @@ status_t MPEG4Writer::Track::threadEntry() {
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
- if (!mIsAudio) {
- lastCttsDurTicks = currCttsDurTicks;
- lastCttsTimeUs = cttsDeltaTimeUs;
- }
-
if (isSync != 0) {
addOneStssTableEntry(mNumSamples);
}
@@ -2157,7 +2172,12 @@ status_t MPEG4Writer::Track::threadEntry() {
addOneSttsTableEntry(sampleCount, lastDurationTicks);
}
- addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
+ if (!mIsAudio && hasBFrames) {
+ LOGV("Add ctts for last sample count = %d, ctts value = %lld", cttsSampleCount,
+ lastCttsDurTicks);
+ addOneCttsTableEntry(cttsSampleCount, lastCttsDurTicks);
+ }
+
mTrackDurationUs += lastDurationUs;
mReachedEOS = true;
@@ -2751,7 +2771,7 @@ void MPEG4Writer::Track::writeCttsBox() {
mOwner->beginBox("ctts");
if (mHasNegativeCttsDeltaDuration) {
- mOwner->writeInt32(0x00010000); // version=1, flags=0
+ mOwner->writeInt32(0x01000000); // version=1 (1 byte), flags=0 (3 bytes)
} else {
mOwner->writeInt32(0); // version=0, flags=0
}
@@ -2764,6 +2784,7 @@ void MPEG4Writer::Track::writeCttsBox() {
mOwner->writeInt32(it->sampleDuration);
totalCount += it->sampleCount;
}
+ LOGV("totalCount = %lld, mNumSamples = %d", totalCount, mNumSamples);
CHECK(totalCount == mNumSamples);
mOwner->endBox(); // ctts
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 5937249..c7e15c7 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -594,6 +594,11 @@ sp<MediaSource> OMXCodec::Create(
&& requiresSecureBuffers) {
flags |= kIgnoreCodecSpecificData;
flags |= kUseSecureInputBuffers;
+ flags |= kEnableGrallocUsageProtected;
+ }
+ else
+ {
+ flags &= ~kEnableGrallocUsageProtected;
}
const char *mime;
@@ -726,15 +731,16 @@ status_t OMXCodec::parseAVCCodecSpecificData(
size_t numSeqParameterSets = ptr[5] & 31;
#ifdef QCOM_HARDWARE
uint16_t spsSize = (((uint16_t)ptr[6]) << 8)
- + (uint16_t)(ptr[7]);
- CODEC_LOGV(" numSeqParameterSets = %d , spsSize = %d",numSeqParameterSets,spsSize);
+ + (uint16_t)(ptr[7]);
+ CODEC_LOGV("numSeqParameterSets = %d , spsSize = %d",
+ numSeqParameterSets,spsSize);
SpsInfo info;
- if ( parseSps( spsSize, ptr + 9, &info ) == OK ) {
+ if (parseSps(spsSize, ptr + 9, &info) == OK) {
mSPSParsed = true;
CODEC_LOGV("SPS parsed");
if (info.mInterlaced) {
mInterlaceFormatDetected = true;
- meta->setInt32(kKeyUseArbitraryMode, 1);
+ mUseArbitraryMode = true;
CODEC_LOGI("Interlace format detected");
} else {
CODEC_LOGI("Non-Interlaced format detected");
@@ -809,6 +815,15 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
uint32_t type;
const void *data;
size_t size;
+#ifdef QCOM_HARDWARE
+ if (!strncasecmp(mMIME, "video/", 6)) {
+ int32_t arbitraryMode = 1;
+ bool success = meta->findInt32(kKeyUseArbitraryMode, &arbitraryMode);
+ if (success) {
+ mUseArbitraryMode = arbitraryMode ? true : false;
+ }
+ }
+#endif
if (meta->findData(kKeyESDS, &type, &data, &size)) {
ESDS esds((const char *)data, size);
CHECK_EQ(esds.InitCheck(), (status_t)OK);
@@ -846,6 +861,7 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
}
if(!strcmp(mComponentName, "OMX.google.h264.decoder")
&& (profile != kAVCProfileBaseline)) {
+ LOGE("%s does not support profiles > kAVCProfileBaseline", mComponentName);
// The profile is unsupported by the decoder
return ERROR_UNSUPPORTED;
}
@@ -985,9 +1001,7 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
}
#ifdef QCOM_HARDWARE
- int32_t useArbitraryMode = 0;
- success = meta->findInt32(kKeyUseArbitraryMode, &useArbitraryMode);
- if (success && useArbitraryMode == 1) {
+ if (mUseArbitraryMode) {
CODEC_LOGI("Decoder should be in arbitrary mode");
// Is it required to set OMX_QCOM_FramePacking_Arbitrary ??
}
@@ -1041,7 +1055,27 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
}
initOutputFormat(meta);
-
+#ifdef QCOM_HARDWARE
+ if ((!strncasecmp(mMIME, "audio/", 6)) && (!strncmp(mComponentName, "OMX.qcom.", 9))) {
+ OMX_PARAM_SUSPENSIONPOLICYTYPE suspensionPolicy;
+ // Suspension policy for the OMX component to honor the Power collapse (TCXO shutdown)
+ // Whenever there is a power collapse, OMX component releases the hardware
+ // resources and hence enabling TCXO shutdown, reducing power consumption.
+ // Return value is ignored, since this is not mandated for all the OMX components.
+ memset(&suspensionPolicy,0,sizeof(suspensionPolicy));
+ suspensionPolicy.ePolicy = OMX_SuspensionEnabled;
+
+ status_t err = mOMX->setParameter(mNode,
+ OMX_IndexParamSuspensionPolicy, &suspensionPolicy, sizeof(suspensionPolicy));
+ if ( err != OMX_ErrorNone ) {
+ CODEC_LOGV("OMXCodec::configureCodec Problem setting suspension"
+ "policy parameters in output port ");
+ } else {
+ CODEC_LOGV("OMXCodec::configureCodec SUCCESS setting suspension "
+ "policy parameters in output port ");
+ }
+ }
+#endif
if ((mFlags & kClientNeedsFramebuffer)
&& !strncmp(mComponentName, "OMX.SEC.", 8)) {
OMX_INDEXTYPE index;
@@ -1293,14 +1327,7 @@ void OMXCodec::setVideoInputFormat(
int32_t width, height, frameRate, bitRate, stride, sliceHeight;
#ifdef QCOM_HARDWARE
- int32_t hfr = 0;
-
- char value[PROPERTY_VALUE_MAX];
- if ( property_get("encoder.video.bitrate", value, 0) > 0 && atoi(value) > 0){
- LOGV("Setting bit rate to %d", atoi(value));
- meta->setInt32(kKeyBitRate, atoi(value));
- }
-
+ int32_t hfr = 0, hfrRatio = 0;
#endif
bool success = meta->findInt32(kKeyWidth, &width);
success = success && meta->findInt32(kKeyHeight, &height);
@@ -1315,7 +1342,9 @@ void OMXCodec::setVideoInputFormat(
CHECK(stride != 0);
#ifdef QCOM_HARDWARE
+ hfrRatio = hfr/frameRate;
frameRate = hfr?hfr:frameRate;
+ bitRate = hfr ? (hfrRatio*bitRate) : bitRate;
#endif
OMX_VIDEO_CODINGTYPE compressionFormat = OMX_VIDEO_CodingUnused;
@@ -1561,7 +1590,7 @@ status_t OMXCodec::getVideoProfileLevel(
status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
int32_t iFramesInterval, frameRate, bitRate;
#ifdef QCOM_HARDWARE
- int32_t hfr = 0;
+ int32_t hfr = 0, hfrRatio = 0;
#endif
bool success = meta->findInt32(kKeyBitRate, &bitRate);
success = success && meta->findInt32(kKeyFrameRate, &frameRate);
@@ -1579,12 +1608,15 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
CHECK_EQ(err, (status_t)OK);
#ifdef QCOM_HARDWARE
+ hfrRatio = hfr ? hfr/frameRate : 1;
+
frameRate = hfr ? hfr : frameRate;
+ bitRate = hfr ? (hfrRatio*bitRate) : bitRate;
+ h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate / hfrRatio);
#endif
h263type.nAllowedPictureTypes =
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
- h263type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
if (h263type.nPFrames == 0) {
h263type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
}
@@ -1617,7 +1649,7 @@ status_t OMXCodec::setupH263EncoderParameters(const sp<MetaData>& meta) {
status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
int32_t iFramesInterval, frameRate, bitRate;
#ifdef QCOM_HARDWARE
- int32_t hfr = 0;
+ int32_t hfr = 0, hfrRatio = 0;
#endif
bool success = meta->findInt32(kKeyBitRate, &bitRate);
success = success && meta->findInt32(kKeyFrameRate, &frameRate);
@@ -1642,9 +1674,13 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
OMX_VIDEO_PictureTypeI | OMX_VIDEO_PictureTypeP;
#ifdef QCOM_HARDWARE
+ hfrRatio = hfr ? hfr/frameRate : 1;
frameRate = hfr ? hfr : frameRate;
-#endif
+ bitRate = hfr ? (hfrRatio*bitRate) : bitRate;
+ mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate / hfrRatio);
+#else
mpeg4type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+#endif
if (mpeg4type.nPFrames == 0) {
mpeg4type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
}
@@ -1669,6 +1705,8 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
if (mpeg4type.eProfile > OMX_VIDEO_MPEG4ProfileSimple) {
mpeg4type.nAllowedPictureTypes |= OMX_VIDEO_PictureTypeB;
mpeg4type.nBFrames = 1;
+ mpeg4type.nPFrames = mpeg4type.nPFrames / 2;
+ mNumBFrames = 1;
}
#endif
@@ -1685,7 +1723,7 @@ status_t OMXCodec::setupMPEG4EncoderParameters(const sp<MetaData>& meta) {
status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
int32_t iFramesInterval, frameRate, bitRate;
#ifdef QCOM_HARDWARE
- int32_t hfr = 0;
+ int32_t hfr = 0, hfrRatio = 0;
#endif
bool success = meta->findInt32(kKeyBitRate, &bitRate);
success = success && meta->findInt32(kKeyFrameRate, &frameRate);
@@ -1717,7 +1755,9 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
h264type.eLevel = static_cast<OMX_VIDEO_AVCLEVELTYPE>(profileLevel.mLevel);
#ifdef QCOM_HARDWARE
+ hfrRatio = hfr ? hfr/frameRate : 1;
frameRate = hfr ? hfr : frameRate;
+ bitRate = hfr ? (hfrRatio*bitRate) : bitRate;
#endif
// FIXME:
@@ -1731,7 +1771,11 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
h264type.bUseHadamard = OMX_TRUE;
h264type.nRefFrames = 1;
h264type.nBFrames = 0;
+#ifdef QCOM_HARDWARE
+ h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate / hfrRatio);
+#else
h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+#endif
if (h264type.nPFrames == 0) {
h264type.nAllowedPictureTypes = OMX_VIDEO_PictureTypeI;
}
@@ -1747,8 +1791,10 @@ status_t OMXCodec::setupAVCEncoderParameters(const sp<MetaData>& meta) {
#ifdef QCOM_HARDWARE
if (h264type.eProfile > OMX_VIDEO_AVCProfileBaseline) {
- h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate);
+ h264type.nPFrames = setPFramesSpacing(iFramesInterval, frameRate / hfrRatio);
h264type.nBFrames = 1;
+ h264type.nPFrames = h264type.nPFrames / 2;
+ mNumBFrames = 1;
}
#endif
@@ -1966,6 +2012,8 @@ OMXCodec::OMXCodec(
mInterlaceFormatDetected(false),
mSPSParsed(false),
mThumbnailMode(false),
+ mNumBFrames(0),
+ mUseArbitraryMode(true),
#endif
mNativeWindow(
(!strncmp(componentName, "OMX.google.", 11)
@@ -2128,6 +2176,10 @@ bool OMXCodec::isIntermediateState(State state) {
|| state == IDLE_TO_EXECUTING
|| state == EXECUTING_TO_IDLE
|| state == IDLE_TO_LOADED
+#ifdef QCOM_HARDWARE
+ || state == PAUSING
+ || state == FLUSHING
+#endif
|| state == RECONFIGURING;
}
@@ -2241,7 +2293,7 @@ status_t OMXCodec::allocateBuffersOnPort(OMX_U32 portIndex) {
}
if (err != OK) {
- LOGE("allocate_buffer_with_backup failed");
+ CODEC_LOGE("allocate_buffer_with_backup failed");
return err;
}
@@ -2408,8 +2460,8 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
android_native_rect_t crop;
crop.left = left;
crop.top = top;
- crop.right = right;
- crop.bottom = bottom;
+ crop.right = right + 1;
+ crop.bottom = bottom + 1;
err = native_window_set_crop(mNativeWindow.get(), &crop);
if (err != OK) {
@@ -2520,8 +2572,8 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
break;
}
-#ifdef QCOM_CAMERA
- private_handle_t *handle = (private_handle_t *)buf->handle;
+#ifdef QCOM_HARDWARE
+ private_handle_t *handle = (private_handle_t *)buf->handle;
if(!handle) {
LOGE("Native Buffer handle is NULL");
break;
@@ -2567,9 +2619,13 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
cancelEnd = def.nBufferCountActual;
}
- for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
- BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
- cancelBufferToNativeWindow(info);
+ if (err != 0) {
+ freeBuffersOnPort(kPortIndexOutput);
+ } else {
+ for (OMX_U32 i = cancelStart; i < cancelEnd; i++) {
+ BufferInfo *info = &mPortBuffers[kPortIndexOutput].editItemAt(i);
+ cancelBufferToNativeWindow(info);
+ }
}
return err;
@@ -2802,7 +2858,7 @@ int64_t OMXCodec::retrieveDecodingTimeUs(bool isCodecSpecific) {
}
void OMXCodec::on_message(const omx_message &msg) {
- if (mState == ERROR) {
+ if (mState == ERROR && !strncmp(mComponentName, "OMX.google.", 11)) {
LOGW("Dropping OMX message - we're in ERROR state.");
return;
}
@@ -2992,6 +3048,9 @@ void OMXCodec::on_message(const omx_message &msg) {
if (mIsEncoder) {
int64_t decodingTimeUs = retrieveDecodingTimeUs(isCodecSpecific);
+ CODEC_LOGV("kkeyTime = %lld, kKeyDecodingTime = %lld, ctts = %lld",
+ msg.u.extended_buffer_data.timestamp, decodingTimeUs,
+ msg.u.extended_buffer_data.timestamp - decodingTimeUs);
buffer->meta_data()->setInt64(kKeyDecodingTime, decodingTimeUs);
}
@@ -3413,14 +3472,33 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) {
mPortStatus[kPortIndexInput] = ENABLED;
mPortStatus[kPortIndexOutput] = ENABLED;
- if ((mFlags & kEnableGrallocUsageProtected) &&
- mNativeWindow != NULL) {
- // We push enough 1x1 blank buffers to ensure that one of
- // them has made it to the display. This allows the OMX
- // component teardown to zero out any protected buffers
- // without the risk of scanning out one of those buffers.
- pushBlankBuffersToNativeWindow();
+#ifdef QCOM_HARDWARE
+ if (mNativeWindow != NULL) {
+ /*
+ * reset buffer size field with SurfaceTexture
+ * back to 0. This will ensure proper size
+ * buffers are allocated if the same SurfaceTexture
+ * is re-used in a different decode session
+ */
+ int err =
+ mNativeWindow.get()->perform(mNativeWindow.get(),
+ NATIVE_WINDOW_SET_BUFFERS_SIZE,
+ 0);
+ if (err != 0) {
+ LOGE("set_buffers_size failed: %s (%d)", strerror(-err),
+ -err);
+ }
+#endif
+ if (mFlags & kEnableGrallocUsageProtected) {
+ // We push enough 1x1 blank buffers to ensure that one of
+ // them has made it to the display. This allows the OMX
+ // component teardown to zero out any protected buffers
+ // without the risk of scanning out one of those buffers.
+ pushBlankBuffersToNativeWindow();
+ }
+#ifdef QCOM_HARDWARE
}
+#endif
setState(IDLE_TO_LOADED);
}
@@ -3457,7 +3535,17 @@ void OMXCodec::onStateChange(OMX_STATETYPE newState) {
setState(LOADED);
break;
}
+#ifdef QCOM_HARDWARE
+ case OMX_StatePause:
+ {
+ CODEC_LOGV("Now paused.");
+ CHECK_EQ(mState, PAUSING);
+
+ setState(PAUSED);
+ break;
+ }
+#endif
case OMX_StateInvalid:
{
setState(ERROR);
@@ -3585,8 +3673,11 @@ void OMXCodec::onPortSettingsChanged(OMX_U32 portIndex) {
bool OMXCodec::flushPortAsync(OMX_U32 portIndex) {
CHECK(mState == EXECUTING || mState == RECONFIGURING
+#ifdef QCOM_HARDWARE
+ || mState == EXECUTING_TO_IDLE || mState == FLUSHING);
+#else
|| mState == EXECUTING_TO_IDLE);
-
+#endif
#ifdef QCOM_HARDWARE
if ( portIndex == -1 ) {
mPortStatus[kPortIndexInput] = SHUTTING_DOWN;
@@ -3644,7 +3735,11 @@ status_t OMXCodec::enablePortAsync(OMX_U32 portIndex) {
}
void OMXCodec::fillOutputBuffers() {
+#ifdef QCOM_HARDWARE
+ CHECK(mState == EXECUTING || mState == FLUSHING);
+#else
CHECK_EQ((int)mState, (int)EXECUTING);
+#endif
// This is a workaround for some decoders not properly reporting
// end-of-output-stream. If we own all input buffers and also own
@@ -3682,7 +3777,11 @@ void OMXCodec::fillOutputBuffers() {
}
void OMXCodec::drainInputBuffers() {
+#ifdef QCOM_HARDWARE
+ CHECK(mState == EXECUTING || mState == RECONFIGURING || mState == FLUSHING);
+#else
CHECK(mState == EXECUTING || mState == RECONFIGURING);
+#endif
if (mFlags & kUseSecureInputBuffers) {
Vector<BufferInfo> *buffers = &mPortBuffers[kPortIndexInput];
@@ -3714,6 +3813,9 @@ void OMXCodec::drainInputBuffers() {
}
if (mFlags & kOnlySubmitOneInputBufferAtOneTime) {
+#ifdef QCOM_HARDWARE
+ if (i == mNumBFrames)
+#endif
break;
}
}
@@ -3978,6 +4080,7 @@ bool OMXCodec::drainInputBuffer(BufferInfo *info) {
CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &lastBufferTimeUs));
CHECK(lastBufferTimeUs >= 0);
if (mIsEncoder) {
+ CODEC_LOGV("pushing %lld to mDecodingTimeList", lastBufferTimeUs);
mDecodingTimeList.push_back(lastBufferTimeUs);
}
@@ -4680,8 +4783,32 @@ void OMXCodec::clearCodecSpecificData() {
}
status_t OMXCodec::start(MetaData *meta) {
+ CODEC_LOGV("OMXCodec::start ");
Mutex::Autolock autoLock(mLock);
+#ifdef QCOM_HARDWARE
+ if(mPaused) {
+ if (!strncmp(mComponentName, "OMX.qcom.", 9)) {
+ while (isIntermediateState(mState)) {
+ mAsyncCompletion.wait(mLock);
+ }
+ CHECK_EQ(mState, (status_t)PAUSED);
+ status_t err = mOMX->sendCommand(mNode,
+ OMX_CommandStateSet, OMX_StateExecuting);
+ CHECK_EQ(err, (status_t)OK);
+ setState(IDLE_TO_EXECUTING);
+ mPaused = false;
+ while (mState != EXECUTING && mState != ERROR) {
+ mAsyncCompletion.wait(mLock);
+ }
+ drainInputBuffers();
+ return mState == ERROR ? UNKNOWN_ERROR : OK;
+ } else { // SW Codec
+ mPaused = false;
+ return OK;
+ }
+ }
+#endif
if (mState != LOADED) {
return UNKNOWN_ERROR;
}
@@ -4753,7 +4880,8 @@ status_t OMXCodec::stop() {
*/
bool canFree = true;
- if (!strncmp(mComponentName, "OMX.qcom.video.decoder.", 23)) {
+ if (!strncmp(mComponentName, "OMX.qcom.video.decoder.", 23) ||
+ !strncmp(mComponentName, "OMX.qcom.video.encoder.", 23)) {
if (state == OMX_StateInvalid) {
canFree = true;
}
@@ -4792,7 +4920,9 @@ status_t OMXCodec::stop() {
// else fall through to the idling code
isError = true;
}
-
+#ifdef QCOM_HARDWARE
+ case PAUSED:
+#endif
case EXECUTING:
{
setState(EXECUTING_TO_IDLE);
@@ -4939,6 +5069,7 @@ status_t OMXCodec::read(
CHECK_EQ((int)mState, (int)EXECUTING);
#ifdef QCOM_HARDWARE
+ setState(FLUSHING);
//DSP supports flushing of ports simultaneously. Flushing individual port is not supported.
if(mQuirks & kRequiresGlobalFlush) {
@@ -4979,7 +5110,12 @@ status_t OMXCodec::read(
if (mState == ERROR) {
return UNKNOWN_ERROR;
}
-
+#ifdef QCOM_HARDWARE
+ if(seeking) {
+ CHECK_EQ((int)mState, (int)FLUSHING);
+ setState(EXECUTING);
+ }
+#endif
if (mFilledBuffers.empty()) {
return mSignalledEOS ? mFinalStatus : ERROR_END_OF_STREAM;
}
@@ -5658,12 +5794,12 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
int32_t frameRate = 0, hfr = 0;
success = inputFormat->findInt32(kKeyHFR, &hfr);
- success = inputFormat->findInt32(kKeySampleRate, &frameRate);
+ success = inputFormat->findInt32(kKeyFrameRate, &frameRate);
mOutputFormat->setInt32(kKeyWidth, width);
mOutputFormat->setInt32(kKeyHeight, height);
mOutputFormat->setInt32(kKeyHFR, hfr);
- mOutputFormat->setInt32(kKeySampleRate, frameRate);
+ mOutputFormat->setInt32(kKeyFrameRate, frameRate);
#endif
}
break;
@@ -5686,13 +5822,37 @@ void OMXCodec::initOutputFormat(const sp<MetaData> &inputFormat) {
}
status_t OMXCodec::pause() {
- Mutex::Autolock autoLock(mLock);
+ CODEC_LOGV("pause mState=%d", mState);
- mPaused = true;
+ Mutex::Autolock autoLock(mLock);
+#ifdef QCOM_HARDWARE
+ if (mState != EXECUTING) {
+ return UNKNOWN_ERROR;
+ }
+
+ while (isIntermediateState(mState)) {
+ mAsyncCompletion.wait(mLock);
+ }
+ if (!strncmp(mComponentName, "OMX.qcom.", 9)) {
+ status_t err = mOMX->sendCommand(mNode,
+ OMX_CommandStateSet, OMX_StatePause);
+ CHECK_EQ(err, (status_t)OK);
+ setState(PAUSING);
+
+ mPaused = true;
+ while (mState != PAUSED && mState != ERROR) {
+ mAsyncCompletion.wait(mLock);
+ }
+ return mState == ERROR ? UNKNOWN_ERROR : OK;
+ } else {
+#endif
+ mPaused = true;
+ return OK;
+#ifdef QCOM_HARDWARE
+ }
+#endif
- return OK;
}
-
#ifdef QCOM_HARDWARE
void OMXCodec::parseFlags(uint32_t flags) {
//TODO - uncomment if needed
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index c7b00b1..85c2ccd 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -307,7 +307,7 @@ status_t SampleIterator::findSampleTime(
*time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
- *time += mTable->getCompositionTimeOffset(sampleIndex);
+ *time = (int64_t)(*time) + (int32_t)mTable->getCompositionTimeOffset(sampleIndex);
return OK;
}
diff --git a/media/libstagefright/SampleTable.cpp b/media/libstagefright/SampleTable.cpp
index 046e9cb..d664078 100644
--- a/media/libstagefright/SampleTable.cpp
+++ b/media/libstagefright/SampleTable.cpp
@@ -360,8 +360,9 @@ status_t SampleTable::setCompositionTimeToSampleParams(
return ERROR_IO;
}
- if (U32_AT(header) != 0) {
- // Expected version = 0, flags = 0.
+ if (U32_AT(header) != 0 &&
+ U32_AT(header) != 0x01000000) { //version 1 (1 byte), flags (3 bytes)
+ // Expected version = 0 or 1, flags = 0.
return ERROR_MALFORMED;
}
@@ -502,7 +503,7 @@ void SampleTable::buildSampleEntriesTable() {
mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
- uint32_t compTimeDelta =
+ int32_t compTimeDelta = (int32_t)
mCompositionDeltaLookup->getCompositionTimeOffset(
sampleIndex);
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 3715fe9..b820b6a 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -251,10 +251,12 @@ status_t OMX::allocateNode(
status_t OMX::freeNode(node_id node) {
OMXNodeInstance *instance = findInstance(node);
-
- ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
- CHECK(index >= 0);
- mLiveNodes.removeItemsAt(index);
+ {
+ Mutex::Autolock autoLock(mLock);
+ ssize_t index = mLiveNodes.indexOfKey(instance->observer()->asBinder());
+ CHECK(index >= 0);
+ mLiveNodes.removeItemsAt(index);
+ }
instance->observer()->asBinder()->unlinkToDeath(this);
@@ -262,7 +264,7 @@ status_t OMX::freeNode(node_id node) {
{
Mutex::Autolock autoLock(mLock);
- index = mDispatchers.indexOfKey(node);
+ ssize_t index = mDispatchers.indexOfKey(node);
CHECK(index >= 0);
mDispatchers.removeItemsAt(index);
}