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