• 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 "native_buffer_inner.h"
20 #include "videoenc_api11_sample.h"
21 using namespace OHOS;
22 using namespace OHOS::Media;
23 using namespace std;
24 namespace {
25 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
26 constexpr int64_t NANOS_IN_MICRO = 1000L;
27 constexpr uint32_t FRAME_INTERVAL = 16666;
28 constexpr uint32_t DEFAULT_BITRATE = 10000000;
29 constexpr uint32_t DOUBLE = 2;
30 constexpr uint32_t THREE = 3;
31 sptr<Surface> cs = nullptr;
32 sptr<Surface> ps = nullptr;
33 VEncAPI11FuzzSample *g_vEncSample = nullptr;
34 
35 } // namespace
36 
~VEncAPI11FuzzSample()37 VEncAPI11FuzzSample::~VEncAPI11FuzzSample()
38 {
39     if (surfInput && nativeWindow) {
40         OH_NativeWindow_DestroyNativeWindow(nativeWindow);
41         nativeWindow = nullptr;
42     }
43     Release();
44 }
45 
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)46 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
47 {
48     cout << "Error errorCode=" << errorCode << endl;
49     g_vEncSample->isRunning_.store(false);
50     g_vEncSample->signal_->inCond_.notify_all();
51 }
52 
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)53 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
54 {
55     cout << "Format Changed" << endl;
56 }
57 
onEncInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)58 static void onEncInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
59 {
60     VEncSignal *signal = static_cast<VEncSignal *>(userData);
61     unique_lock<mutex> lock(signal->inMutex_);
62     signal->inIdxQueue_.push(index);
63     signal->inBufferQueue_.push(buffer);
64     signal->inCond_.notify_all();
65 }
66 
onEncOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)67 static void onEncOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
68 {
69     OH_VideoEncoder_FreeOutputBuffer(codec, index);
70 }
71 
onEncInputParam(OH_AVCodec * codec,uint32_t index,OH_AVFormat * parameter,void * userData)72 static void onEncInputParam(OH_AVCodec *codec, uint32_t index, OH_AVFormat *parameter, void *userData)
73 {
74     OH_AVFormat_SetIntValue(parameter, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
75     OH_VideoEncoder_PushInputParameter(codec, index);
76     return;
77 }
78 
GetSystemTimeUs()79 int64_t VEncAPI11FuzzSample::GetSystemTimeUs()
80 {
81     struct timespec now;
82     (void)clock_gettime(CLOCK_BOOTTIME, &now);
83     int64_t nanoTime = reinterpret_cast<int64_t>(now.tv_sec) * NANOS_IN_SECOND + now.tv_nsec;
84 
85     return nanoTime / NANOS_IN_MICRO;
86 }
87 
ConfigureVideoEncoder()88 int32_t VEncAPI11FuzzSample::ConfigureVideoEncoder()
89 {
90     OH_AVFormat *format = OH_AVFormat_Create();
91     if (format == nullptr) {
92         return AV_ERR_UNKNOWN;
93     }
94     OH_AVFormat_SetIntValue(format, OH_MD_KEY_PROFILE, HEVC_PROFILE_MAIN_10);
95     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
96     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
97     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defaultPixFmt);
98     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
99     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
100     if (defaultBitRate == CQ) {
101         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, defaultQuality);
102     } else {
103         (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitRate);
104     }
105     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitrateMode);
106     if (enableRepeat) {
107         OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, 1);
108         if (setMaxCount) {
109             OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, 1);
110         }
111     }
112     int ret = OH_VideoEncoder_Configure(venc_, format);
113     OH_AVFormat_Destroy(format);
114     return ret;
115 }
SetVideoEncoderCallback()116 int32_t VEncAPI11FuzzSample::SetVideoEncoderCallback()
117 {
118     signal_ = new VEncSignal();
119     if (signal_ == nullptr) {
120         cout << "Failed to new VEncSignal" << endl;
121         return AV_ERR_UNKNOWN;
122     }
123     if (surfInput) {
124         int32_t ret = OH_VideoEncoder_RegisterParameterCallback(venc_, onEncInputParam, static_cast<void *>(this));
125         if (ret != AV_ERR_OK) {
126             return ret;
127         }
128     }
129     cb_.onError = VencError;
130     cb_.onStreamChanged = VencFormatChanged;
131     cb_.onNeedInputBuffer = onEncInputBufferAvailable;
132     cb_.onNewOutputBuffer = onEncOutputBufferAvailable;
133     return OH_VideoEncoder_RegisterCallback(venc_, cb_, static_cast<void *>(signal_));
134 }
135 
CreateSurface()136 int32_t VEncAPI11FuzzSample::CreateSurface()
137 {
138     int32_t ret = 0;
139     ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
140     if (ret != AV_ERR_OK) {
141         cout << "OH_VideoEncoder_GetSurface fail" << endl;
142         return ret;
143     }
144     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
145     if (ret != AV_ERR_OK) {
146         cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
147         return ret;
148     }
149     ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, defaultWidth, defaultHeight);
150     if (ret != AV_ERR_OK) {
151         cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
152         return ret;
153     }
154     return AV_ERR_OK;
155 }
156 
OpenFile()157 int32_t VEncAPI11FuzzSample::OpenFile()
158 {
159     if (fuzzMode) {
160         return AV_ERR_OK;
161     }
162     int32_t ret = AV_ERR_OK;
163     inFile_ = make_unique<ifstream>();
164     if (inFile_ == nullptr) {
165         isRunning_.store(false);
166         (void)OH_VideoEncoder_Stop(venc_);
167         return AV_ERR_UNKNOWN;
168     }
169     inFile_->open(inpDir, ios::in | ios::binary);
170     if (!inFile_->is_open()) {
171         cout << "file open fail" << endl;
172         isRunning_.store(false);
173         (void)OH_VideoEncoder_Stop(venc_);
174         inFile_->close();
175         inFile_.reset();
176         inFile_ = nullptr;
177         return AV_ERR_UNKNOWN;
178     }
179     return ret;
180 }
181 
GetStride()182 void VEncAPI11FuzzSample::GetStride()
183 {
184     OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
185     int32_t inputStride = 0;
186     OH_AVFormat_GetIntValue(format, "stride", &inputStride);
187     stride_ = inputStride;
188     OH_AVFormat_Destroy(format);
189 }
190 
StartVideoEncoder()191 int32_t VEncAPI11FuzzSample::StartVideoEncoder()
192 {
193     isRunning_.store(true);
194     int32_t ret = 0;
195     if (surfInput) {
196         ret = CreateSurface();
197         if (ret != AV_ERR_OK) {
198             return ret;
199         }
200     }
201     if (OpenFile() != AV_ERR_OK) {
202         return AV_ERR_UNKNOWN;
203     }
204     ret = OH_VideoEncoder_Start(venc_);
205     GetStride();
206     if (ret != AV_ERR_OK) {
207         isRunning_.store(false);
208         signal_->inCond_.notify_all();
209         return ret;
210     }
211     if (surfInput) {
212         inputLoop_ = make_unique<thread>(&VEncAPI11FuzzSample::InputFuncSurface, this);
213     } else {
214         inputLoop_ = make_unique<thread>(&VEncAPI11FuzzSample::InputFunc, this);
215     }
216     if (inputLoop_ == nullptr) {
217         isRunning_.store(false);
218         (void)OH_VideoEncoder_Stop(venc_);
219         return AV_ERR_UNKNOWN;
220     }
221     return AV_ERR_OK;
222 }
223 
CreateVideoEncoder()224 int32_t VEncAPI11FuzzSample::CreateVideoEncoder()
225 {
226     venc_ = OH_VideoEncoder_CreateByMime(OH_AVCODEC_MIMETYPE_VIDEO_HEVC);
227     g_vEncSample = this;
228     return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
229 }
230 
WaitForEOS()231 void VEncAPI11FuzzSample::WaitForEOS()
232 {
233     if (inputLoop_)
234         inputLoop_->join();
235     inputLoop_ = nullptr;
236 }
237 
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)238 uint32_t VEncAPI11FuzzSample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
239 {
240     struct Region region;
241     struct Region::Rect *rect = new Region::Rect();
242     rect->x = 0;
243     rect->y = 0;
244     rect->w = defaultWidth;
245     rect->h = defaultHeight;
246     region.rects = rect;
247     NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
248     int32_t err = OH_NativeBuffer_Unmap(nativeBuffer);
249     if (err != 0) {
250         return 1;
251     }
252     err = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
253     delete rect;
254     if (err != 0) {
255         return 1;
256     }
257     return 0;
258 }
259 
InputFuncSurface()260 void VEncAPI11FuzzSample::InputFuncSurface()
261 {
262     while (isRunning_.load()) {
263         OHNativeWindowBuffer *ohNativeWindowBuffer;
264         int fenceFd = -1;
265         if (nativeWindow == nullptr) {
266             cout << "nativeWindow == nullptr" << endl;
267             isRunning_.store(false);
268             break;
269         }
270         int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
271         if (err != 0) {
272             cout << "RequestBuffer failed, GSError=" << err << endl;
273             isRunning_.store(false);
274             break;
275         }
276         if (fenceFd > 0) {
277             close(fenceFd);
278         }
279         OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
280         void *virAddr = nullptr;
281         OH_NativeBuffer_Config config;
282         OH_NativeBuffer_GetConfig (nativeBuffer, &config);
283         err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
284         if (err != 0) {
285             cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
286             isRunning_.store(false);
287             break;
288         }
289         uint8_t *dst = (uint8_t *)virAddr;
290         if (dst == nullptr) {
291             break;
292         }
293         if (memcpy_s(dst, (config.stride * config.height * THREE) / DOUBLE, fuzzData, fuzzSize) != EOK) {
294             break;
295         }
296         if (frameCount == maxFrameInput) {
297             err = OH_VideoEncoder_NotifyEndOfStream(venc_);
298             if (err != 0) {
299                 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
300                 isRunning_.store(false);
301             }
302             break;
303         }
304         if (FlushSurf(ohNativeWindowBuffer, nativeBuffer)) {
305             break;
306         }
307         usleep(FRAME_INTERVAL);
308         frameCount++;
309     }
310 }
311 
SetEOS(uint32_t index,OH_AVBuffer * buffer)312 void VEncAPI11FuzzSample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
313 {
314     OH_AVCodecBufferAttr attr;
315     attr.pts = 0;
316     attr.size = 0;
317     attr.offset = 0;
318     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
319     OH_AVBuffer_SetBufferAttr(buffer, &attr);
320     int32_t res = OH_VideoEncoder_PushInputBuffer(venc_, index);
321     cout << "OH_VideoEncoder_PushInputBuffer    EOS   res: " << res << endl;
322     unique_lock<mutex> lock(signal_->inMutex_);
323 }
324 
InputFunc()325 void VEncAPI11FuzzSample::InputFunc()
326 {
327     errCount = 0;
328     while (isRunning_.load()) {
329         unique_lock<mutex> lock(signal_->inMutex_);
330         signal_->inCond_.wait(lock, [this]() {
331             if (!isRunning_.load()) {
332                 return true;
333             }
334             return signal_->inIdxQueue_.size() > 0;
335         });
336         if (!isRunning_.load()) {
337             break;
338         }
339         uint32_t index = signal_->inIdxQueue_.front();
340         auto buffer = signal_->inBufferQueue_.front();
341 
342         signal_->inIdxQueue_.pop();
343         signal_->inBufferQueue_.pop();
344 
345         lock.unlock();
346         OH_AVCodecBufferAttr attr;
347         int32_t bufferSize = OH_AVBuffer_GetCapacity(buffer);
348         uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
349         if (fileBuffer == nullptr) {
350             break;
351         }
352         if (memcpy_s(fileBuffer, bufferSize, fuzzData, fuzzSize) != EOK) {
353             cout << "Fatal: memcpy fail" << endl;
354             break;
355         }
356         attr.size = fuzzSize;
357         if (frameCount == maxFrameInput) {
358             SetEOS(index, buffer);
359             break;
360         }
361         attr.pts = GetSystemTimeUs();
362         attr.offset = 0;
363         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
364         OH_AVBuffer_SetBufferAttr(buffer, &attr);
365         OH_VideoEncoder_PushInputBuffer(venc_, index);
366         frameCount++;
367         if (sleepOnFPS) {
368             usleep(FRAME_INTERVAL);
369         }
370     }
371 }
372 
Release()373 int32_t VEncAPI11FuzzSample::Release()
374 {
375     int ret = OH_VideoEncoder_Destroy(venc_);
376     venc_ = nullptr;
377     if (signal_ != nullptr) {
378         delete signal_;
379         signal_ = nullptr;
380     }
381     return ret;
382 }
383 
SetParameter(int32_t data)384 int32_t VEncAPI11FuzzSample::SetParameter(int32_t data)
385 {
386     if (venc_) {
387         OH_AVFormat *format = OH_AVFormat_Create();
388         if (format == nullptr) {
389             return AV_ERR_UNKNOWN;
390         }
391         double frameRate = data;
392         (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
393         OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
394         int ret = OH_VideoEncoder_SetParameter(venc_, format);
395         OH_AVFormat_Destroy(format);
396         return ret;
397     }
398     return AV_ERR_UNKNOWN;
399 }