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