1 /*
2  * Copyright (C) 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 #include <arpa/inet.h>
16 #include <sys/time.h>
17 #include <utility>
18 #include "iconsumer_surface.h"
19 #include "openssl/crypto.h"
20 #include "openssl/sha.h"
21 #include "native_buffer_inner.h"
22 #include "videoenc_api11_sample.h"
23 using namespace OHOS;
24 using namespace OHOS::Media;
25 using namespace std;
26 namespace {
27 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
28 constexpr int64_t NANOS_IN_MICRO = 1000L;
29 constexpr uint32_t FRAME_INTERVAL = 16666;
30 constexpr uint32_t MAX_PIXEL_FMT = 5;
31 constexpr uint32_t DEFAULT_BITRATE = 10000000;
32 constexpr uint32_t DOUBLE = 2;
33 sptr<Surface> cs = nullptr;
34 sptr<Surface> ps = nullptr;
35 
36 
clearIntqueue(std::queue<uint32_t> & q)37 void clearIntqueue(std::queue<uint32_t> &q)
38 {
39     std::queue<uint32_t> empty;
40     swap(empty, q);
41 }
42 } // namespace
43 
~VEncAPI11FuzzSample()44 VEncAPI11FuzzSample::~VEncAPI11FuzzSample()
45 {
46     if (surfInput && nativeWindow) {
47         OH_NativeWindow_DestroyNativeWindow(nativeWindow);
48         nativeWindow = nullptr;
49     }
50     Release();
51 }
52 
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)53 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
54 {
55     cout << "Error errorCode=" << errorCode << endl;
56 }
57 
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)58 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
59 {
60     cout << "Format Changed" << endl;
61 }
62 
onEncInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)63 static void onEncInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
64 {
65     VEncSignal *signal = static_cast<VEncSignal *>(userData);
66     unique_lock<mutex> lock(signal->inMutex_);
67     signal->inIdxQueue_.push(index);
68     signal->inBufferQueue_.push(buffer);
69     signal->inCond_.notify_all();
70 }
71 
onEncOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)72 static void onEncOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
73 {
74     OH_VideoEncoder_FreeOutputBuffer(codec, index);
75 }
76 
onEncInputParam(OH_AVCodec * codec,uint32_t index,OH_AVFormat * parameter,void * userData)77 static void onEncInputParam(OH_AVCodec *codec, uint32_t index, OH_AVFormat *parameter, void *userData)
78 {
79     OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
80     OH_VideoEncoder_PushInputParameter(codec, index);
81     return;
82 }
83 
GetSystemTimeUs()84 int64_t VEncAPI11FuzzSample::GetSystemTimeUs()
85 {
86     struct timespec now;
87     (void)clock_gettime(CLOCK_BOOTTIME, &now);
88     int64_t nanoTime = reinterpret_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
89 
90     return nanoTime / NANOS_IN_MICRO;
91 }
92 
ConfigureVideoEncoderFuzz(int32_t data)93 int32_t VEncAPI11FuzzSample::ConfigureVideoEncoderFuzz(int32_t data)
94 {
95     OH_AVFormat *format = OH_AVFormat_Create();
96     if (format == nullptr) {
97         cout << "Fatal: Failed to create format" << endl;
98         return AV_ERR_UNKNOWN;
99     }
100     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
101     defaultWidth = data;
102     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
103     defaultHeight = data;
104     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
105     double frameRate = data;
106     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
107 
108     OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, data);
109     OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, data);
110     OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, data);
111     OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, data);
112     OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, data);
113     OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
114     OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
115     OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, data);
116 
117     int ret = OH_VideoEncoder_Configure(venc_, format);
118     OH_AVFormat_Destroy(format);
119     return ret;
120 }
121 
ConfigureVideoEncoder()122 int32_t VEncAPI11FuzzSample::ConfigureVideoEncoder()
123 {
124     OH_AVFormat *format = OH_AVFormat_Create();
125     if (format == nullptr) {
126         return AV_ERR_UNKNOWN;
127     }
128     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
129     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
130     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defaultPixFmt);
131     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
132     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
133     if (defaultBitRate == CQ) {
134         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, defaultQuality);
135     } else {
136         (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitRate);
137     }
138     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitrateMode);
139     int ret = OH_VideoEncoder_Configure(venc_, format);
140     OH_AVFormat_Destroy(format);
141     return ret;
142 }
SetVideoEncoderCallback()143 int32_t VEncAPI11FuzzSample::SetVideoEncoderCallback()
144 {
145     signal_ = new VEncSignal();
146     if (signal_ == nullptr) {
147         cout << "Failed to new VEncSignal" << endl;
148         return AV_ERR_UNKNOWN;
149     }
150     if (surfInput) {
151         int32_t ret = OH_VideoEncoder_RegisterParameterCallback(venc_, onEncInputParam, static_cast<void *>(this));
152         if (ret != AV_ERR_OK) {
153             return ret;
154         }
155     }
156     cb_.onError = VencError;
157     cb_.onStreamChanged = VencFormatChanged;
158     cb_.onNeedInputBuffer = onEncInputBufferAvailable;
159     cb_.onNewOutputBuffer = onEncOutputBufferAvailable;
160     return OH_VideoEncoder_RegisterCallback(venc_, cb_, static_cast<void *>(signal_));
161 }
162 
StopInloop()163 void VEncAPI11FuzzSample::StopInloop()
164 {
165     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
166         unique_lock<mutex> lock(signal_->inMutex_);
167         clearIntqueue(signal_->inIdxQueue_);
168         isRunning_.store(false);
169         signal_->inCond_.notify_all();
170         lock.unlock();
171 
172         inputLoop_->join();
173         inputLoop_ = nullptr;
174     }
175 }
176 
ReleaseInFile()177 void VEncAPI11FuzzSample::ReleaseInFile()
178 {
179     if (inFile_ != nullptr) {
180         if (inFile_->is_open()) {
181             inFile_->close();
182         }
183         inFile_.reset();
184         inFile_ = nullptr;
185     }
186 }
187 
CreateSurface()188 int32_t VEncAPI11FuzzSample::CreateSurface()
189 {
190     int32_t ret = 0;
191     ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
192     if (ret != AV_ERR_OK) {
193         cout << "OH_VideoEncoder_GetSurface fail" << endl;
194         return ret;
195     }
196     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
197     if (ret != AV_ERR_OK) {
198         cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
199         return ret;
200     }
201     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, defaultWidth, defaultHeight);
202     if (ret != AV_ERR_OK) {
203         cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
204         return ret;
205     }
206     return AV_ERR_OK;
207 }
208 
OpenFile()209 int32_t VEncAPI11FuzzSample::OpenFile()
210 {
211     int32_t ret = AV_ERR_OK;
212     inFile_ = make_unique<ifstream>();
213     if (inFile_ == nullptr) {
214         isRunning_.store(false);
215         (void)OH_VideoEncoder_Stop(venc_);
216         return AV_ERR_UNKNOWN;
217     }
218     inFile_->open(inpDir, ios::in | ios::binary);
219     if (!inFile_->is_open()) {
220         cout << "file open fail" << endl;
221         isRunning_.store(false);
222         (void)OH_VideoEncoder_Stop(venc_);
223         inFile_->close();
224         inFile_.reset();
225         inFile_ = nullptr;
226         return AV_ERR_UNKNOWN;
227     }
228     return ret;
229 }
230 
GetStride()231 void VEncAPI11FuzzSample::GetStride()
232 {
233     OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
234     int32_t inputStride = 0;
235     OH_AVFormat_GetIntValue(format, "stride", &inputStride);
236     stride_ = inputStride;
237     OH_AVFormat_Destroy(format);
238 }
239 
StartVideoEncoder()240 int32_t VEncAPI11FuzzSample::StartVideoEncoder()
241 {
242     isRunning_.store(true);
243     int32_t ret = 0;
244     if (surfInput) {
245         ret = CreateSurface();
246         if (ret != AV_ERR_OK) {
247             return ret;
248         }
249     }
250     if (OpenFile() != AV_ERR_OK) {
251         return AV_ERR_UNKNOWN;
252     }
253     ret = OH_VideoEncoder_Start(venc_);
254     GetStride();
255     if (ret != AV_ERR_OK) {
256         isRunning_.store(false);
257         signal_->inCond_.notify_all();
258         return ret;
259     }
260     if (surfInput) {
261         inputLoop_ = make_unique<thread>(&VEncAPI11FuzzSample::InputFuncSurface, this);
262     } else {
263         inputLoop_ = make_unique<thread>(&VEncAPI11FuzzSample::InputFunc, this);
264     }
265     if (inputLoop_ == nullptr) {
266         isRunning_.store(false);
267         (void)OH_VideoEncoder_Stop(venc_);
268         return AV_ERR_UNKNOWN;
269     }
270     return AV_ERR_OK;
271 }
272 
CreateVideoEncoder()273 int32_t VEncAPI11FuzzSample::CreateVideoEncoder()
274 {
275     venc_ = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_AVC);
276     return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
277 }
278 
WaitForEOS()279 void VEncAPI11FuzzSample::WaitForEOS()
280 {
281     if (inputLoop_)
282         inputLoop_->join();
283     inputLoop_ = nullptr;
284 }
285 
PushData(OH_AVBuffer * buffer,uint32_t index,int32_t & result)286 int32_t VEncAPI11FuzzSample::PushData(OH_AVBuffer *buffer, uint32_t index, int32_t &result)
287 {
288     int32_t res = -2;
289     OH_AVCodecBufferAttr attr;
290     uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
291     if (fileBuffer == nullptr) {
292         cout << "Fatal: no memory" << endl;
293         return -1;
294     }
295     int32_t size = OH_AVBuffer_GetCapacity(buffer);
296     if (size < (defaultWidth * stride_ + (defaultWidth * stride_ / DOUBLE))) {
297         return -1;
298     }
299     attr.size = ReadOneFrameYUV420SP(fileBuffer);
300     if (inFile_->eof()) {
301         SetEOS(index, buffer);
302         return 0;
303     }
304     attr.pts = GetSystemTimeUs();
305     attr.offset = 0;
306     attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
307     OH_AVBuffer_SetBufferAttr(buffer, &attr);
308     result = OH_VideoEncoder_PushInputBuffer(venc_, index);
309     frameCount++;
310     unique_lock<mutex> lock(signal_->inMutex_);
311     signal_->inIdxQueue_.pop();
312     signal_->inBufferQueue_.pop();
313     return res;
314 }
315 
ReadOneFrameYUV420SP(uint8_t * dst)316 uint32_t VEncAPI11FuzzSample::ReadOneFrameYUV420SP(uint8_t *dst)
317 {
318     uint8_t *start = dst;
319     // copy Y
320     for (uint32_t i = 0; i < defaultWidth; i++) {
321         inFile_->read(reinterpret_cast<char *>(dst), defaultWidth);
322         if (!ReturnZeroIfEOS(defaultWidth)) {
323             return 0;
324         }
325         dst += stride_;
326     }
327     // copy UV
328     for (uint32_t i = 0; i < defaultWidth / DOUBLE; i++) {
329         inFile_->read(reinterpret_cast<char *>(dst), defaultWidth);
330         if (!ReturnZeroIfEOS(defaultWidth)) {
331             return 0;
332         }
333         dst += stride_;
334     }
335     return dst - start;
336 }
337 
ReturnZeroIfEOS(uint32_t expectedSize)338 uint32_t VEncAPI11FuzzSample::ReturnZeroIfEOS(uint32_t expectedSize)
339 {
340     if (inFile_->gcount() != (expectedSize)) {
341         cout << "no more data" << endl;
342         return 0;
343     }
344     return 1;
345 }
346 
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)347 uint32_t VEncAPI11FuzzSample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
348 {
349     struct Region region;
350     struct Region::Rect *rect = new Region::Rect();
351     rect->x = 0;
352     rect->y = 0;
353     rect->w = defaultWidth;
354     rect->h = defaultHeight;
355     region.rects = rect;
356     NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
357     int32_t err = OH_NativeBuffer_Unmap(nativeBuffer);
358     if (err != 0) {
359         return 1;
360     }
361     err = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
362     delete rect;
363     if (err != 0) {
364         return 1;
365     }
366     return 0;
367 }
368 
InputFuncSurface()369 void VEncAPI11FuzzSample::InputFuncSurface()
370 {
371     while (isRunning_.load()) {
372         OHNativeWindowBuffer *ohNativeWindowBuffer;
373         int fenceFd = -1;
374         if (nativeWindow == nullptr) {
375             cout << "nativeWindow == nullptr" << endl;
376             isRunning_.store(false);
377             break;
378         }
379         int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
380         if (err != 0) {
381             cout << "RequestBuffer failed, GSError=" << err << endl;
382             isRunning_.store(false);
383             break;
384         }
385         if (fenceFd > 0) {
386             close(fenceFd);
387         }
388         OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
389         void *virAddr = nullptr;
390         err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
391         if (err != 0) {
392             cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
393             isRunning_.store(false);
394             break;
395         }
396         if (frameCount == maxFrameInput) {
397             err = OH_VideoEncoder_NotifyEndOfStream(venc_);
398             if (err != 0) {
399                 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
400                 isRunning_.store(false);
401             }
402             break;
403         }
404         if (FlushSurf(ohNativeWindowBuffer, nativeBuffer)) {
405             break;
406         }
407         usleep(FRAME_INTERVAL);
408         frameCount++;
409     }
410 }
411 
SetEOS(uint32_t index,OH_AVBuffer * buffer)412 void VEncAPI11FuzzSample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
413 {
414     OH_AVCodecBufferAttr attr;
415     attr.pts = 0;
416     attr.size = 0;
417     attr.offset = 0;
418     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
419     OH_AVBuffer_SetBufferAttr(buffer, &attr);
420     int32_t res = OH_VideoEncoder_PushInputBuffer(venc_, index);
421     cout << "OH_VideoEncoder_PushInputBuffer    EOS   res: " << res << endl;
422     unique_lock<mutex> lock(signal_->inMutex_);
423     signal_->inIdxQueue_.pop();
424     signal_->inBufferQueue_.pop();
425 }
426 
InputFunc()427 void VEncAPI11FuzzSample::InputFunc()
428 {
429     errCount = 0;
430     while (isRunning_.load()) {
431         unique_lock<mutex> lock(signal_->inMutex_);
432         signal_->inCond_.wait(lock, [this]() {
433             if (!isRunning_.load()) {
434                 return true;
435             }
436             return signal_->inIdxQueue_.size() > 0;
437         });
438         if (!isRunning_.load()) {
439             break;
440         }
441         uint32_t index = signal_->inIdxQueue_.front();
442         auto buffer = signal_->inBufferQueue_.front();
443 
444         lock.unlock();
445         OH_AVCodecBufferAttr attr;
446         uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
447         if (fileBuffer == nullptr) {
448             break;
449         }
450         attr.size = OH_AVBuffer_GetCapacity(buffer);
451         if (frameCount == maxFrameInput) {
452             SetEOS(index, buffer);
453             break;
454         }
455         attr.pts = GetSystemTimeUs();
456         attr.offset = 0;
457         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
458         OH_AVBuffer_SetBufferAttr(buffer, &attr);
459         OH_VideoEncoder_PushInputBuffer(venc_, index);
460         frameCount++;
461         signal_->inIdxQueue_.pop();
462         signal_->inBufferQueue_.pop();
463         if (sleepOnFPS) {
464             usleep(FRAME_INTERVAL);
465         }
466     }
467 }
468 
CheckAttrFlag(OH_AVCodecBufferAttr attr)469 int32_t VEncAPI11FuzzSample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
470 {
471     if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
472         cout << "attr.flags == AVCODEC_BUFFER_FLAGS_EOS" << endl;
473         unique_lock<mutex> inLock(signal_->inMutex_);
474         isRunning_.store(false);
475         signal_->inCond_.notify_all();
476         inLock.unlock();
477         return -1;
478     }
479     if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
480         cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
481     }
482     return 0;
483 }
484 
Flush()485 int32_t VEncAPI11FuzzSample::Flush()
486 {
487     unique_lock<mutex> inLock(signal_->inMutex_);
488     clearIntqueue(signal_->inIdxQueue_);
489     signal_->inCond_.notify_all();
490     inLock.unlock();
491     return OH_VideoEncoder_Flush(venc_);
492 }
493 
Reset()494 int32_t VEncAPI11FuzzSample::Reset()
495 {
496     isRunning_.store(false);
497     StopInloop();
498     return OH_VideoEncoder_Reset(venc_);
499 }
500 
Release()501 int32_t VEncAPI11FuzzSample::Release()
502 {
503     int ret = OH_VideoEncoder_Destroy(venc_);
504     venc_ = nullptr;
505     if (signal_ != nullptr) {
506         delete signal_;
507         signal_ = nullptr;
508     }
509     return ret;
510 }
511 
Stop()512 int32_t VEncAPI11FuzzSample::Stop()
513 {
514     StopInloop();
515     return OH_VideoEncoder_Stop(venc_);
516 }
517 
Start()518 int32_t VEncAPI11FuzzSample::Start()
519 {
520     return OH_VideoEncoder_Start(venc_);
521 }
522 
SetParameter(int32_t data)523 int32_t VEncAPI11FuzzSample::SetParameter(int32_t data)
524 {
525     if (venc_) {
526         OH_AVFormat *format = OH_AVFormat_Create();
527         if (format == nullptr) {
528             return AV_ERR_UNKNOWN;
529         }
530         double frameRate = data;
531         (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
532         OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
533         int ret = OH_VideoEncoder_SetParameter(venc_, format);
534         OH_AVFormat_Destroy(format);
535         return ret;
536     }
537     return AV_ERR_UNKNOWN;
538 }