Loading apex/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ apex_defaults { // Use a custom AndroidManifest.xml used for API targeting. androidManifest: ":com.android.media-androidManifest", legacy_android10_support: true, } apex { Loading Loading @@ -76,6 +78,8 @@ apex_defaults { // Use a custom AndroidManifest.xml used for API targeting. androidManifest: ":com.android.media.swcodec-androidManifest", legacy_android10_support: true, } prebuilt_etc { Loading media/extractors/mp4/MPEG4Extractor.cpp +39 −21 Original line number Diff line number Diff line Loading @@ -1631,8 +1631,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { { *offset += chunk_size; if (mLastTrack == NULL) // the absolute minimum size of a compliant mett box is 11 bytes: // 6 byte reserved, 2 byte index, null byte, one char mime_format, null byte // The resulting mime_format would be invalid at that size though. if (mLastTrack == NULL || chunk_data_size < 11) { return ERROR_MALFORMED; } auto buffer = heapbuffer<uint8_t>(chunk_data_size); if (buffer.get() == NULL) { Loading @@ -1644,10 +1648,24 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; } // ISO-14496-12: // int8 reserved[6]; // should be all zeroes // int16_t data_reference_index; // char content_encoding[]; // null terminated, optional (= just the null byte) // char mime_format[]; // null terminated, mandatory // optional other boxes // // API < 29: // char mime_format[]; // null terminated // // API >= 29 // char mime_format[]; // null terminated // char mime_format[]; // null terminated // Prior to API 29, the metadata track was not compliant with ISO/IEC // 14496-12-2015. This led to some ISO-compliant parsers failing to read the // metatrack. As of API 29 and onwards, a change was made to metadata track to // make it compliant with the standard. The workaround is to write the // make it somewhat compatible with the standard. The workaround is to write the // null-terminated mime_format string twice. This allows compliant parsers to // read the missing reserved, data_reference_index, and content_encoding fields // from the first mime_type string. The actual mime_format field would then be Loading @@ -1656,25 +1674,25 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // as it would only read the first null-terminated mime_format string. To enable // reading metadata tracks generated from both the non-compliant and compliant // formats, a check needs to be done to see which format is used. int null_pos = 0; const unsigned char *str = buffer.get(); while (null_pos < chunk_data_size) { if (*(str + null_pos) == '\0') { break; } ++null_pos; } const char *str = (const char*) buffer.get(); size_t string_length = strnlen(str, chunk_data_size); if (null_pos == chunk_data_size - 1) { // This is not a standard ompliant metadata track. String8 mimeFormat((const char *)(buffer.get()), chunk_data_size); AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, mimeFormat.string()); if (string_length == chunk_data_size - 1) { // This is likely a pre API 29 file, since it's a single null terminated // string filling the entire box. AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, str); } else { // This is a standard compliant metadata track. String8 contentEncoding((const char *)(buffer.get() + 8)); String8 mimeFormat((const char *)(buffer.get() + 8 + contentEncoding.size() + 1), chunk_data_size - 8 - contentEncoding.size() - 1); // This might be a fully compliant metadata track, a "double mime" compatibility // track, or anything else, including a single non-terminated string, so we need // to determine the length of each string we want to parse out of the box. size_t encoding_length = strnlen(str + 8, chunk_data_size - 8); if (encoding_length + 8 >= chunk_data_size - 2) { // the encoding extends to the end of the box, so there's no mime_format return ERROR_MALFORMED; } String8 contentEncoding(str + 8, encoding_length); String8 mimeFormat(str + 8 + encoding_length + 1, chunk_data_size - 8 - encoding_length - 1); AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, mimeFormat.string()); } Loading media/libstagefright/MediaCodec.cpp +51 −1 Original line number Diff line number Diff line Loading @@ -101,6 +101,10 @@ static const char *kCodecLatencyCount = "android.media.mediacodec.latency.n"; static const char *kCodecLatencyHist = "android.media.mediacodec.latency.hist"; /* in us */ static const char *kCodecLatencyUnknown = "android.media.mediacodec.latency.unknown"; static const char *kCodecNumLowLatencyModeOn = "android.media.mediacodec.low-latency.on"; /* 0..n */ static const char *kCodecNumLowLatencyModeOff = "android.media.mediacodec.low-latency.off"; /* 0..n */ static const char *kCodecFirstFrameIndexLowLatencyModeOn = "android.media.mediacodec.low-latency.first-frame"; /* 0..n */ // the kCodecRecent* fields appear only in getMetrics() results static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max"; /* in us */ static const char *kCodecRecentLatencyMin = "android.media.mediacodec.recent.min"; /* in us */ Loading Loading @@ -583,7 +587,12 @@ MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid) mHaveInputSurface(false), mHavePendingInputBuffers(false), mCpuBoostRequested(false), mLatencyUnknown(0) { mLatencyUnknown(0), mNumLowLatencyEnables(0), mNumLowLatencyDisables(0), mIsLowLatencyModeOn(false), mIndexOfFirstFrameWhenLowLatencyOn(-1), mInputBufferCounter(0) { if (uid == kNoUid) { mUid = AIBinder_getCallingUid(); } else { Loading Loading @@ -616,6 +625,16 @@ void MediaCodec::initMediametrics() { } mRecentHead = 0; } { Mutex::Autolock al(mLatencyLock); mBuffersInFlight.clear(); mNumLowLatencyEnables = 0; mNumLowLatencyDisables = 0; mIsLowLatencyModeOn = false; mIndexOfFirstFrameWhenLowLatencyOn = -1; mInputBufferCounter = 0; } } void MediaCodec::updateMediametrics() { Loading @@ -641,6 +660,13 @@ void MediaCodec::updateMediametrics() { mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown); } { Mutex::Autolock al(mLatencyLock); mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOn, mNumLowLatencyEnables); mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOff, mNumLowLatencyDisables); mediametrics_setInt64(mMetricsHandle, kCodecFirstFrameIndexLowLatencyModeOn, mIndexOfFirstFrameWhenLowLatencyOn); } #if 0 // enable for short term, only while debugging updateEphemeralMediametrics(mMetricsHandle); Loading Loading @@ -697,6 +723,22 @@ void MediaCodec::flushMediametrics() { } } void MediaCodec::updateLowLatency(const sp<AMessage> &msg) { int32_t lowLatency = 0; if (msg->findInt32("low-latency", &lowLatency)) { Mutex::Autolock al(mLatencyLock); if (lowLatency > 0) { ++mNumLowLatencyEnables; // This is just an estimate since low latency mode change happens ONLY at key frame mIsLowLatencyModeOn = true; } else if (lowLatency == 0) { ++mNumLowLatencyDisables; // This is just an estimate since low latency mode change happens ONLY at key frame mIsLowLatencyModeOn = false; } } } bool MediaCodec::Histogram::setup(int nbuckets, int64_t width, int64_t floor) { if (nbuckets <= 0 || width <= 0) { Loading Loading @@ -813,6 +855,11 @@ void MediaCodec::statsBufferSent(int64_t presentationUs) { // XXX: we *could* make sure that the time is later than the end of queue // as part of a consistency check... mBuffersInFlight.push_back(startdata); if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) { mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter; } ++mInputBufferCounter; } } Loading Loading @@ -1133,6 +1180,8 @@ status_t MediaCodec::configure( } } updateLowLatency(format); msg->setMessage("format", format); msg->setInt32("flags", flags); msg->setObject("surface", surface); Loading Loading @@ -3714,6 +3763,7 @@ status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { } status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { updateLowLatency(params); mCodec->signalSetParameters(params); return OK; Loading media/libstagefright/codecs/amrnb/common/Android.bp +1 −1 Original line number Diff line number Diff line cc_library_shared { cc_library { name: "libstagefright_amrnb_common", vendor_available: true, Loading media/libstagefright/include/media/stagefright/MediaCodec.h +7 −0 Original line number Diff line number Diff line Loading @@ -313,6 +313,7 @@ private: void updateMediametrics(); void flushMediametrics(); void updateEphemeralMediametrics(mediametrics_handle_t item); void updateLowLatency(const sp<AMessage> &msg); sp<AMessage> mOutputFormat; sp<AMessage> mInputFormat; Loading Loading @@ -440,6 +441,12 @@ private: std::deque<BufferFlightTiming_t> mBuffersInFlight; Mutex mLatencyLock; int64_t mLatencyUnknown; // buffers for which we couldn't calculate latency int64_t mNumLowLatencyEnables; // how many times low latency mode is enabled int64_t mNumLowLatencyDisables; // how many times low latency mode is disabled bool mIsLowLatencyModeOn; // is low latency mode on currently int64_t mIndexOfFirstFrameWhenLowLatencyOn; // index of the first frame queued // when low latency is on int64_t mInputBufferCounter; // number of input buffers queued since last reset/flush sp<BatteryChecker> mBatteryChecker; Loading Loading
apex/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,8 @@ apex_defaults { // Use a custom AndroidManifest.xml used for API targeting. androidManifest: ":com.android.media-androidManifest", legacy_android10_support: true, } apex { Loading Loading @@ -76,6 +78,8 @@ apex_defaults { // Use a custom AndroidManifest.xml used for API targeting. androidManifest: ":com.android.media.swcodec-androidManifest", legacy_android10_support: true, } prebuilt_etc { Loading
media/extractors/mp4/MPEG4Extractor.cpp +39 −21 Original line number Diff line number Diff line Loading @@ -1631,8 +1631,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { { *offset += chunk_size; if (mLastTrack == NULL) // the absolute minimum size of a compliant mett box is 11 bytes: // 6 byte reserved, 2 byte index, null byte, one char mime_format, null byte // The resulting mime_format would be invalid at that size though. if (mLastTrack == NULL || chunk_data_size < 11) { return ERROR_MALFORMED; } auto buffer = heapbuffer<uint8_t>(chunk_data_size); if (buffer.get() == NULL) { Loading @@ -1644,10 +1648,24 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { return ERROR_IO; } // ISO-14496-12: // int8 reserved[6]; // should be all zeroes // int16_t data_reference_index; // char content_encoding[]; // null terminated, optional (= just the null byte) // char mime_format[]; // null terminated, mandatory // optional other boxes // // API < 29: // char mime_format[]; // null terminated // // API >= 29 // char mime_format[]; // null terminated // char mime_format[]; // null terminated // Prior to API 29, the metadata track was not compliant with ISO/IEC // 14496-12-2015. This led to some ISO-compliant parsers failing to read the // metatrack. As of API 29 and onwards, a change was made to metadata track to // make it compliant with the standard. The workaround is to write the // make it somewhat compatible with the standard. The workaround is to write the // null-terminated mime_format string twice. This allows compliant parsers to // read the missing reserved, data_reference_index, and content_encoding fields // from the first mime_type string. The actual mime_format field would then be Loading @@ -1656,25 +1674,25 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { // as it would only read the first null-terminated mime_format string. To enable // reading metadata tracks generated from both the non-compliant and compliant // formats, a check needs to be done to see which format is used. int null_pos = 0; const unsigned char *str = buffer.get(); while (null_pos < chunk_data_size) { if (*(str + null_pos) == '\0') { break; } ++null_pos; } const char *str = (const char*) buffer.get(); size_t string_length = strnlen(str, chunk_data_size); if (null_pos == chunk_data_size - 1) { // This is not a standard ompliant metadata track. String8 mimeFormat((const char *)(buffer.get()), chunk_data_size); AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, mimeFormat.string()); if (string_length == chunk_data_size - 1) { // This is likely a pre API 29 file, since it's a single null terminated // string filling the entire box. AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, str); } else { // This is a standard compliant metadata track. String8 contentEncoding((const char *)(buffer.get() + 8)); String8 mimeFormat((const char *)(buffer.get() + 8 + contentEncoding.size() + 1), chunk_data_size - 8 - contentEncoding.size() - 1); // This might be a fully compliant metadata track, a "double mime" compatibility // track, or anything else, including a single non-terminated string, so we need // to determine the length of each string we want to parse out of the box. size_t encoding_length = strnlen(str + 8, chunk_data_size - 8); if (encoding_length + 8 >= chunk_data_size - 2) { // the encoding extends to the end of the box, so there's no mime_format return ERROR_MALFORMED; } String8 contentEncoding(str + 8, encoding_length); String8 mimeFormat(str + 8 + encoding_length + 1, chunk_data_size - 8 - encoding_length - 1); AMediaFormat_setString(mLastTrack->meta, AMEDIAFORMAT_KEY_MIME, mimeFormat.string()); } Loading
media/libstagefright/MediaCodec.cpp +51 −1 Original line number Diff line number Diff line Loading @@ -101,6 +101,10 @@ static const char *kCodecLatencyCount = "android.media.mediacodec.latency.n"; static const char *kCodecLatencyHist = "android.media.mediacodec.latency.hist"; /* in us */ static const char *kCodecLatencyUnknown = "android.media.mediacodec.latency.unknown"; static const char *kCodecNumLowLatencyModeOn = "android.media.mediacodec.low-latency.on"; /* 0..n */ static const char *kCodecNumLowLatencyModeOff = "android.media.mediacodec.low-latency.off"; /* 0..n */ static const char *kCodecFirstFrameIndexLowLatencyModeOn = "android.media.mediacodec.low-latency.first-frame"; /* 0..n */ // the kCodecRecent* fields appear only in getMetrics() results static const char *kCodecRecentLatencyMax = "android.media.mediacodec.recent.max"; /* in us */ static const char *kCodecRecentLatencyMin = "android.media.mediacodec.recent.min"; /* in us */ Loading Loading @@ -583,7 +587,12 @@ MediaCodec::MediaCodec(const sp<ALooper> &looper, pid_t pid, uid_t uid) mHaveInputSurface(false), mHavePendingInputBuffers(false), mCpuBoostRequested(false), mLatencyUnknown(0) { mLatencyUnknown(0), mNumLowLatencyEnables(0), mNumLowLatencyDisables(0), mIsLowLatencyModeOn(false), mIndexOfFirstFrameWhenLowLatencyOn(-1), mInputBufferCounter(0) { if (uid == kNoUid) { mUid = AIBinder_getCallingUid(); } else { Loading Loading @@ -616,6 +625,16 @@ void MediaCodec::initMediametrics() { } mRecentHead = 0; } { Mutex::Autolock al(mLatencyLock); mBuffersInFlight.clear(); mNumLowLatencyEnables = 0; mNumLowLatencyDisables = 0; mIsLowLatencyModeOn = false; mIndexOfFirstFrameWhenLowLatencyOn = -1; mInputBufferCounter = 0; } } void MediaCodec::updateMediametrics() { Loading @@ -641,6 +660,13 @@ void MediaCodec::updateMediametrics() { mediametrics_setInt64(mMetricsHandle, kCodecLatencyUnknown, mLatencyUnknown); } { Mutex::Autolock al(mLatencyLock); mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOn, mNumLowLatencyEnables); mediametrics_setInt64(mMetricsHandle, kCodecNumLowLatencyModeOff, mNumLowLatencyDisables); mediametrics_setInt64(mMetricsHandle, kCodecFirstFrameIndexLowLatencyModeOn, mIndexOfFirstFrameWhenLowLatencyOn); } #if 0 // enable for short term, only while debugging updateEphemeralMediametrics(mMetricsHandle); Loading Loading @@ -697,6 +723,22 @@ void MediaCodec::flushMediametrics() { } } void MediaCodec::updateLowLatency(const sp<AMessage> &msg) { int32_t lowLatency = 0; if (msg->findInt32("low-latency", &lowLatency)) { Mutex::Autolock al(mLatencyLock); if (lowLatency > 0) { ++mNumLowLatencyEnables; // This is just an estimate since low latency mode change happens ONLY at key frame mIsLowLatencyModeOn = true; } else if (lowLatency == 0) { ++mNumLowLatencyDisables; // This is just an estimate since low latency mode change happens ONLY at key frame mIsLowLatencyModeOn = false; } } } bool MediaCodec::Histogram::setup(int nbuckets, int64_t width, int64_t floor) { if (nbuckets <= 0 || width <= 0) { Loading Loading @@ -813,6 +855,11 @@ void MediaCodec::statsBufferSent(int64_t presentationUs) { // XXX: we *could* make sure that the time is later than the end of queue // as part of a consistency check... mBuffersInFlight.push_back(startdata); if (mIsLowLatencyModeOn && mIndexOfFirstFrameWhenLowLatencyOn < 0) { mIndexOfFirstFrameWhenLowLatencyOn = mInputBufferCounter; } ++mInputBufferCounter; } } Loading Loading @@ -1133,6 +1180,8 @@ status_t MediaCodec::configure( } } updateLowLatency(format); msg->setMessage("format", format); msg->setInt32("flags", flags); msg->setObject("surface", surface); Loading Loading @@ -3714,6 +3763,7 @@ status_t MediaCodec::setParameters(const sp<AMessage> ¶ms) { } status_t MediaCodec::onSetParameters(const sp<AMessage> ¶ms) { updateLowLatency(params); mCodec->signalSetParameters(params); return OK; Loading
media/libstagefright/codecs/amrnb/common/Android.bp +1 −1 Original line number Diff line number Diff line cc_library_shared { cc_library { name: "libstagefright_amrnb_common", vendor_available: true, Loading
media/libstagefright/include/media/stagefright/MediaCodec.h +7 −0 Original line number Diff line number Diff line Loading @@ -313,6 +313,7 @@ private: void updateMediametrics(); void flushMediametrics(); void updateEphemeralMediametrics(mediametrics_handle_t item); void updateLowLatency(const sp<AMessage> &msg); sp<AMessage> mOutputFormat; sp<AMessage> mInputFormat; Loading Loading @@ -440,6 +441,12 @@ private: std::deque<BufferFlightTiming_t> mBuffersInFlight; Mutex mLatencyLock; int64_t mLatencyUnknown; // buffers for which we couldn't calculate latency int64_t mNumLowLatencyEnables; // how many times low latency mode is enabled int64_t mNumLowLatencyDisables; // how many times low latency mode is disabled bool mIsLowLatencyModeOn; // is low latency mode on currently int64_t mIndexOfFirstFrameWhenLowLatencyOn; // index of the first frame queued // when low latency is on int64_t mInputBufferCounter; // number of input buffers queued since last reset/flush sp<BatteryChecker> mBatteryChecker; Loading