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 "openssl/crypto.h"
19 #include "openssl/sha.h"
20 #include "native_buffer_inner.h"
21 #include "display_type.h"
22 #include "iconsumer_surface.h"
23 #include "videoenc_ndk_inner_sample.h"
24
25 using namespace OHOS;
26 using namespace OHOS::MediaAVCodec;
27 using namespace std;
28
29 namespace {
30 const string MIME_TYPE = "video/avc";
31 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
32 constexpr int64_t NANOS_IN_MICRO = 1000L;
33 constexpr uint32_t FRAME_INTERVAL = 16666;
34 constexpr uint32_t MAX_PIXEL_FMT = 5;
35 constexpr uint32_t IDR_FRAME_INTERVAL = 10;
36
clearIntqueue(std::queue<uint32_t> & q)37 void clearIntqueue(std::queue<uint32_t> &q)
38 {
39 std::queue<uint32_t> empty;
40 swap(empty, q);
41 }
42
clearBufferqueue(std::queue<AVCodecBufferInfo> & q)43 void clearBufferqueue(std::queue<AVCodecBufferInfo> &q)
44 {
45 std::queue<AVCodecBufferInfo> empty;
46 swap(empty, q);
47 }
48
clearFlagqueue(std::queue<AVCodecBufferFlag> & q)49 void clearFlagqueue(std::queue<AVCodecBufferFlag> &q)
50 {
51 std::queue<AVCodecBufferFlag> empty;
52 swap(empty, q);
53 }
54 } // namespace
55
VEncInnerCallback(std::shared_ptr<VEncInnerSignal> signal)56 VEncInnerCallback::VEncInnerCallback(std::shared_ptr<VEncInnerSignal> signal) : innersignal_(signal) {}
57
OnError(AVCodecErrorType errorType,int32_t errorCode)58 void VEncInnerCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
59 {
60 cout << "Error errorType:" << errorType << " errorCode:" << errorCode << endl;
61 }
62
OnOutputFormatChanged(const Format & format)63 void VEncInnerCallback::OnOutputFormatChanged(const Format& format)
64 {
65 cout << "Format Changed" << endl;
66 }
67
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)68 void VEncInnerCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
69 {
70 cout << "OnInputBufferAvailable index:" << index << endl;
71 if (innersignal_ == nullptr) {
72 std::cout << "buffer is null 1" << endl;
73 return;
74 }
75
76 unique_lock<mutex> lock(innersignal_->inMutex_);
77 innersignal_->inIdxQueue_.push(index);
78 innersignal_->inBufferQueue_.push(buffer);
79 innersignal_->inCond_.notify_all();
80 }
81
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)82 void VEncInnerCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info,
83 AVCodecBufferFlag flag, std::shared_ptr<AVSharedMemory> buffer)
84 {
85 cout << "OnOutputBufferAvailable index:" << index << endl;
86 unique_lock<mutex> lock(innersignal_->outMutex_);
87 innersignal_->outIdxQueue_.push(index);
88 innersignal_->infoQueue_.push(info);
89 innersignal_->flagQueue_.push(flag);
90 innersignal_->outBufferQueue_.push(buffer);
91 cout << "**********out info size = " << info.size << endl;
92 innersignal_->outCond_.notify_all();
93 }
94
~VEncNdkInnerSample()95 VEncNdkInnerSample::~VEncNdkInnerSample()
96 {
97 Release();
98 }
99
GetSystemTimeUs()100 int64_t VEncNdkInnerSample::GetSystemTimeUs()
101 {
102 struct timespec now;
103 (void)clock_gettime(CLOCK_BOOTTIME, &now);
104 int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
105
106 return nanoTime / NANOS_IN_MICRO;
107 }
108
CreateByMime(const std::string & mime)109 int32_t VEncNdkInnerSample::CreateByMime(const std::string &mime)
110 {
111 venc_ = VideoEncoderFactory::CreateByMime(mime);
112 return venc_ == nullptr ? AVCS_ERR_INVALID_OPERATION : AVCS_ERR_OK;
113 }
114
CreateByName(const std::string & name)115 int32_t VEncNdkInnerSample::CreateByName(const std::string &name)
116 {
117 venc_ = VideoEncoderFactory::CreateByName(name);
118 return venc_ == nullptr ? AVCS_ERR_INVALID_OPERATION : AVCS_ERR_OK;
119 }
120
Configure()121 int32_t VEncNdkInnerSample::Configure()
122 {
123 Format format;
124 format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, DEFAULT_WIDTH);
125 format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, DEFAULT_HEIGHT);
126 format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::NV12));
127 format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
128 format.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, DEFAULT_BITRATE);
129
130 return venc_->Configure(format);
131 }
132
ConfigureFuzz(int32_t data)133 int32_t VEncNdkInnerSample::ConfigureFuzz(int32_t data)
134 {
135 Format format;
136 double frameRate = data;
137 format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, data);
138 format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, data);
139 format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
140 format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate);
141 format.PutIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, data);
142 format.PutIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, data);
143 format.PutIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, data);
144 format.PutIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, data);
145 format.PutIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, data);
146 format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
147 format.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, data);
148 format.PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, data);
149
150 return venc_->Configure(format);
151 }
152
Prepare()153 int32_t VEncNdkInnerSample::Prepare()
154 {
155 return venc_->Prepare();
156 }
157
Start()158 int32_t VEncNdkInnerSample::Start()
159 {
160 return venc_->Start();
161 }
162
Stop()163 int32_t VEncNdkInnerSample::Stop()
164 {
165 StopInloop();
166 clearIntqueue(signal_->outIdxQueue_);
167 clearBufferqueue(signal_->infoQueue_);
168 clearFlagqueue(signal_->flagQueue_);
169 ReleaseInFile();
170
171 return venc_->Stop();
172 }
173
Flush()174 int32_t VEncNdkInnerSample::Flush()
175 {
176 unique_lock<mutex> inLock(signal_->inMutex_);
177 clearIntqueue(signal_->inIdxQueue_);
178 signal_->inCond_.notify_all();
179 inLock.unlock();
180 unique_lock<mutex> outLock(signal_->outMutex_);
181 clearIntqueue(signal_->outIdxQueue_);
182 clearBufferqueue(signal_->infoQueue_);
183 clearFlagqueue(signal_->flagQueue_);
184 signal_->outCond_.notify_all();
185 outLock.unlock();
186
187 return venc_->Flush();
188 }
189
NotifyEos()190 int32_t VEncNdkInnerSample::NotifyEos()
191 {
192 return venc_->NotifyEos();
193 }
194
Reset()195 int32_t VEncNdkInnerSample::Reset()
196 {
197 isRunning_.store(false);
198 StopInloop();
199 StopOutloop();
200 ReleaseInFile();
201
202 if (venc_ == nullptr) {
203 std::cout << "InnerEncoder create failed!" << std::endl;
204 return AVCS_ERR_INVALID_OPERATION;
205 }
206 return venc_->Reset();
207 }
208
Release()209 int32_t VEncNdkInnerSample::Release()
210 {
211 int32_t ret = venc_->Release();
212 venc_ = nullptr;
213 if (signal_ != nullptr) {
214 signal_ = nullptr;
215 }
216 return ret;
217 }
218
CreateInputSurface()219 int32_t VEncNdkInnerSample::CreateInputSurface()
220 {
221 sptr<Surface> surface = venc_->CreateInputSurface();
222 if (surface == nullptr) {
223 cout << "CreateInputSurface fail" << endl;
224 return AVCS_ERR_INVALID_OPERATION;
225 }
226
227 nativeWindow = CreateNativeWindowFromSurface(&surface);
228 if (nativeWindow == nullptr) {
229 cout << "CreateNativeWindowFromSurface failed!" << endl;
230 return AVCS_ERR_INVALID_VAL;
231 }
232
233 int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
234 if (ret != AVCS_ERR_OK) {
235 cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
236 return ret;
237 }
238
239 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
240 if (ret != AVCS_ERR_OK) {
241 cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
242 return ret;
243 }
244
245 return AVCS_ERR_OK;
246 }
247
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)248 int32_t VEncNdkInnerSample::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
249 {
250 return venc_->QueueInputBuffer(index, info, flag);
251 }
252
GetOutputFormat(Format & format)253 int32_t VEncNdkInnerSample::GetOutputFormat(Format &format)
254 {
255 return venc_->GetOutputFormat(format);
256 }
257
ReleaseOutputBuffer(uint32_t index)258 int32_t VEncNdkInnerSample::ReleaseOutputBuffer(uint32_t index)
259 {
260 return venc_->ReleaseOutputBuffer(index);
261 }
262
SetParameter(const Format & format)263 int32_t VEncNdkInnerSample::SetParameter(const Format &format)
264 {
265 return venc_->SetParameter(format);
266 }
267
SetCallback()268 int32_t VEncNdkInnerSample::SetCallback()
269 {
270 signal_ = make_shared<VEncInnerSignal>();
271 if (signal_ == nullptr) {
272 cout << "Failed to new VEncInnerSignal" << endl;
273 return AVCS_ERR_UNKNOWN;
274 }
275
276 cb_ = make_shared<VEncInnerCallback>(signal_);
277 return venc_->SetCallback(cb_);
278 }
279
GetInputFormat(Format & format)280 int32_t VEncNdkInnerSample::GetInputFormat(Format &format)
281 {
282 return venc_->GetInputFormat(format);
283 }
284
StartVideoEncoder()285 int32_t VEncNdkInnerSample::StartVideoEncoder()
286 {
287 isRunning_.store(true);
288 int32_t ret = 0;
289
290 if (surfaceInput) {
291 ret = CreateInputSurface();
292 return ret;
293 }
294
295 ret = venc_->Start();
296 if (ret != AVCS_ERR_OK) {
297 cout << "Failed to start codec" << endl;
298 isRunning_.store(false);
299 signal_->inCond_.notify_all();
300 signal_->outCond_.notify_all();
301 return ret;
302 }
303
304 inFile_ = make_unique<ifstream>();
305 if (inFile_ == nullptr) {
306 isRunning_.store(false);
307 venc_->Stop();
308 return AVCS_ERR_UNKNOWN;
309 }
310
311 inFile_->open(INP_DIR, ios::in | ios::binary);
312 if (!inFile_->is_open()) {
313 OpenFileFail();
314 }
315
316 if (surfaceInput) {
317 inputLoop_ = make_unique<thread>(&VEncNdkInnerSample::InputFuncSurface, this);
318 } else {
319 inputLoop_ = make_unique<thread>(&VEncNdkInnerSample::InputFunc, this);
320 }
321
322 if (inputLoop_ == nullptr) {
323 cout << "Failed to create input loop" << endl;
324 isRunning_.store(false);
325 venc_->Stop();
326 ReleaseInFile();
327 return AVCS_ERR_UNKNOWN;
328 }
329
330 outputLoop_ = make_unique<thread>(&VEncNdkInnerSample::OutputFunc, this);
331 if (outputLoop_ == nullptr) {
332 cout << "Failed to create output loop" << endl;
333 isRunning_.store(false);
334 venc_->Stop();
335 ReleaseInFile();
336 StopInloop();
337 Release();
338 return AVCS_ERR_UNKNOWN;
339 }
340 return AVCS_ERR_OK;
341 }
342
testApi()343 int32_t VEncNdkInnerSample::testApi()
344 {
345 if (venc_ == nullptr) {
346 std::cout << "InnerEncoder create failed!" << std::endl;
347 return AVCS_ERR_INVALID_OPERATION;
348 }
349
350 Format format;
351 format.PutIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, 1);
352 venc_->CreateInputSurface();
353 venc_->Prepare();
354 venc_->GetInputFormat(format);
355 venc_->Start();
356 venc_->SetParameter(format);
357 venc_->NotifyEos();
358 venc_->GetOutputFormat(format);
359 venc_->Flush();
360 venc_->Stop();
361 venc_->Reset();
362
363 return AVCS_ERR_OK;
364 }
365
PushData(std::shared_ptr<AVSharedMemory> buffer,uint32_t index,int32_t & result)366 int32_t VEncNdkInnerSample::PushData(std::shared_ptr<AVSharedMemory> buffer, uint32_t index, int32_t &result)
367 {
368 int32_t res = -2;
369 uint32_t yuvSize = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3 / 2;
370 uint8_t *fileBuffer = buffer->GetBase();
371 if (fileBuffer == nullptr) {
372 cout << "Fatal: no memory" << endl;
373 return -1;
374 }
375 (void)inFile_->read((char *)fileBuffer, yuvSize);
376
377 if (repeatRun && inFile_->eof()) {
378 inFile_->clear();
379 inFile_->seekg(0, ios::beg);
380 encodeCount++;
381 cout << "repeat" << " encodeCount:" << encodeCount << endl;
382 return -1;
383 }
384
385 if (inFile_->eof()) {
386 SetEOS(index);
387 return 0;
388 }
389
390 AVCodecBufferInfo info;
391 info.presentationTimeUs = GetSystemTimeUs();
392 info.size = yuvSize;
393 info.offset = 0;
394 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_NONE;
395
396 int32_t size = buffer->GetSize();
397 if (size < (int32_t)yuvSize) {
398 cout << "bufferSize smaller than yuv size" << endl;
399 return -1;
400 }
401
402 if (enableForceIDR && (frameCount % IDR_FRAME_INTERVAL == 0)) {
403 Format format;
404 format.PutIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, 1);
405 venc_->SetParameter(format);
406 }
407 result = venc_->QueueInputBuffer(index, info, flag);
408 unique_lock<mutex> lock(signal_->inMutex_);
409 signal_->inIdxQueue_.pop();
410 signal_->inBufferQueue_.pop();
411
412 return res;
413 }
414
OpenFileFail()415 int32_t VEncNdkInnerSample::OpenFileFail()
416 {
417 cout << "file open fail" << endl;
418 isRunning_.store(false);
419 venc_->Stop();
420 inFile_->close();
421 inFile_.reset();
422 inFile_ = nullptr;
423 return AVCS_ERR_UNKNOWN;
424 }
425
CheckResult(bool isRandomEosSuccess,int32_t pushResult)426 int32_t VEncNdkInnerSample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
427 {
428 if (isRandomEosSuccess) {
429 if (pushResult == 0) {
430 errCount = errCount + 1;
431 cout << "push input after eos should be failed! pushResult:" << pushResult << endl;
432 }
433 return -1;
434 } else if (pushResult != 0) {
435 errCount = errCount + 1;
436 cout << "push input data failed, error:" << pushResult << endl;
437 return -1;
438 }
439 return 0;
440 }
441
CheckFlag(AVCodecBufferFlag flag)442 int32_t VEncNdkInnerSample::CheckFlag(AVCodecBufferFlag flag)
443 {
444 if (flag == AVCODEC_BUFFER_FLAG_EOS) {
445 cout << "flag == AVCODEC_BUFFER_FLAG_EOS" << endl;
446 unique_lock<mutex> inLock(signal_->inMutex_);
447 isRunning_.store(false);
448 signal_->inCond_.notify_all();
449 signal_->outCond_.notify_all();
450 inLock.unlock();
451 return -1;
452 }
453
454 if (flag == AVCODEC_BUFFER_FLAG_CODEC_DATA) {
455 cout << "enc AVCODEC_BUFFER_FLAG_CODEC_DATA" << endl;
456 }
457 outCount = outCount + 1;
458 return 0;
459 }
460
InputProcess(OH_NativeBuffer * nativeBuffer,OHNativeWindowBuffer * ohNativeWindowBuffer)461 int32_t VEncNdkInnerSample::InputProcess(OH_NativeBuffer *nativeBuffer, OHNativeWindowBuffer *ohNativeWindowBuffer)
462 {
463 int32_t ret = 0;
464 struct Region region;
465 struct Region::Rect *rect = new Region::Rect();
466 rect->x = 0;
467 rect->y = 0;
468 rect->w = DEFAULT_WIDTH;
469 rect->h = DEFAULT_HEIGHT;
470 region.rects = rect;
471 NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
472 ret = OH_NativeBuffer_Unmap(nativeBuffer);
473 if (ret != 0) {
474 cout << "OH_NativeBuffer_Unmap failed" << endl;
475 delete rect;
476 return ret;
477 }
478
479 ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
480 delete rect;
481 if (ret != 0) {
482 cout << "FlushBuffer failed" << endl;
483 return ret;
484 }
485 return ret;
486 }
487
StateEOS()488 int32_t VEncNdkInnerSample::StateEOS()
489 {
490 unique_lock<mutex> lock(signal_->inMutex_);
491 signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
492 uint32_t index = signal_->inIdxQueue_.front();
493 signal_->inIdxQueue_.pop();
494 signal_->inBufferQueue_.pop();
495 lock.unlock();
496
497 AVCodecBufferInfo info;
498 info.presentationTimeUs = 0;
499 info.size = 0;
500 info.offset = 0;
501 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
502
503 return venc_->QueueInputBuffer(index, info, flag);
504 }
505
ReturnZeroIfEOS(uint32_t expectedSize)506 uint32_t VEncNdkInnerSample::ReturnZeroIfEOS(uint32_t expectedSize)
507 {
508 if (inFile_->gcount() != (int32_t)expectedSize) {
509 cout << "no more data" << endl;
510 return 0;
511 }
512 return 1;
513 }
514
ReadOneFrameYUV420SP(uint8_t * dst)515 uint32_t VEncNdkInnerSample::ReadOneFrameYUV420SP(uint8_t *dst)
516 {
517 uint8_t *start = dst;
518 // copy Y
519 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
520 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
521 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
522 return 0;
523 dst += stride_;
524 }
525 // copy UV
526 for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
527 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
528 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
529 return 0;
530 dst += stride_;
531 }
532 return dst - start;
533 }
534
RandomEOS(uint32_t index)535 bool VEncNdkInnerSample::RandomEOS(uint32_t index)
536 {
537 uint32_t random_eos = rand() % 25;
538 if (enableRandomEos && random_eos == frameCount) {
539 AVCodecBufferInfo info;
540 info.presentationTimeUs = 0;
541 info.size = 0;
542 info.offset = 0;
543 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
544
545 venc_->QueueInputBuffer(index, info, flag);
546 cout << "random eos" << endl;
547 frameCount++;
548 unique_lock<mutex> lock(signal_->inMutex_);
549 signal_->inIdxQueue_.pop();
550 signal_->inBufferQueue_.pop();
551 return true;
552 }
553 return false;
554 }
555
RepeatStartBeforeEOS()556 void VEncNdkInnerSample::RepeatStartBeforeEOS()
557 {
558 if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
559 REPEAT_START_FLUSH_BEFORE_EOS--;
560 venc_->Flush();
561 FlushBuffer();
562 venc_->Start();
563 }
564
565 if (REPEAT_START_STOP_BEFORE_EOS > 0) {
566 REPEAT_START_STOP_BEFORE_EOS--;
567 venc_->Stop();
568 FlushBuffer();
569 venc_->Start();
570 }
571 }
572
SetEOS(uint32_t index)573 void VEncNdkInnerSample::SetEOS(uint32_t index)
574 {
575 AVCodecBufferInfo info;
576 info.presentationTimeUs = 0;
577 info.size = 0;
578 info.offset = 0;
579 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
580
581 int32_t res = venc_->QueueInputBuffer(index, info, flag);
582 cout << "QueueInputBuffer EOS res: " << res << endl;
583 unique_lock<mutex> lock(signal_->inMutex_);
584 signal_->inIdxQueue_.pop();
585 signal_->inBufferQueue_.pop();
586 }
587
WaitForEOS()588 void VEncNdkInnerSample::WaitForEOS()
589 {
590 if (inputLoop_)
591 inputLoop_->join();
592 if (outputLoop_)
593 outputLoop_->join();
594 inputLoop_ = nullptr;
595 outputLoop_ = nullptr;
596 }
597
InputFuncSurface()598 void VEncNdkInnerSample::InputFuncSurface()
599 {
600 while (true) {
601 OHNativeWindowBuffer *ohNativeWindowBuffer;
602 int fenceFd = -1;
603 if (nativeWindow == nullptr) {
604 cout << "nativeWindow == nullptr" << endl;
605 break;
606 }
607
608 int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
609 if (err != 0) {
610 cout << "RequestBuffer failed, GSError=" << err << endl;
611 continue;
612 }
613 if (fenceFd > 0) {
614 close(fenceFd);
615 }
616 OH_NativeBuffer *nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
617 void *virAddr = nullptr;
618 err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
619 if (err != 0) {
620 cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
621 isRunning_.store(false);
622 break;
623 }
624 uint8_t *dst = (uint8_t *)virAddr;
625 const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
626 int32_t stride = sbuffer->GetStride();
627 if (dst == nullptr || stride < (int32_t)DEFAULT_WIDTH) {
628 cout << "invalid va or stride=" << stride << endl;
629 err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
630 isRunning_.store(false);
631 break;
632 }
633 stride_ = stride;
634 if (!ReadOneFrameYUV420SP(dst)) {
635 err = venc_->NotifyEos();
636 if (err != 0) {
637 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
638 }
639 break;
640 }
641
642 err = InputProcess(nativeBuffer, ohNativeWindowBuffer);
643 if (err != 0) {
644 break;
645 }
646 usleep(FRAME_INTERVAL);
647 }
648 }
649
InputFunc()650 void VEncNdkInnerSample::InputFunc()
651 {
652 errCount = 0;
653 while (true) {
654 if (!isRunning_.load()) {
655 break;
656 }
657 RepeatStartBeforeEOS();
658 unique_lock<mutex> lock(signal_->inMutex_);
659 signal_->inCond_.wait(lock, [this]() {
660 if (!isRunning_.load()) {
661 return true;
662 }
663 return signal_->inIdxQueue_.size() > 0;
664 });
665 if (!isRunning_.load()) {
666 break;
667 }
668 uint32_t index = signal_->inIdxQueue_.front();
669 auto buffer = signal_->inBufferQueue_.front();
670
671 lock.unlock();
672 if (!inFile_->eof()) {
673 bool isRandomEosSuccess = RandomEOS(index);
674 if (isRandomEosSuccess) {
675 continue;
676 }
677 int32_t pushResult = 0;
678 int32_t ret = PushData(buffer, index, pushResult);
679 if (ret == 0) {
680 break;
681 } else if (ret == -1) {
682 continue;
683 }
684
685 if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
686 break;
687 }
688 frameCount++;
689 }
690 if (sleepOnFPS) {
691 usleep(FRAME_INTERVAL);
692 }
693 }
694 }
695
OutputFunc()696 void VEncNdkInnerSample::OutputFunc()
697 {
698 FILE *outFile = fopen(OUT_DIR, "wb");
699
700 while (true) {
701 if (!isRunning_.load()) {
702 break;
703 }
704
705 unique_lock<mutex> lock(signal_->outMutex_);
706 signal_->outCond_.wait(lock, [this]() {
707 if (!isRunning_.load()) {
708 return true;
709 }
710 return signal_->outIdxQueue_.size() > 0;
711 });
712
713 if (!isRunning_.load()) {
714 break;
715 }
716
717 std::shared_ptr<AVSharedMemory> buffer = signal_->outBufferQueue_.front();
718 AVCodecBufferInfo info = signal_->infoQueue_.front();
719 AVCodecBufferFlag flag = signal_->flagQueue_.front();
720 uint32_t index = signal_->outIdxQueue_.front();
721
722 signal_->outBufferQueue_.pop();
723 signal_->outIdxQueue_.pop();
724 signal_->infoQueue_.pop();
725 signal_->flagQueue_.pop();
726 lock.unlock();
727
728 if (CheckFlag(flag) == -1) {
729 break;
730 }
731
732 int size = info.size;
733 if (outFile == nullptr) {
734 cout << "dump data fail" << endl;
735 } else {
736 fwrite(buffer->GetBase(), 1, size, outFile);
737 }
738
739 if (venc_->ReleaseOutputBuffer(index) != AVCS_ERR_OK) {
740 cout << "Fatal: ReleaseOutputBuffer fail" << endl;
741 errCount = errCount + 1;
742 }
743 if (errCount > 0) {
744 OutputFuncFail();
745 break;
746 }
747 }
748 (void)fclose(outFile);
749 }
750
OutputFuncFail()751 void VEncNdkInnerSample::OutputFuncFail()
752 {
753 cout << "errCount > 0" << endl;
754 unique_lock<mutex> inLock(signal_->inMutex_);
755 isRunning_.store(false);
756 signal_->inCond_.notify_all();
757 signal_->outCond_.notify_all();
758 inLock.unlock();
759 (void)Stop();
760 Release();
761 }
762
FlushBuffer()763 void VEncNdkInnerSample::FlushBuffer()
764 {
765 std::queue<std::shared_ptr<AVSharedMemory>> empty;
766 unique_lock<mutex> inLock(signal_->inMutex_);
767 clearIntqueue(signal_->inIdxQueue_);
768 swap(empty, signal_->inBufferQueue_);
769 signal_->inCond_.notify_all();
770 inLock.unlock();
771
772 unique_lock<mutex> outLock(signal_->outMutex_);
773 clearIntqueue(signal_->outIdxQueue_);
774 clearBufferqueue(signal_->infoQueue_);
775 clearFlagqueue(signal_->flagQueue_);
776 signal_->outCond_.notify_all();
777 outLock.unlock();
778 }
779
StopInloop()780 void VEncNdkInnerSample::StopInloop()
781 {
782 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
783 unique_lock<mutex> lock(signal_->inMutex_);
784 clearIntqueue(signal_->inIdxQueue_);
785 isRunning_.store(false);
786 signal_->inCond_.notify_all();
787 lock.unlock();
788
789 inputLoop_->join();
790 inputLoop_ = nullptr;
791 }
792 }
793
StopOutloop()794 void VEncNdkInnerSample::StopOutloop()
795 {
796 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
797 unique_lock<mutex> lock(signal_->outMutex_);
798 clearIntqueue(signal_->outIdxQueue_);
799 clearBufferqueue(signal_->infoQueue_);
800 clearFlagqueue(signal_->flagQueue_);
801 signal_->outCond_.notify_all();
802 lock.unlock();
803 }
804 }
805
ReleaseInFile()806 void VEncNdkInnerSample::ReleaseInFile()
807 {
808 if (inFile_ != nullptr) {
809 if (inFile_->is_open()) {
810 inFile_->close();
811 }
812 inFile_.reset();
813 inFile_ = nullptr;
814 }
815 }
816