1#include "gfx_util.h"
2
3#include <strings.h>
4#include <stdio.h>
5
6extern "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.
28gfx_convert_func
29resolve_colorspace(color_space colorSpace, AVPixelFormat pixelFormat, int width,
30	int height)
31{
32	CPUCapabilities cpu;
33
34	switch (colorSpace) {
35		case B_RGB32:
36			// Planar Formats
37			if (pixelFormat == AV_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 == AV_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 == AV_PIX_FMT_YUV420P
48				|| pixelFormat == AV_PIX_FMT_YUVJ420P) {
49#if 0
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 == AV_PIX_FMT_YUV422P
67				|| pixelFormat == AV_PIX_FMT_YUVJ422P) {
68#if 0
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			if (pixelFormat == AV_PIX_FMT_GBRP) {
85				return gfx_conv_GBRP_RGB32_c;
86			}
87
88			// Packed Formats
89			if (pixelFormat == AV_PIX_FMT_YUYV422) {
90#if 0
91				if (cpu.HasSSSE3() && width % 8 == 0) {
92					return gfx_conv_yuv422_rgba32_ssse3;
93				} else if (cpu.HasSSE2() && width % 8 == 0) {
94					return gfx_conv_yuv422_rgba32_sse2;
95				} else if (cpu.HasSSE1() && width % 4 == 0
96					&& height % 2 == 0) {
97					return gfx_conv_yuv422_rgba32_sse;
98				}
99#endif
100				return gfx_conv_YCbCr422_RGB32_c;
101			}
102
103			if (pixelFormat == AV_PIX_FMT_YUV420P10LE)
104				return gfx_conv_yuv420p10le_rgb32_c;
105
106			TRACE("resolve_colorspace: %s => B_RGB32: NULL\n",
107				pixfmt_to_string(pixelFormat));
108			return NULL;
109
110		case B_RGB24_BIG:
111			TRACE("resolve_colorspace: %s => B_RGB24_BIG: NULL\n",
112				pixfmt_to_string(pixelFormat));
113			return NULL;
114
115		case B_RGB24:
116			TRACE("resolve_colorspace: %s => B_RGB24: NULL\n",
117				pixfmt_to_string(pixelFormat));
118			return NULL;
119
120		case B_YCbCr422:
121			if (pixelFormat == AV_PIX_FMT_YUV410P) {
122				TRACE("resolve_colorspace: gfx_conv_yuv410p_ycbcr422_c\n");
123				return gfx_conv_yuv410p_ycbcr422_c;
124			}
125
126			if (pixelFormat == AV_PIX_FMT_YUV411P) {
127				TRACE("resolve_colorspace: gfx_conv_yuv411p_ycbcr422_c\n");
128				return gfx_conv_yuv411p_ycbcr422_c;
129			}
130
131			if (pixelFormat == AV_PIX_FMT_YUV420P
132				|| pixelFormat == AV_PIX_FMT_YUVJ420P) {
133				TRACE("resolve_colorspace: gfx_conv_yuv420p_ycbcr422_c\n");
134				return gfx_conv_yuv420p_ycbcr422_c;
135			}
136
137			if (pixelFormat == AV_PIX_FMT_YUYV422) {
138				TRACE("resolve_colorspace: PIX_FMT_YUV422 => B_YCbCr422: "
139					"gfx_conv_null\n");
140				return gfx_conv_null;
141			}
142
143			TRACE("resolve_colorspace: %s => B_YCbCr422: NULL\n",
144				pixfmt_to_string(pixelFormat));
145			return NULL;
146
147		default:
148			TRACE("resolve_colorspace: default: NULL!!!\n");
149			return NULL;
150	}
151}
152
153
154const char*
155pixfmt_to_string(int pixFormat)
156{
157	const char* name = av_get_pix_fmt_name((enum AVPixelFormat)pixFormat);
158	if (name == NULL)
159		return "(unknown)";
160	return name;
161}
162
163
164color_space
165pixfmt_to_colorspace(int pixFormat)
166{
167	switch (pixFormat) {
168		default:
169			TRACE("No BE API colorspace definition for pixel format "
170				"\"%s\".\n", pixfmt_to_string(pixFormat));
171			// Supposed to fall through.
172		case AV_PIX_FMT_NONE:
173			return B_NO_COLOR_SPACE;
174
175		// NOTE: See pixfmt_to_colorspace() for what these are.
176		case AV_PIX_FMT_YUV420P:
177			return B_YUV420;
178		case AV_PIX_FMT_YUYV422:
179			return B_YUV422;
180		case AV_PIX_FMT_RGB24:
181			return B_RGB24_BIG;
182		case AV_PIX_FMT_BGR24:
183			return B_RGB24;
184		case AV_PIX_FMT_YUV422P:
185			return B_YUV422;
186		case AV_PIX_FMT_YUV444P:
187			return B_YUV444;
188		case AV_PIX_FMT_RGB32:
189			return B_RGBA32_BIG;
190		case AV_PIX_FMT_YUV410P:
191			return B_YUV9;
192		case AV_PIX_FMT_YUV411P:
193			return B_YUV12;
194		case AV_PIX_FMT_RGB565:
195			return B_RGB16_BIG;
196		case AV_PIX_FMT_RGB555:
197			return B_RGB15_BIG;
198		case AV_PIX_FMT_GRAY8:
199			return B_GRAY8;
200		case AV_PIX_FMT_MONOBLACK:
201			return B_GRAY1;
202		case AV_PIX_FMT_PAL8:
203			return B_CMAP8;
204		case AV_PIX_FMT_BGR32:
205			return B_RGB32;
206		case AV_PIX_FMT_BGR565:
207			return B_RGB16;
208		case AV_PIX_FMT_BGR555:
209			return B_RGB15;
210	}
211}
212
213
214AVPixelFormat
215colorspace_to_pixfmt(color_space format)
216{
217	switch(format) {
218		default:
219		case B_NO_COLOR_SPACE:
220			return AV_PIX_FMT_NONE;
221
222		// NOTE: See pixfmt_to_colorspace() for what these are.
223		case B_YUV420:
224			return AV_PIX_FMT_YUV420P;
225		case B_YUV422:
226			return AV_PIX_FMT_YUV422P;
227		case B_RGB24_BIG:
228			return AV_PIX_FMT_RGB24;
229		case B_RGB24:
230			return AV_PIX_FMT_BGR24;
231		case B_YUV444:
232			return AV_PIX_FMT_YUV444P;
233		case B_RGBA32_BIG:
234		case B_RGB32_BIG:
235			return AV_PIX_FMT_BGR32;
236		case B_YUV9:
237			return AV_PIX_FMT_YUV410P;
238		case B_YUV12:
239			return AV_PIX_FMT_YUV411P;
240		// TODO: YCbCr color spaces! These are not the same as YUV!
241		case B_RGB16_BIG:
242			return AV_PIX_FMT_RGB565;
243		case B_RGB15_BIG:
244			return AV_PIX_FMT_RGB555;
245		case B_GRAY8:
246			return AV_PIX_FMT_GRAY8;
247		case B_GRAY1:
248			return AV_PIX_FMT_MONOBLACK;
249		case B_CMAP8:
250			return AV_PIX_FMT_PAL8;
251		case B_RGBA32:
252		case B_RGB32:
253			return AV_PIX_FMT_RGB32;
254		case B_RGB16:
255			return AV_PIX_FMT_BGR565;
256		case B_RGB15:
257			return AV_PIX_FMT_BGR555;
258	}
259}
260
261
262#define BEGIN_TAG "\033[31m"
263#define END_TAG "\033[0m"
264
265void
266dump_ffframe_audio(AVFrame* frame, const char* name)
267{
268	printf(BEGIN_TAG "AVFrame(%s) [ pkt_dts:%-10lld #samples:%-5d %s"
269		" ]\n" END_TAG,
270		name,
271		frame->pkt_dts,
272		frame->nb_samples,
273		av_get_sample_fmt_name(static_cast<AVSampleFormat>(frame->format)));
274}
275
276
277void
278dump_ffframe_video(AVFrame* frame, const char* name)
279{
280	const char* picttypes[] = {"no pict type", "intra", "predicted",
281		"bidir pre", "s(gmc)-vop"};
282	printf(BEGIN_TAG "AVFrame(%s) [ pkt_dts:%-10lld cnum:%-5d dnum:%-5d %s%s"
283		" ]\n" END_TAG,
284		name,
285		frame->pkt_dts,
286		frame->coded_picture_number,
287		frame->display_picture_number,
288		frame->key_frame?"keyframe, ":"",
289		picttypes[frame->pict_type]);
290}
291