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