• 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 #include <media/MediaTrackTranscoder.h>
18 #include <media/MediaTrackTranscoderCallback.h>
19 #include <media/MediaTranscoder.h>
20 
21 #include <condition_variable>
22 #include <memory>
23 #include <mutex>
24 
25 namespace android {
26 
27 //
28 // This file contains transcoding test utilities.
29 //
30 
31 namespace TranscoderTestUtils {
32 
33 std::shared_ptr<AMediaFormat> GetVideoFormat(const std::string& path,
34                                              std::string* mimeOut = nullptr) {
35     int fd = open(path.c_str(), O_RDONLY);
36     EXPECT_GT(fd, 0);
37     ssize_t fileSize = lseek(fd, 0, SEEK_END);
38     lseek(fd, 0, SEEK_SET);
39 
40     auto sampleReader = MediaSampleReaderNDK::createFromFd(fd, 0, fileSize);
41     EXPECT_NE(sampleReader, nullptr);
42 
43     for (size_t i = 0; i < sampleReader->getTrackCount(); ++i) {
44         AMediaFormat* format = sampleReader->getTrackFormat(i);
45 
46         const char* mime = nullptr;
47         AMediaFormat_getString(format, AMEDIAFORMAT_KEY_MIME, &mime);
48         if (strncmp(mime, "video/", 6) == 0) {
49             if (mimeOut != nullptr) {
50                 mimeOut->assign(mime);
51             }
52             return std::shared_ptr<AMediaFormat>(format, &AMediaFormat_delete);
53         }
54 
55         AMediaFormat_delete(format);
56     }
57     return nullptr;
58 }
59 
60 };  // namespace TranscoderTestUtils
61 
62 class TrackTranscoderTestUtils {
63 public:
64     static std::shared_ptr<AMediaFormat> getDefaultVideoDestinationFormat(
65             AMediaFormat* sourceFormat, bool includeBitrate = true) {
66         // Default video destination format setup.
67         static constexpr float kFrameRate = 30.0f;
68         static constexpr int32_t kBitRate = 2 * 1000 * 1000;
69 
70         AMediaFormat* destinationFormat = AMediaFormat_new();
71         AMediaFormat_copy(destinationFormat, sourceFormat);
72         AMediaFormat_setFloat(destinationFormat, AMEDIAFORMAT_KEY_FRAME_RATE, kFrameRate);
73         if (includeBitrate) {
74             AMediaFormat_setInt32(destinationFormat, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
75         }
76 
77         return std::shared_ptr<AMediaFormat>(destinationFormat, &AMediaFormat_delete);
78     }
79 };
80 
81 class TestTrackTranscoderCallback : public MediaTrackTranscoderCallback {
82 public:
83     TestTrackTranscoderCallback() = default;
84     ~TestTrackTranscoderCallback() = default;
85 
86     // MediaTrackTranscoderCallback
onTrackFormatAvailable(const MediaTrackTranscoder * transcoder __unused)87     void onTrackFormatAvailable(const MediaTrackTranscoder* transcoder __unused) {
88         std::unique_lock<std::mutex> lock(mMutex);
89         mTrackFormatAvailable = true;
90         mTrackFormatAvailableCondition.notify_all();
91     }
92 
onTrackFinished(const MediaTrackTranscoder * transcoder __unused)93     void onTrackFinished(const MediaTrackTranscoder* transcoder __unused) {
94         std::unique_lock<std::mutex> lock(mMutex);
95         mTranscodingFinished = true;
96         mTranscodingFinishedCondition.notify_all();
97     }
98 
onTrackStopped(const MediaTrackTranscoder * transcoder __unused)99     virtual void onTrackStopped(const MediaTrackTranscoder* transcoder __unused) override {
100         std::unique_lock<std::mutex> lock(mMutex);
101         mTranscodingFinished = true;
102         mTranscodingStopped = true;
103         mTranscodingFinishedCondition.notify_all();
104     }
105 
onTrackError(const MediaTrackTranscoder * transcoder __unused,media_status_t status)106     void onTrackError(const MediaTrackTranscoder* transcoder __unused, media_status_t status) {
107         std::unique_lock<std::mutex> lock(mMutex);
108         mTranscodingFinished = true;
109         mStatus = status;
110         mTranscodingFinishedCondition.notify_all();
111     }
112     // ~MediaTrackTranscoderCallback
113 
waitUntilFinished()114     media_status_t waitUntilFinished() {
115         std::unique_lock<std::mutex> lock(mMutex);
116         while (!mTranscodingFinished) {
117             mTranscodingFinishedCondition.wait(lock);
118         }
119         return mStatus;
120     }
121 
waitUntilTrackFormatAvailable()122     void waitUntilTrackFormatAvailable() {
123         std::unique_lock<std::mutex> lock(mMutex);
124         while (!mTrackFormatAvailable) {
125             mTrackFormatAvailableCondition.wait(lock);
126         }
127     }
128 
transcodingWasStopped()129     bool transcodingWasStopped() const { return mTranscodingFinished && mTranscodingStopped; }
transcodingFinished()130     bool transcodingFinished() const {
131         return mTranscodingFinished && !mTranscodingStopped && mStatus == AMEDIA_OK;
132     }
133 
134 private:
135     media_status_t mStatus = AMEDIA_OK;
136     std::mutex mMutex;
137     std::condition_variable mTranscodingFinishedCondition;
138     std::condition_variable mTrackFormatAvailableCondition;
139     bool mTranscodingFinished = false;
140     bool mTranscodingStopped = false;
141     bool mTrackFormatAvailable = false;
142 };
143 
144 class TestTranscoderCallbacks : public MediaTranscoder::CallbackInterface {
145 public:
onFinished(const MediaTranscoder * transcoder __unused)146     virtual void onFinished(const MediaTranscoder* transcoder __unused) override {
147         std::unique_lock<std::mutex> lock(mMutex);
148         EXPECT_FALSE(mFinished);
149         mFinished = true;
150         mCondition.notify_all();
151     }
152 
onError(const MediaTranscoder * transcoder __unused,media_status_t error)153     virtual void onError(const MediaTranscoder* transcoder __unused,
154                          media_status_t error) override {
155         std::unique_lock<std::mutex> lock(mMutex);
156         EXPECT_NE(error, AMEDIA_OK);
157         EXPECT_FALSE(mFinished);
158         mFinished = true;
159         mStatus = error;
160         mCondition.notify_all();
161     }
162 
onProgressUpdate(const MediaTranscoder * transcoder __unused,int32_t progress)163     virtual void onProgressUpdate(const MediaTranscoder* transcoder __unused,
164                                   int32_t progress) override {
165         std::unique_lock<std::mutex> lock(mMutex);
166         if (progress > 0 && !mProgressMade) {
167             mProgressMade = true;
168             mCondition.notify_all();
169         }
170     }
171 
onHeartBeat(const MediaTranscoder * transcoder __unused)172     virtual void onHeartBeat(const MediaTranscoder* transcoder __unused) override {
173         std::unique_lock<std::mutex> lock(mMutex);
174         mHeartBeatCount++;
175     }
176 
onCodecResourceLost(const MediaTranscoder * transcoder __unused,const std::shared_ptr<ndk::ScopedAParcel> & pausedState __unused)177     virtual void onCodecResourceLost(const MediaTranscoder* transcoder __unused,
178                                      const std::shared_ptr<ndk::ScopedAParcel>& pausedState
179                                              __unused) override {}
180 
waitForTranscodingFinished()181     void waitForTranscodingFinished() {
182         std::unique_lock<std::mutex> lock(mMutex);
183         while (!mFinished) {
184             mCondition.wait(lock);
185         }
186     }
187 
waitForProgressMade()188     void waitForProgressMade() {
189         std::unique_lock<std::mutex> lock(mMutex);
190         while (!mProgressMade && !mFinished) {
191             mCondition.wait(lock);
192         }
193     }
194     media_status_t mStatus = AMEDIA_OK;
195     bool mFinished = false;
196     int32_t mHeartBeatCount = 0;
197 
198 private:
199     std::mutex mMutex;
200     std::condition_variable mCondition;
201     bool mProgressMade = false;
202 };
203 
204 class OneShotSemaphore {
205 public:
wait()206     void wait() {
207         std::unique_lock<std::mutex> lock(mMutex);
208         while (!mSignaled) {
209             mCondition.wait(lock);
210         }
211     }
212 
signal()213     void signal() {
214         std::unique_lock<std::mutex> lock(mMutex);
215         mSignaled = true;
216         mCondition.notify_all();
217     }
218 
219 private:
220     std::mutex mMutex;
221     std::condition_variable mCondition;
222     bool mSignaled = false;
223 };
224 
225 };  // namespace android
226