summaryrefslogtreecommitdiffstats
path: root/gst
diff options
context:
space:
mode:
Diffstat (limited to 'gst')
-rw-r--r--gst/aacparse/gstaacparse.c67
-rw-r--r--gst/aacparse/gstbaseparse.c10
-rw-r--r--gst/amrparse/gstamrparse.c1
-rw-r--r--gst/amrparse/gstbaseparse.c10
-rw-r--r--gst/dvdspu/Makefile.am2
-rw-r--r--gst/flacparse/gstbaseparse.c10
-rw-r--r--gst/qtmux/atoms.c6
-rw-r--r--gst/qtmux/atoms.h4
-rw-r--r--gst/qtmux/ftypcc.h3
-rw-r--r--gst/qtmux/gstqtmuxmap.c48
-rw-r--r--gst/shapewipe/gstshapewipe.c43
11 files changed, 137 insertions, 67 deletions
diff --git a/gst/aacparse/gstaacparse.c b/gst/aacparse/gstaacparse.c
index c9ad0b5f..07906347 100644
--- a/gst/aacparse/gstaacparse.c
+++ b/gst/aacparse/gstaacparse.c
@@ -70,22 +70,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_aacparse_debug);
#define GST_CAT_DEFAULT gst_aacparse_debug
-static const guint aac_sample_rates[] = {
- 96000,
- 88200,
- 64000,
- 48000,
- 44100,
- 32000,
- 24000,
- 22050,
- 16000,
- 12000,
- 11025,
- 8000
-};
-
-
#define ADIF_MAX_SIZE 40 /* Should be enough */
#define ADTS_MAX_SIZE 10 /* Should be enough */
@@ -121,6 +105,18 @@ gboolean gst_aacparse_event (GstBaseParse * parse, GstEvent * event);
GST_BOILERPLATE_FULL (GstAacParse, gst_aacparse, GstBaseParse,
GST_TYPE_BASE_PARSE, _do_init);
+static inline gint
+gst_aacparse_get_sample_rate_from_index (guint sr_idx)
+{
+ static const guint aac_sample_rates[] = { 96000, 88200, 64000, 48000, 44100,
+ 32000, 24000, 22050, 16000, 12000, 11025, 8000
+ };
+
+ if (sr_idx < G_N_ELEMENTS (aac_sample_rates))
+ return aac_sample_rates[sr_idx];
+ GST_WARNING ("Invalid sample rate index %u", sr_idx);
+ return 0;
+}
/**
* gst_aacparse_base_init:
@@ -213,21 +209,30 @@ gst_aacparse_finalize (GObject * object)
static gboolean
gst_aacparse_set_src_caps (GstAacParse * aacparse)
{
- GstCaps *src_caps = NULL;
- gchar *caps_str = NULL;
+ GstStructure *s;
+ GstCaps *sink_caps, *src_caps = NULL;
gboolean res = FALSE;
- src_caps = gst_caps_new_simple ("audio/mpeg",
- "framed", G_TYPE_BOOLEAN, TRUE,
+ sink_caps = GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad);
+ GST_DEBUG_OBJECT (aacparse, "sink caps: %" GST_PTR_FORMAT, sink_caps);
+ if (sink_caps)
+ src_caps = gst_caps_copy (sink_caps);
+ else
+ src_caps = gst_caps_new_simple ("audio/mpeg", NULL);
+
+ gst_caps_set_simple (src_caps, "framed", G_TYPE_BOOLEAN, TRUE,
"mpegversion", G_TYPE_INT, aacparse->mpegversion, NULL);
- caps_str = gst_caps_to_string (src_caps);
- GST_DEBUG_OBJECT (aacparse, "setting srcpad caps: %s", caps_str);
- g_free (caps_str);
+ s = gst_caps_get_structure (src_caps, 0);
+ if (!gst_structure_has_field (s, "rate") && aacparse->sample_rate > 0)
+ gst_structure_set (s, "rate", G_TYPE_INT, aacparse->sample_rate, NULL);
+ if (!gst_structure_has_field (s, "channels") && aacparse->channels > 0)
+ gst_structure_set (s, "channels", G_TYPE_INT, aacparse->channels, NULL);
+
+ GST_DEBUG_OBJECT (aacparse, "setting src caps: %" GST_PTR_FORMAT, src_caps);
gst_pad_use_fixed_caps (GST_BASE_PARSE (aacparse)->srcpad);
res = gst_pad_set_caps (GST_BASE_PARSE (aacparse)->srcpad, src_caps);
- gst_pad_fixate_caps (GST_BASE_PARSE (aacparse)->srcpad, src_caps);
gst_caps_unref (src_caps);
return res;
}
@@ -266,9 +271,11 @@ gst_aacparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps)
if (value) {
GstBuffer *buf = gst_value_get_buffer (value);
const guint8 *buffer = GST_BUFFER_DATA (buf);
+ guint sr_idx;
+
+ sr_idx = ((buffer[0] & 0x07) << 1) | ((buffer[1] & 0x80) >> 7);
aacparse->object_type = (buffer[0] & 0xf8) >> 3;
- aacparse->sample_rate = ((buffer[0] & 0x07) << 1) |
- ((buffer[1] & 0x80) >> 7);
+ aacparse->sample_rate = gst_aacparse_get_sample_rate_from_index (sr_idx);
aacparse->channels = (buffer[1] & 0x78) >> 3;
aacparse->header_type = DSPAAC_HEADER_NONE;
aacparse->mpegversion = 4;
@@ -468,13 +475,13 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
aacparse->header_type = DSPAAC_HEADER_ADTS;
sr_idx = (data[2] & 0x3c) >> 2;
- aacparse->sample_rate = aac_sample_rates[sr_idx];
+ aacparse->sample_rate = gst_aacparse_get_sample_rate_from_index (sr_idx);
aacparse->mpegversion = (data[1] & 0x08) ? 2 : 4;
aacparse->object_type = (data[2] & 0xc0) >> 6;
aacparse->channels = ((data[2] & 0x01) << 2) | ((data[3] & 0xc0) >> 6);
aacparse->bitrate = ((data[5] & 0x1f) << 6) | ((data[6] & 0xfc) >> 2);
- aacparse->frames_per_sec = aac_sample_rates[sr_idx] / 1024.f;
+ aacparse->frames_per_sec = aacparse->sample_rate / 1024.f;
GST_DEBUG ("ADTS: samplerate %d, channels %d, bitrate %d, objtype %d, "
"fps %f", aacparse->sample_rate, aacparse->channels,
@@ -544,9 +551,9 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
/* FIXME: This gives totally wrong results. Duration calculation cannot
be based on this */
- aacparse->sample_rate = aac_sample_rates[sr_idx];
+ aacparse->sample_rate = gst_aacparse_get_sample_rate_from_index (sr_idx);
- aacparse->frames_per_sec = aac_sample_rates[sr_idx] / 1024.f;
+ aacparse->frames_per_sec = aacparse->sample_rate / 1024.f;
GST_INFO ("ADIF fps: %f", aacparse->frames_per_sec);
// FIXME: Can we assume this?
diff --git a/gst/aacparse/gstbaseparse.c b/gst/aacparse/gstbaseparse.c
index 34d28ec2..026b1341 100644
--- a/gst/aacparse/gstbaseparse.c
+++ b/gst/aacparse/gstbaseparse.c
@@ -1730,18 +1730,14 @@ gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
GstBaseParseClass *klass;
gboolean res = TRUE;
- gchar *caps_str = gst_caps_to_string (caps);
- g_free (caps_str);
-
- parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
+ parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
klass = GST_BASE_PARSE_GET_CLASS (parse);
- GST_DEBUG_OBJECT (parse, "setcaps: %s", caps_str);
+ GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
if (klass->set_sink_caps)
res = klass->set_sink_caps (parse, caps);
parse->negotiated = res;
- gst_object_unref (parse);
- return gst_pad_set_caps (pad, caps);
+ return res && gst_pad_set_caps (pad, caps);
}
diff --git a/gst/amrparse/gstamrparse.c b/gst/amrparse/gstamrparse.c
index 5ec0c6c2..64cf9547 100644
--- a/gst/amrparse/gstamrparse.c
+++ b/gst/amrparse/gstamrparse.c
@@ -210,7 +210,6 @@ gst_amrparse_set_src_caps (GstAmrParse * amrparse)
}
gst_pad_use_fixed_caps (GST_BASE_PARSE (amrparse)->srcpad);
res = gst_pad_set_caps (GST_BASE_PARSE (amrparse)->srcpad, src_caps);
- gst_pad_fixate_caps (GST_BASE_PARSE (amrparse)->srcpad, src_caps);
gst_caps_unref (src_caps);
return res;
}
diff --git a/gst/amrparse/gstbaseparse.c b/gst/amrparse/gstbaseparse.c
index e0f1f4d7..ad963785 100644
--- a/gst/amrparse/gstbaseparse.c
+++ b/gst/amrparse/gstbaseparse.c
@@ -1730,18 +1730,14 @@ gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
GstBaseParseClass *klass;
gboolean res = TRUE;
- gchar *caps_str = gst_caps_to_string (caps);
- g_free (caps_str);
-
- parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
+ parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
klass = GST_BASE_PARSE_GET_CLASS (parse);
- GST_DEBUG_OBJECT (parse, "setcaps: %s", caps_str);
+ GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
if (klass->set_sink_caps)
res = klass->set_sink_caps (parse, caps);
parse->negotiated = res;
- gst_object_unref (parse);
- return gst_pad_set_caps (pad, caps);
+ return res && gst_pad_set_caps (pad, caps);
}
diff --git a/gst/dvdspu/Makefile.am b/gst/dvdspu/Makefile.am
index 07a66357..950ed82c 100644
--- a/gst/dvdspu/Makefile.am
+++ b/gst/dvdspu/Makefile.am
@@ -8,6 +8,6 @@ libgstdvdspu_la_LIBADD = $(GST_LIBS)
libgstdvdspu_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstdvdspu_la_LIBTOOLFLAGS = --tag=disable-static
-noinst_HEADERS = gstdvdspu.h gstspu-pgs.h gstspu-vobsub.h
+noinst_HEADERS = gstdvdspu.h gstspu-pgs.h gstspu-vobsub.h gstspu-common.h
EXTRA_DIST = Notes.txt
diff --git a/gst/flacparse/gstbaseparse.c b/gst/flacparse/gstbaseparse.c
index 066fe517..85fb8d71 100644
--- a/gst/flacparse/gstbaseparse.c
+++ b/gst/flacparse/gstbaseparse.c
@@ -1960,18 +1960,14 @@ gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps)
GstBaseParseClass *klass;
gboolean res = TRUE;
- gchar *caps_str = gst_caps_to_string (caps);
- g_free (caps_str);
-
- parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
+ parse = GST_BASE_PARSE (GST_PAD_PARENT (pad));
klass = GST_BASE_PARSE_GET_CLASS (parse);
- GST_DEBUG_OBJECT (parse, "setcaps: %s", caps_str);
+ GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps);
if (klass->set_sink_caps)
res = klass->set_sink_caps (parse, caps);
parse->negotiated = res;
- gst_object_unref (parse);
- return gst_pad_set_caps (pad, caps);
+ return res && gst_pad_set_caps (pad, caps);
}
diff --git a/gst/qtmux/atoms.c b/gst/qtmux/atoms.c
index a5d8fe38..47db40ce 100644
--- a/gst/qtmux/atoms.c
+++ b/gst/qtmux/atoms.c
@@ -2783,6 +2783,9 @@ atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
atom_trak_set_audio_commons (trak, context, scale);
ste = atom_trak_add_audio_entry (trak, context, entry->fourcc);
+ trak->is_video = FALSE;
+ trak->is_h264 = FALSE;
+
ste->version = entry->version;
ste->compression_id = entry->compression_id;
ste->sample_size = entry->sample_size;
@@ -2811,6 +2814,9 @@ atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
entry->height);
ste = atom_trak_add_video_entry (trak, context, entry->fourcc);
+ trak->is_video = TRUE;
+ trak->is_h264 = (entry->fourcc == FOURCC_avc1);
+
ste->width = entry->width;
ste->height = entry->height;
ste->depth = entry->depth;
diff --git a/gst/qtmux/atoms.h b/gst/qtmux/atoms.h
index 4d8dce19..23bc19bb 100644
--- a/gst/qtmux/atoms.h
+++ b/gst/qtmux/atoms.h
@@ -518,6 +518,10 @@ typedef struct _AtomTRAK
AtomTKHD tkhd;
AtomMDIA mdia;
+
+ /* some helper info for structural conformity checks */
+ gboolean is_video;
+ gboolean is_h264;
} AtomTRAK;
typedef struct _AtomMOOV
diff --git a/gst/qtmux/ftypcc.h b/gst/qtmux/ftypcc.h
index d8320c79..4855adf7 100644
--- a/gst/qtmux/ftypcc.h
+++ b/gst/qtmux/ftypcc.h
@@ -53,6 +53,9 @@ G_BEGIN_DECLS
#define FOURCC_mp41 GST_MAKE_FOURCC('m','p','4','1')
#define FOURCC_mp42 GST_MAKE_FOURCC('m','p','4','2')
#define FOURCC_mjp2 GST_MAKE_FOURCC('m','j','p','2')
+#define FOURCC_3gp4 GST_MAKE_FOURCC('3','g','p','4')
+#define FOURCC_3gp6 GST_MAKE_FOURCC('3','g','p','6')
+#define FOURCC_3gg6 GST_MAKE_FOURCC('3','g','g','6')
#define FOURCC_3gg7 GST_MAKE_FOURCC('3','g','g','7')
#define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1')
#define FOURCC_qt__ GST_MAKE_FOURCC('q','t',' ',' ')
diff --git a/gst/qtmux/gstqtmuxmap.c b/gst/qtmux/gstqtmuxmap.c
index 11913670..e0e4faed 100644
--- a/gst/qtmux/gstqtmuxmap.c
+++ b/gst/qtmux/gstqtmuxmap.c
@@ -205,14 +205,40 @@ gst_qt_mux_map_format_to_flavor (GstQTMuxFormat format)
return ATOMS_TREE_FLAVOR_ISOM;
}
+static void
+gst_qt_mux_map_check_tracks (AtomMOOV * moov, gint * _video, gint * _audio,
+ gboolean * _has_h264)
+{
+ GList *it;
+ gint video = 0, audio = 0;
+ gboolean has_h264 = FALSE;
+
+ for (it = moov->traks; it != NULL; it = g_list_next (it)) {
+ AtomTRAK *track = it->data;
+
+ if (track->is_video) {
+ video++;
+ if (track->is_h264)
+ has_h264 = TRUE;
+ } else
+ audio++;
+ }
+
+ if (_video)
+ *_video = video;
+ if (_audio)
+ *_audio = audio;
+ if (_has_h264)
+ *_has_h264 = has_h264;
+}
+
/* pretty static, but possibly dynamic format info */
/* notes:
* - avc1 brand is not used, since the specific extensions indicated by it
* are not used (e.g. sample groupings, etc)
- * - 3GPP2 specific formats not (yet) used, only 3GPP, so no need yet either
- * for 3g2a (but later on, moov might be used to conditionally switch to
- * 3g2a if needed) */
+ * - TODO: maybe even more 3GPP brand fine-tuning ??
+ * (but that might need ftyp rewriting at the end) */
void
gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
guint32 * _major, guint32 * _version, GList ** _compatible, AtomMOOV * moov)
@@ -244,9 +270,23 @@ gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
comp = mp4_brands;
break;
case GST_QT_MUX_FORMAT_3GP:
- major = FOURCC_3gg7;
+ {
+ gint video, audio;
+ gboolean has_h264;
+
+ gst_qt_mux_map_check_tracks (moov, &video, &audio, &has_h264);
+ /* only track restriction really matters for Basic Profile */
+ if (video <= 1 && audio <= 1) {
+ /* it seems only newer spec knows about H264 */
+ major = has_h264 ? FOURCC_3gp6 : FOURCC_3gp4;
+ version = has_h264 ? 0x100 : 0x200;
+ } else {
+ major = FOURCC_3gg6;
+ version = 0x100;
+ }
comp = gpp_brands;
break;
+ }
case GST_QT_MUX_FORMAT_MJ2:
major = FOURCC_mjp2;
comp = mjp2_brands;
diff --git a/gst/shapewipe/gstshapewipe.c b/gst/shapewipe/gstshapewipe.c
index ec33f0a7..c2c4ce2b 100644
--- a/gst/shapewipe/gstshapewipe.c
+++ b/gst/shapewipe/gstshapewipe.c
@@ -17,6 +17,27 @@
* Boston, MA 02111-1307, USA.
*/
+/**
+ * SECTION:element-shapewipe
+ *
+ * The shapewipe element provides custom transitions on video streams
+ * based on a grayscale bitmap. The state of the transition can be
+ * controlled by the position property and an optional blended border
+ * can be added by the border property.
+ *
+ * Transition bitmaps can be downloaded from the
+ * <ulink url="http://cinelerra.org/transitions.php">Cinelerra transition</ulink>
+ * page.
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch -v videotestsrc ! video/x-raw-yuv,width=640,height=480 ! shapewipe position=0.5 name=shape ! videomixer name=mixer ! ffmpegcolorspace ! autovideosink filesrc location=mask.png ! typefind ! decodebin2 ! ffmpegcolorspace ! videoscale ! queue ! shape.mask_sink videotestsrc pattern=snow ! video/x-raw-yuv,width=640,height=480 ! queue ! mixer.
+ * ]| This pipeline adds the transition from mask.png with position 0.5 to an SMPTE test screen and snow.
+ * </refsect2>
+ */
+
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -571,7 +592,7 @@ gst_shape_wipe_blend_16 (GstShapeWipe * self, GstBuffer * inbuf,
for (i = 0; i < self->height; i++) {
for (j = 0; j < self->width; j++) {
- gfloat in = *mask / 65535.0f;
+ gfloat in = *mask / 65536.0f;
if (in < low) {
output[0] = 0x00; /* A */
@@ -627,7 +648,7 @@ gst_shape_wipe_blend_8 (GstShapeWipe * self, GstBuffer * inbuf,
for (i = 0; i < self->height; i++) {
for (j = 0; j < self->width; j++) {
- gfloat in = *mask / 255.0f;
+ gfloat in = *mask / 256.0f;
if (in < low) {
output[0] = 0x00; /* A */
@@ -678,26 +699,26 @@ gst_shape_wipe_video_sink_chain (GstPad * pad, GstBuffer * buffer)
GST_TIME_ARGS (timestamp), self->mask_position);
g_mutex_lock (self->mask_mutex);
- mask = self->mask;
- if (self->mask)
- gst_buffer_ref (self->mask);
- else
+ if (!self->mask)
g_cond_wait (self->mask_cond, self->mask_mutex);
if (self->mask == NULL) {
g_mutex_unlock (self->mask_mutex);
+ gst_buffer_unref (buffer);
return GST_FLOW_UNEXPECTED;
+ } else {
+ mask = gst_buffer_ref (self->mask);
}
-
- mask = gst_buffer_ref (self->mask);
-
g_mutex_unlock (self->mask_mutex);
ret =
gst_pad_alloc_buffer_and_set_caps (self->srcpad, GST_BUFFER_OFFSET_NONE,
GST_BUFFER_SIZE (buffer), GST_PAD_CAPS (self->srcpad), &outbuf);
- if (G_UNLIKELY (ret != GST_FLOW_OK))
+ if (G_UNLIKELY (ret != GST_FLOW_OK)) {
+ gst_buffer_unref (buffer);
+ gst_buffer_unref (mask);
return ret;
+ }
if (self->mask_bpp == 16)
ret = gst_shape_wipe_blend_16 (self, buffer, mask, outbuf);
@@ -728,6 +749,8 @@ gst_shape_wipe_mask_sink_chain (GstPad * pad, GstBuffer * buffer)
g_cond_signal (self->mask_cond);
g_mutex_unlock (self->mask_mutex);
+ gst_buffer_unref (buffer);
+
return ret;
}