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();