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/tests/MediaSampleReaderNDKTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
index 323e5ae..e8acd48 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaSampleReaderNDKTests.cpp
@@ -26,10 +26,14 @@
 #include <gtest/gtest.h>
 #include <media/MediaSampleReaderNDK.h>
 #include <utils/Timers.h>
-
 #include <cmath>
+#include <mutex>
+#include <thread>
 
 // TODO(b/153453392): Test more asset types and validate sample data from readSampleDataForTrack.
+// TODO(b/153453392): Test for sequential and parallel (single thread and multi thread) access.
+// TODO(b/153453392): Test for switching between sequential and parallel access in different points
+//  of time.
 
 namespace android {
 
@@ -121,48 +125,47 @@
             MediaSampleReaderNDK::createFromFd(mSourceFd, 0, mFileSize);
     ASSERT_TRUE(sampleReader);
 
-    MediaSampleInfo info;
-    int trackEosCount = 0;
-    std::vector<bool> trackReachedEos(mTrackCount, false);
-    std::vector<std::vector<int64_t>> readerTimestamps(mTrackCount);
+    for (int trackIndex = 0; trackIndex < mTrackCount; trackIndex++) {
+        EXPECT_EQ(sampleReader->selectTrack(trackIndex), AMEDIA_OK);
+    }
 
     // Initialize the extractor timestamps.
     initExtractorTimestamps();
 
-    // Read 5s of each track at a time.
-    const int64_t chunkDurationUs = SEC_TO_USEC(5);
-    int64_t chunkEndTimeUs = chunkDurationUs;
+    std::mutex timestampMutex;
+    std::vector<std::thread> trackThreads;
+    std::vector<std::vector<int64_t>> readerTimestamps(mTrackCount);
 
-    // Loop until all tracks have reached End Of Stream.
-    while (trackEosCount < mTrackCount) {
-        for (int trackIndex = 0; trackIndex < mTrackCount; trackIndex++) {
-            if (trackReachedEos[trackIndex]) continue;
-
-            // Advance current track to next chunk end time.
-            do {
+    for (int trackIndex = 0; trackIndex < mTrackCount; trackIndex++) {
+        trackThreads.emplace_back([sampleReader, trackIndex, &timestampMutex, &readerTimestamps] {
+            MediaSampleInfo info;
+            while (true) {
                 media_status_t status = sampleReader->getSampleInfoForTrack(trackIndex, &info);
                 if (status != AMEDIA_OK) {
-                    ASSERT_EQ(status, AMEDIA_ERROR_END_OF_STREAM);
-                    ASSERT_TRUE((info.flags & SAMPLE_FLAG_END_OF_STREAM) != 0);
-                    trackReachedEos[trackIndex] = true;
-                    trackEosCount++;
+                    EXPECT_EQ(status, AMEDIA_ERROR_END_OF_STREAM);
+                    EXPECT_TRUE((info.flags & SAMPLE_FLAG_END_OF_STREAM) != 0);
                     break;
                 }
                 ASSERT_TRUE((info.flags & SAMPLE_FLAG_END_OF_STREAM) == 0);
+                timestampMutex.lock();
                 readerTimestamps[trackIndex].push_back(info.presentationTimeUs);
+                timestampMutex.unlock();
                 sampleReader->advanceTrack(trackIndex);
-            } while (info.presentationTimeUs < chunkEndTimeUs);
-        }
-        chunkEndTimeUs += chunkDurationUs;
+            }
+        });
+    }
+
+    for (auto& thread : trackThreads) {
+        thread.join();
     }
 
     for (int trackIndex = 0; trackIndex < mTrackCount; trackIndex++) {
         LOG(DEBUG) << "Track " << trackIndex << ", comparing "
                    << readerTimestamps[trackIndex].size() << " samples.";
-        ASSERT_EQ(readerTimestamps[trackIndex].size(), mExtractorTimestamps[trackIndex].size());
+        EXPECT_EQ(readerTimestamps[trackIndex].size(), mExtractorTimestamps[trackIndex].size());
         for (size_t sampleIndex = 0; sampleIndex < readerTimestamps[trackIndex].size();
              sampleIndex++) {
-            ASSERT_EQ(readerTimestamps[trackIndex][sampleIndex],
+            EXPECT_EQ(readerTimestamps[trackIndex][sampleIndex],
                       mExtractorTimestamps[trackIndex][sampleIndex]);
         }
     }
@@ -178,6 +181,8 @@
 
     std::vector<int32_t> actualTrackBitrates = getTrackBitrates();
     for (int trackIndex = 0; trackIndex < mTrackCount; ++trackIndex) {
+        EXPECT_EQ(sampleReader->selectTrack(trackIndex), AMEDIA_OK);
+
         int32_t bitrate;
         EXPECT_EQ(sampleReader->getEstimatedBitrateForTrack(trackIndex, &bitrate), AMEDIA_OK);
         EXPECT_GT(bitrate, 0);