xref: /haiku/src/add-ons/media/plugins/ffmpeg/gfx_util.cpp (revision 385ee03ba83b7a40d315e17b03031b3ca37820c0)
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 #endif
49 
50 
51 //! This function will try to find the best colorspaces for both the ff-codec
52 // and the Media Kit sides.
53 gfx_convert_func
54 resolve_colorspace(color_space colorSpace, AVPixelFormat pixelFormat, int width,
55 	int height)
56 {
57 	CPUCapabilities cpu;
58 
59 	switch (colorSpace) {
60 		case B_RGB32:
61 			// Planar Formats
62 			if (pixelFormat == AV_PIX_FMT_YUV410P) {
63 				TRACE("resolve_colorspace: gfx_conv_yuv410p_rgb32_c\n");
64 				return gfx_conv_yuv410p_rgb32_c;
65 			}
66 
67 			if (pixelFormat == AV_PIX_FMT_YUV411P) {
68 				TRACE("resolve_colorspace: gfx_conv_yuv411p_rgb32_c\n");
69 				return gfx_conv_yuv411p_rgb32_c;
70 			}
71 
72 			if (pixelFormat == AV_PIX_FMT_YUV420P
73 				|| pixelFormat == AV_PIX_FMT_YUVJ420P) {
74 #ifndef __x86_64__
75 				if (cpu.HasSSSE3() && width % 8 == 0 && height % 2 == 0) {
76 					TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_ssse3\n");
77 					return gfx_conv_yuv420p_rgba32_ssse3;
78 				} else if (cpu.HasSSE2() && width % 8 == 0 && height % 2 == 0) {
79 					TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_sse2\n");
80 					return gfx_conv_yuv420p_rgba32_sse2;
81 				} else if (cpu.HasSSE1() && width % 4 == 0
82 					&& height % 2 == 0) {
83 					TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_sse\n");
84 					return gfx_conv_yuv420p_rgba32_sse;
85 				}
86 #endif
87 				TRACE("resolve_colorspace: gfx_conv_YCbCr420p_RGB32_c\n");
88 				return gfx_conv_YCbCr420p_RGB32_c;
89 			}
90 
91 			if (pixelFormat == AV_PIX_FMT_YUV422P
92 				|| pixelFormat == AV_PIX_FMT_YUVJ422P) {
93 #ifndef __x86_64__
94 				if (cpu.HasSSSE3() && width % 8 == 0) {
95 					TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_ssse3\n");
96 					return gfx_conv_yuv422p_rgba32_ssse3;
97 				} else if (cpu.HasSSE2() && width % 8 == 0) {
98 					TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_sse2\n");
99 					return gfx_conv_yuv422p_rgba32_sse2;
100 				} else if (cpu.HasSSE1() && width % 4 == 0) {
101 					TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_sse\n");
102 					return gfx_conv_yuv422p_rgba32_sse;
103 				}
104 #endif
105 				TRACE("resolve_colorspace: gfx_conv_YCbCr422p_RGB32_c\n");
106 				return gfx_conv_YCbCr422_RGB32_c;
107 			}
108 
109 			// Packed Formats
110 			if (pixelFormat == AV_PIX_FMT_YUYV422) {
111 #ifndef __x86_64__
112 				if (cpu.HasSSSE3() && width % 8 == 0) {
113 					return gfx_conv_yuv422_rgba32_ssse3;
114 				} else if (cpu.HasSSE2() && width % 8 == 0) {
115 					return gfx_conv_yuv422_rgba32_sse2;
116 				} else if (cpu.HasSSE1() && width % 4 == 0
117 					&& height % 2 == 0) {
118 					return gfx_conv_yuv422_rgba32_sse;
119 				}
120 #endif
121 				return gfx_conv_YCbCr422_RGB32_c;
122 			}
123 
124 			if (pixelFormat == AV_PIX_FMT_YUV420P10LE)
125 				return gfx_conv_yuv420p10le_rgb32_c;
126 
127 			TRACE("resolve_colorspace: %s => B_RGB32: NULL\n",
128 				pixfmt_to_string(pixelFormat));
129 			return NULL;
130 
131 		case B_RGB24_BIG:
132 			TRACE("resolve_colorspace: %s => B_RGB24_BIG: NULL\n",
133 				pixfmt_to_string(pixelFormat));
134 			return NULL;
135 
136 		case B_RGB24:
137 			TRACE("resolve_colorspace: %s => B_RGB24: NULL\n",
138 				pixfmt_to_string(pixelFormat));
139 			return NULL;
140 
141 		case B_YCbCr422:
142 			if (pixelFormat == AV_PIX_FMT_YUV410P) {
143 				TRACE("resolve_colorspace: gfx_conv_yuv410p_ycbcr422_c\n");
144 				return gfx_conv_yuv410p_ycbcr422_c;
145 			}
146 
147 			if (pixelFormat == AV_PIX_FMT_YUV411P) {
148 				TRACE("resolve_colorspace: gfx_conv_yuv411p_ycbcr422_c\n");
149 				return gfx_conv_yuv411p_ycbcr422_c;
150 			}
151 
152 			if (pixelFormat == AV_PIX_FMT_YUV420P
153 				|| pixelFormat == AV_PIX_FMT_YUVJ420P) {
154 				TRACE("resolve_colorspace: gfx_conv_yuv420p_ycbcr422_c\n");
155 				return gfx_conv_yuv420p_ycbcr422_c;
156 			}
157 
158 			if (pixelFormat == AV_PIX_FMT_YUYV422) {
159 				TRACE("resolve_colorspace: PIX_FMT_YUV422 => B_YCbCr422: "
160 					"gfx_conv_null\n");
161 				return gfx_conv_null;
162 			}
163 
164 			TRACE("resolve_colorspace: %s => B_YCbCr422: NULL\n",
165 				pixfmt_to_string(pixelFormat));
166 			return NULL;
167 
168 		default:
169 			TRACE("resolve_colorspace: default: NULL!!!\n");
170 			return NULL;
171 	}
172 }
173 
174 
175 const char*
176 pixfmt_to_string(int pixFormat)
177 {
178 	const char* name = av_get_pix_fmt_name((enum AVPixelFormat)pixFormat);
179 	if (name == NULL)
180 		return "(unknown)";
181 	return name;
182 }
183 
184 
185 color_space
186 pixfmt_to_colorspace(int pixFormat)
187 {
188 	switch (pixFormat) {
189 		default:
190 			TRACE("No BE API colorspace definition for pixel format "
191 				"\"%s\".\n", pixfmt_to_string(pixFormat));
192 			// Supposed to fall through.
193 		case AV_PIX_FMT_NONE:
194 			return B_NO_COLOR_SPACE;
195 
196 		// NOTE: See pixfmt_to_colorspace() for what these are.
197 		case AV_PIX_FMT_YUV420P:
198 			return B_YUV420;
199 		case AV_PIX_FMT_YUYV422:
200 			return B_YUV422;
201 		case AV_PIX_FMT_RGB24:
202 			return B_RGB24_BIG;
203 		case AV_PIX_FMT_BGR24:
204 			return B_RGB24;
205 		case AV_PIX_FMT_YUV422P:
206 			return B_YUV422;
207 		case AV_PIX_FMT_YUV444P:
208 			return B_YUV444;
209 		case AV_PIX_FMT_RGB32:
210 			return B_RGBA32_BIG;
211 		case AV_PIX_FMT_YUV410P:
212 			return B_YUV9;
213 		case AV_PIX_FMT_YUV411P:
214 			return B_YUV12;
215 		case AV_PIX_FMT_RGB565:
216 			return B_RGB16_BIG;
217 		case AV_PIX_FMT_RGB555:
218 			return B_RGB15_BIG;
219 		case AV_PIX_FMT_GRAY8:
220 			return B_GRAY8;
221 		case AV_PIX_FMT_MONOBLACK:
222 			return B_GRAY1;
223 		case AV_PIX_FMT_PAL8:
224 			return B_CMAP8;
225 		case AV_PIX_FMT_BGR32:
226 			return B_RGB32;
227 		case AV_PIX_FMT_BGR565:
228 			return B_RGB16;
229 		case AV_PIX_FMT_BGR555:
230 			return B_RGB15;
231 	}
232 }
233 
234 
235 AVPixelFormat
236 colorspace_to_pixfmt(color_space format)
237 {
238 	switch(format) {
239 		default:
240 		case B_NO_COLOR_SPACE:
241 			return AV_PIX_FMT_NONE;
242 
243 		// NOTE: See pixfmt_to_colorspace() for what these are.
244 		case B_YUV420:
245 			return AV_PIX_FMT_YUV420P;
246 		case B_YUV422:
247 			return AV_PIX_FMT_YUV422P;
248 		case B_RGB24_BIG:
249 			return AV_PIX_FMT_RGB24;
250 		case B_RGB24:
251 			return AV_PIX_FMT_BGR24;
252 		case B_YUV444:
253 			return AV_PIX_FMT_YUV444P;
254 		case B_RGBA32_BIG:
255 		case B_RGB32_BIG:
256 			return AV_PIX_FMT_BGR32;
257 		case B_YUV9:
258 			return AV_PIX_FMT_YUV410P;
259 		case B_YUV12:
260 			return AV_PIX_FMT_YUV411P;
261 		// TODO: YCbCr color spaces! These are not the same as YUV!
262 		case B_RGB16_BIG:
263 			return AV_PIX_FMT_RGB565;
264 		case B_RGB15_BIG:
265 			return AV_PIX_FMT_RGB555;
266 		case B_GRAY8:
267 			return AV_PIX_FMT_GRAY8;
268 		case B_GRAY1:
269 			return AV_PIX_FMT_MONOBLACK;
270 		case B_CMAP8:
271 			return AV_PIX_FMT_PAL8;
272 		case B_RGBA32:
273 		case B_RGB32:
274 			return AV_PIX_FMT_RGB32;
275 		case B_RGB16:
276 			return AV_PIX_FMT_BGR565;
277 		case B_RGB15:
278 			return AV_PIX_FMT_BGR555;
279 	}
280 }
281 
282 
283 #define BEGIN_TAG "\033[31m"
284 #define END_TAG "\033[0m"
285 
286 void
287 dump_ffframe_audio(AVFrame* frame, const char* name)
288 {
289 	printf(BEGIN_TAG"AVFrame(%s) [ pkt_dts:%-10lld #samples:%-5d %s"
290 		" ]\n"END_TAG,
291 		name,
292 		frame->pkt_dts,
293 		frame->nb_samples,
294 		av_get_sample_fmt_name(static_cast<AVSampleFormat>(frame->format)));
295 }
296 
297 
298 void
299 dump_ffframe_video(AVFrame* frame, const char* name)
300 {
301 	const char* picttypes[] = {"no pict type", "intra", "predicted",
302 		"bidir pre", "s(gmc)-vop"};
303 	printf(BEGIN_TAG"AVFrame(%s) [ pkt_dts:%-10lld cnum:%-5d dnum:%-5d %s%s"
304 		" ]\n"END_TAG,
305 		name,
306 		frame->pkt_dts,
307 		frame->coded_picture_number,
308 		frame->display_picture_number,
309 		frame->key_frame?"keyframe, ":"",
310 		picttypes[frame->pict_type]);
311 }
312