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