1 /*
2 * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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 "video_sink_decoder.h"
17 #include <securec.h>
18 #include "avcodec_codec_name.h"
19 #include "avcodec_errors.h"
20 #include "avcodec_mime_type.h"
21 #include "buffer/avsharedmemory.h"
22 #include "common/common_macro.h"
23 #include "common/media_log.h"
24 #include "configuration/include/config.h"
25 #include "utils/utils.h"
26
27 namespace OHOS {
28 namespace Sharing {
VideoSinkDecoder(uint32_t controlId, bool forceSWDecoder)29 VideoSinkDecoder::VideoSinkDecoder(uint32_t controlId, bool forceSWDecoder)
30 {
31 SHARING_LOGD("trace.");
32 controlId_ = controlId;
33 forceSWDecoder_ = forceSWDecoder;
34 }
35
~VideoSinkDecoder()36 VideoSinkDecoder::~VideoSinkDecoder()
37 {
38 SHARING_LOGD("trace.");
39 Release();
40 }
41
Init(CodecId videoCodecId)42 bool VideoSinkDecoder::Init(CodecId videoCodecId)
43 {
44 SHARING_LOGD("trace.");
45 videoCodecId_ = videoCodecId;
46 return InitDecoder() && SetVideoCallback();
47 }
48
InitDecoder()49 bool VideoSinkDecoder::InitDecoder()
50 {
51 SHARING_LOGD("trace.");
52 if (videoDecoder_ != nullptr) {
53 SHARING_LOGD("start video decoder already init.");
54 return true;
55 }
56 if (forceSWDecoder_) {
57 SHARING_LOGD("begin create software video decoder.");
58 videoDecoder_ = OHOS::MediaAVCodec::VideoDecoderFactory::CreateByName(
59 (MediaAVCodec::AVCodecCodecName::VIDEO_DECODER_AVC_NAME).data());
60 } else {
61 SHARING_LOGD("begin create hardware video decoder.");
62 videoDecoder_ = OHOS::MediaAVCodec::VideoDecoderFactory::CreateByMime(
63 (MediaAVCodec::AVCodecMimeType::MEDIA_MIMETYPE_VIDEO_AVC).data());
64 }
65
66 if (videoDecoder_ == nullptr) {
67 SHARING_LOGE("create video decoder failed!");
68 return false;
69 }
70 SHARING_LOGD("init video decoder success.");
71 return true;
72 }
73
SetDecoderFormat(const VideoTrack &track)74 bool VideoSinkDecoder::SetDecoderFormat(const VideoTrack &track)
75 {
76 SHARING_LOGD("trace.");
77 RETURN_FALSE_IF_NULL(videoDecoder_);
78 videoTrack_ = track;
79 MediaAVCodec::Format format;
80 format.PutIntValue("width", track.width);
81 format.PutIntValue("height", track.height);
82
83 auto ret = videoDecoder_->Configure(format);
84 if (ret != MediaAVCodec::AVCS_ERR_OK) {
85 SHARING_LOGE("configure decoder format param failed!");
86 return false;
87 }
88 SHARING_LOGD("configure video decoder format success.");
89 return true;
90 }
91
SetVideoCallback()92 bool VideoSinkDecoder::SetVideoCallback()
93 {
94 SHARING_LOGD("trace.");
95 RETURN_FALSE_IF_NULL(videoDecoder_);
96 auto ret = videoDecoder_->SetCallback(shared_from_this());
97 if (ret != MediaAVCodec::AVCS_ERR_OK) {
98 SHARING_LOGE("set video decoder callback failed!");
99 return false;
100 }
101 SHARING_LOGD("set video decoder callback success.");
102 return true;
103 }
104
SetVideoDecoderListener(VideoSinkDecoderListener::Ptr listener)105 void VideoSinkDecoder::SetVideoDecoderListener(VideoSinkDecoderListener::Ptr listener)
106 {
107 SHARING_LOGD("trace.");
108 videoDecoderListener_ = listener;
109 }
110
Start()111 bool VideoSinkDecoder::Start()
112 {
113 SHARING_LOGD("trace.");
114 if (isRunning_) {
115 MEDIA_LOGD("decoder is running!");
116 return true;
117 }
118 if (StartDecoder()) {
119 isRunning_ = true;
120 return true;
121 } else {
122 return false;
123 }
124 }
125
Stop()126 void VideoSinkDecoder::Stop()
127 {
128 SHARING_LOGD("trace %{public}p.", this);
129 if (!isRunning_) {
130 SHARING_LOGD("decoder is not running.");
131 return;
132 }
133
134 if (StopDecoder()) {
135 SHARING_LOGD("stop success.");
136 isRunning_ = false;
137 std::lock_guard<std::mutex> lock(inMutex_);
138 std::queue<int32_t> temp;
139 std::swap(temp, inQueue_);
140 }
141 }
142
Release()143 void VideoSinkDecoder::Release()
144 {
145 SHARING_LOGD("trace.");
146 if (videoDecoder_ != nullptr) {
147 videoDecoder_->Release();
148 videoDecoder_.reset();
149 }
150 }
151
StartDecoder()152 bool VideoSinkDecoder::StartDecoder()
153 {
154 SHARING_LOGD("trace.");
155 RETURN_FALSE_IF_NULL(videoDecoder_);
156 auto ret = videoDecoder_->Prepare();
157 if (ret != MediaAVCodec::AVCS_ERR_OK) {
158 SHARING_LOGE("prepare decoder failed!");
159 return false;
160 }
161
162 ret = videoDecoder_->Start();
163 if (ret != MediaAVCodec::AVCS_ERR_OK) {
164 SHARING_LOGE("start decoder failed!");
165 return false;
166 }
167 SHARING_LOGD("start video decoder success.");
168 return true;
169 }
170
StopDecoder()171 bool VideoSinkDecoder::StopDecoder()
172 {
173 SHARING_LOGD("trace.");
174 if (videoDecoder_ == nullptr) {
175 SHARING_LOGD("StopDecoder no need.");
176 return true;
177 }
178
179 SHARING_LOGD("before Stop.");
180 auto ret = videoDecoder_->Stop();
181 if (ret != MediaAVCodec::AVCS_ERR_OK) {
182 SHARING_LOGE("stop decoder failed!");
183 return false;
184 }
185
186 SHARING_LOGD("before Reset.");
187 ret = videoDecoder_->Reset();
188 if (ret != MediaAVCodec::AVCS_ERR_OK) {
189 SHARING_LOGE("Reset decoder failed!");
190 return false;
191 }
192
193 SHARING_LOGD("try set decoder formt for next play.");
194 if (SetDecoderFormat(videoTrack_)) {
195 if (enableSurface_ && (nullptr != surface_)) {
196 videoDecoder_->SetOutputSurface(surface_);
197 }
198 } else {
199 SHARING_LOGE("set decoder formt failed!");
200 return false;
201 }
202
203 SHARING_LOGD("StopDecoder success.");
204 return true;
205 }
206
DecodeVideoData(const char *data, int32_t size)207 bool VideoSinkDecoder::DecodeVideoData(const char *data, int32_t size)
208 {
209 MEDIA_LOGD("decode data controlId: %{public}u.", controlId_);
210 RETURN_FALSE_IF_NULL(videoDecoder_);
211
212 std::unique_lock<std::mutex> lock(inMutex_);
213 auto inputIndex = inQueue_.front();
214 MEDIA_LOGD("inQueue front: %{public}d.", inputIndex);
215 auto inputBuffer = inBufferQueue_.front();
216 if (inputBuffer == nullptr) {
217 MEDIA_LOGE("GetInputBuffer failed controlId: %{public}u.", controlId_);
218 return false;
219 }
220 lock.unlock();
221 MEDIA_LOGD("try copy data dest size: %{public}d data size: %{public}d.", inputBuffer->GetSize(), size);
222
223 auto ret = memcpy_s(inputBuffer->GetBase(), inputBuffer->GetSize(), data, size);
224 if (ret != EOK) {
225 MEDIA_LOGE("copy data failed controlId: %{public}u.", controlId_);
226 return false;
227 }
228
229 MediaAVCodec::AVCodecBufferInfo bufferInfo;
230 bufferInfo.presentationTimeUs = 0;
231 bufferInfo.size = size;
232 bufferInfo.offset = 0;
233
234 auto p = data;
235 p = *(p + 2) == 0x01 ? p + 3 : p + 4; // 2: offset, 3: offset, 4: offset
236 if ((p[0] & 0x1f) == 0x06 || (p[0] & 0x1f) == 0x07 || (p[0] & 0x1f) == 0x08) {
237 MEDIA_LOGD("media flag codec data controlId: %{public}u.", controlId_);
238 ret = videoDecoder_->QueueInputBuffer(inputIndex, bufferInfo, MediaAVCodec::AVCODEC_BUFFER_FLAG_CODEC_DATA);
239 } else {
240 MEDIA_LOGD("media flag none controlId: %{public}u.", controlId_);
241 ret = videoDecoder_->QueueInputBuffer(inputIndex, bufferInfo, MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE);
242 }
243
244 if (ret != MediaAVCodec::AVCS_ERR_OK) {
245 MEDIA_LOGE("QueueInputBuffer failed error: %{public}d controlId: %{public}u.", ret, controlId_);
246 return false;
247 }
248
249 lock.lock();
250 inQueue_.pop();
251 inBufferQueue_.pop();
252
253 MEDIA_LOGD("process data success controlId: %{public}u.", controlId_);
254 return true;
255 }
256
OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)257 void VideoSinkDecoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
258 {
259 SHARING_LOGE("controlId: %{public}u.", controlId_);
260 auto listener = videoDecoderListener_.lock();
261 if (listener) {
262 listener->OnError(errorCode);
263 }
264 }
265
OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info, MediaAVCodec::AVCodecBufferFlag flag, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)266 void VideoSinkDecoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info,
267 MediaAVCodec::AVCodecBufferFlag flag, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
268 {
269 MEDIA_LOGD("OnOutputBufferAvailable index: %{public}u controlId: %{public}u.", index, controlId_);
270 if (!videoDecoder_) {
271 MEDIA_LOGW("decoder is null!");
272 return;
273 }
274 if (forceSWDecoder_) {
275 MEDIA_LOGD("forceSWDecoder_ is true.");
276 }
277 if (forceSWDecoder_) {
278 if (buffer == nullptr || buffer->GetBase() == nullptr) {
279 MEDIA_LOGW("OnOutputBufferAvailable buffer null!");
280 return;
281 }
282 size_t dataSize = static_cast<size_t>(info.size);
283 SHARING_LOGD("OnOutputBufferAvailable size: %{public}zu.", dataSize);
284 auto dataBuf = std::make_shared<DataBuffer>(dataSize);
285 if (dataBuf != nullptr) {
286 dataBuf->PushData((char *)buffer->GetBase(), dataSize);
287 auto listerner = videoDecoderListener_.lock();
288 if (listerner) {
289 listerner->OnVideoDataDecoded(dataBuf);
290 }
291 } else {
292 MEDIA_LOGE("get databuffer failed!");
293 }
294 }
295
296 if (videoDecoder_->ReleaseOutputBuffer(index, true) != MediaAVCodec::AVCS_ERR_OK) {
297 MEDIA_LOGW("ReleaseOutputBuffer failed!");
298 }
299 }
300
OnInputBufferAvailable(uint32_t index, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)301 void VideoSinkDecoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
302 {
303 MEDIA_LOGD("OnInputBufferAvailable index: %{public}u controlId: %{public}u.", index, controlId_);
304 {
305 std::lock_guard<std::mutex> lock(inMutex_);
306 inQueue_.push(index);
307 inBufferQueue_.push(buffer);
308 }
309 inCond_.notify_all();
310 MEDIA_LOGD("OnInputBufferAvailable notify.");
311 }
312
OnOutputFormatChanged(const MediaAVCodec::Format &format)313 void VideoSinkDecoder::OnOutputFormatChanged(const MediaAVCodec::Format &format)
314 {
315 SHARING_LOGD("controlId: %{public}u.", controlId_);
316 }
317
SetSurface(sptr<Surface> surface)318 bool VideoSinkDecoder::SetSurface(sptr<Surface> surface)
319 {
320 SHARING_LOGD("trace.");
321 RETURN_FALSE_IF_NULL(surface);
322 RETURN_FALSE_IF_NULL(videoDecoder_);
323 if (isRunning_) {
324 SHARING_LOGW("decoder is running, cann't set surface!");
325 return false;
326 }
327
328 auto ret = videoDecoder_->SetOutputSurface(surface);
329 if (ret != MediaAVCodec::AVCS_ERR_OK) {
330 SHARING_LOGE("decoder set surface error, ret code: %{public}u.", ret);
331 return false;
332 }
333 enableSurface_ = true;
334 surface_ = surface;
335 return true;
336 }
337
338 } // namespace Sharing
339 } // namespace OHOS