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_inner_sample.h"
24 #include "meta/meta_key.h"
25 #include <random>
26 #include "avcodec_list.h"
27 #include "native_avcodec_base.h"
28
29 using namespace OHOS;
30 using namespace OHOS::MediaAVCodec;
31 using namespace std;
32
33 namespace {
34 const string MIME_TYPE = "video/avc";
35 constexpr int64_t NANOS_IN_SECOND = 1000000000L;
36 constexpr int64_t NANOS_IN_MICRO = 1000L;
37 constexpr uint32_t FRAME_INTERVAL = 16666;
38 constexpr uint32_t MAX_PIXEL_FMT = 5;
39 constexpr uint32_t IDR_FRAME_INTERVAL = 10;
40 std::random_device rd;
41 constexpr uint8_t RGBA_SIZE = 4;
42 constexpr uint8_t FILE_END = -1;
43 constexpr uint8_t LOOP_END = 0;
44 int32_t g_picWidth;
45 int32_t g_picHeight;
46 int32_t g_keyWidth;
47 int32_t g_keyHeight;
48
clearIntqueue(std::queue<uint32_t> & q)49 void clearIntqueue(std::queue<uint32_t> &q)
50 {
51 std::queue<uint32_t> empty;
52 swap(empty, q);
53 }
54
clearBufferqueue(std::queue<AVCodecBufferInfo> & q)55 void clearBufferqueue(std::queue<AVCodecBufferInfo> &q)
56 {
57 std::queue<AVCodecBufferInfo> empty;
58 swap(empty, q);
59 }
60
clearFlagqueue(std::queue<AVCodecBufferFlag> & q)61 void clearFlagqueue(std::queue<AVCodecBufferFlag> &q)
62 {
63 std::queue<AVCodecBufferFlag> empty;
64 swap(empty, q);
65 }
66 } // namespace
67
VEncNdkInnerSample(std::shared_ptr<VEncInnerSignal> signal)68 VEncNdkInnerSample::VEncNdkInnerSample(std::shared_ptr<VEncInnerSignal> signal)
69 : signal_(signal)
70 {
71 }
72
VEncInnerCallback(std::shared_ptr<VEncInnerSignal> signal)73 VEncInnerCallback::VEncInnerCallback(std::shared_ptr<VEncInnerSignal> signal) : innersignal_(signal) {}
74
OnError(AVCodecErrorType errorType,int32_t errorCode)75 void VEncInnerCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
76 {
77 cout << "Error errorType:" << errorType << " errorCode:" << errorCode << endl;
78 }
79
OnOutputFormatChanged(const Format & format)80 void VEncInnerCallback::OnOutputFormatChanged(const Format& format)
81 {
82 cout << "Format Changed" << endl;
83 format.GetIntValue(OH_MD_KEY_VIDEO_PIC_WIDTH, g_picWidth);
84 format.GetIntValue(OH_MD_KEY_VIDEO_PIC_HEIGHT, g_picHeight);
85 format.GetIntValue(OH_MD_KEY_WIDTH, g_keyWidth);
86 format.GetIntValue(OH_MD_KEY_HEIGHT, g_keyHeight);
87 cout << "format info: " << format.Stringify() << ", OH_MD_KEY_VIDEO_PIC_WIDTH: " << g_picWidth
88 << ", OH_MD_KEY_VIDEO_PIC_HEIGHT: "<< g_picHeight << ", OH_MD_KEY_WIDTH: " << g_keyWidth
89 << ", OH_MD_KEY_HEIGHT: " << g_keyHeight << endl;
90 }
91
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVSharedMemory> buffer)92 void VEncInnerCallback::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVSharedMemory> buffer)
93 {
94 if (innersignal_ == nullptr) {
95 std::cout << "buffer is null 1" << endl;
96 return;
97 }
98 unique_lock<mutex> lock(innersignal_->inMutex_);
99 innersignal_->inIdxQueue_.push(index);
100 innersignal_->inBufferQueue_.push(buffer);
101 innersignal_->inCond_.notify_all();
102 }
103
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag,std::shared_ptr<AVSharedMemory> buffer)104 void VEncInnerCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info,
105 AVCodecBufferFlag flag, std::shared_ptr<AVSharedMemory> buffer)
106 {
107 unique_lock<mutex> lock(innersignal_->outMutex_);
108 innersignal_->outIdxQueue_.push(index);
109 innersignal_->infoQueue_.push(info);
110 innersignal_->flagQueue_.push(flag);
111 innersignal_->outBufferQueue_.push(buffer);
112 innersignal_->outCond_.notify_all();
113 }
114
VEncParamWithAttrCallbackTest(std::shared_ptr<VEncInnerSignal> signal)115 VEncParamWithAttrCallbackTest::VEncParamWithAttrCallbackTest(
116 std::shared_ptr<VEncInnerSignal> signal) : signal_(signal) {}
117
~VEncParamWithAttrCallbackTest()118 VEncParamWithAttrCallbackTest::~VEncParamWithAttrCallbackTest()
119 {
120 signal_ = nullptr;
121 }
122
OnInputParameterWithAttrAvailable(uint32_t index,std::shared_ptr<Format> attribute,std::shared_ptr<Format> parameter)123 void VEncParamWithAttrCallbackTest::OnInputParameterWithAttrAvailable(uint32_t index,
124 std::shared_ptr<Format> attribute,
125 std::shared_ptr<Format> parameter)
126 {
127 if (signal_ == nullptr) {
128 return;
129 }
130 unique_lock<mutex> lock(signal_->inMutex_);
131 cout << "OnInputParameterWithAttrAvailable" <<endl;
132 signal_->inIdxQueue_.push(index);
133 signal_->inAttrQueue_.push(attribute);
134 signal_->inFormatQueue_.push(parameter);
135 signal_->inCond_.notify_all();
136 }
137
~VEncNdkInnerSample()138 VEncNdkInnerSample::~VEncNdkInnerSample()
139 {
140 Release();
141 }
142
GetSystemTimeUs()143 int64_t VEncNdkInnerSample::GetSystemTimeUs()
144 {
145 struct timespec now;
146 (void)clock_gettime(CLOCK_BOOTTIME, &now);
147 int64_t nanoTime = (int64_t)now.tv_sec * NANOS_IN_SECOND + now.tv_nsec;
148
149 return nanoTime / NANOS_IN_MICRO;
150 }
151
CreateByMime(const std::string & mime)152 int32_t VEncNdkInnerSample::CreateByMime(const std::string &mime)
153 {
154 venc_ = VideoEncoderFactory::CreateByMime(mime);
155 return venc_ == nullptr ? AVCS_ERR_INVALID_OPERATION : AVCS_ERR_OK;
156 }
157
CreateByName(const std::string & name)158 int32_t VEncNdkInnerSample::CreateByName(const std::string &name)
159 {
160 venc_ = VideoEncoderFactory::CreateByName(name);
161 return venc_ == nullptr ? AVCS_ERR_INVALID_OPERATION : AVCS_ERR_OK;
162 }
163
Configure()164 int32_t VEncNdkInnerSample::Configure()
165 {
166 Format format;
167 format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, DEFAULT_WIDTH);
168 format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, DEFAULT_HEIGHT);
169 format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, static_cast<int32_t>(VideoPixelFormat::NV12));
170 format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, DEFAULT_FRAME_RATE);
171 format.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, DEFAULT_BITRATE);
172 if (configMain10) {
173 format.PutIntValue(OH_MD_KEY_PROFILE, HEVC_PROFILE_MAIN_10);
174 } else if (configMain) {
175 format.PutIntValue(OH_MD_KEY_PROFILE, HEVC_PROFILE_MAIN);
176 }
177 format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, DEFAULT_BITRATE_MODE);
178 if (enableRepeat) {
179 format.PutIntValue(Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_FRAME_AFTER, DEFAULT_FRAME_AFTER);
180 if (setMaxCount) {
181 format.PutIntValue(Media::Tag::VIDEO_ENCODER_REPEAT_PREVIOUS_MAX_COUNT, DEFAULT_MAX_COUNT);
182 }
183 }
184 if (isDiscardFrame) {
185 format.PutIntValue(Media::Tag::VIDEO_I_FRAME_INTERVAL, DEFAULT_KEY_I_FRAME_INTERVAL);
186 }
187 return venc_->Configure(format);
188 }
189
ConfigureFuzz(int32_t data)190 int32_t VEncNdkInnerSample::ConfigureFuzz(int32_t data)
191 {
192 Format format;
193 double frameRate = data;
194 format.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, data);
195 format.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, data);
196 format.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, data % MAX_PIXEL_FMT);
197 format.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, frameRate);
198 format.PutIntValue(MediaDescriptionKey::MD_KEY_RANGE_FLAG, data);
199 format.PutIntValue(MediaDescriptionKey::MD_KEY_COLOR_PRIMARIES, data);
200 format.PutIntValue(MediaDescriptionKey::MD_KEY_TRANSFER_CHARACTERISTICS, data);
201 format.PutIntValue(MediaDescriptionKey::MD_KEY_MATRIX_COEFFICIENTS, data);
202 format.PutIntValue(MediaDescriptionKey::MD_KEY_I_FRAME_INTERVAL, data);
203 format.PutIntValue(MediaDescriptionKey::MD_KEY_VIDEO_ENCODE_BITRATE_MODE, data);
204 format.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, data);
205 format.PutIntValue(MediaDescriptionKey::MD_KEY_QUALITY, data);
206
207 return venc_->Configure(format);
208 }
209
Prepare()210 int32_t VEncNdkInnerSample::Prepare()
211 {
212 return venc_->Prepare();
213 }
214
Start()215 int32_t VEncNdkInnerSample::Start()
216 {
217 return venc_->Start();
218 }
219
Stop()220 int32_t VEncNdkInnerSample::Stop()
221 {
222 StopInloop();
223 clearIntqueue(signal_->outIdxQueue_);
224 clearBufferqueue(signal_->infoQueue_);
225 clearFlagqueue(signal_->flagQueue_);
226 ReleaseInFile();
227
228 return venc_->Stop();
229 }
230
Flush()231 int32_t VEncNdkInnerSample::Flush()
232 {
233 unique_lock<mutex> inLock(signal_->inMutex_);
234 clearIntqueue(signal_->inIdxQueue_);
235 signal_->inCond_.notify_all();
236 inLock.unlock();
237 unique_lock<mutex> outLock(signal_->outMutex_);
238 clearIntqueue(signal_->outIdxQueue_);
239 clearBufferqueue(signal_->infoQueue_);
240 clearFlagqueue(signal_->flagQueue_);
241 signal_->outCond_.notify_all();
242 outLock.unlock();
243
244 return venc_->Flush();
245 }
246
NotifyEos()247 int32_t VEncNdkInnerSample::NotifyEos()
248 {
249 return venc_->NotifyEos();
250 }
251
Reset()252 int32_t VEncNdkInnerSample::Reset()
253 {
254 isRunning_.store(false);
255 StopInloop();
256 StopOutloop();
257 ReleaseInFile();
258
259 if (venc_ == nullptr) {
260 std::cout << "InnerEncoder create failed!" << std::endl;
261 return AVCS_ERR_INVALID_OPERATION;
262 }
263 return venc_->Reset();
264 }
265
Release()266 int32_t VEncNdkInnerSample::Release()
267 {
268 int32_t ret = 0;
269 if (venc_) {
270 ret = venc_->Release();
271 venc_ = nullptr;
272 }
273 if (signal_ != nullptr) {
274 signal_ = nullptr;
275 }
276 return ret;
277 }
278
CreateInputSurface()279 int32_t VEncNdkInnerSample::CreateInputSurface()
280 {
281 sptr<Surface> surface = venc_->CreateInputSurface();
282 if (surface == nullptr) {
283 cout << "CreateInputSurface fail" << endl;
284 return AVCS_ERR_INVALID_OPERATION;
285 }
286
287 nativeWindow = CreateNativeWindowFromSurface(&surface);
288 if (nativeWindow == nullptr) {
289 cout << "CreateNativeWindowFromSurface failed!" << endl;
290 return AVCS_ERR_INVALID_VAL;
291 }
292
293 int32_t ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
294 if (ret != AVCS_ERR_OK) {
295 cout << "NativeWindowHandleOpt SET_FORMAT fail" << endl;
296 return ret;
297 }
298
299 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
300 if (ret != AVCS_ERR_OK) {
301 cout << "NativeWindowHandleOpt SET_BUFFER_GEOMETRY fail" << endl;
302 return ret;
303 }
304 return AVCS_ERR_OK;
305 }
306
QueueInputBuffer(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)307 int32_t VEncNdkInnerSample::QueueInputBuffer(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
308 {
309 return venc_->QueueInputBuffer(index, info, flag);
310 }
311
GetOutputFormat(Format & format)312 int32_t VEncNdkInnerSample::GetOutputFormat(Format &format)
313 {
314 return venc_->GetOutputFormat(format);
315 }
316
ReleaseOutputBuffer(uint32_t index)317 int32_t VEncNdkInnerSample::ReleaseOutputBuffer(uint32_t index)
318 {
319 return venc_->ReleaseOutputBuffer(index);
320 }
321
SetParameter(const Format & format)322 int32_t VEncNdkInnerSample::SetParameter(const Format &format)
323 {
324 return venc_->SetParameter(format);
325 }
326
SetCallback()327 int32_t VEncNdkInnerSample::SetCallback()
328 {
329 if (signal_ == nullptr) {
330 signal_ = make_shared<VEncInnerSignal>();
331 }
332 if (signal_ == nullptr) {
333 cout << "Failed to new VEncInnerSignal" << endl;
334 return AVCS_ERR_UNKNOWN;
335 }
336
337 cb_ = make_shared<VEncInnerCallback>(signal_);
338 return venc_->SetCallback(cb_);
339 }
340
SetCallback(std::shared_ptr<MediaCodecParameterWithAttrCallback> cb)341 int32_t VEncNdkInnerSample::SetCallback(std::shared_ptr<MediaCodecParameterWithAttrCallback> cb)
342 {
343 if (venc_ == nullptr) {
344 return AV_ERR_UNKNOWN;
345 }
346 int32_t ret = venc_->SetCallback(cb);
347 isSetParamCallback_ = ret == AV_ERR_OK;
348 return ret;
349 }
350
351
GetInputFormat(Format & format)352 int32_t VEncNdkInnerSample::GetInputFormat(Format &format)
353 {
354 return venc_->GetInputFormat(format);
355 }
356
StartVideoEncoder()357 int32_t VEncNdkInnerSample::StartVideoEncoder()
358 {
359 isRunning_.store(true);
360 int32_t ret = 0;
361 if (surfaceInput) {
362 ret = CreateInputSurface();
363 if (ret != AVCS_ERR_OK) {
364 return ret;
365 }
366 }
367 ret = venc_->Start();
368 if (ret != AVCS_ERR_OK) {
369 isRunning_.store(false);
370 signal_->inCond_.notify_all();
371 signal_->outCond_.notify_all();
372 return ret;
373 }
374
375 inFile_ = make_unique<ifstream>();
376 if (inFile_ == nullptr) {
377 isRunning_.store(false);
378 venc_->Stop();
379 return AVCS_ERR_UNKNOWN;
380 }
381 readMultiFilesFunc();
382 if (surfaceInput) {
383 inputLoop_ = make_unique<thread>(&VEncNdkInnerSample::InputFuncSurface, this);
384 inputParamLoop_ = isSetParamCallback_ ? make_unique<thread>(&VEncNdkInnerSample::InputParamLoopFunc,
385 this):nullptr;
386 } else {
387 inputLoop_ = make_unique<thread>(&VEncNdkInnerSample::InputFunc, this);
388 }
389
390 if (inputLoop_ == nullptr) {
391 isRunning_.store(false);
392 venc_->Stop();
393 ReleaseInFile();
394 return AVCS_ERR_UNKNOWN;
395 }
396
397 outputLoop_ = make_unique<thread>(&VEncNdkInnerSample::OutputFunc, this);
398 if (outputLoop_ == nullptr) {
399 isRunning_.store(false);
400 venc_->Stop();
401 ReleaseInFile();
402 StopInloop();
403 Release();
404 return AVCS_ERR_UNKNOWN;
405 }
406 return AVCS_ERR_OK;
407 }
408
readMultiFilesFunc()409 void VEncNdkInnerSample::readMultiFilesFunc()
410 {
411 if (!readMultiFiles) {
412 inFile_->open(INP_DIR, ios::in | ios::binary);
413 if (!inFile_->is_open()) {
414 OpenFileFail();
415 }
416 }
417 }
418
testApi()419 int32_t VEncNdkInnerSample::testApi()
420 {
421 if (venc_ == nullptr) {
422 std::cout << "InnerEncoder create failed!" << std::endl;
423 return AVCS_ERR_INVALID_OPERATION;
424 }
425
426 Format format;
427 format.PutIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, 1);
428 venc_->CreateInputSurface();
429 venc_->Prepare();
430 venc_->GetInputFormat(format);
431 venc_->Start();
432 venc_->SetParameter(format);
433 venc_->NotifyEos();
434 venc_->GetOutputFormat(format);
435 venc_->Flush();
436 venc_->Stop();
437 venc_->Reset();
438
439 return AVCS_ERR_OK;
440 }
441
PushData(std::shared_ptr<AVSharedMemory> buffer,uint32_t index,int32_t & result)442 int32_t VEncNdkInnerSample::PushData(std::shared_ptr<AVSharedMemory> buffer, uint32_t index, int32_t &result)
443 {
444 int32_t res = -2;
445 uint32_t yuvSize = DEFAULT_WIDTH * DEFAULT_HEIGHT * 3 / 2;
446 uint8_t *fileBuffer = buffer->GetBase();
447 if (fileBuffer == nullptr) {
448 cout << "Fatal: no memory" << endl;
449 return -1;
450 }
451 (void)inFile_->read((char *)fileBuffer, yuvSize);
452
453 if (repeatRun && inFile_->eof()) {
454 inFile_->clear();
455 inFile_->seekg(0, ios::beg);
456 encodeCount++;
457 cout << "repeat" << " encodeCount:" << encodeCount << endl;
458 return -1;
459 }
460
461 if (inFile_->eof()) {
462 SetEOS(index);
463 return 0;
464 }
465
466 AVCodecBufferInfo info;
467 info.presentationTimeUs = GetSystemTimeUs();
468 info.size = yuvSize;
469 info.offset = 0;
470 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_NONE;
471
472 int32_t size = buffer->GetSize();
473 if (size < (int32_t)yuvSize) {
474 cout << "bufferSize smaller than yuv size" << endl;
475 return -1;
476 }
477
478 if (enableForceIDR && (frameCount % IDR_FRAME_INTERVAL == 0)) {
479 Format format;
480 format.PutIntValue(MediaDescriptionKey::MD_KEY_REQUEST_I_FRAME, 1);
481 venc_->SetParameter(format);
482 }
483 result = venc_->QueueInputBuffer(index, info, flag);
484 unique_lock<mutex> lock(signal_->inMutex_);
485 signal_->inIdxQueue_.pop();
486 signal_->inBufferQueue_.pop();
487
488 return res;
489 }
490
OpenFileFail()491 int32_t VEncNdkInnerSample::OpenFileFail()
492 {
493 cout << "file open fail" << endl;
494 isRunning_.store(false);
495 venc_->Stop();
496 inFile_->close();
497 inFile_.reset();
498 inFile_ = nullptr;
499 return AVCS_ERR_UNKNOWN;
500 }
501
CheckResult(bool isRandomEosSuccess,int32_t pushResult)502 int32_t VEncNdkInnerSample::CheckResult(bool isRandomEosSuccess, int32_t pushResult)
503 {
504 if (isRandomEosSuccess) {
505 if (pushResult == 0) {
506 errCount = errCount + 1;
507 cout << "push input after eos should be failed! pushResult:" << pushResult << endl;
508 }
509 return -1;
510 } else if (pushResult != 0) {
511 errCount = errCount + 1;
512 cout << "push input data failed, error:" << pushResult << endl;
513 return -1;
514 }
515 return 0;
516 }
517
CheckFlag(AVCodecBufferFlag flag)518 int32_t VEncNdkInnerSample::CheckFlag(AVCodecBufferFlag flag)
519 {
520 if (flag == AVCODEC_BUFFER_FLAG_EOS) {
521 cout << "flag == AVCODEC_BUFFER_FLAG_EOS" << endl;
522 unique_lock<mutex> inLock(signal_->inMutex_);
523 isRunning_.store(false);
524 signal_->inCond_.notify_all();
525 signal_->outCond_.notify_all();
526 inLock.unlock();
527 return -1;
528 }
529
530 if (flag == AVCODEC_BUFFER_FLAG_CODEC_DATA) {
531 cout << "enc AVCODEC_BUFFER_FLAG_CODEC_DATA" << endl;
532 } else {
533 outCount = outCount + 1;
534 }
535 return 0;
536 }
537
InputProcess(OH_NativeBuffer * nativeBuffer,OHNativeWindowBuffer * ohNativeWindowBuffer)538 int32_t VEncNdkInnerSample::InputProcess(OH_NativeBuffer *nativeBuffer, OHNativeWindowBuffer *ohNativeWindowBuffer)
539 {
540 int32_t ret = 0;
541 struct Region region;
542 struct Region::Rect *rect = new Region::Rect();
543 rect->x = 0;
544 rect->y = 0;
545 rect->w = DEFAULT_WIDTH;
546 rect->h = DEFAULT_HEIGHT;
547 region.rects = rect;
548 NativeWindowHandleOpt(nativeWindow, SET_UI_TIMESTAMP, GetSystemTimeUs());
549 ret = OH_NativeBuffer_Unmap(nativeBuffer);
550 if (ret != 0) {
551 cout << "OH_NativeBuffer_Unmap failed" << endl;
552 delete rect;
553 return ret;
554 }
555
556 ret = OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow, ohNativeWindowBuffer, -1, region);
557 delete rect;
558 if (ret != 0) {
559 cout << "FlushBuffer failed" << endl;
560 return ret;
561 }
562 return ret;
563 }
564
StateEOS()565 int32_t VEncNdkInnerSample::StateEOS()
566 {
567 unique_lock<mutex> lock(signal_->inMutex_);
568 signal_->inCond_.wait(lock, [this]() { return signal_->inIdxQueue_.size() > 0; });
569 uint32_t index = signal_->inIdxQueue_.front();
570 signal_->inIdxQueue_.pop();
571 signal_->inBufferQueue_.pop();
572 lock.unlock();
573
574 AVCodecBufferInfo info;
575 info.presentationTimeUs = 0;
576 info.size = 0;
577 info.offset = 0;
578 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
579
580 return venc_->QueueInputBuffer(index, info, flag);
581 }
582
ReturnZeroIfEOS(uint32_t expectedSize)583 uint32_t VEncNdkInnerSample::ReturnZeroIfEOS(uint32_t expectedSize)
584 {
585 if (inFile_->gcount() != (int32_t)expectedSize) {
586 cout << "no more data" << endl;
587 return 0;
588 }
589 return 1;
590 }
591
ReadOneFrameYUV420SP(uint8_t * dst)592 uint32_t VEncNdkInnerSample::ReadOneFrameYUV420SP(uint8_t *dst)
593 {
594 uint8_t *start = dst;
595 // copy Y
596 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
597 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
598 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
599 return 0;
600 dst += stride_;
601 }
602 // copy UV
603 for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
604 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH);
605 if (!ReturnZeroIfEOS(DEFAULT_WIDTH))
606 return 0;
607 dst += stride_;
608 }
609 return dst - start;
610 }
611
ReadOneFrameYUVP010(uint8_t * dst)612 uint32_t VEncNdkInnerSample::ReadOneFrameYUVP010(uint8_t *dst)
613 {
614 uint8_t *start = dst;
615 int32_t num = 2;
616 // copy Y
617 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
618 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH*num);
619 if (!ReturnZeroIfEOS(DEFAULT_WIDTH*num))
620 return 0;
621 dst += stride_;
622 }
623 // copy UV
624 for (uint32_t i = 0; i < DEFAULT_HEIGHT / SAMPLE_RATIO; i++) {
625 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH*num);
626 if (!ReturnZeroIfEOS(DEFAULT_WIDTH*num))
627 return 0;
628 dst += stride_;
629 }
630 return dst - start;
631 }
632
ReadOneFrameFromList(uint8_t * dst,int32_t & index)633 uint32_t VEncNdkInnerSample::ReadOneFrameFromList(uint8_t *dst, int32_t &index)
634 {
635 int32_t ret = 0;
636 if (index >= fileInfos.size()) {
637 ret = venc_->NotifyEos();
638 if (ret != 0) {
639 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
640 }
641 return LOOP_END;
642 }
643 if (!inFile_->is_open()) {
644 inFile_->open(fileInfos[index].fileDir);
645 if (!inFile_->is_open()) {
646 return OpenFileFail();
647 }
648 DEFAULT_WIDTH = fileInfos[index].width;
649 DEFAULT_HEIGHT = fileInfos[index].height;
650 if (setFormatRbgx) {
651 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_RGBX_8888);
652 } else if (setFormat8Bit) {
653 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_420_SP);
654 } else if (setFormat10Bit) {
655 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, GRAPHIC_PIXEL_FMT_YCBCR_P010);
656 } else {
657 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_FORMAT, fileInfos[index].format);
658 }
659 if (ret != AVCS_ERR_OK) {
660 return ret;
661 }
662 ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow, SET_BUFFER_GEOMETRY, DEFAULT_WIDTH, DEFAULT_HEIGHT);
663 if (ret != AVCS_ERR_OK) {
664 return ret;
665 }
666 cout << fileInfos[index].fileDir << endl;
667 cout << "set width:" << fileInfos[index].width << "height: " << fileInfos[index].height << endl;
668 return FILE_END;
669 }
670 ret = ReadOneFrameByType(dst, fileInfos[index].format);
671 if (!ret) {
672 if (inFile_->is_open()) {
673 inFile_->close();
674 }
675 index++;
676 if (index >= fileInfos.size()) {
677 venc_->NotifyEos();
678 return LOOP_END;
679 }
680 return FILE_END;
681 }
682 return ret;
683 }
684
ReadOneFrameByType(uint8_t * dst,std::string & fileType)685 uint32_t VEncNdkInnerSample::ReadOneFrameByType(uint8_t *dst, std::string &fileType)
686 {
687 if (fileType == "rgba") {
688 return ReadOneFrameRGBA8888(dst);
689 } else if (fileType == "nv12" || fileType == "nv21") {
690 return ReadOneFrameYUV420SP(dst);
691 } else {
692 cout << "error fileType" << endl;
693 return 0;
694 }
695 }
696
ReadOneFrameByType(uint8_t * dst,GraphicPixelFormat format)697 uint32_t VEncNdkInnerSample::ReadOneFrameByType(uint8_t *dst, GraphicPixelFormat format)
698 {
699 if (format == GRAPHIC_PIXEL_FMT_RGBA_8888) {
700 return ReadOneFrameRGBA8888(dst);
701 } else if (format == GRAPHIC_PIXEL_FMT_YCBCR_420_SP || format == GRAPHIC_PIXEL_FMT_YCRCB_420_SP) {
702 return ReadOneFrameYUV420SP(dst);
703 } else if (format == GRAPHIC_PIXEL_FMT_YCBCR_P010) {
704 return ReadOneFrameYUVP010(dst);
705 } else {
706 cout << "error fileType" << endl;
707 return 0;
708 }
709 }
710
ReadOneFrameRGBA8888(uint8_t * dst)711 uint32_t VEncNdkInnerSample::ReadOneFrameRGBA8888(uint8_t *dst)
712 {
713 uint8_t *start = dst;
714 for (uint32_t i = 0; i < DEFAULT_HEIGHT; i++) {
715 inFile_->read(reinterpret_cast<char *>(dst), DEFAULT_WIDTH * RGBA_SIZE);
716 if (inFile_->eof())
717 return 0;
718 dst += stride_;
719 }
720 return dst - start;
721 }
722
RandomEOS(uint32_t index)723 bool VEncNdkInnerSample::RandomEOS(uint32_t index)
724 {
725 uint32_t random_eos = rand() % 25;
726 if (enableRandomEos && random_eos == frameCount) {
727 AVCodecBufferInfo info;
728 info.presentationTimeUs = 0;
729 info.size = 0;
730 info.offset = 0;
731 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
732
733 venc_->QueueInputBuffer(index, info, flag);
734 cout << "random eos" << endl;
735 frameCount++;
736 unique_lock<mutex> lock(signal_->inMutex_);
737 signal_->inIdxQueue_.pop();
738 signal_->inBufferQueue_.pop();
739 return true;
740 }
741 return false;
742 }
743
RepeatStartBeforeEOS()744 void VEncNdkInnerSample::RepeatStartBeforeEOS()
745 {
746 if (REPEAT_START_FLUSH_BEFORE_EOS > 0) {
747 REPEAT_START_FLUSH_BEFORE_EOS--;
748 venc_->Flush();
749 FlushBuffer();
750 venc_->Start();
751 }
752
753 if (REPEAT_START_STOP_BEFORE_EOS > 0) {
754 REPEAT_START_STOP_BEFORE_EOS--;
755 venc_->Stop();
756 FlushBuffer();
757 venc_->Start();
758 }
759 }
760
SetEOS(uint32_t index)761 void VEncNdkInnerSample::SetEOS(uint32_t index)
762 {
763 AVCodecBufferInfo info;
764 info.presentationTimeUs = 0;
765 info.size = 0;
766 info.offset = 0;
767 AVCodecBufferFlag flag = AVCODEC_BUFFER_FLAG_EOS;
768
769 int32_t res = venc_->QueueInputBuffer(index, info, flag);
770 cout << "QueueInputBuffer EOS res: " << res << endl;
771 unique_lock<mutex> lock(signal_->inMutex_);
772 signal_->inIdxQueue_.pop();
773 signal_->inBufferQueue_.pop();
774 }
775
WaitForEOS()776 void VEncNdkInnerSample::WaitForEOS()
777 {
778 if (inputLoop_)
779 inputLoop_->join();
780 if (outputLoop_)
781 outputLoop_->join();
782 if (inputParamLoop_)
783 inputParamLoop_->join();
784 inputLoop_ = nullptr;
785 outputLoop_ = nullptr;
786 inputParamLoop_ = nullptr;
787 }
788
InputFuncSurface()789 void VEncNdkInnerSample::InputFuncSurface()
790 {
791 int32_t readFileIndex = 0;
792 while (true) {
793 OHNativeWindowBuffer *ohNativeWindowBuffer = nullptr;
794 OH_NativeBuffer *nativeBuffer = nullptr;
795 uint8_t *dst = nullptr;
796 int err = InitBuffer(ohNativeWindowBuffer, nativeBuffer, dst);
797 if (err == 0) {
798 break;
799 } else if (err == -1) {
800 continue;
801 }
802 if (readMultiFiles) {
803 err = ReadOneFrameFromList(dst, readFileIndex);
804 if (err == LOOP_END) {
805 break;
806 } else if (err == FILE_END) {
807 OH_NativeWindow_NativeWindowAbortBuffer(nativeWindow, ohNativeWindowBuffer);
808 continue;
809 }
810 } else if (!ReadOneFrameYUV420SP(dst)) {
811 err = venc_->NotifyEos();
812 if (err != 0) {
813 cout << "OH_VideoEncoder_NotifyEndOfStream failed" << endl;
814 }
815 break;
816 }
817 inputFrameCount++;
818 err = InputProcess(nativeBuffer, ohNativeWindowBuffer);
819 if (err != 0) {
820 break;
821 }
822 usleep(FRAME_INTERVAL);
823 InputEnableRepeatSleep();
824 }
825 }
826
InitBuffer(OHNativeWindowBuffer * & ohNativeWindowBuffer,OH_NativeBuffer * & nativeBuffer,uint8_t * & dst)827 int32_t VEncNdkInnerSample::InitBuffer(OHNativeWindowBuffer *&ohNativeWindowBuffer,
828 OH_NativeBuffer *&nativeBuffer, uint8_t *&dst)
829 {
830 int fenceFd = -1;
831 if (nativeWindow == nullptr) {
832 return 0;
833 }
834 int32_t err = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow, &ohNativeWindowBuffer, &fenceFd);
835 if (err != 0) {
836 cout << "RequestBuffer failed, GSError=" << err << endl;
837 return -1;
838 }
839 if (fenceFd > 0) {
840 close(fenceFd);
841 }
842 nativeBuffer = OH_NativeBufferFromNativeWindowBuffer(ohNativeWindowBuffer);
843 void *virAddr = nullptr;
844 err = OH_NativeBuffer_Map(nativeBuffer, &virAddr);
845 if (err != 0) {
846 cout << "OH_NativeBuffer_Map failed, GSError=" << err << endl;
847 isRunning_.store(false);
848 return 0;
849 }
850 dst = (uint8_t *)virAddr;
851 const SurfaceBuffer *sbuffer = SurfaceBuffer::NativeBufferToSurfaceBuffer(nativeBuffer);
852 int32_t stride = sbuffer->GetStride();
853 if (dst == nullptr || stride < (int32_t)DEFAULT_WIDTH) {
854 cout << "invalid va or stride=" << stride << endl;
855 err = NativeWindowCancelBuffer(nativeWindow, ohNativeWindowBuffer);
856 isRunning_.store(false);
857 return 0;
858 }
859 stride_ = stride;
860 return 1;
861 }
862
InputEnableRepeatSleep()863 void VEncNdkInnerSample::InputEnableRepeatSleep()
864 {
865 inCount = inCount + 1;
866 int32_t inCountNum = 15;
867 if (enableRepeat && inCount == inCountNum) {
868 if (setMaxCount) {
869 int32_t sleepTimeMaxCount = 730000;
870 usleep(sleepTimeMaxCount);
871 } else {
872 int32_t sleepTime = 1000000;
873 usleep(sleepTime);
874 }
875 if (enableSeekEos) {
876 inFile_->clear();
877 inFile_->seekg(-1, ios::beg);
878 }
879 }
880 }
881
InputParamLoopFunc()882 void VEncNdkInnerSample::InputParamLoopFunc()
883 {
884 if (signal_ == nullptr || venc_ == nullptr) {
885 cout << "signal or venc is null" << endl;
886 return;
887 }
888 cout<< "InputParamLoopFunc" <<endl;
889 while (isRunning_.load()) {
890 unique_lock<mutex> lock(signal_->inMutex_);
891 signal_->inCond_.wait(
892 lock, [this]() { return (signal_->inIdxQueue_.size() > 0) || (!isRunning_.load()); });
893 if (!isRunning_.load()) {
894 cout << "InputLoopFunc stop running" << endl;
895 break;
896 }
897 int32_t index = signal_->inIdxQueue_.front();
898 auto format = signal_->inFormatQueue_.front();
899 auto attr = signal_->inAttrQueue_.front();
900 signal_->inIdxQueue_.pop();
901 signal_->inFormatQueue_.pop();
902 signal_->inAttrQueue_.pop();
903 if (attr != nullptr) {
904 int64_t pts = 0;
905 if (true != attr->GetLongValue(Media::Tag::MEDIA_TIME_STAMP, pts)) {
906 return;
907 }
908 }
909 if (IsFrameDiscard(inputFrameCount)) {
910 discardFrameCount++;
911 format->PutIntValue(Media::Tag::VIDEO_ENCODER_PER_FRAME_DISCARD, 1);
912 }
913 int32_t ret = PushInputParameter(index);
914 if (ret != AV_ERR_OK) {
915 cout << "Fatal: PushInputData fail, exit" << endl;
916 }
917 }
918 }
919
InputFunc()920 void VEncNdkInnerSample::InputFunc()
921 {
922 errCount = 0;
923 while (true) {
924 if (!isRunning_.load()) {
925 break;
926 }
927 RepeatStartBeforeEOS();
928 unique_lock<mutex> lock(signal_->inMutex_);
929 signal_->inCond_.wait(lock, [this]() {
930 if (!isRunning_.load()) {
931 return true;
932 }
933 return signal_->inIdxQueue_.size() > 0;
934 });
935 if (!isRunning_.load()) {
936 break;
937 }
938 uint32_t index = signal_->inIdxQueue_.front();
939 auto buffer = signal_->inBufferQueue_.front();
940
941 lock.unlock();
942 if (!inFile_->eof()) {
943 bool isRandomEosSuccess = RandomEOS(index);
944 if (isRandomEosSuccess) {
945 continue;
946 }
947 int32_t pushResult = 0;
948 int32_t ret = PushData(buffer, index, pushResult);
949 if (ret == 0) {
950 break;
951 } else if (ret == -1) {
952 continue;
953 }
954
955 if (CheckResult(isRandomEosSuccess, pushResult) == -1) {
956 break;
957 }
958 frameCount++;
959 }
960 if (sleepOnFPS) {
961 usleep(FRAME_INTERVAL);
962 }
963 }
964 }
965
OutputFunc()966 void VEncNdkInnerSample::OutputFunc()
967 {
968 FILE *outFile = fopen(OUT_DIR, "wb");
969
970 while (true) {
971 if (!isRunning_.load()) {
972 break;
973 }
974
975 unique_lock<mutex> lock(signal_->outMutex_);
976 signal_->outCond_.wait(lock, [this]() {
977 if (!isRunning_.load()) {
978 return true;
979 }
980 return signal_->outIdxQueue_.size() > 0;
981 });
982
983 if (!isRunning_.load()) {
984 break;
985 }
986
987 std::shared_ptr<AVSharedMemory> buffer = signal_->outBufferQueue_.front();
988 AVCodecBufferInfo info = signal_->infoQueue_.front();
989 AVCodecBufferFlag flag = signal_->flagQueue_.front();
990 uint32_t index = signal_->outIdxQueue_.front();
991
992 signal_->outBufferQueue_.pop();
993 signal_->outIdxQueue_.pop();
994 signal_->infoQueue_.pop();
995 signal_->flagQueue_.pop();
996 lock.unlock();
997
998 if (CheckFlag(flag) == -1) {
999 break;
1000 }
1001
1002 int size = info.size;
1003 if (outFile == nullptr) {
1004 cout << "dump data fail" << endl;
1005 } else {
1006 fwrite(buffer->GetBase(), 1, size, outFile);
1007 }
1008
1009 if (venc_->ReleaseOutputBuffer(index) != AVCS_ERR_OK) {
1010 cout << "Fatal: ReleaseOutputBuffer fail" << endl;
1011 errCount = errCount + 1;
1012 }
1013 if (errCount > 0) {
1014 OutputFuncFail();
1015 break;
1016 }
1017 }
1018 (void)fclose(outFile);
1019 }
1020
OutputFuncFail()1021 void VEncNdkInnerSample::OutputFuncFail()
1022 {
1023 cout << "errCount > 0" << endl;
1024 unique_lock<mutex> inLock(signal_->inMutex_);
1025 isRunning_.store(false);
1026 signal_->inCond_.notify_all();
1027 signal_->outCond_.notify_all();
1028 inLock.unlock();
1029 (void)Stop();
1030 Release();
1031 }
1032
FlushBuffer()1033 void VEncNdkInnerSample::FlushBuffer()
1034 {
1035 std::queue<std::shared_ptr<AVSharedMemory>> empty;
1036 unique_lock<mutex> inLock(signal_->inMutex_);
1037 clearIntqueue(signal_->inIdxQueue_);
1038 swap(empty, signal_->inBufferQueue_);
1039 signal_->inCond_.notify_all();
1040 inLock.unlock();
1041
1042 unique_lock<mutex> outLock(signal_->outMutex_);
1043 clearIntqueue(signal_->outIdxQueue_);
1044 clearBufferqueue(signal_->infoQueue_);
1045 clearFlagqueue(signal_->flagQueue_);
1046 signal_->outCond_.notify_all();
1047 outLock.unlock();
1048 }
1049
StopInloop()1050 void VEncNdkInnerSample::StopInloop()
1051 {
1052 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
1053 unique_lock<mutex> lock(signal_->inMutex_);
1054 clearIntqueue(signal_->inIdxQueue_);
1055 isRunning_.store(false);
1056 signal_->inCond_.notify_all();
1057 lock.unlock();
1058
1059 inputLoop_->join();
1060 inputLoop_ = nullptr;
1061 }
1062 }
1063
StopOutloop()1064 void VEncNdkInnerSample::StopOutloop()
1065 {
1066 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
1067 unique_lock<mutex> lock(signal_->outMutex_);
1068 clearIntqueue(signal_->outIdxQueue_);
1069 clearBufferqueue(signal_->infoQueue_);
1070 clearFlagqueue(signal_->flagQueue_);
1071 signal_->outCond_.notify_all();
1072 lock.unlock();
1073 }
1074 }
1075
ReleaseInFile()1076 void VEncNdkInnerSample::ReleaseInFile()
1077 {
1078 if (inFile_ != nullptr) {
1079 if (inFile_->is_open()) {
1080 inFile_->close();
1081 }
1082 inFile_.reset();
1083 inFile_ = nullptr;
1084 }
1085 }
1086
PushRandomDiscardIndex(uint32_t count,uint32_t max,uint32_t min)1087 void VEncNdkInnerSample::PushRandomDiscardIndex(uint32_t count, uint32_t max, uint32_t min)
1088 {
1089 cout << "random farame index :";
1090 while (discardFrameIndex.size() < count) {
1091 uint32_t num = 0;
1092 if (max != 0) {
1093 num = rd() % max + min;
1094 }
1095 if (find(discardFrameIndex.begin(), discardFrameIndex.end(), num) == discardFrameIndex.end()) {
1096 cout << num << ",";
1097 discardFrameIndex.push_back(num);
1098 }
1099 cout << endl;
1100 }
1101 }
1102
IsFrameDiscard(uint32_t index)1103 bool VEncNdkInnerSample::IsFrameDiscard(uint32_t index)
1104 {
1105 if (!isDiscardFrame) {
1106 return false;
1107 }
1108 if (discardMinIndex > -1 && discardMaxIndex >= discardMinIndex) {
1109 if (index >= discardMinIndex && index <= discardMaxIndex) {
1110 return true;
1111 }
1112 }
1113 if (find(discardFrameIndex.begin(), discardFrameIndex.end(), index) != discardFrameIndex.end()) {
1114 return true;
1115 }
1116 if (discardInterval > 0 && index % discardInterval == 0) {
1117 return true;
1118 }
1119 return false;
1120 }
1121
CheckOutputFrameCount()1122 bool VEncNdkInnerSample::CheckOutputFrameCount()
1123 {
1124 cout << "checooutpuframecount" << inputFrameCount << ", " << discardFrameCount<< ", " << outCount << endl;
1125 if (inputFrameCount - discardFrameCount == outCount) {
1126 return true;
1127 }
1128 return false;
1129 }
1130
PushInputParameter(uint32_t index)1131 int32_t VEncNdkInnerSample::PushInputParameter(uint32_t index)
1132 {
1133 if (venc_ == nullptr) {
1134 return AV_ERR_UNKNOWN;
1135 }
1136 return venc_->QueueInputParameter(index);
1137 }
1138
SetCustomBuffer(BufferRequestConfig bufferConfig)1139 int32_t VEncNdkInnerSample::SetCustomBuffer(BufferRequestConfig bufferConfig)
1140 {
1141 int32_t waterMarkFlag = enableWaterMark ? 1 : 0;
1142 auto allocator = Media::AVAllocatorFactory::CreateSurfaceAllocator(bufferConfig);
1143 std::shared_ptr<AVBuffer> avbuffer = AVBuffer::CreateAVBuffer(allocator);
1144 if (avbuffer == nullptr) {
1145 cout << "avbuffer is nullptr" << endl;
1146 return AVCS_ERR_INVALID_VAL;
1147 }
1148 cout << WATER_MARK_DIR << endl;
1149 ReadCustomDataToAVBuffer(WATER_MARK_DIR, avbuffer);
1150 Format format;
1151 format.SetMeta(avbuffer->meta_);
1152 format.PutIntValue(Media::Tag::VIDEO_ENCODER_ENABLE_WATERMARK, waterMarkFlag);
1153 format.PutIntValue(Media::Tag::VIDEO_COORDINATE_X, videoCoordinateX);
1154 format.PutIntValue(Media::Tag::VIDEO_COORDINATE_Y, videoCoordinateY);
1155 format.PutIntValue(Media::Tag::VIDEO_COORDINATE_W, videoCoordinateWidth);
1156 format.PutIntValue(Media::Tag::VIDEO_COORDINATE_H, videoCoordinateHeight);
1157 *(avbuffer->meta_) = *(format.GetMeta());
1158 int32_t ret = venc_->SetCustomBuffer(avbuffer);
1159 return ret;
1160 }
1161
ReadCustomDataToAVBuffer(const std::string & fileName,std::shared_ptr<AVBuffer> buffer)1162 bool VEncNdkInnerSample::ReadCustomDataToAVBuffer(const std::string &fileName, std::shared_ptr<AVBuffer> buffer)
1163 {
1164 std::unique_ptr<std::ifstream> inFile = std::make_unique<std::ifstream>();
1165 inFile->open(fileName.c_str(), std::ios::in | std::ios::binary);
1166 if (!inFile->is_open()) {
1167 cout << "open file filed,filename:" << fileName.c_str() << endl;
1168 }
1169 sptr<SurfaceBuffer> surfaceBuffer = buffer->memory_->GetSurfaceBuffer();
1170 if (surfaceBuffer == nullptr) {
1171 cout << "in is nullptr" << endl;
1172 return false;
1173 }
1174 int32_t width = surfaceBuffer->GetWidth();
1175 int32_t height = surfaceBuffer->GetHeight();
1176 int32_t bufferSize = width * height * 4;
1177 uint8_t *in = (uint8_t *)malloc(bufferSize);
1178 if (in == nullptr) {
1179 cout << "in is nullptr" <<endl;
1180 }
1181 inFile->read(reinterpret_cast<char *>(in), bufferSize);
1182 int32_t dstWidthStride = surfaceBuffer->GetStride();
1183 uint8_t *dstAddr = (uint8_t *)surfaceBuffer->GetVirAddr();
1184 if (dstAddr == nullptr) {
1185 cout << "dst is nullptr" << endl;
1186 }
1187 const int32_t srcWidthStride = width << 2;
1188 uint8_t *inStream = in;
1189 for (uint32_t i = 0; i < height; ++i) {
1190 if (memcpy_s(dstAddr, dstWidthStride, inStream, srcWidthStride)) {
1191 cout << "memcpy_s failed" <<endl;
1192 };
1193 dstAddr += dstWidthStride;
1194 inStream += srcWidthStride;
1195 }
1196 inFile->close();
1197 if (in) {
1198 free(in);
1199 in = nullptr;
1200 }
1201 return true;
1202 }
1203
GetWaterMarkCapability(std::string codecMimeType)1204 bool VEncNdkInnerSample::GetWaterMarkCapability(std::string codecMimeType)
1205 {
1206 std::shared_ptr<AVCodecList> codecCapability = AVCodecListFactory::CreateAVCodecList();
1207 CapabilityData *capabilityData = nullptr;
1208 capabilityData = codecCapability->GetCapability(codecMimeType, true, AVCodecCategory::AVCODEC_HARDWARE);
1209 if (capabilityData->featuresMap.count(static_cast<int32_t>(AVCapabilityFeature::VIDEO_WATERMARK))) {
1210 std::cout << "Support watermark" << std::endl;
1211 return true;
1212 } else {
1213 std::cout << " Not support watermark" << std::endl;
1214 return false;
1215 }
1216 }