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