• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 
16 #include "avcodec_venc_demo.h"
17 #include <iostream>
18 #include <sync_fence.h>
19 #include "securec.h"
20 #include "demo_log.h"
21 #include "display_type.h"
22 #include "media_errors.h"
23 
24 using namespace OHOS;
25 using namespace OHOS::Media;
26 using namespace std;
27 namespace {
28     constexpr uint32_t DEFAULT_WIDTH = 480;
29     constexpr uint32_t DEFAULT_HEIGHT = 360;
30     constexpr uint32_t DEFAULT_FRAME_RATE = 30;
31     constexpr uint32_t YUV_BUFFER_SIZE = 259200; // 480 * 360 * 3 / 2
32     constexpr uint32_t STRIDE_ALIGN = 8;
33 
34     constexpr int32_t FAST_PRODUCER = 50; // 50 fps producer, used to test max_encoder_fps property
35     constexpr int32_t SLOW_PRODUCER = 20; // 20 fps producer, used to test repeat_frame_after property
36     constexpr uint32_t REPEAT_FRAME_AFTER_MS = 50;
37     constexpr uint32_t DEFAULT_FRAME_COUNT = 50;
38 }
39 
40 static BufferFlushConfig g_flushConfig = {
41     .damage = {
42         .x = 0,
43         .y = 0,
44         .w = DEFAULT_WIDTH,
45         .h = DEFAULT_HEIGHT
46     },
47     .timestamp = 0
48 };
49 
50 static BufferRequestConfig g_request = {
51     .width = DEFAULT_WIDTH,
52     .height = DEFAULT_HEIGHT,
53     .strideAlignment = STRIDE_ALIGN,
54     .format = PIXEL_FMT_YCRCB_420_SP,
55     .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
56     .timeout = 0
57 };
58 
RunCase(bool enableProp)59 void VEncDemo::RunCase(bool enableProp)
60 {
61     DEMO_CHECK_AND_RETURN_LOG(CreateVenc() == MSERR_OK, "Fatal: CreateVenc fail");
62 
63     Format format;
64     format.PutIntValue("width", DEFAULT_WIDTH);
65     format.PutIntValue("height", DEFAULT_HEIGHT);
66     format.PutIntValue("pixel_format", NV21);
67     format.PutIntValue("frame_rate", DEFAULT_FRAME_RATE);
68     DEMO_CHECK_AND_RETURN_LOG(Configure(format) == MSERR_OK, "Fatal: Configure fail");
69 
70     surface_ = GetVideoSurface();
71     DEMO_CHECK_AND_RETURN_LOG(surface_ != nullptr, "Fatal: GetVideoSurface fail");
72 
73     DEMO_CHECK_AND_RETURN_LOG(Prepare() == MSERR_OK, "Fatal: Prepare fail");
74     DEMO_CHECK_AND_RETURN_LOG(Start() == MSERR_OK, "Fatal: Start fail");
75 
76     if (enableProp) {
77         DEMO_CHECK_AND_RETURN_LOG(SetParameter(0, DEFAULT_FRAME_RATE, REPEAT_FRAME_AFTER_MS) == MSERR_OK,
78             "Fatal: SetParameter fail");
79         GenerateData(DEFAULT_FRAME_COUNT, FAST_PRODUCER);
80         GenerateData(DEFAULT_FRAME_COUNT, SLOW_PRODUCER);
81         DEMO_CHECK_AND_RETURN_LOG(SetParameter(1, 0, 0) == MSERR_OK, "Fatal: Set suspend fail");
82         GenerateData(DEFAULT_FRAME_COUNT, DEFAULT_FRAME_RATE);
83     } else {
84         GenerateData(DEFAULT_FRAME_COUNT, DEFAULT_FRAME_RATE);
85     }
86 
87     DEMO_CHECK_AND_RETURN_LOG(Stop() == MSERR_OK, "Fatal: Stop fail");
88     DEMO_CHECK_AND_RETURN_LOG(Release() == MSERR_OK, "Fatal: Release fail");
89 }
90 
GenerateData(uint32_t count,uint32_t fps)91 void VEncDemo::GenerateData(uint32_t count, uint32_t fps)
92 {
93     if (fps == 0) {
94         return;
95     }
96     constexpr uint32_t secToUs = 1000000;
97     uint32_t intervalUs = secToUs / fps;
98     uint32_t frameCount = 0;
99     while (frameCount <= count) {
100         usleep(intervalUs);
101 
102         sptr<OHOS::SurfaceBuffer> buffer = nullptr;
103         int32_t fence = -1;
104         if (surface_->RequestBuffer(buffer, fence, g_request) != SURFACE_ERROR_OK) {
105             continue;
106         }
107         DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: SurfaceBuffer is nullptr");
108 
109         sptr<SyncFence> tempFence = new SyncFence(fence);
110         tempFence->Wait(100); // 100ms
111 
112         auto addr = static_cast<uint8_t *>(buffer->GetVirAddr());
113         if (addr == nullptr) {
114             cout << "Fatal: SurfaceBuffer address is nullptr" << endl;
115             (void)surface_->CancelBuffer(buffer);
116             break;
117         }
118         DEMO_CHECK_AND_BREAK_LOG(memset_s(addr, buffer->GetSize(), 0xFF, YUV_BUFFER_SIZE) == EOK, "Fatal");
119 
120         const sptr<OHOS::BufferExtraData>& extraData = buffer->GetExtraData();
121         DEMO_CHECK_AND_BREAK_LOG(extraData != nullptr, "Fatal: SurfaceBuffer is nullptr");
122         (void)extraData->ExtraSet("timeStamp", timestampNs_);
123         timestampNs_ += static_cast<int64_t>(intervalUs * 1000); // us to ns
124 
125         (void)surface_->FlushBuffer(buffer, -1, g_flushConfig);
126         cout << "Generate input buffer success, timestamp: " << timestampNs_ << endl;
127         frameCount++;
128     }
129 }
130 
CreateVenc()131 int32_t VEncDemo::CreateVenc()
132 {
133     venc_ = VideoEncoderFactory::CreateByMime("video/mp4v-es");
134     DEMO_CHECK_AND_RETURN_RET_LOG(venc_ != nullptr, MSERR_UNKNOWN, "Fatal: CreateByMime fail");
135 
136     signal_ = make_shared<VEncSignal>();
137     DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
138 
139     cb_ = make_shared<VEncDemoCallback>(signal_);
140     DEMO_CHECK_AND_RETURN_RET_LOG(cb_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
141     DEMO_CHECK_AND_RETURN_RET_LOG(venc_->SetCallback(cb_) == MSERR_OK, MSERR_UNKNOWN, "Fatal: SetCallback fail");
142 
143     return MSERR_OK;
144 }
145 
Configure(const Format & format)146 int32_t VEncDemo::Configure(const Format &format)
147 {
148     return venc_->Configure(format);
149 }
150 
Prepare()151 int32_t VEncDemo::Prepare()
152 {
153     return venc_->Prepare();
154 }
155 
Start()156 int32_t VEncDemo::Start()
157 {
158     isRunning_.store(true);
159     readLoop_ = make_unique<thread>(&VEncDemo::LoopFunc, this);
160     DEMO_CHECK_AND_RETURN_RET_LOG(readLoop_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
161     return venc_->Start();
162 }
163 
SetParameter(int32_t suspend,int32_t maxFps,int32_t repeatMs)164 int32_t VEncDemo::SetParameter(int32_t suspend, int32_t maxFps, int32_t repeatMs)
165 {
166     Format format;
167     format.PutIntValue("suspend_input_surface", suspend);
168     format.PutIntValue("max_encoder_fps", maxFps);
169     format.PutIntValue("repeat_frame_after", repeatMs);
170     return venc_->SetParameter(format);
171 }
172 
Stop()173 int32_t VEncDemo::Stop()
174 {
175     isRunning_.store(false);
176 
177     if (readLoop_ != nullptr && readLoop_->joinable()) {
178         unique_lock<mutex> queueLock(signal_->mutex_);
179         signal_->bufferQueue_.push(0);
180         signal_->cond_.notify_all();
181         queueLock.unlock();
182         readLoop_->join();
183         readLoop_.reset();
184     }
185 
186     return venc_->Stop();
187 }
188 
Flush()189 int32_t VEncDemo::Flush()
190 {
191     return venc_->Flush();
192 }
193 
Reset()194 int32_t VEncDemo::Reset()
195 {
196     return venc_->Reset();
197 }
198 
Release()199 int32_t VEncDemo::Release()
200 {
201     return venc_->Release();
202 }
203 
GetVideoSurface()204 sptr<Surface> VEncDemo::GetVideoSurface()
205 {
206     return venc_->CreateInputSurface();
207 }
208 
LoopFunc()209 void VEncDemo::LoopFunc()
210 {
211     while (true) {
212         if (!isRunning_.load()) {
213             break;
214         }
215 
216         unique_lock<mutex> lock(signal_->mutex_);
217         signal_->cond_.wait(lock, [this](){ return signal_->bufferQueue_.size() > 0; });
218 
219         if (!isRunning_.load()) {
220             break;
221         }
222 
223         uint32_t index = signal_->bufferQueue_.front();
224         auto buffer = venc_->GetOutputBuffer(index);
225         if (!buffer) {
226             cout << "Fatal: GetOutputBuffer fail, exit" << endl;
227             break;
228         }
229 
230         if (venc_->ReleaseOutputBuffer(index) != MSERR_OK) {
231             cout << "Fatal: ReleaseOutputBuffer fail, exit" << endl;
232             break;
233         }
234         signal_->bufferQueue_.pop();
235     }
236 }
237 
VEncDemoCallback(shared_ptr<VEncSignal> signal)238 VEncDemoCallback::VEncDemoCallback(shared_ptr<VEncSignal> signal)
239     : signal_(signal)
240 {
241 }
242 
OnError(AVCodecErrorType errorType,int32_t errorCode)243 void VEncDemoCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
244 {
245     cout << "Error received, errorType:" << errorType << " errorCode:" << errorCode << endl;
246 }
247 
OnOutputFormatChanged(const Format & format)248 void VEncDemoCallback::OnOutputFormatChanged(const Format &format)
249 {
250     cout << "OnOutputFormatChanged received" << endl;
251 }
252 
OnInputBufferAvailable(uint32_t index)253 void VEncDemoCallback::OnInputBufferAvailable(uint32_t index)
254 {
255     (void)index;
256 }
257 
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)258 void VEncDemoCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
259 {
260     cout << "OnOutputBufferAvailable received, index:" << index << " timestamp:" << info.presentationTimeUs << endl;
261     unique_lock<mutex> lock(signal_->mutex_);
262     signal_->bufferQueue_.push(index);
263     signal_->cond_.notify_all();
264 }
265