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