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 format.PutDoubleValue("frame_rate", track.frameRate);
83
84 auto ret = videoDecoder_->Configure(format);
85 if (ret != MediaAVCodec::AVCS_ERR_OK) {
86 SHARING_LOGE("configure decoder format param failed!");
87 return false;
88 }
89 SHARING_LOGD("configure video decoder format success.");
90 return true;
91 }
92
SetVideoCallback()93 bool VideoSinkDecoder::SetVideoCallback()
94 {
95 SHARING_LOGD("trace.");
96 RETURN_FALSE_IF_NULL(videoDecoder_);
97 auto ret = videoDecoder_->SetCallback(shared_from_this());
98 if (ret != MediaAVCodec::AVCS_ERR_OK) {
99 SHARING_LOGE("set video decoder callback failed!");
100 return false;
101 }
102 SHARING_LOGD("set video decoder callback success.");
103 return true;
104 }
105
SetVideoDecoderListener(VideoSinkDecoderListener::Ptr listener)106 void VideoSinkDecoder::SetVideoDecoderListener(VideoSinkDecoderListener::Ptr listener)
107 {
108 SHARING_LOGD("trace.");
109 videoDecoderListener_ = listener;
110 }
111
Start()112 bool VideoSinkDecoder::Start()
113 {
114 SHARING_LOGD("trace.");
115 if (isRunning_) {
116 MEDIA_LOGD("decoder is running!");
117 return true;
118 }
119 if (StartDecoder()) {
120 isRunning_ = true;
121 return true;
122 } else {
123 return false;
124 }
125 }
126
Stop()127 void VideoSinkDecoder::Stop()
128 {
129 SHARING_LOGD("trace.");
130 if (!isRunning_) {
131 SHARING_LOGD("decoder is not running.");
132 return;
133 }
134
135 if (StopDecoder()) {
136 SHARING_LOGD("stop success.");
137 isRunning_ = false;
138 std::lock_guard<std::mutex> lock(inMutex_);
139 std::queue<int32_t> temp;
140 std::swap(temp, inQueue_);
141 }
142 }
143
Release()144 void VideoSinkDecoder::Release()
145 {
146 SHARING_LOGD("trace.");
147 if (videoDecoder_ != nullptr) {
148 videoDecoder_->Release();
149 videoDecoder_.reset();
150 }
151 }
152
StartDecoder()153 bool VideoSinkDecoder::StartDecoder()
154 {
155 SHARING_LOGD("trace.");
156 RETURN_FALSE_IF_NULL(videoDecoder_);
157 auto ret = videoDecoder_->Prepare();
158 if (ret != MediaAVCodec::AVCS_ERR_OK) {
159 SHARING_LOGE("prepare decoder failed!");
160 return false;
161 }
162
163 ret = videoDecoder_->Start();
164 if (ret != MediaAVCodec::AVCS_ERR_OK) {
165 SHARING_LOGE("start decoder failed!");
166 return false;
167 }
168 SHARING_LOGD("start video decoder success.");
169 return true;
170 }
171
StopDecoder()172 bool VideoSinkDecoder::StopDecoder()
173 {
174 SHARING_LOGD("trace.");
175 if (videoDecoder_ == nullptr) {
176 SHARING_LOGD("StopDecoder no need.");
177 return true;
178 }
179
180 SHARING_LOGD("before Stop.");
181 auto ret = videoDecoder_->Stop();
182 if (ret != MediaAVCodec::AVCS_ERR_OK) {
183 SHARING_LOGE("stop decoder failed!");
184 return false;
185 }
186
187 SHARING_LOGD("before Reset.");
188 ret = videoDecoder_->Reset();
189 if (ret != MediaAVCodec::AVCS_ERR_OK) {
190 SHARING_LOGE("Reset decoder failed!");
191 return false;
192 }
193
194 SHARING_LOGD("try set decoder formt for next play.");
195 if (SetDecoderFormat(videoTrack_)) {
196 if (enableSurface_ && (nullptr != surface_)) {
197 videoDecoder_->SetOutputSurface(surface_);
198 }
199 } else {
200 SHARING_LOGE("set decoder formt failed!");
201 return false;
202 }
203
204 SHARING_LOGD("StopDecoder success.");
205 return true;
206 }
207
DecodeVideoData(const char * data,int32_t size)208 bool VideoSinkDecoder::DecodeVideoData(const char *data, int32_t size)
209 {
210 MEDIA_LOGD("decode data controlId: %{public}u.", controlId_);
211 RETURN_FALSE_IF_NULL(videoDecoder_);
212
213 std::unique_lock<std::mutex> lock(inMutex_);
214 auto inputIndex = inQueue_.front();
215 MEDIA_LOGD("inQueue front: %{public}d.", inputIndex);
216 auto inputBuffer = inBufferQueue_.front();
217 if (inputBuffer == nullptr) {
218 MEDIA_LOGE("GetInputBuffer failed controlId: %{public}u.", controlId_);
219 return false;
220 }
221 lock.unlock();
222 MEDIA_LOGD("try copy data dest size: %{public}d data size: %{public}d.", inputBuffer->GetSize(), size);
223
224 auto ret = memcpy_s(inputBuffer->GetBase(), inputBuffer->GetSize(), data, size);
225 if (ret != EOK) {
226 MEDIA_LOGE("copy data failed controlId: %{public}u.", controlId_);
227 return false;
228 }
229
230 MediaAVCodec::AVCodecBufferInfo bufferInfo;
231 bufferInfo.presentationTimeUs = 0;
232 bufferInfo.size = size;
233 bufferInfo.offset = 0;
234
235 auto p = data;
236 p = *(p + 2) == 0x01 ? p + 3 : p + 4; // 2: offset, 3: offset, 4: offset
237 if ((p[0] & 0x1f) == 0x06 || (p[0] & 0x1f) == 0x07 || (p[0] & 0x1f) == 0x08) {
238 MEDIA_LOGD("media flag codec data controlId: %{public}u.", controlId_);
239 ret = videoDecoder_->QueueInputBuffer(inputIndex, bufferInfo, MediaAVCodec::AVCODEC_BUFFER_FLAG_CODEC_DATA);
240 } else {
241 MEDIA_LOGD("media flag none controlId: %{public}u.", controlId_);
242 ret = videoDecoder_->QueueInputBuffer(inputIndex, bufferInfo, MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE);
243 }
244
245 if (ret != MediaAVCodec::AVCS_ERR_OK) {
246 MEDIA_LOGE("QueueInputBuffer failed error: %{public}d controlId: %{public}u.", ret, controlId_);
247 return false;
248 }
249
250 lock.lock();
251 inQueue_.pop();
252 inBufferQueue_.pop();
253
254 MEDIA_LOGD("process data success controlId: %{public}u.", controlId_);
255 return true;
256 }
257
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)258 void VideoSinkDecoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
259 {
260 SHARING_LOGE("controlId: %{public}u.", controlId_);
261 auto listener = videoDecoderListener_.lock();
262 if (listener) {
263 listener->OnError(errorCode);
264 }
265 }
266
OnOutputBufferAvailable(uint32_t index,MediaAVCodec::AVCodecBufferInfo info,MediaAVCodec::AVCodecBufferFlag flag,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)267 void VideoSinkDecoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info,
268 MediaAVCodec::AVCodecBufferFlag flag, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
269 {
270 MEDIA_LOGD("OnOutputBufferAvailable index: %{public}u controlId: %{public}u.", index, controlId_);
271 if (!videoDecoder_) {
272 MEDIA_LOGW("decoder is null!");
273 return;
274 }
275 if (forceSWDecoder_) {
276 MEDIA_LOGD("forceSWDecoder_ is true.");
277 }
278 if (forceSWDecoder_) {
279 if (buffer == nullptr || buffer->GetBase() == nullptr) {
280 MEDIA_LOGW("OnOutputBufferAvailable buffer null!");
281 return;
282 }
283 size_t dataSize = static_cast<size_t>(info.size);
284 SHARING_LOGD("OnOutputBufferAvailable size: %{public}zu.", dataSize);
285 auto dataBuf = std::make_shared<DataBuffer>(dataSize);
286 if (dataBuf != nullptr) {
287 dataBuf->PushData((char *)buffer->GetBase(), dataSize);
288 auto listerner = videoDecoderListener_.lock();
289 if (listerner) {
290 listerner->OnVideoDataDecoded(dataBuf);
291 }
292 } else {
293 MEDIA_LOGE("get databuffer failed!");
294 }
295 }
296
297 if (videoDecoder_->ReleaseOutputBuffer(index, true) != MediaAVCodec::AVCS_ERR_OK) {
298 MEDIA_LOGW("ReleaseOutputBuffer failed!");
299 }
300 }
301
OnInputBufferAvailable(uint32_t index,std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)302 void VideoSinkDecoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr<MediaAVCodec::AVSharedMemory> buffer)
303 {
304 MEDIA_LOGD("OnInputBufferAvailable index: %{public}u controlId: %{public}u.", index, controlId_);
305 {
306 std::lock_guard<std::mutex> lock(inMutex_);
307 inQueue_.push(index);
308 inBufferQueue_.push(buffer);
309 }
310 inCond_.notify_all();
311 MEDIA_LOGD("OnInputBufferAvailable notify.");
312 }
313
OnOutputFormatChanged(const MediaAVCodec::Format & format)314 void VideoSinkDecoder::OnOutputFormatChanged(const MediaAVCodec::Format &format)
315 {
316 SHARING_LOGD("controlId: %{public}u.", controlId_);
317 }
318
SetSurface(sptr<Surface> surface)319 bool VideoSinkDecoder::SetSurface(sptr<Surface> surface)
320 {
321 SHARING_LOGD("trace.");
322 RETURN_FALSE_IF_NULL(surface);
323 RETURN_FALSE_IF_NULL(videoDecoder_);
324 if (isRunning_) {
325 SHARING_LOGW("decoder is running, cann't set surface!");
326 return false;
327 }
328
329 auto ret = videoDecoder_->SetOutputSurface(surface);
330 if (ret != MediaAVCodec::AVCS_ERR_OK) {
331 SHARING_LOGE("decoder set surface error, ret code: %{public}u.", ret);
332 return false;
333 }
334 enableSurface_ = true;
335 surface_ = surface;
336 return true;
337 }
338
339 } // namespace Sharing
340 } // namespace OHOS