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