gst/ffmpegcolorspace/gstffmpegcodecmap.c: Patch from Eric Jonas to support conversion...
[platform/upstream/gstreamer.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 /*
34  * Read a palette from a caps.
35  */
36
37 static void
38 gst_ffmpeg_get_palette (const GstCaps * caps, AVCodecContext * context)
39 {
40   GstStructure *str = gst_caps_get_structure (caps, 0);
41   const GValue *palette_v;
42
43   /* do we have a palette? */
44   if ((palette_v = gst_structure_get_value (str, "palette_data")) && context) {
45     const GstBuffer *palette;
46
47     palette = gst_value_get_buffer (palette_v);
48     if (palette && GST_BUFFER_SIZE (palette) >= 256 * 4) {
49       if (context->palctrl)
50         av_free (context->palctrl);
51       context->palctrl = av_malloc (sizeof (AVPaletteControl));
52       context->palctrl->palette_changed = 1;
53       memcpy (context->palctrl->palette, GST_BUFFER_DATA (palette),
54           AVPALETTE_SIZE);
55     }
56   }
57 }
58
59 static void
60 gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context)
61 {
62   if (context->palctrl) {
63     GstBuffer *palette = gst_buffer_new_and_alloc (256 * 4);
64
65     memcpy (GST_BUFFER_DATA (palette), context->palctrl->palette,
66         AVPALETTE_SIZE);
67     gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, palette, NULL);
68     gst_buffer_unref (palette);
69   }
70 }
71
72 /* this macro makes a caps width fixed or unfixed width/height
73  * properties depending on whether we've got a context.
74  *
75  * See below for why we use this.
76  *
77  * We should actually do this stuff at the end, like in riff-media.c,
78  * but I'm too lazy today. Maybe later.
79  */
80
81 #define GST_FF_VID_CAPS_NEW(mimetype, ...)                      \
82     (context != NULL) ?                                         \
83     gst_caps_new_simple (mimetype,                              \
84         "width",     G_TYPE_INT,   context->width,              \
85         "height",    G_TYPE_INT,   context->height,             \
86         "framerate", GST_TYPE_FRACTION,                         \
87         (gint) context->frame_rate, (gint) context->frame_rate_base, \
88         __VA_ARGS__, NULL)                                      \
89     :                                                           \
90     gst_caps_new_simple (mimetype,                              \
91         "width",     GST_TYPE_INT_RANGE, 1, G_MAXINT,           \
92         "height",    GST_TYPE_INT_RANGE, 1, G_MAXINT,           \
93         "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,\
94         __VA_ARGS__, NULL)
95
96 /* same for audio - now with channels/sample rate
97  */
98
99 #define GST_FF_AUD_CAPS_NEW(mimetype, ...)                      \
100     (context != NULL) ?                                         \
101     gst_caps_new_simple (mimetype,                              \
102         "rate", G_TYPE_INT, context->sample_rate,               \
103         "channels", G_TYPE_INT, context->channels,              \
104         __VA_ARGS__, NULL)                                      \
105     :                                                           \
106     gst_caps_new_simple (mimetype,                              \
107         __VA_ARGS__, NULL)
108
109 /* Convert a FFMPEG Pixel Format and optional AVCodecContext
110  * to a GstCaps. If the context is ommitted, no fixed values
111  * for video/audio size will be included in the GstCaps
112  *
113  * See below for usefulness
114  */
115
116 static GstCaps *
117 gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context)
118 {
119   GstCaps *caps = NULL;
120
121   int bpp = 0, depth = 0, endianness = 0;
122   gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
123   guint32 fmt = 0;
124
125   switch (pix_fmt) {
126     case PIX_FMT_YUV420P:
127       fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
128       break;
129     case PIX_FMT_YVU420P:
130       fmt = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
131       break;
132     case PIX_FMT_YUV422:
133       fmt = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
134       break;
135     case PIX_FMT_UYVY422:
136       fmt = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
137       break;
138     case PIX_FMT_RGB24:
139       bpp = depth = 24;
140       endianness = G_BIG_ENDIAN;
141       r_mask = 0xff0000;
142       g_mask = 0x00ff00;
143       b_mask = 0x0000ff;
144       break;
145     case PIX_FMT_BGR24:
146       bpp = depth = 24;
147       endianness = G_BIG_ENDIAN;
148       r_mask = 0x0000ff;
149       g_mask = 0x00ff00;
150       b_mask = 0xff0000;
151       break;
152     case PIX_FMT_YUV422P:
153       fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
154       break;
155     case PIX_FMT_YUV444P:
156       fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
157       break;
158     case PIX_FMT_RGB32:
159       bpp = 32;
160       depth = 24;
161       endianness = G_BIG_ENDIAN;
162 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
163       r_mask = 0x00ff0000;
164       g_mask = 0x0000ff00;
165       b_mask = 0x000000ff;
166 #else
167       r_mask = 0x0000ff00;
168       g_mask = 0x00ff0000;
169       b_mask = 0xff000000;
170 #endif
171       break;
172     case PIX_FMT_BGR32:
173       bpp = 32;
174       depth = 24;
175       endianness = G_BIG_ENDIAN;
176 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
177       r_mask = 0x0000ff00;
178       g_mask = 0x00ff0000;
179       b_mask = 0xff000000;
180 #else
181       r_mask = 0x00ff0000;
182       g_mask = 0x0000ff00;
183       b_mask = 0x000000ff;
184 #endif
185       break;
186     case PIX_FMT_RGBA32:
187       bpp = 32;
188       depth = 32;
189       endianness = G_BIG_ENDIAN;
190 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
191       r_mask = 0x000000ff;
192       g_mask = 0x0000ff00;
193       b_mask = 0x00ff0000;
194       a_mask = 0xff000000;
195 #else
196       r_mask = 0xff000000;
197       g_mask = 0x00ff0000;
198       b_mask = 0x0000ff00;
199       a_mask = 0x000000ff;
200 #endif
201       break;
202     case PIX_FMT_BGRA32:
203       bpp = 32;
204       depth = 32;
205       endianness = G_BIG_ENDIAN;
206 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
207       r_mask = 0x0000ff00;
208       g_mask = 0x00ff0000;
209       b_mask = 0xff000000;
210       a_mask = 0x000000ff;
211 #else
212       r_mask = 0x00ff0000;
213       g_mask = 0x0000ff00;
214       b_mask = 0x000000ff;
215       a_mask = 0xff000000;
216
217 #endif
218       break;
219     case PIX_FMT_YUV410P:
220       fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
221       break;
222     case PIX_FMT_YUV411P:
223       fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
224       break;
225     case PIX_FMT_RGB565:
226       bpp = depth = 16;
227       endianness = G_BYTE_ORDER;
228       r_mask = 0xf800;
229       g_mask = 0x07e0;
230       b_mask = 0x001f;
231       break;
232     case PIX_FMT_RGB555:
233       bpp = 16;
234       depth = 15;
235       endianness = G_BYTE_ORDER;
236       r_mask = 0x7c00;
237       g_mask = 0x03e0;
238       b_mask = 0x001f;
239       break;
240     case PIX_FMT_PAL8:
241       bpp = depth = 8;
242       endianness = G_BYTE_ORDER;
243       break;
244     case PIX_FMT_AYUV4444:
245       fmt = GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
246       break;
247     case PIX_FMT_GRAY8:
248       bpp = depth = 8;
249       caps = GST_FF_VID_CAPS_NEW ("video/x-raw-gray",
250           "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL);
251       break;
252     default:
253       /* give up ... */
254       break;
255   }
256
257   if (caps == NULL) {
258     if (bpp != 0) {
259       if (a_mask != 0) {
260         caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
261             "bpp", G_TYPE_INT, bpp,
262             "depth", G_TYPE_INT, depth,
263             "red_mask", G_TYPE_INT, r_mask,
264             "green_mask", G_TYPE_INT, g_mask,
265             "blue_mask", G_TYPE_INT, b_mask,
266             "alpha_mask", G_TYPE_INT, a_mask,
267             "endianness", G_TYPE_INT, endianness, NULL);
268       } else if (r_mask != 0) {
269         caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
270             "bpp", G_TYPE_INT, bpp,
271             "depth", G_TYPE_INT, depth,
272             "red_mask", G_TYPE_INT, r_mask,
273             "green_mask", G_TYPE_INT, g_mask,
274             "blue_mask", G_TYPE_INT, b_mask,
275             "endianness", G_TYPE_INT, endianness, NULL);
276       } else {
277         caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
278             "bpp", G_TYPE_INT, bpp,
279             "depth", G_TYPE_INT, depth,
280             "endianness", G_TYPE_INT, endianness, NULL);
281         if (context) {
282           gst_ffmpeg_set_palette (caps, context);
283         }
284       }
285     } else if (fmt) {
286       caps = GST_FF_VID_CAPS_NEW ("video/x-raw-yuv",
287           "format", GST_TYPE_FOURCC, fmt, NULL);
288     }
289   }
290
291   if (caps != NULL) {
292     char *str = gst_caps_to_string (caps);
293
294     GST_DEBUG ("caps for pix_fmt=%d: %s", pix_fmt, str);
295     g_free (str);
296   } else {
297     GST_WARNING ("No caps found for pix_fmt=%d", pix_fmt);
298   }
299
300   return caps;
301 }
302
303 /* Convert a FFMPEG Sample Format and optional AVCodecContext
304  * to a GstCaps. If the context is ommitted, no fixed values
305  * for video/audio size will be included in the GstCaps
306  *
307  * See below for usefulness
308  */
309
310 static GstCaps *
311 gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt,
312     AVCodecContext * context)
313 {
314   GstCaps *caps = NULL;
315
316   int bpp = 0;
317   gboolean signedness = FALSE;
318
319   switch (sample_fmt) {
320     case SAMPLE_FMT_S16:
321       signedness = TRUE;
322       bpp = 16;
323       break;
324
325     default:
326       /* .. */
327       break;
328   }
329
330   if (bpp) {
331     caps = GST_FF_AUD_CAPS_NEW ("audio/x-raw-int",
332         "signed", G_TYPE_BOOLEAN, signedness,
333         "endianness", G_TYPE_INT, G_BYTE_ORDER,
334         "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
335   }
336
337   if (caps != NULL) {
338     char *str = gst_caps_to_string (caps);
339
340     GST_DEBUG ("caps for sample_fmt=%d: %s", sample_fmt, str);
341     g_free (str);
342   } else {
343     GST_WARNING ("No caps found for sample_fmt=%d", sample_fmt);
344   }
345
346   return caps;
347 }
348
349 /* Convert a FFMPEG codec Type and optional AVCodecContext
350  * to a GstCaps. If the context is ommitted, no fixed values
351  * for video/audio size will be included in the GstCaps
352  *
353  * CodecType is primarily meant for uncompressed data GstCaps!
354  */
355
356 GstCaps *
357 gst_ffmpegcsp_codectype_to_caps (enum CodecType codec_type,
358     AVCodecContext * context)
359 {
360   GstCaps *caps;
361
362   switch (codec_type) {
363     case CODEC_TYPE_VIDEO:
364       if (context) {
365         caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt,
366             context->width == -1 ? NULL : context);
367       } else {
368         GstCaps *temp;
369         enum PixelFormat i;
370
371         caps = gst_caps_new_empty ();
372         for (i = 0; i < PIX_FMT_NB; i++) {
373           temp = gst_ffmpeg_pixfmt_to_caps (i, NULL);
374           if (temp != NULL) {
375             gst_caps_append (caps, temp);
376           }
377         }
378       }
379       break;
380
381     case CODEC_TYPE_AUDIO:
382       if (context) {
383         caps = gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context);
384       } else {
385         GstCaps *temp;
386         enum SampleFormat i;
387
388         caps = gst_caps_new_empty ();
389         for (i = 0; i <= SAMPLE_FMT_S16; i++) {
390           temp = gst_ffmpeg_smpfmt_to_caps (i, NULL);
391           if (temp != NULL) {
392             gst_caps_append (caps, temp);
393           }
394         }
395       }
396       break;
397
398     default:
399       /* .. */
400       caps = NULL;
401       break;
402   }
403
404   return caps;
405 }
406
407 /* Convert a GstCaps (audio/raw) to a FFMPEG SampleFmt
408  * and other audio properties in a AVCodecContext.
409  *
410  * For usefulness, see below
411  */
412
413 static void
414 gst_ffmpeg_caps_to_smpfmt (const GstCaps * caps,
415     AVCodecContext * context, gboolean raw)
416 {
417   GstStructure *structure;
418   gint depth = 0, width = 0, endianness = 0;
419   gboolean signedness = FALSE;
420
421   g_return_if_fail (gst_caps_get_size (caps) == 1);
422   structure = gst_caps_get_structure (caps, 0);
423
424   gst_structure_get_int (structure, "channels", &context->channels);
425   gst_structure_get_int (structure, "rate", &context->sample_rate);
426
427   if (!raw)
428     return;
429
430   if (gst_structure_get_int (structure, "width", &width) &&
431       gst_structure_get_int (structure, "depth", &depth) &&
432       gst_structure_get_int (structure, "signed", &signedness) &&
433       gst_structure_get_int (structure, "endianness", &endianness)) {
434     if (width == 16 && depth == 16 &&
435         endianness == G_BYTE_ORDER && signedness == TRUE) {
436       context->sample_fmt = SAMPLE_FMT_S16;
437     }
438   }
439 }
440
441
442 /* Convert a GstCaps (video/raw) to a FFMPEG PixFmt
443  * and other video properties in a AVCodecContext.
444  *
445  * For usefulness, see below
446  */
447
448 static void
449 gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps,
450     AVCodecContext * context, gboolean raw)
451 {
452   GstStructure *structure;
453   const GValue *fps;
454   gboolean ret;
455
456   g_return_if_fail (gst_caps_get_size (caps) == 1);
457   structure = gst_caps_get_structure (caps, 0);
458
459   ret = gst_structure_get_int (structure, "width", &context->width);
460   ret &= gst_structure_get_int (structure, "height", &context->height);
461   g_return_if_fail (ret == TRUE);
462
463   fps = gst_structure_get_value (structure, "framerate");
464   g_return_if_fail (GST_VALUE_HOLDS_FRACTION (fps));
465
466   /* framerate does not really matter */
467   context->frame_rate = gst_value_get_fraction_numerator (fps);
468   context->frame_rate_base = gst_value_get_fraction_denominator (fps);
469
470   if (!raw)
471     return;
472
473   if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
474     guint32 fourcc;
475
476     if (gst_structure_get_fourcc (structure, "format", &fourcc)) {
477       switch (fourcc) {
478         case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
479           context->pix_fmt = PIX_FMT_YUV422;
480           break;
481         case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
482           context->pix_fmt = PIX_FMT_UYVY422;
483           break;
484         case GST_MAKE_FOURCC ('I', '4', '2', '0'):
485           context->pix_fmt = PIX_FMT_YUV420P;
486           break;
487         case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
488           context->pix_fmt = PIX_FMT_YVU420P;
489           break;
490         case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
491           context->pix_fmt = PIX_FMT_YUV411P;
492           break;
493         case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
494           context->pix_fmt = PIX_FMT_YUV422P;
495           break;
496         case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
497           context->pix_fmt = PIX_FMT_YUV410P;
498           break;
499         case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
500           context->pix_fmt = PIX_FMT_AYUV4444;
501           break;
502         case GST_MAKE_FOURCC ('Y', '4', '4', '4'):
503           context->pix_fmt = PIX_FMT_YUV444P;
504           break;
505       }
506     }
507   } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
508     gint bpp = 0, rmask = 0, endianness = 0, amask = 0, depth = 0;
509
510     if (gst_structure_get_int (structure, "bpp", &bpp) &&
511         gst_structure_get_int (structure, "endianness", &endianness)) {
512       if (gst_structure_get_int (structure, "red_mask", &rmask)) {
513         switch (bpp) {
514           case 32:
515             if (gst_structure_get_int (structure, "alpha_mask", &amask)) {
516 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
517               if (rmask == 0x0000ff00)
518 #else
519               if (rmask == 0x00ff0000)
520 #endif
521                 context->pix_fmt = PIX_FMT_BGRA32;
522               else
523                 context->pix_fmt = PIX_FMT_RGBA32;
524             } else {
525 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
526               if (rmask == 0x00ff0000)
527 #else
528               if (rmask == 0x0000ff00)
529 #endif
530                 context->pix_fmt = PIX_FMT_RGB32;
531
532 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
533               if (rmask == 0x0000ff00)
534 #else
535               if (rmask == 0x00ff0000)
536 #endif
537                 context->pix_fmt = PIX_FMT_BGR32;
538             }
539             break;
540           case 24:
541             if (rmask == 0x0000FF)
542               context->pix_fmt = PIX_FMT_BGR24;
543             else
544               context->pix_fmt = PIX_FMT_RGB24;
545             break;
546           case 16:
547             if (endianness == G_BYTE_ORDER) {
548               context->pix_fmt = PIX_FMT_RGB565;
549               if (gst_structure_get_int (structure, "depth", &depth)) {
550                 if (depth == 15)
551                   context->pix_fmt = PIX_FMT_RGB555;
552               }
553             }
554             break;
555           case 15:
556             if (endianness == G_BYTE_ORDER)
557               context->pix_fmt = PIX_FMT_RGB555;
558             break;
559           default:
560             /* nothing */
561             break;
562         }
563       } else {
564         if (bpp == 8) {
565           context->pix_fmt = PIX_FMT_PAL8;
566           gst_ffmpeg_get_palette (caps, context);
567         }
568       }
569     }
570   } else if (gst_structure_has_name (structure, "video/x-raw-gray")) {
571     gint bpp = 0;
572
573     if (gst_structure_get_int (structure, "bpp", &bpp)) {
574       switch (bpp) {
575         case 8:
576           context->pix_fmt = PIX_FMT_GRAY8;
577           break;
578       }
579     }
580   }
581 }
582
583 /* Convert a GstCaps and a FFMPEG codec Type to a
584  * AVCodecContext. If the context is ommitted, no fixed values
585  * for video/audio size will be included in the context
586  *
587  * CodecType is primarily meant for uncompressed data GstCaps!
588  */
589
590 void
591 gst_ffmpegcsp_caps_with_codectype (enum CodecType type,
592     const GstCaps * caps, AVCodecContext * context)
593 {
594   if (context == NULL)
595     return;
596
597   switch (type) {
598     case CODEC_TYPE_VIDEO:
599       gst_ffmpeg_caps_to_pixfmt (caps, context, TRUE);
600       break;
601
602     case CODEC_TYPE_AUDIO:
603       gst_ffmpeg_caps_to_smpfmt (caps, context, TRUE);
604       break;
605
606     default:
607       /* unknown */
608       break;
609   }
610 }
611
612 #define GEN_MASK(x) ((1<<(x))-1)
613 #define ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x))
614 #define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x))
615
616 /*
617  * Fill in pointers to memory in a AVPicture, where
618  * everything is aligned by 4 (as required by X).
619  * This is mostly a copy from imgconvert.c with some
620  * small changes.
621  */
622 int
623 gst_ffmpegcsp_avpicture_fill (AVPicture * picture,
624     uint8_t * ptr, enum PixelFormat pix_fmt, int width, int height)
625 {
626   int size, w2, h2, size2;
627   int stride, stride2;
628   PixFmtInfo *pinfo;
629
630   pinfo = get_pix_fmt_info (pix_fmt);
631
632   switch (pix_fmt) {
633     case PIX_FMT_YUV420P:
634     case PIX_FMT_YUV422P:
635     case PIX_FMT_YUV444P:
636     case PIX_FMT_YUV410P:
637     case PIX_FMT_YUV411P:
638     case PIX_FMT_YUVJ420P:
639     case PIX_FMT_YUVJ422P:
640     case PIX_FMT_YUVJ444P:
641       stride = GST_ROUND_UP_4 (width);
642       h2 = ROUND_UP_X (height, pinfo->y_chroma_shift);
643       size = stride * h2;
644       w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift);
645       stride2 = GST_ROUND_UP_4 (w2);
646       h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift);
647       size2 = stride2 * h2;
648       picture->data[0] = ptr;
649       picture->data[1] = picture->data[0] + size;
650       picture->data[2] = picture->data[1] + size2;
651       picture->linesize[0] = stride;
652       picture->linesize[1] = stride2;
653       picture->linesize[2] = stride2;
654       return size + 2 * size2;
655       /* PIX_FMT_YVU420P = YV12: same as PIX_FMT_YUV420P, but
656        *  with U and V plane swapped. Strides as in videotestsrc */
657     case PIX_FMT_YVU420P:
658       stride = GST_ROUND_UP_4 (width);
659       h2 = GST_ROUND_UP_2 (height);
660       size = stride * h2;
661       stride2 = GST_ROUND_UP_8 (stride) / 2;
662       h2 = GST_ROUND_UP_2 (height) / 2;
663       size2 = stride2 * h2;
664       picture->data[0] = ptr;
665       picture->data[2] = picture->data[0] + size;
666       picture->data[1] = picture->data[2] + size2;
667       picture->linesize[0] = stride;
668       picture->linesize[1] = GST_ROUND_UP_8 (stride) / 2;
669       picture->linesize[2] = GST_ROUND_UP_8 (stride) / 2;
670       return size + 2 * size2;
671     case PIX_FMT_RGB24:
672     case PIX_FMT_BGR24:
673       stride = GST_ROUND_UP_4 (width * 3);
674       size = stride * height;
675       picture->data[0] = ptr;
676       picture->data[1] = NULL;
677       picture->data[2] = NULL;
678       picture->linesize[0] = stride;
679       return size;
680     case PIX_FMT_AYUV4444:
681     case PIX_FMT_RGB32:
682     case PIX_FMT_RGBA32:
683     case PIX_FMT_BGR32:
684     case PIX_FMT_BGRA32:
685       stride = width * 4;
686       size = stride * height;
687       picture->data[0] = ptr;
688       picture->data[1] = NULL;
689       picture->data[2] = NULL;
690       picture->linesize[0] = stride;
691       return size;
692     case PIX_FMT_RGB555:
693     case PIX_FMT_RGB565:
694     case PIX_FMT_YUV422:
695     case PIX_FMT_UYVY422:
696       stride = GST_ROUND_UP_4 (width * 2);
697       size = stride * height;
698       picture->data[0] = ptr;
699       picture->data[1] = NULL;
700       picture->data[2] = NULL;
701       picture->linesize[0] = stride;
702       return size;
703     case PIX_FMT_UYVY411:
704       /* FIXME, probably not the right stride */
705       stride = GST_ROUND_UP_4 (width);
706       size = stride * height;
707       picture->data[0] = ptr;
708       picture->data[1] = NULL;
709       picture->data[2] = NULL;
710       picture->linesize[0] = width + width / 2;
711       return size + size / 2;
712     case PIX_FMT_GRAY8:
713       stride = GST_ROUND_UP_4 (width);
714       size = stride * height;
715       picture->data[0] = ptr;
716       picture->data[1] = NULL;
717       picture->data[2] = NULL;
718       picture->linesize[0] = stride;
719       return size;
720     case PIX_FMT_MONOWHITE:
721     case PIX_FMT_MONOBLACK:
722       stride = GST_ROUND_UP_4 ((width + 7) >> 3);
723       size = stride * height;
724       picture->data[0] = ptr;
725       picture->data[1] = NULL;
726       picture->data[2] = NULL;
727       picture->linesize[0] = stride;
728       return size;
729     case PIX_FMT_PAL8:
730       /* already forced to be with stride, so same result as other function */
731       stride = GST_ROUND_UP_4 (width);
732       size = stride * height;
733       picture->data[0] = ptr;
734       picture->data[1] = ptr + size;    /* palette is stored here as 256 32 bit words */
735       picture->data[2] = NULL;
736       picture->linesize[0] = stride;
737       picture->linesize[1] = 4;
738       return size + 256 * 4;
739     default:
740       picture->data[0] = NULL;
741       picture->data[1] = NULL;
742       picture->data[2] = NULL;
743       picture->data[3] = NULL;
744       return -1;
745   }
746
747   return 0;
748 }