1 /*
2 * Copyright (c) 2022 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
16 #include "image_sink_decoder.h"
17
18 #include <chrono>
19 #include <securec.h>
20
21 #include "dscreen_constants.h"
22 #include "dscreen_errcode.h"
23 #include "dscreen_hisysevent.h"
24 #include "dscreen_log.h"
25
26 namespace OHOS {
27 namespace DistributedHardware {
ConfigureDecoder(const VideoParam & configParam)28 int32_t ImageSinkDecoder::ConfigureDecoder(const VideoParam &configParam)
29 {
30 DHLOGI("%s: ConfigureDecoder.", LOG_TAG);
31 int32_t ret = InitVideoDecoder(configParam);
32 if (ret != DH_SUCCESS) {
33 DHLOGE("%s: InitVideoDecoder failed.", LOG_TAG);
34 return ret;
35 }
36
37 ret = SetDecoderFormat(configParam);
38 if (ret != DH_SUCCESS) {
39 DHLOGE("%s: SetDecoderFormat failed.", LOG_TAG);
40 return ret;
41 }
42
43 return DH_SUCCESS;
44 }
45
ReleaseDecoder()46 int32_t ImageSinkDecoder::ReleaseDecoder()
47 {
48 DHLOGI("%s: ReleaseDecoder.", LOG_TAG);
49 if (videoDecoder_ == nullptr) {
50 DHLOGE("%s: Decoder is null.", LOG_TAG);
51 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
52 }
53
54 int32_t ret = videoDecoder_->Release();
55 if (ret != Media::MSERR_OK) {
56 DHLOGE("%s: ReleaseDecoder failed.", LOG_TAG);
57 return ERR_DH_SCREEN_CODEC_RELEASE_FAILED;
58 }
59 decodeVideoCallback_ = nullptr;
60 videoDecoder_ = nullptr;
61
62 return DH_SUCCESS;
63 }
64
StartDecoder()65 int32_t ImageSinkDecoder::StartDecoder()
66 {
67 DHLOGI("%s: StartDecoder.", LOG_TAG);
68 if (videoDecoder_ == nullptr) {
69 DHLOGE("%s: Decoder is null.", LOG_TAG);
70 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
71 }
72
73 int32_t ret = videoDecoder_->Prepare();
74 if (ret != Media::MSERR_OK) {
75 DHLOGE("%s: Prepare decoder failed.", LOG_TAG);
76 return ERR_DH_SCREEN_CODEC_PREPARE_FAILED;
77 }
78
79 ret = videoDecoder_->Start();
80 if (ret != Media::MSERR_OK) {
81 DHLOGE("%s: Start decoder failed.", LOG_TAG);
82 return ERR_DH_SCREEN_CODEC_START_FAILED;
83 }
84 StartInputThread();
85
86 return DH_SUCCESS;
87 }
88
StopDecoder()89 int32_t ImageSinkDecoder::StopDecoder()
90 {
91 DHLOGI("%s: StopDecoder.", LOG_TAG);
92 if (videoDecoder_ == nullptr) {
93 DHLOGE("%s: Decoder is null.", LOG_TAG);
94 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
95 }
96
97 int32_t ret = videoDecoder_->Flush();
98 if (ret != Media::MSERR_OK) {
99 DHLOGE("%s: Flush decoder failed.", LOG_TAG);
100 return ERR_DH_SCREEN_CODEC_FLUSH_FAILED;
101 }
102
103 ret = videoDecoder_->Stop();
104 if (ret != Media::MSERR_OK) {
105 DHLOGE("%s: Stop decoder failed.", LOG_TAG);
106 return ERR_DH_SCREEN_CODEC_STOP_FAILED;
107 }
108 StopInputThread();
109
110 return DH_SUCCESS;
111 }
112
InitVideoDecoder(const VideoParam & configParam)113 int32_t ImageSinkDecoder::InitVideoDecoder(const VideoParam &configParam)
114 {
115 DHLOGI("%s: InitVideoDecoder.", LOG_TAG);
116 switch (configParam.GetCodecType()) {
117 case VIDEO_CODEC_TYPE_VIDEO_H264:
118 videoDecoder_ = Media::VideoDecoderFactory::CreateByMime("video/avc");
119 break;
120 case VIDEO_CODEC_TYPE_VIDEO_H265:
121 videoDecoder_ = Media::VideoDecoderFactory::CreateByMime("video/hevc");
122 break;
123 case VIDEO_CODEC_TYPE_VIDEO_MPEG4:
124 videoDecoder_ = Media::VideoDecoderFactory::CreateByMime("video/mp4v-es");
125 break;
126 default:
127 DHLOGE("%s: codecType is invalid!", LOG_TAG);
128 videoDecoder_ = nullptr;
129 }
130
131 if (videoDecoder_ == nullptr) {
132 DHLOGE("%s: Create videoEncode failed.", LOG_TAG);
133 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
134 }
135
136 decodeVideoCallback_ = std::make_shared<ImageDecoderCallback>(shared_from_this());
137 int32_t ret = videoDecoder_->SetCallback(decodeVideoCallback_);
138 if (ret != Media::MSERR_OK) {
139 DHLOGE("%s: Set decoder callback failed.", LOG_TAG);
140 return ERR_DH_SCREEN_CODEC_SET_CALLBACK_FAILED;
141 }
142
143 return DH_SUCCESS;
144 }
145
SetDecoderFormat(const VideoParam & configParam)146 int32_t ImageSinkDecoder::SetDecoderFormat(const VideoParam &configParam)
147 {
148 DHLOGI("%s: SetDecoderFormat.", LOG_TAG);
149 if (videoDecoder_ == nullptr) {
150 DHLOGE("%s: Decoder is null.", LOG_TAG);
151 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
152 }
153
154 switch (configParam.GetCodecType()) {
155 case VIDEO_CODEC_TYPE_VIDEO_H264:
156 imageFormat_.PutStringValue("codec_mime", "video/avc");
157 break;
158 case VIDEO_CODEC_TYPE_VIDEO_H265:
159 imageFormat_.PutStringValue("codec_mime", "video/hevc");
160 break;
161 case VIDEO_CODEC_TYPE_VIDEO_MPEG4:
162 imageFormat_.PutStringValue("codec_mime", "video/mp4v-es");
163 break;
164 default:
165 DHLOGE("The current codec type does not support decoding.");
166 return ERR_DH_SCREEN_TRANS_ILLEGAL_OPERATION;
167 }
168 switch (configParam.GetVideoFormat()) {
169 case VIDEO_DATA_FORMAT_YUVI420:
170 imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::YUVI420);
171 break;
172 case VIDEO_DATA_FORMAT_NV12:
173 imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::NV12);
174 break;
175 case VIDEO_DATA_FORMAT_NV21:
176 imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::NV21);
177 break;
178 case VIDEO_DATA_FORMAT_RGBA8888:
179 imageFormat_.PutIntValue("pixel_format", Media::VideoPixelFormat::RGBA);
180 break;
181 default:
182 DHLOGE("The current pixel format does not support decoding.");
183 return ERR_DH_SCREEN_TRANS_ILLEGAL_OPERATION;
184 }
185
186 imageFormat_.PutLongValue("max_input_size", MAX_YUV420_BUFFER_SIZE);
187 imageFormat_.PutIntValue("width", configParam.GetVideoWidth());
188 imageFormat_.PutIntValue("height", configParam.GetVideoHeight());
189 imageFormat_.PutIntValue("frame_rate", configParam.GetFps());
190
191 int32_t ret = videoDecoder_->Configure(imageFormat_);
192 if (ret != Media::MSERR_OK) {
193 DHLOGE("%s: configure decoder format param failed.", LOG_TAG);
194 return ERR_DH_SCREEN_CODEC_CONFIGURE_FAILED;
195 }
196
197 return DH_SUCCESS;
198 }
199
SetOutputSurface(sptr<Surface> & surface)200 int32_t ImageSinkDecoder::SetOutputSurface(sptr<Surface> &surface)
201 {
202 DHLOGI("%s: SetOutputSurface.", LOG_TAG);
203 if (videoDecoder_ == nullptr) {
204 DHLOGE("%s: Decoder is null.", LOG_TAG);
205 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
206 }
207
208 int32_t ret = videoDecoder_->SetOutputSurface(surface);
209 if (ret != Media::MSERR_OK) {
210 DHLOGE("%s: SetOutputSurface failed.", LOG_TAG);
211 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
212 }
213
214 return DH_SUCCESS;
215 }
216
InputScreenData(const std::shared_ptr<DataBuffer> & data)217 int32_t ImageSinkDecoder::InputScreenData(const std::shared_ptr<DataBuffer> &data)
218 {
219 DHLOGD("%s: InputScreenData.", LOG_TAG);
220 std::lock_guard<std::mutex> dataLock(dataMutex_);
221 while (videoDataQueue_.size() >= DATA_QUEUE_MAX_SIZE) {
222 DHLOGE("%s: videoData queue overflow.", LOG_TAG);
223 videoDataQueue_.pop();
224 }
225 videoDataQueue_.push(data);
226 decodeCond_.notify_all();
227
228 return DH_SUCCESS;
229 }
230
OnError(Media::AVCodecErrorType errorType,int32_t errorCode)231 void ImageSinkDecoder::OnError(Media::AVCodecErrorType errorType, int32_t errorCode)
232 {
233 DHLOGI("%s: OnImageDecodeError, errorType(%d), errorCode(%d)", LOG_TAG, errorType, errorCode);
234 std::shared_ptr<IImageSinkProcessorListener> listener = imageProcessorListener_.lock();
235 if (listener == nullptr) {
236 DHLOGE("%s: Listener is null.", LOG_TAG);
237 return;
238 }
239 listener->OnProcessorStateNotify(errorCode);
240 }
241
OnInputBufferAvailable(uint32_t index)242 void ImageSinkDecoder::OnInputBufferAvailable(uint32_t index)
243 {
244 DHLOGI("%s: OnDecodeInputBufferAvailable: %u.", LOG_TAG, index);
245 std::lock_guard<std::mutex> dataLock(dataMutex_);
246 bufferIndexQueue_.push(index);
247 }
248
OnOutputBufferAvailable(uint32_t index,Media::AVCodecBufferInfo info,Media::AVCodecBufferFlag flag)249 void ImageSinkDecoder::OnOutputBufferAvailable(uint32_t index, Media::AVCodecBufferInfo info,
250 Media::AVCodecBufferFlag flag)
251 {
252 DHLOGI("%s: OnDecodeOutputBufferAvailable.", LOG_TAG);
253 if (videoDecoder_ == nullptr) {
254 DHLOGE("%s: Decoder is null.", LOG_TAG);
255 return;
256 }
257
258 decoderBufferInfo_ = info;
259 int32_t ret = videoDecoder_->ReleaseOutputBuffer(index, true);
260 if (ret != Media::MSERR_OK) {
261 DHLOGD("%s: ReleaseOutputBuffer failed.", LOG_TAG);
262 }
263 }
264
OnOutputFormatChanged(const Media::Format & format)265 void ImageSinkDecoder::OnOutputFormatChanged(const Media::Format &format)
266 {
267 (void) format;
268 }
269
StartInputThread()270 int32_t ImageSinkDecoder::StartInputThread()
271 {
272 DHLOGI("%s: StartInputThread.", LOG_TAG);
273 isDecoderReady_ = true;
274 decodeThread_ = std::thread(&ImageSinkDecoder::DecodeScreenData, this);
275
276 return DH_SUCCESS;
277 }
278
StopInputThread()279 int32_t ImageSinkDecoder::StopInputThread()
280 {
281 DHLOGI("%s: StopInputThread.", LOG_TAG);
282 isDecoderReady_ = false;
283 if (decodeThread_.joinable()) {
284 decodeThread_.join();
285 }
286 std::lock_guard<std::mutex> dataLock(dataMutex_);
287 while (!bufferIndexQueue_.empty()) {
288 bufferIndexQueue_.pop();
289 }
290 while (!videoDataQueue_.empty()) {
291 videoDataQueue_.pop();
292 }
293
294 return DH_SUCCESS;
295 }
296
DecodeScreenData()297 void ImageSinkDecoder::DecodeScreenData()
298 {
299 DHLOGI("%s: DecodeScreenData.", LOG_TAG);
300 while (isDecoderReady_) {
301 std::shared_ptr<DataBuffer> screenData;
302 int32_t bufferIndex = 0;
303 {
304 std::unique_lock<std::mutex> lock(dataMutex_);
305 decodeCond_.wait_for(lock, std::chrono::milliseconds(DECODE_WAIT_MILLISECONDS),
306 [this]() { return (!videoDataQueue_.empty() && !bufferIndexQueue_.empty()); });
307
308 if (videoDataQueue_.empty() || bufferIndexQueue_.empty()) {
309 DHLOGD("%s: Index queue or data queue is empty.", LOG_TAG);
310 continue;
311 }
312 bufferIndex = bufferIndexQueue_.front();
313 bufferIndexQueue_.pop();
314 screenData = videoDataQueue_.front();
315 videoDataQueue_.pop();
316 }
317
318 int32_t ret = ProcessData(screenData, bufferIndex);
319 if (ret == ERR_DH_SCREEN_TRANS_NULL_VALUE) {
320 return;
321 } else if (ret != DH_SUCCESS) {
322 continue;
323 }
324 }
325 }
326
ProcessData(const std::shared_ptr<DataBuffer> & screenData,const int32_t bufferIndex)327 int32_t ImageSinkDecoder::ProcessData(const std::shared_ptr<DataBuffer> &screenData, const int32_t bufferIndex)
328 {
329 DHLOGI("%s: ProcessData.", LOG_TAG);
330 if (videoDecoder_ == nullptr) {
331 DHLOGE("%s: Decoder is null.", LOG_TAG);
332 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
333 }
334
335 auto inputBuffer = videoDecoder_->GetInputBuffer(bufferIndex);
336 if (inputBuffer == nullptr) {
337 DHLOGE("%s: GetInputBuffer failed.", LOG_TAG);
338 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
339 }
340
341 int32_t ret = memcpy_s(inputBuffer->GetBase(), inputBuffer->GetSize(), screenData->Data(), screenData->Capacity());
342 if (ret != EOK) {
343 DHLOGE("%s: Copy data failed.", LOG_TAG);
344 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
345 }
346
347 DHLOGD("%s: Decode screen data.", LOG_TAG);
348 Media::AVCodecBufferInfo bufferInfo;
349 bufferInfo.presentationTimeUs = 0;
350 bufferInfo.size = static_cast<int32_t>(screenData->Capacity());
351 bufferInfo.offset = 0;
352 ret = videoDecoder_->QueueInputBuffer(bufferIndex, bufferInfo, Media::AVCODEC_BUFFER_FLAG_NONE);
353 if (ret != Media::MSERR_OK) {
354 DHLOGE("%s: QueueInputBuffer failed.", LOG_TAG);
355 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
356 }
357 return DH_SUCCESS;
358 }
359 } // namespace DistributedHardware
360 } // namespace OHOS
361