1 /*
2 * Copyright (c) 2022-2025 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_source_encoder.h"
17
18 #include <dlfcn.h>
19 #include <fstream>
20 #include <iostream>
21 #include <securec.h>
22 #include <csetjmp>
23 #include <cstddef>
24 #include <string>
25 #include <ctime>
26
27 #include "dscreen_constants.h"
28 #include "dscreen_errcode.h"
29 #include "dscreen_hisysevent.h"
30 #include "dscreen_log.h"
31 #include "jpeglib.h"
32
33 using GetDscreenDBGItfFunc = OHOS::DistributedHardware::IDScreenDBGItf* (*)();
34 using GetImageDirtyFunc = OHOS::DistributedHardware::IImageSetDirty* (*)();
35 namespace OHOS {
36 namespace DistributedHardware {
37 const std::string DBG_SO_NAME = "libdistributed_screen_dbg_itf.z.so";
OnBufferAvailable()38 void ConsumerBufferListener::OnBufferAvailable()
39 {
40 DHLOGI("%{public}s: OnBufferAvailable, receiv data from RS.", DSCREEN_LOG_TAG);
41 encoder_->ConsumeSurface();
42 }
43
InitDscreenDBG()44 void ImageSourceEncoder::InitDscreenDBG()
45 {
46 pHandler_ = dlopen(DBG_SO_NAME.c_str(), RTLD_LAZY | RTLD_NODELETE | RTLD_GLOBAL);
47 if (pHandler_ == nullptr) {
48 DHLOGE("so: %{public}s load failed, fail reason: %{public}s.", DBG_SO_NAME.c_str(), dlerror());
49 return;
50 }
51 GetDscreenDBGItfFunc getDscreenDBGItfFunc = (GetDscreenDBGItfFunc)dlsym(pHandler_, GET_DBG_ITF_FUNC.c_str());
52 GetImageDirtyFunc getImageDirtyFunc = (GetImageDirtyFunc)dlsym(pHandler_, GET_IMAGE_DIRTY_FUNC.c_str());
53 if (getDscreenDBGItfFunc == nullptr || getImageDirtyFunc == nullptr) {
54 DHLOGE("get FUNC failed, failed reason: %{public}s.", dlerror());
55 return;
56 }
57 dscreenDbgItfPtr_ = getDscreenDBGItfFunc();
58 imageSetDirtyPtr_ = getImageDirtyFunc();
59 if (dscreenDbgItfPtr_ == nullptr || imageSetDirtyPtr_ == nullptr) {
60 DHLOGE("Get interface failed.");
61 return;
62 }
63 DHLOGI("InitDscreenDBG success.");
64 dscreenDbgItfPtr_->Init();
65 }
66
ConsumeSurface()67 void ImageSourceEncoder::ConsumeSurface()
68 {
69 DHLOGI("%{public}s: ConsumeSurface.", DSCREEN_LOG_TAG);
70 std::unique_lock<std::mutex> bufLock(bufferMtx_);
71 if (consumerSurface_ == nullptr) {
72 DHLOGE("%{public}s: consumerSurface_ is nullptr.", DSCREEN_LOG_TAG);
73 return;
74 }
75 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
76 syncFence_ = SyncFence::INVALID_FENCE;
77 int64_t timestamp = 0;
78 OHOS::Rect damage = {0, 0, 0, 0};
79 SurfaceError surfaceErr = consumerSurface_->AcquireBuffer(surfaceBuffer, syncFence_, timestamp, damage);
80 if (surfaceErr != SURFACE_ERROR_OK) {
81 DHLOGE("%{public}s: consumerSurface_ acquire buffer failed, errcode: %{public}" PRId32, DSCREEN_LOG_TAG,
82 surfaceErr);
83 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
84 return;
85 }
86 int32_t retcode = syncFence_->Wait(SURFACE_SYNC_FENCE_TIMEOUT);
87 if (retcode == -ETIME) {
88 DHLOGE("%{public}s: Sync fence wait timeout, retcode is %{public}" PRId32, DSCREEN_LOG_TAG, retcode);
89 return;
90 }
91 if (pHandler_ != nullptr) {
92 eventContent_.clear();
93 eventContent_ = imageSetDirtyPtr_->GetDamage();
94 }
95 std::vector<OHOS::Rect> damages = VecToDamage(eventContent_);
96 std::shared_ptr<IImageSourceProcessorListener> listener = imageProcessorListener_.lock();
97 if (listener == nullptr) {
98 DHLOGE("%{public}s: Processor listener is null", DSCREEN_LOG_TAG);
99 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
100 return;
101 }
102 listener->OnDamageProcessDone(surfaceBuffer, damages);
103 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
104 }
105
ConfigureEncoder(const VideoParam & configParam)106 int32_t ImageSourceEncoder::ConfigureEncoder(const VideoParam &configParam)
107 {
108 DHLOGI("%{public}s: ConfigureEncoder.", DSCREEN_LOG_TAG);
109 int32_t ret = InitVideoEncoder(configParam);
110 if (ret != DH_SUCCESS) {
111 DHLOGE("%{public}s: Init encoder failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
112 return ret;
113 }
114
115 ret = SetEncoderFormat(configParam);
116 if (ret != DH_SUCCESS) {
117 DHLOGE("%{public}s: Set encoder format failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
118 return ret;
119 }
120
121 encoderSurface_ = videoEncoder_->CreateInputSurface();
122 if (encoderSurface_ == nullptr) {
123 DHLOGE("%{public}s: Create encoder surface failed.", DSCREEN_LOG_TAG);
124 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
125 }
126 configParam_ = configParam;
127 ret = AddSurface();
128 if (ret != DH_SUCCESS) {
129 DHLOGE("%{public}s: Add surface failed ret: %{public}" PRId32, DSCREEN_LOG_TAG, ret);
130 consumerSurface_ = nullptr;
131 producerSurface_ = nullptr;
132 return ret;
133 }
134 return DH_SUCCESS;
135 }
136
AddSurface()137 int32_t ImageSourceEncoder::AddSurface()
138 {
139 DHLOGI("%{public}s: AddSurface.", DSCREEN_LOG_TAG);
140 consumerSurface_ = IConsumerSurface::Create();
141 if (consumerSurface_ == nullptr) {
142 DHLOGE("%{public}s: creat consumer surface failed.", DSCREEN_LOG_TAG);
143 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
144 }
145 sptr<IBufferProducer> producer = consumerSurface_->GetProducer();
146 if (producer == nullptr) {
147 DHLOGE("%{public}s: Creat producer surface failed.", DSCREEN_LOG_TAG);
148 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
149 }
150 producerSurface_ = Surface::CreateSurfaceAsProducer(producer);
151 if (producerSurface_ == nullptr) {
152 DHLOGE("%{public}s: Create preducer surface failed.", DSCREEN_LOG_TAG);
153 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
154 }
155 consumerBufferListener_ = new ConsumerBufferListener(shared_from_this());
156 consumerSurface_->RegisterConsumerListener(consumerBufferListener_);
157 return DH_SUCCESS;
158 }
159
GetConsumerSurface()160 sptr<Surface> ImageSourceEncoder::GetConsumerSurface()
161 {
162 DHLOGI("%{public}s: GetConsumerSurface.", DSCREEN_LOG_TAG);
163 return consumerSurface_;
164 }
165
GetInputSurface()166 sptr<Surface> &ImageSourceEncoder::GetInputSurface()
167 {
168 DHLOGI("%{public}s: GetInputSurface.", DSCREEN_LOG_TAG);
169 if (producerSurface_ == nullptr || !configParam_.GetPartialRefreshFlag()) {
170 return encoderSurface_;
171 }
172 return producerSurface_;
173 }
174
VecToDamage(std::vector<std::vector<int32_t>> eventContent)175 std::vector<OHOS::Rect> ImageSourceEncoder::VecToDamage(std::vector<std::vector<int32_t>> eventContent)
176 {
177 DHLOGI("%{public}s: VecToDamage.", DSCREEN_LOG_TAG);
178 std::vector<OHOS::Rect> damages;
179 for (auto item : eventContent) {
180 OHOS::Rect damage = {0, 0, 0, 0};
181 damage.x = item[0];
182 damage.y = item[1];
183 damage.w = item[2];
184 damage.h = item[3];
185 damages.push_back(damage);
186 }
187 return damages;
188 }
189
GetEncoderInputSurfaceBuffer()190 sptr<SurfaceBuffer> ImageSourceEncoder::GetEncoderInputSurfaceBuffer()
191 {
192 DHLOGI("%{public}s: GetEncoderInputSurfaceBuffer.", DSCREEN_LOG_TAG);
193 OHOS::BufferRequestConfig requestConfig;
194 requestConfig.width = static_cast<int32_t>(configParam_.GetVideoWidth());
195 requestConfig.height = static_cast<int32_t>(configParam_.GetVideoHeight());
196 requestConfig.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
197 requestConfig.strideAlignment = STRIDE_ALIGNMENT;
198 requestConfig.format = GraphicPixelFormat::GRAPHIC_PIXEL_FMT_RGBA_8888;
199 requestConfig.timeout = 0;
200 sptr<OHOS::SurfaceBuffer> encoderSurfaceBuffer = nullptr;
201 int32_t releaseFence = -1;
202 SurfaceError surfaceErr = encoderSurface_->RequestBuffer(encoderSurfaceBuffer, releaseFence, requestConfig);
203 if (surfaceErr != GSERROR_OK || encoderSurfaceBuffer == nullptr) {
204 DHLOGE("%{public}s: RequestBuffer failed.", DSCREEN_LOG_TAG);
205 encoderSurface_->CancelBuffer(encoderSurfaceBuffer);
206 }
207 return encoderSurfaceBuffer;
208 }
209
FeedEncoderData(sptr<SurfaceBuffer> & surfaceBuffer)210 int32_t ImageSourceEncoder::FeedEncoderData(sptr<SurfaceBuffer> &surfaceBuffer)
211 {
212 sptr<OHOS::SurfaceBuffer> encoderSurfaceBuffer = GetEncoderInputSurfaceBuffer();
213 if (encoderSurfaceBuffer == nullptr) {
214 DHLOGE("Get encoder input producer surface buffer failed.");
215 return ERR_DH_SCREEN_CODEC_SURFACE_ERROR;
216 }
217 uint32_t screenDataSize = configParam_.GetVideoWidth() * configParam_.GetVideoHeight() * RGBA_CHROMA;
218 auto encoderSurfaceAddr = static_cast<uint8_t*>(encoderSurfaceBuffer->GetVirAddr());
219 auto surfaceAddr = static_cast<uint8_t*>(surfaceBuffer->GetVirAddr());
220 int32_t ret = memcpy_s(encoderSurfaceAddr, screenDataSize, surfaceAddr, screenDataSize);
221 if (ret != EOK) {
222 DHLOGE("%{public}s: surfaceBuffer memcpy_s run failed.", DSCREEN_LOG_TAG);
223 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
224 encoderSurface_->CancelBuffer(encoderSurfaceBuffer);
225 return ret;
226 }
227 BufferFlushConfig flushConfig = { {0, 0, encoderSurfaceBuffer->GetWidth(), encoderSurfaceBuffer->GetHeight()}, 0};
228 DHLOGI("%{public}s: FeedEncoderData to encoder.", DSCREEN_LOG_TAG);
229 SurfaceError surfaceErr = encoderSurface_->FlushBuffer(encoderSurfaceBuffer, -1, flushConfig);
230 if (surfaceErr != SURFACE_ERROR_OK) {
231 DHLOGE("%{public}s: encoderSurface_ flush buffer failed.", DSCREEN_LOG_TAG);
232 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
233 encoderSurface_->CancelBuffer(encoderSurfaceBuffer);
234 return surfaceErr;
235 }
236 consumerSurface_->ReleaseBuffer(surfaceBuffer, -1);
237 return DH_SUCCESS;
238 }
239
ReleaseEncoder()240 int32_t ImageSourceEncoder::ReleaseEncoder()
241 {
242 DHLOGI("%{public}s: ReleaseEncoder.", DSCREEN_LOG_TAG);
243 if (videoEncoder_ == nullptr) {
244 DHLOGE("%{public}s: Encoder is null.", DSCREEN_LOG_TAG);
245 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
246 }
247
248 int32_t ret = videoEncoder_->Release();
249 if (ret != MediaAVCodec::AVCS_ERR_OK) {
250 DHLOGE("%{public}s: Release encoder failed.", DSCREEN_LOG_TAG);
251 return ERR_DH_SCREEN_CODEC_RELEASE_FAILED;
252 }
253 if (pHandler_ != nullptr) {
254 dscreenDbgItfPtr_->Release();
255 dlclose(pHandler_);
256 }
257 encodeVideoCallback_ = nullptr;
258 videoEncoder_ = nullptr;
259 consumerBufferListener_ = nullptr;
260 return DH_SUCCESS;
261 }
262
StartEncoder()263 int32_t ImageSourceEncoder::StartEncoder()
264 {
265 DHLOGI("%{public}s: StartEncoder.", DSCREEN_LOG_TAG);
266 if (videoEncoder_ == nullptr) {
267 DHLOGE("%{public}s: Encoder is null.", DSCREEN_LOG_TAG);
268 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
269 }
270
271 int32_t ret = videoEncoder_->Prepare();
272 if (ret != MediaAVCodec::AVCS_ERR_OK) {
273 DHLOGE("%{public}s: Prepare encoder failed.", DSCREEN_LOG_TAG);
274 return ERR_DH_SCREEN_CODEC_PREPARE_FAILED;
275 }
276
277 ret = videoEncoder_->Start();
278 if (ret != MediaAVCodec::AVCS_ERR_OK) {
279 DHLOGE("%{public}s: Start encoder failed.", DSCREEN_LOG_TAG);
280 return ERR_DH_SCREEN_CODEC_START_FAILED;
281 }
282 InitDscreenDBG();
283 return DH_SUCCESS;
284 }
285
StopEncoder()286 int32_t ImageSourceEncoder::StopEncoder()
287 {
288 DHLOGI("%{public}s: StopEncoder.", DSCREEN_LOG_TAG);
289 if (videoEncoder_ == nullptr) {
290 DHLOGE("%{public}s: Encoder is null.", DSCREEN_LOG_TAG);
291 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
292 }
293
294 int32_t ret = videoEncoder_->Flush();
295 if (ret != MediaAVCodec::AVCS_ERR_OK) {
296 DHLOGE("%{public}s: Flush encoder failed.", DSCREEN_LOG_TAG);
297 }
298
299 ret = videoEncoder_->Stop();
300 if (ret != MediaAVCodec::AVCS_ERR_OK) {
301 DHLOGE("%{public}s: Stop encoder failed.", DSCREEN_LOG_TAG);
302 return ERR_DH_SCREEN_CODEC_STOP_FAILED;
303 }
304 std::unique_lock<std::mutex> bufLock(bufferMtx_);
305 if (consumerSurface_ != nullptr) {
306 ret = consumerSurface_->UnregisterConsumerListener();
307 if (ret != SURFACE_ERROR_OK) {
308 DHLOGE("Unregister Consumer Listener failed.");
309 }
310 consumerSurface_ = nullptr;
311 }
312 producerSurface_ = nullptr;
313 return DH_SUCCESS;
314 }
315
InitVideoEncoder(const VideoParam & configParam)316 int32_t ImageSourceEncoder::InitVideoEncoder(const VideoParam &configParam)
317 {
318 DHLOGI("%{public}s: InitVideoEncoder.", DSCREEN_LOG_TAG);
319 switch (configParam.GetCodecType()) {
320 case VIDEO_CODEC_TYPE_VIDEO_H264:
321 videoEncoder_ = MediaAVCodec::VideoEncoderFactory::CreateByMime(
322 std::string(MediaAVCodec::CodecMimeType::VIDEO_AVC));
323 break;
324 case VIDEO_CODEC_TYPE_VIDEO_H265:
325 videoEncoder_ = MediaAVCodec::VideoEncoderFactory::CreateByMime(
326 std::string(MediaAVCodec::CodecMimeType::VIDEO_HEVC));
327 break;
328 default:
329 DHLOGE("%{public}s: codecType is invalid!", DSCREEN_LOG_TAG);
330 videoEncoder_ = nullptr;
331 }
332
333 if (videoEncoder_ == nullptr) {
334 DHLOGE("%{public}s: Create videoEncoder failed.", DSCREEN_LOG_TAG);
335 return ERR_DH_SCREEN_TRANS_CREATE_CODEC_FAILED;
336 }
337
338 encodeVideoCallback_ = std::make_shared<ImageEncoderCallback>(shared_from_this());
339 int32_t ret = videoEncoder_->SetCallback(encodeVideoCallback_);
340 if (ret != MediaAVCodec::AVCS_ERR_OK) {
341 DHLOGE("%{public}s: Set codec callback failed.", DSCREEN_LOG_TAG);
342 return ERR_DH_SCREEN_CODEC_SET_CALLBACK_FAILED;
343 }
344
345 return DH_SUCCESS;
346 }
347
SetEncoderFormat(const VideoParam & configParam)348 int32_t ImageSourceEncoder::SetEncoderFormat(const VideoParam &configParam)
349 {
350 DHLOGI("%{public}s: SetEncoderFormat.", DSCREEN_LOG_TAG);
351 if (videoEncoder_ == nullptr) {
352 DHLOGE("%{public}s: Encoder is null.", DSCREEN_LOG_TAG);
353 return ERR_DH_SCREEN_TRANS_NULL_VALUE;
354 }
355
356 switch (configParam.GetCodecType()) {
357 case VIDEO_CODEC_TYPE_VIDEO_H264:
358 imageFormat_.PutStringValue("codec_mime", MediaAVCodec::CodecMimeType::VIDEO_AVC);
359 break;
360 case VIDEO_CODEC_TYPE_VIDEO_H265:
361 imageFormat_.PutStringValue("codec_mime", MediaAVCodec::CodecMimeType::VIDEO_HEVC);
362 break;
363 default:
364 DHLOGE("%{public}s: Codec type is invalid.", DSCREEN_LOG_TAG);
365 return ERR_DH_SCREEN_TRANS_ILLEGAL_PARAM;
366 }
367
368 imageFormat_.PutIntValue("pixel_format", static_cast<int32_t>(MediaAVCodec::VideoPixelFormat::RGBA));
369 imageFormat_.PutLongValue("max_input_size", MAX_YUV420_BUFFER_SIZE);
370 imageFormat_.PutIntValue("width", configParam.GetVideoWidth());
371 imageFormat_.PutIntValue("height", configParam.GetVideoHeight());
372 imageFormat_.PutDoubleValue("frame_rate", configParam.GetFps());
373
374 int32_t ret = videoEncoder_->Configure(imageFormat_);
375 if (ret != MediaAVCodec::AVCS_ERR_OK) {
376 DHLOGE("%{public}s: Configure encoder failed.", DSCREEN_LOG_TAG);
377 return ERR_DH_SCREEN_CODEC_CONFIGURE_FAILED;
378 }
379 return DH_SUCCESS;
380 }
381
OnError(MediaAVCodec::AVCodecErrorType errorType,int32_t errorCode)382 void ImageSourceEncoder::OnError(MediaAVCodec::AVCodecErrorType errorType, int32_t errorCode)
383 {
384 DHLOGI("%{public}s: Encoder error, errorType:%{public}" PRId32 ", errorCode:%{public}" PRId32, DSCREEN_LOG_TAG,
385 errorType, errorCode);
386 std::shared_ptr<IImageSourceProcessorListener> listener = imageProcessorListener_.lock();
387 if (listener == nullptr) {
388 DHLOGE("%{public}s: Processor listener is null", DSCREEN_LOG_TAG);
389 return;
390 }
391 listener->OnProcessorStateNotify(errorCode);
392 }
393
OnOutputBufferAvailable(uint32_t index,MediaAVCodec::AVCodecBufferInfo info,MediaAVCodec::AVCodecBufferFlag flag,std::shared_ptr<Media::AVSharedMemory> buffer)394 void ImageSourceEncoder::OnOutputBufferAvailable(uint32_t index, MediaAVCodec::AVCodecBufferInfo info,
395 MediaAVCodec::AVCodecBufferFlag flag, std::shared_ptr<Media::AVSharedMemory> buffer)
396 {
397 DHLOGD("%{public}s: OnOutputBufferAvailable, receiv H264 data from encoder.", DSCREEN_LOG_TAG);
398 std::shared_ptr<IImageSourceProcessorListener> listener = imageProcessorListener_.lock();
399 if (listener == nullptr) {
400 DHLOGE("%{public}s: Processor listener is null", DSCREEN_LOG_TAG);
401 return;
402 }
403 if (videoEncoder_ == nullptr) {
404 DHLOGE("%{public}s: Encoder is null.", DSCREEN_LOG_TAG);
405 return;
406 }
407
408 encoderBufferInfo_ = info;
409 if (buffer == nullptr) {
410 DHLOGE("%{public}s: Buffer is null, index = %{public}d", DSCREEN_LOG_TAG, index);
411 return;
412 }
413
414 size_t dataSize = static_cast<size_t>(info.size);
415 if (dataSize == 0 || dataSize > DATA_BUFFER_MAX_SIZE) {
416 DHLOGE("%{public}s:OnOutputBufferAvailable params invalid, size: %{public}zu", DSCREEN_LOG_TAG, dataSize);
417 return;
418 }
419 auto dataBuf = std::make_shared<DataBuffer>(dataSize);
420 int32_t ret = memcpy_s(dataBuf->Data(), dataBuf->Capacity(), buffer->GetBase(), dataSize);
421 if (ret != EOK) {
422 DHLOGE("%{public}s: Copy data failed.", DSCREEN_LOG_TAG);
423 return;
424 }
425 dataBuf->SetDataType(VIDEO_FULL_SCREEN_DATA);
426 dataBuf->SetSize(dataSize);
427 listener->OnImageProcessDone(dataBuf);
428 ret = videoEncoder_->ReleaseOutputBuffer(index);
429 if (ret != MediaAVCodec::AVCS_ERR_OK) {
430 DHLOGE("%{public}s: videoEncoder ReleaseOutputBuffer failed.", DSCREEN_LOG_TAG);
431 }
432 }
433
OnInputBufferAvailable(uint32_t index,std::shared_ptr<Media::AVSharedMemory> buffer)434 void ImageSourceEncoder::OnInputBufferAvailable(uint32_t index, std::shared_ptr<Media::AVSharedMemory> buffer)
435 {
436 (void) index;
437 }
438
OnOutputFormatChanged(const Media::Format & format)439 void ImageSourceEncoder::OnOutputFormatChanged(const Media::Format &format)
440 {
441 (void) format;
442 }
443 } // namespace DistributedHardware
444 } // namespace OHOS
445