1 /*
2  * Copyright (c) 2022-2024 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 <pthread.h>
20 #include <securec.h>
21 
22 #include "dscreen_constants.h"
23 #include "dscreen_errcode.h"
24 #include "dscreen_hisysevent.h"
25 #include "dscreen_log.h"
26 
27 namespace OHOS {
28 namespace DistributedHardware {
29 constexpr const char* DECODE_THREAD = "DecodeThread";
ConfigureDecoder(const VideoParam & configParam)30 int32_t ImageSinkDecoder::ConfigureDecoder(const VideoParam &configParam)
31 {
32     DHLOGI("%{public}s: ConfigureDecoder.", DSCREEN_LOG_TAG);
33     int32_t ret = InitVideoDecoder(configParam);
34     if (ret != DH_SUCCESS) {
35         DHLOGE("%{public}s: InitVideoDecoder failed.", DSCREEN_LOG_TAG);
36         return ret;
37     }
38 
39     ret = SetDecoderFormat(configParam);
40     if (ret != DH_SUCCESS) {
41         DHLOGE("%{public}s: SetDecoderFormat failed.", DSCREEN_LOG_TAG);
42         return ret;
43     }
44     configParam_ = configParam;
45     ret = AddSurface();
46     if (ret != DH_SUCCESS) {
47         DHLOGE("%{public}s: Add surface failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
48         consumerSurface_ = nullptr;
49         producerSurface_ = nullptr;
50         return ret;
51     }
52     alignedHeight_ = configParam_.GetVideoHeight();
53     if (alignedHeight_ % ALIGNEDBITS != 0) {
54         alignedHeight_ = ((alignedHeight_ / ALIGNEDBITS) + 1) * ALIGNEDBITS;
55     }
56     return DH_SUCCESS;
57 }
58 
AddSurface()59 int32_t ImageSinkDecoder::AddSurface()
60 {
61     DHLOGI("%{public}s: AddSurface.", DSCREEN_LOG_TAG);
62     consumerSurface_ = IConsumerSurface::Create();
63     if (consumerSurface_ == nullptr) {
64         DHLOGE("%{public}s: Create consumer surface failed.", DSCREEN_LOG_TAG);
65         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
66     }
67 
68     consumerSurface_->SetDefaultUsage(BUFFER_USAGE_CPU_READ);
69 
70     sptr<IBufferProducer> producer = consumerSurface_->GetProducer();
71     if (producer == nullptr) {
72         DHLOGE("%{public}s: Get preducer surface failed.", DSCREEN_LOG_TAG);
73         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
74     }
75 
76     producerSurface_ = Surface::CreateSurfaceAsProducer(producer);
77     if (producerSurface_ == nullptr) {
78         DHLOGE("%{public}s: Create preducer surface failed.", DSCREEN_LOG_TAG);
79         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
80     }
81 
82     if (consumerBufferListener_ == nullptr) {
83         consumerBufferListener_ = new ConsumBufferListener(shared_from_this());
84     }
85     consumerSurface_->RegisterConsumerListener(consumerBufferListener_);
86     lastFrameSize_ = static_cast<int32_t>(configParam_.GetVideoWidth() *
87         configParam_.GetVideoHeight() * RGB_CHROMA / TWO);
88     lastFrame_ = new uint8_t[lastFrameSize_];
89     return DH_SUCCESS;
90 }
91 
GetLastFrame()92 uint8_t *ImageSinkDecoder::GetLastFrame()
93 {
94     return lastFrame_;
95 }
96 
GetWinSurfaceBuffer()97 sptr<SurfaceBuffer> ImageSinkDecoder::GetWinSurfaceBuffer()
98 {
99     DHLOGI("%{public}s: GetWinSurfaceBuffer.", DSCREEN_LOG_TAG);
100     sptr<SurfaceBuffer> windowSurfaceBuffer = nullptr;
101     int32_t releaseFence = -1;
102     OHOS::BufferRequestConfig requestConfig = {
103         .width = static_cast<int32_t>(configParam_.GetVideoWidth()),
104         .height = static_cast<int32_t>(configParam_.GetVideoHeight()),
105         .strideAlignment = STRIDE_ALIGNMENT,
106         .format = GRAPHIC_PIXEL_FMT_YCBCR_420_SP,
107         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
108     };
109     SurfaceError surfaceErr = windowSurface_->RequestBuffer(windowSurfaceBuffer, releaseFence, requestConfig);
110     if (surfaceErr != SURFACE_ERROR_OK || windowSurfaceBuffer == nullptr) {
111         DHLOGE("%{public}s: windowSurface_ request buffer failed, buffer is nullptr.", DSCREEN_LOG_TAG);
112         windowSurface_->CancelBuffer(windowSurfaceBuffer);
113     }
114     return windowSurfaceBuffer;
115 }
116 
NormalProcess(sptr<SurfaceBuffer> surfaceBuffer,sptr<SurfaceBuffer> windowSurfaceBuffer)117 void ImageSinkDecoder::NormalProcess(sptr<SurfaceBuffer> surfaceBuffer, sptr<SurfaceBuffer> windowSurfaceBuffer)
118 {
119     DHLOGI("%{public}s: NormalProcess.", DSCREEN_LOG_TAG);
120     auto surfaceAddr = static_cast<uint8_t*>(surfaceBuffer->GetVirAddr());
121     auto windowSurfaceAddr = static_cast<uint8_t*>(windowSurfaceBuffer->GetVirAddr());
122     int32_t sizeData = lastFrameSize_;
123     uint32_t size = windowSurfaceBuffer->GetSize();
124     int32_t ret = memcpy_s(windowSurfaceAddr, size, surfaceAddr, sizeData);
125     if (ret != EOK) {
126         DHLOGE("%{public}s: surfaceBuffer memcpy run failed.", DSCREEN_LOG_TAG);
127         windowSurface_->CancelBuffer(windowSurfaceBuffer);
128     }
129 }
130 
OffsetProcess(sptr<SurfaceBuffer> surfaceBuffer,sptr<SurfaceBuffer> windowSurfaceBuffer)131 void ImageSinkDecoder::OffsetProcess(sptr<SurfaceBuffer> surfaceBuffer, sptr<SurfaceBuffer> windowSurfaceBuffer)
132 {
133     DHLOGI("%{public}s: OffsetProcess.", DSCREEN_LOG_TAG);
134     auto surfaceAddr = static_cast<uint8_t*>(surfaceBuffer->GetVirAddr());
135     auto windowSurfaceAddr = static_cast<uint8_t*>(windowSurfaceBuffer->GetVirAddr());
136     uint32_t size = windowSurfaceBuffer->GetSize();
137     uint32_t srcDataOffset = 0;
138     uint32_t dstDataOffset = 0;
139     uint32_t alignedWidth = static_cast<uint32_t>(surfaceBuffer->GetStride());
140     uint32_t chromaOffset = alignedWidth * configParam_.GetVideoHeight();
141     for (unsigned int yh = 0 ; yh < configParam_.GetVideoHeight() ; yh++) {
142         int32_t ret = memcpy_s(windowSurfaceAddr + dstDataOffset, chromaOffset - dstDataOffset,
143             surfaceAddr + srcDataOffset, alignedWidth);
144         if (ret != EOK) {
145             DHLOGE("%{public}s: surfaceBuffer memcpy_s run failed.", DSCREEN_LOG_TAG);
146             windowSurface_->CancelBuffer(windowSurfaceBuffer);
147             return;
148         }
149         dstDataOffset += alignedWidth;
150         srcDataOffset += alignedWidth;
151     }
152     dstDataOffset = chromaOffset;
153     srcDataOffset = alignedWidth * alignedHeight_;
154     for (unsigned int uvh = 0 ; uvh < configParam_.GetVideoHeight() / TWO; uvh++) {
155         int32_t ret = memcpy_s(windowSurfaceAddr + dstDataOffset, size - dstDataOffset,
156             surfaceAddr + srcDataOffset, alignedWidth);
157         if (ret != EOK) {
158             DHLOGE("%{public}s: surfaceBuffer memcpy_s run failed.", DSCREEN_LOG_TAG);
159             windowSurface_->CancelBuffer(windowSurfaceBuffer);
160             return;
161         }
162         dstDataOffset += alignedWidth;
163         srcDataOffset += alignedWidth;
164     }
165 }
166 
ConsumeSurface()167 void ImageSinkDecoder::ConsumeSurface()
168 {
169     DHLOGI("%{public}s: ConsumeSurface.", DSCREEN_LOG_TAG);
170     std::unique_lock<std::mutex> bufLock(decodeMutex_);
171     if (consumerSurface_ == nullptr) {
172         DHLOGE("%{public}s: consumerSurface_ is nullptr.", DSCREEN_LOG_TAG);
173         return;
174     }
175     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
176     int32_t fence = -1;
177     int64_t timestamp = 0;
178     OHOS::Rect damage = {0, 0, 0, 0};
179     SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, fence, timestamp, damage);
180     if (surfaceErr != SURFACE_ERROR_OK) {
181         return;
182     }
183     sptr<OHOS::SurfaceBuffer> windowSurfaceBuffer = GetWinSurfaceBuffer();
184     if (windowSurfaceBuffer == nullptr) {
185         consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
186         return;
187     }
188 
189     if (lastFrameSize_ != surfaceBuffer->GetStride() * surfaceBuffer->GetHeight() * THREE / TWO) {
190         if (lastFrame_ != nullptr) {
191             delete [] lastFrame_;
192         }
193         lastFrameSize_ = surfaceBuffer->GetStride() * surfaceBuffer->GetHeight() * THREE / TWO;
194         lastFrame_ = new uint8_t[lastFrameSize_];
195     }
196 
197     if (static_cast<uint32_t>(alignedHeight_) == configParam_.GetVideoHeight()) {
198         NormalProcess(surfaceBuffer, windowSurfaceBuffer);
199     } else {
200         OffsetProcess(surfaceBuffer, windowSurfaceBuffer);
201     }
202     auto windowSurfaceAddr = static_cast<uint8_t*>(windowSurfaceBuffer->GetVirAddr());
203     BufferFlushConfig flushConfig = { {0, 0, windowSurfaceBuffer->GetWidth(), windowSurfaceBuffer->GetHeight()}, 0};
204     int32_t ret = memcpy_s(lastFrame_, lastFrameSize_, windowSurfaceAddr, lastFrameSize_);
205     if (ret != EOK) {
206         DHLOGE("%{public}s: surfaceBuffer memcpy_s run failed.", DSCREEN_LOG_TAG);
207         consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
208         windowSurface_->CancelBuffer(windowSurfaceBuffer);
209         return;
210     }
211     DHLOGI("%{public}s: ConsumeSurface success, send NV12 to window.", DSCREEN_LOG_TAG);
212     surfaceErr = windowSurface_->FlushBuffer(windowSurfaceBuffer, -1, flushConfig);
213     if (surfaceErr != SURFACE_ERROR_OK) {
214         DHLOGE("%{public}s: windowSurface_ flush buffer failed.", DSCREEN_LOG_TAG);
215         consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
216         windowSurface_->CancelBuffer(windowSurfaceBuffer);
217         return;
218     }
219     consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
220 }
221 
OnBufferAvailable()222 void ConsumBufferListener::OnBufferAvailable()
223 {
224     DHLOGI("%{public}s: OnBufferAvailable, receive NV12 data from decoder.", DSCREEN_LOG_TAG);
225     decoder_->ConsumeSurface();
226 }
227 
ReleaseDecoder()228 int32_t ImageSinkDecoder::ReleaseDecoder()
229 {
230     DHLOGI("%{public}s: ReleaseDecoder.", DSCREEN_LOG_TAG);
231     if (videoDecoder_ == nullptr) {
232         DHLOGE("%{public}s: Decoder is null.", DSCREEN_LOG_TAG);
233         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
234     }
235     if (lastFrame_ != nullptr) {
236         delete [] lastFrame_;
237     }
238     int32_t ret = videoDecoder_->Release();
239     if (ret != MediaAVCodec::AVCS_ERR_OK) {
240         DHLOGE("%{public}s: ReleaseDecoder failed.", DSCREEN_LOG_TAG);
241         return ERR_DH_SCREEN_CODEC_RELEASE_FAILED;
242     }
243     decodeVideoCallback_ = nullptr;
244     videoDecoder_ = nullptr;
245 
246     return DH_SUCCESS;
247 }
248 
StartDecoder()249 int32_t ImageSinkDecoder::StartDecoder()
250 {
251     DHLOGI("%{public}s: StartDecoder.", DSCREEN_LOG_TAG);
252     if (videoDecoder_ == nullptr) {
253         DHLOGE("%{public}s: Decoder is null.", DSCREEN_LOG_TAG);
254         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
255     }
256 
257     int32_t ret = videoDecoder_->Prepare();
258     if (ret != MediaAVCodec::AVCS_ERR_OK) {
259         DHLOGE("%{public}s: Prepare decoder failed.", DSCREEN_LOG_TAG);
260         return ERR_DH_SCREEN_CODEC_PREPARE_FAILED;
261     }
262 
263     ret = videoDecoder_->Start();
264     if (ret != MediaAVCodec::AVCS_ERR_OK) {
265         DHLOGE("%{public}s: Start decoder failed.", DSCREEN_LOG_TAG);
266         return ERR_DH_SCREEN_CODEC_START_FAILED;
267     }
268     StartInputThread();
269 
270     return DH_SUCCESS;
271 }
272 
StopDecoder()273 int32_t ImageSinkDecoder::StopDecoder()
274 {
275     DHLOGI("%{public}s: StopDecoder.", DSCREEN_LOG_TAG);
276     if (videoDecoder_ == nullptr) {
277         DHLOGE("%{public}s: Decoder is null.", DSCREEN_LOG_TAG);
278         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
279     }
280 
281     int32_t ret = videoDecoder_->Flush();
282     if (ret != MediaAVCodec::AVCS_ERR_OK) {
283         DHLOGE("%{public}s: Flush decoder failed.", DSCREEN_LOG_TAG);
284         return ERR_DH_SCREEN_CODEC_FLUSH_FAILED;
285     }
286 
287     ret = videoDecoder_->Stop();
288     if (ret != MediaAVCodec::AVCS_ERR_OK) {
289         DHLOGE("%{public}s: Stop decoder failed.", DSCREEN_LOG_TAG);
290         return ERR_DH_SCREEN_CODEC_STOP_FAILED;
291     }
292     StopInputThread();
293 
294     return DH_SUCCESS;
295 }
296 
InitVideoDecoder(const VideoParam & configParam)297 int32_t ImageSinkDecoder::InitVideoDecoder(const VideoParam &configParam)
298 {
299     DHLOGI("%{public}s: InitVideoDecoder.", DSCREEN_LOG_TAG);
300     switch (configParam.GetCodecType()) {
301         case VIDEO_CODEC_TYPE_VIDEO_H264:
302             videoDecoder_ = MediaAVCodec::VideoDecoderFactory::CreateByMime(
303                 std::string(MediaAVCodec::CodecMimeType::VIDEO_AVC));
304             break;
305         case VIDEO_CODEC_TYPE_VIDEO_H265:
306             videoDecoder_ = MediaAVCodec::VideoDecoderFactory::CreateByMime(
307                 std::string(MediaAVCodec::CodecMimeType::VIDEO_HEVC));
308             break;
309         default:
310             DHLOGE("%{public}s: codecType is invalid!", DSCREEN_LOG_TAG);
311             videoDecoder_ = nullptr;
312     }
313 
314     if (videoDecoder_ == nullptr) {
315         DHLOGE("%{public}s: Create videoEncoder failed.", DSCREEN_LOG_TAG);
316         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
317     }
318 
319     decodeVideoCallback_ = std::make_shared<ImageDecoderCallback>(shared_from_this());
320     int32_t ret = videoDecoder_->SetCallback(decodeVideoCallback_);
321     if (ret != MediaAVCodec::AVCS_ERR_OK) {
322         DHLOGE("%{public}s: Set decoder callback failed.", DSCREEN_LOG_TAG);
323         return ERR_DH_SCREEN_CODEC_SET_CALLBACK_FAILED;
324     }
325 
326     return DH_SUCCESS;
327 }
328 
SetDecoderFormat(const VideoParam & configParam)329 int32_t ImageSinkDecoder::SetDecoderFormat(const VideoParam &configParam)
330 {
331     DHLOGI("%{public}s: SetDecoderFormat.", DSCREEN_LOG_TAG);
332     if (videoDecoder_ == nullptr) {
333         DHLOGE("%{public}s: Decoder is null.", DSCREEN_LOG_TAG);
334         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
335     }
336 
337     switch (configParam.GetCodecType()) {
338         case VIDEO_CODEC_TYPE_VIDEO_H264:
339             imageFormat_.PutStringValue("codec_mime", MediaAVCodec::CodecMimeType::VIDEO_AVC);
340             break;
341         case VIDEO_CODEC_TYPE_VIDEO_H265:
342             imageFormat_.PutStringValue("codec_mime", MediaAVCodec::CodecMimeType::VIDEO_HEVC);
343             break;
344         default:
345             DHLOGE("The current codec type does not support decoding.");
346             return ERR_DH_SCREEN_TRANS_ILLEGAL_OPERATION;
347     }
348 
349     imageFormat_.PutIntValue("pixel_format", static_cast<int32_t>(MediaAVCodec::VideoPixelFormat::NV12));
350     imageFormat_.PutLongValue("max_input_size", MAX_YUV420_BUFFER_SIZE);
351     imageFormat_.PutIntValue("width", configParam.GetVideoWidth());
352     imageFormat_.PutIntValue("height", configParam.GetVideoHeight());
353     imageFormat_.PutDoubleValue("frame_rate", configParam.GetFps());
354 
355     int32_t ret = videoDecoder_->Configure(imageFormat_);
356     if (ret != MediaAVCodec::AVCS_ERR_OK) {
357         DHLOGE("%{public}s: configure decoder format param failed.", DSCREEN_LOG_TAG);
358         return ERR_DH_SCREEN_CODEC_CONFIGURE_FAILED;
359     }
360 
361     return DH_SUCCESS;
362 }
363 
SetOutputSurface(sptr<Surface> & surface)364 int32_t ImageSinkDecoder::SetOutputSurface(sptr<Surface> &surface)
365 {
366     DHLOGI("%{public}s: SetOutputSurface.", DSCREEN_LOG_TAG);
367     if (videoDecoder_ == nullptr || surface == nullptr) {
368         DHLOGE("%{public}s: Decoder or surface is null.", DSCREEN_LOG_TAG);
369         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
370     }
371     windowSurface_ = surface;
372     if (consumerSurface_ == nullptr || producerSurface_ == nullptr || !configParam_.GetPartialRefreshFlag()) {
373         int32_t ret = videoDecoder_->SetOutputSurface(surface);
374         if (ret != MediaAVCodec::AVCS_ERR_OK) {
375             DHLOGE("%{public}s: SetOutputSurface failed.", DSCREEN_LOG_TAG);
376             return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
377         }
378     } else {
379         int32_t ret = videoDecoder_->SetOutputSurface(producerSurface_);
380         if (ret != MediaAVCodec::AVCS_ERR_OK) {
381             DHLOGE("%{public}s: SetOutputSurface failed.", DSCREEN_LOG_TAG);
382             return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
383         }
384     }
385     return DH_SUCCESS;
386 }
387 
InputScreenData(const std::shared_ptr<DataBuffer> & data)388 int32_t ImageSinkDecoder::InputScreenData(const std::shared_ptr<DataBuffer> &data)
389 {
390     if (data == nullptr) {
391         DHLOGE("%{public}s: InputScreenData failed, data is nullptr.", DSCREEN_LOG_TAG);
392         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
393     }
394     DHLOGD("%{public}s: InputScreenData.", DSCREEN_LOG_TAG);
395     std::lock_guard<std::mutex> dataLock(dataMutex_);
396     while (videoDataQueue_.size() >= DATA_QUEUE_MAX_SIZE) {
397         DHLOGE("%{public}s: videoData queue overflow.", DSCREEN_LOG_TAG);
398         videoDataQueue_.pop();
399     }
400     videoDataQueue_.push(data);
401     decodeCond_.notify_all();
402 
403     return DH_SUCCESS;
404 }
405 
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)406 void ImageSinkDecoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
407 {
408     DHLOGI("%{public}s: OnImageDecodeError, errorType:%{public}" PRId32 ", errorCode:%{public}" PRId32,
409         DSCREEN_LOG_TAG, errorType, errorCode);
410     std::shared_ptr<IImageSinkProcessorListener> listener = imageProcessorListener_.lock();
411     if (listener == nullptr) {
412         DHLOGE("%{public}s: Listener is null.", DSCREEN_LOG_TAG);
413         return;
414     }
415     listener->OnProcessorStateNotify(errorCode);
416 }
417 
OnInputBufferAvailable(uint32_t index,std::shared_ptr<Media::AVSharedMemory> buffer)418 void ImageSinkDecoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr<Media::AVSharedMemory> buffer)
419 {
420     DHLOGI("%{public}s: OnDecodeInputBufferAvailable: %{public}" PRIu32, DSCREEN_LOG_TAG, index);
421     std::lock_guard<std::mutex> dataLock(dataMutex_);
422     availableInputIndexsQueue_.push(index);
423     availableInputBufferQueue_.push(buffer);
424 }
425 
OnOutputBufferAvailable(uint32_t index,MediaAVCodec::AVCodecBufferInfo info,MediaAVCodec::AVCodecBufferFlag flag,std::shared_ptr<Media::AVSharedMemory> buffer)426 void ImageSinkDecoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info,
427     MediaAVCodec::AVCodecBufferFlag flag, std::shared_ptr<Media::AVSharedMemory> buffer)
428 {
429     DHLOGI("%{public}s: OnDecodeOutputBufferAvailable.", DSCREEN_LOG_TAG);
430     if (videoDecoder_ == nullptr) {
431         DHLOGE("%{public}s: Decoder is null.", DSCREEN_LOG_TAG);
432         return;
433     }
434 
435     decoderBufferInfo_ = info;
436     int32_t ret = videoDecoder_->ReleaseOutputBuffer(index, true);
437     if (ret != MediaAVCodec::AVCS_ERR_OK) {
438         DHLOGD("%{public}s: ReleaseOutputBuffer failed.", DSCREEN_LOG_TAG);
439     }
440 }
441 
OnOutputFormatChanged(const Media::Format & format)442 void ImageSinkDecoder::OnOutputFormatChanged(const Media::Format &format)
443 {
444     (void) format;
445 }
446 
StartInputThread()447 int32_t ImageSinkDecoder::StartInputThread()
448 {
449     DHLOGI("%{public}s: StartInputThread.", DSCREEN_LOG_TAG);
450     isDecoderReady_ = true;
451     decodeThread_ = std::thread([this] { this->DecodeScreenData(); });
452     return DH_SUCCESS;
453 }
454 
StopInputThread()455 int32_t ImageSinkDecoder::StopInputThread()
456 {
457     DHLOGI("%{public}s: StopInputThread.", DSCREEN_LOG_TAG);
458     isDecoderReady_ = false;
459     if (decodeThread_.joinable()) {
460         decodeThread_.join();
461     }
462     std::lock_guard<std::mutex> dataLock(dataMutex_);
463     std::queue<std::shared_ptr<DataBuffer>>().swap(videoDataQueue_);
464     std::queue<int32_t>().swap(availableInputIndexsQueue_);
465     std::queue<std::shared_ptr<Media::AVSharedMemory>>().swap(availableInputBufferQueue_);
466 
467     return DH_SUCCESS;
468 }
469 
DecodeScreenData()470 void ImageSinkDecoder::DecodeScreenData()
471 {
472     DHLOGI("%{public}s: DecodeScreenData.", DSCREEN_LOG_TAG);
473     int32_t ret = pthread_setname_np(pthread_self(), DECODE_THREAD);
474     if (ret != DH_SUCCESS) {
475         DHLOGE("ImageSinkDecoder set thread name failed, ret %{public}" PRId32, ret);
476     }
477     while (isDecoderReady_) {
478         std::shared_ptr<DataBuffer> screenData;
479         int32_t bufferIndex = 0;
480         {
481             std::unique_lock<std::mutex> lock(dataMutex_);
482             auto status = decodeCond_.wait_for(lock, std::chrono::milliseconds(DECODE_WAIT_MILLISECONDS), [this]() {
483                 return (!videoDataQueue_.empty() && !availableInputIndexsQueue_.empty() &&
484                         !availableInputBufferQueue_.empty());
485             });
486             if (!status) {
487                 DHLOGD("%{public}s: Data queue wait timeout after %{public}d ms.", DSCREEN_LOG_TAG,
488                     DECODE_WAIT_MILLISECONDS);
489                 continue;
490             }
491             if (videoDataQueue_.empty() || availableInputIndexsQueue_.empty() || availableInputBufferQueue_.empty()) {
492                 DHLOGD("%{public}s: Index queue or data queue or buffer queue is empty.", DSCREEN_LOG_TAG);
493                 continue;
494             }
495             bufferIndex = availableInputIndexsQueue_.front();
496             availableInputIndexsQueue_.pop();
497             screenData = videoDataQueue_.front();
498             videoDataQueue_.pop();
499         }
500 
501         ret = ProcessData(screenData, bufferIndex);
502         if (ret == ERR_DH_SCREEN_TRANS_NULL_VALUE) {
503             return;
504         } else if (ret != DH_SUCCESS) {
505             continue;
506         }
507     }
508 }
509 
ProcessData(const std::shared_ptr<DataBuffer> & screenData,const int32_t bufferIndex)510 int32_t ImageSinkDecoder::ProcessData(const std::shared_ptr<DataBuffer> &screenData, const int32_t bufferIndex)
511 {
512     DHLOGI("%{public}s: ProcessData.", DSCREEN_LOG_TAG);
513     if (videoDecoder_ == nullptr || screenData == nullptr) {
514         DHLOGE("%{public}s: Decoder or screenData is null.", DSCREEN_LOG_TAG);
515         return ERR_DH_SCREEN_TRANS_NULL_VALUE;
516     }
517 
518     if (availableInputBufferQueue_.empty()) {
519         DHLOGD("%{public}s: input buffer queue is empty.", DSCREEN_LOG_TAG);
520         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
521     }
522 
523     std::shared_ptr<Media::AVSharedMemory> inputBuffer = availableInputBufferQueue_.front();
524     if (inputBuffer == nullptr) {
525         DHLOGE("%{public}s: Failed to obtain the input shared memory corresponding to the [%{public}d] index.",
526             DSCREEN_LOG_TAG, bufferIndex);
527         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
528     }
529 
530     int32_t ret = memcpy_s(inputBuffer->GetBase(), inputBuffer->GetSize(), screenData->Data(), screenData->Capacity());
531     if (ret != EOK) {
532         DHLOGE("%{public}s: Copy data failed.", DSCREEN_LOG_TAG);
533         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
534     }
535 
536     DHLOGD("%{public}s: Decode screen data. send data to H264 decoder", DSCREEN_LOG_TAG);
537     MediaAVCodec::AVCodecBufferInfo bufferInfo;
538     bufferInfo.presentationTimeUs = 0;
539     bufferInfo.size = static_cast<int32_t>(screenData->Capacity());
540     bufferInfo.offset = 0;
541     ret = videoDecoder_->QueueInputBuffer(bufferIndex, bufferInfo, MediaAVCodec::AVCODEC_BUFFER_FLAG_NONE);
542     if (ret != MediaAVCodec::AVCS_ERR_OK) {
543         DHLOGE("%{public}s: QueueInputBuffer failed.", DSCREEN_LOG_TAG);
544         return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
545     }
546     availableInputBufferQueue_.pop();
547     return DH_SUCCESS;
548 }
549 } // namespace DistributedHardware
550 } // namespace OHOS
551