[ffmpegcolorspace] Support SUYV, SYVY, S420
[framework/multimedia/gst-plugins-base0.10.git] / gst / ffmpegcolorspace / gstffmpegcodecmap.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * This file:
4  * Copyright (c) 2002-2004 Ronald Bultje <rbultje@ronald.bitfreak.net>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <string.h>
27
28 #include <gst/gst.h>
29
30 #include "avcodec.h"
31 #include "gstffmpegcodecmap.h"
32
33 GST_DEBUG_CATEGORY_EXTERN (ffmpegcolorspace_debug);
34 #define GST_CAT_DEFAULT ffmpegcolorspace_debug
35
36 static GstCaps *
37 gst_ff_vid_caps_new (AVCodecContext * context,
38     const char *mimetype, const char *fieldname, ...)
39     G_GNUC_NULL_TERMINATED;
40      static GstCaps *gst_ff_aud_caps_new (AVCodecContext * context,
41     const char *mimetype, const char *fieldname, ...) G_GNUC_NULL_TERMINATED;
42
43 /*
44  * Read a palette from a caps.
45  */
46
47      static void
48          gst_ffmpeg_get_palette (const GstCaps * caps, AVCodecContext * context)
49 {
50   GstStructure *str = gst_caps_get_structure (caps, 0);
51   const GValue *palette_v;
52
53   /* do we have a palette? */
54   if ((palette_v = gst_structure_get_value (str, "palette_data")) && context) {
55     const GstBuffer *palette;
56
57     palette = gst_value_get_buffer (palette_v);
58     if (palette && GST_BUFFER_SIZE (palette) >= 256 * 4) {
59       if (context->palctrl)
60         av_free (context->palctrl);
61       context->palctrl = av_malloc (sizeof (AVPaletteControl));
62       context->palctrl->palette_changed = 1;
63       memcpy (context->palctrl->palette, GST_BUFFER_DATA (palette),
64           AVPALETTE_SIZE);
65     }
66   }
67 }
68
69 static void
70 gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context)
71 {
72   if (context->palctrl) {
73     GstBuffer *palette = gst_buffer_new_and_alloc (256 * 4);
74
75     memcpy (GST_BUFFER_DATA (palette), context->palctrl->palette,
76         AVPALETTE_SIZE);
77     gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, palette, NULL);
78     gst_buffer_unref (palette);
79   }
80 }
81
82 /* this function creates caps with fixed or unfixed width/height
83  * properties depending on whether we've got a context.
84  *
85  * See below for why we use this.
86  *
87  * We should actually do this stuff at the end, like in riff-media.c,
88  * but I'm too lazy today. Maybe later.
89  */
90
91 static GstCaps *
92 gst_ff_vid_caps_new (AVCodecContext * context, const char *mimetype,
93     const char *fieldname, ...)
94 {
95   GstStructure *structure = NULL;
96   GstCaps *caps = NULL;
97   va_list var_args;
98
99   if (context != NULL) {
100     caps = gst_caps_new_simple (mimetype,
101         "width", G_TYPE_INT, context->width,
102         "height", G_TYPE_INT, context->height,
103         "framerate", GST_TYPE_FRACTION,
104         (gint) context->frame_rate, (gint) context->frame_rate_base, NULL);
105   } else {
106     caps = gst_caps_new_simple (mimetype,
107         "width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
108         "height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
109         "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
110   }
111
112   structure = gst_caps_get_structure (caps, 0);
113
114   if (structure) {
115     va_start (var_args, fieldname);
116     gst_structure_set_valist (structure, fieldname, var_args);
117     va_end (var_args);
118   }
119
120   return caps;
121 }
122
123 /* same for audio - now with channels/sample rate
124  */
125
126 static GstCaps *
127 gst_ff_aud_caps_new (AVCodecContext * context, const char *mimetype,
128     const char *fieldname, ...)
129 {
130   GstCaps *caps = NULL;
131   GstStructure *structure = NULL;
132   va_list var_args;
133
134   if (context != NULL) {
135     caps = gst_caps_new_simple (mimetype,
136         "rate", G_TYPE_INT, context->sample_rate,
137         "channels", G_TYPE_INT, context->channels, NULL);
138   } else {
139     caps = gst_caps_new_simple (mimetype, NULL);
140   }
141
142   structure = gst_caps_get_structure (caps, 0);
143
144   if (structure) {
145     va_start (var_args, fieldname);
146     gst_structure_set_valist (structure, fieldname, var_args);
147     va_end (var_args);
148   }
149
150   return caps;
151 }
152
153 /* Convert a FFMPEG Pixel Format and optional AVCodecContext
154  * to a GstCaps. If the context is ommitted, no fixed values
155  * for video/audio size will be included in the GstCaps
156  *
157  * See below for usefulness
158  */
159
160 static GstCaps *
161 gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context)
162 {
163   GstCaps *caps = NULL;
164
165   int bpp = 0, depth = 0, endianness = 0;
166   gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
167   guint32 fmt = 0;
168
169   switch (pix_fmt) {
170     case PIX_FMT_YUV420P:
171       fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
172       break;
173     case PIX_FMT_YUVA420P:
174       fmt = GST_MAKE_FOURCC ('A', '4', '2', '0');
175       break;
176     case PIX_FMT_NV12:
177       fmt = GST_MAKE_FOURCC ('N', 'V', '1', '2');
178       break;
179     case PIX_FMT_NV21:
180       fmt = GST_MAKE_FOURCC ('N', 'V', '2', '1');
181       break;
182     case PIX_FMT_YVU420P:
183       fmt = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
184       break;
185     case PIX_FMT_YUV422:
186       fmt = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
187       break;
188     case PIX_FMT_UYVY422:
189       fmt = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
190       break;
191     case PIX_FMT_YVYU422:
192       fmt = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
193       break;
194     case PIX_FMT_UYVY411:
195       fmt = GST_MAKE_FOURCC ('I', 'Y', 'U', '1');
196       break;
197     case PIX_FMT_RGB24:
198       bpp = depth = 24;
199       endianness = G_BIG_ENDIAN;
200       r_mask = 0xff0000;
201       g_mask = 0x00ff00;
202       b_mask = 0x0000ff;
203       break;
204     case PIX_FMT_BGR24:
205       bpp = depth = 24;
206       endianness = G_BIG_ENDIAN;
207       r_mask = 0x0000ff;
208       g_mask = 0x00ff00;
209       b_mask = 0xff0000;
210       break;
211     case PIX_FMT_YUV422P:
212       fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
213       break;
214     case PIX_FMT_YUV444P:
215       fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
216       break;
217     case PIX_FMT_RGB32:
218       bpp = 32;
219       depth = 24;
220       endianness = G_BIG_ENDIAN;
221 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
222       r_mask = 0x00ff0000;
223       g_mask = 0x0000ff00;
224       b_mask = 0x000000ff;
225 #else
226       r_mask = 0x0000ff00;
227       g_mask = 0x00ff0000;
228       b_mask = 0xff000000;
229 #endif
230       break;
231     case PIX_FMT_BGR32:
232       bpp = 32;
233       depth = 24;
234       endianness = G_BIG_ENDIAN;
235 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
236       r_mask = 0x0000ff00;
237       g_mask = 0x00ff0000;
238       b_mask = 0xff000000;
239 #else
240       r_mask = 0x00ff0000;
241       g_mask = 0x0000ff00;
242       b_mask = 0x000000ff;
243 #endif
244       break;
245     case PIX_FMT_xRGB32:
246       bpp = 32;
247       depth = 24;
248       endianness = G_BIG_ENDIAN;
249 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
250       r_mask = 0xff000000;
251       g_mask = 0x00ff0000;
252       b_mask = 0x0000ff00;
253 #else
254       r_mask = 0x000000ff;
255       g_mask = 0x0000ff00;
256       b_mask = 0x00ff0000;
257 #endif
258       break;
259     case PIX_FMT_BGRx32:
260       bpp = 32;
261       depth = 24;
262       endianness = G_BIG_ENDIAN;
263 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
264       r_mask = 0x000000ff;
265       g_mask = 0x0000ff00;
266       b_mask = 0x00ff0000;
267 #else
268       r_mask = 0xff000000;
269       g_mask = 0x00ff0000;
270       b_mask = 0x0000ff00;
271 #endif
272       break;
273     case PIX_FMT_RGBA32:
274       bpp = 32;
275       depth = 32;
276       endianness = G_BIG_ENDIAN;
277 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
278       r_mask = 0x00ff0000;
279       g_mask = 0x0000ff00;
280       b_mask = 0x000000ff;
281       a_mask = 0xff000000;
282 #else
283       r_mask = 0x0000ff00;
284       g_mask = 0x00ff0000;
285       b_mask = 0xff000000;
286       a_mask = 0x000000ff;
287 #endif
288       break;
289     case PIX_FMT_BGRA32:
290       bpp = 32;
291       depth = 32;
292       endianness = G_BIG_ENDIAN;
293 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
294       r_mask = 0x0000ff00;
295       g_mask = 0x00ff0000;
296       b_mask = 0xff000000;
297       a_mask = 0x000000ff;
298 #else
299       r_mask = 0x00ff0000;
300       g_mask = 0x0000ff00;
301       b_mask = 0x000000ff;
302       a_mask = 0xff000000;
303 #endif
304       break;
305     case PIX_FMT_ARGB32:
306       bpp = 32;
307       depth = 32;
308       endianness = G_BIG_ENDIAN;
309 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
310       r_mask = 0xff000000;
311       g_mask = 0x00ff0000;
312       b_mask = 0x0000ff00;
313       a_mask = 0x000000ff;
314 #else
315       r_mask = 0x000000ff;
316       g_mask = 0x0000ff00;
317       b_mask = 0x00ff0000;
318       a_mask = 0xff000000;
319 #endif
320       break;
321     case PIX_FMT_ABGR32:
322       bpp = 32;
323       depth = 32;
324       endianness = G_BIG_ENDIAN;
325 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
326       r_mask = 0x000000ff;
327       g_mask = 0x0000ff00;
328       b_mask = 0x00ff0000;
329       a_mask = 0xff000000;
330 #else
331       r_mask = 0xff000000;
332       g_mask = 0x00ff0000;
333       b_mask = 0x0000ff00;
334       a_mask = 0x000000ff;
335 #endif
336       break;
337     case PIX_FMT_YUV410P:
338       fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
339       break;
340     case PIX_FMT_YVU410P:
341       fmt = GST_MAKE_FOURCC ('Y', 'V', 'U', '9');
342       break;
343     case PIX_FMT_YUV411P:
344       fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
345       break;
346     case PIX_FMT_Y800:{
347       GstCaps *tmp;
348
349       caps = gst_ff_vid_caps_new (context, "video/x-raw-yuv",
350           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', '8', '0', '0'),
351           NULL);
352       tmp =
353           gst_ff_vid_caps_new (context, "video/x-raw-yuv", "format",
354           GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', '8', ' ', ' '), NULL);
355       gst_caps_append (caps, tmp);
356       tmp = gst_ff_vid_caps_new (context, "video/x-raw-yuv",
357           "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'),
358           NULL);
359       gst_caps_append (caps, tmp);
360       break;
361     }
362     case PIX_FMT_Y16:
363       fmt = GST_MAKE_FOURCC ('Y', '1', '6', ' ');
364       break;
365     case PIX_FMT_RGB565:
366       bpp = depth = 16;
367       endianness = G_BYTE_ORDER;
368       r_mask = 0xf800;
369       g_mask = 0x07e0;
370       b_mask = 0x001f;
371       break;
372     case PIX_FMT_RGB555:
373       bpp = 16;
374       depth = 15;
375       endianness = G_BYTE_ORDER;
376       r_mask = 0x7c00;
377       g_mask = 0x03e0;
378       b_mask = 0x001f;
379       break;
380     case PIX_FMT_PAL8:
381       bpp = depth = 8;
382       endianness = G_BYTE_ORDER;
383       break;
384     case PIX_FMT_V308:
385       fmt = GST_MAKE_FOURCC ('v', '3', '0', '8');
386       break;
387     case PIX_FMT_AYUV4444:
388       fmt = GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
389       break;
390     case PIX_FMT_GRAY8:
391       bpp = depth = 8;
392       caps = gst_ff_vid_caps_new (context, "video/x-raw-gray",
393           "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL);
394       break;
395     case PIX_FMT_GRAY16_L:
396       bpp = depth = 16;
397       caps = gst_ff_vid_caps_new (context, "video/x-raw-gray",
398           "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth,
399           "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
400       break;
401     case PIX_FMT_GRAY16_B:
402       bpp = depth = 16;
403       caps = gst_ff_vid_caps_new (context, "video/x-raw-gray",
404           "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth,
405           "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
406       break;
407     default:
408       /* give up ... */
409       break;
410   }
411
412   if (caps == NULL) {
413     if (bpp != 0) {
414       if (a_mask != 0) {
415         caps = gst_ff_vid_caps_new (context, "video/x-raw-rgb",
416             "bpp", G_TYPE_INT, bpp,
417             "depth", G_TYPE_INT, depth,
418             "red_mask", G_TYPE_INT, r_mask,
419             "green_mask", G_TYPE_INT, g_mask,
420             "blue_mask", G_TYPE_INT, b_mask,
421             "alpha_mask", G_TYPE_INT, a_mask,
422             "endianness", G_TYPE_INT, endianness, NULL);
423       } else if (r_mask != 0) {
424         caps = gst_ff_vid_caps_new (context, "video/x-raw-rgb",
425             "bpp", G_TYPE_INT, bpp,
426             "depth", G_TYPE_INT, depth,
427             "red_mask", G_TYPE_INT, r_mask,
428             "green_mask", G_TYPE_INT, g_mask,
429             "blue_mask", G_TYPE_INT, b_mask,
430             "endianness", G_TYPE_INT, endianness, NULL);
431       } else {
432         caps = gst_ff_vid_caps_new (context, "video/x-raw-rgb",
433             "bpp", G_TYPE_INT, bpp,
434             "depth", G_TYPE_INT, depth,
435             "endianness", G_TYPE_INT, endianness, NULL);
436         if (context && context->pix_fmt == PIX_FMT_PAL8) {
437           gst_ffmpeg_set_palette (caps, context);
438         }
439       }
440     } else if (fmt) {
441       caps = gst_ff_vid_caps_new (context, "video/x-raw-yuv",
442           "format", GST_TYPE_FOURCC, fmt, NULL);
443     }
444   }
445
446   if (caps != NULL) {
447     GST_DEBUG ("caps for pix_fmt=%d: %" GST_PTR_FORMAT, pix_fmt, caps);
448   } else {
449     GST_LOG ("No caps found for pix_fmt=%d", pix_fmt);
450   }
451
452   return caps;
453 }
454
455 /* Convert a FFMPEG Sample Format and optional AVCodecContext
456  * to a GstCaps. If the context is ommitted, no fixed values
457  * for video/audio size will be included in the GstCaps
458  *
459  * See below for usefulness
460  */
461
462 static GstCaps *
463 gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
464     AVCodecContext * context)
465 {
466   GstCaps *caps = NULL;
467
468   int bpp = 0;
469   gboolean signedness = FALSE;
470
471   switch (sample_fmt) {
472     case SAMPLE_FMT_S16:
473       signedness = TRUE;
474       bpp = 16;
475       break;
476
477     default:
478       /* .. */
479       break;
480   }
481
482   if (bpp) {
483     caps = gst_ff_aud_caps_new (context, "audio/x-raw-int",
484         "signed", G_TYPE_BOOLEAN, signedness,
485         "endianness", G_TYPE_INT, G_BYTE_ORDER,
486         "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
487   }
488
489   if (caps != NULL) {
490     GST_DEBUG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
491   } else {
492     GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
493   }
494
495   return caps;
496 }
497
498 /* Convert a FFMPEG codec Type and optional AVCodecContext
499  * to a GstCaps. If the context is ommitted, no fixed values
500  * for video/audio size will be included in the GstCaps
501  *
502  * CodecType is primarily meant for uncompressed data GstCaps!
503  */
504
505 GstCaps *
506 gst_ffmpegcsp_codectype_to_caps (enum CodecType codec_type,
507     AVCodecContext * context)
508 {
509   GstCaps *caps;
510
511   switch (codec_type) {
512     case CODEC_TYPE_VIDEO:
513       if (context) {
514         caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt,
515             context->width == -1 ? NULL : context);
516       } else {
517         GstCaps *temp;
518         enum PixelFormat i;
519
520         caps = gst_caps_new_empty ();
521         for (i = 0; i < PIX_FMT_NB; i++) {
522           temp = gst_ffmpeg_pixfmt_to_caps (i, NULL);
523           if (temp != NULL) {
524             gst_caps_append (caps, temp);
525           }
526         }
527       }
528       break;
529
530     case CODEC_TYPE_AUDIO:
531       if (context) {
532         caps = gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context);
533       } else {
534         GstCaps *temp;
535         enum SampleFormat i;
536
537         caps = gst_caps_new_empty ();
538         for (i = 0; i <= SAMPLE_FMT_S16; i++) {
539           temp = gst_ffmpeg_smpfmt_to_caps (i, NULL);
540           if (temp != NULL) {
541             gst_caps_append (caps, temp);
542           }
543         }
544       }
545       break;
546
547     default:
548       /* .. */
549       caps = NULL;
550       break;
551   }
552
553   return caps;
554 }
555
556 /* Convert a GstCaps (audio/raw) to a FFMPEG SampleFmt
557  * and other audio properties in a AVCodecContext.
558  *
559  * For usefulness, see below
560  */
561
562 static void
563 gst_ffmpeg_caps_to_smpfmt (const GstCaps * caps,
564     AVCodecContext * context, gboolean raw)
565 {
566   GstStructure *structure;
567   gint depth = 0, width = 0, endianness = 0;
568   gboolean signedness = FALSE;
569
570   g_return_if_fail (gst_caps_get_size (caps) == 1);
571   structure = gst_caps_get_structure (caps, 0);
572
573   gst_structure_get_int (structure, "channels", &context->channels);
574   gst_structure_get_int (structure, "rate", &context->sample_rate);
575
576   if (!raw)
577     return;
578
579   if (gst_structure_get_int (structure, "width", &width) &&
580       gst_structure_get_int (structure, "depth", &depth) &&
581       gst_structure_get_boolean (structure, "signed", &signedness) &&
582       gst_structure_get_int (structure, "endianness", &endianness)) {
583     if (width == 16 && depth == 16 &&
584         endianness == G_BYTE_ORDER && signedness == TRUE) {
585       context->sample_fmt = SAMPLE_FMT_S16;
586     }
587   }
588 }
589
590
591 /* Convert a GstCaps (video/raw) to a FFMPEG PixFmt
592  * and other video properties in a AVCodecContext.
593  *
594  * For usefulness, see below
595  */
596
597 static void
598 gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps,
599     AVCodecContext * context, gboolean raw)
600 {
601   GstStructure *structure;
602   const GValue *fps;
603   gboolean ret;
604
605   g_return_if_fail (gst_caps_get_size (caps) == 1);
606   structure = gst_caps_get_structure (caps, 0);
607
608   ret = gst_structure_get_int (structure, "width", &context->width);
609   ret &= gst_structure_get_int (structure, "height", &context->height);
610   g_return_if_fail (ret == TRUE);
611
612   fps = gst_structure_get_value (structure, "framerate");
613   g_return_if_fail (GST_VALUE_HOLDS_FRACTION (fps));
614
615   /* framerate does not really matter */
616   context->frame_rate = gst_value_get_fraction_numerator (fps);
617   context->frame_rate_base = gst_value_get_fraction_denominator (fps);
618
619   if (!raw)
620     return;
621
622   if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
623     guint32 fourcc;
624
625     if (gst_structure_get_fourcc (structure, "format", &fourcc)) {
626       switch (fourcc) {
627         case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
628         case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
629           context->pix_fmt = PIX_FMT_YUV422;
630           break;
631         case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
632         case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
633           context->pix_fmt = PIX_FMT_UYVY422;
634           break;
635         case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
636           context->pix_fmt = PIX_FMT_YVYU422;
637           break;
638         case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'):
639           context->pix_fmt = PIX_FMT_UYVY411;
640           break;
641         case GST_MAKE_FOURCC ('I', '4', '2', '0'):
642         case GST_MAKE_FOURCC ('S', '4', '2', '0'):
643           context->pix_fmt = PIX_FMT_YUV420P;
644           break;
645         case GST_MAKE_FOURCC ('A', '4', '2', '0'):
646           context->pix_fmt = PIX_FMT_YUVA420P;
647           break;
648         case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
649           context->pix_fmt = PIX_FMT_NV12;
650           break;
651         case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
652           context->pix_fmt = PIX_FMT_NV21;
653           break;
654         case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
655           context->pix_fmt = PIX_FMT_YVU420P;
656           break;
657         case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
658           context->pix_fmt = PIX_FMT_YUV411P;
659           break;
660         case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
661           context->pix_fmt = PIX_FMT_YUV422P;
662           break;
663         case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
664           context->pix_fmt = PIX_FMT_YUV410P;
665           break;
666         case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'):
667           context->pix_fmt = PIX_FMT_YVU410P;
668           break;
669         case GST_MAKE_FOURCC ('v', '3', '0', '8'):
670           context->pix_fmt = PIX_FMT_V308;
671           break;
672         case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
673           context->pix_fmt = PIX_FMT_AYUV4444;
674           break;
675         case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
676           context->pix_fmt = PIX_FMT_YUV444P;
677           break;
678         case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
679         case GST_MAKE_FOURCC ('Y', '8', ' ', ' '):
680         case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'):
681           context->pix_fmt = PIX_FMT_Y800;
682           break;
683         case GST_MAKE_FOURCC ('Y', '1', '6', ' '):
684           context->pix_fmt = PIX_FMT_Y16;
685           break;
686       }
687     }
688   } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
689     gint bpp = 0, rmask = 0, endianness = 0, amask = 0, depth = 0;
690
691     if (gst_structure_get_int (structure, "bpp", &bpp) &&
692         gst_structure_get_int (structure, "endianness", &endianness)) {
693       if (gst_structure_get_int (structure, "red_mask", &rmask)) {
694         switch (bpp) {
695           case 32:
696             if (gst_structure_get_int (structure, "alpha_mask", &amask)) {
697 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
698               if (rmask == 0x0000ff00)
699                 context->pix_fmt = PIX_FMT_BGRA32;
700               else if (rmask == 0x00ff0000)
701                 context->pix_fmt = PIX_FMT_RGBA32;
702               else if (rmask == 0xff000000)
703                 context->pix_fmt = PIX_FMT_ARGB32;
704               else              // if (r_mask = 0x000000ff)
705                 context->pix_fmt = PIX_FMT_ABGR32;
706 #else
707               if (rmask == 0x00ff0000)
708                 context->pix_fmt = PIX_FMT_BGRA32;
709               else if (rmask == 0x0000ff00)
710                 context->pix_fmt = PIX_FMT_RGBA32;
711               else if (rmask == 0x000000ff)
712                 context->pix_fmt = PIX_FMT_ARGB32;
713               else              // if (rmask == 0xff000000)
714                 context->pix_fmt = PIX_FMT_ABGR32;
715 #endif
716             } else {
717 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
718               if (rmask == 0x00ff0000)
719                 context->pix_fmt = PIX_FMT_RGB32;
720               else if (rmask == 0x0000ff00)
721                 context->pix_fmt = PIX_FMT_BGR32;
722               else if (rmask == 0xff000000)
723                 context->pix_fmt = PIX_FMT_xRGB32;
724               else              // if (rmask == 0x000000ff)
725                 context->pix_fmt = PIX_FMT_BGRx32;
726 #else
727               if (rmask == 0x0000ff00)
728                 context->pix_fmt = PIX_FMT_RGB32;
729               else if (rmask == 0x00ff0000)
730                 context->pix_fmt = PIX_FMT_BGR32;
731               else if (rmask == 0x000000ff)
732                 context->pix_fmt = PIX_FMT_xRGB32;
733               else              // if (rmask == 0xff000000)
734                 context->pix_fmt = PIX_FMT_BGRx32;
735 #endif
736             }
737             break;
738           case 24:
739             if (rmask == 0x0000FF)
740               context->pix_fmt = PIX_FMT_BGR24;
741             else
742               context->pix_fmt = PIX_FMT_RGB24;
743             break;
744           case 16:
745             if (endianness == G_BYTE_ORDER) {
746               context->pix_fmt = PIX_FMT_RGB565;
747               if (gst_structure_get_int (structure, "depth", &depth)) {
748                 if (depth == 15)
749                   context->pix_fmt = PIX_FMT_RGB555;
750               }
751             }
752             break;
753           case 15:
754             if (endianness == G_BYTE_ORDER)
755               context->pix_fmt = PIX_FMT_RGB555;
756             break;
757           default:
758             /* nothing */
759             break;
760         }
761       } else {
762         if (bpp == 8) {
763           context->pix_fmt = PIX_FMT_PAL8;
764           gst_ffmpeg_get_palette (caps, context);
765         }
766       }
767     }
768   } else if (gst_structure_has_name (structure, "video/x-raw-gray")) {
769     gint bpp = 0;
770
771     if (gst_structure_get_int (structure, "bpp", &bpp)) {
772       switch (bpp) {
773         case 8:
774           context->pix_fmt = PIX_FMT_GRAY8;
775           break;
776         case 16:{
777           gint endianness = 0;
778
779           if (gst_structure_get_int (structure, "endianness", &endianness)) {
780             if (endianness == G_LITTLE_ENDIAN)
781               context->pix_fmt = PIX_FMT_GRAY16_L;
782             else if (endianness == G_BIG_ENDIAN)
783               context->pix_fmt = PIX_FMT_GRAY16_B;
784           }
785         }
786           break;
787       }
788     }
789   }
790 }
791
792 /* Convert a GstCaps and a FFMPEG codec Type to a
793  * AVCodecContext. If the context is ommitted, no fixed values
794  * for video/audio size will be included in the context
795  *
796  * CodecType is primarily meant for uncompressed data GstCaps!
797  */
798
799 void
800 gst_ffmpegcsp_caps_with_codectype (enum CodecType type,
801     const GstCaps * caps, AVCodecContext * context)
802 {
803   if (context == NULL)
804     return;
805
806   switch (type) {
807     case CODEC_TYPE_VIDEO:
808       gst_ffmpeg_caps_to_pixfmt (caps, context, TRUE);
809       break;
810
811     case CODEC_TYPE_AUDIO:
812       gst_ffmpeg_caps_to_smpfmt (caps, context, TRUE);
813       break;
814
815     default:
816       /* unknown */
817       break;
818   }
819 }
820
821 #define GEN_MASK(x) ((1<<(x))-1)
822 #define ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
823 #define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x))
824
825 /*
826  * Fill in pointers to memory in a AVPicture, where
827  * everything is aligned by 4 (as required by X).
828  * This is mostly a copy from imgconvert.c with some
829  * small changes.
830  */
831 int
832 gst_ffmpegcsp_avpicture_fill (AVPicture * picture,
833     uint8_t * ptr, enum PixelFormat pix_fmt, int width, int height,
834     int interlaced)
835 {
836   int size, w2, h2, size2;
837   int stride, stride2;
838   PixFmtInfo *pinfo;
839
840   pinfo = get_pix_fmt_info (pix_fmt);
841
842   picture->interlaced = interlaced;
843
844   switch (pix_fmt) {
845     case PIX_FMT_YUV420P:
846     case PIX_FMT_YUV422P:
847     case PIX_FMT_YUV444P:
848     case PIX_FMT_YUV410P:
849     case PIX_FMT_YUV411P:
850     case PIX_FMT_YUVJ420P:
851     case PIX_FMT_YUVJ422P:
852     case PIX_FMT_YUVJ444P:
853       stride = GST_ROUND_UP_4 (width);
854       h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
855       size = stride * h2;
856       w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
857       stride2 = GST_ROUND_UP_4 (w2);
858       h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
859       size2 = stride2 * h2;
860       picture->data[0] = ptr;
861       picture->data[1] = picture->data[0] + size;
862       picture->data[2] = picture->data[1] + size2;
863       picture->linesize[0] = stride;
864       picture->linesize[1] = stride2;
865       picture->linesize[2] = stride2;
866       return size + 2 * size2;
867       /* PIX_FMT_YVU420P = YV12: same as PIX_FMT_YUV420P, but
868        *  with U and V plane swapped. Strides as in videotestsrc */
869     case PIX_FMT_YUVA420P:
870       stride = GST_ROUND_UP_4 (width);
871       h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
872       size = stride * h2;
873       w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
874       stride2 = GST_ROUND_UP_4 (w2);
875       h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
876       size2 = stride2 * h2;
877       picture->data[0] = ptr;
878       picture->data[1] = picture->data[0] + size;
879       picture->data[2] = picture->data[1] + size2;
880       picture->data[3] = picture->data[2] + size2;
881       picture->linesize[0] = stride;
882       picture->linesize[1] = stride2;
883       picture->linesize[2] = stride2;
884       picture->linesize[3] = stride;
885       return 2 * size + 2 * size2;
886     case PIX_FMT_YVU410P:
887     case PIX_FMT_YVU420P:
888       stride = GST_ROUND_UP_4 (width);
889       h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
890       size = stride * h2;
891       w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
892       stride2 = GST_ROUND_UP_4 (w2);
893       h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
894       size2 = stride2 * h2;
895       picture->data[0] = ptr;
896       picture->data[2] = picture->data[0] + size;
897       picture->data[1] = picture->data[2] + size2;
898       picture->linesize[0] = stride;
899       picture->linesize[1] = stride2;
900       picture->linesize[2] = stride2;
901       return size + 2 * size2;
902     case PIX_FMT_NV12:
903     case PIX_FMT_NV21:
904       stride = GST_ROUND_UP_4 (width);
905       h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
906       size = stride * h2;
907       w2 = 2 * DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
908       stride2 = GST_ROUND_UP_4 (w2);
909       h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
910       size2 = stride2 * h2;
911       picture->data[0] = ptr;
912       picture->data[1] = picture->data[0] + size;
913       picture->data[2] = NULL;
914       picture->linesize[0] = stride;
915       picture->linesize[1] = stride2;
916       picture->linesize[2] = 0;
917       return size + size2;
918     case PIX_FMT_RGB24:
919     case PIX_FMT_BGR24:
920       stride = GST_ROUND_UP_4 (width * 3);
921       size = stride * height;
922       picture->data[0] = ptr;
923       picture->data[1] = NULL;
924       picture->data[2] = NULL;
925       picture->linesize[0] = stride;
926       return size;
927     case PIX_FMT_AYUV4444:
928     case PIX_FMT_RGB32:
929     case PIX_FMT_RGBA32:
930     case PIX_FMT_ARGB32:
931     case PIX_FMT_BGR32:
932     case PIX_FMT_BGRA32:
933     case PIX_FMT_ABGR32:
934     case PIX_FMT_xRGB32:
935     case PIX_FMT_BGRx32:
936       stride = width * 4;
937       size = stride * height;
938       picture->data[0] = ptr;
939       picture->data[1] = NULL;
940       picture->data[2] = NULL;
941       picture->linesize[0] = stride;
942       return size;
943     case PIX_FMT_RGB555:
944     case PIX_FMT_RGB565:
945     case PIX_FMT_YUV422:
946     case PIX_FMT_UYVY422:
947     case PIX_FMT_YVYU422:
948       stride = GST_ROUND_UP_4 (width * 2);
949       size = stride * height;
950       picture->data[0] = ptr;
951       picture->data[1] = NULL;
952       picture->data[2] = NULL;
953       picture->linesize[0] = stride;
954       return size;
955     case PIX_FMT_V308:
956       stride = GST_ROUND_UP_4 (width * 3);
957       size = stride * height;
958       picture->data[0] = ptr;
959       picture->data[1] = NULL;
960       picture->data[2] = NULL;
961       picture->linesize[0] = stride;
962       return size;
963     case PIX_FMT_UYVY411:
964       stride =
965           GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) + GST_ROUND_UP_4 (width) / 2);
966       size = stride * height;
967       picture->data[0] = ptr;
968       picture->data[1] = NULL;
969       picture->data[2] = NULL;
970       picture->linesize[0] = stride;
971       return size;
972     case PIX_FMT_Y800:
973     case PIX_FMT_GRAY8:
974       stride = GST_ROUND_UP_4 (width);
975       size = stride * height;
976       picture->data[0] = ptr;
977       picture->data[1] = NULL;
978       picture->data[2] = NULL;
979       picture->linesize[0] = stride;
980       return size;
981     case PIX_FMT_Y16:
982     case PIX_FMT_GRAY16_L:
983     case PIX_FMT_GRAY16_B:
984       stride = GST_ROUND_UP_4 (width * 2);
985       size = stride * height;
986       picture->data[0] = ptr;
987       picture->data[1] = NULL;
988       picture->data[2] = NULL;
989       picture->linesize[0] = stride;
990       return size;
991     case PIX_FMT_MONOWHITE:
992     case PIX_FMT_MONOBLACK:
993       stride = GST_ROUND_UP_4 ((width + 7) >> 3);
994       size = stride * height;
995       picture->data[0] = ptr;
996       picture->data[1] = NULL;
997       picture->data[2] = NULL;
998       picture->linesize[0] = stride;
999       return size;
1000     case PIX_FMT_PAL8:
1001       /* already forced to be with stride, so same result as other function */
1002       stride = GST_ROUND_UP_4 (width);
1003       size = stride * height;
1004       picture->data[0] = ptr;
1005       picture->data[1] = ptr + size;    /* palette is stored here as 256 32 bit words */
1006       picture->data[2] = NULL;
1007       picture->linesize[0] = stride;
1008       picture->linesize[1] = 4;
1009       return size + 256 * 4;
1010     default:
1011       picture->data[0] = NULL;
1012       picture->data[1] = NULL;
1013       picture->data[2] = NULL;
1014       picture->data[3] = NULL;
1015       return -1;
1016   }
1017
1018   return 0;
1019 }