1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <sync_fence.h>
17 #include "nocopyable.h"
18 #include "media_errors.h"
19 #include "venc_mock.h"
20 using namespace std;
21 using namespace OHOS::Media::VCodecTestParam;
22
23 namespace OHOS {
24 namespace Media {
VEncCallbackTest(std::shared_ptr<VEncSignal> signal)25 VEncCallbackTest::VEncCallbackTest(std::shared_ptr<VEncSignal> signal)
26 : signal_(signal)
27 {
28 }
29
~VEncCallbackTest()30 VEncCallbackTest::~VEncCallbackTest()
31 {
32 }
33
OnError(int32_t errorCode)34 void VEncCallbackTest::OnError(int32_t errorCode)
35 {
36 cout << "VEnc Error errorCode=" << errorCode << endl;
37 }
38
OnStreamChanged(std::shared_ptr<FormatMock> format)39 void VEncCallbackTest::OnStreamChanged(std::shared_ptr<FormatMock> format)
40 {
41 cout << "VEnc Format Changed" << endl;
42 }
43
OnNeedInputData(uint32_t index,std::shared_ptr<AVMemoryMock> data)44 void VEncCallbackTest::OnNeedInputData(uint32_t index, std::shared_ptr<AVMemoryMock> data)
45 {
46 }
47
OnNewOutputData(uint32_t index,std::shared_ptr<AVMemoryMock> data,AVCodecBufferAttrMock attr)48 void VEncCallbackTest::OnNewOutputData(uint32_t index, std::shared_ptr<AVMemoryMock> data, AVCodecBufferAttrMock attr)
49 {
50 if (signal_ == nullptr) {
51 return;
52 }
53 unique_lock<mutex> lock(signal_->outMutex_);
54 if (!signal_->isRunning_.load()) {
55 return;
56 }
57 signal_->outIndexQueue_.push(index);
58 signal_->outSizeQueue_.push(attr.size);
59 signal_->outBufferQueue_.push(data);
60 signal_->outCond_.notify_all();
61 }
62
VEncMock(std::shared_ptr<VEncSignal> signal)63 VEncMock::VEncMock(std::shared_ptr<VEncSignal> signal)
64 : signal_(signal)
65 {
66 }
67
~VEncMock()68 VEncMock::~VEncMock()
69 {
70 }
71
CreateVideoEncMockByMime(const std::string & mime)72 bool VEncMock::CreateVideoEncMockByMime(const std::string &mime)
73 {
74 videoEnc_ = AVCodecMockFactory::CreateVideoEncMockByMime(mime);
75 return videoEnc_ != nullptr;
76 }
77
CreateVideoEncMockByName(const std::string & name)78 bool VEncMock::CreateVideoEncMockByName(const std::string &name)
79 {
80 videoEnc_ = AVCodecMockFactory::CreateVideoEncMockByName(name);
81 return videoEnc_ != nullptr;
82 }
83
SetCallback(std::shared_ptr<AVCodecCallbackMock> cb)84 int32_t VEncMock::SetCallback(std::shared_ptr<AVCodecCallbackMock> cb)
85 {
86 if (videoEnc_ == nullptr) {
87 return MSERR_INVALID_VAL;
88 }
89 return videoEnc_->SetCallback(cb);
90 }
91
GetInputSurface()92 std::shared_ptr<SurfaceMock> VEncMock::GetInputSurface()
93 {
94 if (videoEnc_ == nullptr) {
95 return nullptr;
96 }
97 surface_ = videoEnc_->GetInputSurface();
98 return surface_;
99 }
100
Configure(std::shared_ptr<FormatMock> format)101 int32_t VEncMock::Configure(std::shared_ptr<FormatMock> format)
102 {
103 if (videoEnc_ == nullptr) {
104 return MSERR_INVALID_VAL;
105 }
106 return videoEnc_->Configure(format);
107 }
108
Prepare()109 int32_t VEncMock::Prepare()
110 {
111 if (videoEnc_ == nullptr) {
112 return MSERR_INVALID_VAL;
113 }
114 return videoEnc_->Prepare();
115 }
116
Start()117 int32_t VEncMock::Start()
118 {
119 if (signal_ == nullptr || videoEnc_ == nullptr) {
120 return MSERR_INVALID_VAL;
121 }
122 signal_->isRunning_.store(true);
123 outLoop_ = make_unique<thread>(&VEncMock::OutLoopFunc, this);
124 UNITTEST_CHECK_AND_RETURN_RET_LOG(outLoop_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
125 return videoEnc_->Start();
126 }
127
FlushInner()128 void VEncMock::FlushInner()
129 {
130 if (signal_ == nullptr || videoEnc_ == nullptr) {
131 return;
132 }
133 signal_->isRunning_.store(false);
134 if (outLoop_ != nullptr && outLoop_->joinable()) {
135 unique_lock<mutex> queueLock(signal_->mutex_);
136 signal_->outIndexQueue_.push(10000); // push 10000 to stop queue
137 signal_->outCond_.notify_all();
138 queueLock.unlock();
139 outLoop_->join();
140 outLoop_.reset();
141 std::queue<uint32_t> temp;
142 std::swap(temp, signal_->outIndexQueue_);
143 }
144 }
145
Stop()146 int32_t VEncMock::Stop()
147 {
148 FlushInner();
149 if (videoEnc_ == nullptr) {
150 return MSERR_INVALID_VAL;
151 }
152 return videoEnc_->Stop();
153 }
154
Flush()155 int32_t VEncMock::Flush()
156 {
157 FlushInner();
158 if (videoEnc_ == nullptr) {
159 return MSERR_INVALID_VAL;
160 }
161 return videoEnc_->Flush();
162 }
163
Reset()164 int32_t VEncMock::Reset()
165 {
166 FlushInner();
167 if (videoEnc_ == nullptr) {
168 return MSERR_INVALID_VAL;
169 }
170 return videoEnc_->Reset();
171 }
172
Release()173 int32_t VEncMock::Release()
174 {
175 if (videoEnc_ == nullptr) {
176 return MSERR_INVALID_VAL;
177 }
178 return videoEnc_->Release();
179 }
180
NotifyEos()181 int32_t VEncMock::NotifyEos()
182 {
183 if (videoEnc_ == nullptr) {
184 return MSERR_INVALID_VAL;
185 }
186 return videoEnc_->NotifyEos();
187 }
188
GetOutputMediaDescription()189 std::shared_ptr<FormatMock> VEncMock::GetOutputMediaDescription()
190 {
191 if (videoEnc_ == nullptr) {
192 return nullptr;
193 }
194 return videoEnc_->GetOutputMediaDescription();
195 }
196
SetParameter(std::shared_ptr<FormatMock> format)197 int32_t VEncMock::SetParameter(std::shared_ptr<FormatMock> format)
198 {
199 if (videoEnc_ == nullptr) {
200 return MSERR_INVALID_VAL;
201 }
202 return videoEnc_->SetParameter(format);
203 }
204
FreeOutputData(uint32_t index)205 int32_t VEncMock::FreeOutputData(uint32_t index)
206 {
207 if (videoEnc_ == nullptr) {
208 return MSERR_INVALID_VAL;
209 }
210 return videoEnc_->FreeOutputData(index);
211 }
212
SetOutPath(const std::string & path)213 void VEncMock::SetOutPath(const std::string &path)
214 {
215 outPath_ = path;
216 }
217
OutLoopFunc()218 void VEncMock::OutLoopFunc()
219 {
220 if (signal_ == nullptr || videoEnc_ == nullptr) {
221 return;
222 }
223 while (true) {
224 if (!signal_->isRunning_.load()) {
225 break;
226 }
227
228 unique_lock<mutex> lock(signal_->outMutex_);
229 signal_->outCond_.wait(lock, [this]() { return signal_->outIndexQueue_.size() > 0; });
230
231 if (!signal_->isRunning_.load()) {
232 break;
233 }
234
235 uint32_t index = signal_->outIndexQueue_.front();
236 auto buffer = signal_->outBufferQueue_.front();
237 uint32_t size = signal_->outSizeQueue_.front();
238
239 if (buffer == nullptr) {
240 cout << "Fatal: GetOutputBuffer fail, exit" << endl;
241 break;
242 }
243 frameCount_++;
244
245 if (NEED_DUMP) {
246 FILE *outFile;
247 const char *savepath = outPath_.c_str();
248 outFile = fopen(savepath, "a");
249 if (outFile == nullptr) {
250 cout << "dump data fail" << endl;
251 } else {
252 fwrite(buffer->GetAddr(), 1, size, outFile);
253 fclose(outFile);
254 }
255 }
256 if (index != EOS_INDEX && videoEnc_->FreeOutputData(index) != MSERR_OK) {
257 cout << "Fatal: FreeOutputData fail, exit" << endl;
258 break;
259 }
260 signal_->outIndexQueue_.pop();
261 signal_->outSizeQueue_.pop();
262 signal_->outBufferQueue_.pop();
263 }
264 }
265 } // namespace Media
266 } // namespace OHOS
267