• 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_vdec_demo.h"
17 #include <iostream>
18 #include <unistd.h>
19 #include "securec.h"
20 #include "demo_log.h"
21 #include "media_errors.h"
22 #include "ui/rs_surface_node.h"
23 #include "window.h"
24 #include "window_option.h"
25 
26 using namespace OHOS;
27 using namespace OHOS::Media;
28 using namespace std;
29 namespace {
30     constexpr uint32_t DEFAULT_WIDTH = 480;
31     constexpr uint32_t DEFAULT_HEIGHT = 360;
32     constexpr uint32_t DEFAULT_FRAME_RATE = 30;
33     constexpr uint32_t MAX_INPUT_BUFFER_SIZE = 30000;
34     constexpr uint32_t FRAME_DURATION_US = 33000;
35     constexpr uint32_t DEFAULT_FRAME_COUNT = 1;
36 }
37 
RunCase()38 void VDecDemo::RunCase()
39 {
40     DEMO_CHECK_AND_RETURN_LOG(CreateVdec() == MSERR_OK, "Fatal: CreateVdec fail");
41 
42     Format format;
43     format.PutIntValue("width", DEFAULT_WIDTH);
44     format.PutIntValue("height", DEFAULT_HEIGHT);
45     format.PutIntValue("pixel_format", NV21);
46     format.PutIntValue("frame_rate", DEFAULT_FRAME_RATE);
47     format.PutIntValue("max_input_size", MAX_INPUT_BUFFER_SIZE);
48     DEMO_CHECK_AND_RETURN_LOG(Configure(format) == MSERR_OK, "Fatal: Configure fail");
49 
50     DEMO_CHECK_AND_RETURN_LOG(SetSurface() == MSERR_OK, "Fatal: SetSurface fail");
51     DEMO_CHECK_AND_RETURN_LOG(Prepare() == MSERR_OK, "Fatal: Prepare fail");
52     DEMO_CHECK_AND_RETURN_LOG(Start() == MSERR_OK, "Fatal: Start fail");
53     sleep(3); // start run 3s
54     DEMO_CHECK_AND_RETURN_LOG(Stop() == MSERR_OK, "Fatal: Stop fail");
55     DEMO_CHECK_AND_RETURN_LOG(Release() == MSERR_OK, "Fatal: Release fail");
56 }
57 
CreateVdec()58 int32_t VDecDemo::CreateVdec()
59 {
60     vdec_ = VideoDecoderFactory::CreateByMime("video/avc");
61     DEMO_CHECK_AND_RETURN_RET_LOG(vdec_ != nullptr, MSERR_UNKNOWN, "Fatal: CreateByMime fail");
62 
63     signal_ = make_shared<VDecSignal>();
64     DEMO_CHECK_AND_RETURN_RET_LOG(signal_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
65 
66     cb_ = make_unique<VDecDemoCallback>(signal_);
67     DEMO_CHECK_AND_RETURN_RET_LOG(cb_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
68     DEMO_CHECK_AND_RETURN_RET_LOG(vdec_->SetCallback(cb_) == MSERR_OK, MSERR_UNKNOWN, "Fatal: SetCallback fail");
69 
70     return MSERR_OK;
71 }
72 
Configure(const Format & format)73 int32_t VDecDemo::Configure(const Format &format)
74 {
75     return vdec_->Configure(format);
76 }
77 
Prepare()78 int32_t VDecDemo::Prepare()
79 {
80     return vdec_->Prepare();
81 }
82 
Start()83 int32_t VDecDemo::Start()
84 {
85     isRunning_.store(true);
86 
87     testFile_ = std::make_unique<std::ifstream>();
88     DEMO_CHECK_AND_RETURN_RET_LOG(testFile_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
89     testFile_->open("/data/media/video.es", std::ios::in | std::ios::binary);
90 
91     inputLoop_ = make_unique<thread>(&VDecDemo::InputFunc, this);
92     DEMO_CHECK_AND_RETURN_RET_LOG(inputLoop_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
93 
94     outputLoop_ = make_unique<thread>(&VDecDemo::OutputFunc, this);
95     DEMO_CHECK_AND_RETURN_RET_LOG(outputLoop_ != nullptr, MSERR_UNKNOWN, "Fatal: No memory");
96 
97     return vdec_->Start();
98 }
99 
Stop()100 int32_t VDecDemo::Stop()
101 {
102     isRunning_.store(false);
103 
104     if (inputLoop_ != nullptr && inputLoop_->joinable()) {
105         unique_lock<mutex> lock(signal_->inMutex_);
106         signal_->inQueue_.push(0);
107         signal_->inCond_.notify_all();
108         lock.unlock();
109         inputLoop_->join();
110         inputLoop_.reset();
111     }
112 
113     if (outputLoop_ != nullptr && outputLoop_->joinable()) {
114         unique_lock<mutex> lock(signal_->outMutex_);
115         signal_->outQueue_.push(0);
116         signal_->outCond_.notify_all();
117         lock.unlock();
118         outputLoop_->join();
119         outputLoop_.reset();
120     }
121 
122     return vdec_->Stop();
123 }
124 
Flush()125 int32_t VDecDemo::Flush()
126 {
127     return vdec_->Flush();
128 }
129 
Reset()130 int32_t VDecDemo::Reset()
131 {
132     return vdec_->Reset();
133 }
134 
Release()135 int32_t VDecDemo::Release()
136 {
137     return vdec_->Release();
138 }
139 
SetSurface()140 int32_t VDecDemo::SetSurface()
141 {
142     sptr<Rosen::WindowOption> option = new Rosen::WindowOption();
143     option->SetWindowRect({0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT});
144     option->SetWindowType(Rosen::WindowType::WINDOW_TYPE_APP_LAUNCHING);
145     option->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING);
146     sptr<Rosen::Window> window = Rosen::Window::Create("avcodec video decoder window", option);
147     DEMO_CHECK_AND_RETURN_RET_LOG(window != nullptr && window->GetSurfaceNode() != nullptr, MSERR_UNKNOWN, "Fatal");
148 
149     sptr<Surface> surface = window->GetSurfaceNode()->GetSurface();
150     window->Show();
151     DEMO_CHECK_AND_RETURN_RET_LOG(surface != nullptr, MSERR_UNKNOWN, "Fatal: get surface fail");
152     return vdec_->SetOutputSurface(surface);
153 }
154 
InputFunc()155 void VDecDemo::InputFunc()
156 {
157     while (true) {
158         if (!isRunning_.load()) {
159             break;
160         }
161 
162         unique_lock<mutex> lock(signal_->inMutex_);
163         signal_->inCond_.wait(lock, [this](){ return signal_->inQueue_.size() > 0; });
164 
165         if (!isRunning_.load()) {
166             break;
167         }
168 
169         uint32_t index = signal_->inQueue_.front();
170         auto buffer = vdec_->GetInputBuffer(index);
171         DEMO_CHECK_AND_BREAK_LOG(buffer != nullptr, "Fatal: GetInputBuffer fail");
172         DEMO_CHECK_AND_BREAK_LOG(testFile_ != nullptr && testFile_->is_open(), "Fatal: open file fail");
173 
174         constexpr uint32_t bufferSize = 0; // replace with the actual size
175         char *fileBuffer = static_cast<char *>(malloc(sizeof(char) * bufferSize + 1));
176         DEMO_CHECK_AND_BREAK_LOG(fileBuffer != nullptr, "Fatal: malloc fail");
177 
178         (void)testFile_->read(fileBuffer, bufferSize);
179         if (memcpy_s(buffer->GetBase(), buffer->GetSize(), fileBuffer, bufferSize) != EOK) {
180             free(fileBuffer);
181             cout << "Fatal: memcpy fail" << endl;
182             break;
183         }
184 
185         AVCodecBufferInfo info;
186         info.size = bufferSize;
187         info.offset = 0;
188         info.presentationTimeUs = timeStamp_;
189 
190         int32_t ret = MSERR_OK;
191         if (isFirstFrame_) {
192             ret = vdec_->QueueInputBuffer(index, info, AVCODEC_BUFFER_FLAG_CODEC_DATA);
193             isFirstFrame_ = false;
194         } else {
195             ret = vdec_->QueueInputBuffer(index, info, AVCODEC_BUFFER_FLAG_NONE);
196         }
197 
198         free(fileBuffer);
199         timeStamp_ += FRAME_DURATION_US;
200         signal_->inQueue_.pop();
201 
202         frameCount_++;
203         if (frameCount_ == DEFAULT_FRAME_COUNT) {
204             cout << "Finish decode, exit" << endl;
205             break;
206         }
207 
208         if (ret != MSERR_OK) {
209             cout << "Fatal error, exit" << endl;
210             break;
211         }
212     }
213 }
214 
OutputFunc()215 void VDecDemo::OutputFunc()
216 {
217     while (true) {
218         if (!isRunning_.load()) {
219             break;
220         }
221 
222         unique_lock<mutex> lock(signal_->outMutex_);
223         signal_->outCond_.wait(lock, [this](){ return signal_->outQueue_.size() > 0; });
224 
225         if (!isRunning_.load()) {
226             break;
227         }
228 
229         uint32_t index = signal_->outQueue_.front();
230         if (vdec_->ReleaseOutputBuffer(index, true) != MSERR_OK) {
231             cout << "Fatal: ReleaseOutputBuffer fail" << endl;
232             break;
233         }
234 
235         signal_->outQueue_.pop();
236     }
237 }
238 
VDecDemoCallback(shared_ptr<VDecSignal> signal)239 VDecDemoCallback::VDecDemoCallback(shared_ptr<VDecSignal> signal)
240     : signal_(signal)
241 {
242 }
243 
OnError(AVCodecErrorType errorType,int32_t errorCode)244 void VDecDemoCallback::OnError(AVCodecErrorType errorType, int32_t errorCode)
245 {
246     cout << "Error received, errorType:" << errorType << " errorCode:" << errorCode << endl;
247 }
248 
OnOutputFormatChanged(const Format & format)249 void VDecDemoCallback::OnOutputFormatChanged(const Format &format)
250 {
251     cout << "OnOutputFormatChanged received" << endl;
252 }
253 
OnInputBufferAvailable(uint32_t index)254 void VDecDemoCallback::OnInputBufferAvailable(uint32_t index)
255 {
256     cout << "OnInputBufferAvailable received, index:" << index << endl;
257     unique_lock<mutex> lock(signal_->inMutex_);
258     signal_->inQueue_.push(index);
259     signal_->inCond_.notify_all();
260 }
261 
OnOutputBufferAvailable(uint32_t index,AVCodecBufferInfo info,AVCodecBufferFlag flag)262 void VDecDemoCallback::OnOutputBufferAvailable(uint32_t index, AVCodecBufferInfo info, AVCodecBufferFlag flag)
263 {
264     cout << "OnOutputBufferAvailable received, index:" << index << endl;
265     unique_lock<mutex> lock(signal_->outMutex_);
266     signal_->outQueue_.push(index);
267     signal_->outCond_.notify_all();
268 }