vfs: check userland buffers before reading them.
[haiku.git] / src / add-ons / media / plugins / ffmpeg / gfx_util.cpp
blobf20c61c2516119fa14cfc0ab589b892a89b5d90d
1 #include "gfx_util.h"
3 #include <strings.h>
4 #include <stdio.h>
6 extern "C" {
7 #include <libavutil/pixdesc.h>
10 #include "CpuCapabilities.h"
11 #include "gfx_conv_c.h"
12 #include "gfx_conv_mmx.h"
15 // ref docs
16 // http://www.joemaller.com/fcp/fxscript_yuv_color.shtml
19 #if DEBUG
20 #define TRACE(a...) printf(a)
21 #else
22 #define TRACE(a...)
23 #endif
25 #if LIBAVCODEC_VERSION_INT < ((54 << 16) | (50 << 8))
26 #define AVPixelFormat PixelFormat
27 #define AV_PIX_FMT_NONE PIX_FMT_NONE
28 #define AV_PIX_FMT_YUV410P PIX_FMT_YUV410P
29 #define AV_PIX_FMT_YUV411P PIX_FMT_YUV411P
30 #define AV_PIX_FMT_YUV420P PIX_FMT_YUV420P
31 #define AV_PIX_FMT_YUVJ420P PIX_FMT_YUVJ420P
32 #define AV_PIX_FMT_YUV422P PIX_FMT_YUV422P
33 #define AV_PIX_FMT_YUVJ422P PIX_FMT_YUVJ422P
34 #define AV_PIX_FMT_YUYV422 PIX_FMT_YUYV422
35 #define AV_PIX_FMT_YUV420P10LE PIX_FMT_YUV420P10LE
36 #define AV_PIX_FMT_YUV444P PIX_FMT_YUV444P
37 #define AV_PIX_FMT_RGB24 PIX_FMT_RGB24
38 #define AV_PIX_FMT_BGR24 PIX_FMT_BGR24
39 #define AV_PIX_FMT_RGB565 PIX_FMT_RGB565
40 #define AV_PIX_FMT_RGB555 PIX_FMT_RGB555
41 #define AV_PIX_FMT_GRAY8 PIX_FMT_GRAY8
42 #define AV_PIX_FMT_MONOBLACK PIX_FMT_MONOBLACK
43 #define AV_PIX_FMT_PAL8 PIX_FMT_PAL8
44 #define AV_PIX_FMT_BGR32 PIX_FMT_BGR32
45 #define AV_PIX_FMT_BGR565 PIX_FMT_BGR565
46 #define AV_PIX_FMT_BGR555 PIX_FMT_BGR555
47 #define AV_PIX_FMT_RGB32 PIX_FMT_RGB32
48 #define AV_PIX_FMT_GBRP PIX_FMT_GBRP
49 #endif
52 //! This function will try to find the best colorspaces for both the ff-codec
53 // and the Media Kit sides.
54 gfx_convert_func
55 resolve_colorspace(color_space colorSpace, AVPixelFormat pixelFormat, int width,
56 int height)
58 CPUCapabilities cpu;
60 switch (colorSpace) {
61 case B_RGB32:
62 // Planar Formats
63 if (pixelFormat == AV_PIX_FMT_YUV410P) {
64 TRACE("resolve_colorspace: gfx_conv_yuv410p_rgb32_c\n");
65 return gfx_conv_yuv410p_rgb32_c;
68 if (pixelFormat == AV_PIX_FMT_YUV411P) {
69 TRACE("resolve_colorspace: gfx_conv_yuv411p_rgb32_c\n");
70 return gfx_conv_yuv411p_rgb32_c;
73 if (pixelFormat == AV_PIX_FMT_YUV420P
74 || pixelFormat == AV_PIX_FMT_YUVJ420P) {
75 #ifndef __x86_64__
76 if (cpu.HasSSSE3() && width % 8 == 0 && height % 2 == 0) {
77 TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_ssse3\n");
78 return gfx_conv_yuv420p_rgba32_ssse3;
79 } else if (cpu.HasSSE2() && width % 8 == 0 && height % 2 == 0) {
80 TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_sse2\n");
81 return gfx_conv_yuv420p_rgba32_sse2;
82 } else if (cpu.HasSSE1() && width % 4 == 0
83 && height % 2 == 0) {
84 TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_sse\n");
85 return gfx_conv_yuv420p_rgba32_sse;
87 #endif
88 TRACE("resolve_colorspace: gfx_conv_YCbCr420p_RGB32_c\n");
89 return gfx_conv_YCbCr420p_RGB32_c;
92 if (pixelFormat == AV_PIX_FMT_YUV422P
93 || pixelFormat == AV_PIX_FMT_YUVJ422P) {
94 #ifndef __x86_64__
95 if (cpu.HasSSSE3() && width % 8 == 0) {
96 TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_ssse3\n");
97 return gfx_conv_yuv422p_rgba32_ssse3;
98 } else if (cpu.HasSSE2() && width % 8 == 0) {
99 TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_sse2\n");
100 return gfx_conv_yuv422p_rgba32_sse2;
101 } else if (cpu.HasSSE1() && width % 4 == 0) {
102 TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_sse\n");
103 return gfx_conv_yuv422p_rgba32_sse;
105 #endif
106 TRACE("resolve_colorspace: gfx_conv_YCbCr422p_RGB32_c\n");
107 return gfx_conv_YCbCr422_RGB32_c;
110 if (pixelFormat == AV_PIX_FMT_GBRP) {
111 return gfx_conv_GBRP_RGB32_c;
114 // Packed Formats
115 if (pixelFormat == AV_PIX_FMT_YUYV422) {
116 #ifndef __x86_64__
117 if (cpu.HasSSSE3() && width % 8 == 0) {
118 return gfx_conv_yuv422_rgba32_ssse3;
119 } else if (cpu.HasSSE2() && width % 8 == 0) {
120 return gfx_conv_yuv422_rgba32_sse2;
121 } else if (cpu.HasSSE1() && width % 4 == 0
122 && height % 2 == 0) {
123 return gfx_conv_yuv422_rgba32_sse;
125 #endif
126 return gfx_conv_YCbCr422_RGB32_c;
129 if (pixelFormat == AV_PIX_FMT_YUV420P10LE)
130 return gfx_conv_yuv420p10le_rgb32_c;
132 TRACE("resolve_colorspace: %s => B_RGB32: NULL\n",
133 pixfmt_to_string(pixelFormat));
134 return NULL;
136 case B_RGB24_BIG:
137 TRACE("resolve_colorspace: %s => B_RGB24_BIG: NULL\n",
138 pixfmt_to_string(pixelFormat));
139 return NULL;
141 case B_RGB24:
142 TRACE("resolve_colorspace: %s => B_RGB24: NULL\n",
143 pixfmt_to_string(pixelFormat));
144 return NULL;
146 case B_YCbCr422:
147 if (pixelFormat == AV_PIX_FMT_YUV410P) {
148 TRACE("resolve_colorspace: gfx_conv_yuv410p_ycbcr422_c\n");
149 return gfx_conv_yuv410p_ycbcr422_c;
152 if (pixelFormat == AV_PIX_FMT_YUV411P) {
153 TRACE("resolve_colorspace: gfx_conv_yuv411p_ycbcr422_c\n");
154 return gfx_conv_yuv411p_ycbcr422_c;
157 if (pixelFormat == AV_PIX_FMT_YUV420P
158 || pixelFormat == AV_PIX_FMT_YUVJ420P) {
159 TRACE("resolve_colorspace: gfx_conv_yuv420p_ycbcr422_c\n");
160 return gfx_conv_yuv420p_ycbcr422_c;
163 if (pixelFormat == AV_PIX_FMT_YUYV422) {
164 TRACE("resolve_colorspace: PIX_FMT_YUV422 => B_YCbCr422: "
165 "gfx_conv_null\n");
166 return gfx_conv_null;
169 TRACE("resolve_colorspace: %s => B_YCbCr422: NULL\n",
170 pixfmt_to_string(pixelFormat));
171 return NULL;
173 default:
174 TRACE("resolve_colorspace: default: NULL!!!\n");
175 return NULL;
180 const char*
181 pixfmt_to_string(int pixFormat)
183 const char* name = av_get_pix_fmt_name((enum AVPixelFormat)pixFormat);
184 if (name == NULL)
185 return "(unknown)";
186 return name;
190 color_space
191 pixfmt_to_colorspace(int pixFormat)
193 switch (pixFormat) {
194 default:
195 TRACE("No BE API colorspace definition for pixel format "
196 "\"%s\".\n", pixfmt_to_string(pixFormat));
197 // Supposed to fall through.
198 case AV_PIX_FMT_NONE:
199 return B_NO_COLOR_SPACE;
201 // NOTE: See pixfmt_to_colorspace() for what these are.
202 case AV_PIX_FMT_YUV420P:
203 return B_YUV420;
204 case AV_PIX_FMT_YUYV422:
205 return B_YUV422;
206 case AV_PIX_FMT_RGB24:
207 return B_RGB24_BIG;
208 case AV_PIX_FMT_BGR24:
209 return B_RGB24;
210 case AV_PIX_FMT_YUV422P:
211 return B_YUV422;
212 case AV_PIX_FMT_YUV444P:
213 return B_YUV444;
214 case AV_PIX_FMT_RGB32:
215 return B_RGBA32_BIG;
216 case AV_PIX_FMT_YUV410P:
217 return B_YUV9;
218 case AV_PIX_FMT_YUV411P:
219 return B_YUV12;
220 case AV_PIX_FMT_RGB565:
221 return B_RGB16_BIG;
222 case AV_PIX_FMT_RGB555:
223 return B_RGB15_BIG;
224 case AV_PIX_FMT_GRAY8:
225 return B_GRAY8;
226 case AV_PIX_FMT_MONOBLACK:
227 return B_GRAY1;
228 case AV_PIX_FMT_PAL8:
229 return B_CMAP8;
230 case AV_PIX_FMT_BGR32:
231 return B_RGB32;
232 case AV_PIX_FMT_BGR565:
233 return B_RGB16;
234 case AV_PIX_FMT_BGR555:
235 return B_RGB15;
240 AVPixelFormat
241 colorspace_to_pixfmt(color_space format)
243 switch(format) {
244 default:
245 case B_NO_COLOR_SPACE:
246 return AV_PIX_FMT_NONE;
248 // NOTE: See pixfmt_to_colorspace() for what these are.
249 case B_YUV420:
250 return AV_PIX_FMT_YUV420P;
251 case B_YUV422:
252 return AV_PIX_FMT_YUV422P;
253 case B_RGB24_BIG:
254 return AV_PIX_FMT_RGB24;
255 case B_RGB24:
256 return AV_PIX_FMT_BGR24;
257 case B_YUV444:
258 return AV_PIX_FMT_YUV444P;
259 case B_RGBA32_BIG:
260 case B_RGB32_BIG:
261 return AV_PIX_FMT_BGR32;
262 case B_YUV9:
263 return AV_PIX_FMT_YUV410P;
264 case B_YUV12:
265 return AV_PIX_FMT_YUV411P;
266 // TODO: YCbCr color spaces! These are not the same as YUV!
267 case B_RGB16_BIG:
268 return AV_PIX_FMT_RGB565;
269 case B_RGB15_BIG:
270 return AV_PIX_FMT_RGB555;
271 case B_GRAY8:
272 return AV_PIX_FMT_GRAY8;
273 case B_GRAY1:
274 return AV_PIX_FMT_MONOBLACK;
275 case B_CMAP8:
276 return AV_PIX_FMT_PAL8;
277 case B_RGBA32:
278 case B_RGB32:
279 return AV_PIX_FMT_RGB32;
280 case B_RGB16:
281 return AV_PIX_FMT_BGR565;
282 case B_RGB15:
283 return AV_PIX_FMT_BGR555;
288 #define BEGIN_TAG "\033[31m"
289 #define END_TAG "\033[0m"
291 void
292 dump_ffframe_audio(AVFrame* frame, const char* name)
294 printf(BEGIN_TAG "AVFrame(%s) [ pkt_dts:%-10lld #samples:%-5d %s"
295 " ]\n" END_TAG,
296 name,
297 frame->pkt_dts,
298 frame->nb_samples,
299 av_get_sample_fmt_name(static_cast<AVSampleFormat>(frame->format)));
303 void
304 dump_ffframe_video(AVFrame* frame, const char* name)
306 const char* picttypes[] = {"no pict type", "intra", "predicted",
307 "bidir pre", "s(gmc)-vop"};
308 printf(BEGIN_TAG "AVFrame(%s) [ pkt_dts:%-10lld cnum:%-5d dnum:%-5d %s%s"
309 " ]\n" END_TAG,
310 name,
311 frame->pkt_dts,
312 frame->coded_picture_number,
313 frame->display_picture_number,
314 frame->key_frame?"keyframe, ":"",
315 picttypes[frame->pict_type]);