1 /*
2 * Copyright (C) 2023 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 "display_type.h"
21 #include "videoenc_sample.h"
22 using namespace OHOS;
23 using namespace OHOS::Media;
24 using namespace std;
25 namespace {
26 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
27 constexpr int64_t NANOS_IN_MICRO = 1000L;
28 constexpr uint32_t FRAME_INTERVAL = 16666;
29 constexpr uint32_t MAX_PIXEL_FMT = 5;
30 constexpr uint8_t RGBA_SIZE = 4;
31 constexpr uint32_t IDR_FRAME_INTERVAL = 10;
32 constexpr uint32_t TEST_FRAME_COUNT = 25;
33 constexpr uint32_t DOUBLE = 2;
34 sptr<Surface> cs = nullptr;
35 sptr<Surface> ps = nullptr;
36 VEncNdkSample *enc_sample = 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<OH_AVCodecBufferAttr> & q)44 void clearBufferqueue(std::queue<OH_AVCodecBufferAttr> &q)
45 {
46 std::queue<OH_AVCodecBufferAttr> empty;
47 swap(empty, q);
48 }
49 } // namespace
50
~VEncNdkSample()51 VEncNdkSample::~VEncNdkSample()
52 {
53 if (SURF_INPUT && nativeWindow) {
54 OH_NativeWindow_DestroyNativeWindow(nativeWindow);
55 nativeWindow = nullptr;
56 }
57 Release();
58 }
59
VencError(OH_AVCodec * codec,int32_t errorCode,void * userData)60 static void VencError(OH_AVCodec *codec, int32_t errorCode, void *userData)
61 {
62 cout << "Error errorCode=" << errorCode << endl;
63 }
64
VencFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)65 static void VencFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
66 {
67 cout << "Format Changed" << endl;
68 }
69
VencInputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,void * userData)70 static void VencInputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData)
71 {
72 if (enc_sample->isFlushing_) {
73 return;
74 }
75 if (enc_sample->inputCallbackFlush) {
76 enc_sample->Flush();
77 cout << "OH_VideoEncoder_Flush end" << endl;
78 enc_sample->isRunning_.store(false);
79 enc_sample->signal_->inCond_.notify_all();
80 enc_sample->signal_->outCond_.notify_all();
81 return;
82 }
83 if (enc_sample->inputCallbackStop) {
84 OH_VideoEncoder_Stop(codec);
85 cout << "OH_VideoEncoder_Stop end" << endl;
86 enc_sample->isRunning_.store(false);
87 enc_sample->signal_->inCond_.notify_all();
88 enc_sample->signal_->outCond_.notify_all();
89 return;
90 }
91 VEncSignal *signal = static_cast<VEncSignal *>(userData);
92 unique_lock<mutex> lock(signal->inMutex_);
93 signal->inIdxQueue_.push(index);
94 signal->inBufferQueue_.push(data);
95 signal->inCond_.notify_all();
96 }
97
VencOutputDataReady(OH_AVCodec * codec,uint32_t index,OH_AVMemory * data,OH_AVCodecBufferAttr * attr,void * userData)98 static void VencOutputDataReady(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, OH_AVCodecBufferAttr *attr,
99 void *userData)
100 {
101 if (enc_sample->isFlushing_) {
102 return;
103 }
104 if (enc_sample->outputCallbackFlush) {
105 enc_sample->Flush();
106 cout << "OH_VideoEncoder_Flush end" << endl;
107 enc_sample->isRunning_.store(false);
108 enc_sample->signal_->inCond_.notify_all();
109 enc_sample->signal_->outCond_.notify_all();
110 return;
111 }
112 if (enc_sample->outputCallbackStop) {
113 OH_VideoEncoder_Stop(codec);
114 cout << "OH_VideoEncoder_Stop end" << endl;
115 enc_sample->isRunning_.store(false);
116 enc_sample->signal_->inCond_.notify_all();
117 enc_sample->signal_->outCond_.notify_all();
118 return;
119 }
120 VEncSignal *signal = static_cast<VEncSignal *>(userData);
121 unique_lock<mutex> lock(signal->outMutex_);
122 signal->outIdxQueue_.push(index);
123 signal->attrQueue_.push(*attr);
124 signal->outBufferQueue_.push(data);
125 signal->outCond_.notify_all();
126 }
GetSystemTimeUs()127 int64_t VEncNdkSample::GetSystemTimeUs()
128 {
129 struct timespec now;
130 (void)clock_gettime(CLOCK_BOOTTIME, &now);
131 int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
132
133 return nanoTime / NANOS_IN_MICRO;
134 }
135
ConfigureVideoEncoder()136 int32_t VEncNdkSample::ConfigureVideoEncoder()
137 {
138 OH_AVFormat *format = OH_AVFormat_Create();
139 if (format == nullptr) {
140 cout << "Fatal: Failed to create format" << endl;
141 return AV_ERR_UNKNOWN;
142 }
143 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
144 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
145 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
146 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
147 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
148 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, DEFAULT_KEY_FRAME_INTERVAL);
149 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, 1);
150 if (DEFAULT_BITRATE_MODE == CQ) {
151 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, DEFAULT_QUALITY);
152 }
153 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, DEFAULT_BITRATE_MODE);
154 int ret = OH_VideoEncoder_Configure(venc_, format);
155 OH_AVFormat_Destroy(format);
156 return ret;
157 }
158
ConfigureVideoEncoder_Temporal(int32_t temporal_gop_size)159 int32_t VEncNdkSample::ConfigureVideoEncoder_Temporal(int32_t temporal_gop_size)
160 {
161 OH_AVFormat *format = OH_AVFormat_Create();
162 if (format == nullptr) {
163 cout << "Fatal: Failed to create format" << endl;
164 return AV_ERR_UNKNOWN;
165 }
166 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, DEFAULT_WIDTH);
167 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, DEFAULT_HEIGHT);
168 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, DEFAULT_PIX_FMT);
169 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
170 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, DEFAULT_BITRATE);
171
172 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, DEFAULT_KEY_FRAME_INTERVAL);
173
174 if (TEMPORAL_CONFIG) {
175 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_SIZE, temporal_gop_size);
176 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE,
177 ADJACENT_REFERENCE);
178 }
179 if (TEMPORAL_ENABLE) {
180 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_ENABLE_TEMPORAL_SCALABILITY, 1);
181 }
182 if (TEMPORAL_JUMP_MODE) {
183 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODER_TEMPORAL_GOP_REFERENCE_MODE, JUMP_REFERENCE);
184 }
185 int ret = OH_VideoEncoder_Configure(venc_, format);
186 OH_AVFormat_Destroy(format);
187 return ret;
188 }
189
ConfigureVideoEncoder_fuzz(int32_t data)190 int32_t VEncNdkSample::ConfigureVideoEncoder_fuzz(int32_t data)
191 {
192 OH_AVFormat *format = OH_AVFormat_Create();
193 if (format == nullptr) {
194 cout << "Fatal: Failed to create format" << endl;
195 return AV_ERR_UNKNOWN;
196 }
197 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_WIDTH, data);
198 DEFAULT_WIDTH = data;
199 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_HEIGHT, data);
200 DEFAULT_HEIGHT = data;
201 (void)OH_AVFormat_SetIntValue(format, OH_MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
202 double frameRate = data;
203 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, frameRate);
204
205 OH_AVFormat_SetIntValue(format, OH_MD_KEY_RANGE_FLAG, data);
206 OH_AVFormat_SetIntValue(format, OH_MD_KEY_COLOR_PRIMARIES, data);
207 OH_AVFormat_SetIntValue(format, OH_MD_KEY_TRANSFER_CHARACTERISTICS, data);
208 OH_AVFormat_SetIntValue(format, OH_MD_KEY_MATRIX_COEFFICIENTS, data);
209 OH_AVFormat_SetIntValue(format, OH_MD_KEY_I_FRAME_INTERVAL, data);
210 OH_AVFormat_SetIntValue(format, OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
211 OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, data);
212 OH_AVFormat_SetIntValue(format, OH_MD_KEY_QUALITY, data);
213
214 int ret = OH_VideoEncoder_Configure(venc_, format);
215 OH_AVFormat_Destroy(format);
216 return ret;
217 }
218
SetVideoEncoderCallback()219 int32_t VEncNdkSample::SetVideoEncoderCallback()
220 {
221 signal_ = new VEncSignal();
222 if (signal_ == nullptr) {
223 cout << "Failed to new VEncSignal" << endl;
224 return AV_ERR_UNKNOWN;
225 }
226
227 cb_.onError = VencError;
228 cb_.onStreamChanged = VencFormatChanged;
229 cb_.onNeedInputData = VencInputDataReady;
230 cb_.onNeedOutputData = VencOutputDataReady;
231 return OH_VideoEncoder_SetCallback(venc_, cb_, static_cast<void *>(signal_));
232 }
233
state_EOS()234 int32_t VEncNdkSample::state_EOS()
235 {
236 unique_lock<mutex> lock(signal_->inMutex_);
237 signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
238 uint32_t index = signal_->inIdxQueue_.front();
239 signal_->inIdxQueue_.pop();
240 signal_->inBufferQueue_.pop();
241 lock.unlock();
242 OH_AVCodecBufferAttr attr;
243 attr.pts = 0;
244 attr.size = 0;
245 attr.offset = 0;
246 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
247 return OH_VideoEncoder_PushInputData(venc_, index, attr);
248 }
ReleaseInFile()249 void VEncNdkSample::ReleaseInFile()
250 {
251 if (inFile_ != nullptr) {
252 if (inFile_->is_open()) {
253 inFile_->close();
254 }
255 inFile_.reset();
256 inFile_ = nullptr;
257 }
258 }
259
StopInloop()260 void VEncNdkSample::StopInloop()
261 {
262 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
263 unique_lock<mutex> lock(signal_->inMutex_);
264 clearIntqueue(signal_->inIdxQueue_);
265 isRunning_.store(false);
266 signal_->inCond_.notify_all();
267 lock.unlock();
268
269 inputLoop_->join();
270 inputLoop_ = nullptr;
271 }
272 }
273
testApi()274 void VEncNdkSample::testApi()
275 {
276 OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
277 OH_VideoEncoder_Prepare(venc_);
278 OH_VideoEncoder_GetInputDescription(venc_);
279 OH_VideoEncoder_Start(venc_);
280 OH_AVFormat *format = OH_AVFormat_Create();
281 OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
282 OH_VideoEncoder_SetParameter(venc_, format);
283 OH_VideoEncoder_NotifyEndOfStream(venc_);
284 OH_VideoEncoder_GetOutputDescription(venc_);
285 OH_AVFormat_Destroy(format);
286 OH_VideoEncoder_Flush(venc_);
287 bool isValid = false;
288 OH_VideoEncoder_IsValid(venc_, &isValid);
289 OH_VideoEncoder_Stop(venc_);
290 OH_VideoEncoder_Reset(venc_);
291 }
292
CreateSurface()293 int32_t VEncNdkSample::CreateSurface()
294 {
295 int32_t ret = 0;
296 ret = OH_VideoEncoder_GetSurface(venc_, &nativeWindow);
297 if (ret != AV_ERR_OK) {
298 cout << "OH_VideoEncoder_GetSurface fail" << endl;
299 return ret;
300 }
301 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
302 if (ret != AV_ERR_OK) {
303 cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
304 return ret;
305 }
306 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
307 if (ret != AV_ERR_OK) {
308 cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
309 return ret;
310 }
311 return AV_ERR_OK;
312 }
313
GetStride()314 void VEncNdkSample::GetStride()
315 {
316 OH_AVFormat *format = OH_VideoEncoder_GetInputDescription(venc_);
317 int32_t inputStride = 0;
318 OH_AVFormat_GetIntValue(format, "stride", &inputStride);
319 stride_ = inputStride;
320 OH_AVFormat_Destroy(format);
321 }
322
OpenFile()323 int32_t VEncNdkSample::OpenFile()
324 {
325 if (fuzzMode) {
326 return AV_ERR_OK;
327 }
328 int32_t ret = AV_ERR_OK;
329 inFile_ = make_unique<ifstream>();
330 if (inFile_ == nullptr) {
331 isRunning_.store(false);
332 (void)OH_VideoEncoder_Stop(venc_);
333 return AV_ERR_UNKNOWN;
334 }
335 inFile_->open(INP_DIR, ios::in | ios::binary);
336 if (!inFile_->is_open()) {
337 cout << "file open fail" << endl;
338 isRunning_.store(false);
339 (void)OH_VideoEncoder_Stop(venc_);
340 inFile_->close();
341 inFile_.reset();
342 inFile_ = nullptr;
343 return AV_ERR_UNKNOWN;
344 }
345 return ret;
346 }
347
StartVideoEncoder()348 int32_t VEncNdkSample::StartVideoEncoder()
349 {
350 isRunning_.store(true);
351 int32_t ret = 0;
352 if (SURF_INPUT) {
353 ret = CreateSurface();
354 if (ret != AV_ERR_OK) {
355 return ret;
356 }
357 }
358 ret = OH_VideoEncoder_Start(venc_);
359 GetStride();
360 if (ret != AV_ERR_OK) {
361 cout << "Failed to start codec" << endl;
362 isRunning_.store(false);
363 signal_->inCond_.notify_all();
364 signal_->outCond_.notify_all();
365 return ret;
366 }
367 if (OpenFile() != AV_ERR_OK) {
368 return AV_ERR_UNKNOWN;
369 }
370 if (SURF_INPUT) {
371 inputLoop_ = make_unique<thread>(&VEncNdkSample::InputFuncSurface, this);
372 } else {
373 inputLoop_ = make_unique<thread>(&VEncNdkSample::InputFunc, this);
374 }
375 if (inputLoop_ == nullptr) {
376 isRunning_.store(false);
377 (void)OH_VideoEncoder_Stop(venc_);
378 ReleaseInFile();
379 return AV_ERR_UNKNOWN;
380 }
381 outputLoop_ = make_unique<thread>(&VEncNdkSample::OutputFunc, this);
382 if (outputLoop_ == nullptr) {
383 isRunning_.store(false);
384 (void)OH_VideoEncoder_Stop(venc_);
385 ReleaseInFile();
386 StopInloop();
387 Release();
388 return AV_ERR_UNKNOWN;
389 }
390 return AV_ERR_OK;
391 }
392
CreateVideoEncoder(const char * codecName)393 int32_t VEncNdkSample::CreateVideoEncoder(const char *codecName)
394 {
395 venc_ = OH_VideoEncoder_CreateByName(codecName);
396 enc_sample = this;
397 randomEos = rand() % TEST_FRAME_COUNT;
398 return venc_ == nullptr ? AV_ERR_UNKNOWN : AV_ERR_OK;
399 }
400
WaitForEOS()401 void VEncNdkSample::WaitForEOS()
402 {
403 if (inputLoop_)
404 inputLoop_->join();
405 if (outputLoop_)
406 outputLoop_->join();
407 inputLoop_ = nullptr;
408 outputLoop_ = nullptr;
409 }
410
ReturnZeroIfEOS(uint32_t expectedSize)411 uint32_t VEncNdkSample::ReturnZeroIfEOS(uint32_t expectedSize)
412 {
413 if (inFile_->gcount() != (expectedSize)) {
414 cout << "no more data" << endl;
415 return 0;
416 }
417 return 1;
418 }
419
ReadOneFrameYUV420SP(uint8_t * dst)420 uint32_t VEncNdkSample::ReadOneFrameYUV420SP(uint8_t *dst)
421 {
422 uint8_t *start = dst;
423 // copy Y
424 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
425 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
426 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
427 return 0;
428 dst += stride_;
429 }
430 // copy UV
431 for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
432 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
433 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
434 return 0;
435 dst += stride_;
436 }
437 return dst - start;
438 }
439
ReadOneFrameRGBA8888(uint8_t * dst)440 void VEncNdkSample::ReadOneFrameRGBA8888(uint8_t *dst)
441 {
442 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
443 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH * RGBA_SIZE);
444 dst += stride_;
445 }
446 }
447
FlushSurf(OHNativeWindowBuffer * ohNativeWindowBuffer,OH_NativeBuffer * nativeBuffer)448 uint32_t VEncNdkSample::FlushSurf(OHNativeWindowBuffer *ohNativeWindowBuffer, OH_NativeBuffer *nativeBuffer)
449 {
450 struct Region region;
451 struct Region::Rect *rect = new Region::Rect();
452 rect->x = 0;
453 rect->y = 0;
454 rect->w = DEFAULT_WIDTH;
455 rect->h = DEFAULT_HEIGHT;
456 region.rects = rect;
457 NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
458 int32_t err = OH_NativeBuffer_Unmap(nativeBuffer);
459 if (err != 0) {
460 cout << "OH_NativeBuffer_Unmap failed" << endl;
461 return 1;
462 }
463 err = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
464 delete rect;
465 if (err != 0) {
466 cout << "FlushBuffer failed" << endl;
467 return 1;
468 }
469 return 0;
470 }
471
InputFuncSurface()472 void VEncNdkSample::InputFuncSurface()
473 {
474 while (true) {
475 if (outputCallbackFlush || outputCallbackStop) {
476 OH_VideoEncoder_NotifyEndOfStream(venc_);
477 break;
478 }
479 OHNativeWindowBuffer *ohNativeWindowBuffer;
480 int fenceFd = -1;
481 if (nativeWindow == nullptr) {
482 cout << "nativeWindow == nullptr" << endl;
483 break;
484 }
485
486 int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
487 if (err != 0) {
488 cout << "RequestBuffer failed, GSError=" << err << endl;
489 break;
490 }
491 if (fenceFd > 0) {
492 close(fenceFd);
493 }
494 OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
495 void *virAddr = nullptr;
496 err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
497 if (err != 0) {
498 cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
499 isRunning_.store(false);
500 break;
501 }
502 uint8_t *dst = (uint8_t *)virAddr;
503 const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
504 int stride = sbuffer->GetStride();
505 if (dst == nullptr || stride < DEFAULT_WIDTH) {
506 cout << "invalid va or stride=" << stride << endl;
507 err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
508 isRunning_.store(false);
509 break;
510 }
511 stride_ = stride;
512 if (!ReadOneFrameYUV420SP(dst)) {
513 err = OH_VideoEncoder_NotifyEndOfStream(venc_);
514 if (err != 0) {
515 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
516 }
517 break;
518 }
519 if (FlushSurf(ohNativeWindowBuffer, nativeBuffer))
520 break;
521 usleep(FRAME_INTERVAL);
522 }
523 }
524
Flush_buffer()525 void VEncNdkSample::Flush_buffer()
526 {
527 unique_lock<mutex> inLock(signal_->inMutex_);
528 clearIntqueue(signal_->inIdxQueue_);
529 std::queue<OH_AVMemory *> empty;
530 swap(empty, signal_->inBufferQueue_);
531 signal_->inCond_.notify_all();
532 inLock.unlock();
533 unique_lock<mutex> outLock(signal_->outMutex_);
534 clearIntqueue(signal_->outIdxQueue_);
535 clearBufferqueue(signal_->attrQueue_);
536 signal_->outCond_.notify_all();
537 outLock.unlock();
538 }
539
RepeatStartBeforeEOS()540 void VEncNdkSample::RepeatStartBeforeEOS()
541 {
542 if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
543 REPEAT_START_FLUSH_BEFORE_EOS--;
544 OH_VideoEncoder_Flush(venc_);
545 Flush_buffer();
546 OH_VideoEncoder_Start(venc_);
547 }
548
549 if (REPEAT_START_STOP_BEFORE_EOS > 0) {
550 REPEAT_START_STOP_BEFORE_EOS--;
551 OH_VideoEncoder_Stop(venc_);
552 Flush_buffer();
553 OH_VideoEncoder_Start(venc_);
554 }
555 }
556
RandomEOS(uint32_t index)557 bool VEncNdkSample::RandomEOS(uint32_t index)
558 {
559 if (enable_random_eos && randomEos == frameCount) {
560 OH_AVCodecBufferAttr attr;
561 attr.pts = 0;
562 attr.size = 0;
563 attr.offset = 0;
564 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
565 OH_VideoEncoder_PushInputData(venc_, index, attr);
566 cout << "random eos" << endl;
567 frameCount++;
568 unique_lock<mutex> lock(signal_->inMutex_);
569 signal_->inIdxQueue_.pop();
570 signal_->inBufferQueue_.pop();
571 return true;
572 }
573 return false;
574 }
575
AutoSwitchParam()576 void VEncNdkSample::AutoSwitchParam()
577 {
578 int64_t currentBitrate = DEFAULT_BITRATE;
579 double currentFrameRate = DEFAULT_FRAME_RATE;
580 if (frameCount == switchParamsTimeSec * (int32_t)DEFAULT_FRAME_RATE) {
581 OH_AVFormat *format = OH_AVFormat_Create();
582 if (needResetBitrate) {
583 currentBitrate = DEFAULT_BITRATE >> 1;
584 cout<<"switch bitrate "<< currentBitrate;
585 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, currentBitrate);
586 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
587 }
588 if (needResetFrameRate) {
589 currentFrameRate = DEFAULT_FRAME_RATE * DOUBLE;
590 cout<< "switch framerate" << currentFrameRate << endl;
591 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, currentFrameRate);
592 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
593 }
594 OH_AVFormat_Destroy(format);
595 }
596 if (frameCount == switchParamsTimeSec * (int32_t)DEFAULT_FRAME_RATE * DOUBLE) {
597 OH_AVFormat *format = OH_AVFormat_Create();
598 if (needResetBitrate) {
599 currentBitrate = DEFAULT_BITRATE << 1;
600 cout<<"switch bitrate "<< currentBitrate;
601 (void)OH_AVFormat_SetLongValue(format, OH_MD_KEY_BITRATE, currentBitrate);
602 }
603 if (needResetFrameRate) {
604 currentFrameRate = DEFAULT_FRAME_RATE / DOUBLE;
605 cout<< "switch framerate" << currentFrameRate << endl;
606 (void)OH_AVFormat_SetDoubleValue(format, OH_MD_KEY_FRAME_RATE, currentFrameRate);
607 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
608 }
609 SetParameter(format) == AV_ERR_OK ? (0) : (errCount++);
610 OH_AVFormat_Destroy(format);
611 }
612 }
613
SetEOS(uint32_t index)614 void VEncNdkSample::SetEOS(uint32_t index)
615 {
616 OH_AVCodecBufferAttr attr;
617 attr.pts = 0;
618 attr.size = 0;
619 attr.offset = 0;
620 attr.flags = AVCODEC_BUFFER_FLAGS_EOS;
621 int32_t res = OH_VideoEncoder_PushInputData(venc_, index, attr);
622 cout << "OH_VideoEncoder_PushInputData EOS res: " << res << endl;
623 unique_lock<mutex> lock(signal_->inMutex_);
624 signal_->inIdxQueue_.pop();
625 signal_->inBufferQueue_.pop();
626 }
627
SetForceIDR()628 void VEncNdkSample::SetForceIDR()
629 {
630 OH_AVFormat *format = OH_AVFormat_Create();
631 OH_AVFormat_SetIntValue(format, OH_MD_KEY_REQUEST_I_FRAME, 1);
632 OH_VideoEncoder_SetParameter(venc_, format);
633 OH_AVFormat_Destroy(format);
634 }
635
PushData(OH_AVMemory * buffer,uint32_t index,int32_t & result)636 int32_t VEncNdkSample::PushData(OH_AVMemory *buffer, uint32_t index, int32_t &result)
637 {
638 int32_t res = -2;
639 OH_AVCodecBufferAttr attr;
640 uint8_t *fileBuffer = OH_AVMemory_GetAddr(buffer);
641 if (fileBuffer == nullptr) {
642 cout << "Fatal: no memory" << endl;
643 return -1;
644 }
645 int32_t size = OH_AVMemory_GetSize(buffer);
646 if (DEFAULT_PIX_FMT == AV_PIXEL_FORMAT_RGBA) {
647 if (size < DEFAULT_HEIGHT * stride_) {
648 return -1;
649 }
650 ReadOneFrameRGBA8888(fileBuffer);
651 attr.size = stride_ * DEFAULT_HEIGHT;
652 } else {
653 if (size < (DEFAULT_HEIGHT * stride_ + (DEFAULT_HEIGHT * stride_ / DOUBLE))) {
654 return -1;
655 }
656 attr.size = ReadOneFrameYUV420SP(fileBuffer);
657 }
658 if (repeatRun && inFile_->eof()) {
659 inFile_->clear();
660 inFile_->seekg(0, ios::beg);
661 encode_count++;
662 cout << "repeat"<< " encode_count:" << encode_count << endl;
663 return -1;
664 }
665 if (inFile_->eof()) {
666 SetEOS(index);
667 return 0;
668 }
669 attr.pts = GetSystemTimeUs();
670 attr.offset = 0;
671 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
672 if (enableForceIDR && (frameCount % IDR_FRAME_INTERVAL == 0)) {
673 SetForceIDR();
674 }
675 result = OH_VideoEncoder_PushInputData(venc_, index, attr);
676 unique_lock<mutex> lock(signal_->inMutex_);
677 signal_->inIdxQueue_.pop();
678 signal_->inBufferQueue_.pop();
679 return res;
680 }
681
CheckResult(bool isRandomEosSuccess,int32_t pushResult)682 int32_t VEncNdkSample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
683 {
684 if (isRandomEosSuccess) {
685 if (pushResult == 0) {
686 errCount = errCount + 1;
687 cout << "push input after eos should be failed! pushResult:" << pushResult << endl;
688 }
689 return -1;
690 } else if (pushResult != 0) {
691 errCount = errCount + 1;
692 cout << "push input data failed, error:" << pushResult << endl;
693 return -1;
694 }
695 return 0;
696 }
697
InputDataNormal(bool & runningFlag,uint32_t index,OH_AVMemory * buffer)698 void VEncNdkSample::InputDataNormal(bool &runningFlag, uint32_t index, OH_AVMemory *buffer)
699 {
700 if (!inFile_->eof()) {
701 bool isRandomEosSuccess = RandomEOS(index);
702 if (isRandomEosSuccess) {
703 runningFlag = false;
704 return;
705 }
706 int32_t pushResult = 0;
707 int32_t ret = PushData(buffer, index, pushResult);
708 if (ret == 0) {
709 runningFlag = false;
710 return;
711 } else if (ret == -1) {
712 return;
713 }
714 if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
715 runningFlag = false;
716 isRunning_.store(false);
717 signal_->inCond_.notify_all();
718 signal_->outCond_.notify_all();
719 return;
720 }
721 frameCount++;
722 if (enableAutoSwitchParam) {
723 AutoSwitchParam();
724 }
725 }
726 }
727
InputDataFuzz(bool & runningFlag,uint32_t index)728 void VEncNdkSample::InputDataFuzz(bool &runningFlag, uint32_t index)
729 {
730 frameCount++;
731 if (frameCount == DEFAULT_FUZZ_TIME) {
732 SetEOS(index);
733 runningFlag = false;
734 return;
735 }
736 OH_AVCodecBufferAttr attr;
737 attr.pts = GetSystemTimeUs();
738 attr.offset = 0;
739 attr.flags = AVCODEC_BUFFER_FLAGS_NONE;
740 OH_VideoEncoder_PushInputData(venc_, index, attr);
741 unique_lock<mutex> lock(signal_->inMutex_);
742 signal_->inIdxQueue_.pop();
743 signal_->inBufferQueue_.pop();
744 }
745
InputFunc()746 void VEncNdkSample::InputFunc()
747 {
748 errCount = 0;
749 bool runningFlag = true;
750 while (runningFlag) {
751 if (!isRunning_.load()) {
752 break;
753 }
754 RepeatStartBeforeEOS();
755 unique_lock<mutex> lock(signal_->inMutex_);
756 signal_->inCond_.wait(lock, [this]() {
757 if (!isRunning_.load()) {
758 return true;
759 }
760 return signal_->inIdxQueue_.size() > 0 && !isFlushing_.load();
761 });
762 if (!isRunning_.load()) {
763 break;
764 }
765 uint32_t index = signal_->inIdxQueue_.front();
766 auto buffer = signal_->inBufferQueue_.front();
767 lock.unlock();
768 unique_lock<mutex> flushlock(signal_->flushMutex_);
769 if (isFlushing_) {
770 continue;
771 }
772 if (fuzzMode == false) {
773 InputDataNormal(runningFlag, index, buffer);
774 } else {
775 InputDataFuzz(runningFlag, index);
776 }
777 flushlock.unlock();
778 if (sleepOnFPS) {
779 usleep(FRAME_INTERVAL);
780 }
781 }
782 }
783
CheckAttrFlag(OH_AVCodecBufferAttr attr)784 int32_t VEncNdkSample::CheckAttrFlag(OH_AVCodecBufferAttr attr)
785 {
786 if (attr.flags & AVCODEC_BUFFER_FLAGS_EOS) {
787 cout << "attr.flags == AVCODEC_BUFFER_FLAGS_EOS" << endl;
788 unique_lock<mutex> inLock(signal_->inMutex_);
789 isRunning_.store(false);
790 signal_->inCond_.notify_all();
791 signal_->outCond_.notify_all();
792 inLock.unlock();
793 return -1;
794 }
795 if (attr.flags == AVCODEC_BUFFER_FLAGS_CODEC_DATA) {
796 cout << "enc AVCODEC_BUFFER_FLAGS_CODEC_DATA" << attr.pts << endl;
797 }
798 outCount = outCount + 1;
799 return 0;
800 }
801
OutputFuncFail()802 void VEncNdkSample::OutputFuncFail()
803 {
804 cout << "errCount > 0" << endl;
805 unique_lock<mutex> inLock(signal_->inMutex_);
806 isRunning_.store(false);
807 signal_->inCond_.notify_all();
808 signal_->outCond_.notify_all();
809 inLock.unlock();
810 (void)Stop();
811 Release();
812 }
813
OutputFunc()814 void VEncNdkSample::OutputFunc()
815 {
816 FILE *outFile = fopen(OUT_DIR, "wb");
817
818 while (true) {
819 if (!isRunning_.load()) {
820 break;
821 }
822 OH_AVCodecBufferAttr attr;
823 uint32_t index;
824 unique_lock<mutex> lock(signal_->outMutex_);
825 signal_->outCond_.wait(lock, [this]() {
826 if (!isRunning_.load()) {
827 return true;
828 }
829 return signal_->outIdxQueue_.size() > 0 && !isFlushing_.load();
830 });
831 if (!isRunning_.load()) {
832 break;
833 }
834 index = signal_->outIdxQueue_.front();
835 attr = signal_->attrQueue_.front();
836 OH_AVMemory *buffer = signal_->outBufferQueue_.front();
837 signal_->outBufferQueue_.pop();
838 signal_->outIdxQueue_.pop();
839 signal_->attrQueue_.pop();
840 lock.unlock();
841 if (CheckAttrFlag(attr) == -1) {
842 break;
843 }
844 int size = attr.size;
845 if (outFile == nullptr) {
846 cout << "dump data fail" << endl;
847 } else {
848 fwrite(OH_AVMemory_GetAddr(buffer), 1, size, outFile);
849 }
850
851 if (OH_VideoEncoder_FreeOutputData(venc_, index) != AV_ERR_OK) {
852 cout << "Fatal: ReleaseOutputBuffer fail" << endl;
853 errCount = errCount + 1;
854 }
855 if (errCount > 0) {
856 OutputFuncFail();
857 break;
858 }
859 }
860 if (outFile) {
861 (void)fclose(outFile);
862 }
863 }
864
Flush()865 int32_t VEncNdkSample::Flush()
866 {
867 isFlushing_.store(true);
868 unique_lock<mutex> flushLock(signal_->flushMutex_);
869 unique_lock<mutex> inLock(signal_->inMutex_);
870 clearIntqueue(signal_->inIdxQueue_);
871 signal_->inCond_.notify_all();
872 inLock.unlock();
873 unique_lock<mutex> outLock(signal_->outMutex_);
874 clearIntqueue(signal_->outIdxQueue_);
875 clearBufferqueue(signal_->attrQueue_);
876 signal_->outCond_.notify_all();
877 outLock.unlock();
878 int32_t ret = OH_VideoEncoder_Flush(venc_);
879 isFlushing_.store(false);
880 flushLock.unlock();
881 return ret;
882 }
883
Reset()884 int32_t VEncNdkSample::Reset()
885 {
886 isRunning_.store(false);
887 StopInloop();
888 StopOutloop();
889 ReleaseInFile();
890 return OH_VideoEncoder_Reset(venc_);
891 }
892
Release()893 int32_t VEncNdkSample::Release()
894 {
895 int ret = OH_VideoEncoder_Destroy(venc_);
896 venc_ = nullptr;
897 if (signal_ != nullptr) {
898 delete signal_;
899 signal_ = nullptr;
900 }
901 return ret;
902 }
903
Stop()904 int32_t VEncNdkSample::Stop()
905 {
906 StopInloop();
907 clearIntqueue(signal_->outIdxQueue_);
908 clearBufferqueue(signal_->attrQueue_);
909 ReleaseInFile();
910 return OH_VideoEncoder_Stop(venc_);
911 }
912
Start()913 int32_t VEncNdkSample::Start()
914 {
915 return OH_VideoEncoder_Start(venc_);
916 }
917
StopOutloop()918 void VEncNdkSample::StopOutloop()
919 {
920 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
921 unique_lock<mutex> lock(signal_->outMutex_);
922 clearIntqueue(signal_->outIdxQueue_);
923 clearBufferqueue(signal_->attrQueue_);
924 signal_->outCond_.notify_all();
925 lock.unlock();
926 }
927 }
928
SetParameter(OH_AVFormat * format)929 int32_t VEncNdkSample::SetParameter(OH_AVFormat *format)
930 {
931 if (venc_) {
932 return OH_VideoEncoder_SetParameter(venc_, format);
933 }
934 return AV_ERR_UNKNOWN;
935 }