• 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 "softvideoenc_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 DEFAULT_BITRATE = 10000000;
28 constexpr uint32_t FRAME_INTERVAL = 16666;
29 VEncAPI11FuzzSample *g_sencSample = nullptr;
clearIntqueue(std::queue<uint32_t> & q)30 void clearIntqueue(std::queue<uint32_t> &q)
31 {
32     std::queue<uint32_t> empty;
33     swap(empty, q);
34 }
35 } // namespace
36 
~VEncAPI11FuzzSample()37 VEncAPI11FuzzSample::~VEncAPI11FuzzSample()
38 {
39     Release();
40 }
41 
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)42 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
43 {
44     cout << "Error errorCode=" << errorCode << endl;
45     g_sencSample->isRunning_.store(false);
46     g_sencSample->signal_->inCond_.notify_all();
47 }
48 
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)49 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
50 {
51     cout << "Format Changed" << endl;
52 }
53 
onEncInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)54 static void onEncInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
55 {
56     VEncSignal *signal = static_cast<VEncSignal *>(userData);
57     {
58         unique_lock<mutex> lock(signal->inMutex_);
59         signal->inIdxQueue_.push(index);
60         signal->inBufferQueue_.push(buffer);
61     }
62     signal->inCond_.notify_all();
63 }
64 
onEncOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * buffer,void * userData)65 static void onEncOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *buffer, void *userData)
66 {
67     VEncSignal *signal = static_cast<VEncSignal *>(userData);
68     OH_VideoEncoder_FreeOutputBuffer(codec, index);
69     cout << "count = " << signal->count++ << endl;
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     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, defaultWidth);
95     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, defaultHeight);
96     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, defaultPixFmt);
97     (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, defaultFrameRate);
98     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, defaultKeyFrameInterval);
99     if (defaultBitRateMode == CQ) {
100         (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, defaultQuality);
101     }
102     (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, defaultBitRateMode);
103     int ret = OH_VideoEncoder_Configure(venc_, format);
104     OH_AVFormat_Destroy(format);
105     return ret;
106 }
SetVideoEncoderCallback()107 int32_t VEncAPI11FuzzSample::SetVideoEncoderCallback()
108 {
109     signal_ = new VEncSignal();
110     if (signal_ == nullptr) {
111         cout << "Failed to new VEncSignal" << endl;
112         return AV_ERR_UNKNOWN;
113     }
114     if (surfInput) {
115         int32_t ret = OH_VideoEncoder_RegisterParameterCallback(venc_, onEncInputParam, static_cast<void *>(this));
116         if (ret != AV_ERR_OK) {
117             return ret;
118         }
119     }
120     cb_.onError = VencError;
121     cb_.onStreamChanged = VencFormatChanged;
122     cb_.onNeedInputBuffer = onEncInputBufferAvailable;
123     cb_.onNewOutputBuffer = onEncOutputBufferAvailable;
124     return OH_VideoEncoder_RegisterCallback(venc_, cb_, static_cast<void *>(signal_));
125 }
126 
StopInloop()127 void VEncAPI11FuzzSample::StopInloop()
128 {
129     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
130         unique_lock<mutex> lock(signal_->inMutex_);
131         clearIntqueue(signal_->inIdxQueue_);
132         isRunning_.store(false);
133         signal_->inCond_.notify_all();
134         lock.unlock();
135 
136         inputLoop_->join();
137         inputLoop_ = nullptr;
138     }
139 }
140 
GetStride()141 void VEncAPI11FuzzSample::GetStride()
142 {
143     OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
144     int32_t inputStride = 0;
145     OH_AVFormat_GetIntValue(format, "stride", &inputStride);
146     stride_ = inputStride;
147     OH_AVFormat_Destroy(format);
148 }
149 
StartVideoEncoder()150 int32_t VEncAPI11FuzzSample::StartVideoEncoder()
151 {
152     isRunning_.store(true);
153     int32_t ret = 0;
154     ret = OH_VideoEncoder_Start(venc_);
155     GetStride();
156     if (ret != AV_ERR_OK) {
157         isRunning_.store(false);
158         signal_->inCond_.notify_all();
159         return ret;
160     }
161     inputLoop_ = make_unique<thread>(&VEncAPI11FuzzSample::InputFunc, this);
162     if (inputLoop_ == nullptr) {
163         isRunning_.store(false);
164         (void)OH_VideoEncoder_Stop(venc_);
165         return AV_ERR_UNKNOWN;
166     }
167     return AV_ERR_OK;
168 }
169 
CreateVideoEncoder(const char * codecName)170 int32_t VEncAPI11FuzzSample::CreateVideoEncoder(const char *codecName)
171 {
172     venc_ = OH_VideoEncoder_CreateByName(codecName);
173     g_sencSample = this;
174     return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
175 }
176 
WaitForEOS()177 void VEncAPI11FuzzSample::WaitForEOS()
178 {
179     if (inputLoop_ && inputLoop_->joinable()) {
180         inputLoop_->join();
181     }
182 }
183 
SetEOS(uint32_t index,OH_AVBuffer * buffer)184 void VEncAPI11FuzzSample::SetEOS(uint32_t index, OH_AVBuffer *buffer)
185 {
186     OH_AVCodecBufferAttr attr;
187     attr.pts = 0;
188     attr.size = 0;
189     attr.offset = 0;
190     attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
191     OH_AVBuffer_SetBufferAttr(buffer, &attr);
192     int32_t res = OH_VideoEncoder_PushInputBuffer(venc_, index);
193     cout << "OH_VideoEncoder_PushInputBuffer    EOS   res: " << res << endl;
194     unique_lock<mutex> lock(signal_->inMutex_);
195     signal_->inIdxQueue_.pop();
196     signal_->inBufferQueue_.pop();
197 }
198 
InputFunc()199 void VEncAPI11FuzzSample::InputFunc()
200 {
201     while (isRunning_.load()) {
202         unique_lock<mutex> lock(signal_->inMutex_);
203         signal_->inCond_.wait(lock, [this]() {
204             if (!isRunning_.load()) {
205                 return true;
206             }
207             return signal_->inIdxQueue_.size() > 0;
208         });
209         if (!isRunning_.load()) {
210             break;
211         }
212         uint32_t index = signal_->inIdxQueue_.front();
213         auto buffer = signal_->inBufferQueue_.front();
214         signal_->inIdxQueue_.pop();
215         signal_->inBufferQueue_.pop();
216         lock.unlock();
217         OH_AVCodecBufferAttr attr;
218         uint8_t *fileBuffer = OH_AVBuffer_GetAddr(buffer);
219         int32_t bufferSize = OH_AVBuffer_GetCapacity(buffer);
220         if (fileBuffer == nullptr) {
221             break;
222         }
223         if (memcpy_s(fileBuffer, bufferSize, fuzzData, fuzzSize) != EOK) {
224             cout << "Fatal: memcpy fail" << endl;
225             break;
226         }
227         if (frameCount == maxFrameInput) {
228             SetEOS(index, buffer);
229             break;
230         }
231         attr.pts = GetSystemTimeUs();
232         attr.size = bufferSize;
233         attr.offset = 0;
234         attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
235         OH_AVBuffer_SetBufferAttr(buffer, &attr);
236         OH_VideoEncoder_PushInputBuffer(venc_, index);
237         frameCount++;
238         if (sleepOnFPS) {
239             usleep(FRAME_INTERVAL);
240         }
241     }
242 }
243 
Flush()244 int32_t VEncAPI11FuzzSample::Flush()
245 {
246     unique_lock<mutex> inLock(signal_->inMutex_);
247     clearIntqueue(signal_->inIdxQueue_);
248     signal_->inCond_.notify_all();
249     inLock.unlock();
250     return OH_VideoEncoder_Flush(venc_);
251 }
252 
Reset()253 int32_t VEncAPI11FuzzSample::Reset()
254 {
255     isRunning_.store(false);
256     StopInloop();
257     return OH_VideoEncoder_Reset(venc_);
258 }
259 
Release()260 int32_t VEncAPI11FuzzSample::Release()
261 {
262     int ret = OH_VideoEncoder_Destroy(venc_);
263     venc_ = nullptr;
264     if (signal_ != nullptr) {
265         delete signal_;
266         signal_ = nullptr;
267     }
268     return ret;
269 }
270 
Stop()271 int32_t VEncAPI11FuzzSample::Stop()
272 {
273     StopInloop();
274     return OH_VideoEncoder_Stop(venc_);
275 }
276 
Start()277 int32_t VEncAPI11FuzzSample::Start()
278 {
279     return OH_VideoEncoder_Start(venc_);
280 }
281