• 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 "iconsumer_surface.h"
19 #include "meta/meta_key.h"
20 #include "openssl/crypto.h"
21 #include "openssl/sha.h"
22 #include "native_buffer_inner.h"
23 #include "videodec_inner_sample.h"
24 
25 using namespace OHOS;
26 using namespace OHOS::MediaAVCodec;
27 using namespace std;
28 
29 namespace {
30 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
31 constexpr int64_t NANOS_IN_MICRO = 1000L;
32 constexpr uint32_t START_CODE_SIZE = 4;
33 constexpr uint8_t START_CODE[START_CODE_SIZE] = {0, 0, 0, 1};
34 int32_t g_strideSurface = 0;
35 int32_t g_sliceSurface = 0;
36 VDecNdkInnerFuzzSample *g_decSample = nullptr;
37 
clearIntqueue(std::queue<uint32_t> & q)38 void clearIntqueue(std::queue<uint32_t> &q)
39 {
40     std::queue<uint32_t> empty;
41     swap(empty, q);
42 }
43 
clearBufferqueue(std::queue<AVCodecBufferInfo> & q)44 void clearBufferqueue(std::queue<AVCodecBufferInfo> &q)
45 {
46     std::queue<AVCodecBufferInfo> empty;
47     swap(empty, q);
48 }
49 
clearFlagqueue(std::queue<AVCodecBufferFlag> & q)50 void clearFlagqueue(std::queue<AVCodecBufferFlag> &q)
51 {
52     std::queue<AVCodecBufferFlag> empty;
53     swap(empty, q);
54 }
55 } // namespace
56 
57 class ConsumerListenerBuffer : public IBufferConsumerListener {
58 public:
ConsumerListenerBuffer(sptr<Surface> cs,std::string_view name)59     ConsumerListenerBuffer(sptr<Surface> cs, std::string_view name) : cs(cs)
60     {
61         outFile_ = std::make_unique<std::ofstream>();
62         outFile_->open(name.data(), std::ios::out | std::ios::binary);
63     };
~ConsumerListenerBuffer()64     ~ConsumerListenerBuffer()
65     {
66         if (outFile_ != nullptr) {
67             outFile_->close();
68         }
69     }
OnBufferAvailable()70     void OnBufferAvailable() override
71     {
72         sptr<SurfaceBuffer> buffer;
73         int32_t flushFence;
74         cs->AcquireBuffer(buffer, flushFence, timestamp, damage);
75         cs->ReleaseBuffer(buffer, -1);
76     }
77 
78 private:
79     int64_t timestamp = 0;
80     Rect damage = {};
81     sptr<Surface> cs {nullptr};
82     std::unique_ptr<std::ofstream> outFile_;
83 };
84 
VDecInnerCallback(std::shared_ptr<VDecInnerSignal> signal)85 VDecInnerCallback::VDecInnerCallback(std::shared_ptr<VDecInnerSignal> signal) : innersignal_(signal) {}
86 
OnError(AVCodecErrorType errorType,int32_t errorCode)87 void VDecInnerCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
88 {
89     g_decSample->isRunning_.store(false);
90     innersignal_->inCond_.notify_all();
91     innersignal_->outCond_.notify_all();
92 }
93 
OnOutputFormatChanged(const Format & format)94 void VDecInnerCallback::OnOutputFormatChanged(const Format& format)
95 {
96     cout << "Format Changed" << endl;
97     int32_t currentWidth = 0;
98     int32_t currentHeight = 0;
99     int32_t stride = 0;
100     int32_t sliceHeight = 0;
101     format.GetIntValue(MediaDescriptionKey::MD_KEY_WIDTH, currentWidth);
102     format.GetIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, currentHeight);
103     format.GetIntValue(Media::Tag::VIDEO_STRIDE, stride);
104     format.GetIntValue(Media::Tag::VIDEO_SLICE_HEIGHT, sliceHeight);
105     g_decSample->defaultWidth = currentWidth;
106     g_decSample->defaultHeight = currentHeight;
107     g_strideSurface = stride;
108     g_sliceSurface = sliceHeight;
109 }
110 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)111 void VDecInnerCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
112 {
113     cout << "OnInputBufferAvailable index:" << index << endl;
114     if (innersignal_ == nullptr) {
115         std::cout << "buffer is null 1" << endl;
116         return;
117     }
118 
119     unique_lock<mutex> lock(innersignal_->inMutex_);
120     innersignal_->inIdxQueue_.push(index);
121     innersignal_->inBufferQueue_.push(buffer);
122     innersignal_->inCond_.notify_all();
123 }
124 
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)125 void VDecInnerCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info,
126     AVCodecBufferFlag flag, std::shared_ptr<AVSharedMemory> buffer)
127 {
128     if (g_decSample->sfOutput) {
129         g_decSample->vdec_->ReleaseOutputBuffer(index, true);
130     } else {
131         g_decSample->vdec_->ReleaseOutputBuffer(index, false);
132     }
133 }
134 
~VDecNdkInnerFuzzSample()135 VDecNdkInnerFuzzSample::~VDecNdkInnerFuzzSample()
136 {
137     for (int i = 0; i < static_cast<int>(maxSurfNum); i++) {
138         if (nativeWindow[i]) {
139             OH_NativeWindow_DestroyNativeWindow(nativeWindow[i]);
140             nativeWindow[i] = nullptr;
141         }
142     }
143     if (vdec_ != nullptr) {
144         (void)Stop();
145         Release();
146     }
147 }
148 
GetSystemTimeUs()149 int64_t VDecNdkInnerFuzzSample::GetSystemTimeUs()
150 {
151     struct timespec now;
152     (void)clock_gettime(CLOCK_BOOTTIME, &now);
153     int64_t nanoTime = static_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
154 
155     return nanoTime / NANOS_IN_MICRO;
156 }
157 
CreateSurface()158 void VDecNdkInnerFuzzSample::CreateSurface()
159 {
160     cs[0] = Surface::CreateSurfaceAsConsumer();
161     if (cs[0] == nullptr) {
162         cout << "Create the surface consummer fail" << endl;
163         return;
164     }
165     GSError err = cs[0]->SetDefaultUsage(BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_VIDEO_DECODER | BUFFER_USAGE_CPU_READ);
166     if (err == GSERROR_OK) {
167         cout << "set consumer usage succ" << endl;
168     } else {
169         cout << "set consumer usage failed" << endl;
170     }
171     sptr<IBufferConsumerListener> listener = new ConsumerListenerBuffer(cs[0], outDir);
172     cs[0]->RegisterConsumerListener(listener);
173     auto p = cs[0]->GetProducer();
174     ps[0] = Surface::CreateSurfaceAsProducer(p);
175     nativeWindow[0] = CreateNativeWindowFromSurface(&ps[0]);
176     if (autoSwitchSurface)  {
177         cs[1] = Surface::CreateSurfaceAsConsumer();
178         sptr<IBufferConsumerListener> listener2 = new ConsumerListenerBuffer(cs[1], outDir2);
179         cs[1]->RegisterConsumerListener(listener2);
180         auto p2 = cs[1]->GetProducer();
181         ps[1] = Surface::CreateSurfaceAsProducer(p2);
182         nativeWindow[1] = CreateNativeWindowFromSurface(&ps[1]);
183     }
184 }
185 
CreateByName(const std::string & name)186 int32_t VDecNdkInnerFuzzSample::CreateByName(const std::string &name)
187 {
188     vdec_ = VideoDecoderFactory::CreateByName(name);
189     g_decSample = this;
190     return vdec_ == nullptr ? AVCS_ERR_INVALID_OPERATION : AVCS_ERR_OK;
191 }
192 
Configure()193 int32_t VDecNdkInnerFuzzSample::Configure()
194 {
195     if (autoSwitchSurface) {
196         switchSurfaceFlag = (switchSurfaceFlag == 1) ? 0 : 1;
197         if (ps[switchSurfaceFlag] != nullptr) {
198             if (vdec_->SetOutputSurface(ps[switchSurfaceFlag]) != AVCS_ERR_INVALID_STATE) {
199                 errCount++;
200             }
201         }
202     }
203     Format format;
204     format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, defaultWidth);
205     format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, defaultHeight);
206     format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, DEFAULT_FORMAT);
207     format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, defaultFrameRate);
208     format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_DECODER_OUTPUT_COLOR_SPACE, defaultColorspace);
209     return vdec_->Configure(format);
210 }
211 
Prepare()212 int32_t VDecNdkInnerFuzzSample::Prepare()
213 {
214     return vdec_->Prepare();
215 }
216 
Start()217 int32_t VDecNdkInnerFuzzSample::Start()
218 {
219     int32_t ret = vdec_->Start();
220     if (ret != AVCS_ERR_OK) {
221         cout << "Failed to start codec" << endl;
222         isRunning_.store(false);
223         Release();
224     }
225     return ret;
226 }
227 
Stop()228 int32_t VDecNdkInnerFuzzSample::Stop()
229 {
230     if (signal_ != nullptr) {
231         clearIntqueue(signal_->outIdxQueue_);
232         clearBufferqueue(signal_->infoQueue_);
233         clearFlagqueue(signal_->flagQueue_);
234     }
235 
236     return vdec_->Stop();
237 }
238 
Flush()239 int32_t VDecNdkInnerFuzzSample::Flush()
240 {
241     unique_lock<mutex> inLock(signal_->inMutex_);
242     clearIntqueue(signal_->inIdxQueue_);
243     signal_->inCond_.notify_all();
244     inLock.unlock();
245     unique_lock<mutex> outLock(signal_->outMutex_);
246     clearIntqueue(signal_->outIdxQueue_);
247     clearBufferqueue(signal_->infoQueue_);
248     clearFlagqueue(signal_->flagQueue_);
249     signal_->outCond_.notify_all();
250     outLock.unlock();
251 
252     return vdec_->Flush();
253 }
254 
Reset()255 int32_t VDecNdkInnerFuzzSample::Reset()
256 {
257     isRunning_.store(false);
258     return vdec_->Reset();
259 }
260 
Release()261 int32_t VDecNdkInnerFuzzSample::Release()
262 {
263     int32_t ret = 0;
264     if (vdec_ != nullptr) {
265         ret = vdec_->Release();
266         vdec_ = nullptr;
267     }
268     if (signal_ != nullptr) {
269         signal_ = nullptr;
270     }
271     return ret;
272 }
273 
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)274 int32_t VDecNdkInnerFuzzSample::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
275 {
276     return vdec_->QueueInputBuffer(index, info, flag);
277 }
278 
ReleaseOutputBuffer(uint32_t index)279 int32_t VDecNdkInnerFuzzSample::ReleaseOutputBuffer(uint32_t index)
280 {
281     return vdec_->ReleaseOutputBuffer(index, false);
282 }
283 
SetCallback()284 int32_t VDecNdkInnerFuzzSample::SetCallback()
285 {
286     signal_ = make_shared<VDecInnerSignal>();
287     if (signal_ == nullptr) {
288         cout << "Failed to new VEncInnerSignal" << endl;
289         return AVCS_ERR_UNKNOWN;
290     }
291 
292     cb_ = make_shared<VDecInnerCallback>(signal_);
293     return vdec_->SetCallback(cb_);
294 }
295 
InputFuncFUZZ(const uint8_t * data,size_t size)296 int32_t VDecNdkInnerFuzzSample::InputFuncFUZZ(const uint8_t *data, size_t size)
297 {
298     unique_lock<mutex> lock(signal_->inMutex_);
299     if (!isRunning_.load()) {
300         return AVCS_ERR_NO_MEMORY;
301     }
302     signal_->inCond_.wait(lock, [this]() {
303         if (!isRunning_.load()) {
304             return true;
305         }
306         return signal_->inIdxQueue_.size() > 0;
307     });
308 
309     if (!isRunning_.load()) {
310         return AVCS_ERR_NO_MEMORY;
311     }
312 
313     uint32_t index = signal_->inIdxQueue_.front();
314     auto buffer = signal_->inBufferQueue_.front();
315     signal_->inIdxQueue_.pop();
316     signal_->inBufferQueue_.pop();
317     lock.unlock();
318     int32_t bufferSize = buffer->GetSize();
319     uint8_t *bufferAddr = buffer->GetBase();
320     if (size > bufferSize - START_CODE_SIZE) {
321         vdec_->QueueInputBuffer(index);
322         return AV_ERR_NO_MEMORY;
323     }
324     if (memcpy_s(bufferAddr, bufferSize, START_CODE, START_CODE_SIZE) != EOK) {
325         vdec_->QueueInputBuffer(index);
326         return AV_ERR_NO_MEMORY;
327     }
328     if (memcpy_s(bufferAddr + START_CODE_SIZE, bufferSize - START_CODE_SIZE, data, size) != EOK) {
329         vdec_->QueueInputBuffer(index);
330         cout << "Fatal: memcpy fail" << endl;
331         return AV_ERR_NO_MEMORY;
332     }
333     AVCodecBufferInfo info;
334     AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_NONE;
335     info.presentationTimeUs = GetSystemTimeUs();
336     info.size = bufferSize + START_CODE_SIZE;
337     info.offset = 0;
338     return vdec_->QueueInputBuffer(index, info, flag);
339 }
340 
SetOutputSurface()341 int32_t VDecNdkInnerFuzzSample::SetOutputSurface()
342 {
343     CreateSurface();
344     return vdec_->SetOutputSurface(ps[0]);
345 }