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