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