1 /*
2 * Copyright (c) 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 * http://www.apache.org/licenses/LICENSE-2.0
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS,
9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 * See the License for the specific language governing permissions and
11 * limitations under the License.
12 */
13
14 #include "node_utils.h"
15 #include "map"
16 #include "camera.h"
17 extern "C" {
18 #ifdef DEVICE_USAGE_FFMPEG_ENABLE
19 #include "libavutil/frame.h"
20 #include "libavcodec/avcodec.h"
21 #include "libswscale/swscale.h"
22 #include "libavutil/imgutils.h"
23 #endif // DEVICE_USAGE_FFMPEG_ENABLE
24 }
25
26 namespace OHOS::Camera {
27 using namespace std;
28
29 const int32_t INVALID_ARGUMENT = -1;
30
ConvertOhosFormat2AVPixelFormat(uint32_t format)31 static enum AVPixelFormat ConvertOhosFormat2AVPixelFormat(uint32_t format)
32 {
33 static map<uint32_t, enum AVPixelFormat> ohosFormat2AVPixelFormatMap = {
34 {CAMERA_FORMAT_RGBA_8888, AV_PIX_FMT_RGBA},
35 {CAMERA_FORMAT_RGB_888, AV_PIX_FMT_RGB24},
36 {CAMERA_FORMAT_YCRCB_420_SP, AV_PIX_FMT_NV21},
37 {CAMERA_FORMAT_YCRCB_422_P, AV_PIX_FMT_YUYV422},
38 };
39 auto it = ohosFormat2AVPixelFormatMap.find(format);
40 if (it != ohosFormat2AVPixelFormatMap.end()) {
41 return it->second;
42 }
43 return AV_PIX_FMT_NONE;
44 }
45
ImageFormatConvert(ImageBufferInfo & srcBufferInfo,ImageBufferInfo & dstBufferInfo)46 int32_t NodeUtils::ImageFormatConvert(ImageBufferInfo &srcBufferInfo, ImageBufferInfo &dstBufferInfo)
47 {
48 static uint32_t convertCount = 0;
49 uint32_t id = convertCount++;
50 auto srcAVFmt = ConvertOhosFormat2AVPixelFormat(srcBufferInfo.format);
51 auto dstAVFmt = ConvertOhosFormat2AVPixelFormat(dstBufferInfo.format);
52 if (srcAVFmt == AV_PIX_FMT_NONE || dstAVFmt == AV_PIX_FMT_NONE) {
53 CAMERA_LOGE("NodeUtils::ImageFormatConvert err, id = %{public}d, unsupport format: %{public}d -> %{public}d",
54 id, srcBufferInfo.format, dstBufferInfo.format);
55 return INVALID_ARGUMENT;
56 }
57 CAMERA_LOGI("NodeUtils::ImageFormatConvert Start ====== id = %{public}d", id);
58 CAMERA_LOGI("====imageSize: %{public}d * %{public}d -> %{public}d * %{public}d, format: %{public}d -> %{public}d",
59 srcBufferInfo.width, srcBufferInfo.height, dstBufferInfo.width, dstBufferInfo.height,
60 srcBufferInfo.format, dstBufferInfo.format);
61 CAMERA_LOGI("====buffer: %{public}p [%{public}d] -> %{public}p [%{public}d]",
62 srcBufferInfo.bufferAddr, srcBufferInfo.bufferSize,
63 dstBufferInfo.bufferAddr, dstBufferInfo.bufferSize);
64
65 AVFrame *pFrameSrc = av_frame_alloc();
66 if (pFrameSrc == nullptr) {
67 CAMERA_LOGE("ImageFormatConvert Error pFrameSrc == nullptr");
68 return INVALID_ARGUMENT;
69 }
70 AVFrame *pFrameDst = av_frame_alloc();
71 if (pFrameDst == nullptr) {
72 CAMERA_LOGE("ImageFormatConvert Error pFrameDst == nullptr");
73 av_frame_free(&pFrameSrc);
74 return INVALID_ARGUMENT;
75 }
76
77 av_image_fill_arrays(pFrameSrc->data, pFrameSrc->linesize, static_cast<uint8_t *>(srcBufferInfo.bufferAddr),
78 srcAVFmt, srcBufferInfo.width, srcBufferInfo.height, 1);
79 av_image_fill_arrays(pFrameDst->data, pFrameDst->linesize, static_cast<uint8_t *>(dstBufferInfo.bufferAddr),
80 dstAVFmt, dstBufferInfo.width, dstBufferInfo.height, 1);
81
82 struct SwsContext* imgCtx = sws_getContext(
83 srcBufferInfo.width, srcBufferInfo.height, srcAVFmt,
84 dstBufferInfo.width, dstBufferInfo.height, dstAVFmt,
85 SWS_BILINEAR, 0, 0, 0);
86
87 auto ret = sws_scale(imgCtx, pFrameSrc->data, pFrameSrc->linesize, 0, srcBufferInfo.height,
88 pFrameDst->data, pFrameDst->linesize);
89
90 sws_freeContext(imgCtx);
91 av_frame_free(&pFrameSrc);
92 av_frame_free(&pFrameDst);
93 CAMERA_LOGD("NodeUtils::ImageFormatConvert End [%{public}d] ====== %{public}d", ret, id);
94
95 return 0;
96 }
97
BufferScaleFormatTransform(std::shared_ptr<IBuffer> & buffer,void * dstBuffer,uint32_t dstBufferSize)98 void NodeUtils::BufferScaleFormatTransform(std::shared_ptr<IBuffer>& buffer, void *dstBuffer, uint32_t dstBufferSize)
99 {
100 if (buffer == nullptr) {
101 CAMERA_LOGI("BufferScaleFormatTransform Error buffer == nullptr");
102 return;
103 }
104
105 if (buffer->GetCurWidth() == buffer->GetWidth()
106 && buffer->GetCurHeight() == buffer->GetHeight()
107 && buffer->GetCurFormat() == buffer->GetFormat()) {
108 CAMERA_LOGE("no need ImageFormatConvert, nothing to do");
109 return;
110 }
111 if (buffer->GetIsValidDataInSurfaceBuffer()) {
112 CAMERA_LOGD("IsValidDataInSurfaceBuffer ture");
113 if (memcpy_s(buffer->GetVirAddress(), buffer->GetSize(),
114 buffer->GetSuffaceBufferAddr(), buffer->GetSuffaceBufferSize()) != 0) {
115 CAMERA_LOGE("BufferScaleFormatTransform Fail, memcpy_s error");
116 return;
117 }
118 }
119
120 NodeUtils::ImageBufferInfo srcInfo = {
121 .width = buffer->GetCurWidth(),
122 .height = buffer->GetCurHeight(),
123 .format = buffer->GetCurFormat(),
124 .bufferAddr = buffer->GetVirAddress(),
125 .bufferSize = buffer->GetSize(),
126 };
127
128 NodeUtils::ImageBufferInfo dstInfo = {
129 .width = buffer->GetWidth(),
130 .height = buffer->GetHeight(),
131 .format = buffer->GetFormat(),
132 .bufferAddr = buffer->GetSuffaceBufferAddr(),
133 .bufferSize = buffer->GetSuffaceBufferSize()
134 };
135
136 if (dstBuffer != nullptr && dstBufferSize != 0) {
137 dstInfo.bufferAddr = dstBuffer;
138 dstInfo.bufferSize = dstBufferSize;
139 }
140
141 if (NodeUtils::ImageFormatConvert(srcInfo, dstInfo) == 0) {
142 buffer->SetCurFormat(buffer->GetFormat());
143 buffer->SetCurWidth(buffer->GetWidth());
144 buffer->SetCurHeight(buffer->GetHeight());
145 buffer->SetIsValidDataInSurfaceBuffer(true);
146 }
147 }
148 };