transcoder: wait for actual encoder output format to start writer

bug: 154734285
bug: 158240484

test: unit tests. In particular:

run MediaTranscoderTests and MediaTranscodingServiceRealTests, and
check the output files. Should play with proper aspect ratio on
host and device.

Change-Id: I8254fd8bd42678a414cab5fb0f61c4ba56d6c114
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
index 3db7455..69932f4 100644
--- a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
@@ -95,12 +95,41 @@
         // Transcoding is done and the callback to the client has been sent, so tear down the
         // pipeline but do it asynchronously to avoid deadlocks. If an error occurred, client
         // should clean up the file.
-        std::thread asyncCancelThread{
-                [self = shared_from_this()] { self->cancel(); }};
+        std::thread asyncCancelThread{[self = shared_from_this()] { self->cancel(); }};
         asyncCancelThread.detach();
     }
 }
 
+void MediaTranscoder::onTrackFormatAvailable(const MediaTrackTranscoder* transcoder) {
+    LOG(INFO) << "TrackTranscoder " << transcoder << " format available.";
+
+    std::scoped_lock lock{mTracksAddedMutex};
+
+    // Ignore duplicate format change.
+    if (mTracksAdded.count(transcoder) > 0) {
+        return;
+    }
+
+    // Add track to the writer.
+    const bool ok =
+            mSampleWriter->addTrack(transcoder->getOutputQueue(), transcoder->getOutputFormat());
+    if (!ok) {
+        LOG(ERROR) << "Unable to add track to sample writer.";
+        sendCallback(AMEDIA_ERROR_UNKNOWN);
+        return;
+    }
+
+    mTracksAdded.insert(transcoder);
+    if (mTracksAdded.size() == mTrackTranscoders.size()) {
+        LOG(INFO) << "Starting sample writer.";
+        bool started = mSampleWriter->start();
+        if (!started) {
+            LOG(ERROR) << "Unable to start sample writer.";
+            sendCallback(AMEDIA_ERROR_UNKNOWN);
+        }
+    }
+}
+
 void MediaTranscoder::onTrackFinished(const MediaTrackTranscoder* transcoder) {
     LOG(DEBUG) << "TrackTranscoder " << transcoder << " finished";
 }
@@ -116,7 +145,7 @@
 }
 
 MediaTranscoder::MediaTranscoder(const std::shared_ptr<CallbackInterface>& callbacks)
-     : mCallbacks(callbacks) {}
+      : mCallbacks(callbacks) {}
 
 std::shared_ptr<MediaTranscoder> MediaTranscoder::create(
         const std::shared_ptr<CallbackInterface>& callbacks,
@@ -268,25 +297,9 @@
         return AMEDIA_ERROR_INVALID_OPERATION;
     }
 
-    // Add tracks to the writer.
-    for (auto& transcoder : mTrackTranscoders) {
-        const bool ok = mSampleWriter->addTrack(transcoder->getOutputQueue(),
-                                                transcoder->getOutputFormat());
-        if (!ok) {
-            LOG(ERROR) << "Unable to add track to sample writer.";
-            return AMEDIA_ERROR_UNKNOWN;
-        }
-    }
-
-    bool started = mSampleWriter->start();
-    if (!started) {
-        LOG(ERROR) << "Unable to start sample writer.";
-        return AMEDIA_ERROR_UNKNOWN;
-    }
-
     // Start transcoders
     for (auto& transcoder : mTrackTranscoders) {
-        started = transcoder->start();
+        bool started = transcoder->start();
         if (!started) {
             LOG(ERROR) << "Unable to start track transcoder.";
             cancel();