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