• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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