2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
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.
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.
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.
21 #include "gstmaruutils.h"
22 #include <gst/audio/multichannel.h>
23 #include <gst/pbutils/codec-utils.h>
26 gst_maru_smpfmt_depth (int smp_fmt)
50 GST_ERROR ("Unhandled sample format !");
61 GstAudioChannelPosition gst;
62 } _ff_to_gst_layout[] = {
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}
86 static GstAudioChannelPosition *
87 gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels)
89 guint nchannels = 0, i, j;
90 GstAudioChannelPosition *pos = NULL;
91 gboolean none_layout = FALSE;
93 for (i = 0; i < 64; i++) {
94 if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
99 if (channel_layout == 0) {
100 nchannels = channels;
104 if (nchannels != channels) {
105 GST_ERROR ("Number of channels is different (%u != %u)", channels,
110 pos = g_new (GstAudioChannelPosition, nchannels);
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;
116 if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE) {
122 if (j != nchannels) {
123 GST_WARNING ("Unknown channels in channel layout - assuming NONE layout");
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);
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) {
143 for (i = 0; i < nchannels; i++) {
144 pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
149 if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) {
150 GST_DEBUG ("mono common case; won't set channel positions");
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");
164 gst_maru_codectype_to_video_caps (CodecContext *ctx, const char *name,
165 gboolean encode, CodecElement *codec)
169 GST_DEBUG ("context: %p, codec: %s, encode: %d, pixel format: %d",
170 ctx, name, encode, ctx->video.pix_fmt);
173 caps = gst_maru_pixfmt_to_caps (ctx->video.pix_fmt, ctx, name);
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);
183 gst_caps_append (caps, temp);
192 gst_maru_codectype_to_audio_caps (CodecContext *ctx, const char *name,
193 gboolean encode, CodecElement *codec)
195 GstCaps *caps = NULL;
197 GST_DEBUG ("context: %p, codec: %s, encode: %d, codec: %p",
198 ctx, name, encode, codec);
201 caps = gst_maru_smpfmt_to_caps (ctx->audio.sample_fmt, ctx, name);
202 } else if (codec && codec->sample_fmts[0] != -1){
206 caps = gst_caps_new_empty ();
207 for (i = 0; codec->sample_fmts[i] != -1; i++) {
208 int8_t sample_fmt = -1;
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);
218 gst_maru_smpfmt_to_caps (sample_fmt, ctx, name);
220 gst_caps_append (caps, temp);
226 CodecContext ctx = {{0}, {0}, 0};
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);
233 gst_caps_append (caps, temp);
242 gst_maru_codectype_to_caps (int media_type, CodecContext *ctx,
243 const char *name, gboolean encode)
247 switch (media_type) {
248 case AVMEDIA_TYPE_VIDEO:
250 gst_maru_codectype_to_video_caps (ctx, name, encode, NULL);
252 case AVMEDIA_TYPE_AUDIO:
254 gst_maru_codectype_to_audio_caps (ctx, name, encode, NULL);
265 gst_maru_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
269 const GValue *par = NULL;
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);
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);
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;
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);
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);
300 g_return_if_fail (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
302 if (strcmp (gst_structure_get_name (str), "video/x-raw-yuv") == 0) {
305 if (gst_structure_get_fourcc (str, "format", &fourcc)) {
307 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
308 ctx->video.pix_fmt = PIX_FMT_YUYV422;
310 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
311 ctx->video.pix_fmt = PIX_FMT_YUV420P;
313 case GST_MAKE_FOURCC ('A', '4', '2', '0'):
314 ctx->video.pix_fmt = PIX_FMT_YUVA420P;
316 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
317 ctx->video.pix_fmt = PIX_FMT_YUV411P;
319 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
320 ctx->video.pix_fmt = PIX_FMT_YUV422P;
322 case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
323 ctx->video.pix_fmt = PIX_FMT_YUV410P;
327 } else if (strcmp (gst_structure_get_name (str), "video/x-raw-rgb") == 0) {
328 gint bpp = 0, rmask = 0, endianness = 0;
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)) {
335 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
336 if (rmask == 0x00ff0000) {
338 if (rmask == 0x00ff0000) {
340 ctx->video.pix_fmt = PIX_FMT_RGB32;
344 if (rmask == 0x0000FF) {
345 ctx->video.pix_fmt = PIX_FMT_BGR24;
347 ctx->video.pix_fmt = PIX_FMT_RGB24;
351 if (endianness == G_BYTE_ORDER) {
352 ctx->video.pix_fmt = PIX_FMT_RGB565;
356 if (endianness == G_BYTE_ORDER) {
357 ctx->video.pix_fmt = PIX_FMT_RGB555;
366 ctx->video.pix_fmt = PIX_FMT_PAL8;
370 } else if (strcmp (gst_structure_get_name (str), "video/x-raw-gray") == 0) {
373 if (gst_structure_get_int (str, "bpp", &bpp)) {
376 ctx->video.pix_fmt = PIX_FMT_GRAY8;
384 gst_maru_caps_to_smpfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
387 gint depth = 0, width = 0, endianness = 0;
388 gboolean signedness = FALSE;
391 g_return_if_fail (gst_caps_get_size (caps) == 1);
392 str = gst_caps_get_structure (caps, 0);
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);
403 name = gst_structure_get_name (str);
405 GST_ERROR ("Couldn't get audio sample format from caps %" GST_PTR_FORMAT, caps);
409 if (!strcmp (name, "audio/x-raw-float")) {
410 if (gst_structure_get_int (str, "width", &width) &&
411 gst_structure_get_int (str, "endianness", &endianness)) {
412 if (endianness == G_BYTE_ORDER) {
414 ctx->audio.sample_fmt = SAMPLE_FMT_FLT;
415 } else if (width == 64) {
416 ctx->audio.sample_fmt = SAMPLE_FMT_DBL;
421 if (gst_structure_get_int (str, "width", &width) &&
422 gst_structure_get_int (str, "depth", &depth) &&
423 gst_structure_get_boolean (str, "signed", &signedness) &&
424 gst_structure_get_int (str, "endianness", &endianness)) {
425 if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) {
426 if ((width == 16) && (depth == 16)) {
427 ctx->audio.sample_fmt = SAMPLE_FMT_S16;
428 } else if ((width == 32) && (depth == 32)) {
429 ctx->audio.sample_fmt = SAMPLE_FMT_S32;
437 gst_maru_caps_with_codecname (const char *name, int media_type,
438 const GstCaps *caps, CodecContext *ctx)
440 GstStructure *structure;
442 const GstBuffer *buf;
444 if (!ctx || !gst_caps_get_size (caps)) {
448 structure = gst_caps_get_structure (caps, 0);
450 if ((value = gst_structure_get_value (structure, "codec_data"))) {
454 buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
455 size = GST_BUFFER_SIZE (buf);
456 data = GST_BUFFER_DATA (buf);
457 GST_DEBUG ("extradata: %p, size: %d", data, size);
459 if (ctx->codecdata) {
460 g_free (ctx->codecdata);
464 g_malloc0 (GST_ROUND_UP_16 (size + FF_INPUT_BUFFER_PADDING_SIZE));
465 memcpy (ctx->codecdata, data, size);
466 ctx->codecdata_size = size;
468 if ((strcmp (name, "vc1") == 0) && size > 0 && data[0] == 0) {
469 ctx->codecdata[0] = (guint8) size;
471 } else if (ctx->codecdata == NULL) {
472 ctx->codecdata_size = 0;
473 ctx->codecdata = g_malloc0 (GST_ROUND_UP_16(FF_INPUT_BUFFER_PADDING_SIZE));
474 GST_DEBUG ("no extra data");
477 if ((strcmp (name, "mpeg4") == 0)) {
478 const gchar *mime = gst_structure_get_name (structure);
480 GST_ERROR ("Couldn't get mime type from caps %" GST_PTR_FORMAT, caps);
484 if (!strcmp (mime, "video/x-divx")) {
485 ctx->codec_tag = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
486 } else if (!strcmp (mime, "video/x-xvid")) {
487 ctx->codec_tag = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
488 } else if (!strcmp (mime, "video/x-3ivx")) {
489 ctx->codec_tag = GST_MAKE_FOURCC ('3', 'I', 'V', '1');
490 } else if (!strcmp (mime, "video/mpeg")) {
491 ctx->codec_tag = GST_MAKE_FOURCC ('m', 'p', '4', 'v');
497 if (!gst_caps_is_fixed (caps)) {
501 switch (media_type) {
502 case AVMEDIA_TYPE_VIDEO:
503 gst_maru_caps_to_pixfmt (caps, ctx, FALSE);
506 case AVMEDIA_TYPE_AUDIO:
507 gst_maru_caps_to_smpfmt (caps, ctx, FALSE);
514 #define CODEC_NAME_BUFFER_SIZE 32
517 gst_maru_caps_to_codecname (const GstCaps *caps,
519 CodecContext *context)
521 const gchar *mimetype;
522 const GstStructure *str;
523 int media_type = AVMEDIA_TYPE_UNKNOWN;
525 str = gst_caps_get_structure (caps, 0);
527 mimetype = gst_structure_get_name (str);
529 GST_ERROR ("Couldn't get mimetype from caps %" GST_PTR_FORMAT, caps);
533 if (!strcmp (mimetype, "video/x-h263")) {
534 const gchar *h263version = gst_structure_get_string (str, "h263version");
535 if (h263version && !strcmp (h263version, "h263p")) {
536 g_strlcpy (codec_name, "h263p", CODEC_NAME_BUFFER_SIZE);
538 g_strlcpy (codec_name, "h263", CODEC_NAME_BUFFER_SIZE);
540 media_type = AVMEDIA_TYPE_VIDEO;
541 } else if (!strcmp (mimetype, "video/mpeg")) {
545 if (gst_structure_get_boolean (str, "systemstream", &sys_strm) &&
546 gst_structure_get_int (str, "mpegversion", &mpegversion) &&
548 switch (mpegversion) {
550 g_strlcpy (codec_name, "mpeg1video", CODEC_NAME_BUFFER_SIZE);
553 g_strlcpy (codec_name, "mpeg2video", CODEC_NAME_BUFFER_SIZE);
556 g_strlcpy (codec_name, "mpeg4", CODEC_NAME_BUFFER_SIZE);
561 media_type = AVMEDIA_TYPE_VIDEO;
562 } else if (!strcmp (mimetype, "video/x-wmv")) {
565 if (gst_structure_get_int (str, "wmvversion", &wmvversion)) {
566 switch (wmvversion) {
568 g_strlcpy (codec_name, "wmv1", CODEC_NAME_BUFFER_SIZE);
571 g_strlcpy (codec_name, "wmv2", CODEC_NAME_BUFFER_SIZE);
577 g_strlcpy (codec_name, "wmv3", CODEC_NAME_BUFFER_SIZE);
578 if (gst_structure_get_fourcc (str, "format", &fourcc)) {
579 if ((fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1')) ||
580 (fourcc == GST_MAKE_FOURCC ('W', 'M', 'V', 'A'))) {
581 g_strlcpy (codec_name, "vc1", CODEC_NAME_BUFFER_SIZE);
589 media_type = AVMEDIA_TYPE_VIDEO;
590 } else if (!strcmp (mimetype, "audio/mpeg")) {
592 gint mpegversion = 0;
594 if (gst_structure_get_int (str, "mpegversion", &mpegversion)) {
595 switch (mpegversion) {
598 g_strlcpy (codec_name, "aac", CODEC_NAME_BUFFER_SIZE);
601 if (gst_structure_get_int (str, "layer", &layer)) {
604 g_strlcpy (codec_name, "mp1", CODEC_NAME_BUFFER_SIZE);
607 g_strlcpy (codec_name, "mp2", CODEC_NAME_BUFFER_SIZE);
610 g_strlcpy (codec_name, "mp3", CODEC_NAME_BUFFER_SIZE);
618 media_type = AVMEDIA_TYPE_AUDIO;
619 } else if (!strcmp (mimetype, "audio/x-wma")) {
622 if (gst_structure_get_int (str, "wmaversion", &wmaversion)) {
623 switch (wmaversion) {
625 g_strlcpy (codec_name, "wmav1", CODEC_NAME_BUFFER_SIZE);
628 g_strlcpy (codec_name, "wmav2", CODEC_NAME_BUFFER_SIZE);
631 g_strlcpy (codec_name, "wmapro", CODEC_NAME_BUFFER_SIZE);
636 media_type = AVMEDIA_TYPE_AUDIO;
637 } else if (!strcmp (mimetype, "audio/x-ac3")) {
638 g_strlcpy (codec_name, "ac3", CODEC_NAME_BUFFER_SIZE);
639 media_type = AVMEDIA_TYPE_AUDIO;
640 } else if (!strcmp (mimetype, "audio/x-msmpeg")) {
641 gint msmpegversion = 0;
643 if (gst_structure_get_int (str, "msmpegversion", &msmpegversion)) {
644 switch (msmpegversion) {
646 g_strlcpy (codec_name, "msmpeg4v1", CODEC_NAME_BUFFER_SIZE);
649 g_strlcpy (codec_name, "msmpeg4v2", CODEC_NAME_BUFFER_SIZE);
652 g_strlcpy (codec_name, "msmpeg4", CODEC_NAME_BUFFER_SIZE);
657 media_type = AVMEDIA_TYPE_VIDEO;
658 } else if (!strcmp (mimetype, "video/x-h264")) {
659 g_strlcpy (codec_name, "h264", CODEC_NAME_BUFFER_SIZE);
660 media_type = AVMEDIA_TYPE_VIDEO;
663 if (context != NULL) {
664 gst_maru_caps_with_codecname (codec_name, media_type, caps, context);
667 if (codec_name != NULL) {
668 GST_DEBUG ("The %s belongs to the caps %" GST_PTR_FORMAT, codec_name, caps);
670 GST_WARNING ("Couldn't figure out the name for caps %" GST_PTR_FORMAT, caps);
675 gst_maru_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx)
681 switch (media_type) {
682 case AVMEDIA_TYPE_VIDEO:
683 gst_maru_caps_to_pixfmt (caps, ctx, TRUE);
685 case AVMEDIA_TYPE_AUDIO:
686 gst_maru_caps_to_smpfmt (caps, ctx, TRUE);
694 gst_maru_video_caps_new (CodecContext *ctx, const char *name,
695 const char *mimetype, const char *fieldname, ...)
697 GstStructure *structure = NULL;
698 GstCaps *caps = NULL;
702 GST_LOG ("context: %p, name: %s, mimetype: %s", ctx, name, mimetype);
704 if (ctx != NULL && ctx->video.width != -1) {
707 caps = gst_caps_new_simple (mimetype,
708 "width", G_TYPE_INT, ctx->video.width,
709 "height", G_TYPE_INT, ctx->video.height, NULL);
711 num = ctx->video.fps_d / ctx->video.ticks_per_frame;
712 denom = ctx->video.fps_n;
715 GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num);
717 if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
718 GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom);
722 GST_LOG ("setting framerate: %d/%d", num, denom);
723 gst_caps_set_simple (caps,
724 "framerate", GST_TYPE_FRACTION, num, denom, NULL);
726 if (strcmp (name, "h263") == 0) {
727 /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
728 * because we want automatic negotiation to go as close to 320x240 as
730 const static gint widths[] = { 352, 704, 176, 1408, 128 };
731 const static gint heights[] = { 288, 576, 144, 1152, 96 };
733 gint n_sizes = G_N_ELEMENTS (widths);
735 caps = gst_caps_new_empty ();
736 for (i = 0; i < n_sizes; i++) {
737 temp = gst_caps_new_simple (mimetype,
738 "width", G_TYPE_INT, widths[i],
739 "height", G_TYPE_INT, heights[i],
740 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
742 gst_caps_append (caps, temp);
744 } else if (strcmp (name, "none") == 0) {
745 GST_LOG ("default caps");
749 /* no fixed caps or special restrictions applied;
750 * default unfixed setting */
752 GST_DEBUG ("Creating default caps");
753 caps = gst_caps_new_simple (mimetype,
754 "width", GST_TYPE_INT_RANGE, 16, 4096,
755 "height", GST_TYPE_INT_RANGE, 16, 4096,
756 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
759 for (i = 0; i < gst_caps_get_size (caps); i++) {
760 va_start (var_args, fieldname);
761 structure = gst_caps_get_structure (caps, i);
762 gst_structure_set_valist (structure, fieldname, var_args);
770 gst_maru_audio_caps_new (CodecContext *ctx, const char *name,
771 const char *mimetype, const char *fieldname, ...)
773 GstStructure *structure = NULL;
774 GstCaps *caps = NULL;
778 if (ctx != NULL && ctx->audio.channels != -1) {
779 GstAudioChannelPosition *pos;
780 guint64 channel_layout = ctx->audio.channel_layout;
782 if (channel_layout == 0) {
783 const guint64 default_channel_set[] = {
784 0, 0, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0,
785 CH_LAYOUT_5POINT1, 0, CH_LAYOUT_7POINT1
788 if (strcmp (name, "ac3") == 0) {
789 if (ctx->audio.channels > 0 &&
790 ctx->audio.channels < G_N_ELEMENTS (default_channel_set)) {
791 channel_layout = default_channel_set[ctx->audio.channels - 1];
798 caps = gst_caps_new_simple (mimetype,
799 "rate", G_TYPE_INT, ctx->audio.sample_rate,
800 "channels", G_TYPE_INT, ctx->audio.channels, NULL);
802 pos = gst_ff_channel_layout_to_gst (channel_layout, ctx->audio.channels);
804 gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
808 gint maxchannels = 2;
809 const gint *rates = NULL;
812 if (strcmp (name, "aac") == 0) {
814 } else if (g_str_has_prefix(name, "ac3")) {
815 const static gint l_rates[] = { 48000, 44100, 32000 };
817 n_rates = G_N_ELEMENTS (l_rates);
823 if (maxchannels == 1) {
824 caps = gst_caps_new_simple(mimetype,
825 "channels", G_TYPE_INT, maxchannels, NULL);
827 caps = gst_caps_new_simple(mimetype,
828 "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
832 GValue list = { 0, };
833 GstStructure *structure;
835 g_value_init(&list, GST_TYPE_LIST);
836 for (i = 0; i < n_rates; i++) {
839 g_value_init(&v, G_TYPE_INT);
840 g_value_set_int(&v, rates[i]);
841 gst_value_list_append_value(&list, &v);
844 structure = gst_caps_get_structure(caps, 0);
845 gst_structure_set_value(structure, "rate", &list);
846 g_value_unset(&list);
848 gst_caps_set_simple(caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
852 for (i = 0; i < gst_caps_get_size (caps); i++) {
853 va_start (var_args, fieldname);
854 structure = gst_caps_get_structure (caps, i);
855 gst_structure_set_valist (structure, fieldname, var_args);
863 gst_maru_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name)
865 GstCaps *caps = NULL;
867 int bpp = 0, depth = 0, endianness = 0;
868 gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
872 case PIX_FMT_YUV420P:
873 fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
875 case PIX_FMT_YUYV422:
876 fmt = GST_MAKE_FOURCC ('A', '4', '2', '0');
880 endianness = G_BIG_ENDIAN;
887 endianness = G_BIG_ENDIAN;
892 case PIX_FMT_YUV422P:
893 fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
895 case PIX_FMT_YUV444P:
896 fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
901 endianness = G_BIG_ENDIAN;
902 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
914 case PIX_FMT_YUV410P:
915 fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
917 case PIX_FMT_YUV411P:
918 fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'b');
922 endianness = G_BYTE_ORDER;
930 endianness = G_BYTE_ORDER;
943 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
944 "bpp", G_TYPE_INT, bpp,
945 "depth", G_TYPE_INT, depth,
946 "red_mask", G_TYPE_INT, r_mask,
947 "green_mask", G_TYPE_INT, g_mask,
948 "blue_mask", G_TYPE_INT, b_mask,
949 "alpha_mask", G_TYPE_INT, a_mask,
950 "endianness", G_TYPE_INT, endianness, NULL);
952 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
953 "bpp", G_TYPE_INT, bpp,
954 "depth", G_TYPE_INT, depth,
955 "red_mask", G_TYPE_INT, r_mask,
956 "green_mask", G_TYPE_INT, g_mask,
957 "blue_mask", G_TYPE_INT, b_mask,
958 "alpha_mask", G_TYPE_INT, a_mask,
959 "endianness", G_TYPE_INT, endianness, NULL);
962 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
963 "bpp", G_TYPE_INT, bpp,
964 "depth", G_TYPE_INT, depth,
965 "endianness", G_TYPE_INT, endianness, NULL);
971 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-yuv",
972 "format", GST_TYPE_FOURCC, fmt, NULL);
977 GST_DEBUG ("caps for pix_fmt=%d: %", GST_PTR_FORMAT, pix_fmt, caps);
979 GST_LOG ("No caps found for pix_fmt=%d", pix_fmt);
986 gst_maru_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name)
988 GstCaps *caps = NULL;
991 gboolean integer = TRUE;
992 gboolean signedness = FALSE;
994 switch (sample_fmt) {
996 case SAMPLE_FMT_S16P:
1000 case SAMPLE_FMT_S32:
1001 case SAMPLE_FMT_S32P:
1005 case SAMPLE_FMT_FLT:
1006 case SAMPLE_FMT_FLTP:
1010 case SAMPLE_FMT_DBL:
1011 case SAMPLE_FMT_DBLP:
1019 GST_DEBUG ("sample format: %d", sample_fmt);
1023 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-int",
1024 "signed", G_TYPE_BOOLEAN, signedness,
1025 "endianness", G_TYPE_INT, G_BYTE_ORDER,
1026 "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
1028 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-float",
1029 "endianness", G_TYPE_INT, G_BYTE_ORDER,
1030 "width", G_TYPE_INT, bpp, NULL);
1035 GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
1037 GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
1044 gst_maru_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode)
1046 GstCaps *caps = NULL;
1048 GST_LOG ("codec: %s, context: %p, encode: %d", name, ctx, encode);
1050 if (strcmp (name, "mpegvideo") == 0) {
1051 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1052 "mpegversion", G_TYPE_INT, 1,
1053 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1054 } else if (strcmp (name, "h263") == 0) {
1056 caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
1057 "variant", G_TYPE_STRING, "itu", NULL);
1059 caps = gst_maru_video_caps_new (ctx, "none", "video/x-h263",
1060 "variant", G_TYPE_STRING, "itu", NULL);
1062 } else if (strcmp (name, "h263p") == 0) {
1063 caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
1064 "variant", G_TYPE_STRING, "itu",
1065 "h263version", G_TYPE_STRING, "h263p", NULL);
1066 } else if (strcmp (name, "mpeg2video") == 0) {
1068 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1069 "mpegversion", G_TYPE_INT, 2,
1070 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1072 caps = gst_caps_new_simple ("video/mpeg",
1073 "mpegversion", GST_TYPE_INT_RANGE, 1, 2,
1074 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1076 } else if (strcmp (name, "mpeg4") == 0) {
1077 if (encode && ctx != NULL) {
1079 switch (ctx->codec_tag) {
1080 case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
1081 caps = gst_maru_video_caps_new (ctx, name, "video/x-divx",
1082 "divxversion", G_TYPE_INT, 5, NULL);
1084 case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
1086 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1087 "systemstream", G_TYPE_BOOLEAN, FALSE,
1088 "mpegversion", G_TYPE_INT, 4, NULL);
1092 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1093 "mpegversion", G_TYPE_INT, 4,
1094 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1096 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1097 "mpegversion", G_TYPE_INT, 4,
1098 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1100 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1101 "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
1102 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1103 "video/x-xvid", NULL));
1104 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1105 "video/x-3ivx", NULL));
1108 } else if ((strcmp (name, "h264") == 0) || (strcmp (name, "libx264") == 0)) {
1109 caps = gst_maru_video_caps_new (ctx, name, "video/x-h264", NULL);
1110 } else if (g_str_has_prefix(name, "msmpeg4")) {
1111 // msmpeg4v1,m msmpeg4v2, msmpeg4
1114 if (strcmp (name, "msmpeg4v1") == 0) {
1116 } else if (strcmp (name, "msmpeg4v2") == 0) {
1122 caps = gst_maru_video_caps_new (ctx, name, "video/x-msmpeg",
1123 "msmpegversion", G_TYPE_INT, version, NULL);
1124 if (!encode && !strcmp (name, "msmpeg4")) {
1125 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1126 "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
1128 } else if (strcmp (name, "wmv3") == 0) {
1129 caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1130 "wmvversion", G_TYPE_INT, 3, NULL);
1131 } else if (strcmp (name, "vc1") == 0) {
1132 caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1133 "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
1134 GST_MAKE_FOURCC ('W', 'V', 'C', '1'), NULL);
1135 } else if (strcmp (name, "aac") == 0) {
1136 caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg", NULL);
1138 GValue arr = { 0, };
1139 GValue item = { 0, };
1141 g_value_init (&arr, GST_TYPE_LIST);
1142 g_value_init (&item, G_TYPE_INT);
1143 g_value_set_int (&item, 2);
1144 gst_value_list_append_value (&arr, &item);
1145 g_value_set_int (&item, 4);
1146 gst_value_list_append_value (&arr, &item);
1147 g_value_unset (&item);
1149 gst_caps_set_value (caps, "mpegversion", &arr);
1150 g_value_unset (&arr);
1152 g_value_init (&arr, GST_TYPE_LIST);
1153 g_value_init (&item, G_TYPE_STRING);
1154 g_value_set_string (&item, "raw");
1155 gst_value_list_append_value (&arr, &item);
1156 g_value_set_string (&item, "adts");
1157 gst_value_list_append_value (&arr, &item);
1158 g_value_set_string (&item, "adif");
1159 gst_value_list_append_value (&arr, &item);
1160 g_value_unset (&item);
1162 gst_caps_set_value (caps, "stream-format", &arr);
1163 g_value_unset (&arr);
1165 gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT, 4,
1166 "stream-format", G_TYPE_STRING, "raw",
1167 "base-profile", G_TYPE_STRING, "lc", NULL);
1169 if (ctx && ctx->codecdata_size > 0) {
1170 gst_codec_utils_aac_caps_set_level_and_profile (caps,
1171 ctx->codecdata, ctx->codecdata_size);
1174 } else if (strcmp (name, "ac3") == 0) {
1175 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-ac3", NULL);
1176 } else if (strcmp (name, "mp3") == 0) {
1178 caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg",
1179 "mpegversion", G_TYPE_INT, 1,
1180 "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1182 caps = gst_caps_new_simple("audio/mpeg",
1183 "mpegversion", G_TYPE_INT, 1,
1184 "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1186 } else if (strcmp (name, "mp3adu") == 0) {
1189 mime_type = g_strdup_printf ("audio/x-gst_ff-%s", name);
1190 caps = gst_maru_audio_caps_new (ctx, name, mime_type, NULL);
1195 } else if (g_str_has_prefix(name, "wmav")) {
1197 if (strcmp (name, "wmav2") == 0) {
1200 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-wma", "wmaversion",
1201 G_TYPE_INT, version, "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
1202 "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
1204 GST_ERROR("failed to new caps for %s", name);
1208 if (ctx && ctx->codecdata_size > 0) {
1209 GST_DEBUG ("codec_data size %d", ctx->codecdata_size);
1211 GstBuffer *data = gst_buffer_new_and_alloc (ctx->codecdata_size);
1213 memcpy (GST_BUFFER_DATA(data), ctx->codecdata, ctx->codecdata_size);
1214 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, data, NULL);
1215 gst_buffer_unref (data);
1217 GST_LOG ("caps for codec %s %" GST_PTR_FORMAT, name, caps);
1219 GST_LOG ("No caps found for codec %s", name);
1225 typedef struct PixFmtInfo
1227 uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
1228 uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
1231 static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
1234 gst_maru_init_pix_fmt_info (void)
1236 pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1,
1237 pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
1239 pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
1240 pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
1242 pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
1243 pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
1245 pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
1246 pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
1248 pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
1249 pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
1251 pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
1252 pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
1255 pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
1256 pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
1258 pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
1259 pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
1261 pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
1262 pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
1264 pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
1265 pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
1267 pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
1268 pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
1272 gst_maru_avpicture_size (int pix_fmt, int width, int height)
1274 int size, w2, h2, size2;
1275 int stride, stride2;
1279 pinfo = &pix_fmt_info[pix_fmt];
1282 case PIX_FMT_YUV420P:
1283 case PIX_FMT_YUV422P:
1284 case PIX_FMT_YUV444P:
1285 case PIX_FMT_YUV410P:
1286 case PIX_FMT_YUV411P:
1287 stride = ROUND_UP_4(width);
1288 h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
1290 w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
1291 stride2 = ROUND_UP_4(w2);
1292 h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
1293 size2 = stride2 * h2;
1294 fsize = size + 2 * size2;
1298 stride = ROUND_UP_4 (width * 3);
1299 fsize = stride * height;
1303 fsize = stride * height;
1305 case PIX_FMT_RGB555:
1306 case PIX_FMT_RGB565:
1307 stride = ROUND_UP_4 (width * 2);
1308 fsize = stride * height;
1319 gst_maru_align_size (int buf_size)
1323 align_size = buf_size / 1024;
1325 for (i = 0; i < 14; i++) {
1326 if (align_size < (1 << i)) {
1327 align_size = 1024 * (1 << i);