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