diff options
| author | Martin Jansa <martin.jansa@gmail.com> | 2014-08-08 15:57:52 +0200 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2014-08-17 10:00:17 +0100 |
| commit | 7324d7deb18b81943100bc35301b0c4aa22dc404 (patch) | |
| tree | 2d53a065260f5c549cffddbbd518e03462e9efef | |
| parent | 9e110ce3702ca92125a905c48f8fcbfab5bfe1ab (diff) | |
| download | openembedded-core-7324d7deb18b81943100bc35301b0c4aa22dc404.tar.gz openembedded-core-7324d7deb18b81943100bc35301b0c4aa22dc404.tar.bz2 openembedded-core-7324d7deb18b81943100bc35301b0c4aa22dc404.zip | |
gst-ffmpeg: add PACKAGECONFIG for libav9 and patch from Gentoo
* apply the patch only when PACKAGECONFIG is selected, because the changes
aren't backwards compatible
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/recipes-multimedia/gstreamer/gst-ffmpeg-0.10.13/libav-9.patch | 9304 | ||||
| -rw-r--r-- | meta/recipes-multimedia/gstreamer/gst-ffmpeg_0.10.13.bb | 2 |
2 files changed, 9306 insertions, 0 deletions
diff --git a/meta/recipes-multimedia/gstreamer/gst-ffmpeg-0.10.13/libav-9.patch b/meta/recipes-multimedia/gstreamer/gst-ffmpeg-0.10.13/libav-9.patch new file mode 100644 index 0000000000..9055b341dc --- /dev/null +++ b/meta/recipes-multimedia/gstreamer/gst-ffmpeg-0.10.13/libav-9.patch @@ -0,0 +1,9304 @@ +Taken from gentoo patchset: +http://dev.gentoo.org/~tetromino/distfiles/gst-plugins-ffmpeg/gst-ffmpeg-0.10.13_p2012.11-libav-9-patches.tar.xz + +Upstream-Status: Pending + +Contains following changes, rebased to apply on top of our changes +0002-Fix-includes-for-systemwide-build.patch +0003-libav-Switch-to-non-deprecated-symbols.patch +0005-av-Update-for-some-constant-changes.patch +0006-av-Remove-palette-support-for-now.patch +0007-av-Port-remaining-simple-bits.patch +0008-av-Use-av_codec_is_-en-de-coder-API-instead-of-priva.patch +0009-avprotocol-Port-from-the-URL-protocol-handler-to-san.patch +0010-avdec-don-t-wait-for-keyframe.patch + +Following changes were skipped: +0001-Partially-revert-commit-0300801b.patch +0004-av-update-to-use-AVOption-variants.patch +0011-av_get_bits_per_sample_format-was-removed-in-libav-9.patch + +Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com> + +diff -uNr gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpeg.c gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpeg.c +--- gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpeg.c 2011-10-31 11:14:03.000000000 +0100 ++++ gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpeg.c 2014-08-08 15:26:07.872857555 +0200 +@@ -151,9 +151,6 @@ + #endif + gst_ffmpegaudioresample_register (plugin); + +- av_register_protocol2 (&gstreamer_protocol, sizeof (URLProtocol)); +- av_register_protocol2 (&gstpipe_protocol, sizeof (URLProtocol)); +- + /* Now we can return the pointer to the newly created Plugin object. */ + return TRUE; + } +diff -uNr gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpeg.h gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpeg.h +--- gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpeg.h 2011-05-17 10:53:16.000000000 +0200 ++++ gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpeg.h 2014-08-08 15:26:07.872857555 +0200 +@@ -58,10 +58,13 @@ + int gst_ffmpeg_avcodec_close (AVCodecContext *avctx); + int gst_ffmpeg_av_find_stream_info(AVFormatContext *ic); + +-G_END_DECLS ++int gst_ffmpegdata_open (GstPad * pad, int flags, AVIOContext ** context); ++int gst_ffmpegdata_close (AVIOContext * h); ++typedef struct _GstFFMpegPipe GstFFMpegPipe; ++int gst_ffmpeg_pipe_open (GstFFMpegPipe *ffpipe, int flags, AVIOContext ** context); ++int gst_ffmpeg_pipe_close (AVIOContext * h); + +-extern URLProtocol gstreamer_protocol; +-extern URLProtocol gstpipe_protocol; ++G_END_DECLS + + /* use GST_FFMPEG URL_STREAMHEADER with URL_WRONLY if the first + * buffer should be used as streamheader property on the pad's caps. */ +diff -uNr gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpegcfg.c gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpegcfg.c +--- gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpegcfg.c 2011-07-12 16:35:27.000000000 +0200 ++++ gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpegcfg.c 2014-08-08 15:24:17.899853612 +0200 +@@ -147,7 +147,6 @@ + {FF_DCT_FASTINT, "Fast Integer", "fastint"}, + {FF_DCT_INT, "Accurate Integer", "int"}, + {FF_DCT_MMX, "MMX", "mmx"}, +- {FF_DCT_MLIB, "MLIB", "mlib"}, + {FF_DCT_ALTIVEC, "ALTIVEC", "altivec"}, + {FF_DCT_FAAN, "FAAN", "faan"}, + {0, NULL, NULL}, +@@ -173,8 +172,6 @@ + {FF_IDCT_SIMPLE, "Simple", "simple"}, + {FF_IDCT_SIMPLEMMX, "Simple MMX", "simplemmx"}, + {FF_IDCT_LIBMPEG2MMX, "LIBMPEG2MMX", "libmpeg2mmx"}, +- {FF_IDCT_PS2, "PS2", "ps2"}, +- {FF_IDCT_MLIB, "MLIB", "mlib"}, + {FF_IDCT_ARM, "ARM", "arm"}, + {FF_IDCT_ALTIVEC, "ALTIVEC", "altivec"}, + {FF_IDCT_SH4, "SH4", "sh4"}, +@@ -263,16 +260,11 @@ + + if (!ffmpeg_flags_type) { + static const GFlagsValue ffmpeg_flags[] = { +- {CODEC_FLAG_OBMC, "Use overlapped block motion compensation (h263+)", +- "obmc"}, + {CODEC_FLAG_QSCALE, "Use fixed qscale", "qscale"}, + {CODEC_FLAG_4MV, "Allow 4 MV per MB", "4mv"}, +- {CODEC_FLAG_H263P_AIV, "H.263 alternative inter VLC", "aiv"}, + {CODEC_FLAG_QPEL, "Quartel Pel Motion Compensation", "qpel"}, + {CODEC_FLAG_GMC, "GMC", "gmc"}, + {CODEC_FLAG_MV0, "Always try a MB with MV (0,0)", "mv0"}, +- {CODEC_FLAG_PART, +- "Store MV, DC and AC coefficients in seperate partitions", "part"}, + {CODEC_FLAG_LOOP_FILTER, "Loop filter", "loop-filter"}, + {CODEC_FLAG_GRAY, "Only decode/encode grayscale", "gray"}, + {CODEC_FLAG_NORMALIZE_AQP, +@@ -282,13 +274,9 @@ + "global-headers"}, + {CODEC_FLAG_AC_PRED, "H263 Advanced Intra Coding / MPEG4 AC prediction", + "aic"}, +- {CODEC_FLAG_H263P_UMV, "Unlimited Motion Vector", "umv"}, + {CODEC_FLAG_CBP_RD, "Rate Distoration Optimization for CBP", "cbp-rd"}, + {CODEC_FLAG_QP_RD, "Rate Distoration Optimization for QP selection", + "qp-rd"}, +- {CODEC_FLAG_H263P_SLICE_STRUCT, "H263 slice struct", "ss"}, +- {CODEC_FLAG_SVCD_SCAN_OFFSET, +- "Reserve space for SVCD scan offset user data", "scanoffset"}, + {CODEC_FLAG_CLOSED_GOP, "Closed GOP", "closedgop"}, + {0, NULL, NULL}, + }; +diff -uNr gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpegcodecmap.c gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpegcodecmap.c +--- gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpegcodecmap.c 2011-10-31 11:14:03.000000000 +0100 ++++ gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpegcodecmap.c 2014-08-08 15:31:30.968869139 +0200 +@@ -25,8 +25,10 @@ + #include <gst/gst.h> + #ifdef HAVE_FFMPEG_UNINSTALLED + #include <avcodec.h> ++#include <channel_layout.h>> + #else + #include <libavcodec/avcodec.h> ++#include <libavutil/channel_layout.h> + #endif + #include <string.h> + +@@ -35,43 +37,6 @@ + + #include <gst/pbutils/codec-utils.h> + +-/* +- * Read a palette from a caps. +- */ +- +-static void +-gst_ffmpeg_get_palette (const GstCaps * caps, AVCodecContext * context) +-{ +- GstStructure *str = gst_caps_get_structure (caps, 0); +- const GValue *palette_v; +- const GstBuffer *palette; +- +- /* do we have a palette? */ +- if ((palette_v = gst_structure_get_value (str, "palette_data")) && context) { +- palette = gst_value_get_buffer (palette_v); +- if (GST_BUFFER_SIZE (palette) >= AVPALETTE_SIZE) { +- if (context->palctrl) +- av_free (context->palctrl); +- context->palctrl = av_malloc (sizeof (AVPaletteControl)); +- context->palctrl->palette_changed = 1; +- memcpy (context->palctrl->palette, GST_BUFFER_DATA (palette), +- AVPALETTE_SIZE); +- } +- } +-} +- +-static void +-gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context) +-{ +- if (context->palctrl) { +- GstBuffer *palette = gst_buffer_new_and_alloc (AVPALETTE_SIZE); +- +- memcpy (GST_BUFFER_DATA (palette), context->palctrl->palette, +- AVPALETTE_SIZE); +- gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, palette, NULL); +- } +-} +- + /* IMPORTANT: Keep this sorted by the ffmpeg channel masks */ + static const struct + { +@@ -79,26 +44,26 @@ + GstAudioChannelPosition gst; + } _ff_to_gst_layout[] = { + { +- CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { +- CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { +- CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, { +- CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, { +- CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, { +- CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { +- CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, { +- CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { +- CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, { +- CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, { +- CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { +- CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { +- CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { +- CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { +- CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { +- CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { +- CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { +- CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { +- CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { +- CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} ++ AV_CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { ++ AV_CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { ++ AV_CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, { ++ AV_CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, { ++ AV_CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, { ++ AV_CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { ++ AV_CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, { ++ AV_CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { ++ AV_CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, { ++ AV_CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, { ++ AV_CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { ++ AV_CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { ++ AV_CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} + }; + + static GstAudioChannelPosition * +@@ -342,8 +307,8 @@ + + if (channel_layout == 0) { + const guint64 default_channel_set[] = { +- 0, 0, CH_LAYOUT_SURROUND, CH_LAYOUT_QUAD, CH_LAYOUT_5POINT0, +- CH_LAYOUT_5POINT1, 0, CH_LAYOUT_7POINT1 ++ 0, 0, AV_CH_LAYOUT_SURROUND, AV_CH_LAYOUT_QUAD, AV_CH_LAYOUT_5POINT0, ++ AV_CH_LAYOUT_5POINT1, 0, AV_CH_LAYOUT_7POINT1 + }; + + switch (codec_id) { +@@ -1267,8 +1232,6 @@ + case CODEC_ID_FLIC: + case CODEC_ID_VMDVIDEO: + case CODEC_ID_VMDAUDIO: +- case CODEC_ID_SONIC: +- case CODEC_ID_SONIC_LS: + case CODEC_ID_SNOW: + case CODEC_ID_VIXL: + case CODEC_ID_QPEG: +@@ -1689,11 +1652,6 @@ + gst_buffer_unref (data); + } + +- /* palette */ +- if (context) { +- gst_ffmpeg_set_palette (caps, context); +- } +- + GST_LOG ("caps for codec_id=%d: %" GST_PTR_FORMAT, codec_id, caps); + + } else { +@@ -1830,9 +1788,6 @@ + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "endianness", G_TYPE_INT, endianness, NULL); +- if (caps && context) { +- gst_ffmpeg_set_palette (caps, context); +- } + } + } else if (fmt) { + caps = gst_ff_vid_caps_new (context, codec_id, "video/x-raw-yuv", +@@ -1857,7 +1812,7 @@ + */ + + static GstCaps * +-gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt, ++gst_ffmpeg_smpfmt_to_caps (enum AVSampleFormat sample_fmt, + AVCodecContext * context, enum CodecID codec_id) + { + GstCaps *caps = NULL; +@@ -1867,22 +1822,22 @@ + gboolean signedness = FALSE; + + switch (sample_fmt) { +- case SAMPLE_FMT_S16: ++ case AV_SAMPLE_FMT_S16: + signedness = TRUE; + bpp = 16; + break; + +- case SAMPLE_FMT_S32: ++ case AV_SAMPLE_FMT_S32: + signedness = TRUE; + bpp = 32; + break; + +- case SAMPLE_FMT_FLT: ++ case AV_SAMPLE_FMT_FLT: + integer = FALSE; + bpp = 32; + break; + +- case SAMPLE_FMT_DBL: ++ case AV_SAMPLE_FMT_DBL: + integer = FALSE; + bpp = 64; + break; +@@ -1941,12 +1896,12 @@ + } + } else { + GstCaps *temp; +- enum SampleFormat i; ++ enum AVSampleFormat i; + AVCodecContext ctx = { 0, }; + + ctx.channels = -1; + caps = gst_caps_new_empty (); +- for (i = 0; i <= SAMPLE_FMT_DBL; i++) { ++ for (i = 0; i <= AV_SAMPLE_FMT_DBL; i++) { + temp = gst_ffmpeg_smpfmt_to_caps (i, encode ? &ctx : NULL, codec_id); + if (temp != NULL) { + gst_caps_append (caps, temp); +@@ -2049,9 +2004,9 @@ + gst_structure_get_int (structure, "endianness", &endianness)) { + if (endianness == G_BYTE_ORDER) { + if (width == 32) +- context->sample_fmt = SAMPLE_FMT_FLT; ++ context->sample_fmt = AV_SAMPLE_FMT_FLT; + else if (width == 64) +- context->sample_fmt = SAMPLE_FMT_DBL; ++ context->sample_fmt = AV_SAMPLE_FMT_DBL; + } + } + } else { +@@ -2062,9 +2017,9 @@ + gst_structure_get_int (structure, "endianness", &endianness)) { + if ((endianness == G_BYTE_ORDER) && (signedness == TRUE)) { + if ((width == 16) && (depth == 16)) +- context->sample_fmt = SAMPLE_FMT_S16; ++ context->sample_fmt = AV_SAMPLE_FMT_S16; + else if ((width == 32) && (depth == 32)) +- context->sample_fmt = SAMPLE_FMT_S32; ++ context->sample_fmt = AV_SAMPLE_FMT_S32; + } + } + } +@@ -2190,7 +2145,6 @@ + } else { + if (bpp == 8) { + context->pix_fmt = PIX_FMT_PAL8; +- gst_ffmpeg_get_palette (caps, context); + } + } + } +@@ -2576,7 +2530,6 @@ + switch (codec_type) { + case AVMEDIA_TYPE_VIDEO: + gst_ffmpeg_caps_to_pixfmt (caps, context, codec_id == CODEC_ID_RAWVIDEO); +- gst_ffmpeg_get_palette (caps, context); + break; + case AVMEDIA_TYPE_AUDIO: + gst_ffmpeg_caps_to_smpfmt (caps, context, FALSE); +diff -uNr gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpegcodecmap.c.orig gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpegcodecmap.c.orig +--- gst-ffmpeg-0.10.13.orig/ext/ffmpeg/gstffmpegcodecmap.c.orig 1970-01-01 01:00:00.000000000 +0100 ++++ gst-ffmpeg-0.10.13/ext/ffmpeg/gstffmpegcodecmap.c.orig 2014-08-08 15:30:34.006867097 +0200 +@@ -0,0 +1,3447 @@ ++/* GStreamer ++ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> ++ * This file: ++ * Copyright (c) 2002-2004 Ronald Bultje <rbultje@ronald.bitfreak.net> ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++#include <gst/gst.h> ++#ifdef HAVE_FFMPEG_UNINSTALLED ++#include <avcodec.h> ++#include <channel_layout.h>> ++#else ++#include <libavcodec/avcodec.h> ++#include <libavutil/channel_layout.h> ++#endif ++#include <string.h> ++ ++#include "gstffmpeg.h" ++#include "gstffmpegcodecmap.h" ++ ++#include <gst/pbutils/codec-utils.h> ++ ++/* ++ * Read a palette from a caps. ++ */ ++ ++static void ++gst_ffmpeg_get_palette (const GstCaps * caps, AVCodecContext * context) ++{ ++ GstStructure *str = gst_caps_get_structure (caps, 0); ++ const GValue *palette_v; ++ const GstBuffer *palette; ++ ++ /* do we have a palette? */ ++ if ((palette_v = gst_structure_get_value (str, "palette_data")) && context) { ++ palette = gst_value_get_buffer (palette_v); ++ if (GST_BUFFER_SIZE (palette) >= AVPALETTE_SIZE) { ++ if (context->palctrl) ++ av_free (context->palctrl); ++ context->palctrl = av_malloc (sizeof (AVPaletteControl)); ++ context->palctrl->palette_changed = 1; ++ memcpy (context->palctrl->palette, GST_BUFFER_DATA (palette), ++ AVPALETTE_SIZE); ++ } ++ } ++} ++ ++static void ++gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context) ++{ ++ if (context->palctrl) { ++ GstBuffer *palette = gst_buffer_new_and_alloc (AVPALETTE_SIZE); ++ ++ memcpy (GST_BUFFER_DATA (palette), context->palctrl->palette, ++ AVPALETTE_SIZE); ++ gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, palette, NULL); ++ } ++} ++ ++/* IMPORTANT: Keep this sorted by the ffmpeg channel masks */ ++static const struct ++{ ++ guint64 ff; ++ GstAudioChannelPosition gst; ++} _ff_to_gst_layout[] = { ++ { ++ AV_CH_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { ++ AV_CH_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { ++ AV_CH_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, { ++ AV_CH_LOW_FREQUENCY, GST_AUDIO_CHANNEL_POSITION_LFE}, { ++ AV_CH_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, { ++ AV_CH_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { ++ AV_CH_FRONT_LEFT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, { ++ AV_CH_FRONT_RIGHT_OF_CENTER, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { ++ AV_CH_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, { ++ AV_CH_SIDE_LEFT, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, { ++ AV_CH_SIDE_RIGHT, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { ++ AV_CH_TOP_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_FRONT_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_FRONT_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_FRONT_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_BACK_LEFT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_BACK_CENTER, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_TOP_BACK_RIGHT, GST_AUDIO_CHANNEL_POSITION_NONE}, { ++ AV_CH_STEREO_LEFT, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { ++ AV_CH_STEREO_RIGHT, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT} ++}; ++ ++static GstAudioChannelPosition * ++gst_ff_channel_layout_to_gst (guint64 channel_layout, guint channels) ++{ ++ guint nchannels = 0, i, j; ++ GstAudioChannelPosition *pos = NULL; ++ gboolean none_layout = FALSE; ++ ++ for (i = 0; i < 64; i++) { ++ if ((channel_layout & (G_GUINT64_CONSTANT (1) << i)) != 0) { ++ nchannels++; ++ } ++ } ++ ++ if (channel_layout == 0) { ++ nchannels = channels; ++ none_layout = TRUE; ++ } ++ ++ if (nchannels != channels) { ++ GST_ERROR ("Number of channels is different (%u != %u)", channels, ++ nchannels); ++ return NULL; ++ } ++ ++ pos = g_new (GstAudioChannelPosition, nchannels); ++ ++ for (i = 0, j = 0; i < G_N_ELEMENTS (_ff_to_gst_layout); i++) { ++ if ((channel_layout & _ff_to_gst_layout[i].ff) != 0) { ++ pos[j++] = _ff_to_gst_layout[i].gst; ++ ++ if (_ff_to_gst_layout[i].gst == GST_AUDIO_CHANNEL_POSITION_NONE) ++ none_layout = TRUE; ++ } ++ } ++ ++ if (j != nchannels) { ++ GST_WARNING ("Unknown channels in channel layout - assuming NONE layout"); ++ none_layout = TRUE; ++ } ++ ++ if (!none_layout && !gst_audio_check_channel_positions (pos, nchannels)) { ++ GST_ERROR ("Invalid channel layout %" G_GUINT64_FORMAT ++ " - assuming NONE layout", channel_layout); ++ none_layout = TRUE; ++ } ++ ++ if (none_layout) { ++ if (nchannels == 1) { ++ pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO; ++ } else if (nchannels == 2) { ++ pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; ++ pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; ++ } else if (channel_layout == 0) { ++ g_free (pos); ++ pos = NULL; ++ } else { ++ for (i = 0; i < nchannels; i++) ++ pos[i] = GST_AUDIO_CHANNEL_POSITION_NONE; ++ } ++ } ++ ++ if (nchannels == 1 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER) { ++ GST_DEBUG ("mono common case; won't set channel positions"); ++ g_free (pos); ++ pos = NULL; ++ } else if (nchannels == 2 && pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT ++ && pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) { ++ GST_DEBUG ("stereo common case; won't set channel positions"); ++ g_free (pos); ++ pos = NULL; ++ } ++ ++ return pos; ++} ++ ++/* this macro makes a caps width fixed or unfixed width/height ++ * properties depending on whether we've got a context. ++ * ++ * See below for why we use this. ++ * ++ * We should actually do this stuff at the end, like in riff-media.c, ++ * but I'm too lazy today. Maybe later. ++ */ ++static GstCaps * ++gst_ff_vid_caps_new (AVCodecContext * context, enum CodecID codec_id, ++ const char *mimetype, const char *fieldname, ...) ++{ ++ GstStructure *structure = NULL; ++ GstCaps *caps = NULL; ++ va_list var_args; ++ gint i; ++ ++ GST_LOG ("context:%p, codec_id:%d, mimetype:%s", context, codec_id, mimetype); ++ ++ /* fixed, non probing context */ ++ if (context != NULL && context->width != -1) { ++ gint num, denom; ++ ++ caps = gst_caps_new_simple (mimetype, ++ "width", G_TYPE_INT, context->width, ++ "height", G_TYPE_INT, context->height, NULL); ++ ++ num = context->time_base.den / context->ticks_per_frame; ++ denom = context->time_base.num; ++ ++ if (!denom) { ++ GST_LOG ("invalid framerate: %d/0, -> %d/1", num, num); ++ denom = 1; ++ } ++ if (gst_util_fraction_compare (num, denom, 1000, 1) > 0) { ++ GST_LOG ("excessive framerate: %d/%d, -> 0/1", num, denom); ++ num = 0; ++ denom = 1; ++ } ++ GST_LOG ("setting framerate: %d/%d", num, denom); ++ gst_caps_set_simple (caps, ++ "framerate", GST_TYPE_FRACTION, num, denom, NULL); ++ } else { ++ /* so we are after restricted caps in this case */ ++ switch (codec_id) { ++ case CODEC_ID_H261: ++ { ++ caps = gst_caps_new_simple (mimetype, ++ "width", G_TYPE_INT, 352, ++ "height", G_TYPE_INT, 288, ++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); ++ gst_caps_append (caps, gst_caps_new_simple (mimetype, ++ "width", G_TYPE_INT, 176, ++ "height", G_TYPE_INT, 144, ++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL)); ++ break; ++ } ++ case CODEC_ID_H263: ++ { ++ /* 128x96, 176x144, 352x288, 704x576, and 1408x1152. slightly reordered ++ * because we want automatic negotiation to go as close to 320x240 as ++ * possible. */ ++ const static gint widths[] = { 352, 704, 176, 1408, 128 }; ++ const static gint heights[] = { 288, 576, 144, 1152, 96 }; ++ GstCaps *temp; ++ gint n_sizes = G_N_ELEMENTS (widths); ++ ++ caps = gst_caps_new_empty (); ++ for (i = 0; i < n_sizes; i++) { ++ temp = gst_caps_new_simple (mimetype, ++ "width", G_TYPE_INT, widths[i], ++ "height", G_TYPE_INT, heights[i], ++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); ++ ++ gst_caps_append (caps, temp); ++ } ++ break; ++ } ++ case CODEC_ID_DVVIDEO: ++ { ++ static struct ++ { ++ guint32 csp; ++ gint width, height; ++ gint par_n, par_d; ++ gint framerate_n, framerate_d; ++ } profiles[] = { ++ { ++ GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 480, 10, 11, 30000, 1001}, { ++ GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 480, 40, 33, 30000, 1001}, { ++ GST_MAKE_FOURCC ('I', '4', '2', '0'), 720, 576, 59, 54, 25, 1}, { ++ GST_MAKE_FOURCC ('I', '4', '2', '0'), 720, 576, 118, 81, 25, 1}, { ++ GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 576, 59, 54, 25, 1}, { ++ GST_MAKE_FOURCC ('Y', '4', '1', 'B'), 720, 576, 118, 81, 25, 1} ++ }; ++ GstCaps *temp; ++ gint n_sizes = G_N_ELEMENTS (profiles); ++ ++ caps = gst_caps_new_empty (); ++ for (i = 0; i < n_sizes; i++) { ++ temp = gst_caps_new_simple (mimetype, ++ "width", G_TYPE_INT, profiles[i].width, ++ "height", G_TYPE_INT, profiles[i].height, ++ "framerate", GST_TYPE_FRACTION, profiles[i].framerate_n, ++ profiles[i].framerate_d, "pixel-aspect-ratio", GST_TYPE_FRACTION, ++ profiles[i].par_n, profiles[i].par_d, NULL); ++ ++ gst_caps_append (caps, temp); ++ } ++ break; ++ } ++ case CODEC_ID_DNXHD: ++ { ++ caps = gst_caps_new_simple (mimetype, ++ "width", G_TYPE_INT, 1920, ++ "height", G_TYPE_INT, 1080, ++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); ++ gst_caps_append (caps, gst_caps_new_simple (mimetype, ++ "width", G_TYPE_INT, 1280, ++ "height", G_TYPE_INT, 720, ++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL)); ++ break; ++ } ++ default: ++ break; ++ } ++ } ++ ++ /* no fixed caps or special restrictions applied; ++ * default unfixed setting */ ++ if (!caps) { ++ GST_DEBUG ("Creating default caps"); ++ caps = gst_caps_new_simple (mimetype, ++ "width", GST_TYPE_INT_RANGE, 16, 4096, ++ "height", GST_TYPE_INT_RANGE, 16, 4096, ++ "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); ++ } ++ ++ for (i = 0; i < gst_caps_get_size (caps); i++) { ++ va_start (var_args, fieldname); ++ structure = gst_caps_get_structure (caps, i); ++ gst_structure_set_valist (structure, fieldname, var_args); ++ va_end (var_args); ++ } ++ ++ return caps; ++} ++ ++/* same for audio - now with channels/sample rate ++ */ ++static GstCaps * ++gst_ff_aud_caps_new (AVCodecContext * context, enum CodecID codec_id, ++ const char *mimetype, const char *fieldname, ...) ++{ ++ GstCaps *caps = NULL; ++ GstStructure *structure = NULL; ++ gint i; ++ va_list var_args; ++ ++ /* fixed, non-probing context */ ++ if (context != NULL && context->channels != -1) { ++ GstAudioChannelPosition *pos; ++ guint64 channel_layout = context->channel_layout; ++ ++ if (channel_layout == 0) { ++ const guint64 default_channel_set[] = { ++ 0, 0, AV_CH_LAYOUT_SURROUND, AV_CH_LAYOUT_QUAD, AV_CH_LAYOUT_5POINT0, ++ AV_CH_LAYOUT_5POINT1, 0, AV_CH_LAYOUT_7POINT1 ++ }; ++ ++ switch (codec_id) { ++ case CODEC_ID_EAC3: ++ case CODEC_ID_AC3: ++ case CODEC_ID_DTS: ++ if (context->channels > 0 ++ && context->channels < G_N_ELEMENTS (default_channel_set)) ++ channel_layout = default_channel_set[context->channels - 1]; ++ break; ++ default: ++ break; ++ } ++ } ++ ++ caps = gst_caps_new_simple (mimetype, ++ "rate", G_TYPE_INT, context->sample_rate, ++ "channels", G_TYPE_INT, context->channels, NULL); ++ ++ pos = gst_ff_channel_layout_to_gst (channel_layout, context->channels); ++ if (pos != NULL) { ++ gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); ++ g_free (pos); ++ } ++ } else { ++ gint maxchannels = 2; ++ const gint *rates = NULL; ++ gint n_rates = 0; ++ ++ /* so we must be after restricted caps in this case */ ++ switch (codec_id) { ++ case CODEC_ID_AAC: ++ case CODEC_ID_AAC_LATM: ++ case CODEC_ID_DTS: ++ maxchannels = 6; ++ break; ++ case CODEC_ID_MP2: ++ { ++ const static gint l_rates[] = ++ { 48000, 44100, 32000, 24000, 22050, 16000 }; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ break; ++ } ++ case CODEC_ID_EAC3: ++ case CODEC_ID_AC3: ++ { ++ const static gint l_rates[] = { 48000, 44100, 32000 }; ++ maxchannels = 6; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ break; ++ } ++ case CODEC_ID_ADPCM_G722: ++ { ++ const static gint l_rates[] = { 16000 }; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ maxchannels = 1; ++ break; ++ } ++ case CODEC_ID_ADPCM_G726: ++ { ++ const static gint l_rates[] = { 8000 }; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ maxchannels = 1; ++ break; ++ } ++ case CODEC_ID_ADPCM_SWF: ++ { ++ const static gint l_rates[] = { 11025, 22050, 44100 }; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ break; ++ } ++ case CODEC_ID_ROQ_DPCM: ++ { ++ const static gint l_rates[] = { 22050 }; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ break; ++ } ++ case CODEC_ID_AMR_NB: ++ { ++ const static gint l_rates[] = { 8000 }; ++ maxchannels = 1; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ break; ++ } ++ case CODEC_ID_AMR_WB: ++ { ++ const static gint l_rates[] = { 16000 }; ++ maxchannels = 1; ++ n_rates = G_N_ELEMENTS (l_rates); ++ rates = l_rates; ++ break; ++ } ++ default: ++ break; ++ } ++ ++ /* TODO: handle context->channel_layouts here to set ++ * the list of channel layouts supported by the encoder. ++ * Unfortunately no encoder uses this yet.... ++ */ ++ /* regardless of encode/decode, open up channels if applicable */ ++ /* Until decoders/encoders expose the maximum number of channels ++ * they support, we whitelist them here. */ ++ switch (codec_id) { ++ case CODEC_ID_WMAPRO: ++ case CODEC_ID_TRUEHD: ++ maxchannels = 8; ++ break; ++ default: ++ break; ++ } ++ ++ if (maxchannels == 1) ++ caps = gst_caps_new_simple (mimetype, ++ "channels", G_TYPE_INT, maxchannels, NULL); ++ else ++ caps = gst_caps_new_simple (mimetype, ++ "channels", GST_TYPE_INT_RANGE, 1, maxchannels, NULL); ++ if (n_rates) { ++ GValue list = { 0, }; ++ GstStructure *structure; ++ ++ g_value_init (&list, GST_TYPE_LIST); ++ for (i = 0; i < n_rates; i++) { ++ GValue v = { 0, }; ++ ++ g_value_init (&v, G_TYPE_INT); ++ g_value_set_int (&v, rates[i]); ++ gst_value_list_append_value (&list, &v); ++ g_value_unset (&v); ++ } ++ structure = gst_caps_get_structure (caps, 0); ++ gst_structure_set_value (structure, "rate", &list); ++ g_value_unset (&list); ++ } else ++ gst_caps_set_simple (caps, "rate", GST_TYPE_INT_RANGE, 4000, 96000, NULL); ++ } ++ ++ for (i = 0; i < gst_caps_get_size (caps); i++) { ++ va_start (var_args, fieldname); ++ structure = gst_caps_get_structure (caps, i); ++ gst_structure_set_valist (structure, fieldname, var_args); ++ va_end (var_args); ++ } ++ ++ return caps; ++} ++ ++/* Convert a FFMPEG codec ID and optional AVCodecContext ++ * to a GstCaps. If the context is ommitted, no fixed values ++ * for video/audio size will be included in the GstCaps ++ * ++ * CodecID is primarily meant for compressed data GstCaps! ++ * ++ * encode is a special parameter. gstffmpegdec will say ++ * FALSE, gstffmpegenc will say TRUE. The output caps ++ * depends on this, in such a way that it will be very ++ * specific, defined, fixed and correct caps for encoders, ++ * yet very wide, "forgiving" caps for decoders. Example ++ * for mp3: decode: audio/mpeg,mpegversion=1,layer=[1-3] ++ * but encode: audio/mpeg,mpegversion=1,layer=3,bitrate=x, ++ * rate=x,channels=x. ++ */ ++ ++GstCaps * ++gst_ffmpeg_codecid_to_caps (enum CodecID codec_id, ++ AVCodecContext * context, gboolean encode) ++{ ++ GstCaps *caps = NULL; ++ gboolean buildcaps = FALSE; ++ ++ GST_LOG ("codec_id:%d, context:%p, encode:%d", codec_id, context, encode); ++ ++ switch (codec_id) { ++ case CODEC_ID_MPEG1VIDEO: ++ /* FIXME: bitrate */ ++ caps = gst_ff_vid_caps_new (context, codec_id, "video/mpeg", ++ "mpegversion", G_TYPE_INT, 1, ++ "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); ++ break; ++ ++ case CODEC_ID_MPEG2VIDEO: ++ if (encode) { ++ /* FIXME: bitrate */ ++ caps = gst_ff_vid_caps_new (context, codec_id, "video/mpeg", ++ "mpegversion", G_TYPE_INT, 2, ++ "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); ++ } else { ++ /* decode both MPEG-1 and MPEG-2; width/height/fps are all in ++ * the MPEG video stream headers, so may be omitted from caps. */ ++ caps = gst_caps_new_simple ("video/mpeg", ++ "mpegversion", GST_TYPE_INT_RANGE, 1, 2, ++ "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); ++ } ++ break; ++ ++ case CODEC_ID_MPEG2VIDEO_XVMC: ++ /* this is a special ID - don't need it in GStreamer, I think */ ++ break; ++ ++ case CODEC_ID_H263: ++ if (encode) { ++ caps = gst_ff_vid_caps_new (context, codec_id, "video/x-h263", ++ "variant", G_TYPE_STRING, "itu", ++ "h263version", G_TYPE_STRING, "h263", NULL); ++ } else { ++ /* don't pass codec_id, we can decode other variants with the H263 ++ * decoder that don't have specific size requirements ++ */ ++ caps = gst_ff_vid_caps_new (context, CODEC_ID_NONE, "video/x-h263", ++ "variant", G_TYPE_STRING, "itu", NULL); ++ } ++ break; ++ ++ case CODEC_ID_H263P: ++ caps = gst_ff_vid_caps_new (context, codec_id, "video/x-h263", ++ "variant", G_TYPE_STRING, "itu", ++ "h263version", G_TYPE_STRING, "h263p", NULL); ++ if (encode && context) { ++ ++ gst_caps_set_simple (caps, ++ "annex-f", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_4MV, ++ "annex-j", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_LOOP_FILTER, ++ "annex-i", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_AC_PRED, ++ "annex-t", G_TYPE_BOOLEAN, context->flags & CODEC_FLAG_AC_PRED, ++ NULL); ++ } ++ break; ++ ++ case CODEC_ID_H263I: ++ caps = gst_ff_vid_caps_new (context, codec_id, "video/x-intel-h263", ++ "variant", G_TYPE_STRING, "intel", NULL); ++ break; ++ ++ case CODEC_ID_H261: ++ caps = gst_ff_vid_caps_new (context, codec_id, "video/x-h261", NULL); ++ break; ++ ++ case CODEC_ID_RV10: ++ case CODEC_ID_RV20: ++ case CODEC_ID_RV30: ++ case CODEC_ID_RV40: ++ { ++ gint version; ++ ++ switch (codec_id) { ++ case CODEC_ID_RV40: ++ version = 4; ++ break; ++ case CODEC_ID_RV30: ++ version = 3; ++ break; ++ case CODEC_ID_RV20: ++ version = 2; ++ break; ++ default: ++ version = 1; ++ break; ++ } ++ ++ /* FIXME: context->sub_id must be filled in during decoding */ ++ caps = gst_ff_vid_caps_new (context, codec_id, "video/x-pn-realvideo", ++ "systemstream", G_TYPE_BOOLEAN, FALSE, ++ "rmversion", G_TYPE_INT, version, NULL); ++ if (context) { ++ gst_caps_set_simple (caps, "format", G_TYPE_INT, context->sub_id, NULL); ++ if (context->extradata_size >= 8) { ++ gst_caps_set_simple (caps, ++ "subformat", G |
