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