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 "decoder_demo.h"
17
18 #include <iostream>
19 #include <unistd.h>
20
21 #include "avcodec_list.h"
22 #include "securec.h"
23 #include "ui/rs_surface_node.h"
24 #include "wm_common.h"
25 #include "window.h"
26 #include "window_option.h"
27
28 using namespace OHOS::DistributedHardware;
29
30 static const int32_t ES_R[325] = {
31 11895, 8109, 1578, 1616, 1313, 572, 805, 837, 755, 706, 952, 879, 13193, 422, 389, 509, 725, 465, 479, 959,
32 677, 364, 541, 696, 9306, 322, 318, 767, 590, 422, 530, 403, 505, 566, 445, 508, 7783, 460, 405, 343, 451,
33 608, 431, 411, 543, 487, 527, 400, 6287, 385, 418, 391, 592, 434, 412, 398, 504, 492, 479, 561, 5413, 317,
34 355, 422, 467, 452, 476, 460, 490, 492, 485, 451, 5036, 312, 408, 460, 432, 502, 388, 475, 407, 544, 401,
35 487, 4404, 362, 378, 427, 416, 426, 456, 414, 438, 424, 442, 444, 4310, 362, 388, 393, 390, 441, 398, 423,
36 369, 443, 406, 392, 4231, 343, 363, 355, 390, 459, 371, 378, 381, 405, 392, 426, 3975, 387, 337, 393, 439,
37 378, 355, 374, 484, 381, 373, 423, 3869, 312, 350, 400, 345, 356, 320, 473, 431, 386, 338, 431, 3426, 268,
38 315, 416, 383, 373, 381, 354, 383, 328, 348, 418, 3715, 324, 361, 331, 350, 302, 409, 377, 359, 384, 334,
39 326, 3439, 266, 324, 329, 353, 405, 303, 357, 332, 292, 361, 333, 3542, 294, 284, 247, 331, 306, 322, 287,
40 367, 341, 276, 258, 3980, 246, 245, 259, 309, 333, 250, 275, 334, 281, 253, 371, 3640, 213, 231, 301, 302,
41 228, 289, 290, 281, 201, 284, 277, 4242, 205, 328, 237, 283, 295, 266, 230, 321, 348, 212, 308, 4103, 259,
42 238, 245, 298, 330, 265, 271, 287, 267, 286, 290, 3856, 269, 242, 209, 314, 267, 278, 280, 314, 250, 433,
43 238, 3654, 195, 246, 301, 298, 250, 270, 320, 269, 305, 258, 368, 3810, 231, 212, 279, 289, 252, 303, 287,
44 295, 206, 264, 349, 4071, 242, 296, 271, 231, 307, 265, 254, 267, 317, 232, 348, 4077, 259, 222, 268, 235,
45 324, 266, 256, 312, 246, 248, 325, 4000, 266, 201, 230, 293, 264, 265, 273, 301, 304, 253, 266, 3978, 228,
46 232, 250, 248, 281, 219, 243, 293, 287, 253, 328, 3719
47 };
48
49 static const int32_t ES_W[183] = {
50 2111, 109091, 9316, 969, 13656, 1349, 959, 10484, 1219, 14839, 1092, 23378, 1653, 1725, 1526, 8500, 15407,
51 2058, 1346, 21066, 3758, 1734, 1950, 19955, 3997, 1732, 1784, 22687, 4392, 2448, 2180, 17456, 3930, 1851,
52 1802, 24227, 4393, 2639, 2778, 18314, 4023, 2392, 2283, 20566, 4118, 2664, 2013, 18964, 2624, 45258, 5860,
53 4124, 3473, 27772, 4687, 3140, 2939, 26288, 3808, 2967, 2823, 27219, 3943, 3242, 2667, 27372, 3522, 2899,
54 2316, 26608, 3284, 2853, 2285, 19581, 2894, 2436, 24898, 4002, 2876, 2807, 25730, 3903, 2874, 2975, 26309,
55 3771, 2763, 2666, 23404, 3826, 2410, 2644, 24629, 4145, 3121, 2878, 50773, 7040, 3945, 3292, 30828, 5210,
56 2883, 3277, 31501, 4809, 3068, 3220, 30746, 4715, 3461, 3583, 32278, 4798, 3398, 3389, 31404, 4921, 3382,
57 3766, 31821, 5848, 3860, 4047, 37642, 5793, 4271, 4094, 29853, 6163, 4399, 4063, 32151, 6038, 4332, 4041,
58 30390, 5679, 4098, 3921, 29401, 5307, 3996, 3945, 45997, 7060, 3716, 4183, 26357, 6190, 3714, 4250, 29086,
59 5929, 3491, 4489, 27772, 6656, 4219, 4348, 25851, 6088, 3617, 4477, 25722, 6303, 3856, 4208, 25348, 5896,
60 3816, 4521, 22462, 5914, 3673, 4594, 18091, 6474, 3878, 4492, 10890, 4823, 4148
61 };
62
63 using namespace OHOS;
64 using namespace OHOS::Media;
65 using namespace std;
66 namespace {
67 constexpr uint32_t DEFAULT_FRAME_RATE = 30;
68 constexpr uint32_t MAX_INPUT_BUFFER_SIZE = 30000;
69 constexpr uint32_t FRAME_DURATION_US = 33000;
70 constexpr uint32_t VIDEO_DATA_FORMAT_NV12 = 2;
71 constexpr uint32_t VIDEO_DATA_FORMAT_RGBA = 5;
72 constexpr uint32_t SLEEP_THREE_SECOND = 3;
73 constexpr uint32_t INDEX_CONSTANT = 10000;
74 const string CODEC_NAME_H264 = "OMX_hisi_video_encoder_avc";
75 const string CODEC_NAME_MPEG4 = "avenc_mpeg4";
76 }
77
RunCase()78 void VDecDemo::RunCase()
79 {
80 CheckCodecType();
81 CreateVdec();
82 Format format;
83 format.PutIntValue("width", width_);
84 format.PutIntValue("height", height_);
85 if (isW) {
86 format.PutIntValue("pixel_format", VIDEO_DATA_FORMAT_NV12);
87 } else {
88 format.PutIntValue("pixel_format", VIDEO_DATA_FORMAT_RGBA);
89 }
90 format.PutIntValue("frame_rate", DEFAULT_FRAME_RATE);
91 format.PutIntValue("max_input_size", MAX_INPUT_BUFFER_SIZE);
92 Configure(format);
93 SetSurface();
94 Prepare();
95 Start();
96 sleep(SLEEP_THREE_SECOND);
97 Stop();
98 Release();
99 }
100
CreateVdec()101 int32_t VDecDemo::CreateVdec()
102 {
103 if (isW) {
104 vdec_ = VideoDecoderFactory::CreateByMime("video/avc");
105 } else {
106 vdec_ = VideoDecoderFactory::CreateByMime("video/mp4v-es");
107 }
108
109 signal_ = make_shared<VDecSignal>();
110 cb_ = make_unique<VDecDemoCallback>(signal_);
111 vdec_->SetCallback(cb_);
112 return 0;
113 }
114
Configure(const Format & format)115 int32_t VDecDemo::Configure(const Format &format)
116 {
117 return vdec_->Configure(format);
118 }
119
Prepare()120 int32_t VDecDemo::Prepare()
121 {
122 return vdec_->Prepare();
123 }
124
Start()125 int32_t VDecDemo::Start()
126 {
127 isRunning_.store(true);
128
129 testFile_ = std::make_unique<std::ifstream>();
130 testFile_->open("/data/media/video.es", std::ios::in | std::ios::binary);
131
132 inputLoop_ = make_unique<thread>(&VDecDemo::InputFunc, this);
133 outputLoop_ = make_unique<thread>(&VDecDemo::OutputFunc, this);
134 return vdec_->Start();
135 }
136
Stop()137 int32_t VDecDemo::Stop()
138 {
139 isRunning_.store(false);
140
141 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
142 {
143 unique_lock<mutex> inLock(signal_->inMutex_);
144 signal_->inQueue_.push(INDEX_CONSTANT);
145 signal_->inCond_.notify_all();
146 }
147 inputLoop_->join();
148 inputLoop_.reset();
149 }
150
151 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
152 {
153 unique_lock<mutex> outLock(signal_->outMutex_);
154 signal_->outQueue_.push(INDEX_CONSTANT);
155 signal_->outCond_.notify_all();
156 }
157 outputLoop_->join();
158 outputLoop_.reset();
159 }
160
161 return vdec_->Stop();
162 }
163
Flush()164 int32_t VDecDemo::Flush()
165 {
166 return vdec_->Flush();
167 }
168
Reset()169 int32_t VDecDemo::Reset()
170 {
171 return vdec_->Reset();
172 }
173
Release()174 int32_t VDecDemo::Release()
175 {
176 return vdec_->Release();
177 }
178
SetOutputSurface(sptr<Surface> surface)179 void VDecDemo::SetOutputSurface(sptr<Surface> surface)
180 {
181 surface_ = surface;
182 }
183
SetWindowSize(uint32_t width,uint32_t height)184 void VDecDemo::SetWindowSize(uint32_t width, uint32_t height)
185 {
186 width_ = width;
187 height_ = height;
188 }
189
SetSurface()190 int32_t VDecDemo::SetSurface()
191 {
192 return vdec_->SetOutputSurface(surface_);
193 }
194
CheckCodecType()195 void VDecDemo::CheckCodecType()
196 {
197 std::vector<std::string> localCodecArray;
198 std::shared_ptr<Media::AVCodecList> codecList = Media::AVCodecListFactory::CreateAVCodecList();
199 std::vector<std::shared_ptr<Media::VideoCaps>> caps = codecList->GetVideoEncoderCaps();
200 for (const auto &cap : caps) {
201 std::shared_ptr<Media::AVCodecInfo> codecInfo = cap->GetCodecInfo();
202 localCodecArray.push_back(codecInfo->GetName());
203 }
204
205 if (std::find(localCodecArray.begin(), localCodecArray.end(),
206 CODEC_NAME_H264) != localCodecArray.end()) {
207 DHLOGI("device is W");
208 isW = true;
209 } else if (std::find(localCodecArray.begin(), localCodecArray.end(),
210 CODEC_NAME_MPEG4) != localCodecArray.end()) {
211 DHLOGI("device is R");
212 isW = false;
213 }
214 }
215
GetFrameLen()216 const int32_t* VDecDemo::GetFrameLen()
217 {
218 const int32_t* frameLen = nullptr;
219 if (isW) {
220 frameLen = ES_W;
221 defaultFrameCount_ = sizeof(ES_W) / sizeof(ES_W[0]);
222 } else {
223 frameLen = ES_R;
224 defaultFrameCount_ = sizeof(ES_R) / sizeof(ES_R[0]);
225 }
226 return frameLen;
227 }
228
InputFunc()229 void VDecDemo::InputFunc()
230 {
231 const int32_t *frameLen = GetFrameLen();
232
233 while (true) {
234 if (!isRunning_.load()) {
235 break;
236 }
237
238 unique_lock<mutex> lock(signal_->inMutex_);
239 signal_->inCond_.wait(lock, [this]() { return signal_->inQueue_.size() > 0; });
240
241 if (!isRunning_.load()) {
242 break;
243 }
244
245 uint32_t index = signal_->inQueue_.front();
246 auto buffer = vdec_->GetInputBuffer(index);
247
248 char *fileBuffer = static_cast<char *>(malloc(sizeof(char) * (*frameLen) + 1));
249 if (fileBuffer == nullptr) {
250 break;
251 }
252
253 (void)testFile_->read(fileBuffer, *frameLen);
254 if (memcpy_s(buffer->GetBase(), buffer->GetSize(), fileBuffer, *frameLen) != EOK) {
255 free(fileBuffer);
256 DHLOGI("Fatal: memcpy fail");
257 break;
258 }
259
260 AVCodecBufferInfo info;
261 info.size = *frameLen;
262 info.offset = 0;
263 info.presentationTimeUs = timeStamp_;
264
265 int32_t ret = 0;
266 if (isFirstFrame_) {
267 ret = vdec_->QueueInputBuffer(index, info, AVCODEC_BUFFER_FLAG_CODEC_DATA);
268 isFirstFrame_ = false;
269 } else {
270 ret = vdec_->QueueInputBuffer(index, info, AVCODEC_BUFFER_FLAG_NONE);
271 }
272
273 free(fileBuffer);
274 frameLen++;
275 timeStamp_ += FRAME_DURATION_US;
276 signal_->inQueue_.pop();
277
278 frameCount_++;
279 if (frameCount_ == defaultFrameCount_) {
280 DHLOGI("Finish decode, exit");
281 break;
282 }
283
284 if (ret != 0) {
285 DHLOGI("Fatal error, exit");
286 break;
287 }
288 }
289 }
290
OutputFunc()291 void VDecDemo::OutputFunc()
292 {
293 while (true) {
294 if (!isRunning_.load()) {
295 break;
296 }
297
298 unique_lock<mutex> lock(signal_->outMutex_);
299 signal_->outCond_.wait(lock, [this]() { return signal_->outQueue_.size() > 0; });
300
301 if (!isRunning_.load()) {
302 break;
303 }
304
305 uint32_t index = signal_->outQueue_.front();
306 if (vdec_->ReleaseOutputBuffer(index, true) != 0) {
307 DHLOGI("Fatal: ReleaseOutputBuffer fail");
308 break;
309 }
310
311 signal_->outQueue_.pop();
312 }
313 }
314
VDecDemoCallback(shared_ptr<VDecSignal> signal)315 VDecDemoCallback::VDecDemoCallback(shared_ptr<VDecSignal> signal)
316 : signal_(signal)
317 {
318 }
319
OnError(AVCodecErrorType errorType,int32_t errorCode)320 void VDecDemoCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
321 {
322 DHLOGI("Error received, errorType: %s, errorCode: %d", errorType, errorCode);
323 }
324
OnOutputFormatChanged(const Format & format)325 void VDecDemoCallback::OnOutputFormatChanged(const Format &format)
326 {
327 DHLOGI("OnOutputFormatChanged received");
328 }
329
OnInputBufferAvailable(uint32_t index)330 void VDecDemoCallback::OnInputBufferAvailable(uint32_t index)
331 {
332 DHLOGI("OnInputBufferAvailable received, index: %d", index);
333 unique_lock<mutex> lock(signal_->inMutex_);
334 signal_->inQueue_.push(index);
335 signal_->inCond_.notify_all();
336 }
337
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)338 void VDecDemoCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
339 {
340 DHLOGI("OnOutputBufferAvailable received, index: %d", index);
341 unique_lock<mutex> lock(signal_->outMutex_);
342 signal_->outQueue_.push(index);
343 signal_->outCond_.notify_all();
344 }
345