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