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 "serverdec_sample.h"
19 #include <iostream>
20 #include <chrono>
21 using namespace OHOS;
22 using namespace OHOS::HDI;
23 using namespace OHOS::Media;
24 using namespace OHOS::MediaAVCodec;
25 using namespace std;
26 namespace {
27
28 } // namespace
29
OnError(AVCodecErrorType errorType,int32_t errorCode)30 void VDecServerSample::CallBack::OnError(AVCodecErrorType errorType, int32_t errorCode)
31 {
32 cout << "--OnError--" << endl;
33 tester->isRunning_.store(false);
34 tester->signal_->inCond_.notify_all();
35 }
36
OnOutputFormatChanged(const Format & format)37 void VDecServerSample::CallBack::OnOutputFormatChanged(const Format &format)
38 {
39 tester->GetOutputFormat();
40 }
41
OnInputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)42 void VDecServerSample::CallBack::OnInputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
43 {
44 unique_lock<mutex> lock(tester->signal_->inMutex_);
45 tester->signal_->inIdxQueue_.push(index);
46 tester->signal_->inBufferQueue_.push(buffer);
47 tester->signal_->inCond_.notify_all();
48 }
49
OnOutputBufferAvailable(uint32_t index,std::shared_ptr<AVBuffer> buffer)50 void VDecServerSample::CallBack::OnOutputBufferAvailable(uint32_t index, std::shared_ptr<AVBuffer> buffer)
51 {
52 tester->codec_->ReleaseOutputBuffer(index);
53 }
54
~VDecServerSample()55 VDecServerSample::~VDecServerSample()
56 {
57 if (codec_ != nullptr) {
58 SetParameter();
59 codec_->Stop();
60 codec_->Release();
61 codec_ = nullptr;
62 }
63 if (signal_ != nullptr) {
64 delete signal_;
65 signal_ = nullptr;
66 }
67 }
68
SetParameter()69 int32_t VDecServerSample::SetParameter()
70 {
71 Format fmt;
72 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, defaultWidth);
73 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, defaultHeight);
74 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, defaultPixelFormat);
75 fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, defaultFrameRate);
76 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, 0);
77 return codec_->SetParameter(fmt);
78 }
79
ConfigServerDecoder()80 int32_t VDecServerSample::ConfigServerDecoder()
81 {
82 Format fmt;
83 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_WIDTH, defaultWidth);
84 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_HEIGHT, defaultHeight);
85 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_PIXEL_FORMAT, defaultPixelFormat);
86 fmt.PutDoubleValue(MediaDescriptionKey::MD_KEY_FRAME_RATE, defaultFrameRate);
87 fmt.PutIntValue(MediaDescriptionKey::MD_KEY_ROTATION_ANGLE, 0);
88 return codec_->Configure(fmt);
89 }
90
SetCallback()91 int32_t VDecServerSample::SetCallback()
92 {
93 shared_ptr<CallBack> cb = make_shared<CallBack>(this);
94 return codec_->SetCallback(cb);
95 }
96
RunVideoServerDecoder()97 void VDecServerSample::RunVideoServerDecoder()
98 {
99 codec_ = HCodec::Create("OMX.hisi.video.decoder.hevc");
100 if (codec_ == nullptr) {
101 cout << "Create failed" << endl;
102 return;
103 }
104 Media::Meta meta{};
105 int32_t err = codec_->Init(meta);
106 err = ConfigServerDecoder();
107 if (err != AVCS_ERR_OK) {
108 cout << "ConfigServerDecoder failed" << endl;
109 return;
110 }
111 signal_ = new VDecSignal();
112 if (signal_ == nullptr) {
113 cout << "Failed to new VDecSignal" << endl;
114 return;
115 }
116 err = SetCallback();
117 if (err != AVCS_ERR_OK) {
118 cout << "SetCallback failed" << endl;
119 return;
120 }
121 err = codec_->Start();
122 if (err != AVCS_ERR_OK) {
123 cout << "Start failed" << endl;
124 return;
125 }
126 isRunning_.store(true);
127 inputLoop_ = make_unique<thread>(&VDecServerSample::InputFunc, this);
128 if (inputLoop_ == nullptr) {
129 cout << "Failed to create input loop" << endl;
130 isRunning_.store(false);
131 }
132 }
133
InputFunc()134 void VDecServerSample::InputFunc()
135 {
136 int32_t time = 1000;
137 while (sendFrameIndex < frameIndex) {
138 if (!isRunning_.load()) {
139 break;
140 }
141 unique_lock<mutex> lock(signal_->inMutex_);
142 signal_->inCond_.wait_for(lock, std::chrono::milliseconds(time), [this]() {
143 if (!isRunning_.load()) {
144 cout << "quit signal" << endl;
145 return true;
146 }
147 return signal_->inIdxQueue_.size() > 0;
148 });
149 if (!isRunning_.load() || signal_->inIdxQueue_.size() == 0) {
150 break;
151 }
152 uint32_t index = signal_->inIdxQueue_.front();
153 auto buffer = signal_->inBufferQueue_.front();
154 signal_->inIdxQueue_.pop();
155 signal_->inBufferQueue_.pop();
156 lock.unlock();
157 if (buffer->memory_ == nullptr) {
158 isRunning_.store(false);
159 break;
160 }
161 uint8_t *bufferAddr = buffer->memory_->GetAddr();
162 if (memcpy_s(bufferAddr, buffer->memory_->GetCapacity(), fuzzData, fuzzSize) != EOK) {
163 break;
164 }
165 int32_t err = codec_->QueueInputBuffer(index);
166 if (err != AVCS_ERR_OK) {
167 cout << "QueueInputBuffer fail" << endl;
168 break;
169 }
170 sendFrameIndex++;
171 }
172 }
173
WaitForEos()174 void VDecServerSample::WaitForEos()
175 {
176 if (inputLoop_ && inputLoop_->joinable()) {
177 inputLoop_->join();
178 }
179 }
180
GetOutputFormat()181 void VDecServerSample::GetOutputFormat()
182 {
183 Format fmt;
184 int32_t err = codec_->GetOutputFormat(fmt);
185 if (err != AVCS_ERR_OK) {
186 cout << "GetOutputFormat fail" << endl;
187 isRunning_.store(false);
188 signal_->inCond_.notify_all();
189 }
190 }
191
Flush()192 void VDecServerSample::Flush()
193 {
194 int32_t err = codec_->Flush();
195 if (err != AVCS_ERR_OK) {
196 cout << "Flush fail" << endl;
197 isRunning_.store(false);
198 signal_->inCond_.notify_all();
199 }
200 }
201
Reset()202 void VDecServerSample::Reset()
203 {
204 int32_t err = codec_->Reset();
205 if (err != AVCS_ERR_OK) {
206 cout << "Reset fail" << endl;
207 isRunning_.store(false);
208 signal_->inCond_.notify_all();
209 }
210 }