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_TRANSCODER_H 18 #define ANDROID_MEDIA_TRANSCODER_H 19 20 #include <android/binder_auto_utils.h> 21 #include <media/MediaSampleWriter.h> 22 #include <media/MediaTrackTranscoderCallback.h> 23 #include <media/NdkMediaCodecPlatform.h> 24 #include <media/NdkMediaError.h> 25 #include <media/NdkMediaFormat.h> 26 #include <utils/Mutex.h> 27 28 #include <atomic> 29 #include <memory> 30 #include <mutex> 31 #include <unordered_set> 32 33 namespace android { 34 35 class MediaSampleReader; 36 37 class MediaTranscoder : public std::enable_shared_from_this<MediaTranscoder>, 38 public MediaTrackTranscoderCallback, 39 public MediaSampleWriter::CallbackInterface { 40 public: 41 /** Callbacks from transcoder to client. */ 42 class CallbackInterface { 43 public: 44 /** Transcoder finished successfully. */ 45 virtual void onFinished(const MediaTranscoder* transcoder) = 0; 46 47 /** Transcoder encountered an unrecoverable error. */ 48 virtual void onError(const MediaTranscoder* transcoder, media_status_t error) = 0; 49 50 /** Transcoder progress update reported in percent from 0 to 100. */ 51 virtual void onProgressUpdate(const MediaTranscoder* transcoder, int32_t progress) = 0; 52 53 /** Transcoder heart-beat signal. */ 54 virtual void onHeartBeat(const MediaTranscoder* transcoder) = 0; 55 56 /** 57 * Transcoder lost codec resources and paused operations. The client can resume transcoding 58 * again when resources are available by either: 59 * 1) Calling resume on the same MediaTranscoder instance. 60 * 2) Creating a new MediaTranscoding instance with the paused state and then calling 61 * resume. 62 */ 63 virtual void onCodecResourceLost( 64 const MediaTranscoder* transcoder, 65 const std::shared_ptr<ndk::ScopedAParcel>& pausedState) = 0; 66 67 virtual ~CallbackInterface() = default; 68 }; 69 70 /** 71 * Creates a new MediaTranscoder instance. If the supplied paused state is valid, the transcoder 72 * will be initialized with the paused state and be ready to be resumed right away. It is not 73 * possible to change any configurations on a paused transcoder. 74 */ 75 static std::shared_ptr<MediaTranscoder> create( 76 const std::shared_ptr<CallbackInterface>& callbacks, int64_t heartBeatIntervalUs = -1, 77 pid_t pid = AMEDIACODEC_CALLING_PID, uid_t uid = AMEDIACODEC_CALLING_UID, 78 const std::shared_ptr<ndk::ScopedAParcel>& pausedState = nullptr); 79 80 /** Configures source from path fd. */ 81 media_status_t configureSource(int fd); 82 83 /** Gets the media formats of all tracks in the file. */ 84 std::vector<std::shared_ptr<AMediaFormat>> getTrackFormats() const; 85 86 /** 87 * Configures transcoding of a track. Tracks that are not configured will not present in the 88 * final transcoded file, i.e. tracks will be dropped by default. Passing nullptr for 89 * trackFormat means the track will be copied unchanged ("passthrough") to the destination. 90 * Track configurations must be done after the source has been configured. 91 * Note: trackFormat is not modified but cannot be const. 92 */ 93 media_status_t configureTrackFormat(size_t trackIndex, AMediaFormat* trackFormat); 94 95 /** Configures destination from fd. */ 96 media_status_t configureDestination(int fd); 97 98 /** Starts transcoding. No configurations can be made once the transcoder has started. */ 99 media_status_t start(); 100 101 /** 102 * Pauses transcoding and finalizes the partial transcoded file to disk. Pause is a synchronous 103 * operation and will wait until all internal components are done. Once this method returns it 104 * is safe to release the transcoder instance. No callback will be called if the transcoder was 105 * paused successfully. But if the transcoding finishes or encountered an error during pause, 106 * the corresponding callback will be called. 107 */ 108 media_status_t pause(std::shared_ptr<ndk::ScopedAParcel>* pausedState); 109 110 /** Resumes a paused transcoding. */ 111 media_status_t resume(); 112 113 /** 114 * Cancels the transcoding. Once canceled the transcoding can not be restarted. Client 115 * will be responsible for cleaning up the abandoned file. Cancel is a synchronous operation and 116 * will wait until all internal components are done. Once this method returns it is safe to 117 * release the transcoder instance. Normally no callback will be called when the transcoder is 118 * cancelled. But if the transcoding finishes or encountered an error during cancel, the 119 * corresponding callback will be called. 120 */ 121 media_status_t cancel(); 122 123 virtual ~MediaTranscoder() = default; 124 125 private: 126 MediaTranscoder(const std::shared_ptr<CallbackInterface>& callbacks, 127 int64_t heartBeatIntervalUs, pid_t pid, uid_t uid); 128 129 // MediaTrackTranscoderCallback 130 virtual void onTrackFormatAvailable(const MediaTrackTranscoder* transcoder) override; 131 virtual void onTrackFinished(const MediaTrackTranscoder* transcoder) override; 132 virtual void onTrackStopped(const MediaTrackTranscoder* transcoder) override; 133 virtual void onTrackError(const MediaTrackTranscoder* transcoder, 134 media_status_t status) override; 135 // ~MediaTrackTranscoderCallback 136 137 // MediaSampleWriter::CallbackInterface 138 virtual void onFinished(const MediaSampleWriter* writer, media_status_t status) override; 139 virtual void onStopped(const MediaSampleWriter* writer) override; 140 virtual void onProgressUpdate(const MediaSampleWriter* writer, int32_t progress) override; 141 virtual void onHeartBeat(const MediaSampleWriter* writer) override; 142 // ~MediaSampleWriter::CallbackInterface 143 144 void onThreadFinished(const void* thread, media_status_t threadStatus, bool threadStopped); 145 media_status_t requestStop(bool stopOnSync); 146 void waitForThreads(); 147 148 std::shared_ptr<CallbackInterface> mCallbacks; 149 std::shared_ptr<MediaSampleReader> mSampleReader; 150 std::shared_ptr<MediaSampleWriter> mSampleWriter; 151 std::vector<std::shared_ptr<AMediaFormat>> mSourceTrackFormats; 152 std::vector<std::shared_ptr<MediaTrackTranscoder>> mTrackTranscoders; 153 std::mutex mTracksAddedMutex; 154 std::unordered_set<const MediaTrackTranscoder*> mTracksAdded GUARDED_BY(mTracksAddedMutex); 155 int64_t mHeartBeatIntervalUs; 156 pid_t mPid; 157 uid_t mUid; 158 159 enum ThreadState { 160 PENDING = 0, // Not yet started. 161 RUNNING, // Currently running. 162 DONE, // Done running (can be finished, stopped or error). 163 }; 164 std::mutex mThreadStateMutex; 165 std::condition_variable mThreadsDoneSignal; 166 std::unordered_map<const void*, ThreadState> mThreadStates GUARDED_BY(mThreadStateMutex); 167 media_status_t mTranscoderStatus GUARDED_BY(mThreadStateMutex) = AMEDIA_OK; 168 bool mTranscoderStopped GUARDED_BY(mThreadStateMutex) = false; 169 bool mThreadsDone GUARDED_BY(mThreadStateMutex) = false; 170 bool mCallbackSent GUARDED_BY(mThreadStateMutex) = false; 171 bool mSampleWriterStopped GUARDED_BY(mThreadStateMutex) = false; 172 173 std::atomic_bool mCancelled = false; 174 }; 175 176 } // namespace android 177 #endif // ANDROID_MEDIA_TRANSCODER_H 178