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