1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_MEDIA_TRACK_TRANSCODER_H 18 #define ANDROID_MEDIA_TRACK_TRANSCODER_H 19 20 #include <media/MediaSampleQueue.h> 21 #include <media/MediaSampleReader.h> 22 #include <media/MediaSampleWriter.h> 23 #include <media/NdkMediaError.h> 24 #include <media/NdkMediaFormat.h> 25 #include <utils/Mutex.h> 26 27 #include <functional> 28 #include <memory> 29 #include <mutex> 30 #include <thread> 31 32 namespace android { 33 34 class MediaTrackTranscoderCallback; 35 36 /** 37 * Base class for all track transcoders. MediaTrackTranscoder operates asynchronously on an internal 38 * thread and communicates through a MediaTrackTranscoderCallback instance. Transcoded samples are 39 * enqueued on the MediaTrackTranscoder's output queue. Samples need to be dequeued from the output 40 * queue or the transcoder will run out of buffers and stall. Once the consumer is done with a 41 * transcoded sample it is the consumer's responsibility to as soon as possible release all 42 * references to that sample in order to return the buffer to the transcoder. MediaTrackTranscoder 43 * is an abstract class and instances are created through one of the concrete subclasses. 44 * 45 * The base class MediaTrackTranscoder is responsible for thread and state management and guarantees 46 * that operations {configure, start, stop} are sent to the derived class in correct order. 47 * MediaTrackTranscoder is also responsible for delivering callback notifications once the 48 * transcoder has been successfully started. 49 */ 50 class MediaTrackTranscoder { 51 public: 52 /** 53 * Configures the track transcoder with an input MediaSampleReader and a destination format. 54 * A track transcoder have to be configured before it is started. 55 * @param mediaSampleReader The MediaSampleReader to read input samples from. 56 * @param trackIndex The index of the track to transcode in mediaSampleReader. 57 * @param destinationFormat The destination format. 58 * @return AMEDIA_OK if the track transcoder was successfully configured. 59 */ 60 media_status_t configure(const std::shared_ptr<MediaSampleReader>& mediaSampleReader, 61 int trackIndex, 62 const std::shared_ptr<AMediaFormat>& destinationFormat); 63 64 /** 65 * Starts the track transcoder. After the track transcoder is successfully started it will run 66 * until a callback signals that transcoding has ended. Start should only be called once. 67 * @return True if the track transcoder started, or false if it had already been started. 68 */ 69 bool start(); 70 71 /** 72 * Stops the track transcoder. Once the transcoding has been stopped it cannot be restarted 73 * again. It is safe to call stop multiple times. Stop is an asynchronous operation. Once the 74 * track transcoder has stopped the onTrackStopped callback will get called, unless the 75 * transcoding finished or encountered an error before it could be stopped in which case the 76 * callbacks corresponding to those events will be called instead. 77 * @param stopOnSyncSample Request the transcoder to stop after emitting a sync sample. 78 */ 79 void stop(bool stopOnSyncSample = false); 80 81 /** 82 * Set the sample consumer function. The MediaTrackTranscoder will deliver transcoded samples to 83 * this function. If the MediaTrackTranscoder is started before a consumer is set the transcoder 84 * will buffer a limited number of samples internally before stalling. Once a consumer has been 85 * set the internally buffered samples will be delivered to the consumer. 86 * @param sampleConsumer The sample consumer function. 87 */ 88 void setSampleConsumer(const MediaSampleWriter::MediaSampleConsumerFunction& sampleConsumer); 89 90 /** 91 * Retrieves the track transcoder's final output format. The output is available after the 92 * track transcoder has been successfully configured. 93 * @return The track output format. 94 */ 95 virtual std::shared_ptr<AMediaFormat> getOutputFormat() const = 0; 96 97 virtual ~MediaTrackTranscoder() = default; 98 99 protected: MediaTrackTranscoder(const std::weak_ptr<MediaTrackTranscoderCallback> & transcoderCallback)100 MediaTrackTranscoder(const std::weak_ptr<MediaTrackTranscoderCallback>& transcoderCallback) 101 : mTranscoderCallback(transcoderCallback){}; 102 103 // Called by subclasses when the actual track format becomes available. 104 void notifyTrackFormatAvailable(); 105 106 // Called by subclasses when a transcoded sample is available. Samples must not hold a strong 107 // reference to the track transcoder in order to avoid retain cycles through the track 108 // transcoder's sample queue. 109 void onOutputSampleAvailable(const std::shared_ptr<MediaSample>& sample); 110 111 // configureDestinationFormat needs to be implemented by subclasses, and gets called on an 112 // external thread before start. 113 virtual media_status_t configureDestinationFormat( 114 const std::shared_ptr<AMediaFormat>& destinationFormat) = 0; 115 116 // runTranscodeLoop needs to be implemented by subclasses, and gets called on 117 // MediaTrackTranscoder's internal thread when the track transcoder is started. 118 virtual media_status_t runTranscodeLoop(bool* stopped) = 0; 119 120 // abortTranscodeLoop needs to be implemented by subclasses, and should request transcoding to 121 // be aborted as soon as possible. It should be safe to call abortTranscodeLoop multiple times. 122 virtual void abortTranscodeLoop() = 0; 123 124 std::shared_ptr<MediaSampleReader> mMediaSampleReader; 125 int mTrackIndex; 126 std::shared_ptr<AMediaFormat> mSourceFormat; 127 128 enum StopRequest { 129 NONE, 130 STOP_NOW, 131 STOP_ON_SYNC, 132 }; 133 std::atomic<StopRequest> mStopRequest = NONE; 134 135 private: 136 std::mutex mSampleMutex; 137 // SampleQueue for buffering output samples before a sample consumer has been set. 138 MediaSampleQueue mSampleQueue GUARDED_BY(mSampleMutex); 139 MediaSampleWriter::MediaSampleConsumerFunction mSampleConsumer GUARDED_BY(mSampleMutex); 140 const std::weak_ptr<MediaTrackTranscoderCallback> mTranscoderCallback; 141 std::mutex mStateMutex; 142 enum { 143 UNINITIALIZED, 144 CONFIGURED, 145 STARTED, 146 STOPPED, 147 } mState GUARDED_BY(mStateMutex) = UNINITIALIZED; 148 }; 149 150 } // namespace android 151 #endif // ANDROID_MEDIA_TRACK_TRANSCODER_H 152