2081b49515b709ffdcd1dbd76b0215e6dfe118c2
[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/audio-channels.h>
23 #include <gst/pbutils/codec-utils.h>
24
25 typedef struct
26 {
27   GstVideoFormat format;
28   enum PixelFormat pixfmt;
29 } PixToFmt;
30
31 /* FIXME : FILLME */
32 static const PixToFmt pixtofmttable[] = {
33   /* GST_VIDEO_FORMAT_I420, */
34   {GST_VIDEO_FORMAT_I420, PIX_FMT_YUV420P},
35   /* Note : this should use a different chroma placement */
36   {GST_VIDEO_FORMAT_I420, PIX_FMT_YUVJ420P},
37
38   /* GST_VIDEO_FORMAT_YV12, */
39   /* GST_VIDEO_FORMAT_YUY2, */
40   {GST_VIDEO_FORMAT_YUY2, PIX_FMT_YUYV422},
41   /* GST_VIDEO_FORMAT_UYVY, */
42   {GST_VIDEO_FORMAT_UYVY, PIX_FMT_UYVY422},
43   /* GST_VIDEO_FORMAT_AYUV, */
44   /* GST_VIDEO_FORMAT_RGBx, */
45   /* GST_VIDEO_FORMAT_BGRx, */
46   /* GST_VIDEO_FORMAT_xRGB, */
47   /* GST_VIDEO_FORMAT_xBGR, */
48   /* GST_VIDEO_FORMAT_RGBA, */
49   {GST_VIDEO_FORMAT_RGBA, PIX_FMT_RGBA},
50   /* GST_VIDEO_FORMAT_BGRA, */
51   {GST_VIDEO_FORMAT_BGRA, PIX_FMT_BGRA},
52   /* GST_VIDEO_FORMAT_ARGB, */
53   {GST_VIDEO_FORMAT_ARGB, PIX_FMT_ARGB},
54   /* GST_VIDEO_FORMAT_ABGR, */
55   {GST_VIDEO_FORMAT_ABGR, PIX_FMT_ABGR},
56   /* GST_VIDEO_FORMAT_RGB, */
57   {GST_VIDEO_FORMAT_RGB, PIX_FMT_RGB24},
58   /* GST_VIDEO_FORMAT_BGR, */
59   {GST_VIDEO_FORMAT_BGR, PIX_FMT_BGR24},
60   /* GST_VIDEO_FORMAT_Y41B, */
61   {GST_VIDEO_FORMAT_Y41B, PIX_FMT_YUV411P},
62   /* GST_VIDEO_FORMAT_Y42B, */
63   {GST_VIDEO_FORMAT_Y42B, PIX_FMT_YUV422P},
64   {GST_VIDEO_FORMAT_Y42B, PIX_FMT_YUVJ422P},
65   /* GST_VIDEO_FORMAT_YVYU, */
66   /* GST_VIDEO_FORMAT_Y444, */
67   {GST_VIDEO_FORMAT_Y444, PIX_FMT_YUV444P},
68   {GST_VIDEO_FORMAT_Y444, PIX_FMT_YUVJ444P},
69   /* GST_VIDEO_FORMAT_v210, */
70   /* GST_VIDEO_FORMAT_v216, */
71   /* GST_VIDEO_FORMAT_NV12, */
72   {GST_VIDEO_FORMAT_NV12, PIX_FMT_NV12},
73   /* GST_VIDEO_FORMAT_NV21, */
74   {GST_VIDEO_FORMAT_NV21, PIX_FMT_NV21},
75   /* GST_VIDEO_FORMAT_GRAY8, */
76   {GST_VIDEO_FORMAT_GRAY8, PIX_FMT_GRAY8},
77   /* GST_VIDEO_FORMAT_GRAY16_BE, */
78   {GST_VIDEO_FORMAT_GRAY16_BE, PIX_FMT_GRAY16BE},
79   /* GST_VIDEO_FORMAT_GRAY16_LE, */
80   {GST_VIDEO_FORMAT_GRAY16_LE, PIX_FMT_GRAY16LE},
81   /* GST_VIDEO_FORMAT_v308, */
82   /* GST_VIDEO_FORMAT_Y800, */
83   /* GST_VIDEO_FORMAT_Y16, */
84   /* GST_VIDEO_FORMAT_RGB16, */
85   {GST_VIDEO_FORMAT_RGB16, PIX_FMT_RGB565},
86   /* GST_VIDEO_FORMAT_BGR16, */
87   /* GST_VIDEO_FORMAT_RGB15, */
88   {GST_VIDEO_FORMAT_RGB15, PIX_FMT_RGB555},
89   /* GST_VIDEO_FORMAT_BGR15, */
90   /* GST_VIDEO_FORMAT_UYVP, */
91   /* GST_VIDEO_FORMAT_A420, */
92   {GST_VIDEO_FORMAT_A420, PIX_FMT_YUVA420P},
93   /* GST_VIDEO_FORMAT_RGB8_PALETTED, */
94   {GST_VIDEO_FORMAT_RGB8P, PIX_FMT_PAL8},
95   /* GST_VIDEO_FORMAT_YUV9, */
96   {GST_VIDEO_FORMAT_YUV9, PIX_FMT_YUV410P},
97   /* GST_VIDEO_FORMAT_YVU9, */
98   /* GST_VIDEO_FORMAT_IYU1, */
99   /* GST_VIDEO_FORMAT_ARGB64, */
100   /* GST_VIDEO_FORMAT_AYUV64, */
101   /* GST_VIDEO_FORMAT_r210, */
102   {GST_VIDEO_FORMAT_I420_10LE, PIX_FMT_YUV420P10LE},
103   {GST_VIDEO_FORMAT_I420_10BE, PIX_FMT_YUV420P10BE},
104   {GST_VIDEO_FORMAT_I422_10LE, PIX_FMT_YUV422P10LE},
105   {GST_VIDEO_FORMAT_I422_10BE, PIX_FMT_YUV422P10BE},
106   {GST_VIDEO_FORMAT_Y444_10LE, PIX_FMT_YUV444P10LE},
107   {GST_VIDEO_FORMAT_Y444_10BE, PIX_FMT_YUV444P10BE},
108 };
109
110 gint
111 gst_maru_smpfmt_depth (int32_t smp_fmt)
112 {
113   GST_DEBUG (" >> ENTER ");
114   gint depth = -1;
115
116   switch (smp_fmt) {
117   case SAMPLE_FMT_U8:
118   case SAMPLE_FMT_U8P:
119     depth = 1;
120     break;
121   case SAMPLE_FMT_S16:
122   case SAMPLE_FMT_S16P:
123     depth = 2;
124     break;
125   case SAMPLE_FMT_S32:
126   case SAMPLE_FMT_FLT:
127   case SAMPLE_FMT_S32P:
128   case SAMPLE_FMT_FLTP:
129     depth = 4;
130     break;
131   case SAMPLE_FMT_DBL:
132   case SAMPLE_FMT_DBLP:
133     depth = 8;
134     break;
135   default:
136     GST_ERROR ("Unhandled sample format !");
137     break;
138   }
139
140   return depth;
141 }
142
143 // FFmpeg
144 static const struct
145 {
146   guint64 ff;
147   GstAudioChannelPosition gst;
148 } _ff_to_gst_layout[] = {
149   {
150   CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
151   CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
152   CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
153   CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE1}, {
154   CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
155   CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
156   CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
157   CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
158   CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
159   CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
160   CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
161   CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
162   CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
163   CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
164   CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
165   CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
166   CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
167   CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
168   CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
169   CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
170 };
171
172 static guint64
173 gst_ffmpeg_channel_positions_to_layout (GstAudioChannelPosition * pos,
174     gint channels)
175 {
176   gint i, j;
177   guint64 ret = 0;
178   gint channels_found = 0;
179
180   if (!pos)
181     return 0;
182
183   for (i = 0; i < channels; i++) {
184     for (j = 0; j < G_N_ELEMENTS (_ff_to_gst_layout); j++) {
185       if (_ff_to_gst_layout[j].gst == pos[i]) {
186         ret |= _ff_to_gst_layout[j].ff;
187         channels_found++;
188         break;
189       }
190     }
191   }
192
193   if (channels_found != channels)
194     return 0;
195   return ret;
196 }
197
198 gboolean
199 gst_ffmpeg_channel_layout_to_gst (guint64 channel_layout, gint channels,
200     GstAudioChannelPosition * pos)
201 {
202   guint nchannels = 0;
203   gboolean none_layout = FALSE;
204
205   if (channel_layout == 0) {
206     nchannels = channels;
207     none_layout = TRUE;
208   } else {
209     guint i, j;
210
211     for (i = 0; i < 64; i++) {
212       if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
213         nchannels++;
214       }
215     }
216
217     if (nchannels != channels) {
218       GST_ERROR ("Number of channels is different (%u != %u)", channels,
219           nchannels);
220       nchannels = channels;
221       none_layout = TRUE;
222     } else {
223
224       for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) {
225         if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) {
226           pos[j++] = _ff_to_gst_layout[i].gst;
227
228           if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE)
229             none_layout = TRUE;
230         }
231       }
232
233       if (j != nchannels) {
234         GST_WARNING
235             ("Unknown channels in channel layout - assuming NONE layout");
236         none_layout = TRUE;
237       }
238     }
239   }
240
241   if (!none_layout
242       && !gst_audio_check_valid_channel_positions (pos, nchannels, FALSE)) {
243     GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
244         " - assuming NONE layout", channel_layout);
245     none_layout = TRUE;
246   }
247
248   if (none_layout) {
249     if (nchannels == 1) {
250       pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
251     } else if (nchannels == 2) {
252       pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
253       pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
254     } else {
255       guint i;
256
257       for (i = 0; i < nchannels; i++)
258         pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
259     }
260   }
261
262   return TRUE;
263 }
264
265 static gboolean
266 _gst_value_list_contains (const GValue * list, const GValue * value)
267 {
268   guint i, n;
269   const GValue *tmp;
270
271   n = gst_value_list_get_size (list);
272   for (i = 0; i < n; i++) {
273     tmp = gst_value_list_get_value (list, i);
274     if (gst_value_compare (value, tmp) == GST_VALUE_EQUAL)
275       return TRUE;
276   }
277
278   return FALSE;
279 }
280
281 static void
282 gst_maru_video_set_pix_fmts (GstCaps * caps, const int32_t *fmts)
283 {
284   GValue va = { 0, };
285   GValue v = { 0, };
286   GstVideoFormat format;
287     gint i;
288
289   if (!fmts || fmts[0] == -1) {
290
291     g_value_init (&va, GST_TYPE_LIST);
292     g_value_init (&v, G_TYPE_STRING);
293     for (i = 0; i <= PIX_FMT_NB; i++) {
294       format = gst_maru_pixfmt_to_videoformat (i);
295       if (format == GST_VIDEO_FORMAT_UNKNOWN)
296         continue;
297       g_value_set_string (&v, gst_video_format_to_string (format));
298       gst_value_list_append_value (&va, &v);
299     }
300     gst_caps_set_value (caps, "format", &va);
301     g_value_unset (&v);
302     g_value_unset (&va);
303     return;
304   }
305
306   /* Only a single format */
307   g_value_init (&va, GST_TYPE_LIST);
308   g_value_init (&v, G_TYPE_STRING);
309   i = 0;
310   while (i < 4) {
311     format = gst_maru_pixfmt_to_videoformat (fmts[i]);
312     if (format != GST_VIDEO_FORMAT_UNKNOWN) {
313       g_value_set_string (&v, gst_video_format_to_string (format));
314       /* Only append values we don't have yet */
315       if (!_gst_value_list_contains (&va, &v))
316         gst_value_list_append_value (&va, &v);
317     }
318     i++;
319   }
320   if (gst_value_list_get_size (&va) == 1) {
321     /* The single value is still in v */
322     gst_caps_set_value (caps, "format", &v);
323   } else if (gst_value_list_get_size (&va) > 1) {
324     gst_caps_set_value (caps, "format", &va);
325   }
326   g_value_unset (&v);
327   g_value_unset (&va);
328 }
329
330 static gboolean
331 caps_has_field (GstCaps * caps, const gchar * field)
332 {
333   guint i, n;
334
335   n = gst_caps_get_size (caps);
336   for (i = 0; i < n; i++) {
337     GstStructure *s = gst_caps_get_structure (caps, i);
338
339     if (gst_structure_has_field (s, field))
340       return TRUE;
341   }
342
343   return FALSE;
344 }
345
346 GstCaps*
347 gst_maru_codectype_to_video_caps (CodecContext *ctx, const char *name,
348     gboolean encode, CodecElement *codec)
349 {
350   GST_DEBUG (" >> ENTER ");
351   GstCaps *caps;
352
353   if (ctx) {
354     GST_DEBUG ("context: %p, codec: %s, encode: %d, pixel format: %d",
355         ctx, name, encode, ctx->video.pix_fmt);
356   } else {
357     GST_DEBUG ("context: %p, codec: %s, encode: %d",
358         ctx, name, encode);
359   }
360
361   if (ctx) {
362     caps = gst_maru_pixfmt_to_caps (ctx->video.pix_fmt, ctx, name);
363   } else {
364     caps =
365         gst_maru_video_caps_new (ctx, name, "video/x-raw", NULL);
366     if (!caps_has_field (caps, "format"))
367       gst_maru_video_set_pix_fmts (caps, codec ? codec->pix_fmts : NULL);
368   }
369
370   return caps;
371 }
372
373 GstCaps *
374 gst_maru_codectype_to_audio_caps (CodecContext *ctx, const char *name,
375     gboolean encode, CodecElement *codec)
376 {
377   GST_DEBUG (" >> ENTER ");
378   GstCaps *caps = NULL;
379
380   GST_DEBUG ("context: %p, codec: %s, encode: %d, codec: %p",
381             ctx, name, encode, codec);
382
383   if (ctx) {
384     caps = gst_maru_smpfmt_to_caps (ctx->audio.sample_fmt, ctx, name);
385   } else if (codec && codec->sample_fmts[0] != -1){
386     GstCaps *temp;
387     int i;
388
389     caps = gst_caps_new_empty ();
390     for (i = 0; codec->sample_fmts[i] != -1; i++) {
391       int8_t sample_fmt = -1;
392
393       sample_fmt = codec->sample_fmts[i];
394       if (!strcmp(name, "aac") && encode) {
395         sample_fmt = SAMPLE_FMT_S16;
396         GST_DEBUG ("convert sample_fmt. codec %s, encode %d, sample_fmt %d",
397                   name, encode, sample_fmt);
398       }
399
400       temp =
401           gst_maru_smpfmt_to_caps (sample_fmt, ctx, name);
402       if (temp != NULL) {
403         gst_caps_append (caps, temp);
404       }
405     }
406   } else {
407     GstCaps *temp;
408     int i;
409     CodecContext ctx = {{0}, {0}, 0};
410
411     ctx.audio.channels = -1;
412     caps = gst_caps_new_empty ();
413     for (i = 0; i <= SAMPLE_FMT_DBL; i++) {
414       temp = gst_maru_smpfmt_to_caps (i, encode ? &ctx : NULL, name);
415       if (temp != NULL) {
416         gst_caps_append (caps, temp);
417       }
418     }
419   }
420
421   return caps;
422 }
423
424 GstCaps*
425 gst_maru_codectype_to_caps (int media_type, CodecContext *ctx,
426     const char *name, gboolean encode)
427 {
428   GST_DEBUG (" >> ENTER ");
429   GstCaps *caps;
430
431   switch (media_type) {
432   case AVMEDIA_TYPE_VIDEO:
433     caps =
434         gst_maru_codectype_to_video_caps (ctx, name, encode, NULL);
435     break;
436   case AVMEDIA_TYPE_AUDIO:
437     caps =
438         gst_maru_codectype_to_audio_caps (ctx, name, encode, NULL);
439    break;
440   default:
441     caps = NULL;
442     break;
443   }
444
445   return caps;
446 }
447
448 void
449 gst_maru_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
450 {
451   GST_DEBUG (" >> ENTER ");
452   GstStructure *str;
453   const GValue *fps;
454   const GValue *par = NULL;
455
456   GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
457   g_return_if_fail (gst_caps_get_size (caps) == 1);
458   str = gst_caps_get_structure (caps, 0);
459
460   gst_structure_get_int (str, "width", &ctx->video.width);
461   gst_structure_get_int (str, "height", &ctx->video.height);
462   gst_structure_get_int (str, "bpp", &ctx->video.bpp);
463
464   fps = gst_structure_get_value (str, "framerate");
465   if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
466     ctx->video.fps_d = gst_value_get_fraction_numerator (fps);
467     ctx->video.fps_n = gst_value_get_fraction_denominator (fps);
468     ctx->video.ticks_per_frame = 1;
469
470     GST_DEBUG ("setting framerate %d/%d = %lf",
471         ctx->video.fps_d, ctx->video.fps_n,
472         1. * ctx->video.fps_d / ctx->video.fps_n);
473   }
474
475   par = gst_structure_get_value (str, "pixel-aspect-ratio");
476   if (par && GST_VALUE_HOLDS_FRACTION (par)) {
477     ctx->video.par_n = gst_value_get_fraction_numerator (par);
478     ctx->video.par_d = gst_value_get_fraction_denominator (par);
479   }
480
481   if (!raw) {
482     return;
483   }
484
485   g_return_if_fail (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
486
487   if (strcmp (gst_structure_get_name (str), "video/x-raw-yuv") == 0) {
488     const gchar *format;
489
490     if ((format = gst_structure_get_string (str, "format"))) {
491         if (g_str_equal (format, "YUY2"))
492           ctx->video.pix_fmt = PIX_FMT_YUYV422;
493         else if (g_str_equal (format, "I420"))
494           ctx->video.pix_fmt = PIX_FMT_YUV420P;
495         else if (g_str_equal (format, "A420"))
496           ctx->video.pix_fmt = PIX_FMT_YUVA420P;
497         else if (g_str_equal (format, "Y41B"))
498           ctx->video.pix_fmt = PIX_FMT_YUV411P;
499         else if (g_str_equal (format, "Y42B"))
500           ctx->video.pix_fmt = PIX_FMT_YUV422P;
501         else if (g_str_equal (format, "YUV9"))
502           ctx->video.pix_fmt = PIX_FMT_YUV410P;
503         else {
504           GST_WARNING ("couldn't convert format %s" " to a pixel format",
505               format);
506         }
507     }
508   } else if (strcmp (gst_structure_get_name (str), "video/x-raw-rgb") == 0) {
509     gint bpp = 0, rmask = 0, endianness = 0;
510
511     if (gst_structure_get_int (str, "bpp", &bpp) &&
512       gst_structure_get_int (str, "endianness", &endianness)) {
513       if (gst_structure_get_int (str, "red_mask", &rmask)) {
514         switch (bpp) {
515         case 32:
516 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
517           if (rmask == 0x00ff0000) {
518 #else
519           if (rmask == 0x00ff0000) {
520 #endif
521             ctx->video.pix_fmt = PIX_FMT_RGB32;
522           }
523           break;
524         case 24:
525           if (rmask == 0x0000FF) {
526             ctx->video.pix_fmt = PIX_FMT_BGR24;
527           } else {
528             ctx->video.pix_fmt = PIX_FMT_RGB24;
529           }
530           break;
531         case 16:
532           if (endianness == G_BYTE_ORDER) {
533             ctx->video.pix_fmt = PIX_FMT_RGB565;
534           }
535           break;
536         case 15:
537           if (endianness == G_BYTE_ORDER) {
538             ctx->video.pix_fmt = PIX_FMT_RGB555;
539           }
540           break;
541         default:
542           break;
543         }
544       }
545     } else {
546       if (bpp == 8) {
547         ctx->video.pix_fmt = PIX_FMT_PAL8;
548         // get palette
549       }
550     }
551   } else if (strcmp (gst_structure_get_name (str), "video/x-raw-gray") == 0) {
552     gint bpp = 0;
553
554     if (gst_structure_get_int (str, "bpp", &bpp)) {
555       switch (bpp) {
556       case 8:
557         ctx->video.pix_fmt = PIX_FMT_GRAY8;
558         break;
559       }
560     }
561   }
562 }
563
564 void
565 gst_maru_caps_to_smpfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
566 {
567   GST_DEBUG (" >> ENTER ");
568   GstStructure *str;
569   gint depth = 0, width = 0, endianness = 0;
570   gboolean signedness = FALSE;
571   const gchar *name;
572
573   g_return_if_fail (gst_caps_get_size (caps) == 1);
574   str = gst_caps_get_structure (caps, 0);
575
576   gst_structure_get_int (str, "channels", &ctx->audio.channels);
577   gst_structure_get_int (str, "rate", &ctx->audio.sample_rate);
578   gst_structure_get_int (str, "block_align", &ctx->audio.block_align);
579   gst_structure_get_int (str, "bitrate", &ctx->bit_rate);
580
581   if (!raw) {
582     return;
583   }
584
585   name = gst_structure_get_name (str);
586   if (!name) {
587     GST_ERROR ("Couldn't get audio sample format from caps %" GST_PTR_FORMAT, caps);
588     return;
589   }
590
591   if (!strcmp (name, "audio/x-raw-float")) {
592     if (gst_structure_get_int (str, "width", &width) &&
593       gst_structure_get_int (str, "endianness", &endianness)) {
594       if (endianness == G_BYTE_ORDER) {
595         if (width == 32) {
596           ctx->audio.sample_fmt = SAMPLE_FMT_FLT;
597         } else if (width == 64) {
598           ctx->audio.sample_fmt = SAMPLE_FMT_DBL;
599         }
600       }
601     }
602   } else {
603     if (gst_structure_get_int (str, "width", &width) &&
604       gst_structure_get_int (str, "depth", &depth) &&
605       gst_structure_get_boolean (str, "signed", &signedness) &&
606       gst_structure_get_int (str, "endianness", &endianness)) {
607       if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) {
608         if ((width == 16) && (depth == 16)) {
609           ctx->audio.sample_fmt = SAMPLE_FMT_S16;
610         } else if ((width == 32) && (depth == 32)) {
611           ctx->audio.sample_fmt = SAMPLE_FMT_S32;
612         }
613       }
614     }
615   }
616 }
617
618 void
619 gst_maru_caps_with_codecname (const char *name, int media_type,
620     const GstCaps *caps, CodecContext *ctx)
621 {
622   GST_DEBUG (" >> ENTER ");
623   GstStructure *structure;
624   const GValue *value;
625   GstBuffer *buf;
626
627   if (!ctx || !gst_caps_get_size (caps)) {
628     return;
629   }
630
631   structure = gst_caps_get_structure (caps, 0);
632
633   if ((value = gst_structure_get_value (structure, "codec_data"))) {
634     GstMapInfo mapinfo;
635     guint size;
636     guint8 *data;
637
638     buf = (GstBuffer *) gst_value_get_buffer (value);
639     gst_buffer_map (buf, &mapinfo, GST_MAP_READ);
640     size = mapinfo.size;
641     data = mapinfo.data;
642     gst_buffer_unmap (buf, &mapinfo);
643     GST_DEBUG ("extradata: %p, size: %d", data, size);
644
645     if (ctx->codecdata) {
646       g_free (ctx->codecdata);
647     }
648
649     ctx->codecdata =
650         g_malloc0 (GST_ROUND_UP_16 (size + FF_INPUT_BUFFER_PADDING_SIZE));
651     memcpy (ctx->codecdata, data, size);
652     ctx->codecdata_size = size;
653
654     if ((strcmp (name, "vc1") == 0) && size > 0 && data[0] == 0) {
655       ctx->codecdata[0] = (guint8) size;
656     }
657   } else if (ctx->codecdata == NULL) {
658     ctx->codecdata_size = 0;
659     ctx->codecdata = g_malloc0 (GST_ROUND_UP_16(FF_INPUT_BUFFER_PADDING_SIZE));
660     GST_DEBUG ("no extra data");
661   }
662
663   if ((strcmp (name, "mpeg4") == 0)) {
664     const gchar *mime = gst_structure_get_name (structure);
665     if (!mime) {
666       GST_ERROR ("Couldn't get mime type from caps %" GST_PTR_FORMAT, caps);
667       return;
668     }
669
670     if (!strcmp (mime, "video/x-divx")) {
671       ctx->codec_tag = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
672     } else if (!strcmp (mime, "video/x-xvid")) {
673       ctx->codec_tag = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
674     } else if (!strcmp (mime, "video/x-3ivx")) {
675       ctx->codec_tag = GST_MAKE_FOURCC ('3', 'I', 'V', '1');
676     } else if (!strcmp (mime, "video/mpeg")) {
677       ctx->codec_tag = GST_MAKE_FOURCC ('m', 'p', '4', 'v');
678     }
679   } else {
680     // TODO
681   }
682
683   if (!gst_caps_is_fixed (caps)) {
684     return;
685   }
686
687   switch (media_type) {
688   case AVMEDIA_TYPE_VIDEO:
689     gst_maru_caps_to_pixfmt (caps, ctx, FALSE);
690     // get_palette
691     break;
692   case AVMEDIA_TYPE_AUDIO:
693     gst_maru_caps_to_smpfmt (caps, ctx, FALSE);
694     break;
695   default:
696     break;
697   }
698 }
699
700 #define CODEC_NAME_BUFFER_SIZE 32
701
702 void
703 gst_maru_caps_to_codecname (const GstCaps *caps,
704                             gchar *codec_name,
705                             CodecContext *context)
706 {
707   GST_DEBUG (" >> ENTER ");
708   const gchar *mimetype;
709   const GstStructure *str;
710   int media_type = AVMEDIA_TYPE_UNKNOWN;
711
712   str = gst_caps_get_structure (caps, 0);
713
714   mimetype = gst_structure_get_name (str);
715   if (!mimetype) {
716     GST_ERROR ("Couldn't get mimetype from caps %" GST_PTR_FORMAT, caps);
717     return;
718   }
719
720   if (!strcmp (mimetype, "video/x-h263")) {
721     const gchar *h263version = gst_structure_get_string (str, "h263version");
722     if (h263version && !strcmp (h263version, "h263p")) {
723       g_strlcpy (codec_name, "h263p", CODEC_NAME_BUFFER_SIZE);
724     } else {
725       g_strlcpy (codec_name, "h263", CODEC_NAME_BUFFER_SIZE);
726     }
727     media_type = AVMEDIA_TYPE_VIDEO;
728   } else if (!strcmp (mimetype, "video/mpeg")) {
729     gboolean sys_strm;
730     gint mpegversion;
731
732     if (gst_structure_get_boolean (str, "systemstream", &sys_strm) &&
733         gst_structure_get_int (str, "mpegversion", &mpegversion) &&
734         !sys_strm) {
735       switch (mpegversion) {
736         case 1:
737           g_strlcpy (codec_name, "mpeg1video", CODEC_NAME_BUFFER_SIZE);
738           break;
739         case 2:
740           g_strlcpy (codec_name, "mpeg2video", CODEC_NAME_BUFFER_SIZE);
741           break;
742         case 4:
743           g_strlcpy (codec_name, "mpeg4", CODEC_NAME_BUFFER_SIZE);
744           break;
745       }
746     }
747
748     media_type = AVMEDIA_TYPE_VIDEO;
749   } else if (!strcmp (mimetype, "video/x-wmv")) {
750     gint wmvversion = 0;
751
752     if (gst_structure_get_int (str, "wmvversion", &wmvversion)) {
753       switch (wmvversion) {
754         case 1:
755           g_strlcpy (codec_name, "wmv1", CODEC_NAME_BUFFER_SIZE);
756           break;
757         case 2:
758           g_strlcpy (codec_name, "wmv2", CODEC_NAME_BUFFER_SIZE);
759           break;
760         case 3:
761         {
762           g_strlcpy (codec_name, "wmv3", CODEC_NAME_BUFFER_SIZE);
763           const gchar *format;
764           if ((format = gst_structure_get_string (str, "format"))) {
765             if ((g_str_equal (format, "WVC1")) || (g_str_equal (format, "WMVA"))) {
766               g_strlcpy (codec_name, "vc1", CODEC_NAME_BUFFER_SIZE);
767             }
768           }
769         }
770           break;
771       }
772     }
773
774     media_type = AVMEDIA_TYPE_VIDEO;
775   } else if (!strcmp (mimetype, "audio/mpeg")) {
776     gint layer = 0;
777     gint mpegversion = 0;
778
779     if (gst_structure_get_int (str, "mpegversion", &mpegversion)) {
780       switch (mpegversion) {
781       case 2:
782       case 4:
783         g_strlcpy (codec_name, "aac", CODEC_NAME_BUFFER_SIZE);
784         break;
785       case 1:
786         if (gst_structure_get_int (str, "layer", &layer)) {
787           switch(layer) {
788             case 1:
789               g_strlcpy (codec_name, "mp1", CODEC_NAME_BUFFER_SIZE);
790               break;
791             case 2:
792               g_strlcpy (codec_name, "mp2", CODEC_NAME_BUFFER_SIZE);
793               break;
794             case 3:
795               g_strlcpy (codec_name, "mp3", CODEC_NAME_BUFFER_SIZE);
796               break;
797           }
798         }
799         break;
800       }
801     }
802
803     media_type = AVMEDIA_TYPE_AUDIO;
804   } else if (!strcmp (mimetype, "audio/x-wma")) {
805     gint wmaversion = 0;
806
807     if (gst_structure_get_int (str, "wmaversion", &wmaversion)) {
808       switch (wmaversion) {
809       case 1:
810         g_strlcpy (codec_name, "wmav1", CODEC_NAME_BUFFER_SIZE);
811         break;
812       case 2:
813         g_strlcpy (codec_name, "wmav2", CODEC_NAME_BUFFER_SIZE);
814         break;
815       case 3:
816         g_strlcpy (codec_name, "wmapro", CODEC_NAME_BUFFER_SIZE);
817         break;
818       }
819     }
820
821     media_type = AVMEDIA_TYPE_AUDIO;
822   } else if (!strcmp (mimetype, "audio/x-ac3")) {
823     g_strlcpy (codec_name, "ac3", CODEC_NAME_BUFFER_SIZE);
824     media_type = AVMEDIA_TYPE_AUDIO;
825   } else if (!strcmp (mimetype, "audio/x-msmpeg")) {
826     gint msmpegversion = 0;
827
828     if (gst_structure_get_int (str, "msmpegversion", &msmpegversion)) {
829       switch (msmpegversion) {
830       case 41:
831         g_strlcpy (codec_name, "msmpeg4v1", CODEC_NAME_BUFFER_SIZE);
832         break;
833       case 42:
834         g_strlcpy (codec_name, "msmpeg4v2", CODEC_NAME_BUFFER_SIZE);
835         break;
836       case 43:
837         g_strlcpy (codec_name, "msmpeg4", CODEC_NAME_BUFFER_SIZE);
838         break;
839       }
840     }
841
842     media_type = AVMEDIA_TYPE_VIDEO;
843   } else if (!strcmp (mimetype, "video/x-h264")) {
844     g_strlcpy (codec_name, "h264", CODEC_NAME_BUFFER_SIZE);
845     media_type = AVMEDIA_TYPE_VIDEO;
846   }
847
848   if (context != NULL) {
849     gst_maru_caps_with_codecname (codec_name, media_type, caps, context);
850   }
851
852   if (codec_name != NULL) {
853     GST_DEBUG ("The %s belongs to the caps %" GST_PTR_FORMAT, codec_name, caps);
854   } else {
855     GST_WARNING ("Couldn't figure out the name for caps %" GST_PTR_FORMAT, caps);
856   }
857 }
858
859 void
860 gst_maru_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx)
861 {
862   GST_DEBUG (" >> ENTER ");
863   if (ctx == NULL) {
864     return;
865   }
866
867   switch (media_type) {
868   case AVMEDIA_TYPE_VIDEO:
869     gst_maru_caps_to_pixfmt (caps, ctx, TRUE);
870     break;
871   case AVMEDIA_TYPE_AUDIO:
872     gst_maru_caps_to_smpfmt (caps, ctx, TRUE);
873     break;
874   default:
875     break;
876   }
877 }
878
879 GstCaps *
880 gst_maru_video_caps_new (CodecContext *ctx, const char *name,
881         const char *mimetype, const char *fieldname, ...)
882 {
883   GST_DEBUG (" >> ENTER ");
884   GstCaps *caps = NULL;
885   va_list var_args;
886   gint i;
887
888   GST_DEBUG ("context: %p, name: %s, mimetype: %s", ctx, name, mimetype);
889
890   if (ctx != NULL && ctx->video.width != -1) {
891     gint num, denom;
892
893     caps = gst_caps_new_simple (mimetype,
894       "width", G_TYPE_INT, ctx->video.width,
895       "height", G_TYPE_INT, ctx->video.height, NULL);
896
897     num = ctx->video.fps_d / ctx->video.ticks_per_frame;
898     denom = ctx->video.fps_n;
899
900     if (!denom) {
901       GST_DEBUG ("invalid framerate: %d/0, -> %d/1", num, num);
902       denom = 1;
903     }
904     if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
905       GST_DEBUG ("excessive framerate: %d/%d, -> 0/1", num, denom);
906       num = 0;
907       denom = 1;
908     }
909     GST_DEBUG ("setting framerate: %d/%d", num, denom);
910     gst_caps_set_simple (caps,
911       "framerate", GST_TYPE_FRACTION, num, denom, NULL);
912   } else {
913     if (strcmp (name, "h263") == 0) {
914       /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
915        * because we want automatic negotiation to go as close to 320x240 as
916        * possible. */
917       const static gint widths[] = { 352, 704, 176, 1408, 128 };
918       const static gint heights[] = { 288, 576, 144, 1152, 96 };
919       GstCaps *temp;
920       gint n_sizes = G_N_ELEMENTS (widths);
921
922       caps = gst_caps_new_empty ();
923       for (i = 0; i < n_sizes; i++) {
924         temp = gst_caps_new_simple (mimetype,
925             "width", G_TYPE_INT, widths[i],
926             "height", G_TYPE_INT, heights[i],
927             "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
928
929         gst_caps_append (caps, temp);
930       }
931     } else if (strcmp (name, "none") == 0) {
932       GST_DEBUG ("default caps");
933     }
934   }
935
936   /* no fixed caps or special restrictions applied;
937    * default unfixed setting */
938   if (!caps) {
939     GST_DEBUG ("Creating default caps");
940     caps = gst_caps_new_empty_simple (mimetype);
941   }
942
943   va_start (var_args, fieldname);
944   gst_caps_set_simple_valist (caps, fieldname, var_args);
945   va_end (var_args);
946
947   return caps;
948 }
949
950 GstCaps *
951 gst_maru_audio_caps_new (CodecContext *ctx, const char *name,
952         const char *mimetype, const char *fieldname, ...)
953 {
954   GST_DEBUG (" >> ENTER ");
955
956   GstCaps *caps = NULL;
957   gint i;
958   va_list var_args;
959
960   if (ctx != NULL && ctx->audio.channels != -1) {
961     GstAudioChannelPosition pos[64];
962     guint64 mask;
963
964     caps = gst_caps_new_simple (mimetype,
965             "rate", G_TYPE_INT, ctx->audio.sample_rate,
966             "channels", G_TYPE_INT, ctx->audio.channels, NULL);
967
968     if (ctx->audio.channels > 1 &&
969         gst_ffmpeg_channel_layout_to_gst (ctx->audio.channel_layout,
970             ctx->audio.channels, pos) &&
971         gst_audio_channel_positions_to_mask (pos, ctx->audio.channels, FALSE,
972             &mask)) {
973       gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, mask, NULL);
974     }
975   } else {
976     gint maxchannels = 2;
977     const gint *rates = NULL;
978     gint n_rates = 0;
979
980     if (strcmp (name, "aac") == 0) {
981       maxchannels = 6;
982     } else if (g_str_has_prefix(name, "ac3")) {
983       const static gint l_rates[] = { 48000, 44100, 32000 };
984       maxchannels = 6;
985       n_rates = G_N_ELEMENTS (l_rates);
986       rates = l_rates;
987     } else {
988      // TODO
989     }
990 //TODO Not use the mono type at the moment.
991 /*    if (maxchannels == 1) {
992       caps = gst_caps_new_simple(mimetype,
993               "channels", G_TYPE_INT, maxchannels, NULL);
994     } else {
995       caps = gst_caps_new_simple(mimetype,
996               "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
997     }
998 */
999     caps = gst_caps_new_simple(mimetype,
1000                         "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
1001     if (n_rates) {
1002       GValue list = { 0, };
1003       //GstStructure *structure;
1004
1005       g_value_init(&list, GST_TYPE_LIST);
1006       for (i = 0; i < n_rates; i++) {
1007         GValue v = { 0, };
1008
1009         g_value_init(&v, G_TYPE_INT);
1010         g_value_set_int(&v, rates[i]);
1011         gst_value_list_append_value(&list, &v);
1012         g_value_unset(&v);
1013       }
1014       gst_caps_set_value (caps, "rate", &list);
1015       g_value_unset(&list);
1016     } else {
1017       gst_caps_set_simple(caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
1018     }
1019   }
1020
1021   va_start (var_args, fieldname);
1022   gst_caps_set_simple_valist (caps, fieldname, var_args);
1023   va_end (var_args);
1024
1025   return caps;
1026 }
1027
1028 GstCaps *
1029 gst_maru_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name)
1030 {
1031   GST_DEBUG (" >> ENTER ");
1032   GstCaps *caps = NULL;
1033   GstVideoFormat format;
1034
1035   format = gst_maru_pixfmt_to_videoformat (pix_fmt);
1036
1037   if (format != GST_VIDEO_FORMAT_UNKNOWN) {
1038     caps = gst_maru_video_caps_new (ctx, name, "video/x-raw",
1039         "format", G_TYPE_STRING, gst_video_format_to_string (format), NULL);
1040   }
1041
1042   if (caps != NULL) {
1043     GST_DEBUG ("caps for pix_fmt=%d: %" GST_PTR_FORMAT, pix_fmt, caps);
1044   } else {
1045     GST_DEBUG ("No caps found for pix_fmt=%d", pix_fmt);
1046   }
1047
1048   return caps;
1049 }
1050
1051 GstVideoFormat
1052 gst_maru_pixfmt_to_videoformat (enum PixelFormat pixfmt)
1053 {
1054   guint i;
1055
1056   for (i = 0; i < G_N_ELEMENTS (pixtofmttable); i++)
1057     if (pixtofmttable[i].pixfmt == pixfmt)
1058       return pixtofmttable[i].format;
1059
1060   return GST_VIDEO_FORMAT_UNKNOWN;
1061 }
1062
1063 enum PixelFormat
1064 gst_maru_videoformat_to_pixfmt (GstVideoFormat format)
1065 {
1066   guint i;
1067
1068   for (i = 0; i < G_N_ELEMENTS (pixtofmttable); i++)
1069     if (pixtofmttable[i].format == format)
1070       return pixtofmttable[i].pixfmt;
1071   return PIX_FMT_NONE;
1072 }
1073
1074 void
1075 gst_maru_videoinfo_to_context (GstVideoInfo * info, CodecContext * context)
1076 {
1077   gint i, bpp = 0;
1078
1079   context->video.width = GST_VIDEO_INFO_WIDTH (info);
1080   context->video.height = GST_VIDEO_INFO_HEIGHT (info);
1081   for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++)
1082     bpp += GST_VIDEO_INFO_COMP_DEPTH (info, i);
1083   context->video.bpp = bpp;
1084
1085   context->video.ticks_per_frame = 1;
1086   if (GST_VIDEO_INFO_FPS_N (info) == 0) {
1087     GST_DEBUG ("Using 25/1 framerate");
1088     context->video.fps_d = 25;
1089     context->video.fps_n = 1;
1090   } else {
1091     context->video.fps_d = GST_VIDEO_INFO_FPS_N (info);
1092     context->video.fps_n = GST_VIDEO_INFO_FPS_D (info);
1093   }
1094
1095   context->video.par_n = GST_VIDEO_INFO_PAR_N (info);
1096   context->video.par_d = GST_VIDEO_INFO_PAR_D (info);
1097
1098   context->video.pix_fmt =
1099       gst_maru_videoformat_to_pixfmt (GST_VIDEO_INFO_FORMAT (info));
1100 }
1101
1102 GstCaps *
1103 gst_maru_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name)
1104 {
1105   GstCaps *caps = NULL;
1106   GstAudioFormat format;
1107
1108   format = gst_maru_smpfmt_to_audioformat (sample_fmt);
1109
1110   if (format != GST_AUDIO_FORMAT_UNKNOWN) {
1111     caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw",
1112         "format", G_TYPE_STRING, gst_audio_format_to_string (format),
1113         "layout", G_TYPE_STRING, "interleaved", NULL);
1114     GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
1115   } else {
1116     GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
1117   }
1118
1119   return caps;
1120 }
1121
1122 GstCaps *
1123 gst_maru_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode)
1124 {
1125   GST_DEBUG (" >> ENTER");
1126   GstCaps *caps = NULL;
1127
1128   GST_DEBUG ("codec: %s, context: %p, encode: %d", name, ctx, encode);
1129
1130   if (strcmp (name, "mpegvideo") == 0) {
1131     caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1132                 "mpegversion", G_TYPE_INT, 1,
1133                 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1134   } else if (strcmp (name, "h263") == 0) {
1135     if (encode) {
1136       caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
1137                   "variant", G_TYPE_STRING, "itu", NULL);
1138     } else {
1139       caps = gst_maru_video_caps_new (ctx, "none", "video/x-h263",
1140                   "variant", G_TYPE_STRING, "itu", NULL);
1141     }
1142   } else if (strcmp (name, "h263p") == 0) {
1143     caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
1144               "variant", G_TYPE_STRING, "itu",
1145               "h263version", G_TYPE_STRING, "h263p", NULL);
1146   } else if (strcmp (name, "mpeg2video") == 0) {
1147     if (encode) {
1148       caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1149             "mpegversion", G_TYPE_INT, 2,
1150             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1151     } else {
1152       caps = gst_caps_new_simple ("video/mpeg",
1153             "mpegversion", GST_TYPE_INT_RANGE, 1, 2,
1154             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1155     }
1156   } else if (strcmp (name, "mpeg4") == 0) {
1157     if (encode && ctx != NULL) {
1158       // TODO
1159       switch (ctx->codec_tag) {
1160         case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
1161           caps = gst_maru_video_caps_new (ctx, name, "video/x-divx",
1162               "divxversion", G_TYPE_INT, 5, NULL);
1163           break;
1164         case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
1165         default:
1166           caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1167               "systemstream", G_TYPE_BOOLEAN, FALSE,
1168               "mpegversion", G_TYPE_INT, 4, NULL);
1169           break;
1170       }
1171     } else {
1172       caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1173             "mpegversion", G_TYPE_INT, 4,
1174             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1175       if (encode) {
1176         caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1177             "mpegversion", G_TYPE_INT, 4,
1178             "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1179       } else {
1180         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1181             "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
1182         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1183             "video/x-xvid", NULL));
1184         gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1185             "video/x-3ivx", NULL));
1186       }
1187     }
1188   } else if ((strcmp (name, "h264") == 0) || (strcmp (name, "libx264") == 0)) {
1189     caps = gst_maru_video_caps_new (ctx, name, "video/x-h264", NULL);
1190   } else if (g_str_has_prefix(name, "msmpeg4")) {
1191     // msmpeg4v1,m msmpeg4v2, msmpeg4
1192     gint version;
1193
1194     if (strcmp (name, "msmpeg4v1") == 0) {
1195       version = 41;
1196     } else if (strcmp (name, "msmpeg4v2") == 0) {
1197       version = 42;
1198     } else {
1199       version = 43;
1200     }
1201
1202     caps = gst_maru_video_caps_new (ctx, name, "video/x-msmpeg",
1203           "msmpegversion", G_TYPE_INT, version, NULL);
1204     if (!encode && !strcmp (name, "msmpeg4")) {
1205        gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1206             "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
1207     }
1208   } else if (strcmp (name, "wmv3") == 0) {
1209     caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1210                 "wmvversion", G_TYPE_INT, 3, NULL);
1211   } else if (strcmp (name, "vc1") == 0) {
1212     caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1213                 "wmvversion", G_TYPE_INT, 3, "format",
1214                 G_TYPE_STRING, "WVC1", NULL);
1215   } else if (strcmp (name, "aac") == 0) {
1216     caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg", NULL);
1217     if (!encode) {
1218         GValue arr = { 0, };
1219         GValue item = { 0, };
1220
1221         g_value_init (&arr, GST_TYPE_LIST);
1222         g_value_init (&item, G_TYPE_INT);
1223         g_value_set_int (&item, 2);
1224         gst_value_list_append_value (&arr, &item);
1225         g_value_set_int (&item, 4);
1226         gst_value_list_append_value (&arr, &item);
1227         g_value_unset (&item);
1228
1229         gst_caps_set_value (caps, "mpegversion", &arr);
1230         g_value_unset (&arr);
1231
1232         g_value_init (&arr, GST_TYPE_LIST);
1233         g_value_init (&item, G_TYPE_STRING);
1234         g_value_set_string (&item, "raw");
1235         gst_value_list_append_value (&arr, &item);
1236         g_value_set_string (&item, "adts");
1237         gst_value_list_append_value (&arr, &item);
1238         g_value_set_string (&item, "adif");
1239         gst_value_list_append_value (&arr, &item);
1240         g_value_unset (&item);
1241
1242         gst_caps_set_value (caps, "stream-format", &arr);
1243         g_value_unset (&arr);
1244     } else {
1245       gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT, 4,
1246         "stream-format", G_TYPE_STRING, "raw",
1247         "base-profile", G_TYPE_STRING, "lc", NULL);
1248
1249         if (ctx && ctx->codecdata_size > 0) {
1250           gst_codec_utils_aac_caps_set_level_and_profile (caps,
1251             ctx->codecdata, ctx->codecdata_size);
1252         }
1253     }
1254   } else if (strcmp (name, "ac3") == 0) {
1255     caps = gst_maru_audio_caps_new (ctx, name, "audio/x-ac3", NULL);
1256   } else if (strcmp (name, "mp3") == 0) {
1257     if (encode) {
1258       caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg",
1259               "mpegversion", G_TYPE_INT, 1,
1260               "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1261     } else {
1262       caps = gst_caps_new_simple("audio/mpeg",
1263               "mpegversion", G_TYPE_INT, 1,
1264               "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1265     }
1266   } else if (strcmp (name, "mp3adu") == 0) {
1267     gchar *mime_type;
1268
1269     mime_type = g_strdup_printf ("audio/x-gst_ff-%s", name);
1270     caps = gst_maru_audio_caps_new (ctx, name, mime_type, NULL);
1271
1272     if (mime_type) {
1273       g_free(mime_type);
1274     }
1275   } else if (g_str_has_prefix(name, "wmav")) {
1276     gint version = 1;
1277     if (strcmp (name, "wmav2") == 0) {
1278       version = 2;
1279     }
1280     caps = gst_maru_audio_caps_new (ctx, name, "audio/x-wma", "wmaversion",
1281           G_TYPE_INT, version, "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
1282           "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
1283   } else {
1284     GST_ERROR("failed to new caps for %s", name);
1285   }
1286
1287   if (caps != NULL) {
1288     GST_DEBUG ("caps is NOT null");
1289     if (ctx && ctx->codecdata_size > 0) {
1290       GST_DEBUG ("codec_data size %d", ctx->codecdata_size);
1291
1292       GstBuffer *data = gst_buffer_new_and_alloc (ctx->codecdata_size);
1293
1294       gst_buffer_fill (data, 0, ctx->codecdata, ctx->codecdata_size);
1295       gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, data, NULL);
1296       gst_buffer_unref (data);
1297     }
1298     GST_DEBUG ("caps for codec %s %" GST_PTR_FORMAT, name, caps);
1299   } else {
1300     GST_DEBUG ("No caps found for codec %s", name);
1301   }
1302
1303   return caps;
1304 }
1305
1306 typedef struct PixFmtInfo
1307 {
1308   uint8_t x_chroma_shift;       /* X chroma subsampling factor is 2 ^ shift */
1309   uint8_t y_chroma_shift;       /* Y chroma subsampling factor is 2 ^ shift */
1310 } PixFmtInfo;
1311
1312 static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
1313
1314 void
1315 gst_maru_init_pix_fmt_info (void)
1316 {
1317   GST_DEBUG (" >> ENTER ");
1318   pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1,
1319   pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
1320
1321   pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
1322   pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
1323
1324   pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
1325   pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
1326
1327   pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
1328   pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
1329
1330   pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
1331   pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
1332
1333   pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
1334   pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
1335
1336   /* RGB formats */
1337   pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
1338   pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
1339
1340   pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
1341   pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
1342
1343   pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
1344   pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
1345
1346   pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
1347   pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
1348
1349   pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
1350   pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
1351 }
1352
1353 int
1354 gst_maru_avpicture_size (int pix_fmt, int width, int height)
1355 {
1356   GST_DEBUG (" >> ENTER ");
1357   int size, w2, h2, size2;
1358   int stride, stride2;
1359   int fsize;
1360   PixFmtInfo *pinfo;
1361
1362   pinfo = &pix_fmt_info[pix_fmt];
1363
1364   switch (pix_fmt) {
1365   case PIX_FMT_YUV420P:
1366   case PIX_FMT_YUV422P:
1367   case PIX_FMT_YUV444P:
1368   case PIX_FMT_YUV410P:
1369   case PIX_FMT_YUV411P:
1370     stride = ROUND_UP_4(width);
1371     h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
1372     size = stride * h2;
1373     w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
1374     stride2 = ROUND_UP_4(w2);
1375     h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
1376     size2 = stride2 * h2;
1377     fsize = size + 2 * size2;
1378     break;
1379   case PIX_FMT_RGB24:
1380   case PIX_FMT_BGR24:
1381     stride = ROUND_UP_4 (width * 3);
1382     fsize = stride * height;
1383     break;
1384   case PIX_FMT_RGB32:
1385     stride = width * 4;
1386     fsize = stride * height;
1387     break;
1388   case PIX_FMT_RGB555:
1389   case PIX_FMT_RGB565:
1390     stride = ROUND_UP_4 (width * 2);
1391     fsize = stride * height;
1392     break;
1393   default:
1394     fsize = -1;
1395     break;
1396   }
1397
1398   return fsize;
1399 }
1400
1401 int
1402 gst_maru_align_size (int buf_size)
1403 {
1404   GST_DEBUG (" >> ENTER ");
1405   int i, align_size;
1406
1407   align_size = buf_size / 1024;
1408
1409   for (i = 0; i < 14; i++) {
1410     if (align_size < (1 << i)) {
1411       align_size = 1024 * (1 << i);
1412       break;
1413     }
1414   }
1415
1416   return align_size;
1417 }
1418
1419 GstAudioFormat
1420 gst_maru_smpfmt_to_audioformat(int32_t sample_fmt)
1421 {
1422     switch (sample_fmt) {
1423     case SAMPLE_FMT_U8:
1424     case SAMPLE_FMT_U8P:
1425       return GST_AUDIO_FORMAT_U8;
1426       break;
1427     case SAMPLE_FMT_S16:
1428     case SAMPLE_FMT_S16P:
1429       return GST_AUDIO_FORMAT_S16;
1430       break;
1431     case SAMPLE_FMT_S32:
1432     case SAMPLE_FMT_S32P:
1433       return GST_AUDIO_FORMAT_S32;
1434       break;
1435     case SAMPLE_FMT_FLT:
1436     case SAMPLE_FMT_FLTP:
1437       return GST_AUDIO_FORMAT_F32;
1438       break;
1439     case SAMPLE_FMT_DBL:
1440     case SAMPLE_FMT_DBLP:
1441       return GST_AUDIO_FORMAT_F64;
1442       break;
1443     default:
1444       /* .. */
1445       return GST_AUDIO_FORMAT_UNKNOWN;
1446       break;
1447   }
1448 }
1449
1450 gboolean
1451 gst_maru_channel_layout_to_gst (guint64 channel_layout, gint channels,
1452     GstAudioChannelPosition * pos)
1453 {
1454   guint nchannels = 0;
1455   gboolean none_layout = FALSE;
1456
1457   if (channel_layout == 0) {
1458     nchannels = channels;
1459     none_layout = TRUE;
1460   } else {
1461     guint i, j;
1462
1463     for (i = 0; i < 64; i++) {
1464       if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
1465         nchannels++;
1466       }
1467     }
1468
1469     if (nchannels != channels) {
1470       GST_ERROR ("Number of channels is different (%u != %u)", channels,
1471           nchannels);
1472       nchannels = channels;
1473       none_layout = TRUE;
1474     } else {
1475
1476       for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) {
1477         if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) {
1478           pos[j++] = _ff_to_gst_layout[i].gst;
1479
1480           if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE)
1481             none_layout = TRUE;
1482         }
1483       }
1484
1485       if (j != nchannels) {
1486         GST_WARNING
1487             ("Unknown channels in channel layout - assuming NONE layout");
1488         none_layout = TRUE;
1489       }
1490     }
1491   }
1492
1493   if (!none_layout
1494       && !gst_audio_check_valid_channel_positions (pos, nchannels, FALSE)) {
1495     GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
1496         " - assuming NONE layout", channel_layout);
1497     none_layout = TRUE;
1498   }
1499
1500   if (none_layout) {
1501     if (nchannels == 1) {
1502       pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
1503     } else if (nchannels == 2) {
1504       pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
1505       pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
1506     } else {
1507       guint i;
1508
1509       for (i = 0; i < nchannels; i++)
1510         pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
1511     }
1512   }
1513
1514   return TRUE;
1515 }
1516
1517 void
1518 gst_maru_audioinfo_to_context (GstAudioInfo *info, CodecContext *context)
1519 {
1520   const CodecElement *codec = context->codec;
1521   enum SampleFormat smpl_fmts[4];
1522   enum SampleFormat smpl_fmt = -1;
1523   int i;
1524
1525   context->audio.channels = info->channels;
1526   context->audio.sample_rate = info->rate;
1527   context->audio.channel_layout =
1528       gst_ffmpeg_channel_positions_to_layout (info->position, info->channels);
1529
1530   if (!codec) {
1531     GST_ERROR ("invalid codec");
1532     return ;
1533   }
1534
1535   for (i = 0; i < 4; i++) {
1536     smpl_fmts[i] = codec->sample_fmts[i];
1537   }
1538   i = 0;
1539   switch (info->finfo->format) {
1540     case GST_AUDIO_FORMAT_F32:
1541       if (smpl_fmts[0] != -1) {
1542         while (smpl_fmts[i] != -1) {
1543           if (smpl_fmts[i] == SAMPLE_FMT_FLT) {
1544             smpl_fmt = smpl_fmts[i];
1545             break;
1546           } else if (smpl_fmts[i] == SAMPLE_FMT_FLTP) {
1547             smpl_fmt = smpl_fmts[i];
1548           }
1549
1550           i++;
1551         }
1552       } else {
1553         smpl_fmt = SAMPLE_FMT_FLT;
1554       }
1555       break;
1556     case GST_AUDIO_FORMAT_F64:
1557       if (smpl_fmts[0] != -1) {
1558         while (smpl_fmts[i] != -1) {
1559           if (smpl_fmts[i] == SAMPLE_FMT_DBL) {
1560             smpl_fmt = smpl_fmts[i];
1561             break;
1562           } else if (smpl_fmts[i] == SAMPLE_FMT_DBLP) {
1563             smpl_fmt = smpl_fmts[i];
1564           }
1565
1566           i++;
1567         }
1568       } else {
1569         smpl_fmt = SAMPLE_FMT_DBL;
1570       }
1571       break;
1572     case GST_AUDIO_FORMAT_S32:
1573       if (smpl_fmts[0] != -1) {
1574         while (smpl_fmts[i] != -1) {
1575           if (smpl_fmts[i] == SAMPLE_FMT_S32) {
1576             smpl_fmt = smpl_fmts[i];
1577             break;
1578           } else if (smpl_fmts[i] == SAMPLE_FMT_S32P) {
1579             smpl_fmt = smpl_fmts[i];
1580           }
1581
1582           i++;
1583         }
1584       } else {
1585         smpl_fmt = SAMPLE_FMT_S32;
1586       }
1587       break;
1588     case GST_AUDIO_FORMAT_S16:
1589       if (smpl_fmts[0] != -1) {
1590         while (smpl_fmts[i] != -1) {
1591           if (smpl_fmts[i] == SAMPLE_FMT_S16) {
1592             smpl_fmt = smpl_fmts[i];
1593             break;
1594           } else if (smpl_fmts[i] == SAMPLE_FMT_S16P) {
1595             smpl_fmt = smpl_fmts[i];
1596           }
1597
1598           i++;
1599         }
1600       } else {
1601         smpl_fmt = SAMPLE_FMT_S16;
1602       }
1603       break;
1604     case GST_AUDIO_FORMAT_U8:
1605       if (smpl_fmts[0] != -1) {
1606         while (smpl_fmts[i] != -1) {
1607           if (smpl_fmts[i] == SAMPLE_FMT_U8) {
1608             smpl_fmt = smpl_fmts[i];
1609             break;
1610           } else if (smpl_fmts[i] == SAMPLE_FMT_U8P) {
1611             smpl_fmt = smpl_fmts[i];
1612           }
1613
1614           i++;
1615         }
1616       } else {
1617         smpl_fmt = SAMPLE_FMT_U8;
1618       }
1619       break;
1620     default:
1621       break;
1622   }
1623
1624   g_assert (smpl_fmt != -1);
1625
1626   context->audio.sample_fmt = smpl_fmt;
1627 }