2 * GStreamer codec plugin for Tizen Emulator.
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd. All rights reserved.
7 * KiTae Kim <kt920.kim@samsung.com>
8 * SeokYeon Hwang <syeon.hwang@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library; if not, write to the
23 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 * Boston, MA 02111-1307, USA.
31 #include "gstmaruutils.h"
32 #include <gst/audio/multichannel.h>
33 #include <gst/pbutils/codec-utils.h>
36 gst_maru_smpfmt_depth (int smp_fmt)
55 GST_ERROR ("Unhandled sample format !");
66 GstAudioChannelPosition gst;
67 } _ff_to_gst_layout[] = {
69 CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
70 CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
71 CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
72 CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, {
73 CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, {
74 CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
75 CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, {
76 CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, {
77 CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
78 CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, {
79 CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, {
80 CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
81 CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
82 CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
83 CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
84 CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
85 CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, {
86 CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, {
87 CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, {
88 CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}
91 static GstAudioChannelPosition *
92 gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels)
94 guint nchannels = 0, i, j;
95 GstAudioChannelPosition *pos = NULL;
96 gboolean none_layout = FALSE;
98 for (i = 0; i < 64; i++) {
99 if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) {
104 if (channel_layout == 0) {
105 nchannels = channels;
109 if (nchannels != channels) {
110 GST_ERROR ("Number of channels is different (%u != %u)", channels,
115 pos = g_new (GstAudioChannelPosition, nchannels);
117 for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) {
118 if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) {
119 pos[j++] = _ff_to_gst_layout[i].gst;
121 if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE) {
127 if (j != nchannels) {
128 GST_WARNING ("Unknown channels in channel layout - assuming NONE layout");
132 if (!none_layout && !gst_audio_check_channel_positions (pos, nchannels)) {
133 GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT
134 " - assuming NONE layout", channel_layout);
139 if (nchannels == 1) {
140 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO;
141 } else if (nchannels == 2) {
142 pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
143 pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
144 } else if (channel_layout == 0) {
148 for (i = 0; i < nchannels; i++) {
149 pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
154 if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) {
155 GST_DEBUG ("mono common case; won't set channel positions");
158 } else if (nchannels == 2 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT
159 && pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) {
160 GST_DEBUG ("stereo common case; won't set channel positions");
169 gst_maru_codectype_to_video_caps (CodecContext *ctx, const char *name,
170 gboolean encode, CodecElement *codec)
174 GST_DEBUG ("context: %p, codec: %s, encode: %d, pixel format: %d",
175 ctx, name, encode, ctx->video.pix_fmt);
178 caps = gst_maru_pixfmt_to_caps (ctx->video.pix_fmt, ctx, name);
184 caps = gst_caps_new_empty ();
185 for (i = 0; i <= PIX_FMT_NB; i++) {
186 temp = gst_maru_pixfmt_to_caps (i, encode ? &ctx : NULL, name);
188 gst_caps_append (caps, temp);
197 gst_maru_codectype_to_audio_caps (CodecContext *ctx, const char *name,
198 gboolean encode, CodecElement *codec)
200 GstCaps *caps = NULL;
202 GST_DEBUG ("context: %p, codec: %s, encode: %d, codec: %p",
203 ctx, name, encode, codec);
206 caps = gst_maru_smpfmt_to_caps (ctx->audio.sample_fmt, ctx, name);
207 } else if (codec && codec->sample_fmts[0] != -1){
211 caps = gst_caps_new_empty ();
212 for (i = 0; codec->sample_fmts[i] != -1; i++) {
214 gst_maru_smpfmt_to_caps (codec->sample_fmts[i], ctx, name);
216 gst_caps_append (caps, temp);
222 CodecContext ctx = {{0}, {0}, 0};
224 ctx.audio.channels = -1;
225 caps = gst_caps_new_empty ();
226 for (i = 0; i <= SAMPLE_FMT_DBL; i++) {
227 temp = gst_maru_smpfmt_to_caps (i, encode ? &ctx : NULL, name);
229 gst_caps_append (caps, temp);
238 gst_maru_codectype_to_caps (int media_type, CodecContext *ctx,
239 const char *name, gboolean encode)
243 switch (media_type) {
244 case AVMEDIA_TYPE_VIDEO:
246 gst_maru_codectype_to_video_caps (ctx, name, encode, NULL);
248 case AVMEDIA_TYPE_AUDIO:
250 gst_maru_codectype_to_audio_caps (ctx, name, encode, NULL);
261 gst_maru_caps_to_pixfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
265 const GValue *par = NULL;
267 GST_DEBUG ("converting caps %" GST_PTR_FORMAT, caps);
268 g_return_if_fail (gst_caps_get_size (caps) == 1);
269 str = gst_caps_get_structure (caps, 0);
271 gst_structure_get_int (str, "width", &ctx->video.width);
272 gst_structure_get_int (str, "height", &ctx->video.height);
273 gst_structure_get_int (str, "bpp", &ctx->video.bpp);
275 fps = gst_structure_get_value (str, "framerate");
276 if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
277 ctx->video.fps_d = gst_value_get_fraction_numerator (fps);
278 ctx->video.fps_n = gst_value_get_fraction_denominator (fps);
279 ctx->video.ticks_per_frame = 1;
281 GST_DEBUG ("setting framerate %d/%d = %lf",
282 ctx->video.fps_d, ctx->video.fps_n,
283 1. * ctx->video.fps_d / ctx->video.fps_n);
286 par = gst_structure_get_value (str, "pixel-aspect-ratio");
287 if (par && GST_VALUE_HOLDS_FRACTION (par)) {
288 ctx->video.par_n = gst_value_get_fraction_numerator (par);
289 ctx->video.par_d = gst_value_get_fraction_denominator (par);
296 g_return_if_fail (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
298 if (strcmp (gst_structure_get_name (str), "video/x-raw-yuv") == 0) {
301 if (gst_structure_get_fourcc (str, "format", &fourcc)) {
303 case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
304 ctx->video.pix_fmt = PIX_FMT_YUYV422;
306 case GST_MAKE_FOURCC ('I', '4', '2', '0'):
307 ctx->video.pix_fmt = PIX_FMT_YUV420P;
309 case GST_MAKE_FOURCC ('A', '4', '2', '0'):
310 ctx->video.pix_fmt = PIX_FMT_YUVA420P;
312 case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
313 ctx->video.pix_fmt = PIX_FMT_YUV411P;
315 case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
316 ctx->video.pix_fmt = PIX_FMT_YUV422P;
318 case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'):
319 ctx->video.pix_fmt = PIX_FMT_YUV410P;
323 // printf ("get pixel format: %d, fourcc: %d\n", ctx->video.pix_fmt, fourcc);
324 } else if (strcmp (gst_structure_get_name (str), "video/x-raw-rgb") == 0) {
325 gint bpp = 0, rmask = 0, endianness = 0;
327 if (gst_structure_get_int (str, "bpp", &bpp) &&
328 gst_structure_get_int (str, "endianness", &endianness)) {
329 if (gst_structure_get_int (str, "red_mask", &rmask)) {
332 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
333 if (rmask == 0x00ff0000) {
335 if (rmask == 0x00ff0000) {
337 ctx->video.pix_fmt = PIX_FMT_RGB32;
341 if (rmask == 0x0000FF) {
342 ctx->video.pix_fmt = PIX_FMT_BGR24;
344 ctx->video.pix_fmt = PIX_FMT_RGB24;
348 if (endianness == G_BYTE_ORDER) {
349 ctx->video.pix_fmt = PIX_FMT_RGB565;
353 if (endianness == G_BYTE_ORDER) {
354 ctx->video.pix_fmt = PIX_FMT_RGB555;
363 ctx->video.pix_fmt = PIX_FMT_PAL8;
367 } else if (strcmp (gst_structure_get_name (str), "video/x-raw-gray") == 0) {
370 if (gst_structure_get_int (str, "bpp", &bpp)) {
373 ctx->video.pix_fmt = PIX_FMT_GRAY8;
381 gst_maru_caps_to_smpfmt (const GstCaps *caps, CodecContext *ctx, gboolean raw)
384 gint depth = 0, width = 0, endianness = 0;
385 gboolean signedness = FALSE;
388 g_return_if_fail (gst_caps_get_size (caps) == 1);
389 str = gst_caps_get_structure (caps, 0);
391 gst_structure_get_int (str, "channels", &ctx->audio.channels);
392 gst_structure_get_int (str, "rate", &ctx->audio.sample_rate);
393 gst_structure_get_int (str, "block_align", &ctx->audio.block_align);
394 // gst_structure_get_int (str, "bitrate", &ctx->audio.bit_rate);
395 gst_structure_get_int (str, "bitrate", &ctx->bit_rate);
401 name = gst_structure_get_name (str);
403 if (!strcmp (name, "audio/x-raw-float")) {
404 if (gst_structure_get_int (str, "width", &width) &&
405 gst_structure_get_int (str, "endianness", &endianness)) {
406 if (endianness == G_BYTE_ORDER) {
408 ctx->audio.sample_fmt = SAMPLE_FMT_FLT;
409 } else if (width == 64) {
410 ctx->audio.sample_fmt = SAMPLE_FMT_DBL;
415 if (gst_structure_get_int (str, "width", &width) &&
416 gst_structure_get_int (str, "depth", &depth) &&
417 gst_structure_get_boolean (str, "signed", &signedness) &&
418 gst_structure_get_int (str, "endianness", &endianness)) {
419 if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) {
420 if ((width == 16) && (depth == 16)) {
421 ctx->audio.sample_fmt = SAMPLE_FMT_S16;
422 } else if ((width == 32) && (depth == 32)) {
423 ctx->audio.sample_fmt = SAMPLE_FMT_S32;
431 gst_maru_caps_with_codecname (const char *name, int media_type,
432 const GstCaps *caps, CodecContext *ctx)
434 GstStructure *structure;
436 const GstBuffer *buf;
438 if (!ctx || !gst_caps_get_size (caps)) {
442 structure = gst_caps_get_structure (caps, 0);
444 if ((value = gst_structure_get_value (structure, "codec_data"))) {
448 buf = GST_BUFFER_CAST (gst_value_get_mini_object (value));
449 size = GST_BUFFER_SIZE (buf);
450 data = GST_BUFFER_DATA (buf);
451 GST_DEBUG ("extradata: %p, size: %d\n", data, size);
453 if (ctx->codecdata) {
454 g_free (ctx->codecdata);
458 g_malloc0 (GST_ROUND_UP_16 (size + FF_INPUT_BUFFER_PADDING_SIZE));
459 memcpy (ctx->codecdata, data, size);
460 ctx->codecdata_size = size;
462 if ((strcmp (name, "vc1") == 0) && size > 0 && data[0] == 0) {
463 ctx->codecdata[0] = (guint8) size;
465 } else if (ctx->codecdata == NULL) {
466 ctx->codecdata_size = 0;
467 ctx->codecdata = g_malloc0 (GST_ROUND_UP_16(FF_INPUT_BUFFER_PADDING_SIZE));
468 GST_DEBUG ("no extra data.\n");
471 if ((strcmp (name, "mpeg4") == 0)) {
472 const gchar *mime = gst_structure_get_name (structure);
474 if (!strcmp (mime, "video/x-divx")) {
475 ctx->codec_tag = GST_MAKE_FOURCC ('D', 'I', 'V', 'X');
476 } else if (!strcmp (mime, "video/x-xvid")) {
477 ctx->codec_tag = GST_MAKE_FOURCC ('X', 'V', 'I', 'D');
478 } else if (!strcmp (mime, "video/x-3ivx")) {
479 ctx->codec_tag = GST_MAKE_FOURCC ('3', 'I', 'V', '1');
480 } else if (!strcmp (mime, "video/mpeg")) {
481 ctx->codec_tag = GST_MAKE_FOURCC ('m', 'p', '4', 'v');
484 } else if (strcmp (name, "h263p") == 0) {
487 if (!gst_structure_get_boolean (structure, "annex-f", &val) || val) {
488 ctx->flags |= CODEC_FLAG_4MV;
490 ctx->flags &= ~CODEC_FLAG_4MV;
492 if ((!gst_structure_get_boolean (structure, "annex-i", &val) || val) &&
493 (!gst_structure_get_boolean (structure, "annex-t", &val) || val)) {
494 ctx->flags |= CODEC_FLAG_AC_PRED;
496 ctx->flags &= ~CODEC_FLAG_AC_PRED;
498 if ((!gst_structure_get_boolean (structure, "annex-j", &val) || val)) {
499 ctx->flags |= CODEC_FLAG_LOOP_FILTER;
501 ctx->flags &= ~CODEC_FLAG_LOOP_FILTER;
508 if (!gst_caps_is_fixed (caps)) {
512 switch (media_type) {
513 case AVMEDIA_TYPE_VIDEO:
514 gst_maru_caps_to_pixfmt (caps, ctx, FALSE);
517 case AVMEDIA_TYPE_AUDIO:
518 gst_maru_caps_to_smpfmt (caps, ctx, FALSE);
526 gst_maru_caps_to_codecname (const GstCaps *caps, gchar *codec_name, CodecContext *context)
528 const gchar *mimetype;
529 const GstStructure *str;
531 str = gst_caps_get_structure (caps, 0);
533 mimetype = gst_structure_get_name (str);
535 if (!strcmp (mimetype, "video/x-wmv")) {
538 if (gst_structure_get_int (str, "wmvversion", &wmvversion)) {
539 switch (wmvversion) {
541 g_strlcpy(codec_name, "wmv1", 32);
544 g_strlcpy(codec_name, "wmv2", 32);
550 g_strlcpy(codec_name, "wmv3", 32);
552 if (gst_structure_get_fourcc (str, "format", &fourcc)) {
553 if ((fourcc == GST_MAKE_FOURCC ('W', 'V', 'C', '1')) ||
554 (fourcc == GST_MAKE_FOURCC ('W', 'M', 'V', 'A'))) {
555 g_strlcpy(codec_name, "vc1", 32);
565 if (context != NULL) {
567 context->codec_type = CODEC_TYPE_VIDEO;
568 } else if (audio == TRUE) {
569 context->codec_type = CODEC_TYPE_AUDIO;
571 context->codec_type = CODEC_TYPE_UNKNOWN;
573 context->codec_id = id;
574 gst_maru_caps_with_codecname (name, context->codec_type, caps, context);
578 if (codec_name != NULL) {
579 GST_DEBUG ("The %s belongs to the caps %" GST_PTR_FORMAT, codec_name, caps);
581 GST_WARNING ("Couldn't figure out the name for caps %" GST_PTR_FORMAT, caps);
586 gst_maru_caps_with_codectype (int media_type, const GstCaps *caps, CodecContext *ctx)
592 switch (media_type) {
593 case AVMEDIA_TYPE_VIDEO:
594 gst_maru_caps_to_pixfmt (caps, ctx, TRUE);
596 case AVMEDIA_TYPE_AUDIO:
597 gst_maru_caps_to_smpfmt (caps, ctx, TRUE);
605 gst_maru_video_caps_new (CodecContext *ctx, const char *name,
606 const char *mimetype, const char *fieldname, ...)
608 GstStructure *structure = NULL;
609 GstCaps *caps = NULL;
613 GST_LOG ("context: %p, name: %s, mimetype: %s", ctx, name, mimetype);
615 if (ctx != NULL && ctx->video.width != -1) {
618 caps = gst_caps_new_simple (mimetype,
619 "width", G_TYPE_INT, ctx->video.width,
620 "height", G_TYPE_INT, ctx->video.height, NULL);
622 num = ctx->video.fps_d / ctx->video.ticks_per_frame;
623 denom = ctx->video.fps_n;
626 GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num);
628 if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) {
629 GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom);
633 GST_LOG ("setting framerate: %d/%d", num, denom);
634 gst_caps_set_simple (caps,
635 "framerate", GST_TYPE_FRACTION, num, denom, NULL);
637 if (strcmp (name, "h263") == 0) {
638 /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered
639 * because we want automatic negotiation to go as close to 320x240 as
641 const static gint widths[] = { 352, 704, 176, 1408, 128 };
642 const static gint heights[] = { 288, 576, 144, 1152, 96 };
644 gint n_sizes = G_N_ELEMENTS (widths);
646 caps = gst_caps_new_empty ();
647 for (i = 0; i < n_sizes; i++) {
648 temp = gst_caps_new_simple (mimetype,
649 "width", G_TYPE_INT, widths[i],
650 "height", G_TYPE_INT, heights[i],
651 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
653 gst_caps_append (caps, temp);
655 } else if (strcmp (name, "none") == 0) {
656 GST_LOG ("default caps");
660 /* no fixed caps or special restrictions applied;
661 * default unfixed setting */
663 GST_DEBUG ("Creating default caps");
664 caps = gst_caps_new_simple (mimetype,
665 "width", GST_TYPE_INT_RANGE, 16, 4096,
666 "height", GST_TYPE_INT_RANGE, 16, 4096,
667 "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
670 for (i = 0; i < gst_caps_get_size (caps); i++) {
671 va_start (var_args, fieldname);
672 structure = gst_caps_get_structure (caps, i);
673 gst_structure_set_valist (structure, fieldname, var_args);
681 gst_maru_audio_caps_new (CodecContext *ctx, const char *name,
682 const char *mimetype, const char *fieldname, ...)
684 GstStructure *structure = NULL;
685 GstCaps *caps = NULL;
689 if (ctx != NULL && ctx->audio.channels != -1) {
690 GstAudioChannelPosition *pos;
691 guint64 channel_layout = ctx->audio.channel_layout;
693 if (channel_layout == 0) {
694 const guint64 default_channel_set[] = {
695 0, 0, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0,
696 CH_LAYOUT_5POINT1, 0, CH_LAYOUT_7POINT1
699 if (strcmp (name, "ac3") == 0) {
700 if (ctx->audio.channels > 0 &&
701 ctx->audio.channels < G_N_ELEMENTS (default_channel_set)) {
702 channel_layout = default_channel_set[ctx->audio.channels - 1];
709 caps = gst_caps_new_simple (mimetype,
710 "rate", G_TYPE_INT, ctx->audio.sample_rate,
711 "channels", G_TYPE_INT, ctx->audio.channels, NULL);
713 pos = gst_ff_channel_layout_to_gst (channel_layout, ctx->audio.channels);
715 gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
719 gint maxchannels = 2;
720 const gint *rates = NULL;
723 if (strcmp (name, "aac") == 0) {
725 } else if (g_str_has_prefix(name, "ac3")) {
726 const static gint l_rates[] = { 48000, 44100, 32000 };
728 n_rates = G_N_ELEMENTS (l_rates);
734 if (maxchannels == 1) {
735 caps = gst_caps_new_simple(mimetype,
736 "channels", G_TYPE_INT, maxchannels, NULL);
738 caps = gst_caps_new_simple(mimetype,
739 "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL);
743 GValue list = { 0, };
744 GstStructure *structure;
746 g_value_init(&list, GST_TYPE_LIST);
747 for (i = 0; i < n_rates; i++) {
750 g_value_init(&v, G_TYPE_INT);
751 g_value_set_int(&v, rates[i]);
752 gst_value_list_append_value(&list, &v);
755 structure = gst_caps_get_structure(caps, 0);
756 gst_structure_set_value(structure, "rate", &list);
757 g_value_unset(&list);
759 gst_caps_set_simple(caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL);
763 for (i = 0; i < gst_caps_get_size (caps); i++) {
764 va_start (var_args, fieldname);
765 structure = gst_caps_get_structure (caps, i);
766 gst_structure_set_valist (structure, fieldname, var_args);
774 gst_maru_pixfmt_to_caps (enum PixelFormat pix_fmt, CodecContext *ctx, const char *name)
776 GstCaps *caps = NULL;
778 int bpp = 0, depth = 0, endianness = 0;
779 gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0;
783 case PIX_FMT_YUV420P:
784 fmt = GST_MAKE_FOURCC ('I', '4', '2', '0');
786 case PIX_FMT_YUYV422:
787 fmt = GST_MAKE_FOURCC ('A', '4', '2', '0');
791 endianness = G_BIG_ENDIAN;
798 endianness = G_BIG_ENDIAN;
803 case PIX_FMT_YUV422P:
804 fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
806 case PIX_FMT_YUV444P:
807 fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4');
812 endianness = G_BIG_ENDIAN;
813 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
825 case PIX_FMT_YUV410P:
826 fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
828 case PIX_FMT_YUV411P:
829 fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'b');
833 endianness = G_BYTE_ORDER;
841 endianness = G_BYTE_ORDER;
854 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
855 "bpp", G_TYPE_INT, bpp,
856 "depth", G_TYPE_INT, depth,
857 "red_mask", G_TYPE_INT, r_mask,
858 "green_mask", G_TYPE_INT, g_mask,
859 "blue_mask", G_TYPE_INT, b_mask,
860 "alpha_mask", G_TYPE_INT, a_mask,
861 "endianness", G_TYPE_INT, endianness, NULL);
863 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
864 "bpp", G_TYPE_INT, bpp,
865 "depth", G_TYPE_INT, depth,
866 "red_mask", G_TYPE_INT, r_mask,
867 "green_mask", G_TYPE_INT, g_mask,
868 "blue_mask", G_TYPE_INT, b_mask,
869 "alpha_mask", G_TYPE_INT, a_mask,
870 "endianness", G_TYPE_INT, endianness, NULL);
873 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-rgb",
874 "bpp", G_TYPE_INT, bpp,
875 "depth", G_TYPE_INT, depth,
876 "endianness", G_TYPE_INT, endianness, NULL);
882 caps = gst_maru_video_caps_new (ctx, name, "video/x-raw-yuv",
883 "format", GST_TYPE_FOURCC, fmt, NULL);
888 GST_DEBUG ("caps for pix_fmt=%d: %", GST_PTR_FORMAT, pix_fmt, caps);
890 GST_LOG ("No caps found for pix_fmt=%d", pix_fmt);
897 gst_maru_smpfmt_to_caps (int8_t sample_fmt, CodecContext *ctx, const char *name)
899 GstCaps *caps = NULL;
902 gboolean integer = TRUE;
903 gboolean signedness = FALSE;
905 switch (sample_fmt) {
928 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-int",
929 "signed", G_TYPE_BOOLEAN, signedness,
930 "endianness", G_TYPE_INT, G_BYTE_ORDER,
931 "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL);
933 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-raw-float",
934 "endianness", G_TYPE_INT, G_BYTE_ORDER,
935 "width", G_TYPE_INT, bpp, NULL);
940 GST_LOG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps);
942 GST_LOG ("No caps found for sample_fmt=%d", sample_fmt);
949 gst_maru_codecname_to_caps (const char *name, CodecContext *ctx, gboolean encode)
951 GstCaps *caps = NULL;
953 GST_LOG ("codec: %s, context: %p, encode: %d", name, ctx, encode);
955 if (strcmp (name, "mpegvideo") == 0) {
956 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
957 "mpegversion", G_TYPE_INT, 1,
958 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
959 } else if (strcmp (name, "h263") == 0) {
961 caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
962 "variant", G_TYPE_STRING, "itu", NULL);
964 caps = gst_maru_video_caps_new (ctx, "none", "video/x-h263",
965 "variant", G_TYPE_STRING, "itu", NULL);
967 } else if (strcmp (name, "h263p") == 0) {
968 caps = gst_maru_video_caps_new (ctx, name, "video/x-h263",
969 "variant", G_TYPE_STRING, "itu",
970 "h263version", G_TYPE_STRING, "h263p", NULL);
973 gst_caps_set_simple (caps,
974 "annex-f", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_4MV,
975 "annex-j", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_LOOP_FILTER,
976 "annex-i", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
977 "annex-t", G_TYPE_BOOLEAN, ctx->flags & CODEC_FLAG_AC_PRED,
981 } else if (strcmp (name, "mpeg4") == 0) {
982 if (encode && ctx != NULL) {
984 switch (ctx->codec_tag) {
985 case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'):
986 caps = gst_maru_video_caps_new (ctx, name, "video/x-divx",
987 "divxversion", G_TYPE_INT, 5, NULL);
989 case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
991 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
992 "systemstream", G_TYPE_BOOLEAN, FALSE,
993 "mpegversion", G_TYPE_INT, 4, NULL);
997 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
998 "mpegversion", G_TYPE_INT, 4,
999 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1001 caps = gst_maru_video_caps_new (ctx, name, "video/mpeg",
1002 "mpegversion", G_TYPE_INT, 4,
1003 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1005 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1006 "video/x-divx", "divxversion", GST_TYPE_INT_RANGE, 4, 5, NULL));
1007 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1008 "video/x-xvid", NULL));
1009 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1010 "video/x-3ivx", NULL));
1013 } else if (strcmp (name, "h264") == 0) {
1014 caps = gst_maru_video_caps_new (ctx, name, "video/x-h264", NULL);
1015 } else if (g_str_has_prefix(name, "msmpeg4")) {
1016 // msmpeg4v1,m msmpeg4v2, msmpeg4
1019 if (strcmp (name, "msmpeg4v1") == 0) {
1021 } else if (strcmp (name, "msmpeg4v2") == 0) {
1027 caps = gst_maru_video_caps_new (ctx, name, "video/x-msmpeg",
1028 "msmpegversion", G_TYPE_INT, version, NULL);
1029 if (!encode && !strcmp (name, "msmpeg4")) {
1030 gst_caps_append (caps, gst_maru_video_caps_new (ctx, name,
1031 "video/x-divx", "divxversion", G_TYPE_INT, 3, NULL));
1033 } else if (strcmp (name, "wmv3") == 0) {
1034 caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1035 "wmvversion", G_TYPE_INT, 3, NULL);
1036 } else if (strcmp (name, "vc1") == 0) {
1037 caps = gst_maru_video_caps_new (ctx, name, "video/x-wmv",
1038 "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC,
1039 GST_MAKE_FOURCC ('W', 'V', 'C', '1'), NULL);
1041 } else if (strcmp (name, "vp3") == 0) {
1042 mime_type = g_strdup ("video/x-vp3");
1043 } else if (strcmp (name, "vp8") == 0) {
1044 mime_type = g_strdup ("video/x-vp8");
1046 } else if (strcmp (name, "aac") == 0) {
1047 caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg", NULL);
1049 GValue arr = { 0, };
1050 GValue item = { 0, };
1052 g_value_init (&arr, GST_TYPE_LIST);
1053 g_value_init (&item, G_TYPE_INT);
1054 g_value_set_int (&item, 2);
1055 gst_value_list_append_value (&arr, &item);
1056 g_value_set_int (&item, 4);
1057 gst_value_list_append_value (&arr, &item);
1058 g_value_unset (&item);
1060 gst_caps_set_value (caps, "mpegversion", &arr);
1061 g_value_unset (&arr);
1063 g_value_init (&arr, GST_TYPE_LIST);
1064 g_value_init (&item, G_TYPE_STRING);
1065 g_value_set_string (&item, "raw");
1066 gst_value_list_append_value (&arr, &item);
1067 g_value_set_string (&item, "adts");
1068 gst_value_list_append_value (&arr, &item);
1069 g_value_set_string (&item, "adif");
1070 gst_value_list_append_value (&arr, &item);
1071 g_value_unset (&item);
1073 gst_caps_set_value (caps, "stream-format", &arr);
1074 g_value_unset (&arr);
1076 gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT, 4,
1077 "stream-format", G_TYPE_STRING, "raw",
1078 "base-profile", G_TYPE_STRING, "lc", NULL);
1080 if (ctx && ctx->codecdata_size > 0) {
1081 gst_codec_utils_aac_caps_set_level_and_profile (caps,
1082 ctx->codecdata, ctx->codecdata_size);
1085 } else if (strcmp (name, "ac3") == 0) {
1086 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-ac3", NULL);
1087 } else if (strcmp (name, "mp3") == 0) {
1089 caps = gst_maru_audio_caps_new (ctx, name, "audio/mpeg",
1090 "mpegversion", G_TYPE_INT, 1,
1091 "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1093 caps = gst_caps_new_simple("audio/mpeg",
1094 "mpegversion", G_TYPE_INT, 1,
1095 "layer", GST_TYPE_INT_RANGE, 1, 3, NULL);
1097 } else if (strcmp (name, "mp3adu") == 0) {
1100 mime_type = g_strdup_printf ("audio/x-gst_ff-%s", name);
1101 caps = gst_maru_audio_caps_new (ctx, name, mime_type, NULL);
1106 } else if (g_str_has_prefix(name, "wmav")) {
1108 if (strcmp (name, "wmav2") == 0) {
1111 caps = gst_maru_audio_caps_new (ctx, name, "audio/x-wma", "wmaversion",
1112 G_TYPE_INT, version, "block_align", GST_TYPE_INT_RANGE, 0, G_MAXINT,
1113 "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL);
1115 GST_ERROR("failed to new caps for %s.\n", name);
1121 typedef struct PixFmtInfo
1123 uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */
1124 uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */
1127 static PixFmtInfo pix_fmt_info[PIX_FMT_NB];
1130 gst_maru_init_pix_fmt_info (void)
1132 pix_fmt_info[PIX_FMT_YUV420P].x_chroma_shift = 1,
1133 pix_fmt_info[PIX_FMT_YUV420P].y_chroma_shift = 1;
1135 pix_fmt_info[PIX_FMT_YUV422P].x_chroma_shift = 1;
1136 pix_fmt_info[PIX_FMT_YUV422P].y_chroma_shift = 0;
1138 pix_fmt_info[PIX_FMT_YUV444P].x_chroma_shift = 0;
1139 pix_fmt_info[PIX_FMT_YUV444P].y_chroma_shift = 0;
1141 pix_fmt_info[PIX_FMT_YUYV422].x_chroma_shift = 1;
1142 pix_fmt_info[PIX_FMT_YUYV422].y_chroma_shift = 0;
1144 pix_fmt_info[PIX_FMT_YUV410P].x_chroma_shift = 2;
1145 pix_fmt_info[PIX_FMT_YUV410P].y_chroma_shift = 2;
1147 pix_fmt_info[PIX_FMT_YUV411P].x_chroma_shift = 2;
1148 pix_fmt_info[PIX_FMT_YUV411P].y_chroma_shift = 0;
1151 pix_fmt_info[PIX_FMT_RGB24].x_chroma_shift = 0;
1152 pix_fmt_info[PIX_FMT_RGB24].y_chroma_shift = 0;
1154 pix_fmt_info[PIX_FMT_BGR24].x_chroma_shift = 0;
1155 pix_fmt_info[PIX_FMT_BGR24].y_chroma_shift = 0;
1157 pix_fmt_info[PIX_FMT_RGB32].x_chroma_shift = 0;
1158 pix_fmt_info[PIX_FMT_RGB32].y_chroma_shift = 0;
1160 pix_fmt_info[PIX_FMT_RGB565].x_chroma_shift = 0;
1161 pix_fmt_info[PIX_FMT_RGB565].y_chroma_shift = 0;
1163 pix_fmt_info[PIX_FMT_RGB555].x_chroma_shift = 0;
1164 pix_fmt_info[PIX_FMT_RGB555].y_chroma_shift = 0;
1168 gst_maru_avpicture_size (int pix_fmt, int width, int height)
1170 int size, w2, h2, size2;
1171 int stride, stride2;
1175 pinfo = &pix_fmt_info[pix_fmt];
1178 case PIX_FMT_YUV420P:
1179 case PIX_FMT_YUV422P:
1180 case PIX_FMT_YUV444P:
1181 case PIX_FMT_YUV410P:
1182 case PIX_FMT_YUV411P:
1183 stride = ROUND_UP_4(width);
1184 h2 = ROUND_UP_X(height, pinfo->y_chroma_shift);
1186 w2 = DIV_ROUND_UP_X(width, pinfo->x_chroma_shift);
1187 stride2 = ROUND_UP_4(w2);
1188 h2 = DIV_ROUND_UP_X(height, pinfo->y_chroma_shift);
1189 size2 = stride2 * h2;
1190 fsize = size + 2 * size2;
1194 stride = ROUND_UP_4 (width * 3);
1195 fsize = stride * height;
1199 fsize = stride * height;
1201 case PIX_FMT_RGB555:
1202 case PIX_FMT_RGB565:
1203 stride = ROUND_UP_4 (width * 2);
1204 fsize = stride * height;
1215 gst_maru_align_size (int buf_size)
1219 align_size = buf_size / 1024;
1221 for (i = 0; i < 14; i++) {
1222 if (align_size < (1 << i)) {
1223 align_size = 1024 * (1 << i);