Transcoder: Add support for pausing transcoding on a sync frame.

- Added support for stopping transcoders on a sync frame.
- Refactored MediaTrackTranscoders and MediaSampleWriter to stop()
asynchronously.
- Fixed callback and error handling logic in MediaTranscoder.
- Added tests for pause and stopping on sync frame.

Bug: 162886306
Test: Unit tests.

Change-Id: If689a10dfee198c674c4c13b865a7c56a901e075
diff --git a/media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
index 698594f..15f7427 100644
--- a/media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp
@@ -69,41 +69,44 @@
         LOG(ERROR) << "TrackTranscoder must be configured before started";
         return false;
     }
+    mState = STARTED;
 
-    mTranscodingThread = std::thread([this] {
-        media_status_t status = runTranscodeLoop();
+    std::thread([this] {
+        bool stopped = false;
+        media_status_t status = runTranscodeLoop(&stopped);
+
+        // Output an EOS sample if the transcoder was stopped.
+        if (stopped) {
+            auto sample = std::make_shared<MediaSample>();
+            sample->info.flags = SAMPLE_FLAG_END_OF_STREAM;
+            onOutputSampleAvailable(sample);
+        }
 
         // Notify the client.
         if (auto callbacks = mTranscoderCallback.lock()) {
-            if (status != AMEDIA_OK) {
-                callbacks->onTrackError(this, status);
-            } else {
+            if (stopped) {
+                callbacks->onTrackStopped(this);
+            } else if (status == AMEDIA_OK) {
                 callbacks->onTrackFinished(this);
+            } else {
+                callbacks->onTrackError(this, status);
             }
         }
-    });
+    }).detach();
 
-    mState = STARTED;
     return true;
 }
 
-bool MediaTrackTranscoder::stop() {
+void MediaTrackTranscoder::stop(bool stopOnSyncSample) {
     std::scoped_lock lock{mStateMutex};
 
-    if (mState == STARTED) {
+    if (mState == STARTED || (mStopRequest == STOP_ON_SYNC && !stopOnSyncSample)) {
+        mStopRequest = stopOnSyncSample ? STOP_ON_SYNC : STOP_NOW;
         abortTranscodeLoop();
-        mMediaSampleReader->setEnforceSequentialAccess(false);
-        mTranscodingThread.join();
-        {
-            std::scoped_lock lock{mSampleMutex};
-            mSampleQueue.abort();  // Release any buffered samples.
-        }
         mState = STOPPED;
-        return true;
+    } else {
+        LOG(WARNING) << "TrackTranscoder must be started before stopped";
     }
-
-    LOG(ERROR) << "TrackTranscoder must be started before stopped";
-    return false;
 }
 
 void MediaTrackTranscoder::notifyTrackFormatAvailable() {