• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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