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
resolve_colorspace(color_space colorSpace,AVPixelFormat pixelFormat,int width,int height)29 resolve_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
154 const char*
pixfmt_to_string(int pixFormat)155 pixfmt_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
164 color_space
pixfmt_to_colorspace(int pixFormat)165 pixfmt_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_RGB24:
179 return B_RGB24_BIG;
180 case AV_PIX_FMT_BGR24:
181 return B_RGB24;
182 case AV_PIX_FMT_YUV422P:
183 return B_YUV422;
184 case AV_PIX_FMT_YUV444P:
185 return B_YUV444;
186 case AV_PIX_FMT_RGB32:
187 return B_RGBA32_BIG;
188 case AV_PIX_FMT_YUV410P:
189 return B_YUV9;
190 case AV_PIX_FMT_YUV411P:
191 return B_YUV12;
192 case AV_PIX_FMT_RGB565:
193 return B_RGB16_BIG;
194 case AV_PIX_FMT_RGB555:
195 return B_RGB15_BIG;
196 case AV_PIX_FMT_GRAY8:
197 return B_GRAY8;
198 case AV_PIX_FMT_MONOBLACK:
199 return B_GRAY1;
200 case AV_PIX_FMT_PAL8:
201 return B_CMAP8;
202 case AV_PIX_FMT_BGR32:
203 return B_RGB32;
204 case AV_PIX_FMT_BGR565:
205 return B_RGB16;
206 case AV_PIX_FMT_BGR555:
207 return B_RGB15;
208 // TODO: more YCbCr color spaces! These are not the same as YUV!
209 case AV_PIX_FMT_YUYV422:
210 return B_YCbCr422;
211
212 }
213 }
214
215
216 AVPixelFormat
colorspace_to_pixfmt(color_space format)217 colorspace_to_pixfmt(color_space format)
218 {
219 switch(format) {
220 default:
221 case B_NO_COLOR_SPACE:
222 return AV_PIX_FMT_NONE;
223
224 // NOTE: See pixfmt_to_colorspace() for what these are.
225 case B_YUV420:
226 return AV_PIX_FMT_YUV420P;
227 case B_YUV422:
228 return AV_PIX_FMT_YUV422P;
229 case B_RGB24_BIG:
230 return AV_PIX_FMT_RGB24;
231 case B_RGB24:
232 return AV_PIX_FMT_BGR24;
233 case B_YUV444:
234 return AV_PIX_FMT_YUV444P;
235 case B_RGBA32_BIG:
236 case B_RGB32_BIG:
237 return AV_PIX_FMT_BGR32;
238 case B_YUV9:
239 return AV_PIX_FMT_YUV410P;
240 case B_YUV12:
241 return AV_PIX_FMT_YUV411P;
242 case B_RGB16_BIG:
243 return AV_PIX_FMT_RGB565;
244 case B_RGB15_BIG:
245 return AV_PIX_FMT_RGB555;
246 case B_GRAY8:
247 return AV_PIX_FMT_GRAY8;
248 case B_GRAY1:
249 return AV_PIX_FMT_MONOBLACK;
250 case B_CMAP8:
251 return AV_PIX_FMT_PAL8;
252 case B_RGBA32:
253 case B_RGB32:
254 return AV_PIX_FMT_RGB32;
255 case B_RGB16:
256 return AV_PIX_FMT_BGR565;
257 case B_RGB15:
258 return AV_PIX_FMT_BGR555;
259 // TODO: more YCbCr color spaces! These are not the same as YUV!
260 case B_YCbCr422:
261 return AV_PIX_FMT_YUYV422;
262 }
263 }
264
265
266 #define BEGIN_TAG "\033[31m"
267 #define END_TAG "\033[0m"
268
269 void
dump_ffframe_audio(AVFrame * frame,const char * name)270 dump_ffframe_audio(AVFrame* frame, const char* name)
271 {
272 printf(BEGIN_TAG "AVFrame(%s) [ pkt_dts:%-10" PRId64 " #samples:%-5d %s"
273 " ]\n" END_TAG,
274 name,
275 frame->pkt_dts,
276 frame->nb_samples,
277 av_get_sample_fmt_name(static_cast<AVSampleFormat>(frame->format)));
278 }
279
280
281 void
dump_ffframe_video(AVFrame * frame,const char * name)282 dump_ffframe_video(AVFrame* frame, const char* name)
283 {
284 const char* picttypes[] = {"no pict type", "intra", "predicted",
285 "bidir pre", "s(gmc)-vop", "switching intra", "switching predicted", "BI"};
286 #if LIBAVCODEC_VERSION_MAJOR >= 60
287 printf(BEGIN_TAG "AVFrame(%s) [ pkt_dts:%-10" PRId64 " %s%s%s%s%s%s ]\n" END_TAG, name,
288 frame->pkt_dts,
289 (frame->flags & AV_FRAME_FLAG_CORRUPT) ? "corrupt, " : "",
290 (frame->flags & AV_FRAME_FLAG_KEY) ? "keyframe, " : "",
291 (frame->flags & AV_FRAME_FLAG_DISCARD) ? "discard, " : "",
292 (frame->flags & AV_FRAME_FLAG_INTERLACED) ? "interlaced, " : "",
293 (frame->flags & AV_FRAME_FLAG_TOP_FIELD_FIRST) ? "top field first, " : "",
294 picttypes[frame->pict_type]);
295 #else
296 printf(BEGIN_TAG "AVFrame(%s) [ pkt_dts:%-10" PRId64 " %s%s ]\n" END_TAG, name, frame->pkt_dts,
297 frame->key_frame ? "keyframe, " : "", picttypes[frame->pict_type]);
298 #endif
299 }
300