vdr-plugin-softhddevice-drm-gles 1.4.0
buf2rgb.cpp
Go to the documentation of this file.
1
20extern "C" {
21#include <libavutil/imgutils.h>
22#include <libswscale/swscale.h>
23}
24
25#include <sys/mman.h>
26#include <drm_fourcc.h>
27
28#include "buf2rgb.h"
29#include "logger.h"
30#include "drmbuffer.h"
31
32#define OPAQUE 0xff
33#define TRANSPARENT 0x00
34#define UNMULTIPLY(color, alpha) ((0xff * color) / alpha)
35#define BLEND(back, front, alpha) ((front * alpha) + (back * (255 - alpha))) / 255
36
37/****************************************************************************************
38 * Image data conversion helpers
39 ***************************************************************************************/
40
44enum AVPixelFormat DrmFormatToAVFormat(cDrmBuffer *buf)
45{
46 if (buf->PixFmt() == DRM_FORMAT_NV12)
47 return AV_PIX_FMT_NV12;
48
49 if (buf->PixFmt() == DRM_FORMAT_YUV420)
50 return AV_PIX_FMT_YUV420P;
51
52 if (buf->PixFmt() == DRM_FORMAT_ARGB8888)
53 return AV_PIX_FMT_RGBA;
54
55 if (buf->PixFmt() == DRM_FORMAT_P030)
56 return AV_PIX_FMT_NONE;
57
58 return AV_PIX_FMT_NONE;
59}
60
74uint8_t *BufToRgb(cDrmBuffer *buf, int *size, int dstW, int dstH, enum AVPixelFormat dstPixFmt)
75{
76 uint8_t *srcData[4], *dstData[4];
77 int srcLinesize[4], dstLinesize[4];
78
79 int srcW = buf->Width();
80 int srcH = buf->Height();
81
82 enum AVPixelFormat src_pix_fmt = DrmFormatToAVFormat(buf);
83 if (src_pix_fmt == AV_PIX_FMT_NONE) {
84 LOGERROR("grab: %s: pixel format is not supported!", __FUNCTION__);
85 return NULL;
86 }
87
88 int dstBufsize = 0;
89 struct SwsContext *swsCtx;
90 int ret;
91 void *buffer = NULL;
92
93 // planes aren't mmapped, return
94 // this should be done before in VideoCloneBuf
95 if (!buf->Plane(0)) {
96 LOGERROR("grab: %s: prime data is not mapped!", __FUNCTION__);
97 return NULL;
98 }
99
100 // convert yuv to rgb
101 swsCtx = sws_getContext(srcW, srcH, src_pix_fmt,
102 dstW, dstH, dstPixFmt,
103 SWS_BILINEAR, NULL, NULL, NULL);
104 if (!swsCtx) {
105 LOGERROR("grab: %s: Could not create swsCtx", __FUNCTION__);
106 munmap(buffer, buf->Size(0));
107 return NULL;
108 }
109
110 if ((ret = av_image_alloc(dstData, dstLinesize, dstW, dstH, dstPixFmt, 1)) < 0) {
111 LOGERROR("grab: %s: Could not alloc dst image", __FUNCTION__);
112 munmap(buffer, buf->Size(0));
113 sws_freeContext(swsCtx);
114 return NULL;
115 }
116 dstBufsize = ret;
117
118 // copy src pitches and data
119 for (int i = 0; i < buf->NumPlanes(); i++) {
120 srcLinesize[i] = buf->Pitch(i);
121 srcData[i] = buf->Plane(i) + buf->Offset(i);
122 }
123
124 // scale image
125 sws_scale(swsCtx,
126 (const uint8_t * const*)srcData, srcLinesize, 0, srcH,
127 dstData, dstLinesize);
128
129 if (buffer)
130 munmap(buffer, buf->Size(0));
131 sws_freeContext(swsCtx);
132 *size = dstBufsize;
133
134 LOGDEBUG2(L_GRAB, "grab: %s: return image at %p size %d", __FUNCTION__, dstData[0], dstBufsize);
135 return dstData[0];
136}
137
152uint8_t *ScaleRgb24(uint8_t *src, int *size, int srcW, int srcH, int dstW, int dstH)
153{
154 struct SwsContext *swsCtx;
155 int dstBufsize = 0;
156 int ret;
157
158 uint8_t *dstData[4];
159 int dstLinesize[4];
160 uint8_t *srcData[4] = {src, NULL, NULL, NULL};
161 int srcLinesize[4] = {3 * srcW, 0, 0, 0};
162
163 swsCtx = sws_getContext(srcW, srcH, AV_PIX_FMT_RGB24,
164 dstW, dstH, AV_PIX_FMT_RGB24,
165 SWS_BILINEAR, NULL, NULL, NULL);
166 if (!swsCtx) {
167 LOGERROR("grab: %s: Could not create swsCtx", __FUNCTION__);
168 return NULL;
169 }
170
171 if ((ret = av_image_alloc(dstData, dstLinesize, dstW, dstH, AV_PIX_FMT_RGB24, 1)) < 0) {
172 LOGERROR("grab: %s: Could not alloc dst image", __FUNCTION__);
173 sws_freeContext(swsCtx);
174 return NULL;
175 }
176 dstBufsize = ret;
177
178 sws_scale(swsCtx,
179 (const uint8_t * const*)srcData, srcLinesize, 0, srcH,
180 dstData, dstLinesize);
181
182 sws_freeContext(swsCtx);
183 *size = dstBufsize;
184
185 LOGDEBUG2(L_GRAB, "grab: %s: return scaled image at %p size %d", __FUNCTION__, dstData[0], dstBufsize);
186 return dstData[0];
187}
188
203void AlphaBlend(uint8_t *result, uint8_t *front, uint8_t *back, const unsigned int width, const unsigned int height)
204{
205 for (unsigned long index = 0; index < width * height; index++) {
206 const uint8_t frontAlpha = front[3];
207
208 if (frontAlpha == TRANSPARENT) {
209 for (int i = 0; i < 3; i++) {
210 result[i] = back[i];
211 }
212 back += 3;
213 front += 4;
214 result += 3;
215 continue;
216 }
217
218 if (frontAlpha == OPAQUE) {
219 for (int i = 0; i < 3; i++) {
220 result[i] = front[i];
221 }
222 back += 3;
223 front += 4;
224 result += 3;
225 continue;
226 }
227
228 const uint8_t backR = back[0];
229 const uint8_t backG = back[1];
230 const uint8_t backB = back[2];
231
232 const uint8_t frontR = UNMULTIPLY(front[0], frontAlpha);
233 const uint8_t frontG = UNMULTIPLY(front[1], frontAlpha);
234 const uint8_t frontB = UNMULTIPLY(front[2], frontAlpha);
235
236 const uint8_t R = BLEND(backR, frontR, frontAlpha);
237 const uint8_t G = BLEND(backG, frontG, frontAlpha);
238 const uint8_t B = BLEND(backB, frontB, frontAlpha);
239
240 result[0] = R;
241 result[1] = G;
242 result[2] = B;
243
244 back += 3;
245 front += 4;
246 result += 3;
247 }
248}
249
264int BlitVideo(uint8_t *dst, uint8_t *src, int dstW, int dstH, int dstX, int dstY, int srcW, int srcH)
265{
266 int srcStride = srcW * 3;
267 int dstStride = dstW * 3;
268
269 if ((dstX + srcW > dstW) || (dstY + srcH > dstH)) {
270 LOGDEBUG2(L_GRAB, "grab: %s: wrong dimensions, cropping not supported!", __FUNCTION__);
271 return -1;
272 }
273
274 // blit the (scaled) image into dst
275 for (int y = 0; y < srcH; y++) {
276 memcpy(&dst[((dstY + y) * dstStride + dstX * 3)], &src[y * srcStride], srcStride);
277 }
278
279 return 0;
280}
281
288void PrintStreamData(const uint8_t *data, int size)
289{
290 LOGDEBUG("Stream: %02x %02x %02x %02x %02x %02x %02x %02x %02x "
291 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x "
292 "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x size %d",
293 data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8],
294 data[9], data[10], data[11], data[12], data[13], data[14], data[15], data[16], data[17],
295 data[18], data[19], data[20], data[21], data[22], data[23], data[24], data[25], data[26],
296 data[27], data[28], data[29], data[30], data[31], data[32], data[33], data[34], size);
297}
#define UNMULTIPLY(color, alpha)
Definition: buf2rgb.cpp:34
#define BLEND(back, front, alpha)
Definition: buf2rgb.cpp:35
enum AVPixelFormat DrmFormatToAVFormat(cDrmBuffer *buf)
Convert a DRM format to a ffmpeg AV format.
Definition: buf2rgb.cpp:44
void PrintStreamData(const uint8_t *data, int size)
Print raw stream data.
Definition: buf2rgb.cpp:288
#define TRANSPARENT
Definition: buf2rgb.cpp:33
uint8_t * BufToRgb(cDrmBuffer *buf, int *size, int dstW, int dstH, enum AVPixelFormat dstPixFmt)
Convert a DRM buffer to rgb format image.
Definition: buf2rgb.cpp:74
#define OPAQUE
Definition: buf2rgb.cpp:32
int BlitVideo(uint8_t *dst, uint8_t *src, int dstW, int dstH, int dstX, int dstY, int srcW, int srcH)
Blit the video on black background.
Definition: buf2rgb.cpp:264
void AlphaBlend(uint8_t *result, uint8_t *front, uint8_t *back, const unsigned int width, const unsigned int height)
Blend two images.
Definition: buf2rgb.cpp:203
uint8_t * ScaleRgb24(uint8_t *src, int *size, int srcW, int srcH, int dstW, int dstH)
Scale an image.
Definition: buf2rgb.cpp:152
Some helper functions header file.
uint32_t Pitch(int idx)
Definition: drmbuffer.h:96
uint32_t Width(void)
Definition: drmbuffer.h:67
uint32_t Height(void)
Definition: drmbuffer.h:69
uint8_t * Plane(int idx)
Definition: drmbuffer.h:89
int NumPlanes(void)
Definition: drmbuffer.h:83
uint32_t Size(int idx)
Definition: drmbuffer.h:99
uint32_t PixFmt(void)
Definition: drmbuffer.h:71
uint32_t Offset(int idx)
Definition: drmbuffer.h:93
DRM buffer header file.
Logger class header file.
#define LOGDEBUG2
Definition: logger.h:50
#define LOGDEBUG
Definition: logger.h:49
#define LOGERROR
Definition: logger.h:46
#define L_GRAB
Definition: logger.h:71