summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorRicardo Cerqueira <ricardo@cyngn.com>2015-11-05 01:41:03 +0000
committerRicardo Cerqueira <ricardo@cyngn.com>2015-11-05 15:12:16 +0000
commitd5d618443b0166393389b422892ec033825e57ce (patch)
treead66ae383f72046ed6805b570450ae78709df3aa /media
parent2848080cc0182847cb2130cba1a59282db88bce0 (diff)
parentf733ab6e153fb89f045bfb1cb2746bd58399a0c2 (diff)
downloadframeworks_av-d5d618443b0166393389b422892ec033825e57ce.zip
frameworks_av-d5d618443b0166393389b422892ec033825e57ce.tar.gz
frameworks_av-d5d618443b0166393389b422892ec033825e57ce.tar.bz2
Merge tag 'android-6.0.0_r26' into cm-13.0
Android 6.0.0 release 26 Change-Id: I8a57007bf6efcd8b95c3cebf5e0444345bdd4cda
Diffstat (limited to 'media')
-rw-r--r--media/img_utils/include/img_utils/DngUtils.h31
-rw-r--r--media/img_utils/src/DngUtils.cpp85
-rw-r--r--media/libavextensions/stagefright/AVFactory.cpp2
-rw-r--r--media/libmedia/AudioTrack.cpp15
-rw-r--r--media/libmedia/ICrypto.cpp3
-rw-r--r--media/libmedia/IOMX.cpp6
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp38
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h1
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp4
-rw-r--r--media/libstagefright/AudioSource.cpp4
-rw-r--r--media/libstagefright/AwesomePlayer.cpp4
-rw-r--r--media/libstagefright/DataSource.cpp2
-rwxr-xr-xmedia/libstagefright/MPEG4Extractor.cpp17
-rw-r--r--media/libstagefright/MediaCodec.cpp7
-rw-r--r--media/libstagefright/NuCachedSource2.cpp15
-rw-r--r--media/libstagefright/Utils.cpp8
-rw-r--r--media/libstagefright/codecs/amrnb/dec/Android.mk2
-rw-r--r--media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp5
-rw-r--r--media/libstagefright/codecs/avcdec/SoftAVCDec.cpp364
-rw-r--r--media/libstagefright/codecs/avcdec/SoftAVCDec.h16
-rw-r--r--media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp5
-rw-r--r--media/libstagefright/data/media_codecs_google_tv.xml29
-rw-r--r--[-rwxr-xr-x]media/libstagefright/data/media_codecs_google_video.xml9
-rw-r--r--media/libstagefright/foundation/AMessage.cpp28
-rw-r--r--media/libstagefright/id3/ID3.cpp21
-rw-r--r--media/libstagefright/include/NuCachedSource2.h7
-rw-r--r--media/libstagefright/include/OMX.h2
-rw-r--r--media/libstagefright/include/OMXNodeInstance.h5
-rw-r--r--media/libstagefright/omx/OMX.cpp5
-rw-r--r--media/libstagefright/omx/OMXNodeInstance.cpp1
-rw-r--r--media/utils/Android.mk2
-rw-r--r--media/utils/ISchedulingPolicyService.cpp80
-rw-r--r--media/utils/ISchedulingPolicyService.h45
-rw-r--r--media/utils/SchedulingPolicyService.cpp62
-rw-r--r--media/utils/include/mediautils/SchedulingPolicyService.h31
35 files changed, 611 insertions, 350 deletions
diff --git a/media/img_utils/include/img_utils/DngUtils.h b/media/img_utils/include/img_utils/DngUtils.h
index 3dcedc5..1d8df9c 100644
--- a/media/img_utils/include/img_utils/DngUtils.h
+++ b/media/img_utils/include/img_utils/DngUtils.h
@@ -138,6 +138,34 @@ class ANDROID_API OpcodeListBuilder : public LightRefBase<OpcodeListBuilder> {
double opticalCenterY,
const double* kCoeffs);
+
+ /**
+ * Add FixBadPixelsList opcode for the given metadata parameters.
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ virtual status_t addBadPixelListForMetadata(const uint32_t* hotPixels,
+ uint32_t xyPairCount,
+ uint32_t colorFilterArrangement);
+
+ /**
+ * Add FixBadPixelsList opcode.
+ *
+ * bayerPhase - 0=top-left of image is red, 1=top-left of image is green pixel in red row,
+ * 2=top-left of image is green pixel in blue row, 3=top-left of image is
+ * blue.
+ * badPointCount - number of (x,y) pairs of bad pixels are given in badPointRowColPairs.
+ * badRectCount - number of (top, left, bottom, right) tuples are given in
+ * badRectTopLeftBottomRightTuples
+ *
+ * Returns OK on success, or a negative error code.
+ */
+ virtual status_t addBadPixelList(uint32_t bayerPhase,
+ uint32_t badPointCount,
+ uint32_t badRectCount,
+ const uint32_t* badPointRowColPairs,
+ const uint32_t* badRectTopLeftBottomRightTuples);
+
// TODO: Add other Opcode methods
protected:
static const uint32_t FLAG_OPTIONAL = 0x1u;
@@ -146,6 +174,7 @@ class ANDROID_API OpcodeListBuilder : public LightRefBase<OpcodeListBuilder> {
// Opcode IDs
enum {
WARP_RECTILINEAR_ID = 1,
+ FIX_BAD_PIXELS_LIST = 5,
GAIN_MAP_ID = 9,
};
@@ -161,6 +190,8 @@ class ANDROID_API OpcodeListBuilder : public LightRefBase<OpcodeListBuilder> {
ByteArrayOutput mOpList;
EndianOutput mEndianOut;
+ status_t addOpcodePreamble(uint32_t opcodeId);
+
};
} /*namespace img_utils*/
diff --git a/media/img_utils/src/DngUtils.cpp b/media/img_utils/src/DngUtils.cpp
index b213403..9473dce 100644
--- a/media/img_utils/src/DngUtils.cpp
+++ b/media/img_utils/src/DngUtils.cpp
@@ -224,13 +224,7 @@ status_t OpcodeListBuilder::addGainMap(uint32_t top,
uint32_t mapPlanes,
const float* mapGains) {
- uint32_t opcodeId = GAIN_MAP_ID;
-
- status_t err = mEndianOut.write(&opcodeId, 0, 1);
- if (err != OK) return err;
-
- uint8_t version[] = {1, 3, 0, 0};
- err = mEndianOut.write(version, 0, NELEMS(version));
+ status_t err = addOpcodePreamble(GAIN_MAP_ID);
if (err != OK) return err;
// Allow this opcode to be skipped if not supported
@@ -334,13 +328,7 @@ status_t OpcodeListBuilder::addWarpRectilinear(uint32_t numPlanes,
double opticalCenterY,
const double* kCoeffs) {
- uint32_t opcodeId = WARP_RECTILINEAR_ID;
-
- status_t err = mEndianOut.write(&opcodeId, 0, 1);
- if (err != OK) return err;
-
- uint8_t version[] = {1, 3, 0, 0};
- err = mEndianOut.write(version, 0, NELEMS(version));
+ status_t err = addOpcodePreamble(WARP_RECTILINEAR_ID);
if (err != OK) return err;
// Allow this opcode to be skipped if not supported
@@ -373,5 +361,74 @@ status_t OpcodeListBuilder::addWarpRectilinear(uint32_t numPlanes,
return OK;
}
+status_t OpcodeListBuilder::addBadPixelListForMetadata(const uint32_t* hotPixels,
+ uint32_t xyPairCount,
+ uint32_t colorFilterArrangement) {
+ if (colorFilterArrangement > 3) {
+ ALOGE("%s: Unknown color filter arrangement %" PRIu32, __FUNCTION__,
+ colorFilterArrangement);
+ return BAD_VALUE;
+ }
+
+ return addBadPixelList(colorFilterArrangement, xyPairCount, 0, hotPixels, nullptr);
+}
+
+status_t OpcodeListBuilder::addBadPixelList(uint32_t bayerPhase,
+ uint32_t badPointCount,
+ uint32_t badRectCount,
+ const uint32_t* badPointRowColPairs,
+ const uint32_t* badRectTopLeftBottomRightTuples) {
+
+ status_t err = addOpcodePreamble(FIX_BAD_PIXELS_LIST);
+ if (err != OK) return err;
+
+ // Allow this opcode to be skipped if not supported
+ uint32_t flags = FLAG_OPTIONAL;
+
+ err = mEndianOut.write(&flags, 0, 1);
+ if (err != OK) return err;
+
+ const uint32_t NUM_NON_VARLEN_FIELDS = 3;
+ const uint32_t SIZE_OF_POINT = 2;
+ const uint32_t SIZE_OF_RECT = 4;
+
+ uint32_t totalSize = (NUM_NON_VARLEN_FIELDS + badPointCount * SIZE_OF_POINT +
+ badRectCount * SIZE_OF_RECT) * sizeof(uint32_t);
+ err = mEndianOut.write(&totalSize, 0, 1);
+ if (err != OK) return err;
+
+ err = mEndianOut.write(&bayerPhase, 0, 1);
+ if (err != OK) return err;
+
+ err = mEndianOut.write(&badPointCount, 0, 1);
+ if (err != OK) return err;
+
+ err = mEndianOut.write(&badRectCount, 0, 1);
+ if (err != OK) return err;
+
+ if (badPointCount > 0) {
+ err = mEndianOut.write(badPointRowColPairs, 0, SIZE_OF_POINT * badPointCount);
+ if (err != OK) return err;
+ }
+
+ if (badRectCount > 0) {
+ err = mEndianOut.write(badRectTopLeftBottomRightTuples, 0, SIZE_OF_RECT * badRectCount);
+ if (err != OK) return err;
+ }
+
+ mCount++;
+ return OK;
+}
+
+status_t OpcodeListBuilder::addOpcodePreamble(uint32_t opcodeId) {
+ status_t err = mEndianOut.write(&opcodeId, 0, 1);
+ if (err != OK) return err;
+
+ uint8_t version[] = {1, 3, 0, 0};
+ err = mEndianOut.write(version, 0, NELEMS(version));
+ if (err != OK) return err;
+ return OK;
+}
+
} /*namespace img_utils*/
} /*namespace android*/
diff --git a/media/libavextensions/stagefright/AVFactory.cpp b/media/libavextensions/stagefright/AVFactory.cpp
index 2a3810d..f6d5f53 100644
--- a/media/libavextensions/stagefright/AVFactory.cpp
+++ b/media/libavextensions/stagefright/AVFactory.cpp
@@ -72,7 +72,7 @@ sp<NuCachedSource2> AVFactory::createCachedSource(
const sp<DataSource> &source,
const char *cacheConfig,
bool disconnectAtHighwatermark) {
- return new NuCachedSource2(source, cacheConfig, disconnectAtHighwatermark);
+ return NuCachedSource2::Create(source, cacheConfig, disconnectAtHighwatermark);
}
MediaHTTP* AVFactory::createMediaHTTP(
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 5af70d3..946c118 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -528,6 +528,15 @@ status_t AudioTrack::start()
mTimestampStartupGlitchReported = false;
mRetrogradeMotionReported = false;
+ // If previousState == STATE_STOPPED, we reactivate markers (mMarkerPosition != 0)
+ // as the position is reset to 0. This is legacy behavior. This is not done
+ // in stop() to avoid a race condition where the last marker event is issued twice.
+ // Note: the if is technically unnecessary because previousState == STATE_FLUSHED
+ // is only for streaming tracks, and mMarkerReached is already set to false.
+ if (previousState == STATE_STOPPED) {
+ mMarkerReached = false;
+ }
+
// For offloaded tracks, we don't know if the hardware counters are really zero here,
// since the flush is asynchronous and stop may not fully drain.
// We save the time when the track is started to later verify whether
@@ -603,9 +612,9 @@ void AudioTrack::stop()
mProxy->interrupt();
mAudioTrack->stop();
- // the playback head position will reset to 0, so if a marker is set, we need
- // to activate it again
- mMarkerReached = false;
+
+ // Note: legacy handling - stop does not clear playback marker
+ // and periodic update counter, but flush does for streaming tracks.
if (mSharedBuffer != 0) {
// clear buffer position and loop count.
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index 53b105d..5d822cf 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -301,8 +301,7 @@ status_t BnCrypto::onTransact(
secureBufferId = reinterpret_cast<void *>(static_cast<uintptr_t>(data.readInt64()));
AVMediaUtils::get()->readCustomData(&data, &secureBufferId);
} else {
- dstPtr = malloc(totalSize);
- CHECK(dstPtr != NULL);
+ dstPtr = calloc(1, totalSize);
}
AString errorDetailMsg;
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index ac2e872..5356494 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -965,6 +965,12 @@ status_t BnOMX::onTransact(
node_id node = (node_id)data.readInt32();
OMX_U32 port_index = data.readInt32();
+ if (!isSecure(node) || port_index != 0 /* kPortIndexInput */) {
+ ALOGE("b/24310423");
+ reply->writeInt32(INVALID_OPERATION);
+ return NO_ERROR;
+ }
+
size_t size = data.readInt64();
buffer_id buffer;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index b034459..490a0d2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -120,6 +120,7 @@ NuPlayer::Renderer::Renderer(
mNotifyCompleteVideo(false),
mSyncQueues(false),
mPaused(false),
+ mPauseDrainAudioAllowedUs(0),
mVideoSampleReceived(false),
mVideoRenderingStarted(false),
mVideoRenderingStartGeneration(0),
@@ -652,6 +653,14 @@ void NuPlayer::Renderer::postDrainAudioQueue_l(int64_t delayUs) {
return;
}
+ // FIXME: if paused, wait until AudioTrack stop() is complete before delivering data.
+ if (mPaused) {
+ const int64_t diffUs = mPauseDrainAudioAllowedUs - ALooper::GetNowUs();
+ if (diffUs > delayUs) {
+ delayUs = diffUs;
+ }
+ }
+
mDrainAudioQueuePending = true;
sp<AMessage> msg = new AMessage(kWhatDrainAudioQueue, this);
msg->setInt32("drainGeneration", mAudioDrainGeneration);
@@ -820,6 +829,10 @@ void NuPlayer::Renderer::drainAudioQueueUntilLastEOS() {
}
bool NuPlayer::Renderer::onDrainAudioQueue() {
+ // do not drain audio during teardown as queued buffers may be invalid.
+ if (mAudioTornDown) {
+ return false;
+ }
// TODO: This call to getPosition checks if AudioTrack has been created
// in AudioSink before draining audio. If AudioTrack doesn't exist, then
// CHECKs on getPosition will fail.
@@ -899,6 +912,8 @@ bool NuPlayer::Renderer::onDrainAudioQueue() {
ALOGV("AudioSink write would block when writing %zu bytes", copy);
} else {
ALOGE("AudioSink write error(%zd) when writing %zu bytes", written, copy);
+ // This can only happen when AudioSink was opened with doNotReconnect flag set to
+ // true, in which case the NuPlayer will handle the reconnect.
notifyAudioTearDown();
}
break;
@@ -965,6 +980,10 @@ bool NuPlayer::Renderer::onDrainAudioQueue() {
int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
int32_t sampleRate = offloadingAudio() ?
mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
+ if (sampleRate == 0) {
+ ALOGE("sampleRate is 0 in %s mode", offloadingAudio() ? "offload" : "non-offload");
+ return 0;
+ }
// TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
}
@@ -1368,8 +1387,16 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
mAudioSink->flush();
// Call stop() to signal to the AudioSink to completely fill the
// internal buffer before resuming playback.
+ // FIXME: this is ignored after flush().
mAudioSink->stop();
- if (!mPaused) {
+ if (mPaused) {
+ // Race condition: if renderer is paused and audio sink is stopped,
+ // we need to make sure that the audio track buffer fully drains
+ // before delivering data.
+ // FIXME: remove this if we can detect if stop() is complete.
+ const int delayUs = 2 * 50 * 1000; // (2 full mixer thread cycles at 50ms)
+ mPauseDrainAudioAllowedUs = ALooper::GetNowUs() + delayUs;
+ } else {
mAudioSink->start();
}
mNumFramesWritten = 0;
@@ -1825,6 +1852,12 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
const uint32_t frameCount =
(unsigned long long)sampleRate * getAudioSinkPcmMsSetting() / 1000;
+ // The doNotReconnect means AudioSink will signal back and let NuPlayer to re-construct
+ // AudioSink. We don't want this when there's video because it will cause a video seek to
+ // the previous I frame. But we do want this when there's only audio because it will give
+ // NuPlayer a chance to switch from non-offload mode to offload mode.
+ // So we only set doNotReconnect when there's no video.
+ const bool doNotReconnect = !hasVideo;
status_t err = mAudioSink->open(
sampleRate,
numChannels,
@@ -1835,13 +1868,14 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
mUseAudioCallback ? this : NULL,
(audio_output_flags_t)pcmFlags,
NULL,
- true /* doNotReconnect */,
+ doNotReconnect,
frameCount);
if (err == OK) {
err = mAudioSink->setPlaybackRate(mPlaybackSettings);
}
if (err != OK) {
ALOGW("openAudioSink: non offloaded open failed status: %d", err);
+ mAudioSink->close();
mCurrentPcmInfo = AUDIO_PCMINFO_INITIALIZER;
return err;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index 28ec16f..50bd0a9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -173,6 +173,7 @@ protected:
// modified on only renderer's thread.
bool mPaused;
+ int64_t mPauseDrainAudioAllowedUs; // time when we can drain/deliver audio in pause mode.
bool mVideoSampleReceived;
bool mVideoRenderingStarted;
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index 6d0e075..35567a5 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -139,7 +139,9 @@ void NuPlayer::RTSPSource::pause() {
return;
}
}
- mHandler->pause();
+ if (mHandler != NULL) {
+ mHandler->pause();
+ }
}
void NuPlayer::RTSPSource::resume() {
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index a15bca7..dc9c37b 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -292,6 +292,10 @@ void AudioSource::signalBufferReturned(MediaBuffer *buffer) {
status_t AudioSource::dataCallback(const AudioRecord::Buffer& audioBuffer) {
int64_t timeUs = systemTime() / 1000ll;
+ // Estimate the real sampling time of the 1st sample in this buffer
+ // from AudioRecord's latency. (Apply this adjustment first so that
+ // the start time logic is not affected.)
+ timeUs -= mRecord->latency() * 1000LL;
ALOGV("dataCallbackTimestamp: %" PRId64 " us", timeUs);
Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 4e6c2a6..3cd0b0e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2290,11 +2290,11 @@ status_t AwesomePlayer::finishSetDataSource_l() {
// The widevine extractor does its own caching.
#if 0
- mCachedSource = new NuCachedSource2(
+ mCachedSource = NuCachedSource2::Create(
new ThrottledSource(
mConnectingDataSource, 50 * 1024 /* bytes/sec */));
#else
- mCachedSource = new NuCachedSource2(
+ mCachedSource = NuCachedSource2::Create(
mConnectingDataSource,
cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
disconnectAtHighwatermark);
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 39326c9..2df045f 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -326,7 +326,7 @@ sp<DataSource> DataSource::CreateFromURI(
cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
disconnectAtHighwatermark);
} else {
- source = new NuCachedSource2(
+ source = NuCachedSource2::Create(
httpSource,
cacheConfig.isEmpty() ? NULL : cacheConfig.string(),
disconnectAtHighwatermark);
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 107b4f6..eee13c7 100755
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -2583,6 +2583,12 @@ status_t MPEG4Extractor::parseITunesMetaData(off64_t offset, size_t size) {
mLastCommentName.setTo((const char *)buffer + 4);
break;
case FOURCC('d', 'a', 't', 'a'):
+ if (size < 8) {
+ delete[] buffer;
+ buffer = NULL;
+ ALOGE("b/24346430");
+ return ERROR_MALFORMED;
+ }
mLastCommentData.setTo((const char *)buffer + 8);
break;
}
@@ -4163,7 +4169,10 @@ status_t MPEG4Source::read(
(const uint8_t *)mBuffer->data() + mBuffer->range_offset();
size_t nal_size = parseNALSize(src);
- if (mBuffer->range_length() < mNALLengthSize + nal_size) {
+ if (mNALLengthSize > SIZE_MAX - nal_size) {
+ ALOGE("b/24441553, b/24445122");
+ }
+ if (mBuffer->range_length() - mNALLengthSize < nal_size) {
ALOGE("incomplete NAL unit.");
mBuffer->release();
@@ -4450,7 +4459,11 @@ status_t MPEG4Source::fragmentedRead(
(const uint8_t *)mBuffer->data() + mBuffer->range_offset();
size_t nal_size = parseNALSize(src);
- if (mBuffer->range_length() < mNALLengthSize + nal_size) {
+ if (mNALLengthSize > SIZE_MAX - nal_size) {
+ ALOGE("b/24441553, b/24445122");
+ }
+
+ if (mBuffer->range_length() - mNALLengthSize < nal_size) {
ALOGE("incomplete NAL unit.");
mBuffer->release();
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b74836f..45e9a79 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -573,6 +573,7 @@ status_t MediaCodec::stop() {
}
status_t MediaCodec::reclaim() {
+ ALOGD("MediaCodec::reclaim(%p) %s", this, mInitName.c_str());
sp<AMessage> msg = new AMessage(kWhatRelease, this);
msg->setInt32("reclaimed", 1);
@@ -1159,8 +1160,10 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
resourceType = String8(kResourceNonSecureCodec);
}
- const char *subtype = mIsVideo ? kResourceVideoCodec : kResourceAudioCodec;
- addResource(resourceType, String8(subtype), 1);
+ if (mIsVideo) {
+ // audio codec is currently ignored.
+ addResource(resourceType, String8(kResourceVideoCodec), 1);
+ }
(new AMessage)->postReply(mReplyID);
break;
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index f82636b..d6255d6 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -224,9 +224,6 @@ NuCachedSource2::NuCachedSource2(
// So whenever we call DataSource::readAt it may end up in a call to
// IMediaHTTPConnection::readAt and therefore call back into JAVA.
mLooper->start(false /* runOnCallingThread */, true /* canCallJava */);
-
- Mutex::Autolock autoLock(mLock);
- (new AMessage(kWhatFetchMore, mReflector))->post();
}
NuCachedSource2::~NuCachedSource2() {
@@ -237,6 +234,18 @@ NuCachedSource2::~NuCachedSource2() {
mCache = NULL;
}
+// static
+sp<NuCachedSource2> NuCachedSource2::Create(
+ const sp<DataSource> &source,
+ const char *cacheConfig,
+ bool disconnectAtHighwatermark) {
+ sp<NuCachedSource2> instance = new NuCachedSource2(
+ source, cacheConfig, disconnectAtHighwatermark);
+ Mutex::Autolock autoLock(instance->mLock);
+ (new AMessage(kWhatFetchMore, instance->mReflector))->post();
+ return instance;
+}
+
status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
if (mSource->flags() & kIsHTTPBasedSource) {
HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index e9b7b4f..6e4a1a4 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -202,7 +202,7 @@ status_t convertMetaDataToMessage(
}
int32_t fps;
- if (meta->findInt32(kKeyFrameRate, &fps)) {
+ if (meta->findInt32(kKeyFrameRate, &fps) && fps > 0) {
msg->setInt32("frame-rate", fps);
}
@@ -316,8 +316,8 @@ status_t convertMetaDataToMessage(
} else if (meta->findData(kKeyHVCC, &type, &data, &size)) {
const uint8_t *ptr = (const uint8_t *)data;
- if (size < 23) { // configurationVersion == 1
- ALOGE("b/23680780 size=%zd ptr0=%x", size, ptr[0]);
+ if (size < 23 || ptr[0] != 1) { // configurationVersion == 1
+ ALOGE("b/23680780");
return BAD_VALUE;
}
uint8_t profile __unused = ptr[1] & 31;
@@ -684,7 +684,7 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
}
int32_t fps;
- if (msg->findInt32("frame-rate", &fps)) {
+ if (msg->findInt32("frame-rate", &fps) && fps > 0) {
meta->setInt32(kKeyFrameRate, fps);
}
diff --git a/media/libstagefright/codecs/amrnb/dec/Android.mk b/media/libstagefright/codecs/amrnb/dec/Android.mk
index 415702e..21109d9 100644
--- a/media/libstagefright/codecs/amrnb/dec/Android.mk
+++ b/media/libstagefright/codecs/amrnb/dec/Android.mk
@@ -99,7 +99,7 @@ LOCAL_STATIC_LIBRARIES := \
libstagefright_amrnbdec libsndfile
LOCAL_SHARED_LIBRARIES := \
- libstagefright_amrnb_common libaudioutils
+ libstagefright_amrnb_common libaudioutils liblog
LOCAL_MODULE := libstagefright_amrnbdec_test
LOCAL_MODULE_TAGS := optional
diff --git a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
index fb7cff3..696d2da 100644
--- a/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/src/a_refl.cpp
@@ -59,6 +59,8 @@ terms listed above has been obtained from the copyright holder.
/*----------------------------------------------------------------------------
; INCLUDES
----------------------------------------------------------------------------*/
+#include <log/log.h>
+
#include "a_refl.h"
#include "typedef.h"
#include "cnst.h"
@@ -291,7 +293,8 @@ void A_Refl(
{
refl[i] = 0;
}
- break;
+ ALOGE("b/23609206");
+ return;
}
bState[j] = extract_l(L_temp);
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index e083315..7c5093e 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -38,10 +38,10 @@ namespace android {
/** Function and structure definitions to keep code similar for each codec */
#define ivdec_api_function ih264d_api_function
-#define ivdext_init_ip_t ih264d_init_ip_t
-#define ivdext_init_op_t ih264d_init_op_t
-#define ivdext_fill_mem_rec_ip_t ih264d_fill_mem_rec_ip_t
-#define ivdext_fill_mem_rec_op_t ih264d_fill_mem_rec_op_t
+#define ivdext_create_ip_t ih264d_create_ip_t
+#define ivdext_create_op_t ih264d_create_op_t
+#define ivdext_delete_ip_t ih264d_delete_ip_t
+#define ivdext_delete_op_t ih264d_delete_op_t
#define ivdext_ctl_set_num_cores_ip_t ih264d_ctl_set_num_cores_ip_t
#define ivdext_ctl_set_num_cores_op_t ih264d_ctl_set_num_cores_op_t
@@ -115,15 +115,12 @@ SoftAVC::SoftAVC(
320 /* width */, 240 /* height */, callbacks,
appData, component),
mCodecCtx(NULL),
- mMemRecords(NULL),
mFlushOutBuffer(NULL),
mOmxColorFormat(OMX_COLOR_FormatYUV420Planar),
mIvColorFormat(IV_YUV_420P),
- mNewWidth(mWidth),
- mNewHeight(mHeight),
- mNewLevel(0),
mChangingResolution(false),
- mSignalledError(false) {
+ mSignalledError(false),
+ mStride(mWidth){
initPorts(
kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, CODEC_MIME_TYPE);
@@ -132,14 +129,23 @@ SoftAVC::SoftAVC(
// If input dump is enabled, then open create an empty file
GENERATE_FILE_NAMES();
CREATE_DUMP_FILE(mInFile);
-
- CHECK_EQ(initDecoder(mWidth, mHeight), (status_t)OK);
}
SoftAVC::~SoftAVC() {
CHECK_EQ(deInitDecoder(), (status_t)OK);
}
+static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
+ UNUSED(ctxt);
+ return memalign(alignment, size);
+}
+
+static void ivd_aligned_free(void *ctxt, void *buf) {
+ UNUSED(ctxt);
+ free(buf);
+ return;
+}
+
static size_t GetCPUCoreCount() {
long cpuCoreCount = 1;
#if defined(_SC_NPROCESSORS_ONLN)
@@ -149,7 +155,7 @@ static size_t GetCPUCoreCount() {
cpuCoreCount = sysconf(_SC_NPROC_ONLN);
#endif
CHECK(cpuCoreCount >= 1);
- ALOGD("Number of CPU cores: %ld", cpuCoreCount);
+ ALOGV("Number of CPU cores: %ld", cpuCoreCount);
return (size_t)cpuCoreCount;
}
@@ -235,12 +241,10 @@ status_t SoftAVC::resetDecoder() {
}
mSignalledError = false;
- /* Set the run-time (dynamic) parameters */
- setParams(outputBufferWidth());
-
/* Set number of cores/threads to be used by the codec */
setNumCores();
+ mStride = 0;
return OK;
}
@@ -287,160 +291,41 @@ status_t SoftAVC::setFlushMode() {
return OK;
}
-status_t SoftAVC::initDecoder(uint32_t width, uint32_t height) {
+status_t SoftAVC::initDecoder() {
IV_API_CALL_STATUS_T status;
- UWORD32 u4_num_reorder_frames;
- UWORD32 u4_num_ref_frames;
- UWORD32 u4_share_disp_buf;
- WORD32 i4_level;
-
mNumCores = GetCPUCoreCount();
mCodecCtx = NULL;
- /* Initialize number of ref and reorder modes (for H264) */
- u4_num_reorder_frames = 16;
- u4_num_ref_frames = 16;
- u4_share_disp_buf = 0;
-
- uint32_t displayStride = mIsAdaptive ? mAdaptiveMaxWidth : width;
- uint32_t displayHeight = mIsAdaptive ? mAdaptiveMaxHeight : height;
- uint32_t displaySizeY = displayStride * displayHeight;
-
- if(mNewLevel == 0){
- if (displaySizeY > (1920 * 1088)) {
- i4_level = 50;
- } else if (displaySizeY > (1280 * 720)) {
- i4_level = 40;
- } else if (displaySizeY > (720 * 576)) {
- i4_level = 31;
- } else if (displaySizeY > (624 * 320)) {
- i4_level = 30;
- } else if (displaySizeY > (352 * 288)) {
- i4_level = 21;
- } else {
- i4_level = 20;
- }
- } else {
- i4_level = mNewLevel;
- }
-
- {
- iv_num_mem_rec_ip_t s_num_mem_rec_ip;
- iv_num_mem_rec_op_t s_num_mem_rec_op;
-
- s_num_mem_rec_ip.u4_size = sizeof(s_num_mem_rec_ip);
- s_num_mem_rec_op.u4_size = sizeof(s_num_mem_rec_op);
- s_num_mem_rec_ip.e_cmd = IV_CMD_GET_NUM_MEM_REC;
-
- ALOGV("Get number of mem records");
- status = ivdec_api_function(
- mCodecCtx, (void *)&s_num_mem_rec_ip, (void *)&s_num_mem_rec_op);
- if (IV_SUCCESS != status) {
- ALOGE("Error in getting mem records: 0x%x",
- s_num_mem_rec_op.u4_error_code);
- return UNKNOWN_ERROR;
- }
-
- mNumMemRecords = s_num_mem_rec_op.u4_num_mem_rec;
- }
-
- mMemRecords = (iv_mem_rec_t *)ivd_aligned_malloc(
- 128, mNumMemRecords * sizeof(iv_mem_rec_t));
- if (mMemRecords == NULL) {
- ALOGE("Allocation failure");
- return NO_MEMORY;
- }
-
- memset(mMemRecords, 0, mNumMemRecords * sizeof(iv_mem_rec_t));
-
- {
- size_t i;
- ivdext_fill_mem_rec_ip_t s_fill_mem_ip;
- ivdext_fill_mem_rec_op_t s_fill_mem_op;
- iv_mem_rec_t *ps_mem_rec;
-
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_size =
- sizeof(ivdext_fill_mem_rec_ip_t);
- s_fill_mem_ip.i4_level = i4_level;
- s_fill_mem_ip.u4_num_reorder_frames = u4_num_reorder_frames;
- s_fill_mem_ip.u4_num_ref_frames = u4_num_ref_frames;
- s_fill_mem_ip.u4_share_disp_buf = u4_share_disp_buf;
- s_fill_mem_ip.u4_num_extra_disp_buf = 0;
- s_fill_mem_ip.e_output_format = mIvColorFormat;
-
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.e_cmd = IV_CMD_FILL_NUM_MEM_REC;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.pv_mem_rec_location = mMemRecords;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_wd = displayStride;
- s_fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = displayHeight;
- s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_size =
- sizeof(ivdext_fill_mem_rec_op_t);
-
- ps_mem_rec = mMemRecords;
- for (i = 0; i < mNumMemRecords; i++) {
- ps_mem_rec[i].u4_size = sizeof(iv_mem_rec_t);
- }
-
- status = ivdec_api_function(
- mCodecCtx, (void *)&s_fill_mem_ip, (void *)&s_fill_mem_op);
-
- if (IV_SUCCESS != status) {
- ALOGE("Error in filling mem records: 0x%x",
- s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_error_code);
- return UNKNOWN_ERROR;
- }
- mNumMemRecords =
- s_fill_mem_op.s_ivd_fill_mem_rec_op_t.u4_num_mem_rec_filled;
-
- ps_mem_rec = mMemRecords;
-
- for (i = 0; i < mNumMemRecords; i++) {
- ps_mem_rec->pv_base = ivd_aligned_malloc(
- ps_mem_rec->u4_mem_alignment, ps_mem_rec->u4_mem_size);
- if (ps_mem_rec->pv_base == NULL) {
- ALOGE("Allocation failure for memory record #%zu of size %u",
- i, ps_mem_rec->u4_mem_size);
- status = IV_FAIL;
- return NO_MEMORY;
- }
-
- ps_mem_rec++;
- }
- }
+ mStride = outputBufferWidth();
/* Initialize the decoder */
{
- ivdext_init_ip_t s_init_ip;
- ivdext_init_op_t s_init_op;
+ ivdext_create_ip_t s_create_ip;
+ ivdext_create_op_t s_create_op;
void *dec_fxns = (void *)ivdec_api_function;
- s_init_ip.s_ivd_init_ip_t.u4_size = sizeof(ivdext_init_ip_t);
- s_init_ip.s_ivd_init_ip_t.e_cmd = (IVD_API_COMMAND_TYPE_T)IV_CMD_INIT;
- s_init_ip.s_ivd_init_ip_t.pv_mem_rec_location = mMemRecords;
- s_init_ip.s_ivd_init_ip_t.u4_frm_max_wd = displayStride;
- s_init_ip.s_ivd_init_ip_t.u4_frm_max_ht = displayHeight;
+ s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
+ s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
+ s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
+ s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t);
+ s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorFormat;
+ s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
+ s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
+ s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
- s_init_ip.i4_level = i4_level;
- s_init_ip.u4_num_reorder_frames = u4_num_reorder_frames;
- s_init_ip.u4_num_ref_frames = u4_num_ref_frames;
- s_init_ip.u4_share_disp_buf = u4_share_disp_buf;
- s_init_ip.u4_num_extra_disp_buf = 0;
+ status = ivdec_api_function(mCodecCtx, (void *)&s_create_ip, (void *)&s_create_op);
- s_init_op.s_ivd_init_op_t.u4_size = sizeof(s_init_op);
-
- s_init_ip.s_ivd_init_ip_t.u4_num_mem_rec = mNumMemRecords;
- s_init_ip.s_ivd_init_ip_t.e_output_format = mIvColorFormat;
-
- mCodecCtx = (iv_obj_t *)mMemRecords[0].pv_base;
+ mCodecCtx = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
mCodecCtx->pv_fxns = dec_fxns;
mCodecCtx->u4_size = sizeof(iv_obj_t);
- status = ivdec_api_function(mCodecCtx, (void *)&s_init_ip, (void *)&s_init_op);
if (status != IV_SUCCESS) {
+ ALOGE("Error in create: 0x%x",
+ s_create_op.s_ivd_create_op_t.u4_error_code);
+ deInitDecoder();
mCodecCtx = NULL;
- ALOGE("Error in init: 0x%x",
- s_init_op.s_ivd_init_op_t.u4_error_code);
return UNKNOWN_ERROR;
}
}
@@ -449,7 +334,7 @@ status_t SoftAVC::initDecoder(uint32_t width, uint32_t height) {
resetPlugin();
/* Set the run time (dynamic) parameters */
- setParams(displayStride);
+ setParams(mStride);
/* Set number of cores/threads to be used by the codec */
setNumCores();
@@ -457,61 +342,37 @@ status_t SoftAVC::initDecoder(uint32_t width, uint32_t height) {
/* Get codec version */
logVersion();
- /* Allocate internal picture buffer */
- uint32_t bufferSize = displaySizeY * 3 / 2;
- mFlushOutBuffer = (uint8_t *)ivd_aligned_malloc(128, bufferSize);
- if (NULL == mFlushOutBuffer) {
- ALOGE("Could not allocate flushOutputBuffer of size %u", bufferSize);
- return NO_MEMORY;
- }
-
- mInitNeeded = false;
mFlushNeeded = false;
return OK;
}
status_t SoftAVC::deInitDecoder() {
size_t i;
+ IV_API_CALL_STATUS_T status;
- if (mMemRecords) {
- iv_mem_rec_t *ps_mem_rec;
+ if (mCodecCtx) {
+ ivdext_delete_ip_t s_delete_ip;
+ ivdext_delete_op_t s_delete_op;
- ps_mem_rec = mMemRecords;
- for (i = 0; i < mNumMemRecords; i++) {
- if (ps_mem_rec->pv_base) {
- ivd_aligned_free(ps_mem_rec->pv_base);
- }
- ps_mem_rec++;
+ s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
+ s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
+
+ s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t);
+
+ status = ivdec_api_function(mCodecCtx, (void *)&s_delete_ip, (void *)&s_delete_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("Error in delete: 0x%x",
+ s_delete_op.s_ivd_delete_op_t.u4_error_code);
+ return UNKNOWN_ERROR;
}
- ivd_aligned_free(mMemRecords);
- mMemRecords = NULL;
}
- if (mFlushOutBuffer) {
- ivd_aligned_free(mFlushOutBuffer);
- mFlushOutBuffer = NULL;
- }
- mInitNeeded = true;
mChangingResolution = false;
return OK;
}
-status_t SoftAVC::reInitDecoder(uint32_t width, uint32_t height) {
- status_t ret;
-
- deInitDecoder();
-
- ret = initDecoder(width, height);
- if (OK != ret) {
- ALOGE("Create failure");
- deInitDecoder();
- return NO_MEMORY;
- }
- return OK;
-}
-
void SoftAVC::onReset() {
SoftVideoDecoderOMXComponent::onReset();
@@ -520,23 +381,6 @@ void SoftAVC::onReset() {
resetPlugin();
}
-OMX_ERRORTYPE SoftAVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params) {
- const uint32_t oldWidth = mWidth;
- const uint32_t oldHeight = mHeight;
- OMX_ERRORTYPE ret = SoftVideoDecoderOMXComponent::internalSetParameter(index, params);
- if (mWidth != oldWidth || mHeight != oldHeight) {
- mNewWidth = mWidth;
- mNewHeight = mHeight;
- status_t err = reInitDecoder(mNewWidth, mNewHeight);
- if (err != OK) {
- notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
- mSignalledError = true;
- return OMX_ErrorUnsupportedSetting;
- }
- }
- return ret;
-}
-
void SoftAVC::setDecodeArgs(
ivd_video_decode_ip_t *ps_dec_ip,
ivd_video_decode_op_t *ps_dec_op,
@@ -587,6 +431,17 @@ void SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
if (kOutputPortIndex == portIndex) {
setFlushMode();
+ /* Allocate a picture buffer to flushed data */
+ uint32_t displayStride = outputBufferWidth();
+ uint32_t displayHeight = outputBufferHeight();
+
+ uint32_t bufferSize = displayStride * displayHeight * 3 / 2;
+ mFlushOutBuffer = (uint8_t *)memalign(128, bufferSize);
+ if (NULL == mFlushOutBuffer) {
+ ALOGE("Could not allocate flushOutputBuffer of size %zu", bufferSize);
+ return;
+ }
+
while (true) {
ivd_video_decode_ip_t s_dec_ip;
ivd_video_decode_op_t s_dec_op;
@@ -601,6 +456,12 @@ void SoftAVC::onPortFlushCompleted(OMX_U32 portIndex) {
break;
}
}
+
+ if (mFlushOutBuffer) {
+ free(mFlushOutBuffer);
+ mFlushOutBuffer = NULL;
+ }
+
}
}
@@ -614,6 +475,17 @@ void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
return;
}
+ if (NULL == mCodecCtx) {
+ if (OK != initDecoder()) {
+ return;
+ }
+ }
+ if (outputBufferWidth() != mStride) {
+ /* Set the run-time (dynamic) parameters */
+ mStride = outputBufferWidth();
+ setParams(mStride);
+ }
+
List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
@@ -676,22 +548,6 @@ void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
}
}
- // When there is an init required and the decoder is not in flush mode,
- // update output port's definition and reinitialize decoder.
- if (mInitNeeded && !mIsInFlush) {
- bool portWillReset = false;
-
- status_t err = reInitDecoder(mNewWidth, mNewHeight);
- if (err != OK) {
- notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
- mSignalledError = true;
- return;
- }
-
- handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
- return;
- }
-
/* Get a free slot in timestamp array to hold input timestamp */
{
size_t i;
@@ -726,10 +582,7 @@ void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
IV_API_CALL_STATUS_T status;
status = ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
- bool unsupportedDimensions =
- (IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED == (s_dec_op.u4_error_code & 0xFF));
bool resChanged = (IVD_RES_CHANGED == (s_dec_op.u4_error_code & 0xFF));
- bool unsupportedLevel = (IH264D_UNSUPPORTED_LEVEL == (s_dec_op.u4_error_code & 0xFF));
GETTIME(&mTimeEnd, NULL);
/* Compute time taken for decode() */
@@ -747,46 +600,6 @@ void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
mTimeStampsValid[timeStampIx] = false;
}
-
- // This is needed to handle CTS DecoderTest testCodecResetsH264WithoutSurface,
- // which is not sending SPS/PPS after port reconfiguration and flush to the codec.
- if (unsupportedDimensions && !mFlushNeeded) {
- bool portWillReset = false;
- mNewWidth = s_dec_op.u4_pic_wd;
- mNewHeight = s_dec_op.u4_pic_ht;
-
- status_t err = reInitDecoder(mNewWidth, mNewHeight);
- if (err != OK) {
- notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
- mSignalledError = true;
- return;
- }
-
- handlePortSettingsChange(&portWillReset, mNewWidth, mNewHeight);
-
- setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
-
- ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
- return;
- }
-
- if (unsupportedLevel && !mFlushNeeded) {
-
- mNewLevel = 51;
-
- status_t err = reInitDecoder(mNewWidth, mNewHeight);
- if (err != OK) {
- notify(OMX_EventError, OMX_ErrorUnsupportedSetting, err, NULL);
- mSignalledError = true;
- return;
- }
-
- setDecodeArgs(&s_dec_ip, &s_dec_op, inHeader, outHeader, timeStampIx);
-
- ivdec_api_function(mCodecCtx, (void *)&s_dec_ip, (void *)&s_dec_op);
- return;
- }
-
// If the decoder is in the changing resolution mode and there is no output present,
// that means the switching is done and it's ready to reset the decoder and the plugin.
if (mChangingResolution && !s_dec_op.u4_output_present) {
@@ -796,28 +609,11 @@ void SoftAVC::onQueueFilled(OMX_U32 portIndex) {
continue;
}
- if (unsupportedDimensions || resChanged) {
+ if (resChanged) {
mChangingResolution = true;
if (mFlushNeeded) {
setFlushMode();
}
-
- if (unsupportedDimensions) {
- mNewWidth = s_dec_op.u4_pic_wd;
- mNewHeight = s_dec_op.u4_pic_ht;
- mInitNeeded = true;
- }
- continue;
- }
-
- if (unsupportedLevel) {
-
- if (mFlushNeeded) {
- setFlushMode();
- }
-
- mNewLevel = 51;
- mInitNeeded = true;
continue;
}
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.h b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
index 1ec8991..9dcabb4 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.h
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.h
@@ -23,9 +23,6 @@
namespace android {
-#define ivd_aligned_malloc(alignment, size) memalign(alignment, size)
-#define ivd_aligned_free(buf) free(buf)
-
/** Number of entries in the time-stamp array */
#define MAX_TIME_STAMPS 64
@@ -62,7 +59,6 @@ protected:
virtual void onQueueFilled(OMX_U32 portIndex);
virtual void onPortFlushCompleted(OMX_U32 portIndex);
virtual void onReset();
- virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params);
private:
// Number of input and output buffers
enum {
@@ -70,8 +66,6 @@ private:
};
iv_obj_t *mCodecCtx; // Codec context
- iv_mem_rec_t *mMemRecords; // Memory records requested by the codec
- size_t mNumMemRecords; // Number of memory records requested by the codec
size_t mNumCores; // Number of cores to be uesd by the codec
@@ -97,17 +91,15 @@ private:
bool mIsInFlush; // codec is flush mode
bool mReceivedEOS; // EOS is receieved on input port
- bool mInitNeeded;
- uint32_t mNewWidth;
- uint32_t mNewHeight;
- uint32_t mNewLevel;
+
// The input stream has changed to a different resolution, which is still supported by the
// codec. So the codec is switching to decode the new resolution.
bool mChangingResolution;
bool mFlushNeeded;
bool mSignalledError;
+ size_t mStride;
- status_t initDecoder(uint32_t width, uint32_t height);
+ status_t initDecoder();
status_t deInitDecoder();
status_t setFlushMode();
status_t setParams(size_t stride);
@@ -115,7 +107,7 @@ private:
status_t setNumCores();
status_t resetDecoder();
status_t resetPlugin();
- status_t reInitDecoder(uint32_t width, uint32_t height);
+
void setDecodeArgs(
ivd_video_decode_ip_t *ps_dec_ip,
diff --git a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
index e9ead01..03e4119 100644
--- a/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
+++ b/media/libstagefright/codecs/m4v_h263/dec/src/conceal.cpp
@@ -19,6 +19,7 @@
#include "vlc_decode.h"
#include "bitstream.h"
#include "scaling.h"
+#include "log/log.h"
/* ====================================================================== /
Function : ConcealTexture_I()
@@ -137,6 +138,10 @@ Modified: 6/04/2001 rewrote the function
****************************************************************************/
void CopyVopMB(Vop *curr, uint8 *prevFrame, int mbnum, int width_Y, int height)
{
+ if (curr == NULL || prevFrame == NULL) {
+ ALOGE("b/24630158");
+ return;
+ }
int width_C = width_Y >> 1;
int row = MB_SIZE;
uint8 *y1, *y2, *u1, *u2, *v1, *v2;
diff --git a/media/libstagefright/data/media_codecs_google_tv.xml b/media/libstagefright/data/media_codecs_google_tv.xml
new file mode 100644
index 0000000..330c6fb
--- /dev/null
+++ b/media/libstagefright/data/media_codecs_google_tv.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright (C) 2015 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<Included>
+ <Decoders>
+ <MediaCodec name="OMX.google.mpeg2.decoder" type="video/mpeg2">
+ <!-- profiles and levels: ProfileMain : LevelHL -->
+ <Limit name="size" min="16x16" max="1920x1088" />
+ <Limit name="alignment" value="2x2" />
+ <Limit name="block-size" value="16x16" />
+ <Limit name="blocks-per-second" range="1-244800" />
+ <Limit name="bitrate" range="1-20000000" />
+ <Feature name="adaptive-playback" />
+ </MediaCodec>
+ </Decoders>
+</Included>
diff --git a/media/libstagefright/data/media_codecs_google_video.xml b/media/libstagefright/data/media_codecs_google_video.xml
index a83789c..07e26a2 100755..100644
--- a/media/libstagefright/data/media_codecs_google_video.xml
+++ b/media/libstagefright/data/media_codecs_google_video.xml
@@ -16,15 +16,6 @@
<Included>
<Decoders>
- <MediaCodec name="OMX.google.mpeg2.decoder" type="video/mpeg2">
- <!-- profiles and levels: ProfileMain : LevelHL -->
- <Limit name="size" min="16x16" max="1920x1088" />
- <Limit name="alignment" value="2x2" />
- <Limit name="block-size" value="16x16" />
- <Limit name="blocks-per-second" range="1-244800" />
- <Limit name="bitrate" range="1-20000000" />
- <Feature name="adaptive-playback" />
- </MediaCodec>
<MediaCodec name="OMX.google.mpeg4.decoder">
<Type name="video/mp4v-es" />
<!--
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index e549ff6..725a574 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -601,13 +601,24 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
msg->setWhat(what);
msg->mNumItems = static_cast<size_t>(parcel.readInt32());
+ if (msg->mNumItems > kMaxNumItems) {
+ ALOGE("Too large number of items clipped.");
+ msg->mNumItems = kMaxNumItems;
+ }
+
for (size_t i = 0; i < msg->mNumItems; ++i) {
Item *item = &msg->mItems[i];
const char *name = parcel.readCString();
- item->setName(name, strlen(name));
- item->mType = static_cast<Type>(parcel.readInt32());
+ if (name == NULL) {
+ ALOGE("Failed reading name for an item. Parsing aborted.");
+ msg->mNumItems = i;
+ break;
+ }
+ item->mType = static_cast<Type>(parcel.readInt32());
+ // setName() happens below so that we don't leak memory when parsing
+ // is aborted in the middle.
switch (item->mType) {
case kTypeInt32:
{
@@ -641,7 +652,16 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
case kTypeString:
{
- item->u.stringValue = new AString(parcel.readCString());
+ const char *stringValue = parcel.readCString();
+ if (stringValue == NULL) {
+ ALOGE("Failed reading string value from a parcel. "
+ "Parsing aborted.");
+ msg->mNumItems = i;
+ continue;
+ // The loop will terminate subsequently.
+ } else {
+ item->u.stringValue = new AString(stringValue);
+ }
break;
}
@@ -660,6 +680,8 @@ sp<AMessage> AMessage::FromParcel(const Parcel &parcel) {
TRESPASS();
}
}
+
+ item->setName(name, strlen(name));
}
return msg;
diff --git a/media/libstagefright/id3/ID3.cpp b/media/libstagefright/id3/ID3.cpp
index d9a198d..76d65f0 100644
--- a/media/libstagefright/id3/ID3.cpp
+++ b/media/libstagefright/id3/ID3.cpp
@@ -194,6 +194,13 @@ struct id3_header {
if (header.version_major == 4) {
void *copy = malloc(size);
+ if (copy == NULL) {
+ free(mData);
+ mData = NULL;
+ ALOGE("b/24623447, no more memory");
+ return false;
+ }
+
memcpy(copy, mData, size);
bool success = removeUnsynchronizationV2_4(false /* iTunesHack */);
@@ -234,7 +241,14 @@ struct id3_header {
return false;
}
- size_t extendedHeaderSize = U32_AT(&mData[0]) + 4;
+ size_t extendedHeaderSize = U32_AT(&mData[0]);
+ if (extendedHeaderSize > SIZE_MAX - 4) {
+ free(mData);
+ mData = NULL;
+ ALOGE("b/24623447, extendedHeaderSize is too large");
+ return false;
+ }
+ extendedHeaderSize += 4;
if (extendedHeaderSize > mSize) {
free(mData);
@@ -252,7 +266,10 @@ struct id3_header {
if (extendedHeaderSize >= 10) {
size_t paddingSize = U32_AT(&mData[6]);
- if (mFirstFrameOffset + paddingSize > mSize) {
+ if (paddingSize > SIZE_MAX - mFirstFrameOffset) {
+ ALOGE("b/24623447, paddingSize is too large");
+ }
+ if (paddingSize > mSize - mFirstFrameOffset) {
free(mData);
mData = NULL;
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index d36da6a..afa91ae 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -28,7 +28,7 @@ struct ALooper;
struct PageCache;
struct NuCachedSource2 : public DataSource {
- NuCachedSource2(
+ static sp<NuCachedSource2> Create(
const sp<DataSource> &source,
const char *cacheConfig = NULL,
bool disconnectAtHighwatermark = false);
@@ -72,6 +72,11 @@ protected:
protected:
friend struct AHandlerReflector<NuCachedSource2>;
+ NuCachedSource2(
+ const sp<DataSource> &source,
+ const char *cacheConfig,
+ bool disconnectAtHighwatermark);
+
enum {
kPageSize = 65536,
kDefaultHighWaterThreshold = 20 * 1024 * 1024,
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index d468dfc..e7c4f6d 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -140,6 +140,8 @@ public:
virtual void binderDied(const wp<IBinder> &the_late_who);
+ virtual bool isSecure(IOMX::node_id node);
+
OMX_ERRORTYPE OnEvent(
node_id node,
OMX_IN OMX_EVENTTYPE eEvent,
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index f68e0a9..e5fb45b 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -125,6 +125,10 @@ struct OMXNodeInstance {
const void *data,
size_t size);
+ bool isSecure() const {
+ return mIsSecure;
+ }
+
// handles messages and removes them from the list
void onMessages(std::list<omx_message> &messages);
void onMessage(const omx_message &msg);
@@ -142,6 +146,7 @@ private:
OMX_HANDLETYPE mHandle;
sp<IOMXObserver> mObserver;
bool mDying;
+ bool mIsSecure;
// Lock only covers mGraphicBufferSource. We can't always use mLock
// because of rare instances where we'd end up locking it recursively.
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 2ef30e3..efb1a1c 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -194,6 +194,11 @@ void OMX::binderDied(const wp<IBinder> &the_late_who) {
instance->onObserverDied(mMaster);
}
+bool OMX::isSecure(node_id node) {
+ OMXNodeInstance *instance = findInstance(node);
+ return (instance == NULL ? false : instance->isSecure());
+}
+
bool OMX::livesLocally(node_id /* node */, pid_t pid) {
return pid == getpid();
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index bdd1039..4bcc732 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -206,6 +206,7 @@ OMXNodeInstance::OMXNodeInstance(
mDebugLevelBumpPendingBuffers[1] = 0;
mMetadataType[0] = kMetadataBufferTypeInvalid;
mMetadataType[1] = kMetadataBufferTypeInvalid;
+ mIsSecure = AString(name).endsWith(".secure");
}
OMXNodeInstance::~OMXNodeInstance() {
diff --git a/media/utils/Android.mk b/media/utils/Android.mk
index dfadbc8..54d22b1 100644
--- a/media/utils/Android.mk
+++ b/media/utils/Android.mk
@@ -18,6 +18,8 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
BatteryNotifier.cpp \
+ ISchedulingPolicyService.cpp \
+ SchedulingPolicyService.cpp
LOCAL_SHARED_LIBRARIES := \
libbinder \
diff --git a/media/utils/ISchedulingPolicyService.cpp b/media/utils/ISchedulingPolicyService.cpp
new file mode 100644
index 0000000..f55bc02
--- /dev/null
+++ b/media/utils/ISchedulingPolicyService.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ISchedulingPolicyService"
+//#define LOG_NDEBUG 0
+
+#include <binder/Parcel.h>
+#include "ISchedulingPolicyService.h"
+
+namespace android {
+
+// Keep in sync with frameworks/base/core/java/android/os/ISchedulingPolicyService.aidl
+enum {
+ REQUEST_PRIORITY_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+};
+
+// ----------------------------------------------------------------------
+
+class BpSchedulingPolicyService : public BpInterface<ISchedulingPolicyService>
+{
+public:
+ BpSchedulingPolicyService(const sp<IBinder>& impl)
+ : BpInterface<ISchedulingPolicyService>(impl)
+ {
+ }
+
+ virtual int requestPriority(int32_t pid, int32_t tid, int32_t prio, bool asynchronous)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISchedulingPolicyService::getInterfaceDescriptor());
+ data.writeInt32(pid);
+ data.writeInt32(tid);
+ data.writeInt32(prio);
+ uint32_t flags = asynchronous ? IBinder::FLAG_ONEWAY : 0;
+ status_t status = remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, flags);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ if (asynchronous) {
+ return NO_ERROR;
+ }
+ // fail on exception: force binder reconnection
+ if (reply.readExceptionCode() != 0) {
+ return DEAD_OBJECT;
+ }
+ return reply.readInt32();
+ }
+};
+
+IMPLEMENT_META_INTERFACE(SchedulingPolicyService, "android.os.ISchedulingPolicyService");
+
+// ----------------------------------------------------------------------
+
+status_t BnSchedulingPolicyService::onTransact(
+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+ switch (code) {
+ case REQUEST_PRIORITY_TRANSACTION:
+ // Not reached
+ return NO_ERROR;
+ break;
+ default:
+ return BBinder::onTransact(code, data, reply, flags);
+ }
+}
+
+} // namespace android
diff --git a/media/utils/ISchedulingPolicyService.h b/media/utils/ISchedulingPolicyService.h
new file mode 100644
index 0000000..b94b191
--- /dev/null
+++ b/media/utils/ISchedulingPolicyService.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_ISCHEDULING_POLICY_SERVICE_H
+#define ANDROID_ISCHEDULING_POLICY_SERVICE_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+class ISchedulingPolicyService : public IInterface
+{
+public:
+ DECLARE_META_INTERFACE(SchedulingPolicyService);
+
+ virtual int requestPriority(/*pid_t*/int32_t pid, /*pid_t*/int32_t tid,
+ int32_t prio, bool asynchronous) = 0;
+
+};
+
+class BnSchedulingPolicyService : public BnInterface<ISchedulingPolicyService>
+{
+public:
+ virtual status_t onTransact( uint32_t code,
+ const Parcel& data,
+ Parcel* reply,
+ uint32_t flags = 0);
+};
+
+} // namespace android
+
+#endif // ANDROID_ISCHEDULING_POLICY_SERVICE_H
diff --git a/media/utils/SchedulingPolicyService.cpp b/media/utils/SchedulingPolicyService.cpp
new file mode 100644
index 0000000..17ee9bc
--- /dev/null
+++ b/media/utils/SchedulingPolicyService.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SchedulingPolicyService"
+//#define LOG_NDEBUG 0
+
+#include <binder/IServiceManager.h>
+#include <utils/Mutex.h>
+#include "ISchedulingPolicyService.h"
+#include "mediautils/SchedulingPolicyService.h"
+
+namespace android {
+
+static sp<ISchedulingPolicyService> sSchedulingPolicyService;
+static const String16 _scheduling_policy("scheduling_policy");
+static Mutex sMutex;
+
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous)
+{
+ // FIXME merge duplicated code related to service lookup, caching, and error recovery
+ int ret;
+ for (;;) {
+ sMutex.lock();
+ sp<ISchedulingPolicyService> sps = sSchedulingPolicyService;
+ sMutex.unlock();
+ if (sps == 0) {
+ sp<IBinder> binder = defaultServiceManager()->checkService(_scheduling_policy);
+ if (binder == 0) {
+ sleep(1);
+ continue;
+ }
+ sps = interface_cast<ISchedulingPolicyService>(binder);
+ sMutex.lock();
+ sSchedulingPolicyService = sps;
+ sMutex.unlock();
+ }
+ ret = sps->requestPriority(pid, tid, prio, asynchronous);
+ if (ret != DEAD_OBJECT) {
+ break;
+ }
+ ALOGW("SchedulingPolicyService died");
+ sMutex.lock();
+ sSchedulingPolicyService.clear();
+ sMutex.unlock();
+ }
+ return ret;
+}
+
+} // namespace android
diff --git a/media/utils/include/mediautils/SchedulingPolicyService.h b/media/utils/include/mediautils/SchedulingPolicyService.h
new file mode 100644
index 0000000..a9870d4
--- /dev/null
+++ b/media/utils/include/mediautils/SchedulingPolicyService.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _ANDROID_SCHEDULING_POLICY_SERVICE_H
+#define _ANDROID_SCHEDULING_POLICY_SERVICE_H
+
+namespace android {
+
+// Request elevated priority for thread tid, whose thread group leader must be pid.
+// The priority parameter is currently restricted to either 1 or 2.
+// The asynchronous parameter should be 'true' to return immediately,
+// after the request is enqueued but not necessarily executed.
+// The default value 'false' means to return after request has been enqueued and executed.
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous = false);
+
+} // namespace android
+
+#endif // _ANDROID_SCHEDULING_POLICY_SERVICE_H