• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }