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