Transcoder: Improve AV transcoding speed by enforcing sequential sample access.
MediaSampleReader was bottlenecking the transcoding pipeline due to
non-sequential sample access. This commit adds an option to the sample
reader to enforce sequential sample access by blocking reads until
the underlying extractor advances to that specific track.
Follow-up: b/165374867 Make MediaSampleWriter robust against buffering track transcoders
Fixes: 160268606
Test: Transcoder unit tests, and benchmark tests.
Change-Id: Id2a363d06df927ea3e547462c52803594e0511e1
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
index a651fa2..f0b9304 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaSampleReaderBenchmark.cpp
@@ -42,8 +42,8 @@
using namespace android;
static void ReadMediaSamples(benchmark::State& state, const std::string& srcFileName,
- bool readAudio) {
- // Asset directory
+ bool readAudio, bool sequentialAccess = false) {
+ // Asset directory.
static const std::string kAssetDirectory = "/data/local/tmp/TranscodingBenchmark/";
int srcFd = 0;
@@ -59,9 +59,13 @@
for (auto _ : state) {
auto sampleReader = MediaSampleReaderNDK::createFromFd(srcFd, 0, fileSize);
+ if (sampleReader->setEnforceSequentialAccess(sequentialAccess) != AMEDIA_OK) {
+ state.SkipWithError("setEnforceSequentialAccess failed");
+ return;
+ }
- std::vector<std::thread> trackThreads;
-
+ // Select tracks.
+ std::vector<int> trackIndices;
for (int trackIndex = 0; trackIndex < sampleReader->getTrackCount(); ++trackIndex) {
const char* mime = nullptr;
@@ -78,6 +82,13 @@
continue;
}
+ trackIndices.push_back(trackIndex);
+ sampleReader->selectTrack(trackIndex);
+ }
+
+ // Start threads.
+ std::vector<std::thread> trackThreads;
+ for (auto trackIndex : trackIndices) {
trackThreads.emplace_back([trackIndex, sampleReader, &state] {
LOG(INFO) << "Track " << trackIndex << " started";
MediaSampleInfo info;
@@ -102,14 +113,13 @@
state.SkipWithError("Error reading sample data");
break;
}
-
- sampleReader->advanceTrack(trackIndex);
}
LOG(INFO) << "Track " << trackIndex << " finished";
});
}
+ // Join threads.
for (auto& thread : trackThreads) {
thread.join();
}
@@ -122,17 +132,23 @@
#define TRANSCODER_BENCHMARK(func) \
BENCHMARK(func)->UseRealTime()->MeasureProcessCPUTime()->Unit(benchmark::kMillisecond)
-static void BM_MediaSampleReader_AudioVideo(benchmark::State& state) {
+static void BM_MediaSampleReader_AudioVideo_Parallel(benchmark::State& state) {
ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
true /* readAudio */);
}
+static void BM_MediaSampleReader_AudioVideo_Sequential(benchmark::State& state) {
+ ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
+ true /* readAudio */, true /* sequentialAccess */);
+}
+
static void BM_MediaSampleReader_Video(benchmark::State& state) {
ReadMediaSamples(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
false /* readAudio */);
}
-TRANSCODER_BENCHMARK(BM_MediaSampleReader_AudioVideo);
+TRANSCODER_BENCHMARK(BM_MediaSampleReader_AudioVideo_Parallel);
+TRANSCODER_BENCHMARK(BM_MediaSampleReader_AudioVideo_Sequential);
TRANSCODER_BENCHMARK(BM_MediaSampleReader_Video);
BENCHMARK_MAIN();
diff --git a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
index b31b675..ccd9353 100644
--- a/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
+++ b/media/libmediatranscoding/transcoder/benchmark/MediaTranscoderBenchmark.cpp
@@ -77,7 +77,8 @@
};
static void TranscodeMediaFile(benchmark::State& state, const std::string& srcFileName,
- const std::string& dstFileName, bool includeAudio) {
+ const std::string& dstFileName, bool includeAudio,
+ bool transcodeVideo = true) {
// Default bitrate
static constexpr int32_t kVideoBitRate = 20 * 1000 * 1000; // 20Mbs
// Write-only, create file if non-existent.
@@ -132,8 +133,10 @@
}
if (strncmp(mime, "video/", 6) == 0) {
- dstFormat = AMediaFormat_new();
- AMediaFormat_setInt32(dstFormat, AMEDIAFORMAT_KEY_BIT_RATE, kVideoBitRate);
+ if (transcodeVideo) {
+ dstFormat = AMediaFormat_new();
+ AMediaFormat_setInt32(dstFormat, AMEDIAFORMAT_KEY_BIT_RATE, kVideoBitRate);
+ }
int32_t frameCount;
if (AMediaFormat_getInt32(srcFormat, AMEDIAFORMAT_KEY_FRAME_COUNT, &frameCount)) {
@@ -198,8 +201,21 @@
false /* includeAudio */);
}
+static void BM_TranscodeAudioVideoPassthrough(benchmark::State& state) {
+ TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps_aac.mp4",
+ "video_1920x1080_3648frame_h264_22Mbps_30fps_aac_passthrough_AV.mp4",
+ true /* includeAudio */, false /* transcodeVideo */);
+}
+static void BM_TranscodeVideoPassthrough(benchmark::State& state) {
+ TranscodeMediaFile(state, "video_1920x1080_3648frame_h264_22Mbps_30fps.mp4",
+ "video_1920x1080_3648frame_h264_22Mbps_30fps_passthrough_AV.mp4",
+ false /* includeAudio */, false /* transcodeVideo */);
+}
+
TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcAudioVideo2AudioVideo);
TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcAudioVideo2Video);
TRANSCODER_BENCHMARK(BM_TranscodeAvc2AvcVideo2Video);
+TRANSCODER_BENCHMARK(BM_TranscodeAudioVideoPassthrough);
+TRANSCODER_BENCHMARK(BM_TranscodeVideoPassthrough);
BENCHMARK_MAIN();