91d929e8938dd3141189c3a4af77413d6c3347eb
[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 #if 1
208   } else if (codec && codec->sample_fmts[0] != -1){
209     GstCaps *temp;
210     int i;
211
212     caps = gst_caps_new_empty ();
213     for (i = 0; codec->sample_fmts[i] != -1; i++) {
214       temp =
215           gst_maru_smpfmt_to_caps (codec->sample_fmts[i], ctx, name);
216       if (temp != NULL) {
217         gst_caps_append (caps, temp);
218       }
219     }
220 #endif
221   } else {
222     GstCaps *temp;
223     int i;
224     CodecContext ctx = { 0 };
225
226     ctx.audio.channels = -1;
227     caps = gst_caps_new_empty ();
228     for (i = 0; i <= SAMPLE_FMT_DBL; i++) {
229       temp = gst_maru_smpfmt_to_caps (i, encode ? &ctx : NULL, name);
230       if (temp != NULL) {
231         gst_caps_append (caps, temp);
232       }
233     }
234   }
235
236   return caps;
237 }
238
239 GstCaps*
240 gst_maru_codectype_to_caps (int media_type, CodecContext *ctx,
241     const char *name, gboolean encode)
242 {
243   GstCaps *caps;
244
245   switch (media_type) {
246   case AVMEDIA_TYPE_VIDEO:
247     caps =
248         gst_maru_codectype_to_video_caps (ctx, name, encode, NULL);
249     break;
250   case AVMEDIA_TYPE_AUDIO:
251     caps =
252         gst_maru_codectype_to_audio_caps (ctx, name, encode, NULL);
253    break;
254   default:
255     caps = NULL;
256     break;
257   }
258
259   return caps;
260 }
261
262 void
263 gst_maru_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
264 {
265   GstStructure *str;
266   const GValue *fps;
267   const GValue *par = NULL;
268
269   GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
270   g_return_if_fail (gst_caps_get_size (caps) == 1);
271   str = gst_caps_get_structure (caps, 0);
272
273   gst_structure_get_int (str, "width", &ctx->video.width);
274   gst_structure_get_int (str, "height", &ctx->video.height);
275   gst_structure_get_int (str, "bpp", &ctx->video.bpp);
276
277   fps = gst_structure_get_value (str, "framerate");
278   if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
279     ctx->video.fps_d = gst_value_get_fraction_numerator (fps);
280     ctx->video.fps_n = gst_value_get_fraction_denominator (fps);
281   ctx->video.ticks_per_frame = 1;
282
283     GST_DEBUG ("setting framerate %d/%d = %lf",
284         ctx->video.fps_d, ctx->video.fps_n,
285         1. * ctx->video.fps_d / ctx->video.fps_n);
286   }
287
288   par = gst_structure_get_value (str, "pixel-aspect-ratio");
289   if (par && GST_VALUE_HOLDS_FRACTION (par)) {
290     ctx->video.par_n = gst_value_get_fraction_numerator (par);
291     ctx->video.par_d = gst_value_get_fraction_denominator (par);
292   }
293
294   if (!raw) {
295     return;
296   }
297
298   g_return_if_fail (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
299
300   if (strcmp (gst_structure_get_name (str), "video/x-raw-yuv") == 0) {
301     guint32 fourcc;
302
303     if (gst_structure_get_fourcc (str, "format", &fourcc)) {
304     switch (fourcc) {
305       case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
306         ctx->video.pix_fmt = PIX_FMT_YUYV422;
307         break;
308       case GST_MAKE_FOURCC ('I', '4', '2', '0'):
309         ctx->video.pix_fmt = PIX_FMT_YUV420P;
310         break;
311       case GST_MAKE_FOURCC ('A', '4', '2', '0'):
312         ctx->video.pix_fmt = PIX_FMT_YUVA420P;
313         break;
314       case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
315         ctx->video.pix_fmt = PIX_FMT_YUV411P;
316         break;
317       case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
318         ctx->video.pix_fmt = PIX_FMT_YUV422P;
319         break;
320       case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
321         ctx->video.pix_fmt = PIX_FMT_YUV410P;
322         break;
323       }
324     }
325 //    printf ("get pixel format: %d, fourcc: %d\n", ctx->video.pix_fmt, fourcc);
326   } else if (strcmp (gst_structure_get_name (str), "video/x-raw-rgb") == 0) {
327     gint bpp = 0, rmask = 0, endianness = 0;
328
329     if (gst_structure_get_int (str, "bpp", &bpp) &&
330       gst_structure_get_int (str, "endianness", &endianness)) {
331       if (gst_structure_get_int (str, "red_mask", &rmask)) {
332         switch (bpp) {
333         case 32:
334 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
335           if (rmask == 0x00ff0000) {
336 #else
337           if (rmask == 0x00ff0000) {
338 #endif
339             ctx->video.pix_fmt = PIX_FMT_RGB32;
340           }
341           break;
342         case 24:
343           if (rmask == 0x0000FF) {
344             ctx->video.pix_fmt = PIX_FMT_BGR24;
345           } else {
346             ctx->video.pix_fmt = PIX_FMT_RGB24;
347           }
348           break;
349         case 16:
350           if (endianness == G_BYTE_ORDER) {
351             ctx->video.pix_fmt = PIX_FMT_RGB565;
352           }
353           break;
354         case 15:
355           if (endianness == G_BYTE_ORDER) {
356             ctx->video.pix_fmt = PIX_FMT_RGB555;
357           }
358           break;
359         default:
360           break;
361         }
362       }
363     } else {
364       if (bpp == 8) {
365         ctx->video.pix_fmt = PIX_FMT_PAL8;
366         // get palette
367       }
368     }
369   } else if (strcmp (gst_structure_get_name (str), "video/x-raw-gray") == 0) {
370     gint bpp = 0;
371
372     if (gst_structure_get_int (str, "bpp", &bpp)) {
373       switch (bpp) {
374       case 8:
375         ctx->video.pix_fmt = PIX_FMT_GRAY8;
376         break;
377       }
378     }
379   }
380 }
381
382 void
383 gst_maru_caps_to_smpfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
384 {
385   GstStructure *str;
386   gint depth = 0, width = 0, endianness = 0;
387   gboolean signedness = FALSE;
388   const gchar *name;
389
390   g_return_if_fail (gst_caps_get_size (caps) == 1);
391   str = gst_caps_get_structure (caps, 0);
392
393   gst_structure_get_int (str, "channels", &ctx->audio.channels);
394   gst_structure_get_int (str, "rate", &ctx->audio.sample_rate);
395   gst_structure_get_int (str, "block_align", &ctx->audio.block_align);
396 //  gst_structure_get_int (str, "bitrate", &ctx->audio.bit_rate);
397   gst_structure_get_int (str, "bitrate", &ctx->bit_rate);
398
399   if (!raw) {
400     return;
401   }
402
403   name = gst_structure_get_name (str);
404
405   if (!strcmp (name, "audio/x-raw-float")) {
406     if (gst_structure_get_int (str, "width", &width) &&
407       gst_structure_get_int (str, "endianness", &endianness)) {
408       if (endianness == G_BYTE_ORDER) {
409         if (width == 32) {
410           ctx->audio.sample_fmt = SAMPLE_FMT_FLT;
411         } else if (width == 64) {
412           ctx->audio.sample_fmt = SAMPLE_FMT_DBL;
413         }
414       }
415     }
416   } else {
417     if (gst_structure_get_int (str, "width", &width) &&
418       gst_structure_get_int (str, "depth", &depth) &&
419       gst_structure_get_boolean (str, "signed", &signedness) &&
420       gst_structure_get_int (str, "endianness", &endianness)) {
421       if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) {
422         if ((width == 16) && (depth == 16)) {
423           ctx->audio.sample_fmt = SAMPLE_FMT_S16;
424         } else if ((width == 32) && (depth == 32)) {
425           ctx->audio.sample_fmt = SAMPLE_FMT_S32;
426         }
427       }
428     }
429   }
430 }
431
432 void
433 gst_maru_caps_with_codecname (const char *name, int media_type,
434     const GstCaps *caps, CodecContext *ctx)
435 {
436   GstStructure *structure;
437   const GValue *value;
438   const GstBuffer *buf;
439
440   if (!ctx || !gst_caps_get_size (caps)) {
441     return;
442   }
443
444   structure = gst_caps_get_structure (caps, 0);
445
446   if ((value = gst_structure_get_value (structure, "codec_data"))) {
447     guint size;
448     guint8 *data;
449
450     buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
451     size = GST_BUFFER_SIZE (buf);
452     data = GST_BUFFER_DATA (buf);
453     GST_DEBUG ("extradata: %p, size: %d\n", data, size);
454
455     if (ctx->codecdata) {
456       g_free (ctx->codecdata);
457     }
458
459     ctx->codecdata =
460         g_malloc0 (GST_ROUND_UP_16 (size + FF_INPUT_BUFFER_PADDING_SIZE));
461     memcpy (ctx->codecdata, data, size);
462     ctx->codecdata_size = size;
463
464     if ((strcmp (name, "vc1") == 0) && size > 0 && data[0] == 0) {
465       ctx->codecdata[0] = (guint8) size;
466     }
467   } else if (ctx->codecdata == NULL) {
468     ctx->codecdata_size = 0;
469     ctx->codecdata = g_malloc0 (GST_ROUND_UP_16(FF_INPUT_BUFFER_PADDING_SIZE));
470     GST_DEBUG ("no extra data.\n");
471   }
472
473   if ((strcmp (name, "mpeg4") == 0)) {
474     const gchar *mime = gst_structure_get_name (structure);
475
476     if (!strcmp (mime, "video/x-divx")) {
477       ctx->codec_tag = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
478     } else if (!strcmp (mime, "video/x-xvid")) {
479       ctx->codec_tag = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
480     } else if (!strcmp (mime, "video/x-3ivx")) {
481       ctx->codec_tag = GST_MAKE_FOURCC ('3', 'I', 'V', '1');
482     } else if (!strcmp (mime, "video/mpeg")) {
483       ctx->codec_tag = GST_MAKE_FOURCC ('m', 'p', '4', 'v');
484     }
485 #if 0
486   } else if (strcmp (name, "h263p") == 0) {
487     gboolean val;
488
489     if (!gst_structure_get_boolean (structure, "annex-f", &val) || val) {
490       ctx->flags |= CODEC_FLAG_4MV;
491     } else {
492       ctx->flags &= ~CODEC_FLAG_4MV;
493     }
494     if ((!gst_structure_get_boolean (structure, "annex-i", &val) || val) &&
495       (!gst_structure_get_boolean (structure, "annex-t", &val) || val)) {
496       ctx->flags |= CODEC_FLAG_AC_PRED;
497     } else {
498       ctx->flags &= ~CODEC_FLAG_AC_PRED;
499     }
500     if ((!gst_structure_get_boolean (structure, "annex-j", &val) || val)) {
501       ctx->flags |= CODEC_FLAG_LOOP_FILTER;
502     } else {
503       ctx->flags &= ~CODEC_FLAG_LOOP_FILTER;
504     }
505 #endif
506   } else {
507     // TODO
508   }
509
510   if (!gst_caps_is_fixed (caps)) {
511     return;
512   }
513
514   switch (media_type) {
515   case AVMEDIA_TYPE_VIDEO:
516     gst_maru_caps_to_pixfmt (caps, ctx, FALSE);
517   // get_palette
518     break;
519   case AVMEDIA_TYPE_AUDIO:
520     gst_maru_caps_to_smpfmt (caps, ctx, FALSE);
521     break;
522   default:
523     break;
524   }
525 }
526
527 void
528 gst_maru_caps_to_codecname (const GstCaps *caps, gchar *codec_name, CodecContext *context)
529 {
530   const gchar *mimetype;
531   const GstStructure *str;
532   gint wmvversion = 0;
533
534   str = gst_caps_get_structure (caps, 0);
535
536   mimetype = gst_structure_get_name (str);
537
538   if (!strcmp (mimetype, "video/x-wmv")) {
539     gint wmvversion = 0;
540
541     if (gst_structure_get_int (str, "wmvversion", &wmvversion)) {
542       switch (wmvversion) {
543         case 1:
544           g_strlcpy(codec_name, "wmv1", 32);
545           break;
546         case 2:
547           g_strlcpy(codec_name, "wmv2", 32);
548           break;
549         case 3:
550         {
551           guint32 fourcc;
552
553           g_strlcpy(codec_name, "wmv3", 32);
554
555           if (gst_structure_get_fourcc (str, "format", &fourcc)) {
556             if ((fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1')) ||
557                 (fourcc == GST_MAKE_FOURCC ('W', 'M', 'V', 'A'))) {
558               g_strlcpy(codec_name, "vc1", 32);
559             }
560           }
561         }
562           break;
563       }
564     }
565   }
566
567 #if 0 // check other types if it needs.
568   } else if () {
569   }
570 #endif
571
572 #if 0
573   if (context != NULL) {
574     if (video == TRUE) {
575       context->codec_type = CODEC_TYPE_VIDEO;
576     } else if (audio == TRUE) {
577       context->codec_type = CODEC_TYPE_AUDIO;
578     } else {
579       context->codec_type = CODEC_TYPE_UNKNOWN;
580     }
581     context->codec_id = id;
582     gst_maru_caps_with_codecname (name, context->codec_type, caps, context);
583   }
584 #endif
585
586   if (codec_name != NULL) {
587     GST_DEBUG ("The %s belongs to the caps %" GST_PTR_FORMAT, codec_name, caps);
588   } else {
589     GST_WARNING ("Couldn't figure out the name for caps %" GST_PTR_FORMAT, caps);
590   }
591 }
592
593 void
594 gst_maru_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx)
595 {
596   if (ctx == NULL) {
597     return;
598   }
599
600   switch (media_type) {
601   case AVMEDIA_TYPE_VIDEO:
602     gst_maru_caps_to_pixfmt (caps, ctx, TRUE);
603     break;
604   case AVMEDIA_TYPE_AUDIO:
605     gst_maru_caps_to_smpfmt (caps, ctx, TRUE);
606     break;
607   default:
608     break;
609   }
610 }
611
612 GstCaps *
613 gst_maru_video_caps_new (CodecContext *ctx, const char *name,
614         const char *mimetype, const char *fieldname, ...)
615 {
616   GstStructure *structure = NULL;
617   GstCaps *caps = NULL;
618   va_list var_args;
619   gint i;
620
621   GST_LOG ("context: %p, name: %s, mimetype: %s", ctx, name, mimetype);
622
623   if (ctx != NULL && ctx->video.width != -1) {
624     gint num, denom;
625
626     caps = gst_caps_new_simple (mimetype,
627       "width", G_TYPE_INT, ctx->video.width,
628       "height", G_TYPE_INT, ctx->video.height, NULL);
629
630     num = ctx->video.fps_d / ctx->video.ticks_per_frame;
631     denom = ctx->video.fps_n;
632
633     if (!denom) {
634       GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num);
635     }
636     if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
637       GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom);
638       num = 0;
639       denom = 1;
640     }
641     GST_LOG ("setting framerate: %d/%d", num, denom);
642     gst_caps_set_simple (caps,
643       "framerate", GST_TYPE_FRACTION, num, denom, NULL);
644   } else {
645     if (strcmp (name, "h263") == 0) {
646       /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
647        * because we want automatic negotiation to go as close to 320x240 as
648        * possible. */
649       const static gint widths[] = { 352, 704, 176, 1408, 128 };
650       const static gint heights[] = { 288, 576, 144, 1152, 96 };
651       GstCaps *temp;
652       gint n_sizes = G_N_ELEMENTS (widths);
653
654       caps = gst_caps_new_empty ();
655       for (i = 0; i < n_sizes; i++) {
656         temp = gst_caps_new_simple (mimetype,
657             "width", G_TYPE_INT, widths[i],
658             "height", G_TYPE_INT, heights[i],
659             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
660
661         gst_caps_append (caps, temp);
662       }
663     } else if (strcmp (name, "none") == 0) {
664       GST_LOG ("default caps");
665     }
666   }
667
668   /* no fixed caps or special restrictions applied;
669    * default unfixed setting */
670   if (!caps) {
671     GST_DEBUG ("Creating default caps");
672     caps = gst_caps_new_simple (mimetype,
673             "width", GST_TYPE_INT_RANGE, 16, 4096,
674             "height", GST_TYPE_INT_RANGE, 16, 4096,
675              "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
676   }
677
678   for (i = 0; i < gst_caps_get_size (caps); i++) {
679     va_start (var_args, fieldname);
680     structure = gst_caps_get_structure (caps, i);
681     gst_structure_set_valist (structure, fieldname, var_args);
682     va_end (var_args);
683   }
684
685   return caps;
686 }
687
688 GstCaps *
689 gst_maru_audio_caps_new (CodecContext *ctx, const char *name,
690         const char *mimetype, const char *fieldname, ...)
691 {
692   GstStructure *structure = NULL;
693   GstCaps *caps = NULL;
694   gint i;
695   va_list var_args;
696
697   if (ctx != NULL && ctx->audio.channels != -1) {
698     GstAudioChannelPosition *pos;
699     guint64 channel_layout = ctx->audio.channel_layout;
700
701     if (channel_layout == 0) {
702       const guint64 default_channel_set[] = {
703         0, 0, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0,
704         CH_LAYOUT_5POINT1, 0, CH_LAYOUT_7POINT1
705       };
706
707       if (strcmp (name, "ac3") == 0) {
708         if (ctx->audio.channels > 0 &&
709           ctx->audio.channels < G_N_ELEMENTS (default_channel_set)) {
710           channel_layout = default_channel_set[ctx->audio.channels - 1];
711         }
712       } else {
713         // TODO
714       }
715     }
716
717     caps = gst_caps_new_simple (mimetype,
718             "rate", G_TYPE_INT, ctx->audio.sample_rate,
719             "channels", G_TYPE_INT, ctx->audio.channels, NULL);
720
721     pos = gst_ff_channel_layout_to_gst (channel_layout, ctx->audio.channels);
722     if (pos != NULL) {
723       gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
724       g_free (pos);
725     }
726   } else {
727     gint maxchannels = 2;
728     const gint *rates = NULL;
729     gint n_rates = 0;
730
731     if (strcmp (name, "aac") == 0) {
732       maxchannels = 6;
733     } else if (g_str_has_prefix(name, "ac3")) {
734       const static gint l_rates[] = { 48000, 44100, 32000 };
735       maxchannels = 6;
736       n_rates = G_N_ELEMENTS (l_rates);
737       rates = l_rates;
738     } else {
739      // TODO
740     }
741
742     if (maxchannels == 1) {
743       caps = gst_caps_new_simple(mimetype,
744               "channels", G_TYPE_INT, maxchannels, NULL);
745     } else {
746       caps = gst_caps_new_simple(mimetype,
747               "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
748     }
749
750     if (n_rates) {
751       GValue list = { 0, };
752       GstStructure *structure;
753
754       g_value_init(&list, GST_TYPE_LIST);
755       for (i = 0; i < n_rates; i++) {
756         GValue v = { 0, };
757
758         g_value_init(&v, G_TYPE_INT);
759         g_value_set_int(&v, rates[i]);
760         gst_value_list_append_value(&list, &v);
761         g_value_unset(&v);
762       }
763       structure = gst_caps_get_structure(caps, 0);
764       gst_structure_set_value(structure, "rate", &list);
765       g_value_unset(&list);
766     } else {
767       gst_caps_set_simple(caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
768     }
769   }
770
771   for (i = 0; i < gst_caps_get_size (caps); i++) {
772     va_start (var_args, fieldname);
773     structure = gst_caps_get_structure (caps, i);
774     gst_structure_set_valist (structure, fieldname, var_args);
775     va_end (var_args);
776   }
777
778   return caps;
779 }
780
781 GstCaps *
782 gst_maru_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name)
783 {
784   GstCaps *caps = NULL;
785
786   int bpp = 0, depth = 0, endianness = 0;
787   gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
788   guint32 fmt = 0;
789
790   switch (pix_fmt) {
791   case PIX_FMT_YUV420P:
792     fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
793     break;
794   case PIX_FMT_YUYV422:
795     fmt = GST_MAKE_FOURCC ('A', '4', '2', '0');
796     break;
797   case PIX_FMT_RGB24:
798     bpp = depth = 24;
799     endianness = G_BIG_ENDIAN;
800     r_mask = 0xff0000;
801     g_mask = 0x00ff00;
802     b_mask = 0x0000ff;
803     break;
804   case PIX_FMT_BGR24:
805     bpp = depth = 24;
806     endianness = G_BIG_ENDIAN;
807     r_mask = 0x0000ff;
808     g_mask = 0x00ff00;
809     b_mask = 0xff0000;
810     break;
811   case PIX_FMT_YUV422P:
812     fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
813     break;
814   case PIX_FMT_YUV444P:
815     fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
816     break;
817   case PIX_FMT_RGB32:
818     bpp = 32;
819     depth = 32;
820     endianness = G_BIG_ENDIAN;
821 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
822     r_mask = 0x00ff0000;
823     g_mask = 0x0000ff00;
824     b_mask = 0x000000ff;
825     a_mask = 0xff000000;
826 #else
827     r_mask = 0x00ff0000;
828     g_mask = 0x0000ff00;
829     b_mask = 0x000000ff;
830     a_mask = 0xff000000;
831 #endif
832     break;
833   case PIX_FMT_YUV410P:
834     fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
835     break;
836   case PIX_FMT_YUV411P:
837     fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'b');
838     break;
839   case PIX_FMT_RGB565:
840     bpp = depth = 16;
841     endianness = G_BYTE_ORDER;
842     r_mask = 0xf800;
843     g_mask = 0x07e0;
844     b_mask = 0x001f;
845     break;
846   case PIX_FMT_RGB555:
847     bpp = 16;
848     depth = 15;
849     endianness = G_BYTE_ORDER;
850     r_mask = 0x7c00;
851     g_mask = 0x03e0;
852     b_mask = 0x001f;
853     break;
854   default:
855     break;
856   }
857
858   if (caps == NULL) {
859     if (bpp != 0) {
860       if (r_mask != 0) {
861         if (a_mask) {
862         caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
863                 "bpp", G_TYPE_INT, bpp,
864                 "depth", G_TYPE_INT, depth,
865                 "red_mask", G_TYPE_INT, r_mask,
866                 "green_mask", G_TYPE_INT, g_mask,
867                 "blue_mask", G_TYPE_INT, b_mask,
868                 "alpha_mask", G_TYPE_INT, a_mask,
869                 "endianness", G_TYPE_INT, endianness, NULL);
870         } else {
871           caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
872                   "bpp", G_TYPE_INT, bpp,
873                   "depth", G_TYPE_INT, depth,
874                   "red_mask", G_TYPE_INT, r_mask,
875                   "green_mask", G_TYPE_INT, g_mask,
876                   "blue_mask", G_TYPE_INT, b_mask,
877                   "alpha_mask", G_TYPE_INT, a_mask,
878                   "endianness", G_TYPE_INT, endianness, NULL);
879         }
880       } else {
881         caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
882                   "bpp", G_TYPE_INT, bpp,
883                   "depth", G_TYPE_INT, depth,
884                   "endianness", G_TYPE_INT, endianness, NULL);
885         if (caps && ctx) {
886           // set paletee
887         }
888       }
889     } else if (fmt) {
890       caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-yuv",
891                "format", GST_TYPE_FOURCC, fmt, NULL);
892     }
893   }
894
895   if (caps != NULL) {
896     GST_DEBUG ("caps for pix_fmt=%d: %", GST_PTR_FORMAT, pix_fmt, caps);
897   } else {
898     GST_LOG ("No caps found for pix_fmt=%d", pix_fmt);
899   }
900
901   return caps;
902 }
903
904 GstCaps *
905 gst_maru_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name)
906 {
907   GstCaps *caps = NULL;
908
909   int bpp = 0;
910   gboolean integer = TRUE;
911   gboolean signedness = FALSE;
912
913   switch (sample_fmt) {
914   case SAMPLE_FMT_S16:
915     signedness = TRUE;
916     bpp = 16;
917     break;
918   case SAMPLE_FMT_S32:
919     signedness = TRUE;
920     bpp = 32;
921     break;
922   case SAMPLE_FMT_FLT:
923     integer = FALSE;
924     bpp = 32;
925     break;
926   case SAMPLE_FMT_DBL:
927     integer = FALSE;
928     bpp = 64;
929     break;
930   default:
931     break;
932   }
933
934   if (bpp) {
935     if (integer) {
936       caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-int",
937           "signed", G_TYPE_BOOLEAN, signedness,
938           "endianness", G_TYPE_INT, G_BYTE_ORDER,
939           "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
940     } else {
941       caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-float",
942           "endianness", G_TYPE_INT, G_BYTE_ORDER,
943           "width", G_TYPE_INT, bpp, NULL);
944     }
945   }
946
947   if (caps != NULL) {
948     GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
949   } else {
950     GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
951   }
952
953   return caps;
954 }
955
956 GstCaps *
957 gst_maru_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode)
958 {
959   GstCaps *caps = NULL;
960
961   GST_LOG ("codec: %s, context: %p, encode: %d", name, ctx, encode);
962
963   if (strcmp (name, "mpegvideo") == 0) {
964     caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
965                 "mpegversion", G_TYPE_INT, 1,
966                 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
967   } else if (strcmp (name, "h263") == 0) {
968     if (encode) {
969       caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
970                   "variant", G_TYPE_STRING, "itu", NULL);
971     } else {
972       caps = gst_maru_video_caps_new (ctx, "none", "video/x-h263",
973                   "variant", G_TYPE_STRING, "itu", NULL);
974     }
975   } else if (strcmp (name, "h263p") == 0) {
976     caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
977               "variant", G_TYPE_STRING, "itu",
978               "h263version", G_TYPE_STRING, "h263p", NULL);
979 #if 0
980     if (encode && ctx) {
981       gst_caps_set_simple (caps,
982         "annex-f", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_4MV,
983         "annex-j", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_LOOP_FILTER,
984         "annex-i", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
985         "annex-t", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
986         NULL);
987     }
988 #endif
989   } else if (strcmp (name, "mpeg4") == 0) {
990     if (encode && ctx != NULL) {
991       // TODO
992     switch (ctx->codec_tag) {
993     case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
994       caps = gst_maru_video_caps_new (ctx, name, "video/x-divx",
995         "divxversion", G_TYPE_INT, 5, NULL);
996       break;
997     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
998     default:
999       caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1000         "systemstream", G_TYPE_BOOLEAN, FALSE,
1001         "mpegversion", G_TYPE_INT, 4, NULL);
1002       break;
1003     }
1004     } else {
1005       caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1006             "mpegversion", G_TYPE_INT, 4,
1007             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1008       if (encode) {
1009         caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1010             "mpegversion", G_TYPE_INT, 4,
1011             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1012       } else {
1013         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1014             "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
1015         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1016             "video/x-xvid", NULL));
1017         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1018             "video/x-3ivx", NULL));
1019       }
1020     }
1021   } else if (strcmp (name, "h264") == 0) {
1022       caps = gst_maru_video_caps_new (ctx, name, "video/x-h264", NULL);
1023   } else if (g_str_has_prefix(name, "msmpeg4")) {
1024     // msmpeg4v1,m msmpeg4v2, msmpeg4
1025     gint version;
1026
1027     if (strcmp (name, "msmpeg4v1") == 0) {
1028       version = 41;
1029     } else if (strcmp (name, "msmpeg4v2") == 0) {
1030       version = 42;
1031     } else {
1032       version = 43;
1033     }
1034
1035     caps = gst_maru_video_caps_new (ctx, name, "video/x-msmpeg",
1036           "msmpegversion", G_TYPE_INT, version, NULL);
1037     if (!encode && !strcmp (name, "msmpeg4")) {
1038        gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1039             "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
1040     }
1041   } else if (strcmp (name, "wmv3") == 0) {
1042     caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1043                 "wmvversion", G_TYPE_INT, 3, NULL);
1044   } else if (strcmp (name, "vc1") == 0) {
1045     caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1046                 "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
1047                 GST_MAKE_FOURCC ('W', 'V', 'C', '1'),  NULL);
1048 #if 0
1049   } else if (strcmp (name, "vp3") == 0) {
1050     mime_type = g_strdup ("video/x-vp3");
1051   } else if (strcmp (name, "vp8") == 0) {
1052     mime_type = g_strdup ("video/x-vp8");
1053 #endif
1054   } else if (strcmp (name, "aac") == 0) {
1055     caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg", NULL);
1056     if (!encode) {
1057         GValue arr = { 0, };
1058         GValue item = { 0, };
1059
1060         g_value_init (&arr, GST_TYPE_LIST);
1061         g_value_init (&item, G_TYPE_INT);
1062         g_value_set_int (&item, 2);
1063         gst_value_list_append_value (&arr, &item);
1064         g_value_set_int (&item, 4);
1065         gst_value_list_append_value (&arr, &item);
1066         g_value_unset (&item);
1067
1068         gst_caps_set_value (caps, "mpegversion", &arr);
1069         g_value_unset (&arr);
1070
1071         g_value_init (&arr, GST_TYPE_LIST);
1072         g_value_init (&item, G_TYPE_STRING);
1073         g_value_set_string (&item, "raw");
1074         gst_value_list_append_value (&arr, &item);
1075         g_value_set_string (&item, "adts");
1076         gst_value_list_append_value (&arr, &item);
1077         g_value_set_string (&item, "adif");
1078         gst_value_list_append_value (&arr, &item);
1079         g_value_unset (&item);
1080
1081         gst_caps_set_value (caps, "stream-format", &arr);
1082         g_value_unset (&arr);
1083     } else {
1084       gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT, 4,
1085         "stream-format", G_TYPE_STRING, "raw",
1086         "base-profile", G_TYPE_STRING, "lc", NULL);
1087
1088         if (ctx && ctx->codecdata_size > 0) {
1089           gst_codec_utils_aac_caps_set_level_and_profile (caps,
1090             ctx->codecdata, ctx->codecdata_size);
1091         }
1092     }
1093   } else if (strcmp (name, "ac3") == 0) {
1094     caps = gst_maru_audio_caps_new (ctx, name, "audio/x-ac3", NULL);
1095   } else if (strcmp (name, "mp3") == 0) {
1096     if (encode) {
1097       caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg",
1098               "mpegversion", G_TYPE_INT, 1,
1099               "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1100     } else {
1101       caps = gst_caps_new_simple("audio/mpeg",
1102               "mpegversion", G_TYPE_INT, 1,
1103               "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1104     }
1105   } else if (strcmp (name, "mp3adu") == 0) {
1106     gchar *mime_type;
1107
1108     mime_type = g_strdup_printf ("audio/x-gst_ff-%s", name);
1109     caps = gst_maru_audio_caps_new (ctx, name, mime_type, NULL);
1110
1111     if (mime_type) {
1112       g_free(mime_type);
1113     }
1114   } else if (g_str_has_prefix(name, "wmav")) {
1115     gint version = 1;
1116     if (strcmp (name, "wmav2") == 0) {
1117       version = 2;
1118     }
1119     caps = gst_maru_audio_caps_new (ctx, name, "audio/x-wma", "wmaversion",
1120           G_TYPE_INT, version, "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
1121           "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
1122   } else {
1123     GST_ERROR("failed to new caps for %s.\n", name);
1124   }
1125
1126   return caps;
1127 }
1128
1129 typedef struct PixFmtInfo
1130 {
1131   uint8_t x_chroma_shift;       /* X chroma subsampling factor is 2 ^ shift */
1132   uint8_t y_chroma_shift;       /* Y chroma subsampling factor is 2 ^ shift */
1133 } PixFmtInfo;
1134
1135 static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
1136
1137 void
1138 gst_maru_init_pix_fmt_info (void)
1139 {
1140   pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1,
1141   pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
1142
1143   pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
1144   pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
1145
1146   pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
1147   pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
1148
1149   pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
1150   pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
1151
1152   pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
1153   pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
1154
1155   pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
1156   pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
1157
1158   /* RGB formats */
1159   pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
1160   pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
1161
1162   pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
1163   pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
1164
1165   pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
1166   pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
1167
1168   pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
1169   pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
1170
1171   pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
1172   pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
1173 }
1174
1175 int
1176 gst_maru_avpicture_size (int pix_fmt, int width, int height)
1177 {
1178   int size, w2, h2, size2;
1179   int stride, stride2;
1180   int fsize;
1181   PixFmtInfo *pinfo;
1182
1183   pinfo = &pix_fmt_info[pix_fmt];
1184
1185   switch (pix_fmt) {
1186   case PIX_FMT_YUV420P:
1187   case PIX_FMT_YUV422P:
1188   case PIX_FMT_YUV444P:
1189   case PIX_FMT_YUV410P:
1190   case PIX_FMT_YUV411P:
1191     stride = ROUND_UP_4(width);
1192     h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
1193     size = stride * h2;
1194     w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
1195     stride2 = ROUND_UP_4(w2);
1196     h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
1197     size2 = stride2 * h2;
1198     fsize = size + 2 * size2;
1199     break;
1200   case PIX_FMT_RGB24:
1201   case PIX_FMT_BGR24:
1202     stride = ROUND_UP_4 (width * 3);
1203     fsize = stride * height;
1204     break;
1205   case PIX_FMT_RGB32:
1206     stride = width * 4;
1207     fsize = stride * height;
1208     break;
1209   case PIX_FMT_RGB555:
1210   case PIX_FMT_RGB565:
1211     stride = ROUND_UP_4 (width * 2);
1212     fsize = stride * height;
1213     break;
1214   default:
1215     fsize = -1;
1216     break;
1217   }
1218
1219   return fsize;
1220 }
1221
1222 int
1223 gst_maru_align_size (int buf_size)
1224 {
1225   int i, align_size;
1226
1227   align_size = buf_size / 1024;
1228
1229   for (i = 0; i < 14; i++) {
1230     if (align_size < (1 << i)) {
1231       align_size = 1024 * (1 << i);
1232       break;
1233     }
1234   }
1235
1236   return align_size;
1237 }