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