Merge "transcoding: Adding TranscodingJobStats for benchmarking."
diff --git a/apex/testing/test_manifest.json b/apex/testing/test_manifest.json
index ddd642e..e1295a2 100644
--- a/apex/testing/test_manifest.json
+++ b/apex/testing/test_manifest.json
@@ -1,4 +1,4 @@
{
"name": "com.android.media",
- "version": 300000000
+ "version": 2147483647
}
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index 4db94f5..2e85915 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -293,6 +293,30 @@
return OK;
}
+static void MaybeLogTimestampWarning(
+ long long lastFrameEndTimestampUs, long long inputTimestampUs) {
+ using Clock = std::chrono::steady_clock;
+ thread_local Clock::time_point sLastLogTimestamp{};
+ thread_local int32_t sOverlapCount = -1;
+ if (Clock::now() - sLastLogTimestamp > std::chrono::minutes(1) || sOverlapCount < 0) {
+ AString countMessage = "";
+ if (sOverlapCount > 0) {
+ countMessage = AStringPrintf(
+ "(%d overlapping timestamp detected since last log)", sOverlapCount);
+ }
+ ALOGI("Correcting overlapping timestamp: last frame ended at %lldus but "
+ "current frame is starting at %lldus. Using the last frame's end timestamp %s",
+ lastFrameEndTimestampUs, inputTimestampUs, countMessage.c_str());
+ sLastLogTimestamp = Clock::now();
+ sOverlapCount = 0;
+ } else {
+ ALOGV("Correcting overlapping timestamp: last frame ended at %lldus but "
+ "current frame is starting at %lldus. Using the last frame's end timestamp",
+ lastFrameEndTimestampUs, inputTimestampUs);
+ ++sOverlapCount;
+ }
+}
+
void C2SoftAacEnc::process(
const std::unique_ptr<C2Work> &work,
const std::shared_ptr<C2BlockPool> &pool) {
@@ -366,9 +390,7 @@
}
c2_cntr64_t inputTimestampUs = work->input.ordinal.timestamp;
if (inputTimestampUs < mLastFrameEndTimestampUs.value_or(inputTimestampUs)) {
- ALOGW("Correcting overlapping timestamp: last frame ended at %lldus but "
- "current frame is starting at %lldus. Using the last frame's end timestamp",
- mLastFrameEndTimestampUs->peekll(), inputTimestampUs.peekll());
+ MaybeLogTimestampWarning(mLastFrameEndTimestampUs->peekll(), inputTimestampUs.peekll());
inputTimestampUs = *mLastFrameEndTimestampUs;
}
if (capacity > 0) {
diff --git a/media/extractors/aac/Android.bp b/media/extractors/aac/Android.bp
index 60d3ae1..c036bb5 100644
--- a/media/extractors/aac/Android.bp
+++ b/media/extractors/aac/Android.bp
@@ -10,4 +10,11 @@
"libutils",
],
+ host_supported: true,
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
diff --git a/media/extractors/flac/Android.bp b/media/extractors/flac/Android.bp
index 826c1a0..2593000 100644
--- a/media/extractors/flac/Android.bp
+++ b/media/extractors/flac/Android.bp
@@ -21,4 +21,12 @@
"libutils",
],
+ host_supported: true,
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+
}
diff --git a/media/extractors/mkv/Android.bp b/media/extractors/mkv/Android.bp
index 7ad8cc1..330d4fe 100644
--- a/media/extractors/mkv/Android.bp
+++ b/media/extractors/mkv/Android.bp
@@ -21,4 +21,12 @@
"libutils",
],
+ host_supported: true,
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+
}
diff --git a/media/extractors/mp3/Android.bp b/media/extractors/mp3/Android.bp
index 102ac81..7d70548 100644
--- a/media/extractors/mp3/Android.bp
+++ b/media/extractors/mp3/Android.bp
@@ -13,4 +13,11 @@
"libstagefright_foundation",
],
+ host_supported: true,
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
diff --git a/media/extractors/mp4/MPEG4Extractor.cpp b/media/extractors/mp4/MPEG4Extractor.cpp
index 1d828df..7d16fb4 100644
--- a/media/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/extractors/mp4/MPEG4Extractor.cpp
@@ -150,6 +150,7 @@
bool mIsHeif;
bool mIsAudio;
+ bool mIsUsac = false;
sp<ItemTable> mItemTable;
/* Shift start offset (move to earlier time) when media_time > 0,
@@ -4511,7 +4512,7 @@
//AOT_SLS = 38, /**< SLS */
//AOT_ER_AAC_ELD = 39, /**< AAC Enhanced Low Delay */
- //AOT_USAC = 42, /**< USAC */
+ AOT_USAC = 42, /**< USAC */
//AOT_SAOC = 43, /**< SAOC */
//AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */
@@ -4659,7 +4660,7 @@
ABitReader br(csd, csd_size);
uint32_t objectType = br.getBits(5);
- if (objectType == 31) { // AAC-ELD => additional 6 bits
+ if (objectType == AOT_ESCAPE) { // AAC-ELD => additional 6 bits
objectType = 32 + br.getBits(6);
}
@@ -5035,6 +5036,12 @@
mIsPcm = !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW);
mIsAudio = !strncasecmp(mime, "audio/", 6);
+ int32_t aacObjectType = -1;
+
+ if (AMediaFormat_getInt32(format, AMEDIAFORMAT_KEY_AAC_PROFILE, &aacObjectType)) {
+ mIsUsac = (aacObjectType == AOT_USAC);
+ }
+
if (mIsPcm) {
int32_t numChannels = 0;
int32_t bitsPerSample = 0;
@@ -6028,10 +6035,10 @@
}
uint32_t syncSampleIndex = sampleIndex;
- // assume every audio sample is a sync sample. This works around
+ // assume every non-USAC audio sample is a sync sample. This works around
// seek issues with files that were incorrectly written with an
// empty or single-sample stss block for the audio track
- if (err == OK && !mIsAudio) {
+ if (err == OK && (!mIsAudio || mIsUsac)) {
err = mSampleTable->findSyncSampleNear(
sampleIndex, &syncSampleIndex, findFlags);
}
diff --git a/media/extractors/ogg/Android.bp b/media/extractors/ogg/Android.bp
index 7aed683..579065e 100644
--- a/media/extractors/ogg/Android.bp
+++ b/media/extractors/ogg/Android.bp
@@ -20,4 +20,11 @@
"libvorbisidec",
],
+ host_supported: true,
+
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
}
diff --git a/media/extractors/tests/ExtractorUnitTest.cpp b/media/extractors/tests/ExtractorUnitTest.cpp
index a18b122..13d4cf6 100644
--- a/media/extractors/tests/ExtractorUnitTest.cpp
+++ b/media/extractors/tests/ExtractorUnitTest.cpp
@@ -50,8 +50,29 @@
constexpr int32_t kRandomSeed = 700;
constexpr int32_t kUndefined = -1;
+enum inputID {
+ // audio streams
+ AAC_1,
+ AMR_NB_1,
+ AMR_WB_1,
+ FLAC_1,
+ GSM_1,
+ MIDI_1,
+ MP3_1,
+ OPUS_1,
+ VORBIS_1,
+ // video streams
+ HEVC_1,
+ MPEG2_PS_1,
+ MPEG2_TS_1,
+ MPEG4_1,
+ VP9_1,
+ UNKNOWN_ID,
+};
+
// LookUpTable of clips and metadata for component testing
static const struct InputData {
+ inputID inpId;
string mime;
string inputFile;
int32_t firstParam;
@@ -59,26 +80,34 @@
int32_t profile;
int32_t frameRate;
} kInputData[] = {
- {MEDIA_MIMETYPE_AUDIO_AAC, "test_mono_44100Hz_aac.aac", 44100, 1, AACObjectLC, kUndefined},
- {MEDIA_MIMETYPE_AUDIO_AMR_NB, "bbb_mono_8kHz_amrnb.amr", 8000, 1, kUndefined, kUndefined},
- {MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_mono_16kHz_amrwb.amr", 16000, 1, kUndefined, kUndefined},
- {MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_stereo_48kHz_vorbis.ogg", 48000, 2, kUndefined,
+ {AAC_1, MEDIA_MIMETYPE_AUDIO_AAC, "test_mono_44100Hz_aac.aac", 44100, 1, AACObjectLC,
kUndefined},
- {MEDIA_MIMETYPE_AUDIO_MSGSM, "test_mono_8kHz_gsm.wav", 8000, 1, kUndefined, kUndefined},
- {MEDIA_MIMETYPE_AUDIO_RAW, "bbb_stereo_48kHz_flac.flac", 48000, 2, kUndefined, kUndefined},
- {MEDIA_MIMETYPE_AUDIO_OPUS, "test_stereo_48kHz_opus.opus", 48000, 2, kUndefined,
+ {AMR_NB_1, MEDIA_MIMETYPE_AUDIO_AMR_NB, "bbb_mono_8kHz_amrnb.amr", 8000, 1, kUndefined,
kUndefined},
- {MEDIA_MIMETYPE_AUDIO_MPEG, "bbb_stereo_48kHz_mp3.mp3", 48000, 2, kUndefined, kUndefined},
- {MEDIA_MIMETYPE_AUDIO_RAW, "midi_a.mid", 22050, 2, kUndefined, kUndefined},
- {MEDIA_MIMETYPE_VIDEO_MPEG2, "bbb_cif_768kbps_30fps_mpeg2.ts", 352, 288, MPEG2ProfileMain,
- 30},
- {MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_cif_768kbps_30fps_mpeg4.mkv", 352, 288,
- MPEG4ProfileSimple, 30},
+ {AMR_WB_1, MEDIA_MIMETYPE_AUDIO_AMR_WB, "bbb_mono_16kHz_amrwb.amr", 16000, 1, kUndefined,
+ kUndefined},
+ {FLAC_1, MEDIA_MIMETYPE_AUDIO_RAW, "bbb_stereo_48kHz_flac.flac", 48000, 2, kUndefined,
+ kUndefined},
+ {GSM_1, MEDIA_MIMETYPE_AUDIO_MSGSM, "test_mono_8kHz_gsm.wav", 8000, 1, kUndefined,
+ kUndefined},
+ {MIDI_1, MEDIA_MIMETYPE_AUDIO_RAW, "midi_a.mid", 22050, 2, kUndefined, kUndefined},
+ {MP3_1, MEDIA_MIMETYPE_AUDIO_MPEG, "bbb_stereo_48kHz_mp3.mp3", 48000, 2, kUndefined,
+ kUndefined},
+ {OPUS_1, MEDIA_MIMETYPE_AUDIO_OPUS, "test_stereo_48kHz_opus.opus", 48000, 2, kUndefined,
+ kUndefined},
+ {VORBIS_1, MEDIA_MIMETYPE_AUDIO_VORBIS, "bbb_stereo_48kHz_vorbis.ogg", 48000, 2, kUndefined,
+ kUndefined},
+
// Test (b/151677264) for MP4 extractor
- {MEDIA_MIMETYPE_VIDEO_HEVC, "crowd_508x240_25fps_hevc.mp4", 508, 240, HEVCProfileMain,
- 25},
- {MEDIA_MIMETYPE_VIDEO_VP9, "bbb_340x280_30fps_vp9.webm", 340, 280, VP9Profile0, 30},
- {MEDIA_MIMETYPE_VIDEO_MPEG2, "swirl_144x136_mpeg2.mpg", 144, 136, MPEG2ProfileMain, 12},
+ {HEVC_1, MEDIA_MIMETYPE_VIDEO_HEVC, "crowd_508x240_25fps_hevc.mp4", 508, 240,
+ HEVCProfileMain, 25},
+ {MPEG2_PS_1, MEDIA_MIMETYPE_VIDEO_MPEG2, "swirl_144x136_mpeg2.mpg", 144, 136,
+ MPEG2ProfileMain, 12},
+ {MPEG2_TS_1, MEDIA_MIMETYPE_VIDEO_MPEG2, "bbb_cif_768kbps_30fps_mpeg2.ts", 352, 288,
+ MPEG2ProfileMain, 30},
+ {MPEG4_1, MEDIA_MIMETYPE_VIDEO_MPEG4, "bbb_cif_768kbps_30fps_mpeg4.mkv", 352, 288,
+ MPEG4ProfileSimple, 30},
+ {VP9_1, MEDIA_MIMETYPE_VIDEO_VP9, "bbb_340x280_30fps_vp9.webm", 340, 280, VP9Profile0, 30},
};
static ExtractorUnitTestEnvironment *gEnv = nullptr;
@@ -148,14 +177,23 @@
MediaExtractorPluginHelper *mExtractor;
};
-class ExtractorFunctionalityTest : public ExtractorUnitTest,
- public ::testing::TestWithParam<pair<string, string>> {
+class ExtractorFunctionalityTest
+ : public ExtractorUnitTest,
+ public ::testing::TestWithParam<tuple<string /* container */, string /* InputFile */,
+ int32_t /* numTracks */, bool /* seekSupported */>> {
public:
- virtual void SetUp() override { setupExtractor(GetParam().first); }
+ virtual void SetUp() override {
+ tuple<string, string, int32_t, bool> params = GetParam();
+ mContainer = get<0>(params);
+ mNumTracks = get<2>(params);
+ setupExtractor(mContainer);
+ }
+ string mContainer;
+ int32_t mNumTracks;
};
class ConfigParamTest : public ExtractorUnitTest,
- public ::testing::TestWithParam<pair<string, int32_t>> {
+ public ::testing::TestWithParam<pair<string, inputID>> {
public:
virtual void SetUp() override { setupExtractor(GetParam().first); }
@@ -169,7 +207,7 @@
int32_t frameRate;
};
- void getFileProperties(int32_t inputIdx, string &inputFile, configFormat &configParam);
+ void getFileProperties(inputID inputId, string &inputFile, configFormat &configParam);
};
int32_t ExtractorUnitTest::setDataSource(string inputFileName) {
@@ -228,9 +266,16 @@
return 0;
}
-void ConfigParamTest::getFileProperties(int32_t inputIdx, string &inputFile,
+void ConfigParamTest::getFileProperties(inputID inputId, string &inputFile,
configFormat &configParam) {
- if (inputIdx >= sizeof(kInputData) / sizeof(kInputData[0])) {
+ int32_t inputDataSize = sizeof(kInputData) / sizeof(kInputData[0]);
+ int32_t inputIdx = 0;
+ for (; inputIdx < inputDataSize; inputIdx++) {
+ if (inputId == kInputData[inputIdx].inpId) {
+ break;
+ }
+ }
+ if (inputIdx == inputDataSize) {
return;
}
inputFile += kInputData[inputIdx].inputFile;
@@ -316,16 +361,17 @@
if (mDisableTest) return;
ALOGV("Checks if a valid extractor is created for a given input file");
- string inputFileName = gEnv->getRes() + GetParam().second;
+ string inputFileName = gEnv->getRes() + get<1>(GetParam());
- ASSERT_EQ(setDataSource(inputFileName), 0)
- << "SetDataSource failed for" << GetParam().first << "extractor";
+ int32_t status = setDataSource(inputFileName);
+ ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
- ASSERT_EQ(createExtractor(), 0)
- << "Extractor creation failed for" << GetParam().first << "extractor";
+ status = createExtractor();
+ ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
- // A valid extractor instace should return success for following calls
- ASSERT_GT(mExtractor->countTracks(), 0);
+ int32_t numTracks = mExtractor->countTracks();
+ ASSERT_EQ(numTracks, mNumTracks)
+ << "Extractor reported wrong number of track for the given clip";
AMediaFormat *format = AMediaFormat_new();
ASSERT_NE(format, nullptr) << "AMediaFormat_new returned null AMediaformat";
@@ -337,17 +383,18 @@
TEST_P(ExtractorFunctionalityTest, ExtractorTest) {
if (mDisableTest) return;
- ALOGV("Validates %s Extractor for a given input file", GetParam().first.c_str());
- string inputFileName = gEnv->getRes() + GetParam().second;
+ ALOGV("Validates %s Extractor for a given input file", mContainer.c_str());
+ string inputFileName = gEnv->getRes() + get<1>(GetParam());
int32_t status = setDataSource(inputFileName);
- ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
status = createExtractor();
- ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
int32_t numTracks = mExtractor->countTracks();
- ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+ ASSERT_EQ(numTracks, mNumTracks)
+ << "Extractor reported wrong number of track for the given clip";
for (int32_t idx = 0; idx < numTracks; idx++) {
MediaTrackHelper *track = mExtractor->getTrack(idx);
@@ -388,16 +435,17 @@
if (mDisableTest) return;
ALOGV("Validates Extractor's meta data for a given input file");
- string inputFileName = gEnv->getRes() + GetParam().second;
+ string inputFileName = gEnv->getRes() + get<1>(GetParam());
int32_t status = setDataSource(inputFileName);
- ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
status = createExtractor();
- ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
int32_t numTracks = mExtractor->countTracks();
- ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+ ASSERT_EQ(numTracks, mNumTracks)
+ << "Extractor reported wrong number of track for the given clip";
AMediaFormat *extractorFormat = AMediaFormat_new();
ASSERT_NE(extractorFormat, nullptr) << "AMediaFormat_new returned null AMediaformat";
@@ -462,17 +510,18 @@
TEST_P(ExtractorFunctionalityTest, MultipleStartStopTest) {
if (mDisableTest) return;
- ALOGV("Test %s extractor for multiple start and stop calls", GetParam().first.c_str());
- string inputFileName = gEnv->getRes() + GetParam().second;
+ ALOGV("Test %s extractor for multiple start and stop calls", mContainer.c_str());
+ string inputFileName = gEnv->getRes() + get<1>(GetParam());
int32_t status = setDataSource(inputFileName);
- ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
status = createExtractor();
- ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
int32_t numTracks = mExtractor->countTracks();
- ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+ ASSERT_EQ(numTracks, mNumTracks)
+ << "Extractor reported wrong number of track for the given clip";
// start/stop the tracks multiple times
for (int32_t count = 0; count < kMaxCount; count++) {
@@ -504,22 +553,25 @@
TEST_P(ExtractorFunctionalityTest, SeekTest) {
if (mDisableTest) return;
- ALOGV("Validates %s Extractor behaviour for different seek modes", GetParam().first.c_str());
- string inputFileName = gEnv->getRes() + GetParam().second;
+ ALOGV("Validates %s Extractor behaviour for different seek modes", mContainer.c_str());
+ string inputFileName = gEnv->getRes() + get<1>(GetParam());
int32_t status = setDataSource(inputFileName);
- ASSERT_EQ(status, 0) << "SetDataSource failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
status = createExtractor();
- ASSERT_EQ(status, 0) << "Extractor creation failed for" << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
int32_t numTracks = mExtractor->countTracks();
- ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
+ ASSERT_EQ(numTracks, mNumTracks)
+ << "Extractor reported wrong number of track for the given clip";
uint32_t seekFlag = mExtractor->flags();
- if (!(seekFlag & MediaExtractorPluginHelper::CAN_SEEK)) {
- cout << "[ WARN ] Test Skipped. " << GetParam().first
- << " Extractor doesn't support seek\n";
+ bool seekSupported = get<3>(GetParam());
+ bool seekable = seekFlag & MediaExtractorPluginHelper::CAN_SEEK;
+ if (!seekable) {
+ ASSERT_FALSE(seekSupported) << mContainer << "Extractor is expected to support seek ";
+ cout << "[ WARN ] Test Skipped. " << mContainer << " Extractor doesn't support seek\n";
return;
}
@@ -563,7 +615,7 @@
// next/previous sync frames but not to samples between two sync frames.
getSeekablePoints(seekablePoints, track);
ASSERT_GT(seekablePoints.size(), 0)
- << "Failed to get seekable points for " << GetParam().first << " extractor";
+ << "Failed to get seekable points for " << mContainer << " extractor";
AMediaFormat *trackFormat = AMediaFormat_new();
ASSERT_NE(trackFormat, nullptr) << "AMediaFormat_new returned null format";
@@ -664,23 +716,148 @@
seekablePoints.clear();
}
+// Tests the extractors for seek beyond range : (0, ClipDuration)
+TEST_P(ExtractorFunctionalityTest, MonkeySeekTest) {
+ if (mDisableTest) return;
+ // TODO(b/155630778): Enable test for wav extractors
+ if (mExtractorName == WAV) return;
+
+ ALOGV("Validates %s Extractor behaviour for invalid seek points", mContainer.c_str());
+ string inputFileName = gEnv->getRes() + get<1>(GetParam());
+
+ int32_t status = setDataSource(inputFileName);
+ ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
+
+ status = createExtractor();
+ ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
+
+ int32_t numTracks = mExtractor->countTracks();
+ ASSERT_EQ(numTracks, mNumTracks)
+ << "Extractor reported wrong number of track for the given clip";
+
+ uint32_t seekFlag = mExtractor->flags();
+ bool seekSupported = get<3>(GetParam());
+ bool seekable = seekFlag & MediaExtractorPluginHelper::CAN_SEEK;
+ if (!seekable) {
+ ASSERT_FALSE(seekSupported) << mContainer << "Extractor is expected to support seek ";
+ cout << "[ WARN ] Test Skipped. " << mContainer << " Extractor doesn't support seek\n";
+ return;
+ }
+
+ for (int32_t idx = 0; idx < numTracks; idx++) {
+ MediaTrackHelper *track = mExtractor->getTrack(idx);
+ ASSERT_NE(track, nullptr) << "Failed to get track for index " << idx;
+
+ CMediaTrack *cTrack = wrap(track);
+ ASSERT_NE(cTrack, nullptr) << "Failed to get track wrapper for index " << idx;
+
+ MediaBufferGroup *bufferGroup = new MediaBufferGroup();
+ status = cTrack->start(track, bufferGroup->wrap());
+ ASSERT_EQ(OK, (media_status_t)status) << "Failed to start the track";
+
+ AMediaFormat *trackMeta = AMediaFormat_new();
+ ASSERT_NE(trackMeta, nullptr) << "AMediaFormat_new returned null AMediaformat";
+
+ status = mExtractor->getTrackMetaData(
+ trackMeta, idx, MediaExtractorPluginHelper::kIncludeExtensiveMetaData);
+ ASSERT_EQ(OK, (media_status_t)status) << "Failed to get trackMetaData";
+
+ int64_t clipDuration = 0;
+ AMediaFormat_getInt64(trackMeta, AMEDIAFORMAT_KEY_DURATION, &clipDuration);
+ ASSERT_GT(clipDuration, 0) << "Invalid clip duration ";
+ AMediaFormat_delete(trackMeta);
+
+ int64_t seekToTimeStampUs[] = {-clipDuration, clipDuration / 2, clipDuration,
+ clipDuration * 2};
+ for (int32_t mode = CMediaTrackReadOptions::SEEK_PREVIOUS_SYNC;
+ mode <= CMediaTrackReadOptions::SEEK_CLOSEST; mode++) {
+ for (int64_t seekTimeUs : seekToTimeStampUs) {
+ MediaTrackHelper::ReadOptions *options = new MediaTrackHelper::ReadOptions(
+ mode | CMediaTrackReadOptions::SEEK, seekTimeUs);
+ ASSERT_NE(options, nullptr) << "Cannot create read option";
+
+ MediaBufferHelper *buffer = nullptr;
+ status = track->read(&buffer, options);
+ if (status == AMEDIA_ERROR_END_OF_STREAM) {
+ delete options;
+ continue;
+ }
+ if (buffer) {
+ AMediaFormat *metaData = buffer->meta_data();
+ int64_t timeStamp;
+ AMediaFormat_getInt64(metaData, AMEDIAFORMAT_KEY_TIME_US, &timeStamp);
+ ALOGV("Seeked to timestamp : %lld, requested : %lld", (long long)timeStamp,
+ (long long)seekTimeUs);
+ buffer->release();
+ }
+ delete options;
+ }
+ }
+ status = cTrack->stop(track);
+ ASSERT_EQ(OK, status) << "Failed to stop the track";
+ delete bufferGroup;
+ delete track;
+ }
+}
+
+// Tests extractors for invalid tracks
+TEST_P(ExtractorFunctionalityTest, SanityTest) {
+ if (mDisableTest) return;
+ // TODO(b/155626946): Enable test for MPEG2 TS/PS extractors
+ if (mExtractorName == MPEG2TS || mExtractorName == MPEG2PS) return;
+
+ ALOGV("Validates %s Extractor behaviour for invalid tracks", mContainer.c_str());
+ string inputFileName = gEnv->getRes() + get<1>(GetParam());
+
+ int32_t status = setDataSource(inputFileName);
+ ASSERT_EQ(status, 0) << "SetDataSource failed for" << mContainer << "extractor";
+
+ status = createExtractor();
+ ASSERT_EQ(status, 0) << "Extractor creation failed for" << mContainer << "extractor";
+
+ int32_t numTracks = mExtractor->countTracks();
+ ASSERT_EQ(numTracks, mNumTracks)
+ << "Extractor reported wrong number of track for the given clip";
+
+ int32_t trackIdx[] = {-1, numTracks};
+ for (int32_t idx : trackIdx) {
+ MediaTrackHelper *track = mExtractor->getTrack(idx);
+ ASSERT_EQ(track, nullptr) << "Failed to get track for index " << idx << "\n";
+
+ AMediaFormat *extractorFormat = AMediaFormat_new();
+ ASSERT_NE(extractorFormat, nullptr) << "AMediaFormat_new returned null AMediaformat";
+
+ status = mExtractor->getTrackMetaData(
+ extractorFormat, idx, MediaExtractorPluginHelper::kIncludeExtensiveMetaData);
+ ASSERT_NE(OK, status) << "getTrackMetaData should return error for invalid index " << idx;
+ AMediaFormat_delete(extractorFormat);
+ }
+
+ // Validate Extractor's getTrackMetaData for null format
+ AMediaFormat *mediaFormat = nullptr;
+ status = mExtractor->getTrackMetaData(mediaFormat, 0,
+ MediaExtractorPluginHelper::kIncludeExtensiveMetaData);
+ ASSERT_NE(OK, status) << "getTrackMetaData should return error for null Media format";
+}
+
// This test validates config params for a given input file.
// For this test we only take single track files since the focus of this test is
// to validate the file properties reported by Extractor and not multi-track behavior
TEST_P(ConfigParamTest, ConfigParamValidation) {
if (mDisableTest) return;
- ALOGV("Validates %s Extractor for input's file properties", GetParam().first.c_str());
+ string container = GetParam().first;
+ ALOGV("Validates %s Extractor for input's file properties", container.c_str());
string inputFileName = gEnv->getRes();
- int32_t inputFileIdx = GetParam().second;
+ inputID inputFileId = GetParam().second;
configFormat configParam;
- getFileProperties(inputFileIdx, inputFileName, configParam);
+ getFileProperties(inputFileId, inputFileName, configParam);
int32_t status = setDataSource(inputFileName);
- ASSERT_EQ(status, 0) << "SetDataSource failed for " << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "SetDataSource failed for " << container << "extractor";
status = createExtractor();
- ASSERT_EQ(status, 0) << "Extractor creation failed for " << GetParam().first << "extractor";
+ ASSERT_EQ(status, 0) << "Extractor creation failed for " << container << "extractor";
int32_t numTracks = mExtractor->countTracks();
ASSERT_GT(numTracks, 0) << "Extractor didn't find any track for the given clip";
@@ -907,50 +1084,55 @@
make_pair("loudsoftaac.aac", "loudsoftaac.mkv")));
INSTANTIATE_TEST_SUITE_P(ConfigParamTestAll, ConfigParamTest,
- ::testing::Values(make_pair("aac", 0),
- make_pair("amr", 1),
- make_pair("amr", 2),
- make_pair("ogg", 3),
- make_pair("wav", 4),
- make_pair("flac", 5),
- make_pair("ogg", 6),
- make_pair("mp3", 7),
- make_pair("midi", 8),
- make_pair("mpeg2ts", 9),
- make_pair("mkv", 10),
- make_pair("mpeg4", 11),
- make_pair("mkv", 12),
- make_pair("mpeg2ps", 13)));
+ ::testing::Values(make_pair("aac", AAC_1),
+ make_pair("amr", AMR_NB_1),
+ make_pair("amr", AMR_WB_1),
+ make_pair("flac", FLAC_1),
+ make_pair("wav", GSM_1),
+ make_pair("midi", MIDI_1),
+ make_pair("mp3", MP3_1),
+ make_pair("ogg", OPUS_1),
+ make_pair("ogg", VORBIS_1),
-INSTANTIATE_TEST_SUITE_P(ExtractorUnitTestAll, ExtractorFunctionalityTest,
- ::testing::Values(make_pair("aac", "loudsoftaac.aac"),
- make_pair("amr", "testamr.amr"),
- make_pair("amr", "amrwb.wav"),
- make_pair("ogg", "john_cage.ogg"),
- make_pair("wav", "monotestgsm.wav"),
- make_pair("mpeg2ts", "segment000001.ts"),
- make_pair("mpeg2ts", "testac3ts.ts"),
- make_pair("mpeg2ts", "testac4ts.ts"),
- make_pair("mpeg2ts", "testeac3ts.ts"),
- make_pair("flac", "sinesweepflac.flac"),
- make_pair("ogg", "testopus.opus"),
- make_pair("ogg", "sinesweepoggalbumart.ogg"),
- make_pair("midi", "midi_a.mid"),
- make_pair("mkv", "sinesweepvorbis.mkv"),
- make_pair("mkv", "sinesweepmp3lame.mkv"),
- make_pair("mkv", "loudsoftaac.mkv"),
- make_pair("mpeg4", "sinesweepoggmp4.mp4"),
- make_pair("mp3", "sinesweepmp3lame.mp3"),
- make_pair("mp3", "id3test10.mp3"),
- make_pair("mkv", "swirl_144x136_vp9.webm"),
- make_pair("mkv", "swirl_144x136_vp8.webm"),
- make_pair("mkv", "swirl_144x136_avc.mkv"),
- make_pair("mkv", "withoutcues.mkv"),
- make_pair("mpeg2ps", "swirl_144x136_mpeg2.mpg"),
- make_pair("mpeg2ps", "programstream.mpeg"),
- make_pair("mpeg4", "testac3mp4.mp4"),
- make_pair("mpeg4", "testeac3mp4.mp4"),
- make_pair("mpeg4", "swirl_132x130_mpeg4.mp4")));
+ make_pair("mpeg4", HEVC_1),
+ make_pair("mpeg2ps", MPEG2_PS_1),
+ make_pair("mpeg2ts", MPEG2_TS_1),
+ make_pair("mkv", MPEG4_1),
+ make_pair("mkv", VP9_1)));
+
+// Validate extractors for container format, input file and supports seek flag
+INSTANTIATE_TEST_SUITE_P(
+ ExtractorUnitTestAll, ExtractorFunctionalityTest,
+ ::testing::Values(
+ make_tuple("aac", "loudsoftaac.aac", 1, true),
+ make_tuple("amr", "testamr.amr", 1, true),
+ make_tuple("amr", "amrwb.wav", 1, true),
+ make_tuple("flac", "sinesweepflac.flac", 1, true),
+ make_tuple("midi", "midi_a.mid", 1, true),
+ make_tuple("mkv", "sinesweepvorbis.mkv", 1, true),
+ make_tuple("mkv", "sinesweepmp3lame.mkv", 1, true),
+ make_tuple("mkv", "loudsoftaac.mkv", 1, true),
+ make_tuple("mp3", "sinesweepmp3lame.mp3", 1, true),
+ make_tuple("mp3", "id3test10.mp3", 1, true),
+ make_tuple("mpeg2ts", "segment000001.ts", 2, false),
+ make_tuple("mpeg2ts", "testac3ts.ts", 1, false),
+ make_tuple("mpeg2ts", "testac4ts.ts", 1, false),
+ make_tuple("mpeg2ts", "testeac3ts.ts", 1, false),
+ make_tuple("mpeg4", "sinesweepoggmp4.mp4", 1, true),
+ make_tuple("mpeg4", "testac3mp4.mp4", 1, true),
+ make_tuple("mpeg4", "testeac3mp4.mp4", 1, true),
+ make_tuple("ogg", "john_cage.ogg", 1, true),
+ make_tuple("ogg", "testopus.opus", 1, true),
+ make_tuple("ogg", "sinesweepoggalbumart.ogg", 1, true),
+ make_tuple("wav", "monotestgsm.wav", 1, true),
+
+ make_tuple("mkv", "swirl_144x136_avc.mkv", 1, true),
+ make_tuple("mkv", "withoutcues.mkv", 2, true),
+ make_tuple("mkv", "swirl_144x136_vp9.webm", 1, true),
+ make_tuple("mkv", "swirl_144x136_vp8.webm", 1, true),
+ make_tuple("mpeg2ps", "swirl_144x136_mpeg2.mpg", 1, false),
+ make_tuple("mpeg2ps", "programstream.mpeg", 2, false),
+ make_tuple("mpeg4", "swirl_132x130_mpeg4.mp4", 1, true)));
int main(int argc, char **argv) {
gEnv = new ExtractorUnitTestEnvironment();
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index bc973bd..2699dfe 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -314,8 +314,11 @@
void AudioStream::setState(aaudio_stream_state_t state) {
ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
+ if (state == mState) {
+ return; // no change
+ }
// Track transition to DISCONNECTED state.
- if (state == AAUDIO_STREAM_STATE_DISCONNECTED && mState != state) {
+ if (state == AAUDIO_STREAM_STATE_DISCONNECTED) {
android::mediametrics::LogItem(mMetricsId)
.set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
.set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
@@ -323,18 +326,18 @@
}
// CLOSED is a final state
if (mState == AAUDIO_STREAM_STATE_CLOSED) {
- ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
+ ALOGW("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
// Once CLOSING, we can only move to CLOSED state.
} else if (mState == AAUDIO_STREAM_STATE_CLOSING
&& state != AAUDIO_STREAM_STATE_CLOSED) {
- ALOGE("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
+ ALOGW("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
// Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
} else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
&& !(state == AAUDIO_STREAM_STATE_CLOSING
|| state == AAUDIO_STREAM_STATE_CLOSED)) {
- ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
+ ALOGW("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
} else {
mState = state;
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index 6e5110f..d50a74b 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -212,9 +212,6 @@
setSamplesPerFrame(mAudioRecord->channelCount());
int32_t actualSampleRate = mAudioRecord->getSampleRate();
- ALOGW_IF(actualSampleRate != getSampleRate(),
- "open() sampleRate changed from %d to %d",
- getSampleRate(), actualSampleRate);
setSampleRate(actualSampleRate);
// We may need to pass the data through a block size adapter to guarantee constant size.
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index ea08361..74292dd 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -195,9 +195,6 @@
setDeviceFormat(mAudioTrack->format());
int32_t actualSampleRate = mAudioTrack->getSampleRate();
- ALOGW_IF(actualSampleRate != getSampleRate(),
- "open() sampleRate changed from %d to %d",
- getSampleRate(), actualSampleRate);
setSampleRate(actualSampleRate);
// We may need to pass the data through a block size adapter to guarantee constant size.
@@ -240,11 +237,11 @@
setSharingMode(AAUDIO_SHARING_MODE_SHARED); // EXCLUSIVE mode not supported in legacy
- // Log warning if we did not get what we asked for.
- ALOGW_IF(actualFlags != flags,
+ // Log if we did not get what we asked for.
+ ALOGD_IF(actualFlags != flags,
"open() flags changed from 0x%08X to 0x%08X",
flags, actualFlags);
- ALOGW_IF(actualPerformanceMode != perfMode,
+ ALOGD_IF(actualPerformanceMode != perfMode,
"open() perfMode changed from %d to %d",
perfMode, actualPerformanceMode);
diff --git a/media/libeffects/preprocessing/Android.bp b/media/libeffects/preprocessing/Android.bp
index c87635f..16cd0ad 100644
--- a/media/libeffects/preprocessing/Android.bp
+++ b/media/libeffects/preprocessing/Android.bp
@@ -8,12 +8,6 @@
srcs: ["PreProcessing.cpp"],
- include_dirs: [
- "external/webrtc",
- "external/webrtc/webrtc/modules/include",
- "external/webrtc/webrtc/modules/audio_processing/include",
- ],
-
shared_libs: [
"libwebrtc_audio_preprocessing",
"libspeexresampler",
diff --git a/media/libmediatranscoding/tests/assets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4 b/media/libmediatranscoding/tests/assets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
new file mode 100644
index 0000000..df42a15
--- /dev/null
+++ b/media/libmediatranscoding/tests/assets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4
Binary files differ
diff --git a/media/libmediatranscoding/tests/assets/push_assets.sh b/media/libmediatranscoding/tests/assets/push_assets.sh
index 2fcb233..8c85e58 100755
--- a/media/libmediatranscoding/tests/assets/push_assets.sh
+++ b/media/libmediatranscoding/tests/assets/push_assets.sh
@@ -21,5 +21,5 @@
#TODO(hkuang): Check if the destination folder already exists. If so, skip the copying.
echo "Copying files to device"
-adb push $ANDROID_BUILD_TOP/frameworks/av/media/libmediatranscoding/tests/assets /data/local/tmp/TranscodingTestAssets
+adb push $ANDROID_BUILD_TOP/frameworks/av/media/libmediatranscoding/tests/assets/* /data/local/tmp/TranscodingTestAssets
echo "Copy done"
diff --git a/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp b/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
index aaa2adb..0fdb0b7 100644
--- a/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
+++ b/media/libmediatranscoding/transcoder/MediaSampleWriter.cpp
@@ -26,7 +26,19 @@
class DefaultMuxer : public MediaSampleWriterMuxerInterface {
public:
// MediaSampleWriterMuxerInterface
- ssize_t addTrack(const AMediaFormat* trackFormat) override {
+ ssize_t addTrack(AMediaFormat* trackFormat) override {
+ // If the track format has rotation, need to call AMediaMuxer_setOrientationHint
+ // to set the rotation. Muxer doesn't take rotation specified on the track.
+ const char* mime;
+ if (AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &mime) &&
+ strncmp(mime, "video/", 6) == 0) {
+ int32_t rotation;
+ if (AMediaFormat_getInt32(trackFormat, AMEDIAFORMAT_KEY_ROTATION, &rotation) &&
+ (rotation != 0)) {
+ AMediaMuxer_setOrientationHint(mMuxer, rotation);
+ }
+ }
+
return AMediaMuxer_addTrack(mMuxer, trackFormat);
}
media_status_t start() override { return AMediaMuxer_start(mMuxer); }
@@ -213,4 +225,4 @@
return AMEDIA_OK;
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index 96e2e61..4df3296 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -139,6 +139,10 @@
}
AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_COLOR_FORMAT, kColorFormatSurface);
+ // Always encode without rotation. The rotation degree will be transferred directly to
+ // MediaSampleWriter track format, and MediaSampleWriter will call AMediaMuxer_setOrientationHint.
+ AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_ROTATION, 0);
+
mDestinationFormat = std::shared_ptr<AMediaFormat>(encoderFormat, &AMediaFormat_delete);
// Create and configure the encoder.
@@ -339,25 +343,35 @@
// at container level. This is supposed to override any SAR settings in the bitstream,
// thus should always be transferred to the container of the transcoded file.
int32_t sarWidth, sarHeight;
- if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_WIDTH, &sarWidth) &&
+ if (AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_SAR_WIDTH, &sarWidth) &&
(sarWidth > 0) &&
- AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_HEIGHT, &sarHeight) &&
+ AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_SAR_HEIGHT, &sarHeight) &&
(sarHeight > 0)) {
AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth);
AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight);
}
// Transfer DAR settings.
int32_t displayWidth, displayHeight;
- if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_WIDTH,
- &displayWidth) &&
+ if (AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_WIDTH, &displayWidth) &&
(displayWidth > 0) &&
- AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
+ AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
&displayHeight) &&
(displayHeight > 0)) {
AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_WIDTH, displayWidth);
AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, displayHeight);
}
+ // Transfer rotation settings.
+ // Note that muxer itself doesn't take rotation from the track format. It requires
+ // AMediaMuxer_setOrientationHint to set the rotation. Here we pass the rotation to
+ // MediaSampleWriter using the track format. MediaSampleWriter will then call
+ // AMediaMuxer_setOrientationHint as needed.
+ int32_t rotation;
+ if (AMediaFormat_getInt32(mSourceFormat.get(), AMEDIAFORMAT_KEY_ROTATION, &rotation) &&
+ (rotation != 0)) {
+ AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_ROTATION, rotation);
+ }
+
// TODO: transfer other fields as required.
mActualOutputFormat = std::shared_ptr<AMediaFormat>(formatCopy, &AMediaFormat_delete);
diff --git a/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h b/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
index 4d0264b..da83167 100644
--- a/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
+++ b/media/libmediatranscoding/transcoder/include/media/MediaSampleWriter.h
@@ -41,7 +41,7 @@
* @param trackFormat Format of the new track.
* @return A non-negative track index on success, or a negative number on failure.
*/
- virtual ssize_t addTrack(const AMediaFormat* trackFormat) = 0;
+ virtual ssize_t addTrack(AMediaFormat* trackFormat) = 0;
/** Starts the muxer. */
virtual media_status_t start() = 0;
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
index 9ffb32b..98813e7 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
@@ -58,7 +58,7 @@
class TestMuxer : public MediaSampleWriterMuxerInterface {
public:
// MuxerInterface
- ssize_t addTrack(const AMediaFormat* trackFormat) override {
+ ssize_t addTrack(AMediaFormat* trackFormat) override {
mEventQueue.push_back(AddTrack(trackFormat));
return mTrackCount++;
}
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
index 4d9386a..71d3a4e 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
@@ -67,7 +67,7 @@
void initSampleReader() {
const char* sourcePath =
- "/data/local/tmp/TranscoderTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+ "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
const int sourceFd = open(sourcePath, O_RDONLY);
ASSERT_GT(sourceFd, 0);
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index 6bf6562..67f1ca1 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -40,7 +40,7 @@
struct FormatVerifierEntry {
const char* key;
- bool (*equal)(const char* key, AMediaFormat* src, AMediaFormat* dst);
+ std::function<bool(const char*, AMediaFormat*, AMediaFormat*)> equal;
};
static const FormatVerifierEntry kFieldsToPreserve[] = {
@@ -92,11 +92,6 @@
bool mFinished = false;
};
-static const char* SOURCE_PATH_AVC =
- "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
-static const char* SOURCE_PATH_HEVC =
- "/data/local/tmp/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4";
-
// Write-only, create file if non-existent, don't overwrite existing file.
static constexpr int kOpenFlags = O_WRONLY | O_CREAT | O_EXCL;
// User R+W permission.
@@ -161,6 +156,44 @@
return mCallbacks->mStatus;
}
+ void testTranscodeVideo(const char* srcPath, const char* destPath, const char* dstMime) {
+ const int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs
+
+ EXPECT_EQ(
+ transcodeHelper(
+ srcPath, destPath,
+ [dstMime](AMediaFormat* sourceFormat) {
+ AMediaFormat* format = nullptr;
+ const char* mime = nullptr;
+ AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+
+ if (strncmp(mime, "video/", 6) == 0) {
+ format = AMediaFormat_new();
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
+
+ if (dstMime != nullptr) {
+ AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, dstMime);
+ }
+ }
+ return format;
+ }),
+ AMEDIA_OK);
+
+ if (dstMime != nullptr) {
+ std::vector<FormatVerifierEntry> extraVerifiers = {
+ {AMEDIAFORMAT_KEY_MIME,
+ [dstMime](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
+ const char* mime = nullptr;
+ AMediaFormat_getString(dst, key, &mime);
+ return !strcmp(mime, dstMime);
+ }},
+ };
+ verifyOutputFormat(destPath, &extraVerifiers);
+ } else {
+ verifyOutputFormat(destPath);
+ }
+ }
+
void verifyOutputFormat(const char* destPath,
const std::vector<FormatVerifierEntry>* extraVerifiers = nullptr) {
int dstFd = open(destPath, O_RDONLY);
@@ -194,7 +227,8 @@
for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
- mSourceVideoFormat.get(), videoFormat.get()));
+ mSourceVideoFormat.get(), videoFormat.get()))
+ << "Failed at key " << kFieldsToPreserve[i].key;
}
if (extraVerifiers != nullptr) {
@@ -212,76 +246,31 @@
};
TEST_F(MediaTranscoderTests, TestPassthrough) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
const char* destPath = "/data/local/tmp/MediaTranscoder_Passthrough.MP4";
- EXPECT_EQ(transcodeHelper(SOURCE_PATH_AVC, destPath, [](AMediaFormat*) { return nullptr; }),
- AMEDIA_OK);
+ EXPECT_EQ(transcodeHelper(srcPath, destPath, [](AMediaFormat*) { return nullptr; }), AMEDIA_OK);
verifyOutputFormat(destPath);
}
-TEST_F(MediaTranscoderTests, TestBasicVideoTranscodeAvcToAvc) {
- const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscodeAvcToAvc.MP4";
- const int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs
-
- EXPECT_EQ(transcodeHelper(
- SOURCE_PATH_AVC, destPath,
- [](AMediaFormat* sourceFormat) {
- AMediaFormat* format = nullptr;
- const char* mime = nullptr;
- AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
-
- if (strncmp(mime, "video/", 6) == 0) {
- format = AMediaFormat_new();
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
- }
- return format;
- }),
- AMEDIA_OK);
-
- std::vector<FormatVerifierEntry> extraVerifiers = {
- {AMEDIAFORMAT_KEY_MIME,
- [](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
- const char* mime = nullptr;
- AMediaFormat_getString(dst, key, &mime);
- return !strcmp(mime, AMEDIA_MIMETYPE_VIDEO_AVC);
- }},
- };
-
- verifyOutputFormat(destPath, &extraVerifiers);
+TEST_F(MediaTranscoderTests, TestVideoTranscode_AvcToAvc_Basic) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+ const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_AvcToAvc_Basic.MP4";
+ testTranscodeVideo(srcPath, destPath, nullptr /*dstMime*/);
}
-TEST_F(MediaTranscoderTests, TestBasicVideoTranscodeHevcToAvc) {
- const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscodeHevcToAvc.MP4";
+TEST_F(MediaTranscoderTests, TestVideoTranscode_HevcToAvc_Basic) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4";
+ const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_HevcToAvc_Basic.MP4";
+ testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
+}
- EXPECT_EQ(transcodeHelper(
- SOURCE_PATH_HEVC, destPath,
- [](AMediaFormat* sourceFormat) {
- AMediaFormat* format = nullptr;
- const char* mime = nullptr;
- AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
-
- if (strncmp(mime, "video/", 6) == 0) {
- const int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs
- format = AMediaFormat_new();
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
- AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME,
- AMEDIA_MIMETYPE_VIDEO_AVC);
- }
- return format;
- }),
- AMEDIA_OK);
-
- std::vector<FormatVerifierEntry> extraVerifiers = {
- {AMEDIAFORMAT_KEY_MIME,
- [](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
- const char* mime = nullptr;
- AMediaFormat_getString(dst, key, &mime);
- return !strcmp(mime, AMEDIA_MIMETYPE_VIDEO_AVC);
- }},
- };
-
- verifyOutputFormat(destPath, &extraVerifiers);
+TEST_F(MediaTranscoderTests, TestVideoTranscode_HevcToAvc_Rotation) {
+ const char* srcPath =
+ "/data/local/tmp/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4";
+ const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_HevcToAvc_Rotation.MP4";
+ testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
}
} // namespace android
diff --git a/media/libstagefright/Android.bp b/media/libstagefright/Android.bp
index 2f149de..c180edf 100644
--- a/media/libstagefright/Android.bp
+++ b/media/libstagefright/Android.bp
@@ -70,9 +70,18 @@
},
header_libs: [
+ "libaudioclient_headers",
"libstagefright_foundation_headers",
+ "media_ndk_headers",
],
- shared_libs: ["libmediandk"],
+
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+
export_include_dirs: ["include"],
}
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 823c010..4da85a2 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -567,7 +567,7 @@
release();
}
- if (fallocate(mFd, FALLOC_FL_KEEP_SIZE, 0, 1) == 0) {
+ if (fallocate64(mFd, FALLOC_FL_KEEP_SIZE, 0, 1) == 0) {
ALOGD("PreAllocation enabled");
mPreAllocationEnabled = true;
} else {
@@ -1896,7 +1896,7 @@
ALOGV("preAllocateSize :%" PRIu64 " lastFileEndOffset:%" PRIu64, preAllocateSize,
lastFileEndOffset);
- int res = fallocate(mFd, FALLOC_FL_KEEP_SIZE, lastFileEndOffset, preAllocateSize);
+ int res = fallocate64(mFd, FALLOC_FL_KEEP_SIZE, lastFileEndOffset, preAllocateSize);
if (res == -1) {
ALOGE("fallocate err:%s, %d, fd:%d", strerror(errno), errno, mFd);
sp<AMessage> msg = new AMessage(kWhatFallocateError, mReflector);
@@ -1923,7 +1923,7 @@
ALOGD("ftruncate mPreAllocateFileEndOffset:%" PRId64 " mOffset:%" PRIu64
" mMdatEndOffset:%" PRIu64 " diff:%" PRId64, mPreAllocateFileEndOffset, mOffset,
mMdatEndOffset, mPreAllocateFileEndOffset - endOffset);
- if (ftruncate(mFd, endOffset) == -1) {
+ if (ftruncate64(mFd, endOffset) == -1) {
ALOGE("ftruncate err:%s, %d, fd:%d", strerror(errno), errno, mFd);
status = false;
/* No need to post and handle(stop & notify client) error like it's done in preAllocate(),
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index d5272bc..d6d472b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -690,7 +690,9 @@
const sp<SwAudioOutputDescriptor> outputDesc = this->valueAt(i);
if (outputDesc->isActive(volumeSource, inPastMs, sysTime)
&& (!(outputDesc->devices()
- .containsDeviceAmongTypes(getAllOutRemoteDevices())))) {
+ .containsDeviceAmongTypes(getAllOutRemoteDevices())
+ || outputDesc->devices()
+ .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)))) {
return true;
}
}
@@ -722,7 +724,11 @@
const sp<SwAudioOutputDescriptor> otherDesc = valueAt(i);
if (desc->sharesHwModuleWith(otherDesc) &&
otherDesc->isStrategyActive(ps, inPastMs, sysTime)) {
- return true;
+ if (desc == otherDesc
+ || !otherDesc->devices()
+ .onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
+ return true;
+ }
}
}
return false;
diff --git a/services/mediatranscoding/MediaTranscodingService.cpp b/services/mediatranscoding/MediaTranscodingService.cpp
index 2b97c2e..b0ea0db 100644
--- a/services/mediatranscoding/MediaTranscodingService.cpp
+++ b/services/mediatranscoding/MediaTranscodingService.cpp
@@ -84,7 +84,7 @@
//static
void MediaTranscodingService::instantiate() {
std::shared_ptr<TranscoderInterface> transcoder;
- if (property_get_bool("debug.transcoding.simulated_transcoder", true)) {
+ if (property_get_bool("debug.transcoding.simulated_transcoder", false)) {
transcoder = std::make_shared<SimulatedTranscoder>();
} else {
transcoder = std::make_shared<TranscoderWrapper>();