• Home
  • History
  • Annotate
  • 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