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