1c4e483d1a8a9a2ca17d58d4dfdc47f786d0108e
[platform/adaptation/emulator/gst-plugins-emulator.git] / src / gstmaruutils.c
1 /*
2  * GStreamer codec plugin for Tizen Emulator.
3  *
4  * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * KiTae Kim <kt920.kim@samsung.com>
8  * SeokYeon Hwang <syeon.hwang@samsung.com>
9  * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Library General Public
13  * License as published by the Free Software Foundation; either
14  * version 2 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Library General Public License for more details.
20  *
21  * You should have received a copy of the GNU Library General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31 #include "gstmaruutils.h"
32 #include <gst/audio/multichannel.h>
33 #include <gst/pbutils/codec-utils.h>
34
35 gint
36 gst_maru_smpfmt_depth (int smp_fmt)
37 {
38   gint depth = -1;
39
40   switch (smp_fmt) {
41   case SAMPLE_FMT_U8:
42     depth = 1;
43     break;
44   case SAMPLE_FMT_S16:
45     depth = 2;
46     break;
47   case SAMPLE_FMT_S32:
48   case SAMPLE_FMT_FLT:
49     depth = 4;
50     break;
51   case SAMPLE_FMT_DBL:
52     depth = 8;
53     break;
54   default:
55     GST_ERROR ("Unhandled sample format !");
56     break;
57   }
58
59   return depth;
60 }
61
62 // FFmpeg
63 static const struct
64 {
65   guint64 ff;
66   GstAudioChannelPosition gst;
67 } _ff_to_gst_layout[] = {
68   {
69   CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
70   CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
71   CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
72   CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, {
73   CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
74   CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
75   CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
76   CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
77   CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
78   CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
79   CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
80   CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
81   CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
82   CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
83   CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
84   CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
85   CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
86   CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
87   CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
88   CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
89 };
90
91 static GstAudioChannelPosition *
92 gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels)
93 {
94   guint nchannels = 0, i, j;
95   GstAudioChannelPosition *pos = NULL;
96   gboolean none_layout = FALSE;
97
98   for (i = 0; i < 64; i++) {
99     if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
100       nchannels++;
101     }
102   }
103
104   if (channel_layout == 0) {
105     nchannels = channels;
106     none_layout = TRUE;
107   }
108
109   if (nchannels != channels) {
110     GST_ERROR ("Number of channels is different (%u != %u)", channels,
111         nchannels);
112     return NULL;
113   }
114
115   pos = g_new (GstAudioChannelPosition, nchannels);
116
117   for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) {
118     if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) {
119       pos[j++] = _ff_to_gst_layout[i].gst;
120
121       if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE) {
122         none_layout = TRUE;
123       }
124     }
125   }
126
127   if (j != nchannels) {
128     GST_WARNING ("Unknown channels in channel layout - assuming NONE layout");
129     none_layout = TRUE;
130   }
131
132   if (!none_layout && !gst_audio_check_channel_positions (pos, nchannels)) {
133     GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
134       " - assuming NONE layout", channel_layout);
135     none_layout = TRUE;
136   }
137
138   if (none_layout) {
139     if (nchannels == 1) {
140       pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
141     } else if (nchannels == 2) {
142       pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
143       pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
144     } else if (channel_layout == 0) {
145       g_free (pos);
146       pos = NULL;
147     } else {
148       for (i = 0; i < nchannels; i++) {
149         pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
150       }
151     }
152   }
153
154   if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) {
155     GST_DEBUG ("mono common case; won't set channel positions");
156     g_free (pos);
157     pos = NULL;
158   } else if (nchannels == 2 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT
159     && pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) {
160     GST_DEBUG ("stereo common case; won't set channel positions");
161     g_free (pos);
162     pos = NULL;
163   }
164
165   return pos;
166 }
167
168 GstCaps*
169 gst_maru_codectype_to_video_caps (CodecContext *ctx, const char *name,
170     gboolean encode, CodecElement *codec)
171 {
172   GstCaps *caps;
173
174   GST_DEBUG ("context: %p, codec: %s, encode: %d, pixel format: %d",
175       ctx, name, encode, ctx->video.pix_fmt);
176
177   if (ctx) {
178     caps = gst_maru_pixfmt_to_caps (ctx->video.pix_fmt, ctx, name);
179   } else {
180     GstCaps *temp;
181     enum PixelFormat i;
182     CodecContext ctx;
183
184     caps = gst_caps_new_empty ();
185     for (i = 0; i <= PIX_FMT_NB; i++) {
186       temp = gst_maru_pixfmt_to_caps (i, encode ? &ctx : NULL, name);
187       if (temp != NULL) {
188         gst_caps_append (caps, temp);
189       }
190     }
191   }
192
193   return caps;
194 }
195
196 GstCaps *
197 gst_maru_codectype_to_audio_caps (CodecContext *ctx, const char *name,
198     gboolean encode, CodecElement *codec)
199 {
200   GstCaps *caps = NULL;
201
202   GST_DEBUG ("context: %p, codec: %s, encode: %d, codec: %p",
203       ctx, name, encode, codec);
204
205   if (ctx) {
206     caps = gst_maru_smpfmt_to_caps (ctx->audio.sample_fmt, ctx, name);
207   } else if (codec && codec->sample_fmts[0] != -1){
208     GstCaps *temp;
209     int i;
210
211     caps = gst_caps_new_empty ();
212     for (i = 0; codec->sample_fmts[i] != -1; i++) {
213       temp =
214           gst_maru_smpfmt_to_caps (codec->sample_fmts[i], ctx, name);
215       if (temp != NULL) {
216         gst_caps_append (caps, temp);
217       }
218     }
219   } else {
220     GstCaps *temp;
221     int i;
222     CodecContext ctx = {{0}, {0}, 0};
223
224     ctx.audio.channels = -1;
225     caps = gst_caps_new_empty ();
226     for (i = 0; i <= SAMPLE_FMT_DBL; i++) {
227       temp = gst_maru_smpfmt_to_caps (i, encode ? &ctx : NULL, name);
228       if (temp != NULL) {
229         gst_caps_append (caps, temp);
230       }
231     }
232   }
233
234   return caps;
235 }
236
237 GstCaps*
238 gst_maru_codectype_to_caps (int media_type, CodecContext *ctx,
239     const char *name, gboolean encode)
240 {
241   GstCaps *caps;
242
243   switch (media_type) {
244   case AVMEDIA_TYPE_VIDEO:
245     caps =
246         gst_maru_codectype_to_video_caps (ctx, name, encode, NULL);
247     break;
248   case AVMEDIA_TYPE_AUDIO:
249     caps =
250         gst_maru_codectype_to_audio_caps (ctx, name, encode, NULL);
251    break;
252   default:
253     caps = NULL;
254     break;
255   }
256
257   return caps;
258 }
259
260 void
261 gst_maru_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
262 {
263   GstStructure *str;
264   const GValue *fps;
265   const GValue *par = NULL;
266
267   GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
268   g_return_if_fail (gst_caps_get_size (caps) == 1);
269   str = gst_caps_get_structure (caps, 0);
270
271   gst_structure_get_int (str, "width", &ctx->video.width);
272   gst_structure_get_int (str, "height", &ctx->video.height);
273   gst_structure_get_int (str, "bpp", &ctx->video.bpp);
274
275   fps = gst_structure_get_value (str, "framerate");
276   if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
277     ctx->video.fps_d = gst_value_get_fraction_numerator (fps);
278     ctx->video.fps_n = gst_value_get_fraction_denominator (fps);
279   ctx->video.ticks_per_frame = 1;
280
281     GST_DEBUG ("setting framerate %d/%d = %lf",
282         ctx->video.fps_d, ctx->video.fps_n,
283         1. * ctx->video.fps_d / ctx->video.fps_n);
284   }
285
286   par = gst_structure_get_value (str, "pixel-aspect-ratio");
287   if (par && GST_VALUE_HOLDS_FRACTION (par)) {
288     ctx->video.par_n = gst_value_get_fraction_numerator (par);
289     ctx->video.par_d = gst_value_get_fraction_denominator (par);
290   }
291
292   if (!raw) {
293     return;
294   }
295
296   g_return_if_fail (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
297
298   if (strcmp (gst_structure_get_name (str), "video/x-raw-yuv") == 0) {
299     guint32 fourcc;
300
301     if (gst_structure_get_fourcc (str, "format", &fourcc)) {
302     switch (fourcc) {
303       case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
304         ctx->video.pix_fmt = PIX_FMT_YUYV422;
305         break;
306       case GST_MAKE_FOURCC ('I', '4', '2', '0'):
307         ctx->video.pix_fmt = PIX_FMT_YUV420P;
308         break;
309       case GST_MAKE_FOURCC ('A', '4', '2', '0'):
310         ctx->video.pix_fmt = PIX_FMT_YUVA420P;
311         break;
312       case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
313         ctx->video.pix_fmt = PIX_FMT_YUV411P;
314         break;
315       case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
316         ctx->video.pix_fmt = PIX_FMT_YUV422P;
317         break;
318       case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
319         ctx->video.pix_fmt = PIX_FMT_YUV410P;
320         break;
321       }
322     }
323 //    printf ("get pixel format: %d, fourcc: %d\n", ctx->video.pix_fmt, fourcc);
324   } else if (strcmp (gst_structure_get_name (str), "video/x-raw-rgb") == 0) {
325     gint bpp = 0, rmask = 0, endianness = 0;
326
327     if (gst_structure_get_int (str, "bpp", &bpp) &&
328       gst_structure_get_int (str, "endianness", &endianness)) {
329       if (gst_structure_get_int (str, "red_mask", &rmask)) {
330         switch (bpp) {
331         case 32:
332 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
333           if (rmask == 0x00ff0000) {
334 #else
335           if (rmask == 0x00ff0000) {
336 #endif
337             ctx->video.pix_fmt = PIX_FMT_RGB32;
338           }
339           break;
340         case 24:
341           if (rmask == 0x0000FF) {
342             ctx->video.pix_fmt = PIX_FMT_BGR24;
343           } else {
344             ctx->video.pix_fmt = PIX_FMT_RGB24;
345           }
346           break;
347         case 16:
348           if (endianness == G_BYTE_ORDER) {
349             ctx->video.pix_fmt = PIX_FMT_RGB565;
350           }
351           break;
352         case 15:
353           if (endianness == G_BYTE_ORDER) {
354             ctx->video.pix_fmt = PIX_FMT_RGB555;
355           }
356           break;
357         default:
358           break;
359         }
360       }
361     } else {
362       if (bpp == 8) {
363         ctx->video.pix_fmt = PIX_FMT_PAL8;
364         // get palette
365       }
366     }
367   } else if (strcmp (gst_structure_get_name (str), "video/x-raw-gray") == 0) {
368     gint bpp = 0;
369
370     if (gst_structure_get_int (str, "bpp", &bpp)) {
371       switch (bpp) {
372       case 8:
373         ctx->video.pix_fmt = PIX_FMT_GRAY8;
374         break;
375       }
376     }
377   }
378 }
379
380 void
381 gst_maru_caps_to_smpfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
382 {
383   GstStructure *str;
384   gint depth = 0, width = 0, endianness = 0;
385   gboolean signedness = FALSE;
386   const gchar *name;
387
388   g_return_if_fail (gst_caps_get_size (caps) == 1);
389   str = gst_caps_get_structure (caps, 0);
390
391   gst_structure_get_int (str, "channels", &ctx->audio.channels);
392   gst_structure_get_int (str, "rate", &ctx->audio.sample_rate);
393   gst_structure_get_int (str, "block_align", &ctx->audio.block_align);
394 //  gst_structure_get_int (str, "bitrate", &ctx->audio.bit_rate);
395   gst_structure_get_int (str, "bitrate", &ctx->bit_rate);
396
397   if (!raw) {
398     return;
399   }
400
401   name = gst_structure_get_name (str);
402
403   if (!strcmp (name, "audio/x-raw-float")) {
404     if (gst_structure_get_int (str, "width", &width) &&
405       gst_structure_get_int (str, "endianness", &endianness)) {
406       if (endianness == G_BYTE_ORDER) {
407         if (width == 32) {
408           ctx->audio.sample_fmt = SAMPLE_FMT_FLT;
409         } else if (width == 64) {
410           ctx->audio.sample_fmt = SAMPLE_FMT_DBL;
411         }
412       }
413     }
414   } else {
415     if (gst_structure_get_int (str, "width", &width) &&
416       gst_structure_get_int (str, "depth", &depth) &&
417       gst_structure_get_boolean (str, "signed", &signedness) &&
418       gst_structure_get_int (str, "endianness", &endianness)) {
419       if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) {
420         if ((width == 16) && (depth == 16)) {
421           ctx->audio.sample_fmt = SAMPLE_FMT_S16;
422         } else if ((width == 32) && (depth == 32)) {
423           ctx->audio.sample_fmt = SAMPLE_FMT_S32;
424         }
425       }
426     }
427   }
428 }
429
430 void
431 gst_maru_caps_with_codecname (const char *name, int media_type,
432     const GstCaps *caps, CodecContext *ctx)
433 {
434   GstStructure *structure;
435   const GValue *value;
436   const GstBuffer *buf;
437
438   if (!ctx || !gst_caps_get_size (caps)) {
439     return;
440   }
441
442   structure = gst_caps_get_structure (caps, 0);
443
444   if ((value = gst_structure_get_value (structure, "codec_data"))) {
445     guint size;
446     guint8 *data;
447
448     buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
449     size = GST_BUFFER_SIZE (buf);
450     data = GST_BUFFER_DATA (buf);
451     GST_DEBUG ("extradata: %p, size: %d\n", data, size);
452
453     if (ctx->codecdata) {
454       g_free (ctx->codecdata);
455     }
456
457     ctx->codecdata =
458         g_malloc0 (GST_ROUND_UP_16 (size + FF_INPUT_BUFFER_PADDING_SIZE));
459     memcpy (ctx->codecdata, data, size);
460     ctx->codecdata_size = size;
461
462     if ((strcmp (name, "vc1") == 0) && size > 0 && data[0] == 0) {
463       ctx->codecdata[0] = (guint8) size;
464     }
465   } else if (ctx->codecdata == NULL) {
466     ctx->codecdata_size = 0;
467     ctx->codecdata = g_malloc0 (GST_ROUND_UP_16(FF_INPUT_BUFFER_PADDING_SIZE));
468     GST_DEBUG ("no extra data.\n");
469   }
470
471   if ((strcmp (name, "mpeg4") == 0)) {
472     const gchar *mime = gst_structure_get_name (structure);
473
474     if (!strcmp (mime, "video/x-divx")) {
475       ctx->codec_tag = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
476     } else if (!strcmp (mime, "video/x-xvid")) {
477       ctx->codec_tag = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
478     } else if (!strcmp (mime, "video/x-3ivx")) {
479       ctx->codec_tag = GST_MAKE_FOURCC ('3', 'I', 'V', '1');
480     } else if (!strcmp (mime, "video/mpeg")) {
481       ctx->codec_tag = GST_MAKE_FOURCC ('m', 'p', '4', 'v');
482     }
483 #if 0
484   } else if (strcmp (name, "h263p") == 0) {
485     gboolean val;
486
487     if (!gst_structure_get_boolean (structure, "annex-f", &val) || val) {
488       ctx->flags |= CODEC_FLAG_4MV;
489     } else {
490       ctx->flags &= ~CODEC_FLAG_4MV;
491     }
492     if ((!gst_structure_get_boolean (structure, "annex-i", &val) || val) &&
493       (!gst_structure_get_boolean (structure, "annex-t", &val) || val)) {
494       ctx->flags |= CODEC_FLAG_AC_PRED;
495     } else {
496       ctx->flags &= ~CODEC_FLAG_AC_PRED;
497     }
498     if ((!gst_structure_get_boolean (structure, "annex-j", &val) || val)) {
499       ctx->flags |= CODEC_FLAG_LOOP_FILTER;
500     } else {
501       ctx->flags &= ~CODEC_FLAG_LOOP_FILTER;
502     }
503 #endif
504   } else {
505     // TODO
506   }
507
508   if (!gst_caps_is_fixed (caps)) {
509     return;
510   }
511
512   switch (media_type) {
513   case AVMEDIA_TYPE_VIDEO:
514     gst_maru_caps_to_pixfmt (caps, ctx, FALSE);
515   // get_palette
516     break;
517   case AVMEDIA_TYPE_AUDIO:
518     gst_maru_caps_to_smpfmt (caps, ctx, FALSE);
519     break;
520   default:
521     break;
522   }
523 }
524
525 void
526 gst_maru_caps_to_codecname (const GstCaps *caps, gchar *codec_name, CodecContext *context)
527 {
528   const gchar *mimetype;
529   const GstStructure *str;
530
531   str = gst_caps_get_structure (caps, 0);
532
533   mimetype = gst_structure_get_name (str);
534
535   if (!strcmp (mimetype, "video/x-wmv")) {
536     gint wmvversion = 0;
537
538     if (gst_structure_get_int (str, "wmvversion", &wmvversion)) {
539       switch (wmvversion) {
540         case 1:
541           g_strlcpy(codec_name, "wmv1", 32);
542           break;
543         case 2:
544           g_strlcpy(codec_name, "wmv2", 32);
545           break;
546         case 3:
547         {
548           guint32 fourcc;
549
550           g_strlcpy(codec_name, "wmv3", 32);
551
552           if (gst_structure_get_fourcc (str, "format", &fourcc)) {
553             if ((fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1')) ||
554                 (fourcc == GST_MAKE_FOURCC ('W', 'M', 'V', 'A'))) {
555               g_strlcpy(codec_name, "vc1", 32);
556             }
557           }
558         }
559           break;
560       }
561     }
562   }
563
564 #if 0
565   if (context != NULL) {
566     if (video == TRUE) {
567       context->codec_type = CODEC_TYPE_VIDEO;
568     } else if (audio == TRUE) {
569       context->codec_type = CODEC_TYPE_AUDIO;
570     } else {
571       context->codec_type = CODEC_TYPE_UNKNOWN;
572     }
573     context->codec_id = id;
574     gst_maru_caps_with_codecname (name, context->codec_type, caps, context);
575   }
576 #endif
577
578   if (codec_name != NULL) {
579     GST_DEBUG ("The %s belongs to the caps %" GST_PTR_FORMAT, codec_name, caps);
580   } else {
581     GST_WARNING ("Couldn't figure out the name for caps %" GST_PTR_FORMAT, caps);
582   }
583 }
584
585 void
586 gst_maru_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx)
587 {
588   if (ctx == NULL) {
589     return;
590   }
591
592   switch (media_type) {
593   case AVMEDIA_TYPE_VIDEO:
594     gst_maru_caps_to_pixfmt (caps, ctx, TRUE);
595     break;
596   case AVMEDIA_TYPE_AUDIO:
597     gst_maru_caps_to_smpfmt (caps, ctx, TRUE);
598     break;
599   default:
600     break;
601   }
602 }
603
604 GstCaps *
605 gst_maru_video_caps_new (CodecContext *ctx, const char *name,
606         const char *mimetype, const char *fieldname, ...)
607 {
608   GstStructure *structure = NULL;
609   GstCaps *caps = NULL;
610   va_list var_args;
611   gint i;
612
613   GST_LOG ("context: %p, name: %s, mimetype: %s", ctx, name, mimetype);
614
615   if (ctx != NULL && ctx->video.width != -1) {
616     gint num, denom;
617
618     caps = gst_caps_new_simple (mimetype,
619       "width", G_TYPE_INT, ctx->video.width,
620       "height", G_TYPE_INT, ctx->video.height, NULL);
621
622     num = ctx->video.fps_d / ctx->video.ticks_per_frame;
623     denom = ctx->video.fps_n;
624
625     if (!denom) {
626       GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num);
627     }
628     if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
629       GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom);
630       num = 0;
631       denom = 1;
632     }
633     GST_LOG ("setting framerate: %d/%d", num, denom);
634     gst_caps_set_simple (caps,
635       "framerate", GST_TYPE_FRACTION, num, denom, NULL);
636   } else {
637     if (strcmp (name, "h263") == 0) {
638       /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
639        * because we want automatic negotiation to go as close to 320x240 as
640        * possible. */
641       const static gint widths[] = { 352, 704, 176, 1408, 128 };
642       const static gint heights[] = { 288, 576, 144, 1152, 96 };
643       GstCaps *temp;
644       gint n_sizes = G_N_ELEMENTS (widths);
645
646       caps = gst_caps_new_empty ();
647       for (i = 0; i < n_sizes; i++) {
648         temp = gst_caps_new_simple (mimetype,
649             "width", G_TYPE_INT, widths[i],
650             "height", G_TYPE_INT, heights[i],
651             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
652
653         gst_caps_append (caps, temp);
654       }
655     } else if (strcmp (name, "none") == 0) {
656       GST_LOG ("default caps");
657     }
658   }
659
660   /* no fixed caps or special restrictions applied;
661    * default unfixed setting */
662   if (!caps) {
663     GST_DEBUG ("Creating default caps");
664     caps = gst_caps_new_simple (mimetype,
665             "width", GST_TYPE_INT_RANGE, 16, 4096,
666             "height", GST_TYPE_INT_RANGE, 16, 4096,
667              "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
668   }
669
670   for (i = 0; i < gst_caps_get_size (caps); i++) {
671     va_start (var_args, fieldname);
672     structure = gst_caps_get_structure (caps, i);
673     gst_structure_set_valist (structure, fieldname, var_args);
674     va_end (var_args);
675   }
676
677   return caps;
678 }
679
680 GstCaps *
681 gst_maru_audio_caps_new (CodecContext *ctx, const char *name,
682         const char *mimetype, const char *fieldname, ...)
683 {
684   GstStructure *structure = NULL;
685   GstCaps *caps = NULL;
686   gint i;
687   va_list var_args;
688
689   if (ctx != NULL && ctx->audio.channels != -1) {
690     GstAudioChannelPosition *pos;
691     guint64 channel_layout = ctx->audio.channel_layout;
692
693     if (channel_layout == 0) {
694       const guint64 default_channel_set[] = {
695         0, 0, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0,
696         CH_LAYOUT_5POINT1, 0, CH_LAYOUT_7POINT1
697       };
698
699       if (strcmp (name, "ac3") == 0) {
700         if (ctx->audio.channels > 0 &&
701           ctx->audio.channels < G_N_ELEMENTS (default_channel_set)) {
702           channel_layout = default_channel_set[ctx->audio.channels - 1];
703         }
704       } else {
705         // TODO
706       }
707     }
708
709     caps = gst_caps_new_simple (mimetype,
710             "rate", G_TYPE_INT, ctx->audio.sample_rate,
711             "channels", G_TYPE_INT, ctx->audio.channels, NULL);
712
713     pos = gst_ff_channel_layout_to_gst (channel_layout, ctx->audio.channels);
714     if (pos != NULL) {
715       gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
716       g_free (pos);
717     }
718   } else {
719     gint maxchannels = 2;
720     const gint *rates = NULL;
721     gint n_rates = 0;
722
723     if (strcmp (name, "aac") == 0) {
724       maxchannels = 6;
725     } else if (g_str_has_prefix(name, "ac3")) {
726       const static gint l_rates[] = { 48000, 44100, 32000 };
727       maxchannels = 6;
728       n_rates = G_N_ELEMENTS (l_rates);
729       rates = l_rates;
730     } else {
731      // TODO
732     }
733
734     if (maxchannels == 1) {
735       caps = gst_caps_new_simple(mimetype,
736               "channels", G_TYPE_INT, maxchannels, NULL);
737     } else {
738       caps = gst_caps_new_simple(mimetype,
739               "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
740     }
741
742     if (n_rates) {
743       GValue list = { 0, };
744       GstStructure *structure;
745
746       g_value_init(&list, GST_TYPE_LIST);
747       for (i = 0; i < n_rates; i++) {
748         GValue v = { 0, };
749
750         g_value_init(&v, G_TYPE_INT);
751         g_value_set_int(&v, rates[i]);
752         gst_value_list_append_value(&list, &v);
753         g_value_unset(&v);
754       }
755       structure = gst_caps_get_structure(caps, 0);
756       gst_structure_set_value(structure, "rate", &list);
757       g_value_unset(&list);
758     } else {
759       gst_caps_set_simple(caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
760     }
761   }
762
763   for (i = 0; i < gst_caps_get_size (caps); i++) {
764     va_start (var_args, fieldname);
765     structure = gst_caps_get_structure (caps, i);
766     gst_structure_set_valist (structure, fieldname, var_args);
767     va_end (var_args);
768   }
769
770   return caps;
771 }
772
773 GstCaps *
774 gst_maru_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name)
775 {
776   GstCaps *caps = NULL;
777
778   int bpp = 0, depth = 0, endianness = 0;
779   gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
780   guint32 fmt = 0;
781
782   switch (pix_fmt) {
783   case PIX_FMT_YUV420P:
784     fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
785     break;
786   case PIX_FMT_YUYV422:
787     fmt = GST_MAKE_FOURCC ('A', '4', '2', '0');
788     break;
789   case PIX_FMT_RGB24:
790     bpp = depth = 24;
791     endianness = G_BIG_ENDIAN;
792     r_mask = 0xff0000;
793     g_mask = 0x00ff00;
794     b_mask = 0x0000ff;
795     break;
796   case PIX_FMT_BGR24:
797     bpp = depth = 24;
798     endianness = G_BIG_ENDIAN;
799     r_mask = 0x0000ff;
800     g_mask = 0x00ff00;
801     b_mask = 0xff0000;
802     break;
803   case PIX_FMT_YUV422P:
804     fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
805     break;
806   case PIX_FMT_YUV444P:
807     fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
808     break;
809   case PIX_FMT_RGB32:
810     bpp = 32;
811     depth = 32;
812     endianness = G_BIG_ENDIAN;
813 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
814     r_mask = 0x00ff0000;
815     g_mask = 0x0000ff00;
816     b_mask = 0x000000ff;
817     a_mask = 0xff000000;
818 #else
819     r_mask = 0x00ff0000;
820     g_mask = 0x0000ff00;
821     b_mask = 0x000000ff;
822     a_mask = 0xff000000;
823 #endif
824     break;
825   case PIX_FMT_YUV410P:
826     fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
827     break;
828   case PIX_FMT_YUV411P:
829     fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'b');
830     break;
831   case PIX_FMT_RGB565:
832     bpp = depth = 16;
833     endianness = G_BYTE_ORDER;
834     r_mask = 0xf800;
835     g_mask = 0x07e0;
836     b_mask = 0x001f;
837     break;
838   case PIX_FMT_RGB555:
839     bpp = 16;
840     depth = 15;
841     endianness = G_BYTE_ORDER;
842     r_mask = 0x7c00;
843     g_mask = 0x03e0;
844     b_mask = 0x001f;
845     break;
846   default:
847     break;
848   }
849
850   if (caps == NULL) {
851     if (bpp != 0) {
852       if (r_mask != 0) {
853         if (a_mask) {
854         caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
855                 "bpp", G_TYPE_INT, bpp,
856                 "depth", G_TYPE_INT, depth,
857                 "red_mask", G_TYPE_INT, r_mask,
858                 "green_mask", G_TYPE_INT, g_mask,
859                 "blue_mask", G_TYPE_INT, b_mask,
860                 "alpha_mask", G_TYPE_INT, a_mask,
861                 "endianness", G_TYPE_INT, endianness, NULL);
862         } else {
863           caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
864                   "bpp", G_TYPE_INT, bpp,
865                   "depth", G_TYPE_INT, depth,
866                   "red_mask", G_TYPE_INT, r_mask,
867                   "green_mask", G_TYPE_INT, g_mask,
868                   "blue_mask", G_TYPE_INT, b_mask,
869                   "alpha_mask", G_TYPE_INT, a_mask,
870                   "endianness", G_TYPE_INT, endianness, NULL);
871         }
872       } else {
873         caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
874                   "bpp", G_TYPE_INT, bpp,
875                   "depth", G_TYPE_INT, depth,
876                   "endianness", G_TYPE_INT, endianness, NULL);
877         if (caps && ctx) {
878           // set paletee
879         }
880       }
881     } else if (fmt) {
882       caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-yuv",
883                "format", GST_TYPE_FOURCC, fmt, NULL);
884     }
885   }
886
887   if (caps != NULL) {
888     GST_DEBUG ("caps for pix_fmt=%d: %", GST_PTR_FORMAT, pix_fmt, caps);
889   } else {
890     GST_LOG ("No caps found for pix_fmt=%d", pix_fmt);
891   }
892
893   return caps;
894 }
895
896 GstCaps *
897 gst_maru_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name)
898 {
899   GstCaps *caps = NULL;
900
901   int bpp = 0;
902   gboolean integer = TRUE;
903   gboolean signedness = FALSE;
904
905   switch (sample_fmt) {
906   case SAMPLE_FMT_S16:
907     signedness = TRUE;
908     bpp = 16;
909     break;
910   case SAMPLE_FMT_S32:
911     signedness = TRUE;
912     bpp = 32;
913     break;
914   case SAMPLE_FMT_FLT:
915     integer = FALSE;
916     bpp = 32;
917     break;
918   case SAMPLE_FMT_DBL:
919     integer = FALSE;
920     bpp = 64;
921     break;
922   default:
923     break;
924   }
925
926   if (bpp) {
927     if (integer) {
928       caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-int",
929           "signed", G_TYPE_BOOLEAN, signedness,
930           "endianness", G_TYPE_INT, G_BYTE_ORDER,
931           "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
932     } else {
933       caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-float",
934           "endianness", G_TYPE_INT, G_BYTE_ORDER,
935           "width", G_TYPE_INT, bpp, NULL);
936     }
937   }
938
939   if (caps != NULL) {
940     GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
941   } else {
942     GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
943   }
944
945   return caps;
946 }
947
948 GstCaps *
949 gst_maru_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode)
950 {
951   GstCaps *caps = NULL;
952
953   GST_LOG ("codec: %s, context: %p, encode: %d", name, ctx, encode);
954
955   if (strcmp (name, "mpegvideo") == 0) {
956     caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
957                 "mpegversion", G_TYPE_INT, 1,
958                 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
959   } else if (strcmp (name, "h263") == 0) {
960     if (encode) {
961       caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
962                   "variant", G_TYPE_STRING, "itu", NULL);
963     } else {
964       caps = gst_maru_video_caps_new (ctx, "none", "video/x-h263",
965                   "variant", G_TYPE_STRING, "itu", NULL);
966     }
967   } else if (strcmp (name, "h263p") == 0) {
968     caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
969               "variant", G_TYPE_STRING, "itu",
970               "h263version", G_TYPE_STRING, "h263p", NULL);
971 #if 0
972     if (encode && ctx) {
973       gst_caps_set_simple (caps,
974         "annex-f", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_4MV,
975         "annex-j", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_LOOP_FILTER,
976         "annex-i", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
977         "annex-t", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
978         NULL);
979     }
980 #endif
981   } else if (strcmp (name, "mpeg4") == 0) {
982     if (encode && ctx != NULL) {
983       // TODO
984     switch (ctx->codec_tag) {
985     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
986       caps = gst_maru_video_caps_new (ctx, name, "video/x-divx",
987         "divxversion", G_TYPE_INT, 5, NULL);
988       break;
989     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
990     default:
991       caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
992         "systemstream", G_TYPE_BOOLEAN, FALSE,
993         "mpegversion", G_TYPE_INT, 4, NULL);
994       break;
995     }
996     } else {
997       caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
998             "mpegversion", G_TYPE_INT, 4,
999             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1000       if (encode) {
1001         caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1002             "mpegversion", G_TYPE_INT, 4,
1003             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1004       } else {
1005         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1006             "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
1007         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1008             "video/x-xvid", NULL));
1009         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1010             "video/x-3ivx", NULL));
1011       }
1012     }
1013   } else if (strcmp (name, "h264") == 0) {
1014       caps = gst_maru_video_caps_new (ctx, name, "video/x-h264", NULL);
1015   } else if (g_str_has_prefix(name, "msmpeg4")) {
1016     // msmpeg4v1,m msmpeg4v2, msmpeg4
1017     gint version;
1018
1019     if (strcmp (name, "msmpeg4v1") == 0) {
1020       version = 41;
1021     } else if (strcmp (name, "msmpeg4v2") == 0) {
1022       version = 42;
1023     } else {
1024       version = 43;
1025     }
1026
1027     caps = gst_maru_video_caps_new (ctx, name, "video/x-msmpeg",
1028           "msmpegversion", G_TYPE_INT, version, NULL);
1029     if (!encode && !strcmp (name, "msmpeg4")) {
1030        gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1031             "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
1032     }
1033   } else if (strcmp (name, "wmv3") == 0) {
1034     caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1035                 "wmvversion", G_TYPE_INT, 3, NULL);
1036   } else if (strcmp (name, "vc1") == 0) {
1037     caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1038                 "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
1039                 GST_MAKE_FOURCC ('W', 'V', 'C', '1'),  NULL);
1040 #if 0
1041   } else if (strcmp (name, "vp3") == 0) {
1042     mime_type = g_strdup ("video/x-vp3");
1043   } else if (strcmp (name, "vp8") == 0) {
1044     mime_type = g_strdup ("video/x-vp8");
1045 #endif
1046   } else if (strcmp (name, "aac") == 0) {
1047     caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg", NULL);
1048     if (!encode) {
1049         GValue arr = { 0, };
1050         GValue item = { 0, };
1051
1052         g_value_init (&arr, GST_TYPE_LIST);
1053         g_value_init (&item, G_TYPE_INT);
1054         g_value_set_int (&item, 2);
1055         gst_value_list_append_value (&arr, &item);
1056         g_value_set_int (&item, 4);
1057         gst_value_list_append_value (&arr, &item);
1058         g_value_unset (&item);
1059
1060         gst_caps_set_value (caps, "mpegversion", &arr);
1061         g_value_unset (&arr);
1062
1063         g_value_init (&arr, GST_TYPE_LIST);
1064         g_value_init (&item, G_TYPE_STRING);
1065         g_value_set_string (&item, "raw");
1066         gst_value_list_append_value (&arr, &item);
1067         g_value_set_string (&item, "adts");
1068         gst_value_list_append_value (&arr, &item);
1069         g_value_set_string (&item, "adif");
1070         gst_value_list_append_value (&arr, &item);
1071         g_value_unset (&item);
1072
1073         gst_caps_set_value (caps, "stream-format", &arr);
1074         g_value_unset (&arr);
1075     } else {
1076       gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT, 4,
1077         "stream-format", G_TYPE_STRING, "raw",
1078         "base-profile", G_TYPE_STRING, "lc", NULL);
1079
1080         if (ctx && ctx->codecdata_size > 0) {
1081           gst_codec_utils_aac_caps_set_level_and_profile (caps,
1082             ctx->codecdata, ctx->codecdata_size);
1083         }
1084     }
1085   } else if (strcmp (name, "ac3") == 0) {
1086     caps = gst_maru_audio_caps_new (ctx, name, "audio/x-ac3", NULL);
1087   } else if (strcmp (name, "mp3") == 0) {
1088     if (encode) {
1089       caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg",
1090               "mpegversion", G_TYPE_INT, 1,
1091               "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1092     } else {
1093       caps = gst_caps_new_simple("audio/mpeg",
1094               "mpegversion", G_TYPE_INT, 1,
1095               "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1096     }
1097   } else if (strcmp (name, "mp3adu") == 0) {
1098     gchar *mime_type;
1099
1100     mime_type = g_strdup_printf ("audio/x-gst_ff-%s", name);
1101     caps = gst_maru_audio_caps_new (ctx, name, mime_type, NULL);
1102
1103     if (mime_type) {
1104       g_free(mime_type);
1105     }
1106   } else if (g_str_has_prefix(name, "wmav")) {
1107     gint version = 1;
1108     if (strcmp (name, "wmav2") == 0) {
1109       version = 2;
1110     }
1111     caps = gst_maru_audio_caps_new (ctx, name, "audio/x-wma", "wmaversion",
1112           G_TYPE_INT, version, "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
1113           "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
1114   } else {
1115     GST_ERROR("failed to new caps for %s.\n", name);
1116   }
1117
1118   return caps;
1119 }
1120
1121 typedef struct PixFmtInfo
1122 {
1123   uint8_t x_chroma_shift;       /* X chroma subsampling factor is 2 ^ shift */
1124   uint8_t y_chroma_shift;       /* Y chroma subsampling factor is 2 ^ shift */
1125 } PixFmtInfo;
1126
1127 static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
1128
1129 void
1130 gst_maru_init_pix_fmt_info (void)
1131 {
1132   pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1,
1133   pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
1134
1135   pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
1136   pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
1137
1138   pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
1139   pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
1140
1141   pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
1142   pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
1143
1144   pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
1145   pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
1146
1147   pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
1148   pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
1149
1150   /* RGB formats */
1151   pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
1152   pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
1153
1154   pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
1155   pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
1156
1157   pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
1158   pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
1159
1160   pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
1161   pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
1162
1163   pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
1164   pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
1165 }
1166
1167 int
1168 gst_maru_avpicture_size (int pix_fmt, int width, int height)
1169 {
1170   int size, w2, h2, size2;
1171   int stride, stride2;
1172   int fsize;
1173   PixFmtInfo *pinfo;
1174
1175   pinfo = &pix_fmt_info[pix_fmt];
1176
1177   switch (pix_fmt) {
1178   case PIX_FMT_YUV420P:
1179   case PIX_FMT_YUV422P:
1180   case PIX_FMT_YUV444P:
1181   case PIX_FMT_YUV410P:
1182   case PIX_FMT_YUV411P:
1183     stride = ROUND_UP_4(width);
1184     h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
1185     size = stride * h2;
1186     w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
1187     stride2 = ROUND_UP_4(w2);
1188     h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
1189     size2 = stride2 * h2;
1190     fsize = size + 2 * size2;
1191     break;
1192   case PIX_FMT_RGB24:
1193   case PIX_FMT_BGR24:
1194     stride = ROUND_UP_4 (width * 3);
1195     fsize = stride * height;
1196     break;
1197   case PIX_FMT_RGB32:
1198     stride = width * 4;
1199     fsize = stride * height;
1200     break;
1201   case PIX_FMT_RGB555:
1202   case PIX_FMT_RGB565:
1203     stride = ROUND_UP_4 (width * 2);
1204     fsize = stride * height;
1205     break;
1206   default:
1207     fsize = -1;
1208     break;
1209   }
1210
1211   return fsize;
1212 }
1213
1214 int
1215 gst_maru_align_size (int buf_size)
1216 {
1217   int i, align_size;
1218
1219   align_size = buf_size / 1024;
1220
1221   for (i = 0; i < 14; i++) {
1222     if (align_size < (1 << i)) {
1223       align_size = 1024 * (1 << i);
1224       break;
1225     }
1226   }
1227
1228   return align_size;
1229 }