1 /*
2 * Copyright (C) 2025 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 #include <arpa/inet.h>
16 #include <sys/time.h>
17 #include <utility>
18 #include <vector>
19 #include <string>
20 #include <sstream>
21 #include "openssl/crypto.h"
22 #include "openssl/sha.h"
23 #include "syncdecoder_sample.h"
24 #include "nlohmann/json.hpp"
25
26 using namespace OHOS;
27 using namespace OHOS::Media;
28 using namespace std;
29 using namespace nlohmann;
30 namespace {
31 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
32 constexpr int64_t NANOS_IN_MICRO = 1000L;
33 constexpr uint32_t START_CODE_SIZE = 4;
34 constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
35 VDecSyncSample *g_decSample = nullptr;
36 } // namespace
37
38 class ConsumerListenerBuffer : public IBufferConsumerListener {
39 public:
ConsumerListenerBuffer(sptr<Surface> cs,std::string_view name)40 ConsumerListenerBuffer(sptr<Surface> cs, std::string_view name) : cs(cs)
41 {
42 outFile_ = std::make_unique<std::ofstream>();
43 outFile_->open(name.data(), std::ios::out | std::ios::binary);
44 };
~ConsumerListenerBuffer()45 ~ConsumerListenerBuffer()
46 {
47 if (outFile_ != nullptr) {
48 outFile_->close();
49 }
50 }
OnBufferAvailable()51 void OnBufferAvailable() override
52 {
53 sptr<SurfaceBuffer> buffer;
54 int32_t flushFence;
55 cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
56 cs->ReleaseBuffer(buffer, -1);
57 }
58
59 private:
60 int64_t timestamp = 0;
61 Rect damage = {};
62 sptr<Surface> cs {nullptr};
63 std::unique_ptr<std::ofstream> outFile_;
64 };
65
~VDecSyncSample()66 VDecSyncSample::~VDecSyncSample()
67 {
68 for (int i = 0; i < maxSurfNum; i++) {
69 if (nativeWindow[i]) {
70 OH_NativeWindow_DestroyNativeWindow(nativeWindow[i]);
71 nativeWindow[i] = nullptr;
72 }
73 }
74 Stop();
75 Release();
76 }
77
GetSystemTimeUs()78 int64_t VDecSyncSample::GetSystemTimeUs()
79 {
80 struct timespec now;
81 (void)clock_gettime(CLOCK_BOOTTIME, &now);
82 int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
83 return nanoTime / NANOS_IN_MICRO;
84 }
85
ConfigureVideoDecoder()86 int32_t VDecSyncSample::ConfigureVideoDecoder()
87 {
88 OH_AVFormat *format = OH_AVFormat_Create();
89 if (format == nullptr) {
90 cout << "Fatal: Failed to create format" << endl;
91 return AV_ERR_UNKNOWN;
92 }
93 if (maxInputSize > 0) {
94 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_MAX_INPUT_SIZE, maxInputSize);
95 }
96 originalWidth = defaultWidth;
97 originalHeight = defaultHeight;
98 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
99 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
100 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defualtPixelFormat);
101 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
102 if (useHDRSource) {
103 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, DEFAULT_PROFILE);
104 } else {
105 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, DEFAULT_PROFILE);
106 }
107
108 if (transferFlag) {
109 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_DECODER_OUTPUT_COLOR_SPACE, OH_COLORSPACE_BT709_LIMIT);
110 }
111 if (nV21Flag) {
112 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, AV_PIXEL_FORMAT_NV21);
113 }
114 if (enableVRR) {
115 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_DECODER_OUTPUT_ENABLE_VRR, 1);
116 }
117 if (enableLowLatency) {
118 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENABLE_LOW_LATENCY, 1);
119 }
120 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_ENABLE_SYNC_MODE, enbleSyncMode);
121 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_DECODER_BLANK_FRAME_ON_SHUTDOWN, enbleBlankFrame);
122 int ret = OH_VideoDecoder_Configure(vdec_, format);
123 OH_AVFormat_Destroy(format);
124 return ret;
125 }
126
CreateSurface()127 void VDecSyncSample::CreateSurface()
128 {
129 cs[0] = Surface::CreateSurfaceAsConsumer();
130 if (cs[0] == nullptr) {
131 cout << "Create the surface consummer fail" << endl;
132 return;
133 }
134 GSError err = cs[0]->SetDefaultUsage(BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_VIDEO_DECODER | BUFFER_USAGE_CPU_READ);
135 if (err == GSERROR_OK) {
136 cout << "set consumer usage succ" << endl;
137 } else {
138 cout << "set consumer usage failed" << endl;
139 }
140 sptr<IBufferConsumerListener> listener = new ConsumerListenerBuffer(cs[0], outDir);
141 cs[0]->RegisterConsumerListener(listener);
142 auto p = cs[0]->GetProducer();
143 ps[0] = Surface::CreateSurfaceAsProducer(p);
144 nativeWindow[0] = CreateNativeWindowFromSurface(&ps[0]);
145 if (autoSwitchSurface) {
146 cs[1] = Surface::CreateSurfaceAsConsumer();
147 sptr<IBufferConsumerListener> listener2 = new ConsumerListenerBuffer(cs[1], outDir2);
148 cs[1]->RegisterConsumerListener(listener2);
149 auto p2 = cs[1]->GetProducer();
150 ps[1] = Surface::CreateSurfaceAsProducer(p2);
151 nativeWindow[1] = CreateNativeWindowFromSurface(&ps[1]);
152 }
153 }
154
CreateVideoDecoder(string codeName)155 int32_t VDecSyncSample::CreateVideoDecoder(string codeName)
156 {
157 vdec_ = OH_VideoDecoder_CreateByName(codeName.c_str());
158 g_decSample = this;
159 return vdec_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
160 }
161
SyncInputFuncFuzz(const uint8_t * data,size_t size)162 int32_t VDecSyncSample::SyncInputFuncFuzz(const uint8_t *data, size_t size)
163 {
164 uint32_t index;
165 if (!isRunning_.load()) {
166 return AV_ERR_NO_MEMORY;
167 }
168 cout << "OH_VideoDecoder_QueryInputBuffer start" << endl;
169 if (OH_VideoDecoder_QueryInputBuffer(vdec_, &index, syncInputWaitTime) != AV_ERR_OK) {
170 cout << "OH_VideoDecoder_QueryInputBuffer fail" << endl;
171 return AV_ERR_NO_MEMORY;
172 }
173 cout << "OH_VideoDecoder_QueryInputBuffer succ" << endl;
174 OH_AVBuffer *buffer = OH_VideoDecoder_GetInputBuffer(vdec_, index);
175 if (buffer == nullptr) {
176 cout << "OH_VideoDecoder_GetInputBuffer fail" << endl;
177 errCount = errCount + 1;
178 return AV_ERR_NO_MEMORY;
179 }
180 int32_t bufferSize = OH_AVBuffer_GetCapacity(buffer);
181 uint8_t *bufferAddr = OH_AVBuffer_GetAddr(buffer);
182 if (size > bufferSize - START_CODE_SIZE) {
183 OH_VideoDecoder_PushInputBuffer(vdec_, index);
184 return AV_ERR_NO_MEMORY;
185 }
186 if (memcpy_s(bufferAddr, bufferSize, START_CODE, START_CODE_SIZE) != EOK) {
187 OH_VideoDecoder_PushInputBuffer(vdec_, index);
188 return AV_ERR_NO_MEMORY;
189 }
190 if (memcpy_s(bufferAddr + START_CODE_SIZE, bufferSize - START_CODE_SIZE, data, size) != EOK) {
191 OH_VideoDecoder_PushInputBuffer(vdec_, index);
192 cout << "Fatal: memcpy fail" << endl;
193 return AV_ERR_NO_MEMORY;
194 }
195 OH_AVCodecBufferAttr attr;
196 attr.pts = GetSystemTimeUs();
197 attr.size = size;
198 attr.offset = 0;
199 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
200 OH_AVBuffer_SetBufferAttr(buffer, &attr);
201 OH_AVErrCode ret = OH_VideoDecoder_PushInputBuffer(vdec_, index);
202 return ret;
203 }
204
SyncOutputFuncFuzz()205 int32_t VDecSyncSample::SyncOutputFuncFuzz()
206 {
207 uint32_t index = 0;
208 cout << "OH_VideoDecoder_QueryOutputBuffer start" << endl;
209 int32_t ret = OH_VideoDecoder_QueryOutputBuffer(vdec_, &index, syncOutputWaitTime);
210 if (ret != AV_ERR_OK) {
211 cout << "OH_VideoDecoder_QueryOutputBuffer fail" << endl;
212 return AV_ERR_UNKNOWN;
213 }
214 cout << "OH_VideoDecoder_QueryOutputBuffer succ" << endl;
215 OH_AVBuffer *buffer = OH_VideoDecoder_GetOutputBuffer(vdec_, index);
216 if (buffer == nullptr) {
217 cout << "OH_VideoDecoder_QueryOutputBuffer fail" << endl;
218 return AV_ERR_UNKNOWN;
219 }
220 if (sfOutput) {
221 if (isRenderAttime) {
222 ret = OH_VideoDecoder_RenderOutputBufferAtTime(vdec_, index, renderTimestampNs);
223 } else {
224 ret = OH_VideoDecoder_RenderOutputBuffer(vdec_, index);
225 }
226 } else {
227 ret = OH_VideoDecoder_FreeOutputBuffer(vdec_, index);
228 }
229 if (ret != AV_ERR_OK) {
230 Flush();
231 Start();
232 }
233 return AV_ERR_OK;
234 }
235
Flush()236 int32_t VDecSyncSample::Flush()
237 {
238 isFlushing_.store(true);
239 isRunning_.store(false);
240 int32_t ret = OH_VideoDecoder_Flush(vdec_);
241 isFlushing_.store(false);
242 return ret;
243 }
244
Reset()245 int32_t VDecSyncSample::Reset()
246 {
247 isRunning_.store(false);
248 return OH_VideoDecoder_Reset(vdec_);
249 }
250
Release()251 int32_t VDecSyncSample::Release()
252 {
253 int ret = 0;
254 if (vdec_ != nullptr) {
255 ret = OH_VideoDecoder_Destroy(vdec_);
256 vdec_ = nullptr;
257 }
258 return ret;
259 }
260
Stop()261 int32_t VDecSyncSample::Stop()
262 {
263 return OH_VideoDecoder_Stop(vdec_);
264 }
265
Start()266 int32_t VDecSyncSample::Start()
267 {
268 isRunning_.store(true);
269 return OH_VideoDecoder_Start(vdec_);
270 }
271
DecodeSetSurface()272 int32_t VDecSyncSample::DecodeSetSurface()
273 {
274 CreateSurface();
275 return OH_VideoDecoder_SetSurface(vdec_, nativeWindow[0]);
276 }
277
SetParameter(int32_t data)278 void VDecSyncSample::SetParameter(int32_t data)
279 {
280 OH_AVFormat *format = OH_AVFormat_Create();
281 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
282 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
283 OH_VideoDecoder_SetParameter(vdec_, format);
284 OH_AVFormat_Destroy(format);
285 }