11553Srgrimes#include "gfx_util.h"
21553Srgrimes
31553Srgrimes#include <strings.h>
41553Srgrimes#include <stdio.h>
51553Srgrimes
61553Srgrimes#include "CpuCapabilities.h"
71553Srgrimes#include "gfx_conv_c.h"
81553Srgrimes#include "gfx_conv_mmx.h"
91553Srgrimes
101553Srgrimes
111553Srgrimes// ref docs
121553Srgrimes// http://www.joemaller.com/fcp/fxscript_yuv_color.shtml
131553Srgrimes
141553Srgrimes
151553Srgrimes#if 1
161553Srgrimes  #define TRACE(a...) printf(a)
171553Srgrimes#else
181553Srgrimes  #define TRACE(a...)
191553Srgrimes#endif
201553Srgrimes
211553Srgrimes
221553Srgrimes//! This function will try to find the best colorspaces for both the ff-codec
231553Srgrimes// and the Media Kit sides.
241553Srgrimesgfx_convert_func
251553Srgrimesresolve_colorspace(color_space colorSpace, PixelFormat pixelFormat, int width,
261553Srgrimes	int height)
271553Srgrimes{
281553Srgrimes	CPUCapabilities cpu;
291553Srgrimes
301553Srgrimes	switch (colorSpace) {
3130642Scharnier		case B_RGB32:
321553Srgrimes			// Planar Formats
3330642Scharnier			if (pixelFormat == PIX_FMT_YUV410P) {
3430642Scharnier				TRACE("resolve_colorspace: gfx_conv_yuv410p_rgb32_c\n");
3550479Speter				return gfx_conv_yuv410p_rgb32_c;
361553Srgrimes			}
371553Srgrimes
381553Srgrimes			if (pixelFormat == PIX_FMT_YUV411P) {
391553Srgrimes				TRACE("resolve_colorspace: gfx_conv_yuv411p_rgb32_c\n");
401553Srgrimes				return gfx_conv_yuv411p_rgb32_c;
411553Srgrimes			}
421553Srgrimes
431553Srgrimes			if (pixelFormat == PIX_FMT_YUV420P
441553Srgrimes				|| pixelFormat == PIX_FMT_YUVJ420P) {
451553Srgrimes				if (cpu.HasSSSE3() && width % 8 == 0 && height % 2 == 0) {
461553Srgrimes					TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_ssse3\n");
47246209Scharnier					return gfx_conv_yuv420p_rgba32_ssse3;
481553Srgrimes				} else if (cpu.HasSSE2() && width % 8 == 0 && height % 2 == 0) {
491553Srgrimes					TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_sse2\n");
501553Srgrimes					return gfx_conv_yuv420p_rgba32_sse2;
511553Srgrimes				} else if (cpu.HasSSE1() && width % 4 == 0
521553Srgrimes					&& height % 2 == 0) {
531553Srgrimes					TRACE("resolve_colorspace: gfx_conv_yuv420p_rgba32_sse\n");
541553Srgrimes					return gfx_conv_yuv420p_rgba32_sse;
551553Srgrimes				} else {
561553Srgrimes					TRACE("resolve_colorspace: gfx_conv_YCbCr420p_RGB32_c\n");
571553Srgrimes					return gfx_conv_YCbCr420p_RGB32_c;
581553Srgrimes				}
591553Srgrimes			}
601553Srgrimes
611553Srgrimes			if (pixelFormat == PIX_FMT_YUV422P
621553Srgrimes				|| pixelFormat == PIX_FMT_YUVJ422P) {
631553Srgrimes				if (cpu.HasSSSE3() && width % 8 == 0) {
641553Srgrimes					TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_ssse3\n");
651553Srgrimes					return gfx_conv_yuv422p_rgba32_ssse3;
661553Srgrimes				} else if (cpu.HasSSE2() && width % 8 == 0) {
671553Srgrimes					TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_sse2\n");
681553Srgrimes					return gfx_conv_yuv422p_rgba32_sse2;
691553Srgrimes				} else if (cpu.HasSSE1() && width % 4 == 0) {
701553Srgrimes					TRACE("resolve_colorspace: gfx_conv_yuv422p_RGB32_sse\n");
711553Srgrimes					return gfx_conv_yuv422p_rgba32_sse;
721553Srgrimes				} else {
731553Srgrimes					TRACE("resolve_colorspace: gfx_conv_YCbCr422p_RGB32_c\n");
741553Srgrimes					return gfx_conv_YCbCr422_RGB32_c;
751553Srgrimes				}
761553Srgrimes			}
771553Srgrimes
7830830Scharnier			// Packed Formats
791553Srgrimes			if (pixelFormat == PIX_FMT_YUYV422) {
801553Srgrimes				if (cpu.HasSSSE3() && width % 8 == 0) {
811553Srgrimes					return gfx_conv_yuv422_rgba32_ssse3;
821553Srgrimes				} else if (cpu.HasSSE2() && width % 8 == 0) {
831553Srgrimes					return gfx_conv_yuv422_rgba32_sse2;
841553Srgrimes				} else if (cpu.HasSSE1() && width % 4 == 0
851553Srgrimes					&& height % 2 == 0) {
861553Srgrimes					return gfx_conv_yuv422_rgba32_sse;
871553Srgrimes				} else {
881553Srgrimes					return gfx_conv_YCbCr422_RGB32_c;
891553Srgrimes				}
901553Srgrimes			}
911553Srgrimes
921553Srgrimes			TRACE("resolve_colorspace: %s => B_RGB32: NULL\n",
931553Srgrimes				pixfmt_to_string(pixelFormat));
941553Srgrimes			return NULL;
951553Srgrimes
961553Srgrimes		case B_RGB24_BIG:
971553Srgrimes			TRACE("resolve_colorspace: %s => B_RGB24_BIG: NULL\n",
981553Srgrimes				pixfmt_to_string(pixelFormat));
991553Srgrimes			return NULL;
1001553Srgrimes
1011553Srgrimes		case B_RGB24:
1021553Srgrimes			TRACE("resolve_colorspace: %s => B_RGB24: NULL\n",
1031553Srgrimes				pixfmt_to_string(pixelFormat));
1041553Srgrimes			return NULL;
1051553Srgrimes
1061553Srgrimes		case B_YCbCr422:
1071553Srgrimes			if (pixelFormat == PIX_FMT_YUV410P) {
1081553Srgrimes				TRACE("resolve_colorspace: gfx_conv_yuv410p_ycbcr422_c\n");
1091553Srgrimes				return gfx_conv_yuv410p_ycbcr422_c;
1101553Srgrimes			}
1111553Srgrimes
1121553Srgrimes			if (pixelFormat == PIX_FMT_YUV411P) {
1131553Srgrimes				TRACE("resolve_colorspace: gfx_conv_yuv411p_ycbcr422_c\n");
1141553Srgrimes				return gfx_conv_yuv411p_ycbcr422_c;
1151553Srgrimes			}
1161553Srgrimes
1171553Srgrimes			if (pixelFormat == PIX_FMT_YUV420P
1181553Srgrimes				|| pixelFormat == PIX_FMT_YUVJ420P) {
1191553Srgrimes				TRACE("resolve_colorspace: gfx_conv_yuv420p_ycbcr422_c\n");
1201553Srgrimes				return gfx_conv_yuv420p_ycbcr422_c;
1218857Srgrimes			}
1221553Srgrimes
1231553Srgrimes			if (pixelFormat == PIX_FMT_YUYV422) {
1241553Srgrimes				TRACE("resolve_colorspace: PIX_FMT_YUV422 => B_YCbCr422: "
1251553Srgrimes					"gfx_conv_null\n");
1261553Srgrimes				return gfx_conv_null;
1271553Srgrimes			}
1281553Srgrimes
1291553Srgrimes			TRACE("resolve_colorspace: %s => B_YCbCr422: NULL\n",
1301553Srgrimes				pixfmt_to_string(pixelFormat));
1311553Srgrimes			return NULL;
1321553Srgrimes
1331553Srgrimes		default:
1341553Srgrimes			TRACE("resolve_colorspace: default: NULL!!!\n");
1351553Srgrimes			return NULL;
1361553Srgrimes	}
13730830Scharnier}
1381553Srgrimes
1391553Srgrimes
1401553Srgrimesconst char*
1411553Srgrimespixfmt_to_string(int pixFormat)
1421553Srgrimes{
1431553Srgrimes	switch (pixFormat) {
1441553Srgrimes		case PIX_FMT_NONE:
1451553Srgrimes			return "PIX_FMT_NONE";
1461553Srgrimes
1471553Srgrimes		case PIX_FMT_YUV420P:
1481553Srgrimes			// planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
1491553Srgrimes			return "PIX_FMT_YUV420P";
1501553Srgrimes
1511553Srgrimes		case PIX_FMT_YUYV422:
1521553Srgrimes			// packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
1531553Srgrimes			return "PIX_FMT_YUYV422";
1541553Srgrimes
1551553Srgrimes		case PIX_FMT_RGB24:
1561553Srgrimes			// packed RGB 8:8:8, 24bpp, RGBRGB...
1571553Srgrimes			return "PIX_FMT_RGB24";
1581553Srgrimes
1591553Srgrimes		case PIX_FMT_BGR24:
1601553Srgrimes			// packed RGB 8:8:8, 24bpp, BGRBGR...
1611553Srgrimes			return "PIX_FMT_BGR24";
1621553Srgrimes
163		case PIX_FMT_YUV422P:
164			// planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
165			return "PIX_FMT_YUV422P";
166
167		case PIX_FMT_YUV444P:
168			// planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
169			return "PIX_FMT_YUV444P";
170
171		case PIX_FMT_RGB32:
172			// packed RGB 8:8:8, 32bpp, (msb)8A 8R 8G 8B(lsb), in CPU
173			// endianness
174			return "PIX_FMT_RGB32";
175
176		case PIX_FMT_YUV410P:
177			// planar YUV 4:1:0,  9bpp, (1 Cr & Cb sample per 4x4 Y samples)
178			return "PIX_FMT_YUV410P";
179
180		case PIX_FMT_YUV411P:
181			// planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
182			return "PIX_FMT_YUV411P";
183
184		case PIX_FMT_RGB565:
185			// packed RGB 5:6:5, 16bpp, (msb)5R 6G 5B(lsb), in CPU endianness
186			return "PIX_FMT_RGB565";
187
188		case PIX_FMT_RGB555:
189			// packed RGB 5:5:5, 16bpp, (msb)1A 5R 5G 5B(lsb), in CPU
190			// endianness, most significant bit to 0
191			return "PIX_FMT_RGB555";
192
193		case PIX_FMT_GRAY8:
194			// Y, 8bpp
195			return "PIX_FMT_GRAY8";
196
197		case PIX_FMT_MONOWHITE:
198			// Y, 1bpp, 0 is white, 1 is black
199			return "PIX_FMT_MONOWHITE";
200
201		case PIX_FMT_MONOBLACK:
202			// Y, 1bpp, 0 is black, 1 is white
203			return "PIX_FMT_MONOBLACK";
204
205		case PIX_FMT_PAL8:
206			// 8 bit with PIX_FMT_RGB32 palette
207			return "PIX_FMT_PAL8";
208
209		case PIX_FMT_YUVJ420P:
210			// planar YUV 4:2:0, 12bpp, full scale (JPEG)
211			return "PIX_FMT_YUVJ420P - YUV420P (Jpeg)";
212
213		case PIX_FMT_YUVJ422P:
214			// planar YUV 4:2:2, 16bpp, full scale (JPEG)
215			return "PIX_FMT_YUVJ422P - YUV422P (Jpeg)";
216
217		case PIX_FMT_YUVJ444P:
218			// planar YUV 4:4:4, 24bpp, full scale (JPEG)
219			return "PIX_FMT_YUVJ444P";
220
221		case PIX_FMT_XVMC_MPEG2_MC:
222			// XVideo Motion Acceleration via common packet passing
223			return "PIX_FMT_XVMC_MPEG2_MC";
224
225		case PIX_FMT_XVMC_MPEG2_IDCT:
226			return "PIX_FMT_XVMC_MPEG2_IDCT";
227		case PIX_FMT_UYVY422:
228			// packed YUV 4:2:2, 16bpp, Cb Y0 Cr Y1
229			return "PIX_FMT_UYVY422";
230
231		case PIX_FMT_UYYVYY411:
232			// packed YUV 4:1:1, 12bpp, Cb Y0 Y1 Cr Y2 Y3
233			return "PIX_FMT_UYYVYY411";
234
235		case PIX_FMT_BGR32:
236			// packed RGB 8:8:8, 32bpp, (msb)8A 8B 8G 8R(lsb), in CPU
237			// endianness
238			return "PIX_FMT_BGR32";
239
240		case PIX_FMT_BGR565:
241			// packed RGB 5:6:5, 16bpp, (msb)5B 6G 5R(lsb), in CPU endianness
242			return "PIX_FMT_BGR565";
243
244		case PIX_FMT_BGR555:
245			// packed RGB 5:5:5, 16bpp, (msb)1A 5B 5G 5R(lsb), in CPU
246			// endianness, most significant bit to 1
247			return "PIX_FMT_BGR555";
248
249		case PIX_FMT_BGR8:
250			// packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
251			return "PIX_FMT_BGR8";
252
253		case PIX_FMT_BGR4:
254			// packed RGB 1:2:1, 4bpp, (msb)1B 2G 1R(lsb)
255			return "PIX_FMT_BGR4";
256
257		case PIX_FMT_BGR4_BYTE:
258			// packed RGB 1:2:1,  8bpp, (msb)1B 2G 1R(lsb)
259			return "PIX_FMT_BGR4_BYTE";
260
261		case PIX_FMT_RGB8:
262			// packed RGB 3:3:2, 8bpp, (msb)2R 3G 3B(lsb)
263			return "PIX_FMT_RGB8";
264
265		case PIX_FMT_RGB4:
266			// packed RGB 1:2:1, 4bpp, (msb)1R 2G 1B(lsb)
267			return "PIX_FMT_RGB4";
268
269		case PIX_FMT_RGB4_BYTE:
270			// packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
271			return "PIX_FMT_RGB4_BYTE";
272
273		case PIX_FMT_NV12:
274			// planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 for UV
275			return "PIX_FMT_NV12";
276
277		case PIX_FMT_NV21:
278			// as above, but U and V bytes are swapped
279			return "PIX_FMT_NV21";
280
281		case PIX_FMT_RGB32_1:
282			// packed RGB 8:8:8, 32bpp, (msb)8R 8G 8B 8A(lsb), in CPU
283			// endianness
284			return "PIX_FMT_RGB32_1";
285
286		case PIX_FMT_BGR32_1:
287			// packed RGB 8:8:8, 32bpp, (msb)8B 8G 8R 8A(lsb), in CPU
288			// endianness
289			return "PIX_FMT_BGR32_1";
290
291		case PIX_FMT_GRAY16BE:
292			// Y, 16bpp, big-endian
293			return "PIX_FMT_GRAY16BE";
294
295		case PIX_FMT_GRAY16LE:
296			// Y, 16bpp, little-endian
297			return "PIX_FMT_GRAY16LE";
298
299		case PIX_FMT_YUV440P:
300			// planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
301			return "PIX_FMT_YUV440P";
302
303		case PIX_FMT_YUVJ440P:
304			// planar YUV 4:4:0 full scale (JPEG)
305			return "PIX_FMT_YUVJ440P - YUV440P (Jpeg)";
306
307		case PIX_FMT_YUVA420P:
308			// planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A
309			// samples)
310			return "PIX_FMT_YUVA420P - YUV420P (Alpha)";
311
312		case PIX_FMT_VDPAU_H264:
313			// H.264 HW decoding with VDPAU, data[0] contains a
314			// vdpau_render_state struct which contains the bitstream of the
315			// slices as well as various fields extracted from headers
316			return "PIX_FMT_VDPAU_H264";
317
318		case PIX_FMT_VDPAU_MPEG1:
319			// MPEG-1 HW decoding with VDPAU, data[0] contains a
320			// vdpau_render_state struct which contains the bitstream of the
321			// slices as well as various fields extracted from headers
322			return "PIX_FMT_VDPAU_MPEG1";
323
324		case PIX_FMT_VDPAU_MPEG2:
325			// MPEG-2 HW decoding with VDPAU, data[0] contains a
326			// vdpau_render_state struct which contains the bitstream of the
327			// slices as well as various fields extracted from headers
328			return "PIX_FMT_VDPAU_MPEG2";
329
330		case PIX_FMT_VDPAU_WMV3:
331			// WMV3 HW decoding with VDPAU, data[0] contains a
332			// vdpau_render_state struct which contains the bitstream of the
333			// slices as well as various fields extracted from headers
334			return "PIX_FMT_VDPAU_WMV3";
335
336		case PIX_FMT_VDPAU_VC1:
337			// VC-1 HW decoding with VDPAU, data[0] contains a
338			// vdpau_render_state struct which contains the bitstream of the
339			// slices as well as various fields extracted from headers
340			return "PIX_FMT_VDPAU_VC1";
341
342		case PIX_FMT_RGB48BE:
343			// packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, big-endian
344			return "PIX_FMT_RGB48BE";
345
346		case PIX_FMT_RGB48LE:
347			// packed RGB 16:16:16, 48bpp, 16R, 16G, 16B, little-endian
348			return "PIX_FMT_RGB48LE";
349
350		case PIX_FMT_VAAPI_MOCO:
351			// HW acceleration through VA API at motion compensation
352			// entry-point, Picture.data[0] contains a vaapi_render_state
353			// struct which contains macroblocks as well as various fields
354			// extracted from headers
355			return "PIX_FMT_VAAPI_MOCO";
356
357		case PIX_FMT_VAAPI_IDCT:
358			// HW acceleration through VA API at IDCT entry-point,
359			// Picture.data[0] contains a vaapi_render_state struct which
360			// contains fields extracted from headers
361			return "PIX_FMT_VAAPI_IDCT";
362
363		case PIX_FMT_VAAPI_VLD:
364			// HW decoding through VA API, Picture.data[0] contains a
365			// vaapi_render_state struct which contains the bitstream of the
366			// slices as well as various fields extracted from headers
367			return "PIX_FMT_VAAPI_VLD";
368
369		default:
370			return "(unknown)";
371	}
372}
373
374
375color_space
376pixfmt_to_colorspace(int pixFormat)
377{
378	switch(pixFormat) {
379		default:
380			TRACE("No BE API colorspace definition for pixel format "
381				"\"%s\".\n", pixfmt_to_string(pixFormat));
382			// Supposed to fall through.
383		case PIX_FMT_NONE:
384			return B_NO_COLOR_SPACE;
385
386		// NOTE: See pixfmt_to_colorspace() for what these are.
387		case PIX_FMT_YUV420P:
388			return B_YUV420;
389		case PIX_FMT_YUYV422:
390			return B_YUV422;
391		case PIX_FMT_RGB24:
392			return B_RGB24_BIG;
393		case PIX_FMT_BGR24:
394			return B_RGB24;
395		case PIX_FMT_YUV422P:
396			return B_YUV422;
397		case PIX_FMT_YUV444P:
398			return B_YUV444;
399		case PIX_FMT_RGB32:
400			return B_RGBA32_BIG;
401		case PIX_FMT_YUV410P:
402			return B_YUV9;
403		case PIX_FMT_YUV411P:
404			return B_YUV12;
405		case PIX_FMT_RGB565:
406			return B_RGB16_BIG;
407		case PIX_FMT_RGB555:
408			return B_RGB15_BIG;
409		case PIX_FMT_GRAY8:
410			return B_GRAY8;
411		case PIX_FMT_MONOBLACK:
412			return B_GRAY1;
413		case PIX_FMT_PAL8:
414			return B_CMAP8;
415		case PIX_FMT_BGR32:
416			return B_RGB32;
417		case PIX_FMT_BGR565:
418			return B_RGB16;
419		case PIX_FMT_BGR555:
420			return B_RGB15;
421	}
422}
423
424
425PixelFormat
426colorspace_to_pixfmt(color_space format)
427{
428	switch(format) {
429		default:
430		case B_NO_COLOR_SPACE:
431			return PIX_FMT_NONE;
432
433		// NOTE: See pixfmt_to_colorspace() for what these are.
434		case B_YUV420:
435			return PIX_FMT_YUV420P;
436		case B_YUV422:
437			return PIX_FMT_YUV422P;
438		case B_RGB24_BIG:
439			return PIX_FMT_RGB24;
440		case B_RGB24:
441			return PIX_FMT_BGR24;
442		case B_YUV444:
443			return PIX_FMT_YUV444P;
444		case B_RGBA32_BIG:
445		case B_RGB32_BIG:
446			return PIX_FMT_BGR32;
447		case B_YUV9:
448			return PIX_FMT_YUV410P;
449		case B_YUV12:
450			return PIX_FMT_YUV411P;
451		// TODO: YCbCr color spaces! These are not the same as YUV!
452		case B_RGB16_BIG:
453			return PIX_FMT_RGB565;
454		case B_RGB15_BIG:
455			return PIX_FMT_RGB555;
456		case B_GRAY8:
457			return PIX_FMT_GRAY8;
458		case B_GRAY1:
459			return PIX_FMT_MONOBLACK;
460		case B_CMAP8:
461			return PIX_FMT_PAL8;
462		case B_RGBA32:
463		case B_RGB32:
464			return PIX_FMT_RGB32;
465		case B_RGB16:
466			return PIX_FMT_BGR565;
467		case B_RGB15:
468			return PIX_FMT_BGR555;
469	}
470}
471
472
473#define BEGIN_TAG "\033[31m"
474#define END_TAG "\033[0m"
475
476void
477dump_ffframe(AVFrame* frame, const char* name)
478{
479	const char* picttypes[] = {"no pict type", "intra", "predicted",
480		"bidir pre", "s(gmc)-vop"};
481	printf(BEGIN_TAG"AVFrame(%s) pts:%-10lld cnum:%-5d dnum:%-5d %s%s, "
482		" ]\n"END_TAG,
483		name,
484		frame->pts,
485		frame->coded_picture_number,
486		frame->display_picture_number,
487//		frame->quality,
488		frame->key_frame?"keyframe, ":"",
489		picttypes[frame->pict_type]);
490//	printf(BEGIN_TAG"\t\tlinesize[] = {%ld, %ld, %ld, %ld}\n"END_TAG,
491//		frame->linesize[0], frame->linesize[1], frame->linesize[2],
492//		frame->linesize[3]);
493}
494
495