xref: /haiku/src/add-ons/media/plugins/ffmpeg/gfx_util.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 #include "gfx_util.h"
2 
3 #include <strings.h>
4 #include <stdio.h>
5 
6 extern "C" {
7 #include <libavutil/pixdesc.h>
8 }
9 
10 #include "CpuCapabilities.h"
11 #include "gfx_conv_c.h"
12 #include "gfx_conv_mmx.h"
13 
14 
15 // ref docs
16 // http://www.joemaller.com/fcp/fxscript_yuv_color.shtml
17 
18 
19 #if DEBUG
20   #define TRACE(a...) printf(a)
21 #else
22   #define TRACE(a...)
23 #endif
24 
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
50 
51 
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)
57 {
58 	CPUCapabilities cpu;
59 
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;
66 			}
67 
68 			if (pixelFormat == AV_PIX_FMT_YUV411P) {
69 				TRACE("resolve_colorspace: gfx_conv_yuv411p_rgb32_c\n");
70 				return gfx_conv_yuv411p_rgb32_c;
71 			}
72 
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;
86 				}
87 #endif
88 				TRACE("resolve_colorspace: gfx_conv_YCbCr420p_RGB32_c\n");
89 				return gfx_conv_YCbCr420p_RGB32_c;
90 			}
91 
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;
104 				}
105 #endif
106 				TRACE("resolve_colorspace: gfx_conv_YCbCr422p_RGB32_c\n");
107 				return gfx_conv_YCbCr422_RGB32_c;
108 			}
109 
110 			if (pixelFormat == AV_PIX_FMT_GBRP) {
111 				return gfx_conv_GBRP_RGB32_c;
112 			}
113 
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;
124 				}
125 #endif
126 				return gfx_conv_YCbCr422_RGB32_c;
127 			}
128 
129 			if (pixelFormat == AV_PIX_FMT_YUV420P10LE)
130 				return gfx_conv_yuv420p10le_rgb32_c;
131 
132 			TRACE("resolve_colorspace: %s => B_RGB32: NULL\n",
133 				pixfmt_to_string(pixelFormat));
134 			return NULL;
135 
136 		case B_RGB24_BIG:
137 			TRACE("resolve_colorspace: %s => B_RGB24_BIG: NULL\n",
138 				pixfmt_to_string(pixelFormat));
139 			return NULL;
140 
141 		case B_RGB24:
142 			TRACE("resolve_colorspace: %s => B_RGB24: NULL\n",
143 				pixfmt_to_string(pixelFormat));
144 			return NULL;
145 
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;
150 			}
151 
152 			if (pixelFormat == AV_PIX_FMT_YUV411P) {
153 				TRACE("resolve_colorspace: gfx_conv_yuv411p_ycbcr422_c\n");
154 				return gfx_conv_yuv411p_ycbcr422_c;
155 			}
156 
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;
161 			}
162 
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;
167 			}
168 
169 			TRACE("resolve_colorspace: %s => B_YCbCr422: NULL\n",
170 				pixfmt_to_string(pixelFormat));
171 			return NULL;
172 
173 		default:
174 			TRACE("resolve_colorspace: default: NULL!!!\n");
175 			return NULL;
176 	}
177 }
178 
179 
180 const char*
181 pixfmt_to_string(int pixFormat)
182 {
183 	const char* name = av_get_pix_fmt_name((enum AVPixelFormat)pixFormat);
184 	if (name == NULL)
185 		return "(unknown)";
186 	return name;
187 }
188 
189 
190 color_space
191 pixfmt_to_colorspace(int pixFormat)
192 {
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;
200 
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;
236 	}
237 }
238 
239 
240 AVPixelFormat
241 colorspace_to_pixfmt(color_space format)
242 {
243 	switch(format) {
244 		default:
245 		case B_NO_COLOR_SPACE:
246 			return AV_PIX_FMT_NONE;
247 
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;
284 	}
285 }
286 
287 
288 #define BEGIN_TAG "\033[31m"
289 #define END_TAG "\033[0m"
290 
291 void
292 dump_ffframe_audio(AVFrame* frame, const char* name)
293 {
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)));
300 }
301 
302 
303 void
304 dump_ffframe_video(AVFrame* frame, const char* name)
305 {
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]);
316 }
317