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