blob: 35fe25b61aec772c8c29cf8ab15a353ac810c3d3 [file] [log] [blame]
Linus Nilsson52df71c2021-03-08 13:01:11 -08001/*
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
25namespace android {
26
27//
28// This file contains transcoding test utilities.
29//
30
31namespace TranscoderTestUtils {
32
33std::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
62class TrackTranscoderTestUtils {
63public:
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
81class TestTrackTranscoderCallback : public MediaTrackTranscoderCallback {
82public:
83 TestTrackTranscoderCallback() = default;
84 ~TestTrackTranscoderCallback() = default;
85
86 // MediaTrackTranscoderCallback
87 void onTrackFormatAvailable(const MediaTrackTranscoder* transcoder __unused) {
88 std::unique_lock<std::mutex> lock(mMutex);
89 mTrackFormatAvailable = true;
90 mTrackFormatAvailableCondition.notify_all();
91 }
92
93 void onTrackFinished(const MediaTrackTranscoder* transcoder __unused) {
94 std::unique_lock<std::mutex> lock(mMutex);
95 mTranscodingFinished = true;
96 mTranscodingFinishedCondition.notify_all();
97 }
98
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
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
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
122 void waitUntilTrackFormatAvailable() {
123 std::unique_lock<std::mutex> lock(mMutex);
124 while (!mTrackFormatAvailable) {
125 mTrackFormatAvailableCondition.wait(lock);
126 }
127 }
128
129 bool transcodingWasStopped() const { return mTranscodingFinished && mTranscodingStopped; }
130 bool transcodingFinished() const {
131 return mTranscodingFinished && !mTranscodingStopped && mStatus == AMEDIA_OK;
132 }
133
134private:
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
144class TestTranscoderCallbacks : public MediaTranscoder::CallbackInterface {
145public:
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
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
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
172 virtual void onHeartBeat(const MediaTranscoder* transcoder __unused) override {
173 std::unique_lock<std::mutex> lock(mMutex);
174 mHeartBeatCount++;
175 }
176
177 virtual void onCodecResourceLost(const MediaTranscoder* transcoder __unused,
178 const std::shared_ptr<ndk::ScopedAParcel>& pausedState
179 __unused) override {}
180
181 void waitForTranscodingFinished() {
182 std::unique_lock<std::mutex> lock(mMutex);
183 while (!mFinished) {
184 mCondition.wait(lock);
185 }
186 }
187
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
198private:
199 std::mutex mMutex;
200 std::condition_variable mCondition;
201 bool mProgressMade = false;
202};
203
204class OneShotSemaphore {
205public:
206 void wait() {
207 std::unique_lock<std::mutex> lock(mMutex);
208 while (!mSignaled) {
209 mCondition.wait(lock);
210 }
211 }
212
213 void signal() {
214 std::unique_lock<std::mutex> lock(mMutex);
215 mSignaled = true;
216 mCondition.notify_all();
217 }
218
219private:
220 std::mutex mMutex;
221 std::condition_variable mCondition;
222 bool mSignaled = false;
223};
224
225}; // namespace android