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