From 17240ac9ec0a3a7baa723547115d2dabfba80d1b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Ren=C3=A9=20Stadler?= Date: Sat, 26 Nov 2011 10:01:07 +0100 Subject: [PATCH] matroska: port to 0.11 Support for TAG_IMAGE and TAG_ATTACHMENT is commented out; this requires caps on buffers which is gone from 0.11. Segment handling in the demuxer is a bit complex; I added some FIXME comments in places where I'm not yet sure if I ported correctly. --- configure.ac | 2 +- gst/matroska/ebml-read.c | 11 +- gst/matroska/ebml-read.h | 1 + gst/matroska/ebml-write.c | 75 ++-- gst/matroska/matroska-demux.c | 791 +++++++++++++++++++----------------- gst/matroska/matroska-demux.h | 2 +- gst/matroska/matroska-ids.h | 8 +- gst/matroska/matroska-mux.c | 381 ++++++++--------- gst/matroska/matroska-mux.h | 3 + gst/matroska/matroska-parse.c | 171 ++++---- gst/matroska/matroska-read-common.c | 139 ++++--- gst/matroska/matroska-read-common.h | 5 +- gst/matroska/webm-mux.c | 14 +- tests/check/elements/matroskamux.c | 62 +-- 14 files changed, 850 insertions(+), 815 deletions(-) diff --git a/configure.ac b/configure.ac index eee3cb7..45d9537 100644 --- a/configure.ac +++ b/configure.ac @@ -314,7 +314,7 @@ dnl *** plug-ins to include *** dnl Non ported plugins (non-dependant, then dependant) dnl Make sure you have a space before and after all plugins GST_PLUGINS_NONPORTED="deinterlace flx goom2k1 \ - imagefreeze interleave matroska monoscope smpte \ + imagefreeze interleave monoscope smpte \ videobox videomixer \ cairo cairo_gobject dv1394 gdk_pixbuf libdv libpng \ oss oss4 shout2 \ diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index f6bf134..666c585 100644 --- a/gst/matroska/ebml-read.c +++ b/gst/matroska/ebml-read.c @@ -164,6 +164,7 @@ gst_ebml_read_init (GstEbmlRead * ebml, GstElement * el, GstBuffer * buf, guint64 offset) { GstEbmlMaster m; + gsize buf_size; g_return_if_fail (el); g_return_if_fail (buf); @@ -171,9 +172,10 @@ gst_ebml_read_init (GstEbmlRead * ebml, GstElement * el, GstBuffer * buf, ebml->el = el; ebml->offset = offset; ebml->buf = buf; + ebml->buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ); ebml->readers = g_array_sized_new (FALSE, FALSE, sizeof (GstEbmlMaster), 10); m.offset = ebml->offset; - gst_byte_reader_init (&m.br, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_byte_reader_init (&m.br, ebml->buf_data, buf_size); g_array_append_val (ebml->readers, m); } @@ -183,8 +185,10 @@ gst_ebml_read_clear (GstEbmlRead * ebml) if (ebml->readers) g_array_free (ebml->readers, TRUE); ebml->readers = NULL; - if (ebml->buf) + if (ebml->buf) { + gst_buffer_unmap (ebml->buf, ebml->buf_data, -1); gst_buffer_unref (ebml->buf); + } ebml->buf = NULL; ebml->el = NULL; } @@ -334,7 +338,8 @@ gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf) offset = gst_ebml_read_get_pos (ebml) - ebml->offset; if (G_LIKELY (gst_byte_reader_skip (gst_ebml_read_br (ebml), length))) { - *buf = gst_buffer_create_sub (ebml->buf, offset, length); + *buf = gst_buffer_copy_region (ebml->buf, GST_BUFFER_COPY_ALL, + offset, length); } else { *buf = NULL; return GST_FLOW_PARSE; diff --git a/gst/matroska/ebml-read.h b/gst/matroska/ebml-read.h index 9db38f5..b175706 100644 --- a/gst/matroska/ebml-read.h +++ b/gst/matroska/ebml-read.h @@ -54,6 +54,7 @@ typedef struct _GstEbmlRead { GstElement *el; GstBuffer *buf; + gpointer buf_data; guint64 offset; GArray *readers; diff --git a/gst/matroska/ebml-write.c b/gst/matroska/ebml-write.c index 06f3568..bf17d62 100644 --- a/gst/matroska/ebml-write.c +++ b/gst/matroska/ebml-write.c @@ -33,19 +33,15 @@ GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug); #define GST_CAT_DEFAULT gst_ebml_write_debug -#define _do_init(thing) \ +#define _do_init \ GST_DEBUG_CATEGORY_INIT (gst_ebml_write_debug, "ebmlwrite", 0, "Write EBML structured data") -GST_BOILERPLATE_FULL (GstEbmlWrite, gst_ebml_write, GstObject, GST_TYPE_OBJECT, +#define parent_class gst_ebml_write_parent_class +G_DEFINE_TYPE_WITH_CODE (GstEbmlWrite, gst_ebml_write, GST_TYPE_OBJECT, _do_init); static void gst_ebml_write_finalize (GObject * object); static void -gst_ebml_write_base_init (gpointer g_class) -{ -} - -static void gst_ebml_write_class_init (GstEbmlWriteClass * klass) { GObjectClass *object = G_OBJECT_CLASS (klass); @@ -54,11 +50,11 @@ gst_ebml_write_class_init (GstEbmlWriteClass * klass) } static void -gst_ebml_write_init (GstEbmlWrite * ebml, GstEbmlWriteClass * klass) +gst_ebml_write_init (GstEbmlWrite * ebml) { ebml->srcpad = NULL; ebml->pos = 0; - ebml->last_pos = G_MAXUINT64; /* force newsegment event */ + ebml->last_pos = G_MAXUINT64; /* force segment event */ ebml->cache = NULL; ebml->streamheader = NULL; @@ -89,7 +85,7 @@ gst_ebml_write_finalize (GObject * object) ebml->caps = NULL; } - GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -126,7 +122,7 @@ void gst_ebml_write_reset (GstEbmlWrite * ebml) { ebml->pos = 0; - ebml->last_pos = G_MAXUINT64; /* force newsegment event */ + ebml->last_pos = G_MAXUINT64; /* force segment event */ if (ebml->cache) { gst_byte_writer_free (ebml->cache); @@ -182,7 +178,7 @@ gst_ebml_stop_streamheader (GstEbmlWrite * ebml) buffer = gst_byte_writer_free_and_get_buffer (ebml->streamheader); ebml->streamheader = NULL; - GST_DEBUG ("Streamheader was size %d", GST_BUFFER_SIZE (buffer)); + GST_DEBUG ("Streamheader was size %d", gst_buffer_get_size (buffer)); ebml->writing_streamheader = FALSE; return buffer; @@ -211,14 +207,19 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size) } static gboolean -gst_ebml_writer_send_new_segment_event (GstEbmlWrite * ebml, guint64 new_pos) +gst_ebml_writer_send_segment_event (GstEbmlWrite * ebml, guint64 new_pos) { + GstSegment segment; gboolean res; GST_INFO ("seeking to %" G_GUINT64_FORMAT, new_pos); - res = gst_pad_push_event (ebml->srcpad, - gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, new_pos, -1, 0)); + gst_segment_init (&segment, GST_FORMAT_BYTES); + segment.start = new_pos; + segment.stop = -1; + segment.position = 0; + + res = gst_pad_push_event (ebml->srcpad, gst_event_new_segment (&segment)); if (!res) GST_WARNING ("seek to %" G_GUINT64_FORMAT "failed", new_pos); @@ -244,14 +245,13 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe, buffer = gst_byte_writer_free_and_get_buffer (ebml->cache); ebml->cache = NULL; - GST_DEBUG ("Flushing cache of size %d", GST_BUFFER_SIZE (buffer)); - gst_buffer_set_caps (buffer, ebml->caps); + GST_DEBUG ("Flushing cache of size %d", gst_buffer_get_size (buffer)); GST_BUFFER_TIMESTAMP (buffer) = timestamp; - GST_BUFFER_OFFSET (buffer) = ebml->pos - GST_BUFFER_SIZE (buffer); + GST_BUFFER_OFFSET (buffer) = ebml->pos - gst_buffer_get_size (buffer); GST_BUFFER_OFFSET_END (buffer) = ebml->pos; if (ebml->last_write_result == GST_FLOW_OK) { if (GST_BUFFER_OFFSET (buffer) != ebml->last_pos) { - gst_ebml_writer_send_new_segment_event (ebml, GST_BUFFER_OFFSET (buffer)); + gst_ebml_writer_send_segment_event (ebml, GST_BUFFER_OFFSET (buffer)); GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); } if (ebml->writing_streamheader) { @@ -290,7 +290,7 @@ gst_ebml_write_element_new (GstEbmlWrite * ebml, guint8 ** data_out, guint size) buf = gst_buffer_new_and_alloc (size); GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp; - *data_out = GST_BUFFER_DATA (buf); + *data_out = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); return buf; } @@ -408,31 +408,33 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf, { guint data_size; - if (!buf_data) - buf_data = GST_BUFFER_DATA (buf); - - if (buf_data_end) { + if (buf_data_end) data_size = buf_data_end - buf_data; - GST_BUFFER_SIZE (buf) = data_size; - } else { - data_size = GST_BUFFER_SIZE (buf); - } + else + data_size = gst_buffer_get_size (buf); ebml->pos += data_size; /* if there's no cache, then don't push it! */ if (ebml->writing_streamheader) { + if (!buf_data) + buf_data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); gst_byte_writer_put_data (ebml->streamheader, buf_data, data_size); } if (ebml->cache) { + if (!buf_data) + buf_data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE); gst_byte_writer_put_data (ebml->cache, buf_data, data_size); + gst_buffer_unmap (buf, buf_data, -1); gst_buffer_unref (buf); return; } + if (buf_data) + gst_buffer_unmap (buf, buf_data, -1); + if (ebml->last_write_result == GST_FLOW_OK) { - buf = gst_buffer_make_metadata_writable (buf); - gst_buffer_set_caps (buf, ebml->caps); + buf = gst_buffer_make_writable (buf); GST_BUFFER_OFFSET (buf) = ebml->pos - data_size; GST_BUFFER_OFFSET_END (buf) = ebml->pos; if (ebml->writing_streamheader) { @@ -441,7 +443,7 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf, GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); if (GST_BUFFER_OFFSET (buf) != ebml->last_pos) { - gst_ebml_writer_send_new_segment_event (ebml, GST_BUFFER_OFFSET (buf)); + gst_ebml_writer_send_segment_event (ebml, GST_BUFFER_OFFSET (buf)); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); } ebml->last_pos = ebml->pos; @@ -730,12 +732,12 @@ gst_ebml_write_master_finish_full (GstEbmlWrite * ebml, guint64 startpos, guint64 extra_size) { guint64 pos = ebml->pos; - GstBuffer *buf; + guint8 *data = g_malloc (8); + GstBuffer *buf = gst_buffer_new_wrapped (data, 8); gst_ebml_write_seek (ebml, startpos); - buf = gst_buffer_new_and_alloc (8); - GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), + GST_WRITE_UINT64_BE (data, (G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size)); gst_ebml_write_element_push (ebml, buf, NULL, NULL); @@ -835,11 +837,12 @@ void gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num) { guint64 oldpos = ebml->pos; - GstBuffer *buf = gst_buffer_new_and_alloc (8); guint8 *data_start, *data_end; + GstBuffer *buf; - data_start = GST_BUFFER_DATA (buf); + data_start = g_malloc (8); data_end = data_start; + buf = gst_buffer_new_wrapped (data_start, 8); gst_ebml_write_seek (ebml, pos); gst_ebml_write_set_uint (&data_end, num, 8); diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index eaf4c8d..bff3c1c 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -59,8 +59,8 @@ #include #include +#include #include - #include #include "matroska-demux.h" @@ -130,23 +130,22 @@ static gboolean gst_matroska_demux_element_query (GstElement * element, GstQuery * query); /* pad functions */ -static gboolean gst_matroska_demux_sink_activate_pull (GstPad * sinkpad, - gboolean active); -static gboolean gst_matroska_demux_sink_activate (GstPad * sinkpad); +static gboolean gst_matroska_demux_sink_activate (GstPad * sinkpad, + GstObject * parent); +static gboolean gst_matroska_demux_sink_activate_mode (GstPad * sinkpad, + GstObject * parent, GstPadMode mode, gboolean active); static gboolean gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, GstPad * pad, GstEvent * event); static gboolean gst_matroska_demux_handle_src_event (GstPad * pad, - GstEvent * event); -static const GstQueryType *gst_matroska_demux_get_src_query_types (GstPad * - pad); + GstObject * parent, GstEvent * event); static gboolean gst_matroska_demux_handle_src_query (GstPad * pad, - GstQuery * query); + GstObject * parent, GstQuery * query); static gboolean gst_matroska_demux_handle_sink_event (GstPad * pad, - GstEvent * event); + GstObject * parent, GstEvent * event); static GstFlowReturn gst_matroska_demux_chain (GstPad * pad, - GstBuffer * buffer); + GstObject * object, GstBuffer * buffer); static GstStateChangeReturn gst_matroska_demux_change_state (GstElement * element, @@ -178,28 +177,8 @@ static void gst_matroska_demux_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); GType gst_matroska_demux_get_type (void); -GST_BOILERPLATE (GstMatroskaDemux, gst_matroska_demux, GstElement, - GST_TYPE_ELEMENT); - -static void -gst_matroska_demux_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&video_src_templ)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&audio_src_templ)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&subtitle_src_templ)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_templ)); - - gst_element_class_set_details_simple (element_class, "Matroska demuxer", - "Codec/Demuxer", - "Demuxes Matroska/WebM streams into video/audio/subtitles", - "GStreamer maintainers "); -} +#define parent_class gst_matroska_demux_parent_class +G_DEFINE_TYPE (GstMatroskaDemux, gst_matroska_demux, GST_TYPE_ELEMENT); static void gst_matroska_demux_finalize (GObject * object) @@ -237,7 +216,7 @@ gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass) g_object_class_install_property (gobject_class, ARG_MAX_GAP_TIME, g_param_spec_uint64 ("max-gap-time", "Maximum gap time", - "The demuxer sends out newsegment events for skipping " + "The demuxer sends out segment events for skipping " "gaps longer than this (0 = disabled).", 0, G_MAXUINT64, DEFAULT_MAX_GAP_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); @@ -252,18 +231,31 @@ gst_matroska_demux_class_init (GstMatroskaDemuxClass * klass) GST_DEBUG_FUNCPTR (gst_matroska_demux_set_index); gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_matroska_demux_get_index); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&video_src_templ)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&audio_src_templ)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&subtitle_src_templ)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_templ)); + + gst_element_class_set_details_simple (gstelement_class, "Matroska demuxer", + "Codec/Demuxer", + "Demuxes Matroska/WebM streams into video/audio/subtitles", + "GStreamer maintainers "); } static void -gst_matroska_demux_init (GstMatroskaDemux * demux, - GstMatroskaDemuxClass * klass) +gst_matroska_demux_init (GstMatroskaDemux * demux) { demux->common.sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); gst_pad_set_activate_function (demux->common.sinkpad, GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate)); - gst_pad_set_activatepull_function (demux->common.sinkpad, - GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate_pull)); + gst_pad_set_activatemode_function (demux->common.sinkpad, + GST_DEBUG_FUNCPTR (gst_matroska_demux_sink_activate_mode)); gst_pad_set_chain_function (demux->common.sinkpad, GST_DEBUG_FUNCPTR (gst_matroska_demux_chain)); gst_pad_set_event_function (demux->common.sinkpad, @@ -444,7 +436,7 @@ gst_matroska_demux_reset (GstElement * element) demux->next_cluster_offset = 0; demux->index_offset = 0; demux->seekable = FALSE; - demux->need_newsegment = FALSE; + demux->need_segment = FALSE; demux->building_index = FALSE; if (demux->seek_event) { gst_event_unref (demux->seek_event); @@ -473,9 +465,14 @@ gst_matroska_demux_reset (GstElement * element) if (demux->common.global_tags) { gst_tag_list_free (demux->common.global_tags); } - demux->common.global_tags = gst_tag_list_new (); + demux->common.global_tags = gst_tag_list_new_empty (); if (demux->common.cached_buffer) { + if (demux->common.cached_data) { + gst_buffer_unmap (demux->common.cached_buffer, + demux->common.cached_data, -1); + demux->common.cached_data = NULL; + } gst_buffer_unref (demux->common.cached_buffer); demux->common.cached_buffer = NULL; } @@ -484,32 +481,28 @@ gst_matroska_demux_reset (GstElement * element) static GstBuffer * gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf) { - guint8 *data; - guint size; - GstBuffer *new_buf; + gpointer data, buf_data; + gsize size, buf_size; g_return_val_if_fail (GST_IS_BUFFER (buf), NULL); GST_DEBUG ("decoding buffer %p", buf); - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); + buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ); + + g_return_val_if_fail (buf_size > 0, buf); - g_return_val_if_fail (data != NULL && size > 0, buf); + data = buf_data; + size = buf_size; if (gst_matroska_decode_data (context->encodings, &data, &size, GST_MATROSKA_TRACK_ENCODING_SCOPE_FRAME, FALSE)) { - new_buf = gst_buffer_new (); - GST_BUFFER_MALLOCDATA (new_buf) = (guint8 *) data; - GST_BUFFER_DATA (new_buf) = (guint8 *) data; - GST_BUFFER_SIZE (new_buf) = size; - + gst_buffer_unmap (buf, buf_data, buf_size); gst_buffer_unref (buf); - buf = new_buf; - - return buf; + return gst_buffer_new_wrapped (data, size); } else { GST_DEBUG ("decode data failed"); + gst_buffer_unmap (buf, buf_data, buf_size); gst_buffer_unref (buf); return NULL; } @@ -1210,13 +1203,11 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) padname = g_strdup_printf ("video_%u", demux->num_v_streams++); templ = gst_element_class_get_pad_template (klass, "video_%u"); caps = gst_matroska_demux_video_caps (videocontext, - context->codec_id, (guint8 *) context->codec_priv, + context->codec_id, context->codec_priv, context->codec_priv_size, &codec, &riff_fourcc); if (codec) { - list = gst_tag_list_new (); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, - GST_TAG_VIDEO_CODEC, codec, NULL); + list = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec, NULL); g_free (codec); } break; @@ -1233,9 +1224,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) &codec, &riff_audio_fmt); if (codec) { - list = gst_tag_list_new (); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, - GST_TAG_AUDIO_CODEC, codec, NULL); + list = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec, NULL); g_free (codec); } break; @@ -1272,7 +1261,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) const gchar *lang; if (!list) - list = gst_tag_list_new (); + list = gst_tag_list_new_empty (); /* Matroska contains ISO 639-2B codes, we want ISO 639-1 */ lang = gst_tag_get_language_code (context->language); @@ -1285,17 +1274,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) "codec_id='%s'", context->codec_id); switch (context->type) { case GST_MATROSKA_TRACK_TYPE_VIDEO: - caps = gst_caps_new_simple ("video/x-unknown", NULL); + caps = gst_caps_new_empty_simple ("video/x-unknown"); break; case GST_MATROSKA_TRACK_TYPE_AUDIO: - caps = gst_caps_new_simple ("audio/x-unknown", NULL); + caps = gst_caps_new_empty_simple ("audio/x-unknown"); break; case GST_MATROSKA_TRACK_TYPE_SUBTITLE: - caps = gst_caps_new_simple ("application/x-subtitle-unknown", NULL); + caps = gst_caps_new_empty_simple ("application/x-subtitle-unknown"); break; case GST_MATROSKA_TRACK_TYPE_COMPLEX: default: - caps = gst_caps_new_simple ("application/x-matroska-unknown", NULL); + caps = gst_caps_new_empty_simple ("application/x-matroska-unknown"); break; } gst_caps_set_simple (caps, "codec-id", G_TYPE_STRING, context->codec_id, @@ -1304,8 +1293,12 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) /* add any unrecognised riff fourcc / audio format, but after codec-id */ if (context->type == GST_MATROSKA_TRACK_TYPE_AUDIO && riff_audio_fmt != 0) gst_caps_set_simple (caps, "format", G_TYPE_INT, riff_audio_fmt, NULL); - else if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO && riff_fourcc != 0) - gst_caps_set_simple (caps, "fourcc", GST_TYPE_FOURCC, riff_fourcc, NULL); + else if (context->type == GST_MATROSKA_TRACK_TYPE_VIDEO && riff_fourcc != 0) { + gchar *fstr = g_strdup_printf ("%" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (riff_fourcc)); + gst_caps_set_simple (caps, "fourcc", G_TYPE_STRING, fstr, NULL); + g_free (fstr); + } } /* the pad in here */ @@ -1314,8 +1307,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) gst_pad_set_event_function (context->pad, GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_event)); - gst_pad_set_query_type_function (context->pad, - GST_DEBUG_FUNCPTR (gst_matroska_demux_get_src_query_types)); gst_pad_set_query_function (context->pad, GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_query)); @@ -1327,8 +1318,8 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) gst_pad_set_element_private (context->pad, context); gst_pad_use_fixed_caps (context->pad); - gst_pad_set_caps (context->pad, context->caps); gst_pad_set_active (context->pad, TRUE); + gst_pad_set_caps (context->pad, context->caps); gst_element_add_pad (GST_ELEMENT (demux), context->pad); g_free (padname); @@ -1337,19 +1328,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static const GstQueryType * -gst_matroska_demux_get_src_query_types (GstPad * pad) -{ - static const GstQueryType query_types[] = { - GST_QUERY_POSITION, - GST_QUERY_DURATION, - GST_QUERY_SEEKING, - 0 - }; - - return query_types; -} - static gboolean gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad, GstQuery * query) @@ -1375,7 +1353,7 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad, context->pos - demux->stream_start_time); else gst_query_set_position (query, GST_FORMAT_TIME, - demux->common.segment.last_stop - demux->stream_start_time); + demux->common.segment.position - demux->stream_start_time); GST_OBJECT_UNLOCK (demux); } else if (format == GST_FORMAT_DEFAULT && context && context->default_duration) { @@ -1441,7 +1419,7 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad, break; } default: - res = gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, (GstObject *) demux, query); break; } @@ -1455,16 +1433,12 @@ gst_matroska_demux_element_query (GstElement * element, GstQuery * query) } static gboolean -gst_matroska_demux_handle_src_query (GstPad * pad, GstQuery * query) +gst_matroska_demux_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query) { - gboolean ret; - GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad)); - - ret = gst_matroska_demux_query (demux, pad, query); + GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent); - gst_object_unref (demux); - - return ret; + return gst_matroska_demux_query (demux, pad, query); } /* returns FALSE if there are no pads to deliver event to, @@ -1473,7 +1447,7 @@ gst_matroska_demux_handle_src_query (GstPad * pad, GstQuery * query) static gboolean gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event) { - gboolean is_newsegment; + gboolean is_segment; gboolean ret = FALSE; gint i; @@ -1482,7 +1456,7 @@ gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event) GST_DEBUG_OBJECT (demux, "Sending event of type %s to all source pads", GST_EVENT_TYPE_NAME (event)); - is_newsegment = (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT); + is_segment = (GST_EVENT_TYPE (event) == GST_EVENT_SEGMENT); g_assert (demux->common.src->len == demux->common.num_streams); for (i = 0; i < demux->common.src->len; i++) { @@ -1494,22 +1468,32 @@ gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event) ret = TRUE; /* FIXME: send global tags before stream tags */ - if (G_UNLIKELY (is_newsegment && stream->pending_tags != NULL)) { + if (G_UNLIKELY (is_segment && stream->pending_tags != NULL)) { GST_DEBUG_OBJECT (demux, "Sending pending_tags %p for pad %s:%s : %" GST_PTR_FORMAT, stream->pending_tags, GST_DEBUG_PAD_NAME (stream->pad), stream->pending_tags); - gst_element_found_tags_for_pad (GST_ELEMENT (demux), stream->pad, - stream->pending_tags); + gst_pad_push_event (stream->pad, gst_event_new_tag (stream->pending_tags)); stream->pending_tags = NULL; } } - if (G_UNLIKELY (is_newsegment && demux->common.global_tags != NULL)) { + if (G_UNLIKELY (is_segment && demux->common.global_tags != NULL)) { + GstEvent *tag_event; gst_tag_list_add (demux->common.global_tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT, "Matroska", NULL); GST_DEBUG_OBJECT (demux, "Sending global_tags %p : %" GST_PTR_FORMAT, demux->common.global_tags, demux->common.global_tags); - gst_element_found_tags (GST_ELEMENT (demux), demux->common.global_tags); + + tag_event = gst_event_new_tag (demux->common.global_tags); + + for (i = 0; i < demux->common.src->len; i++) { + GstMatroskaTrackContext *stream; + + stream = g_ptr_array_index (demux->common.src, i); + gst_pad_push_event (stream->pad, gst_event_ref (tag_event)); + } + + gst_event_unref (tag_event); demux->common.global_tags = NULL; } @@ -1554,7 +1538,7 @@ gst_matroska_demux_move_to_entry (GstMatroskaDemux * demux, /* update the time */ gst_matroska_read_common_reset_streams (&demux->common, entry->time, TRUE); - demux->common.segment.last_stop = entry->time; + demux->common.segment.position = entry->time; demux->seek_block = entry->block; demux->seek_first = TRUE; demux->last_stop_end = GST_CLOCK_TIME_NONE; @@ -1597,6 +1581,8 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos) GstFlowReturn ret = GST_FLOW_OK; const guint chunk = 64 * 1024; GstBuffer *buf = NULL; + gpointer data = NULL; + gsize size; guint64 length; guint32 id; guint needed; @@ -1633,6 +1619,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos) gint cluster_pos; if (buf != NULL) { + gst_buffer_unmap (buf, data, size); gst_buffer_unref (buf); buf = NULL; } @@ -1640,8 +1627,9 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos) if (ret != GST_FLOW_OK) break; GST_DEBUG_OBJECT (demux, "read buffer size %d at offset %" G_GINT64_FORMAT, - GST_BUFFER_SIZE (buf), newpos); - gst_byte_reader_init_from_buffer (&reader, buf); + gst_buffer_get_size (buf), newpos); + data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + gst_byte_reader_init (&reader, data, size); resume: cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, GST_MATROSKA_ID_CLUSTER, 0, gst_byte_reader_get_remaining (&reader)); @@ -1695,6 +1683,7 @@ gst_matroska_demux_search_cluster (GstMatroskaDemux * demux, gint64 * pos) } if (buf) { + gst_buffer_unmap (buf, data, size); gst_buffer_unref (buf); buf = NULL; } @@ -1741,7 +1730,7 @@ gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time) /* estimate using start and current position */ GST_OBJECT_LOCK (demux); opos = demux->common.offset - demux->common.ebml_segment_start; - otime = demux->common.segment.last_stop; + otime = demux->common.segment.position; GST_OBJECT_UNLOCK (demux); /* avoid division by zero in first estimation below */ @@ -1924,11 +1913,11 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, if (event) { GST_DEBUG_OBJECT (demux, "configuring seek"); - gst_segment_set_seek (&seeksegment, rate, format, flags, + gst_segment_do_seek (&seeksegment, rate, format, flags, cur_type, cur, stop_type, stop, &update); /* compensate for clip start time */ if (GST_CLOCK_TIME_IS_VALID (demux->stream_start_time)) { - seeksegment.last_stop += demux->stream_start_time; + seeksegment.position += demux->stream_start_time; seeksegment.start += demux->stream_start_time; if (GST_CLOCK_TIME_IS_VALID (seeksegment.stop)) seeksegment.stop += demux->stream_start_time; @@ -1953,7 +1942,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, GST_OBJECT_LOCK (demux); track = gst_matroska_read_common_get_seek_track (&demux->common, track); if ((entry = gst_matroska_read_common_do_index_seek (&demux->common, track, - seeksegment.last_stop, &demux->seek_index, &demux->seek_entry)) == + seeksegment.position, &demux->seek_index, &demux->seek_entry)) == NULL) { /* pull mode without index can scan later on */ if (demux->common.index || demux->streaming) { @@ -1968,7 +1957,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, if (demux->streaming) { /* need to seek to cluster start to pick up cluster time */ /* upstream takes care of flushing and all that - * ... and newsegment event handling takes care of the rest */ + * ... and segment event handling takes care of the rest */ return perform_seek_to_offset (demux, entry->pos + demux->common.ebml_segment_start); } @@ -1996,8 +1985,9 @@ next: if (!demux->streaming && !demux->common.index) { /* need to stop flushing upstream as we need it next */ if (flush) - gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_stop ()); - entry = gst_matroska_demux_search_pos (demux, seeksegment.last_stop); + gst_pad_push_event (demux->common.sinkpad, + gst_event_new_flush_stop (TRUE)); + entry = gst_matroska_demux_search_pos (demux, seeksegment.position); /* keep local copy */ if (entry) { scan_entry = *entry; @@ -2006,7 +1996,7 @@ next: } else { GST_DEBUG_OBJECT (demux, "Scan failed to find matching position"); if (flush) - gst_matroska_demux_send_event (demux, gst_event_new_flush_stop ()); + gst_matroska_demux_send_event (demux, gst_event_new_flush_stop (TRUE)); goto seek_error; } } @@ -2015,26 +2005,26 @@ next: GST_DEBUG_OBJECT (demux, "seek to key unit, adjusting segment start to %" GST_TIME_FORMAT, GST_TIME_ARGS (entry->time)); seeksegment.start = entry->time; - seeksegment.last_stop = entry->time; + seeksegment.position = entry->time; seeksegment.time = entry->time - demux->stream_start_time; } exit: if (flush) { GST_DEBUG_OBJECT (demux, "Stopping flush"); - gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_stop ()); - gst_matroska_demux_send_event (demux, gst_event_new_flush_stop ()); + gst_pad_push_event (demux->common.sinkpad, gst_event_new_flush_stop (TRUE)); + gst_matroska_demux_send_event (demux, gst_event_new_flush_stop (TRUE)); } else if (demux->segment_running && update) { + GstSegment segment; GST_DEBUG_OBJECT (demux, "Closing currently running segment"); GST_OBJECT_LOCK (demux); if (demux->close_segment) gst_event_unref (demux->close_segment); - demux->close_segment = gst_event_new_new_segment (TRUE, - demux->common.segment.rate, GST_FORMAT_TIME, - demux->common.segment.start, demux->common.segment.last_stop, - demux->common.segment.time); + segment = demux->common.segment; + segment.stop = segment.position; + demux->close_segment = gst_event_new_segment (&segment); GST_OBJECT_UNLOCK (demux); } @@ -2060,10 +2050,8 @@ exit: GST_OBJECT_LOCK (demux); if (demux->new_segment) gst_event_unref (demux->new_segment); - demux->new_segment = gst_event_new_new_segment_full (!update, - demux->common.segment.rate, demux->common.segment.applied_rate, - demux->common.segment.format, demux->common.segment.start, - demux->common.segment.stop, demux->common.segment.time); + /* On port from 0.10, discarded !update (for segment.update) here, FIXME? */ + demux->new_segment = gst_event_new_segment (&demux->common.segment); GST_OBJECT_UNLOCK (demux); /* restart our task since it might have been stopped when we did the @@ -2170,9 +2158,9 @@ gst_matroska_demux_handle_seek_push (GstMatroskaDemux * demux, GstPad * pad, } static gboolean -gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event) +gst_matroska_demux_handle_src_event (GstPad * pad, GstObject * parent, GstEvent * event) { - GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (gst_pad_get_parent (pad)); + GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent); gboolean res = TRUE; switch (GST_EVENT_TYPE (event)) { @@ -2199,7 +2187,7 @@ gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event) GstClockTimeDiff diff; GstClockTime timestamp; - gst_event_parse_qos (event, &proportion, &diff, ×tamp); + gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp); GST_OBJECT_LOCK (demux); videocontext->earliest_time = timestamp + diff; @@ -2222,8 +2210,6 @@ gst_matroska_demux_handle_src_event (GstPad * pad, GstEvent * event) break; } - gst_object_unref (demux); - return res; } @@ -2390,7 +2376,7 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) GST_OBJECT_LOCK (demux); GST_LOG_OBJECT (demux, "Sync to %" GST_TIME_FORMAT, - GST_TIME_ARGS (demux->common.segment.last_stop)); + GST_TIME_ARGS (demux->common.segment.position)); g_assert (demux->common.num_streams == demux->common.src->len); for (stream_nr = 0; stream_nr < demux->common.src->len; stream_nr++) { @@ -2410,13 +2396,14 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) /* does it lag? 0.5 seconds is a random threshold... * lag need only be considered if we have advanced into requested segment */ if (GST_CLOCK_TIME_IS_VALID (context->pos) && - GST_CLOCK_TIME_IS_VALID (demux->common.segment.last_stop) && - demux->common.segment.last_stop > demux->common.segment.start && - context->pos + (GST_SECOND / 2) < demux->common.segment.last_stop) { + GST_CLOCK_TIME_IS_VALID (demux->common.segment.position) && + demux->common.segment.position > demux->common.segment.start && + context->pos + (GST_SECOND / 2) < demux->common.segment.position) { gint64 new_start; + GstSegment segment; GstEvent *event; - new_start = demux->common.segment.last_stop - (GST_SECOND / 2); + new_start = demux->common.segment.position - (GST_SECOND / 2); if (GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) new_start = MIN (new_start, demux->common.segment.stop); GST_DEBUG_OBJECT (demux, @@ -2427,9 +2414,10 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) context->pos = new_start; /* advance stream time */ - event = gst_event_new_new_segment (TRUE, demux->common.segment.rate, - demux->common.segment.format, new_start, demux->common.segment.stop, - new_start); + segment = demux->common.segment; + segment.start = new_start; + segment.position = new_start; + event = gst_event_new_segment (&segment); GST_OBJECT_UNLOCK (demux); gst_pad_push_event (context->pad, event); GST_OBJECT_LOCK (demux); @@ -2446,9 +2434,7 @@ gst_matroska_demux_push_hdr_buf (GstMatroskaDemux * demux, GstFlowReturn ret, cret; GstBuffer *header_buf; - header_buf = gst_buffer_new_and_alloc (len); - gst_buffer_set_caps (header_buf, stream->caps); - memcpy (GST_BUFFER_DATA (header_buf), data, len); + header_buf = gst_buffer_new_wrapped (g_memdup (data, len), len); if (stream->set_discont) { GST_BUFFER_FLAG_SET (header_buf, GST_BUFFER_FLAG_DISCONT); @@ -2513,12 +2499,10 @@ gst_matroska_demux_push_speex_codec_priv_data (GstMatroskaDemux * demux, GstMatroskaTrackContext * stream) { GstFlowReturn ret; - guint8 *pdata; + guint8 *pdata = stream->codec_priv; GST_LOG_OBJECT (demux, "priv data size = %u", stream->codec_priv_size); - pdata = (guint8 *) stream->codec_priv; - /* need at least 'fLaC' marker + STREAMINFO metadata block */ if (stream->codec_priv_size < 80) { GST_WARNING_OBJECT (demux, "not enough codec priv data for speex headers"); @@ -2546,7 +2530,7 @@ gst_matroska_demux_push_xiph_codec_priv_data (GstMatroskaDemux * demux, GstMatroskaTrackContext * stream) { GstFlowReturn ret; - guint8 *p = (guint8 *) stream->codec_priv; + guint8 *p = stream->codec_priv; gint i, offset, num_packets; guint *length, last; @@ -2613,7 +2597,7 @@ gst_matroska_demux_push_dvd_clut_change_event (GstMatroskaDemux * demux, * elsewhere, but for now, only interested in a small part */ /* make sure we have terminating 0 */ - buf = g_strndup ((gchar *) stream->codec_priv, stream->codec_priv_size); + buf = g_strndup (stream->codec_priv, stream->codec_priv_size); /* just locate and parse palette part */ start = strstr (buf, "palette:"); @@ -2671,7 +2655,7 @@ gst_matroska_demux_add_mpeg_seq_header (GstElement * element, { guint8 *seq_header; guint seq_header_len; - guint32 header; + guint32 header, tmp; if (stream->codec_state) { seq_header = stream->codec_state; @@ -2687,23 +2671,25 @@ gst_matroska_demux_add_mpeg_seq_header (GstElement * element, if (GST_BUFFER_FLAG_IS_SET (*buf, GST_BUFFER_FLAG_DELTA_UNIT)) return GST_FLOW_OK; - if (GST_BUFFER_SIZE (*buf) < 4) + if (gst_buffer_get_size (*buf) < 4) return GST_FLOW_OK; - header = GST_READ_UINT32_BE (GST_BUFFER_DATA (*buf)); + gst_buffer_extract (*buf, 0, &tmp, sizeof (guint32)); + header = GUINT32_FROM_BE (tmp); + /* Sequence start code, if not found prepend */ if (header != 0x000001b3) { GstBuffer *newbuf; - newbuf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (*buf) + seq_header_len); - gst_buffer_set_caps (newbuf, stream->caps); - GST_DEBUG_OBJECT (element, "Prepending MPEG sequence header"); - gst_buffer_copy_metadata (newbuf, *buf, GST_BUFFER_COPY_TIMESTAMPS | - GST_BUFFER_COPY_FLAGS); - g_memmove (GST_BUFFER_DATA (newbuf), seq_header, seq_header_len); - g_memmove (GST_BUFFER_DATA (newbuf) + seq_header_len, - GST_BUFFER_DATA (*buf), GST_BUFFER_SIZE (*buf)); + + newbuf = gst_buffer_new_wrapped (g_memdup (seq_header, seq_header_len), + seq_header_len); + + gst_buffer_copy_into (newbuf, *buf, GST_BUFFER_COPY_TIMESTAMPS | + GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_MEMORY, 0, + gst_buffer_get_size (*buf)); + gst_buffer_unref (*buf); *buf = newbuf; } @@ -2718,8 +2704,7 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, GstMatroskaTrackAudioContext *audiocontext = (GstMatroskaTrackAudioContext *) stream; GstBuffer *newbuf = NULL; - guint8 *data; - guint newlen; + guint8 *buf_data, *data; Wavpack4Header wvh; wvh.ck_id[0] = 'w'; @@ -2734,22 +2719,22 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, wvh.block_index = audiocontext->wvpk_block_index; if (audiocontext->channels <= 2) { - guint32 block_samples; + guint32 block_samples, tmp; + gsize size = gst_buffer_get_size (*buf); - block_samples = GST_READ_UINT32_LE (GST_BUFFER_DATA (*buf)); + gst_buffer_extract (*buf, 0, &tmp, sizeof (guint32)); + block_samples = GUINT32_FROM_LE (tmp); /* we need to reconstruct the header of the wavpack block */ /* -20 because ck_size is the size of the wavpack block -8 * and lace_size is the size of the wavpack block + 12 * (the three guint32 of the header that already are in the buffer) */ - wvh.ck_size = GST_BUFFER_SIZE (*buf) + sizeof (Wavpack4Header) - 20; + wvh.ck_size = size + sizeof (Wavpack4Header) - 20; /* block_samples, flags and crc are already in the buffer */ - newlen = GST_BUFFER_SIZE (*buf) + sizeof (Wavpack4Header) - 12; - newbuf = gst_buffer_new_and_alloc (newlen); - gst_buffer_set_caps (newbuf, stream->caps); + newbuf = gst_buffer_new_allocate (NULL, sizeof (Wavpack4Header) - 12, 0); - data = GST_BUFFER_DATA (newbuf); + data = gst_buffer_map (newbuf, NULL, NULL, GST_MAP_WRITE); data[0] = 'w'; data[1] = 'v'; data[2] = 'p'; @@ -2760,26 +2745,31 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, GST_WRITE_UINT8 (data + 11, wvh.index_no); GST_WRITE_UINT32_LE (data + 12, wvh.total_samples); GST_WRITE_UINT32_LE (data + 16, wvh.block_index); - g_memmove (data + 20, GST_BUFFER_DATA (*buf), GST_BUFFER_SIZE (*buf)); - gst_buffer_copy_metadata (newbuf, *buf, - GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); + + /* Append data from buf: */ + gst_buffer_copy_into (newbuf, *buf, GST_BUFFER_COPY_TIMESTAMPS | + GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_MEMORY, 0, size); + gst_buffer_unref (*buf); *buf = newbuf; audiocontext->wvpk_block_index += block_samples; } else { guint8 *outdata; guint outpos = 0; - guint size; + gsize buf_size, size, out_size; guint32 block_samples, flags, crc, blocksize; - data = GST_BUFFER_DATA (*buf); - size = GST_BUFFER_SIZE (*buf); + buf_data = gst_buffer_map (*buf, &buf_size, NULL, GST_MAP_READ); - if (size < 4) { + if (buf_size < 4) { GST_ERROR_OBJECT (element, "Too small wavpack buffer"); + gst_buffer_unmap (*buf, buf_data, buf_size); return GST_FLOW_ERROR; } + data = buf_data; + size = buf_size; + block_samples = GST_READ_UINT32_LE (data); data += 4; size -= 4; @@ -2799,20 +2789,19 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, break; if (newbuf == NULL) { - newbuf = gst_buffer_new_and_alloc (sizeof (Wavpack4Header) + blocksize); - gst_buffer_set_caps (newbuf, stream->caps); + out_size = sizeof (Wavpack4Header) + blocksize; + newbuf = gst_buffer_new_allocate (NULL, out_size, 0); - gst_buffer_copy_metadata (newbuf, *buf, - GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); + gst_buffer_copy_into (newbuf, *buf, + GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS, 0, -1); outpos = 0; - outdata = GST_BUFFER_DATA (newbuf); + outdata = gst_buffer_map (newbuf, NULL, NULL, GST_MAP_WRITE); } else { - GST_BUFFER_SIZE (newbuf) += sizeof (Wavpack4Header) + blocksize; - GST_BUFFER_DATA (newbuf) = - g_realloc (GST_BUFFER_DATA (newbuf), GST_BUFFER_SIZE (newbuf)); - GST_BUFFER_MALLOCDATA (newbuf) = GST_BUFFER_DATA (newbuf); - outdata = GST_BUFFER_DATA (newbuf); + gst_buffer_unmap (newbuf, outdata, out_size); + out_size += sizeof (Wavpack4Header) + blocksize; + gst_buffer_set_size (newbuf, out_size); + outdata = gst_buffer_map (newbuf, NULL, NULL, GST_MAP_WRITE); } outdata[outpos] = 'w'; @@ -2838,7 +2827,12 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, data += blocksize; size -= blocksize; } + gst_buffer_unmap (*buf, buf_data, buf_size); gst_buffer_unref (*buf); + + if (newbuf) + gst_buffer_unmap (newbuf, outdata, out_size); + *buf = newbuf; audiocontext->wvpk_block_index += block_samples; } @@ -2883,16 +2877,16 @@ gst_matroska_demux_check_subtitle_buffer (GstElement * element, GstMatroskaTrackContext * stream, GstBuffer ** buf) { GstMatroskaTrackSubtitleContext *sub_stream; - const gchar *encoding, *data; + const gchar *encoding; GError *err = NULL; GstBuffer *newbuf; gchar *utf8; - guint size; + gpointer data; + gsize size; sub_stream = (GstMatroskaTrackSubtitleContext *) stream; - data = (const gchar *) GST_BUFFER_DATA (*buf); - size = GST_BUFFER_SIZE (*buf); + data = gst_buffer_map (*buf, &size, NULL, GST_MAP_READ); if (!sub_stream->invalid_utf8) { if (g_utf8_validate (data, size, NULL)) { @@ -2934,17 +2928,14 @@ gst_matroska_demux_check_subtitle_buffer (GstElement * element, if (utf8 == NULL) utf8 = g_strdup ("invalid subtitle"); - newbuf = gst_buffer_new (); - GST_BUFFER_MALLOCDATA (newbuf) = (guint8 *) utf8; - GST_BUFFER_DATA (newbuf) = (guint8 *) utf8; - GST_BUFFER_SIZE (newbuf) = strlen (utf8); - gst_buffer_copy_metadata (newbuf, *buf, - GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); + newbuf = gst_buffer_new_wrapped (utf8, strlen (utf8)); + gst_buffer_copy_into (newbuf, *buf, + GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS, 0, -1); + gst_buffer_unmap (*buf, data, size); gst_buffer_unref (*buf); *buf = newbuf; - data = (const gchar *) GST_BUFFER_DATA (*buf); - size = GST_BUFFER_SIZE (*buf); + data = gst_buffer_map (*buf, &size, NULL, GST_MAP_READ); next: /* caps claim markup text, so we need to escape text, @@ -2955,12 +2946,10 @@ next: if (!sub_stream->seen_markup_tag) { utf8 = g_markup_escape_text (data, size); - newbuf = gst_buffer_new (); - GST_BUFFER_MALLOCDATA (newbuf) = (guint8 *) utf8; - GST_BUFFER_DATA (newbuf) = (guint8 *) utf8; - GST_BUFFER_SIZE (newbuf) = strlen (utf8); - gst_buffer_copy_metadata (newbuf, *buf, - GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); + newbuf = gst_buffer_new_wrapped (utf8, strlen (utf8)); + gst_buffer_copy_into (newbuf, *buf, + GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS, 0, -1); + gst_buffer_unmap (*buf, data, size); gst_buffer_unref (*buf); *buf = newbuf; @@ -2973,11 +2962,11 @@ static GstFlowReturn gst_matroska_demux_check_aac (GstElement * element, GstMatroskaTrackContext * stream, GstBuffer ** buf) { - const guint8 *data; + guint8 data[2]; guint size; - data = GST_BUFFER_DATA (*buf); - size = GST_BUFFER_SIZE (*buf); + gst_buffer_extract (*buf, 0, data, 2); + size = gst_buffer_get_size (*buf); if (size > 2 && data[0] == 0xff && (data[1] >> 4 == 0x0f)) { GstCaps *new_caps; @@ -2991,7 +2980,6 @@ gst_matroska_demux_check_aac (GstElement * element, gst_structure_remove_field (s, "codec_data"); gst_caps_replace (&stream->caps, new_caps); gst_pad_set_caps (stream->pad, new_caps); - gst_buffer_set_caps (*buf, new_caps); GST_DEBUG_OBJECT (element, "ADTS AAC audio data; removing codec-data, " "new caps: %" GST_PTR_FORMAT, new_caps); gst_caps_unref (new_caps); @@ -3003,6 +2991,44 @@ gst_matroska_demux_check_aac (GstElement * element, return GST_FLOW_OK; } +static GstBuffer * +gst_matroska_demux_align_buffer (GstMatroskaDemux * demux, + GstBuffer * buffer, gsize alignment) +{ + gpointer data; + gsize size; + + data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ); + + if (size < sizeof (guintptr)) { + gst_buffer_unmap (buffer, data, size); + return buffer; + } + + if (((guintptr) data) & (alignment - 1)) { + GstBuffer *new_buffer; + gpointer new_data; + + new_buffer = gst_buffer_new_allocate (NULL, + gst_buffer_get_size (buffer), alignment); + /* Copy data "by hand", so ensure alignment is kept: */ + new_data = gst_buffer_map (new_buffer, NULL, NULL, GST_MAP_WRITE); + memcpy (new_data, data, size); + gst_buffer_unmap (new_buffer, new_data, -1); + gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1); + GST_DEBUG_OBJECT (demux, "We want output aligned on %d, reallocated", + alignment); + + gst_buffer_unmap (buffer, data, size); + gst_buffer_unref (buffer); + + return new_buffer; + } + + gst_buffer_unmap (buffer, data, size); + return buffer; +} + static GstFlowReturn gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, GstEbmlRead * ebml, guint64 cluster_time, guint64 cluster_offset, @@ -3014,6 +3040,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, guint32 id; guint64 block_duration = -1; GstBuffer *buf = NULL; + gpointer buf_data = NULL; + gsize buf_size; gint stream_num = -1, n, laces = 0; guint size = 0; gint *lace_size = NULL; @@ -3044,14 +3072,16 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, guint8 *data; if (buf) { + gst_buffer_unmap (buf, buf_data, buf_size); gst_buffer_unref (buf); buf = NULL; } if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK) break; - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); + buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ); + data = buf_data; + size = buf_size; /* first byte(s): blocknum */ if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) @@ -3284,7 +3314,10 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, } /* need to refresh segment info ASAP */ - if (GST_CLOCK_TIME_IS_VALID (lace_time) && demux->need_newsegment) { + if (GST_CLOCK_TIME_IS_VALID (lace_time) && demux->need_segment) { + GstSegment *segment = &demux->common.segment; + guint64 segment_duration = 0; + GST_DEBUG_OBJECT (demux, "generating segment starting at %" GST_TIME_FORMAT, GST_TIME_ARGS (lace_time)); @@ -3294,15 +3327,17 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, "Setting stream start time to %" GST_TIME_FORMAT, GST_TIME_ARGS (lace_time)); } - gst_segment_set_newsegment (&demux->common.segment, FALSE, - demux->common.segment.rate, GST_FORMAT_TIME, lace_time, - GST_CLOCK_TIME_NONE, lace_time - demux->stream_start_time); + if (GST_CLOCK_TIME_IS_VALID (segment->stop)) + segment_duration = segment->stop - segment->start; + else if (GST_CLOCK_TIME_IS_VALID (segment->position)) + segment_duration = segment->position - segment->start; + segment->base += segment_duration / fabs (segment->rate); + segment->start = lace_time; + segment->stop = GST_CLOCK_TIME_NONE; + segment->position = lace_time - demux->stream_start_time; /* now convey our segment notion downstream */ - gst_matroska_demux_send_event (demux, gst_event_new_new_segment (FALSE, - demux->common.segment.rate, demux->common.segment.format, - demux->common.segment.start, demux->common.segment.stop, - demux->common.segment.start)); - demux->need_newsegment = FALSE; + gst_matroska_demux_send_event (demux, gst_event_new_segment (segment)); + demux->need_segment = FALSE; } if (block_duration != -1) { @@ -3379,8 +3414,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, } } - sub = gst_buffer_create_sub (buf, - GST_BUFFER_SIZE (buf) - size, lace_size[n]); + sub = gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL, + gst_buffer_get_size (buf) - size, lace_size[n]); GST_DEBUG_OBJECT (demux, "created subbuffer %p", sub); if (delta_unit) @@ -3424,9 +3459,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) && demux->common.segment.rate > 0.0) { GstClockTimeDiff diff; - GstEvent *event1, *event2; - /* only send newsegments with increasing start times, + /* only send segments with increasing start times, * otherwise if these go back and forth downstream (sinks) increase * accumulated time and running_time */ diff = GST_CLOCK_DIFF (demux->last_stop_end, lace_time); @@ -3434,40 +3468,43 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, && lace_time > demux->common.segment.start && (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop) || lace_time < demux->common.segment.stop)) { + GstSegment segment; + GstEvent *event1, *event2; GST_DEBUG_OBJECT (demux, "Gap of %" G_GINT64_FORMAT " ns detected in" "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). " - "Sending updated NEWSEGMENT events", diff, + "Sending updated SEGMENT events", diff, stream->index, GST_TIME_ARGS (stream->pos), GST_TIME_ARGS (lace_time)); - /* send newsegment events such that the gap is not accounted in - * accum time, hence running_time */ + /* send segment events such that the gap is not accounted in + * segment base time, hence running_time */ /* close ahead of gap */ - event1 = gst_event_new_new_segment (TRUE, - demux->common.segment.rate, demux->common.segment.format, - demux->last_stop_end, demux->last_stop_end, - demux->last_stop_end); + segment = demux->common.segment; + segment.start = demux->last_stop_end; + segment.stop = demux->last_stop_end; + segment.position = demux->last_stop_end; + event1 = gst_event_new_segment (&segment); /* skip gap */ - event2 = gst_event_new_new_segment (FALSE, - demux->common.segment.rate, - demux->common.segment.format, lace_time, - demux->common.segment.stop, lace_time); + segment.start = lace_time; + segment.stop = demux->common.segment.stop; + segment.position = lace_time; + event2 = gst_event_new_segment (&segment); GST_OBJECT_UNLOCK (demux); gst_matroska_demux_send_event (demux, event1); gst_matroska_demux_send_event (demux, event2); GST_OBJECT_LOCK (demux); /* align segment view with downstream, - * prevents double-counting accum when closing segment */ - gst_segment_set_newsegment (&demux->common.segment, FALSE, - demux->common.segment.rate, demux->common.segment.format, - lace_time, demux->common.segment.stop, lace_time); - demux->common.segment.last_stop = lace_time; + * prevents double-counting base time when closing segment */ + /* FIXME: in 0.10, the segment base/accum got updated here, but + * maybe we don't need that because of the double accounting + * mentioned above? */ + demux->common.segment = segment; } } - if (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.last_stop) - || demux->common.segment.last_stop < lace_time) { - demux->common.segment.last_stop = lace_time; + if (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.position) + || demux->common.segment.position < lace_time) { + demux->common.segment.position = lace_time; } GST_OBJECT_UNLOCK (demux); @@ -3485,8 +3522,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, if (demux->common.segment.duration == -1 || demux->common.segment.duration < lace_time - demux->stream_start_time) { - gst_segment_set_duration (&demux->common.segment, GST_FORMAT_TIME, - last_stop_end - demux->stream_start_time); + demux->common.segment.duration = + last_stop_end - demux->stream_start_time; GST_OBJECT_UNLOCK (demux); gst_element_post_message (GST_ELEMENT_CAST (demux), gst_message_new_duration (GST_OBJECT_CAST (demux), @@ -3515,7 +3552,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, GST_DEBUG_OBJECT (demux, "Pushing lace %d, data of size %d for stream %d, time=%" GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n, - GST_BUFFER_SIZE (sub), stream_num, + gst_buffer_get_size (sub), stream_num, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), GST_TIME_ARGS (GST_BUFFER_DURATION (sub))); @@ -3535,8 +3572,6 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, cluster_offset, NULL); } - gst_buffer_set_caps (sub, GST_PAD_CAPS (stream->pad)); - /* Postprocess the buffers depending on the codec used */ if (stream->postprocess_frame) { GST_LOG_OBJECT (demux, "running post process"); @@ -3550,16 +3585,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, elements typically assume minimal alignment. Therefore, create an aligned copy if necessary. */ g_assert (stream->alignment <= G_MEM_ALIGN); - if (((guintptr) GST_BUFFER_DATA (sub)) & (stream->alignment - 1)) { - GstBuffer *buffer = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (sub)); - memcpy (GST_BUFFER_DATA (buffer), GST_BUFFER_DATA (sub), - GST_BUFFER_SIZE (sub)); - gst_buffer_copy_metadata (buffer, sub, GST_BUFFER_COPY_ALL); - GST_DEBUG_OBJECT (demux, "We want output aligned on %d, reallocated", - stream->alignment); - gst_buffer_unref (sub); - sub = buffer; - } + sub = gst_matroska_demux_align_buffer (demux, sub, stream->alignment); ret = gst_pad_push (stream->pad, sub); if (demux->common.segment.rate < 0) { @@ -3585,8 +3611,10 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, } done: - if (buf) + if (buf) { + gst_buffer_unmap (buf, buf_data, buf_size); gst_buffer_unref (buf); + } g_free (lace_size); return ret; @@ -3966,10 +3994,9 @@ gst_matroska_demux_check_seekability (GstMatroskaDemux * demux) /* try harder to query upstream size if we didn't get it the first time */ if (seekable && stop == -1) { - GstFormat fmt = GST_FORMAT_BYTES; - GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop"); - gst_pad_query_peer_duration (demux->common.sinkpad, &fmt, &stop); + gst_pad_peer_query_duration (demux->common.sinkpad, GST_FORMAT_BYTES, + &stop); } /* if upstream doesn't know the size, it's likely that it's not seekable in @@ -4141,10 +4168,10 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, demux->first_cluster_offset = demux->common.offset; GST_DEBUG_OBJECT (demux, "signaling no more pads"); gst_element_no_more_pads (GST_ELEMENT (demux)); - /* send initial newsegment - we wait till we know the first + /* send initial segment - we wait till we know the first incoming timestamp, so we can properly set the start of the segment. */ - demux->need_newsegment = TRUE; + demux->need_segment = TRUE; } demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = demux->common.offset; @@ -4431,12 +4458,11 @@ pause: * if no stop was set */ if (GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) && !GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) { - GstEvent *event = - gst_event_new_new_segment_full (TRUE, demux->common.segment.rate, - demux->common.segment.applied_rate, demux->common.segment.format, - demux->common.segment.start, - MAX (demux->last_stop_end, demux->common.segment.start), - demux->common.segment.time); + GstSegment segment = demux->common.segment; + GstEvent *event; + + segment.stop = MAX (demux->last_stop_end, segment.start); + event = gst_event_new_segment (&segment); gst_matroska_demux_send_event (demux, event); } @@ -4492,14 +4518,14 @@ perform_seek_to_offset (GstMatroskaDemux * demux, guint64 offset) res = gst_pad_push_event (demux->common.sinkpad, event); - /* newsegment event will update offset */ + /* segment event will update offset */ return res; } static GstFlowReturn -gst_matroska_demux_chain (GstPad * pad, GstBuffer * buffer) +gst_matroska_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { - GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (pad)); + GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent); guint available; GstFlowReturn ret = GST_FLOW_OK; guint needed = 0; @@ -4544,32 +4570,26 @@ next: } static gboolean -gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) +gst_matroska_demux_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) { gboolean res = TRUE; - GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (pad)); + GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent); GST_DEBUG_OBJECT (demux, "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: { - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time = 0; - gboolean update; - GstSegment segment; + const GstSegment *segment; /* some debug output */ - gst_segment_init (&segment, GST_FORMAT_UNDEFINED); - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - gst_segment_set_newsegment_full (&segment, update, rate, arate, format, - start, stop, time); + gst_event_parse_segment (event, &segment); + /* FIXME: do we need to update segment base here (like accum in 0.10)? */ GST_DEBUG_OBJECT (demux, - "received format %d newsegment %" GST_SEGMENT_FORMAT, format, - &segment); + "received format %d segment %" GST_SEGMENT_FORMAT, segment->format, + segment); if (demux->common.state < GST_MATROSKA_READ_STATE_DATA) { GST_DEBUG_OBJECT (demux, "still starting"); @@ -4577,7 +4597,7 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) } /* we only expect a BYTE segment, e.g. following a seek */ - if (format != GST_FORMAT_BYTES) { + if (segment->format != GST_FORMAT_BYTES) { GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring"); goto exit; } @@ -4587,18 +4607,18 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) /* clear current segment leftover */ gst_adapter_clear (demux->common.adapter); /* and some streaming setup */ - demux->common.offset = start; + demux->common.offset = segment->start; /* do not know where we are; - * need to come across a cluster and generate newsegment */ - demux->common.segment.last_stop = GST_CLOCK_TIME_NONE; + * need to come across a cluster and generate segment */ + demux->common.segment.position = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; - demux->need_newsegment = TRUE; + demux->need_segment = TRUE; /* but keep some of the upstream segment */ - demux->common.segment.rate = rate; + demux->common.segment.rate = segment->rate; GST_OBJECT_UNLOCK (demux); exit: - /* chain will send initial newsegment after pads have been added, + /* chain will send initial segment after pads have been added, * or otherwise come up with one */ GST_DEBUG_OBJECT (demux, "eating event"); gst_event_unref (event); @@ -4625,14 +4645,14 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) GST_OBJECT_LOCK (demux); gst_matroska_read_common_reset_streams (&demux->common, GST_CLOCK_TIME_NONE, TRUE); - demux->common.segment.last_stop = GST_CLOCK_TIME_NONE; + demux->common.segment.position = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; GST_OBJECT_UNLOCK (demux); /* fall-through */ } default: - res = gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, parent, event); break; } @@ -4640,39 +4660,53 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) } static gboolean -gst_matroska_demux_sink_activate (GstPad * sinkpad) +gst_matroska_demux_sink_activate (GstPad * sinkpad, GstObject * parent) { - GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (sinkpad)); + GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent); + GstQuery *query; + gboolean pull_mode = FALSE; + + query = gst_query_new_scheduling (); - if (gst_pad_check_pull_range (sinkpad)) { + if (gst_pad_peer_query (sinkpad, query)) + pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL); + + gst_query_unref (query); + + if (pull_mode) { GST_DEBUG ("going to pull mode"); demux->streaming = FALSE; - return gst_pad_activate_pull (sinkpad, TRUE); + return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE); } else { GST_DEBUG ("going to push (streaming) mode"); demux->streaming = TRUE; - return gst_pad_activate_push (sinkpad, TRUE); + return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE); } - - return FALSE; } static gboolean -gst_matroska_demux_sink_activate_pull (GstPad * sinkpad, gboolean active) +gst_matroska_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent, + GstPadMode mode, gboolean active) { - GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (GST_PAD_PARENT (sinkpad)); - - if (active) { - /* if we have a scheduler we can start the task */ - demux->segment_running = TRUE; - gst_pad_start_task (sinkpad, (GstTaskFunction) gst_matroska_demux_loop, - sinkpad); - } else { - demux->segment_running = FALSE; - gst_pad_stop_task (sinkpad); + GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (parent); + + switch (mode) { + case GST_PAD_MODE_PULL: + if (active) { + /* if we have a scheduler we can start the task */ + demux->segment_running = TRUE; + gst_pad_start_task (sinkpad, (GstTaskFunction) gst_matroska_demux_loop, + sinkpad); + } else { + demux->segment_running = FALSE; + gst_pad_stop_task (sinkpad); + } + return TRUE; + case GST_PAD_MODE_PUSH: + return TRUE; + default: + return FALSE; } - - return TRUE; } static void @@ -4758,10 +4792,11 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * vids->imp_colors = GUINT32_FROM_LE (vids->imp_colors); if (size > sizeof (gst_riff_strf_vids)) { /* some extra_data */ - buf = gst_buffer_new_and_alloc (size - sizeof (gst_riff_strf_vids)); - memcpy (GST_BUFFER_DATA (buf), - (guint8 *) vids + sizeof (gst_riff_strf_vids), - GST_BUFFER_SIZE (buf)); + gsize offset = sizeof (gst_riff_strf_vids); + + buf = + gst_buffer_new_wrapped (g_memdup ((guint8 *) vids + offset, + size - offset), size - offset); } if (riff_fourcc) @@ -4782,28 +4817,28 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * g_free (vids); } } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED)) { - guint32 fourcc = 0; + const gchar *format = NULL; switch (videocontext->fourcc) { case GST_MAKE_FOURCC ('I', '4', '2', '0'): *codec_name = g_strdup ("Raw planar YUV 4:2:0"); - fourcc = videocontext->fourcc; + format = "I420"; break; case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): *codec_name = g_strdup ("Raw packed YUV 4:2:2"); - fourcc = videocontext->fourcc; + format = "YUY2"; break; case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): *codec_name = g_strdup ("Raw packed YUV 4:2:0"); - fourcc = videocontext->fourcc; + format = "YV12"; break; case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): *codec_name = g_strdup ("Raw packed YUV 4:2:2"); - fourcc = videocontext->fourcc; + format = "UYVY"; break; case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'): *codec_name = g_strdup ("Raw packed YUV 4:4:4 with alpha channel"); - fourcc = videocontext->fourcc; + format = "AYUV"; break; default: @@ -4812,8 +4847,8 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * return NULL; } - caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, fourcc, NULL); + caps = gst_caps_new_simple ("video/x-raw", + "format", G_TYPE_STRING, format, NULL); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_SP)) { caps = gst_caps_new_simple ("video/x-divx", "divxversion", G_TYPE_INT, 4, NULL); @@ -4832,9 +4867,9 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * "mpegversion", G_TYPE_INT, 4, "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); if (data) { - GstBuffer *priv = gst_buffer_new_and_alloc (size); + GstBuffer *priv; - memcpy (GST_BUFFER_DATA (priv), data, size); + priv = gst_buffer_new_wrapped (g_memdup (data, size), size); gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL); gst_buffer_unref (priv); } @@ -4867,12 +4902,12 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * *codec_name = g_strdup_printf ("MPEG-%d video", mpegversion); context->postprocess_frame = gst_matroska_demux_add_mpeg_seq_header; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MJPEG)) { - caps = gst_caps_new_simple ("image/jpeg", NULL); + caps = gst_caps_new_empty_simple ("image/jpeg"); *codec_name = g_strdup ("Motion-JPEG"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_MPEG4_AVC)) { - caps = gst_caps_new_simple ("video/x-h264", NULL); + caps = gst_caps_new_empty_simple ("video/x-h264"); if (data) { - GstBuffer *priv = gst_buffer_new_and_alloc (size); + GstBuffer *priv; /* First byte is the version, second is the profile indication, and third * is the 5 contraint_set_flags and 3 reserved bits. Fourth byte is the @@ -4880,7 +4915,7 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * gst_codec_utils_h264_caps_set_level_and_profile (caps, data + 1, size - 1); - memcpy (GST_BUFFER_DATA (priv), data, size); + priv = gst_buffer_new_wrapped (g_memdup (data, size), size); gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL); gst_buffer_unref (priv); @@ -4919,25 +4954,23 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext * subformat = GST_READ_UINT32_BE (data + 0x1a); rformat = GST_READ_UINT32_BE (data + 0x1e); - priv = gst_buffer_new_and_alloc (size - 0x1a); - - memcpy (GST_BUFFER_DATA (priv), data + 0x1a, size - 0x1a); - gst_caps_set_simple (caps, - "codec_data", GST_TYPE_BUFFER, priv, - "format", G_TYPE_INT, rformat, - "subformat", G_TYPE_INT, subformat, NULL); + priv = + gst_buffer_new_wrapped (g_memdup (data + 0x1a, size - 0x1a), + size - 0x1a); + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, "format", + G_TYPE_INT, rformat, "subformat", G_TYPE_INT, subformat, NULL); gst_buffer_unref (priv); } *codec_name = g_strdup_printf ("RealVideo %d.0", rmversion); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_THEORA)) { - caps = gst_caps_new_simple ("video/x-theora", NULL); + caps = gst_caps_new_empty_simple ("video/x-theora"); context->send_xiph_headers = TRUE; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_DIRAC)) { - caps = gst_caps_new_simple ("video/x-dirac", NULL); + caps = gst_caps_new_empty_simple ("video/x-dirac"); *codec_name = g_strdup_printf ("Dirac"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VP8)) { - caps = gst_caps_new_simple ("video/x-vp8", NULL); + caps = gst_caps_new_empty_simple ("video/x-vp8"); *codec_name = g_strdup_printf ("On2 VP8"); } else { GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id); @@ -5127,26 +5160,33 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * *codec_name = g_strdup_printf ("MPEG-1 layer %d", layer); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE) || !strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE)) { + gboolean sign; gint endianness; + GstAudioFormat format; + sign = (audiocontext->bitdepth != 8); if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE)) endianness = G_BIG_ENDIAN; else endianness = G_LITTLE_ENDIAN; - caps = gst_caps_new_simple ("audio/x-raw-int", - "width", G_TYPE_INT, audiocontext->bitdepth, - "depth", G_TYPE_INT, audiocontext->bitdepth, - "signed", G_TYPE_BOOLEAN, audiocontext->bitdepth != 8, - "endianness", G_TYPE_INT, endianness, NULL); + format = gst_audio_format_build_integer (sign, endianness, + audiocontext->bitdepth, audiocontext->bitdepth); + + caps = gst_caps_new_simple ("audio/x-raw", + "format", G_TYPE_STRING, gst_audio_format_to_string (format), NULL); *codec_name = g_strdup_printf ("Raw %d-bit PCM audio", audiocontext->bitdepth); context->alignment = audiocontext->bitdepth / 8; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT)) { - caps = gst_caps_new_simple ("audio/x-raw-float", - "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, - "width", G_TYPE_INT, audiocontext->bitdepth, NULL); + const gchar *format; + if (audiocontext->bitdepth == 32) + format = "F32LE"; + else + format = "F64LE"; + caps = gst_caps_new_simple ("audio/x-raw", + "format", G_TYPE_STRING, format, NULL); *codec_name = g_strdup_printf ("Raw %d-bit floating-point audio", audiocontext->bitdepth); context->alignment = audiocontext->bitdepth / 8; @@ -5161,23 +5201,23 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * "framed", G_TYPE_BOOLEAN, TRUE, NULL); *codec_name = g_strdup ("E-AC-3 audio"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_DTS)) { - caps = gst_caps_new_simple ("audio/x-dts", NULL); + caps = gst_caps_new_empty_simple ("audio/x-dts"); *codec_name = g_strdup ("DTS audio"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_VORBIS)) { - caps = gst_caps_new_simple ("audio/x-vorbis", NULL); + caps = gst_caps_new_empty_simple ("audio/x-vorbis"); context->send_xiph_headers = TRUE; /* vorbis decoder does tags */ } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_FLAC)) { - caps = gst_caps_new_simple ("audio/x-flac", NULL); + caps = gst_caps_new_empty_simple ("audio/x-flac"); context->send_flac_headers = TRUE; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_SPEEX)) { - caps = gst_caps_new_simple ("audio/x-speex", NULL); + caps = gst_caps_new_empty_simple ("audio/x-speex"); context->send_speex_headers = TRUE; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_ACM)) { gst_riff_strf_auds auds; if (data) { - GstBuffer *codec_data = gst_buffer_new (); + GstBuffer *codec_data; /* little-endian -> byte-order */ auds.format = GST_READ_UINT16_LE (data); @@ -5188,7 +5228,7 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * auds.size = GST_READ_UINT16_LE (data + 16); /* 18 is the waveformatex size */ - gst_buffer_set_data (codec_data, data + 18, auds.size); + codec_data = gst_buffer_new_wrapped_full (data + 18, NULL, 0, auds.size); if (riff_audio_fmt) *riff_audio_fmt = auds.format; @@ -5219,9 +5259,8 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * if (freq_index == 15) explicit_freq_bytes = 3; GST_DEBUG ("obj_type = %u, freq_index = %u", obj_type, freq_index); - priv = gst_buffer_new_and_alloc (context->codec_priv_size); - memcpy (GST_BUFFER_DATA (priv), context->codec_priv, - context->codec_priv_size); + priv = gst_buffer_new_wrapped (g_memdup (context->codec_priv, + context->codec_priv_size), context->codec_priv_size); /* assume SBR if samplerate <= 24kHz */ if (obj_type == 5 || (freq_index >= 6 && freq_index != 15) || (context->codec_priv_size == (5 + explicit_freq_bytes))) { @@ -5241,18 +5280,19 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * /* make up decoder-specific data if it is not supplied */ if (priv == NULL) { - priv = gst_buffer_new_and_alloc (5); - data = GST_BUFFER_DATA (priv); + priv = gst_buffer_new_allocate (NULL, 5, 0); + data = gst_buffer_map (priv, NULL, NULL, GST_MAP_WRITE); rate_idx = aac_rate_idx (audiocontext->samplerate); profile = aac_profile_idx (codec_id); data[0] = ((profile + 1) << 3) | ((rate_idx & 0xE) >> 1); data[1] = ((rate_idx & 0x1) << 7) | (audiocontext->channels << 3); - GST_BUFFER_SIZE (priv) = 2; if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2, strlen (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG2))) { mpegversion = 2; + gst_buffer_unmap (priv, data, 5); + gst_buffer_set_size (priv, 2); } else if (!strncmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4, strlen (GST_MATROSKA_CODEC_ID_AUDIO_AAC_MPEG4))) { mpegversion = 4; @@ -5264,9 +5304,13 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * data[2] = AAC_SYNC_EXTENSION_TYPE >> 3; data[3] = ((AAC_SYNC_EXTENSION_TYPE & 0x07) << 5) | 5; data[4] = (1 << 7) | (rate_idx << 3); - GST_BUFFER_SIZE (priv) = 5; + gst_buffer_unmap (priv, data, 5); + } else { + gst_buffer_unmap (priv, data, 5); + gst_buffer_set_size (priv, 2); } } else { + gst_buffer_unmap (priv, data, 5); gst_buffer_unref (priv); priv = NULL; GST_ERROR ("Unknown AAC profile and no codec private data"); @@ -5335,8 +5379,8 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * G_TYPE_INT, leaf_size, "width", G_TYPE_INT, sample_width, NULL); if ((size - 78) >= extra_data_size) { - priv = gst_buffer_new_and_alloc (extra_data_size); - memcpy (GST_BUFFER_DATA (priv), data + 78, extra_data_size); + priv = gst_buffer_new_wrapped (g_memdup (data + 78, extra_data_size), + extra_data_size); gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL); gst_buffer_unref (priv); } @@ -5345,13 +5389,13 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * *codec_name = g_strdup_printf ("RealAudio %d.0", raversion); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR)) { - caps = gst_caps_new_simple ("audio/x-sipro", NULL); + caps = gst_caps_new_empty_simple ("audio/x-sipro"); *codec_name = g_strdup ("Sipro/ACELP.NET Voice Codec"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_RALF)) { - caps = gst_caps_new_simple ("audio/x-ralf-mpeg4-generic", NULL); + caps = gst_caps_new_empty_simple ("audio/x-ralf-mpeg4-generic"); *codec_name = g_strdup ("Real Audio Lossless"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_ATRC)) { - caps = gst_caps_new_simple ("audio/x-vnd.sony.atrac3", NULL); + caps = gst_caps_new_empty_simple ("audio/x-vnd.sony.atrac3"); *codec_name = g_strdup ("Sony ATRAC3"); } else { GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id); @@ -5397,35 +5441,34 @@ gst_matroska_demux_subtitle_caps (GstMatroskaTrackSubtitleContext * * Check if we have to do something with codec_private */ if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_UTF8)) { /* well, plain text simply does not have a lot of markup ... */ - caps = gst_caps_new_simple ("text/x-pango-markup", NULL); + caps = gst_caps_new_empty_simple ("text/x-pango-markup"); context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_SSA)) { - caps = gst_caps_new_simple ("application/x-ssa", NULL); + caps = gst_caps_new_empty_simple ("application/x-ssa"); context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_ASS)) { - caps = gst_caps_new_simple ("application/x-ass", NULL); + caps = gst_caps_new_empty_simple ("application/x-ass"); context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_USF)) { - caps = gst_caps_new_simple ("application/x-usf", NULL); + caps = gst_caps_new_empty_simple ("application/x-usf"); context->postprocess_frame = gst_matroska_demux_check_subtitle_buffer; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_VOBSUB)) { - caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL); + caps = gst_caps_new_empty_simple ("video/x-dvd-subpicture"); ((GstMatroskaTrackContext *) subtitlecontext)->send_dvd_event = TRUE; } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_HDMVPGS)) { - caps = gst_caps_new_simple ("subpicture/x-pgs", NULL); + caps = gst_caps_new_empty_simple ("subpicture/x-pgs"); } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_SUBTITLE_KATE)) { - caps = gst_caps_new_simple ("subtitle/x-kate", NULL); + caps = gst_caps_new_empty_simple ("subtitle/x-kate"); context->send_xiph_headers = TRUE; } else { GST_DEBUG ("Unknown subtitle stream: codec_id='%s'", codec_id); - caps = gst_caps_new_simple ("application/x-subtitle-unknown", NULL); + caps = gst_caps_new_empty_simple ("application/x-subtitle-unknown"); } if (data != NULL && size > 0) { GstBuffer *buf; - buf = gst_buffer_new_and_alloc (size); - memcpy (GST_BUFFER_DATA (buf), data, size); + buf = gst_buffer_new_wrapped (g_memdup (data, size), size); gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL); gst_buffer_unref (buf); } diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index 2b08b2e..65061c1 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -87,7 +87,7 @@ typedef struct _GstMatroskaDemux { gboolean building_index; guint64 index_offset; GstEvent *seek_event; - gboolean need_newsegment; + gboolean need_segment; /* reverse playback */ GArray *seek_index; diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h index ade72a0..ec56bb1 100644 --- a/gst/matroska/matroska-ids.h +++ b/gst/matroska/matroska-ids.h @@ -486,10 +486,10 @@ struct _GstMatroskaTrackContext { /* some often-used info */ gchar *codec_id, *codec_name, *name, *language; - guint8 *codec_priv; - guint codec_priv_size; - guint8 *codec_state; - guint codec_state_size; + gpointer codec_priv; + gsize codec_priv_size; + gpointer codec_state; + gsize codec_state_size; GstMatroskaTrackType type; guint uid, num; GstMatroskaTrackFlags flags; diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index 06e7d42..bc87b80 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -126,8 +127,8 @@ static GstStaticPadTemplate videosink_templ = COMMON_VIDEO_CAPS "; " "video/x-vp8, " COMMON_VIDEO_CAPS "; " - "video/x-raw-yuv, " - "format = (fourcc) { YUY2, I420, YV12, UYVY, AYUV }, " + "video/x-raw, " + "format = (string) { YUY2, I420, YV12, UYVY, AYUV }, " COMMON_VIDEO_CAPS "; " "video/x-wmv, " "wmvversion = (int) [ 1, 3 ], " COMMON_VIDEO_CAPS) ); @@ -163,32 +164,8 @@ static GstStaticPadTemplate audiosink_templ = COMMON_AUDIO_CAPS "; " "audio/x-speex, " COMMON_AUDIO_CAPS "; " - "audio/x-raw-int, " - "width = (int) 8, " - "depth = (int) 8, " - "signed = (boolean) false, " - COMMON_AUDIO_CAPS ";" - "audio/x-raw-int, " - "width = (int) 16, " - "depth = (int) 16, " - "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " - "signed = (boolean) true, " - COMMON_AUDIO_CAPS ";" - "audio/x-raw-int, " - "width = (int) 24, " - "depth = (int) 24, " - "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " - "signed = (boolean) true, " - COMMON_AUDIO_CAPS ";" - "audio/x-raw-int, " - "width = (int) 32, " - "depth = (int) 32, " - "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " - "signed = (boolean) true, " - COMMON_AUDIO_CAPS ";" - "audio/x-raw-float, " - "width = (int) [ 32, 64 ], " - "endianness = (int) LITTLE_ENDIAN, " + "audio/x-raw, " + "format = (string) { U8, S16BE, S16LE, S24BE, S24LE, S32BE, S32LE, F32LE, F64LE }, " COMMON_AUDIO_CAPS ";" "audio/x-tta, " "width = (int) { 8, 16, 24 }, " @@ -213,10 +190,9 @@ GST_STATIC_PAD_TEMPLATE ("subtitle_%u", static GArray *used_uids; G_LOCK_DEFINE_STATIC (used_uids); -static void gst_matroska_mux_add_interfaces (GType type); - -GST_BOILERPLATE_FULL (GstMatroskaMux, gst_matroska_mux, GstElement, - GST_TYPE_ELEMENT, gst_matroska_mux_add_interfaces); +#define parent_class gst_matroska_mux_parent_class +G_DEFINE_TYPE_WITH_CODE (GstMatroskaMux, gst_matroska_mux, GST_TYPE_ELEMENT, + G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL)); /* Matroska muxer destructor */ static void gst_matroska_mux_finalize (GObject * object); @@ -227,9 +203,9 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data); /* pad functions */ static gboolean gst_matroska_mux_handle_src_event (GstPad * pad, - GstEvent * event); + GstObject * parent, GstEvent * event); static GstPad *gst_matroska_mux_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name); + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); static void gst_matroska_mux_release_pad (GstElement * element, GstPad * pad); /* gst internal change state handler */ @@ -263,19 +239,6 @@ gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag, gpointer data); static void -gst_matroska_mux_add_interfaces (GType type) -{ - static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL }; - - g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, &tag_setter_info); -} - -static void -gst_matroska_mux_base_init (gpointer g_class) -{ -} - -static void gst_matroska_mux_class_init (GstMatroskaMuxClass * klass) { GObjectClass *gobject_class; @@ -343,12 +306,12 @@ gst_matroska_mux_class_init (GstMatroskaMuxClass * klass) * Matroska muxer constructor. */ static void -gst_matroska_mux_init (GstMatroskaMux * mux, GstMatroskaMuxClass * g_class) +gst_matroska_mux_init (GstMatroskaMux * mux) { GstPadTemplate *templ; templ = - gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (mux), "src"); mux->srcpad = gst_pad_new_from_template (templ, "src"); gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event); @@ -586,7 +549,8 @@ gst_matroska_mux_reset (GstElement * element) * Returns: #TRUE on success. */ static gboolean -gst_matroska_mux_handle_src_event (GstPad * pad, GstEvent * event) +gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent, + GstEvent * event) { GstEventType type; @@ -600,7 +564,7 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstEvent * event) break; } - return gst_pad_event_default (pad, event); + return gst_pad_event_default (pad, parent, event); } /** @@ -613,17 +577,27 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstEvent * event) * Returns: #TRUE on success. */ static gboolean -gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event) +gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) { GstMatroskaTrackContext *context; GstMatroskaPad *collect_pad; - GstMatroskaMux *mux; + GstMatroskaMux *mux = GST_MATROSKA_MUX (parent); GstTagList *list; gboolean ret = TRUE; - mux = GST_MATROSKA_MUX (gst_pad_get_parent (pad)); - switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CAPS:{ + GstCaps *caps; + + collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad); + gst_event_parse_caps (event, &caps); + + ret = collect_pad->capsfunc (pad, caps); + gst_event_unref (event); + event = NULL; + break; + } case GST_EVENT_TAG:{ gchar *lang = NULL; @@ -658,12 +632,11 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event) event = NULL; break; } - case GST_EVENT_NEWSEGMENT:{ - GstFormat format; + case GST_EVENT_SEGMENT:{ + const GstSegment *segment; - gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL, - NULL); - if (format != GST_FORMAT_TIME) { + gst_event_parse_segment (event, &segment); + if (segment->format != GST_FORMAT_TIME) { ret = FALSE; gst_event_unref (event); event = NULL; @@ -687,9 +660,7 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event) /* now GstCollectPads can take care of the rest, e.g. EOS */ if (event) - ret = mux->collect_event (pad, event); - - gst_object_unref (mux); + ret = mux->collect_event (pad, parent, event); return ret; } @@ -714,7 +685,7 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) GstStructure *structure; const gchar *mimetype; const GValue *value = NULL; - const GstBuffer *codec_buf = NULL; + GstBuffer *codec_buf = NULL; gint width, height, pixel_width, pixel_height; gint fps_d, fps_n; gboolean interlaced = FALSE; @@ -790,12 +761,17 @@ skip_details: /* extract codec_data, may turn out needed */ value = gst_structure_get_value (structure, "codec_data"); if (value) - codec_buf = gst_value_get_buffer (value); + codec_buf = (GstBuffer *) gst_value_get_buffer (value); /* find type */ - if (!strcmp (mimetype, "video/x-raw-yuv")) { + if (!strcmp (mimetype, "video/x-raw")) { + const gchar *fstr; context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED); - gst_structure_get_fourcc (structure, "format", &videocontext->fourcc); + fstr = gst_structure_get_string (structure, "format"); + if (fstr && strlen (fstr) == 4) + videocontext->fourcc = GST_STR_FOURCC (fstr); + } else if (!strcmp (mimetype, "image/jpeg")) { + context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG); } else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */ ||!strcmp (mimetype, "video/x-huffyuv") || !strcmp (mimetype, "video/x-divx") @@ -848,9 +824,11 @@ skip_details: } } else if (!strcmp (mimetype, "video/x-wmv")) { gint wmvversion; - guint32 format; - if (gst_structure_get_fourcc (structure, "format", &format)) { - fourcc = format; + const gchar *fstr; + + fstr = gst_structure_get_string (structure, "format"); + if (fstr && strlen (fstr) == 4) { + fourcc = GST_STR_FOURCC (fstr); } else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) { if (wmvversion == 2) { fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2'); @@ -879,11 +857,11 @@ skip_details: /* process codec private/initialization data, if any */ if (codec_buf) { - size += GST_BUFFER_SIZE (codec_buf); + size += gst_buffer_get_size (codec_buf); bih = g_realloc (bih, size); GST_WRITE_UINT32_LE (&bih->size, size); - memcpy ((guint8 *) bih + sizeof (gst_riff_strf_vids), - GST_BUFFER_DATA (codec_buf), GST_BUFFER_SIZE (codec_buf)); + gst_buffer_extract (codec_buf, 0, + (guint8 *) bih + sizeof (gst_riff_strf_vids), -1); } context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC); @@ -900,10 +878,9 @@ skip_details: /* Create avcC header */ if (codec_buf != NULL) { - context->codec_priv_size = GST_BUFFER_SIZE (codec_buf); + context->codec_priv_size = gst_buffer_get_size (codec_buf); context->codec_priv = g_malloc0 (context->codec_priv_size); - memcpy (context->codec_priv, GST_BUFFER_DATA (codec_buf), - context->codec_priv_size); + gst_buffer_extract (codec_buf, 0, context->codec_priv, -1); } } else if (!strcmp (mimetype, "video/x-theora")) { const GValue *streamheader; @@ -946,10 +923,9 @@ skip_details: /* global headers may be in codec data */ if (codec_buf != NULL) { - context->codec_priv_size = GST_BUFFER_SIZE (codec_buf); + context->codec_priv_size = gst_buffer_get_size (codec_buf); context->codec_priv = g_malloc0 (context->codec_priv_size); - memcpy (context->codec_priv, GST_BUFFER_DATA (codec_buf), - context->codec_priv_size); + gst_buffer_extract (codec_buf, 0, context->codec_priv, -1); } } else if (!strcmp (mimetype, "video/x-msmpeg")) { msmpeg43: @@ -984,10 +960,10 @@ skip_details: GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data); - priv_data_size = GST_BUFFER_SIZE (codec_data_buf); + priv_data_size = gst_buffer_get_size (codec_data_buf); priv_data = g_malloc0 (priv_data_size); - memcpy (priv_data, GST_BUFFER_DATA (codec_data_buf), priv_data_size); + gst_buffer_extract (codec_data_buf, 0, priv_data, -1); context->codec_priv = priv_data; context->codec_priv_size = priv_data_size; @@ -1045,12 +1021,12 @@ xiphN_streamheader_to_codecdata (const GValue * streamheader, priv_data_size = 1; if (bufarr->len > 0) { for (i = 0; i < bufarr->len - 1; i++) { - priv_data_size += GST_BUFFER_SIZE (buf[i]) / 0xff + 1; + priv_data_size += gst_buffer_get_size (buf[i]) / 0xff + 1; } } for (i = 0; i < bufarr->len; ++i) { - priv_data_size += GST_BUFFER_SIZE (buf[i]); + priv_data_size += gst_buffer_get_size (buf[i]); } priv_data = g_malloc0 (priv_data_size); @@ -1060,17 +1036,16 @@ xiphN_streamheader_to_codecdata (const GValue * streamheader, if (bufarr->len > 0) { for (bufi = 0; bufi < bufarr->len - 1; bufi++) { - for (i = 0; i < GST_BUFFER_SIZE (buf[bufi]) / 0xff; ++i) { + for (i = 0; i < gst_buffer_get_size (buf[bufi]) / 0xff; ++i) { priv_data[offset++] = 0xff; } - priv_data[offset++] = GST_BUFFER_SIZE (buf[bufi]) % 0xff; + priv_data[offset++] = gst_buffer_get_size (buf[bufi]) % 0xff; } } for (i = 0; i < bufarr->len; ++i) { - memcpy (priv_data + offset, GST_BUFFER_DATA (buf[i]), - GST_BUFFER_SIZE (buf[i])); - offset += GST_BUFFER_SIZE (buf[i]); + gst_buffer_extract (buf[i], 0, priv_data + offset, -1); + offset += gst_buffer_get_size (buf[i]); } context->codec_priv = priv_data; @@ -1116,17 +1091,19 @@ vorbis_streamheader_to_codecdata (const GValue * streamheader, if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3)) return FALSE; - if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 4) { + if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 4) { GST_WARNING ("First vorbis header too small, ignoring"); } else { - if (memcmp (GST_BUFFER_DATA (buf0) + 1, "vorbis", 6) == 0) { + if (gst_buffer_memcmp (buf0, 1, "vorbis", 6) == 0) { GstMatroskaTrackAudioContext *audiocontext; - guint8 *hdr; + guint8 *data, *hdr; - hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 4; + data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ); + hdr = data + 1 + 6 + 4; audiocontext = (GstMatroskaTrackAudioContext *) context; audiocontext->channels = GST_READ_UINT8 (hdr); audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1); + gst_buffer_unmap (buf0, data, -1); } } @@ -1145,16 +1122,17 @@ theora_streamheader_to_codecdata (const GValue * streamheader, if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3)) return FALSE; - if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 26) { + if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 26) { GST_WARNING ("First theora header too small, ignoring"); - } else if (memcmp (GST_BUFFER_DATA (buf0), "\200theora\003\002", 9) != 0) { + } else if (gst_buffer_memcmp (buf0, 0, "\200theora\003\002", 9) != 0) { GST_WARNING ("First header not a theora identification header, ignoring"); } else { GstMatroskaTrackVideoContext *videocontext; guint fps_num, fps_denom, par_num, par_denom; - guint8 *hdr; + guint8 *data, *hdr; - hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 3 + 2 + 2; + data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ); + hdr = data + 1 + 6 + 3 + 2 + 2; videocontext = (GstMatroskaTrackVideoContext *) context; videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8; @@ -1185,6 +1163,8 @@ theora_streamheader_to_codecdata (const GValue * streamheader, videocontext->display_height = 0; } hdr += 3 + 3; + + gst_buffer_unmap (buf0, data, -1); } if (buf0) @@ -1202,9 +1182,9 @@ kate_streamheader_to_codecdata (const GValue * streamheader, if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1)) return FALSE; - if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 64) { /* Kate ID header is 64 bytes */ + if (buf0 == NULL || gst_buffer_get_size (buf0) < 64) { /* Kate ID header is 64 bytes */ GST_WARNING ("First kate header too small, ignoring"); - } else if (memcmp (GST_BUFFER_DATA (buf0), "\200kate\0\0\0", 8) != 0) { + } else if (gst_buffer_memcmp (buf0, 0, "\200kate\0\0\0", 8) != 0) { GST_WARNING ("First header not a kate identification header, ignoring"); } @@ -1245,19 +1225,19 @@ flac_streamheader_to_codecdata (const GValue * streamheader, buffer = g_value_peek_pointer (bufval); /* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */ - if (GST_BUFFER_SIZE (buffer) < 9 + 4 + 4 + 34 - || memcmp (GST_BUFFER_DATA (buffer) + 1, "FLAC", 4) != 0 - || memcmp (GST_BUFFER_DATA (buffer) + 9, "fLaC", 4) != 0) { + if (gst_buffer_get_size (buffer) < 9 + 4 + 4 + 34 + || gst_buffer_memcmp (buffer, 1, "FLAC", 4) != 0 + || gst_buffer_memcmp (buffer, 9, "fLaC", 4) != 0) { GST_WARNING ("Invalid streamheader for FLAC"); return FALSE; } - context->codec_priv = g_malloc (GST_BUFFER_SIZE (buffer) - 9); - context->codec_priv_size = GST_BUFFER_SIZE (buffer) - 9; - memcpy (context->codec_priv, GST_BUFFER_DATA (buffer) + 9, - GST_BUFFER_SIZE (buffer) - 9); + context->codec_priv_size = gst_buffer_get_size (buffer) - 9; + context->codec_priv = g_malloc (context->codec_priv_size); + gst_buffer_extract (buffer, 9, context->codec_priv, -1); for (i = 1; i < bufarr->len; i++) { + guint old_size; bufval = &g_array_index (bufarr, GValue, i); if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) { @@ -1270,13 +1250,13 @@ flac_streamheader_to_codecdata (const GValue * streamheader, buffer = g_value_peek_pointer (bufval); - context->codec_priv = - g_realloc (context->codec_priv, - context->codec_priv_size + GST_BUFFER_SIZE (buffer)); - memcpy ((guint8 *) context->codec_priv + context->codec_priv_size, - GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); - context->codec_priv_size = - context->codec_priv_size + GST_BUFFER_SIZE (buffer); + old_size = context->codec_priv_size; + context->codec_priv_size += gst_buffer_get_size (buffer); + + context->codec_priv = g_realloc (context->codec_priv, + context->codec_priv_size); + gst_buffer_extract (buffer, 0, + (guint8 *) context->codec_priv + old_size, -1); } return TRUE; @@ -1289,6 +1269,7 @@ speex_streamheader_to_codecdata (const GValue * streamheader, GArray *bufarr; GValue *bufval; GstBuffer *buffer; + guint old_size; if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) { GST_WARNING ("No or invalid streamheader field in the caps"); @@ -1311,16 +1292,15 @@ speex_streamheader_to_codecdata (const GValue * streamheader, buffer = g_value_peek_pointer (bufval); - if (GST_BUFFER_SIZE (buffer) < 80 - || memcmp (GST_BUFFER_DATA (buffer), "Speex ", 8) != 0) { + if (gst_buffer_get_size (buffer) < 80 + || gst_buffer_memcmp (buffer, 0, "Speex ", 8) != 0) { GST_WARNING ("Invalid streamheader for Speex"); return FALSE; } - context->codec_priv = g_malloc (GST_BUFFER_SIZE (buffer)); - context->codec_priv_size = GST_BUFFER_SIZE (buffer); - memcpy (context->codec_priv, GST_BUFFER_DATA (buffer), - GST_BUFFER_SIZE (buffer)); + context->codec_priv_size = gst_buffer_get_size (buffer); + context->codec_priv = g_malloc (context->codec_priv_size); + gst_buffer_extract (buffer, 0, context->codec_priv, -1); bufval = &g_array_index (bufarr, GValue, 1); @@ -1334,28 +1314,26 @@ speex_streamheader_to_codecdata (const GValue * streamheader, buffer = g_value_peek_pointer (bufval); - context->codec_priv = - g_realloc (context->codec_priv, - context->codec_priv_size + GST_BUFFER_SIZE (buffer)); - memcpy ((guint8 *) context->codec_priv + context->codec_priv_size, - GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); - context->codec_priv_size = - context->codec_priv_size + GST_BUFFER_SIZE (buffer); + old_size = context->codec_priv_size; + context->codec_priv_size += gst_buffer_get_size (buffer); + context->codec_priv = g_realloc (context->codec_priv, + context->codec_priv_size); + gst_buffer_extract (buffer, 0, (guint8 *) context->codec_priv + old_size, -1); return TRUE; } static const gchar * -aac_codec_data_to_codec_id (const GstBuffer * buf) +aac_codec_data_to_codec_id (GstBuffer * buf) { const gchar *result; - gint profile; + guint8 profile; /* default to MAIN */ profile = 1; - if (GST_BUFFER_SIZE (buf) >= 2) { - profile = GST_READ_UINT8 (GST_BUFFER_DATA (buf)); + if (gst_buffer_get_size (buf) >= 2) { + gst_buffer_extract (buf, 0, &profile, 1); profile >>= 3; } @@ -1401,7 +1379,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) gint samplerate = 0, channels = 0; GstStructure *structure; const GValue *codec_data = NULL; - const GstBuffer *buf = NULL; + GstBuffer *buf = NULL; const gchar *stream_format = NULL; mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad)); @@ -1513,51 +1491,45 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) default: goto refuse_caps; } - } else if (!strcmp (mimetype, "audio/x-raw-int")) { - gint width, depth; - gint endianness = G_LITTLE_ENDIAN; - gboolean signedness = TRUE; - - if (!gst_structure_get_int (structure, "width", &width) || - !gst_structure_get_int (structure, "depth", &depth) || - !gst_structure_get_boolean (structure, "signed", &signedness)) { - GST_DEBUG_OBJECT (mux, "broken caps, width/depth/signed field missing"); - goto refuse_caps; - } - - if (depth > 8 && - !gst_structure_get_int (structure, "endianness", &endianness)) { - GST_DEBUG_OBJECT (mux, "broken caps, no endianness specified"); - goto refuse_caps; - } - - if (width != depth) { - GST_DEBUG_OBJECT (mux, "width must be same as depth!"); - goto refuse_caps; - } + } else if (!strcmp (mimetype, "audio/x-raw")) { + GstAudioInfo info; - /* FIXME: where is this spec'ed out? (tpm) */ - if ((width == 8 && signedness) || (width >= 16 && !signedness)) { - GST_DEBUG_OBJECT (mux, "8-bit PCM must be unsigned, 16-bit PCM signed"); + gst_audio_info_init (&info); + if (!gst_audio_info_from_caps (&info, caps)) { + GST_DEBUG_OBJECT (mux, + "broken caps, rejected by gst_audio_info_from_caps"); goto refuse_caps; } - audiocontext->bitdepth = depth; - if (endianness == G_BIG_ENDIAN) - context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE); - else - context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE); + switch (GST_AUDIO_INFO_FORMAT (&info)) { + case GST_AUDIO_FORMAT_U8: + case GST_AUDIO_FORMAT_S16BE: + case GST_AUDIO_FORMAT_S16LE: + case GST_AUDIO_FORMAT_S24BE: + case GST_AUDIO_FORMAT_S24LE: + case GST_AUDIO_FORMAT_S32BE: + case GST_AUDIO_FORMAT_S32LE: + if (GST_AUDIO_INFO_WIDTH (&info) != GST_AUDIO_INFO_DEPTH (&info)) { + GST_DEBUG_OBJECT (mux, "width must be same as depth!"); + goto refuse_caps; + } + if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info)) + context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE); + else + context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE); + break; - } else if (!strcmp (mimetype, "audio/x-raw-float")) { - gint width; + case GST_AUDIO_FORMAT_F32LE: + case GST_AUDIO_FORMAT_F64LE: + context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT); + break; - if (!gst_structure_get_int (structure, "width", &width)) { - GST_DEBUG_OBJECT (mux, "broken caps, width field missing"); - goto refuse_caps; + default: + GST_DEBUG_OBJECT (mux, "wrong format in raw audio caps"); + goto refuse_caps; } - audiocontext->bitdepth = width; - context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT); + audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info); } else if (!strcmp (mimetype, "audio/x-vorbis")) { const GValue *streamheader; @@ -1650,10 +1622,10 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data); - priv_data_size = GST_BUFFER_SIZE (codec_data_buf); + priv_data_size = gst_buffer_get_size (codec_data_buf); priv_data = g_malloc0 (priv_data_size); - memcpy (priv_data, GST_BUFFER_DATA (codec_data_buf), priv_data_size); + gst_buffer_extract (codec_data_buf, 0, priv_data, -1); context->codec_priv = priv_data; context->codec_priv_size = priv_data_size; @@ -1717,7 +1689,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) codec_priv_size = WAVEFORMATEX_SIZE; if (buf) - codec_priv_size += GST_BUFFER_SIZE (buf); + codec_priv_size += gst_buffer_get_size (buf); /* serialize waveformatex structure */ codec_priv = g_malloc0 (codec_priv_size); @@ -1728,14 +1700,14 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps) GST_WRITE_UINT16_LE (codec_priv + 12, block_align); GST_WRITE_UINT16_LE (codec_priv + 14, 0); if (buf) - GST_WRITE_UINT16_LE (codec_priv + 16, GST_BUFFER_SIZE (buf)); + GST_WRITE_UINT16_LE (codec_priv + 16, gst_buffer_get_size (buf)); else GST_WRITE_UINT16_LE (codec_priv + 16, 0); /* process codec private/initialization data, if any */ if (buf) { - memcpy ((guint8 *) codec_priv + WAVEFORMATEX_SIZE, - GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_buffer_extract (buf, 0, + (guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1); } context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM); @@ -1839,7 +1811,7 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps) */ static GstPad * gst_matroska_mux_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * req_name) + GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps) { GstElementClass *klass = GST_ELEMENT_GET_CLASS (element); GstMatroskaMux *mux = GST_MATROSKA_MUX (element); @@ -1847,7 +1819,7 @@ gst_matroska_mux_request_new_pad (GstElement * element, GstPad *newpad = NULL; gchar *name = NULL; const gchar *pad_name = NULL; - GstPadSetCapsFunction setcapsfunc = NULL; + GstMatroskaCapsFunc capsfunc = NULL; GstMatroskaTrackContext *context = NULL; gint pad_id; @@ -1860,7 +1832,7 @@ gst_matroska_mux_request_new_pad (GstElement * element, name = g_strdup_printf ("audio_%u", mux->num_a_streams++); pad_name = name; } - setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps); + capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps); context = (GstMatroskaTrackContext *) g_new0 (GstMatroskaTrackAudioContext, 1); context->type = GST_MATROSKA_TRACK_TYPE_AUDIO; @@ -1874,7 +1846,7 @@ gst_matroska_mux_request_new_pad (GstElement * element, name = g_strdup_printf ("video_%u", mux->num_v_streams++); pad_name = name; } - setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps); + capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps); context = (GstMatroskaTrackContext *) g_new0 (GstMatroskaTrackVideoContext, 1); context->type = GST_MATROSKA_TRACK_TYPE_VIDEO; @@ -1888,7 +1860,7 @@ gst_matroska_mux_request_new_pad (GstElement * element, name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++); pad_name = name; } - setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps); + capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps); context = (GstMatroskaTrackContext *) g_new0 (GstMatroskaTrackSubtitleContext, 1); context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE; @@ -1920,7 +1892,7 @@ gst_matroska_mux_request_new_pad (GstElement * element, gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event)); - gst_pad_set_setcaps_function (newpad, setcapsfunc); + collect_pad->capsfunc = capsfunc; gst_pad_set_active (newpad, TRUE); if (!gst_element_add_pad (element, newpad)) goto pad_add_failed; @@ -2109,9 +2081,9 @@ gst_matroska_mux_start (GstMatroskaMux * mux) GTimeVal time = { 0, 0 }; if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) { - ebml->caps = gst_caps_new_simple ("video/webm", NULL); + ebml->caps = gst_caps_new_empty_simple ("video/webm"); } else { - ebml->caps = gst_caps_new_simple ("video/x-matroska", NULL); + ebml->caps = gst_caps_new_empty_simple ("video/x-matroska"); } /* we start with a EBML header */ doctype = mux->doctype; @@ -2176,7 +2148,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux) for (collected = mux->collect->data; collected; collected = g_slist_next (collected)) { GstMatroskaPad *collect_pad; - GstFormat format = GST_FORMAT_TIME; GstPad *thepad; gint64 trackduration; @@ -2185,7 +2156,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux) /* Query the total length of the track. */ GST_DEBUG_OBJECT (thepad, "querying peer duration"); - if (gst_pad_query_peer_duration (thepad, &format, &trackduration)) { + if (gst_pad_peer_query_duration (thepad, GST_FORMAT_TIME, &trackduration)) { GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (trackduration)); if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) { @@ -2503,7 +2474,7 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped) GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (collect_pad->buffer)), GST_TIME_ARGS (time)); collect_pad->buffer = - gst_buffer_make_metadata_writable (collect_pad->buffer); + gst_buffer_make_writable (collect_pad->buffer); GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time; } } @@ -2539,15 +2510,16 @@ gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track, gint16 relative_timestamp, int flags) { GstBuffer *hdr; + guint8 *data = g_malloc (4); - hdr = gst_buffer_new_and_alloc (4); + hdr = gst_buffer_new_wrapped (data, 4); /* track num - FIXME: what if num >= 0x80 (unlikely)? */ - GST_BUFFER_DATA (hdr)[0] = track->num | 0x80; + data[0] = track->num | 0x80; /* time relative to clustertime */ - GST_WRITE_UINT16_BE (GST_BUFFER_DATA (hdr) + 1, relative_timestamp); + GST_WRITE_UINT16_BE (data + 1, relative_timestamp); /* flags */ - GST_BUFFER_DATA (hdr)[3] = flags; + data[3] = flags; return hdr; } @@ -2562,14 +2534,18 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux, { GstMatroskaTrackVideoContext *ctx = (GstMatroskaTrackVideoContext *) collect_pad->track; - const guint8 *data = GST_BUFFER_DATA (buf); - guint size = GST_BUFFER_SIZE (buf); + guint8 *buf_data, *data; + gsize size; guint8 parse_code; guint32 next_parse_offset; GstBuffer *ret = NULL; gboolean is_muxing_unit = FALSE; - if (GST_BUFFER_SIZE (buf) < 13) { + buf_data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + data = buf_data; + + if (size < 13) { + gst_buffer_unmap (buf, buf_data, -1); gst_buffer_unref (buf); return ret; } @@ -2577,6 +2553,7 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux, /* Check if this buffer contains a picture or end-of-sequence packet */ while (size >= 13) { if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) { + gst_buffer_unmap (buf, buf_data, -1); gst_buffer_unref (buf); return ret; } @@ -2607,12 +2584,13 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux, else ctx->dirac_unit = gst_buffer_ref (buf); + gst_buffer_unmap (buf, buf_data, -1); + if (is_muxing_unit) { - ret = gst_buffer_make_metadata_writable (ctx->dirac_unit); + ret = gst_buffer_make_writable (ctx->dirac_unit); ctx->dirac_unit = NULL; - gst_buffer_copy_metadata (ret, buf, - GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | - GST_BUFFER_COPY_CAPS); + gst_buffer_copy_into (ret, buf, + GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1); gst_buffer_unref (buf); } else { gst_buffer_unref (buf); @@ -2634,9 +2612,9 @@ gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux) streamheader_buffer = gst_ebml_stop_streamheader (ebml); if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) { - caps = gst_caps_new_simple ("video/webm", NULL); + caps = gst_caps_new_empty_simple ("video/webm"); } else { - caps = gst_caps_new_simple ("video/x-matroska", NULL); + caps = gst_caps_new_empty_simple ("video/x-matroska"); } s = gst_caps_get_structure (caps, 0); g_value_init (&streamheader, GST_TYPE_ARRAY); @@ -2836,14 +2814,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad) relative_timestamp, flags); gst_ebml_write_set_cache (ebml, 0x40); gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK, - GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr)); + gst_buffer_get_size (buf) + gst_buffer_get_size (hdr)); gst_ebml_write_buffer (ebml, hdr); gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf)); gst_ebml_write_buffer (ebml, buf); return gst_ebml_last_write_result (ebml); } else { - gst_ebml_write_set_cache (ebml, GST_BUFFER_SIZE (buf) * 2); + gst_ebml_write_set_cache (ebml, gst_buffer_get_size (buf) * 2); /* write and call order slightly unnatural, * but avoids seek and minizes pushing */ blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP); @@ -2853,9 +2831,10 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad) if (write_duration) gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration); gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK, - GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr)); + gst_buffer_get_size (buf) + gst_buffer_get_size (hdr)); gst_ebml_write_buffer (ebml, hdr); - gst_ebml_write_master_finish_full (ebml, blockgroup, GST_BUFFER_SIZE (buf)); + gst_ebml_write_master_finish_full (ebml, blockgroup, + gst_buffer_get_size (buf)); gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf)); gst_ebml_write_buffer (ebml, buf); diff --git a/gst/matroska/matroska-mux.h b/gst/matroska/matroska-mux.h index 73bdc09..4377f26 100644 --- a/gst/matroska/matroska-mux.h +++ b/gst/matroska/matroska-mux.h @@ -53,10 +53,13 @@ typedef struct _GstMatroskaMetaSeekIndex { guint64 pos; } GstMatroskaMetaSeekIndex; +typedef gboolean (*GstMatroskaCapsFunc) (GstPad *pad, GstCaps *caps); + /* all information needed for one matroska stream */ typedef struct { GstCollectData collect; /* we extend the CollectData */ + GstMatroskaCapsFunc capsfunc; GstMatroskaTrackContext *track; GstBuffer *buffer; /* the queued buffer for this pad */ diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 2424baf..8032515 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -111,16 +111,14 @@ static gboolean gst_matroska_parse_element_query (GstElement * element, static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse, GstPad * pad, GstEvent * event); static gboolean gst_matroska_parse_handle_src_event (GstPad * pad, - GstEvent * event); -static const GstQueryType *gst_matroska_parse_get_src_query_types (GstPad * - pad); + GstObject * parent, GstEvent * event); static gboolean gst_matroska_parse_handle_src_query (GstPad * pad, - GstQuery * query); + GstObject * parent, GstQuery * query); static gboolean gst_matroska_parse_handle_sink_event (GstPad * pad, - GstEvent * event); + GstObject * parent, GstEvent * event); static GstFlowReturn gst_matroska_parse_chain (GstPad * pad, - GstBuffer * buffer); + GstObject * parent, GstBuffer * buffer); static GstStateChangeReturn gst_matroska_parse_change_state (GstElement * element, @@ -135,24 +133,8 @@ static gboolean perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset); GType gst_matroska_parse_get_type (void); -GST_BOILERPLATE (GstMatroskaParse, gst_matroska_parse, GstElement, - GST_TYPE_ELEMENT); - -static void -gst_matroska_parse_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_templ)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_templ)); - - gst_element_class_set_details_simple (element_class, "Matroska parser", - "Codec/Parser", - "Parses Matroska/WebM streams into video/audio/subtitles", - "GStreamer maintainers "); -} +#define parent_class gst_matroska_parse_parent_class +G_DEFINE_TYPE (GstMatroskaParse, gst_matroska_parse, GST_TYPE_ELEMENT); static void gst_matroska_parse_finalize (GObject * object) @@ -196,11 +178,20 @@ gst_matroska_parse_class_init (GstMatroskaParseClass * klass) GST_DEBUG_FUNCPTR (gst_matroska_parse_set_index); gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_matroska_parse_get_index); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_templ)); + + gst_element_class_set_details_simple (gstelement_class, + "Matroska parser", "Codec/Parser", + "Parses Matroska/WebM streams into video/audio/subtitles", + "GStreamer maintainers "); } static void -gst_matroska_parse_init (GstMatroskaParse * parse, - GstMatroskaParseClass * klass) +gst_matroska_parse_init (GstMatroskaParse * parse) { parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); @@ -213,8 +204,6 @@ gst_matroska_parse_init (GstMatroskaParse * parse, parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src"); gst_pad_set_event_function (parse->srcpad, GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_event)); - gst_pad_set_query_type_function (parse->srcpad, - GST_DEBUG_FUNCPTR (gst_matroska_parse_get_src_query_types)); gst_pad_set_query_function (parse->srcpad, GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query)); gst_pad_use_fixed_caps (parse->srcpad); @@ -374,7 +363,7 @@ gst_matroska_parse_reset (GstElement * element) if (parse->common.global_tags) { gst_tag_list_free (parse->common.global_tags); } - parse->common.global_tags = gst_tag_list_new (); + parse->common.global_tags = gst_tag_list_new_empty (); if (parse->common.cached_buffer) { gst_buffer_unref (parse->common.cached_buffer); @@ -1078,19 +1067,6 @@ gst_matroska_parse_add_stream (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static const GstQueryType * -gst_matroska_parse_get_src_query_types (GstPad * pad) -{ - static const GstQueryType query_types[] = { - GST_QUERY_POSITION, - GST_QUERY_DURATION, - GST_QUERY_SEEKING, - 0 - }; - - return query_types; -} - static gboolean gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad, GstQuery * query) @@ -1115,7 +1091,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad, gst_query_set_position (query, GST_FORMAT_TIME, context->pos); else gst_query_set_position (query, GST_FORMAT_TIME, - parse->common.segment.last_stop); + parse->common.segment.position); GST_OBJECT_UNLOCK (parse); } else if (format == GST_FORMAT_DEFAULT && context && context->default_duration) { @@ -1175,7 +1151,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad, break; } default: - res = gst_pad_query_default (pad, query); + res = gst_pad_query_default (pad, (GstObject *) parse, query); break; } @@ -1189,15 +1165,14 @@ gst_matroska_parse_element_query (GstElement * element, GstQuery * query) } static gboolean -gst_matroska_parse_handle_src_query (GstPad * pad, GstQuery * query) +gst_matroska_parse_handle_src_query (GstPad * pad, GstObject * parent, + GstQuery * query) { gboolean ret; - GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad)); + GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent); ret = gst_matroska_parse_query (parse, pad, query); - gst_object_unref (parse); - return ret; } @@ -1248,6 +1223,8 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos) GstFlowReturn ret = GST_FLOW_OK; const guint chunk = 64 * 1024; GstBuffer *buf = NULL; + gpointer data; + gsize size; guint64 length; guint32 id; guint needed; @@ -1263,13 +1240,13 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos) if (ret != GST_FLOW_OK) break; GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT, - GST_BUFFER_SIZE (buf), newpos); - gst_byte_reader_init_from_buffer (&reader, buf); + gst_buffer_get_size (buf), newpos); + data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + gst_byte_reader_init (&reader, data, size); cluster_pos = 0; resume: cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, - GST_MATROSKA_ID_CLUSTER, cluster_pos, - GST_BUFFER_SIZE (buf) - cluster_pos); + GST_MATROSKA_ID_CLUSTER, cluster_pos, size - cluster_pos); if (cluster_pos >= 0) { newpos += cluster_pos; GST_DEBUG_OBJECT (parse, @@ -1311,13 +1288,15 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos) goto resume; } else { /* partial cluster id may have been in tail of buffer */ - newpos += MAX (GST_BUFFER_SIZE (buf), 4) - 3; + newpos += MAX (size, 4) - 3; + gst_buffer_unmap (buf, data, size); gst_buffer_unref (buf); buf = NULL; } } if (buf) { + gst_buffer_unmap (buf, data, size); gst_buffer_unref (buf); buf = NULL; } @@ -1362,7 +1341,7 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse, if (event) { GST_DEBUG_OBJECT (parse, "configuring seek"); - gst_segment_set_seek (&seeksegment, rate, format, flags, + gst_segment_do_seek (&seeksegment, rate, format, flags, cur_type, cur, stop_type, stop, &update); } @@ -1371,7 +1350,7 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse, /* check sanity before we start flushing and all that */ GST_OBJECT_LOCK (parse); if ((entry = gst_matroska_read_common_do_index_seek (&parse->common, track, - seeksegment.last_stop, &parse->seek_index, &parse->seek_entry)) == + seeksegment.position, &parse->seek_index, &parse->seek_entry)) == NULL) { /* pull mode without index can scan later on */ GST_DEBUG_OBJECT (parse, "No matching seek entry in index"); @@ -1473,9 +1452,10 @@ gst_matroska_parse_handle_seek_push (GstMatroskaParse * parse, GstPad * pad, } static gboolean -gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event) +gst_matroska_parse_handle_src_event (GstPad * pad, GstObject * parent, + GstEvent * event) { - GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad)); + GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent); gboolean res = TRUE; switch (GST_EVENT_TYPE (event)) { @@ -1499,7 +1479,7 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event) GstClockTimeDiff diff; GstClockTime timestamp; - gst_event_parse_qos (event, &proportion, &diff, ×tamp); + gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp); GST_OBJECT_LOCK (parse); videocontext->earliest_time = timestamp + diff; @@ -1522,8 +1502,6 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event) break; } - gst_object_unref (parse); - return res; } @@ -1635,6 +1613,8 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, guint32 id; guint64 block_duration = 0; GstBuffer *buf = NULL; + gpointer buf_data = NULL; + gsize buf_size = 0; gint stream_num = -1, n, laces = 0; guint size = 0; gint *lace_size = NULL; @@ -1668,8 +1648,10 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK) break; - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); + buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ); + + data = buf_data; + size = buf_size; /* first byte(s): blocknum */ if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) @@ -1873,18 +1855,18 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, } /* need to refresh segment info ASAP */ if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) { + GstSegment segment; GST_DEBUG_OBJECT (parse, "generating segment starting at %" GST_TIME_FORMAT, GST_TIME_ARGS (lace_time)); /* pretend we seeked here */ - gst_segment_set_seek (&parse->common.segment, parse->common.segment.rate, + gst_segment_do_seek (&parse->common.segment, parse->common.segment.rate, GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL); /* now convey our segment notion downstream */ - gst_matroska_parse_send_event (parse, gst_event_new_new_segment (FALSE, - parse->common.segment.rate, parse->common.segment.format, - parse->common.segment.start, parse->common.segment.stop, - parse->common.segment.start)); + segment = parse->common.segment; + segment.position = segment.start; + gst_matroska_parse_send_event (parse, gst_event_new_segment (&segment)); parse->need_newsegment = FALSE; } @@ -2134,8 +2116,10 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, } done: - if (buf) + if (buf) { + gst_buffer_unmap (buf, buf_data, buf_size); gst_buffer_unref (buf); + } g_free (lace_size); return ret; @@ -2419,10 +2403,9 @@ gst_matroska_parse_check_seekability (GstMatroskaParse * parse) /* try harder to query upstream size if we didn't get it the first time */ if (seekable && stop == -1) { - GstFormat fmt = GST_FORMAT_BYTES; - GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop"); - gst_pad_query_peer_duration (parse->common.sinkpad, &fmt, &stop); + gst_pad_peer_query_duration (parse->common.sinkpad, GST_FORMAT_BYTES, + &stop); } /* if upstream doesn't know the size, it's likely that it's not seekable in @@ -2506,14 +2489,15 @@ gst_matroska_parse_accumulate_streamheader (GstMatroskaParse * parse, GstBuffer *buf; buf = gst_buffer_span (parse->streamheader, 0, buffer, - GST_BUFFER_SIZE (parse->streamheader) + GST_BUFFER_SIZE (buffer)); + gst_buffer_get_size (parse->streamheader) + + gst_buffer_get_size (buffer)); gst_buffer_unref (parse->streamheader); parse->streamheader = buf; } else { parse->streamheader = gst_buffer_ref (buffer); } - GST_DEBUG ("%d", GST_BUFFER_SIZE (parse->streamheader)); + GST_DEBUG ("%d", gst_buffer_get_size (parse->streamheader)); } static GstFlowReturn @@ -2529,7 +2513,7 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer, GValue bufval = { 0 }; GstBuffer *buf; - caps = gst_caps_new_simple ("video/x-matroska", NULL); + caps = gst_caps_new_empty_simple ("video/x-matroska"); s = gst_caps_get_structure (caps, 0); g_value_init (&streamheader, GST_TYPE_ARRAY); g_value_init (&bufval, GST_TYPE_BUFFER); @@ -2545,7 +2529,6 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer, gst_pad_set_caps (parse->srcpad, caps); buf = gst_buffer_copy (parse->streamheader); - gst_buffer_set_caps (buf, caps); gst_caps_unref (caps); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); @@ -2567,7 +2550,6 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer, } else { GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp; } - gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); ret = gst_pad_push (parse->srcpad, gst_buffer_ref (buffer)); return ret; @@ -3028,9 +3010,9 @@ perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset) } static GstFlowReturn -gst_matroska_parse_chain (GstPad * pad, GstBuffer * buffer) +gst_matroska_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) { - GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad)); + GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent); guint available; GstFlowReturn ret = GST_FLOW_OK; guint needed = 0; @@ -3075,7 +3057,8 @@ next: } static gboolean -gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) +gst_matroska_parse_handle_sink_event (GstPad * pad, GstObject * parent, + GstEvent * event) { gboolean res = TRUE; GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad)); @@ -3084,23 +3067,15 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event); switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: { - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time = 0; - gboolean update; - GstSegment segment; + const GstSegment *segment; /* some debug output */ - gst_segment_init (&segment, GST_FORMAT_UNDEFINED); - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - gst_segment_set_newsegment_full (&segment, update, rate, arate, format, - start, stop, time); + gst_event_parse_segment (event, &segment); GST_DEBUG_OBJECT (parse, - "received format %d newsegment %" GST_SEGMENT_FORMAT, format, - &segment); + "received format %d newsegment %" GST_SEGMENT_FORMAT, + segment->format, segment); if (parse->common.state < GST_MATROSKA_READ_STATE_DATA) { GST_DEBUG_OBJECT (parse, "still starting"); @@ -3108,7 +3083,7 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) } /* we only expect a BYTE segment, e.g. following a seek */ - if (format != GST_FORMAT_BYTES) { + if (segment->format != GST_FORMAT_BYTES) { GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring"); goto exit; } @@ -3117,15 +3092,15 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) /* clear current segment leftover */ gst_adapter_clear (parse->common.adapter); /* and some streaming setup */ - parse->common.offset = start; + parse->common.offset = segment->start; /* do not know where we are; * need to come across a cluster and generate newsegment */ - parse->common.segment.last_stop = GST_CLOCK_TIME_NONE; + parse->common.segment.position = GST_CLOCK_TIME_NONE; parse->cluster_time = GST_CLOCK_TIME_NONE; parse->cluster_offset = 0; parse->need_newsegment = TRUE; /* but keep some of the upstream segment */ - parse->common.segment.rate = rate; + parse->common.segment.rate = segment->rate; exit: /* chain will send initial newsegment after pads have been added, * or otherwise come up with one */ @@ -3155,13 +3130,13 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) gst_matroska_read_common_reset_streams (&parse->common, GST_CLOCK_TIME_NONE, TRUE); GST_OBJECT_UNLOCK (parse); - parse->common.segment.last_stop = GST_CLOCK_TIME_NONE; + parse->common.segment.position = GST_CLOCK_TIME_NONE; parse->cluster_time = GST_CLOCK_TIME_NONE; parse->cluster_offset = 0; /* fall-through */ } default: - res = gst_pad_event_default (pad, event); + res = gst_pad_event_default (pad, parent, event); break; } diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index 5fd178f..3c7573c 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -58,7 +58,7 @@ GST_DEBUG_CATEGORY (matroskareadcommon_debug); static gboolean gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc, - guint8 ** data_out, guint * size_out, + gpointer * data_out, gsize * size_out, GstMatroskaTrackCompressionAlgorithm algo) { guint8 *new_data = NULL; @@ -237,8 +237,8 @@ gst_matroska_decode_content_encodings (GArray * encodings) for (i = 0; i < encodings->len; i++) { GstMatroskaTrackEncoding *enc = &g_array_index (encodings, GstMatroskaTrackEncoding, i); - guint8 *data = NULL; - guint size; + gpointer data = NULL; + gsize size; if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING) == 0) @@ -270,11 +270,11 @@ gst_matroska_decode_content_encodings (GArray * encodings) } gboolean -gst_matroska_decode_data (GArray * encodings, guint8 ** data_out, - guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free) +gst_matroska_decode_data (GArray * encodings, gpointer * data_out, + gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free) { - guint8 *data; - guint size; + gpointer data; + gsize size; gboolean ret = TRUE; gint i; @@ -288,8 +288,8 @@ gst_matroska_decode_data (GArray * encodings, guint8 ** data_out, for (i = 0; i < encodings->len; i++) { GstMatroskaTrackEncoding *enc = &g_array_index (encodings, GstMatroskaTrackEncoding, i); - guint8 *new_data = NULL; - guint new_size = 0; + gpointer new_data = NULL; + gsize new_size = 0; if ((enc->scope & scope) == 0) continue; @@ -430,21 +430,31 @@ gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common, gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND); gst_tag_list_free (taglist); } else { + GstEvent *tag_event = gst_event_new_tag (taglist); + gint i; + /* hm, already sent, no need to cache and wait anymore */ GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT, taglist); - gst_element_found_tags (el, taglist); + + for (i = 0; i < common->src->len; i++) { + GstMatroskaTrackContext *stream; + + stream = g_ptr_array_index (common->src, i); + gst_pad_push_event (stream->pad, gst_event_ref (tag_event)); + } + + gst_event_unref (tag_event); } } gint64 gst_matroska_read_common_get_length (GstMatroskaReadCommon * common) { - GstFormat fmt = GST_FORMAT_BYTES; gint64 end = -1; - if (!gst_pad_query_peer_duration (common->sinkpad, &fmt, &end) || - fmt != GST_FORMAT_BYTES || end < 0) + if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES, + &end) || end < 0) GST_DEBUG_OBJECT (common, "no upstream length"); return end; @@ -569,7 +579,7 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common, if (filename && mimetype && data && datalen > 0) { GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE; GstBuffer *tagbuffer = NULL; - GstCaps *caps; + /* GstCaps *caps; */ gchar *filename_lc = g_utf8_strdown (filename, -1); GST_DEBUG_OBJECT (common, "Creating tag for attachment with " @@ -600,31 +610,32 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common, if (!tagbuffer) image_type = GST_TAG_IMAGE_TYPE_NONE; + else + data = NULL; } /* if this failed create an attachment buffer */ if (!tagbuffer) { - tagbuffer = gst_buffer_new_and_alloc (datalen); - - memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen); - GST_BUFFER_SIZE (tagbuffer) = datalen; - - caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); - if (caps == NULL) - caps = gst_caps_new_simple (mimetype, NULL); - gst_buffer_set_caps (tagbuffer, caps); - gst_caps_unref (caps); + tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen); + + /* FIXME: We can't attach caps to buffers in 0.11. */ + /* caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); */ + /* if (caps == NULL) */ + /* caps = gst_caps_new_simple (mimetype, NULL); */ + /* gst_buffer_set_caps (tagbuffer, caps); */ + /* gst_caps_unref (caps); */ } + /* FIXME: We can't attach caps to buffers in 0.11. */ /* Set filename and description on the caps */ - caps = GST_BUFFER_CAPS (tagbuffer); - gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); - if (description) - gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, - NULL); + /* caps = GST_BUFFER_CAPS (tagbuffer); */ + /* gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); */ + /* if (description) */ + /* gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, */ + /* NULL); */ - GST_DEBUG_OBJECT (common, - "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); + /* GST_DEBUG_OBJECT (common, */ + /* "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); */ /* and append to the tag list */ if (image_type != GST_TAG_IMAGE_TYPE_NONE) @@ -658,7 +669,7 @@ gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common, return ret; } - taglist = gst_tag_list_new (); + taglist = gst_tag_list_new_empty (); while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) @@ -1280,9 +1291,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common, break; GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text)); - taglist = gst_tag_list_new (); - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, - NULL); + taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL); gst_matroska_read_common_found_global_tag (common, el, taglist); g_free (text); break; @@ -1313,7 +1322,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common, dur_u = gst_gdouble_to_guint64 (dur_f * gst_guint64_to_gdouble (common->time_scale)); if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64) - gst_segment_set_duration (&common->segment, GST_FORMAT_TIME, dur_u); + common->segment.duration = dur_u; } DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret); @@ -1518,7 +1527,7 @@ gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common, return ret; } - taglist = gst_tag_list_new (); + taglist = gst_tag_list_new_empty (); while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) @@ -1551,7 +1560,8 @@ static GstFlowReturn gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint peek, const guint8 ** data) { - *data = gst_adapter_peek (common->adapter, peek); + /* Caller needs to gst_adapter_unmap. */ + *data = gst_adapter_map (common->adapter, peek); if (*data == NULL) return GST_FLOW_UNEXPECTED; @@ -1571,19 +1581,26 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64 * We do it mainly to avoid pulling buffers of 1 byte all the time */ if (common->cached_buffer) { guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer); - guint cache_size = GST_BUFFER_SIZE (common->cached_buffer); + gsize cache_size = gst_buffer_get_size (common->cached_buffer); if (cache_offset <= common->offset && (common->offset + size) <= (cache_offset + cache_size)) { if (p_buf) - *p_buf = gst_buffer_create_sub (common->cached_buffer, - common->offset - cache_offset, size); - if (bytes) - *bytes = GST_BUFFER_DATA (common->cached_buffer) + common->offset - - cache_offset; + *p_buf = gst_buffer_copy_region (common->cached_buffer, + GST_BUFFER_COPY_ALL, common->offset - cache_offset, size); + if (bytes) { + if (!common->cached_data) + common->cached_data = gst_buffer_map (common->cached_buffer, + NULL, NULL, GST_MAP_READ); + *bytes = common->cached_data + common->offset - cache_offset; + } return GST_FLOW_OK; } /* not enough data in the cache, free cache and get a new one */ + if (common->cached_data) { + gst_buffer_unmap (common->cached_buffer, common->cached_data, -1); + common->cached_data = NULL; + } gst_buffer_unref (common->cached_buffer); common->cached_buffer = NULL; } @@ -1596,11 +1613,15 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64 return ret; } - if (GST_BUFFER_SIZE (common->cached_buffer) >= size) { + if (gst_buffer_get_size (common->cached_buffer) >= size) { if (p_buf) - *p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size); - if (bytes) - *bytes = GST_BUFFER_DATA (common->cached_buffer); + *p_buf = gst_buffer_copy_region (common->cached_buffer, + GST_BUFFER_COPY_ALL, 0, size); + if (bytes) { + common->cached_data = gst_buffer_map (common->cached_buffer, + NULL, NULL, GST_MAP_READ); + *bytes = common->cached_data; + } return GST_FLOW_OK; } @@ -1621,10 +1642,10 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64 return ret; } - if (GST_BUFFER_SIZE (common->cached_buffer) < size) { + if (gst_buffer_get_size (common->cached_buffer) < size) { GST_WARNING_OBJECT (common, "Dropping short buffer at offset %" G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", common->offset, - size, GST_BUFFER_SIZE (common->cached_buffer)); + size, gst_buffer_get_size (common->cached_buffer)); gst_buffer_unref (common->cached_buffer); common->cached_buffer = NULL; @@ -1636,9 +1657,13 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64 } if (p_buf) - *p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size); - if (bytes) - *bytes = GST_BUFFER_DATA (common->cached_buffer); + *p_buf = gst_buffer_copy_region (common->cached_buffer, + GST_BUFFER_COPY_ALL, 0, size); + if (bytes) { + common->cached_data = gst_buffer_map (common->cached_buffer, + NULL, NULL, GST_MAP_READ); + *bytes = common->cached_data; + } return GST_FLOW_OK; } @@ -1664,9 +1689,15 @@ GstFlowReturn gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common, GstElement * el, guint32 * _id, guint64 * _length, guint * _needed) { - return gst_ebml_peek_id_length (_id, _length, _needed, + GstFlowReturn ret; + + ret = gst_ebml_peek_id_length (_id, _length, _needed, (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common, el, common->offset); + + gst_adapter_unmap (common->adapter); + + return ret; } static GstFlowReturn diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index cf617e6..752d1a8 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -81,6 +81,7 @@ typedef struct _GstMatroskaReadCommon { /* pull mode caching */ GstBuffer *cached_buffer; + guint8 *cached_data; /* push and pull mode */ guint64 offset; @@ -90,8 +91,8 @@ typedef struct _GstMatroskaReadCommon { } GstMatroskaReadCommon; GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings); -gboolean gst_matroska_decode_data (GArray * encodings, guint8 ** data_out, - guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free); +gboolean gst_matroska_decode_data (GArray * encodings, gpointer * data_out, + gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free); gint gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time, gpointer user_data); GstMatroskaIndex * gst_matroska_read_common_do_index_seek ( diff --git a/gst/matroska/webm-mux.c b/gst/matroska/webm-mux.c index 71ec461..0dbac38 100644 --- a/gst/matroska/webm-mux.c +++ b/gst/matroska/webm-mux.c @@ -32,8 +32,8 @@ * ]| This pipeline re-encodes a video file of any format into a WebM file. * |[ * gst-launch-0.10 webmmux name=mux ! filesink location=test.webm \ - * videotestsrc num-buffers=250 ! video/x-raw-yuv,framerate=25/1 ! ffmpegcolorspace ! vp8enc ! queue ! mux.video_0 \ - * audiotestsrc samplesperbuffer=44100 num-buffers=10 ! audio/x-raw-float,rate=44100 ! vorbisenc ! queue ! mux.audio_0 + * videotestsrc num-buffers=250 ! video/x-raw,framerate=25/1 ! ffmpegcolorspace ! vp8enc ! queue ! mux.video_0 \ + * audiotestsrc samplesperbuffer=44100 num-buffers=10 ! audio/x-raw,rate=44100 ! vorbisenc ! queue ! mux.audio_0 * ]| This pipeline muxes a test video and a sine wave into a WebM file. * */ @@ -53,8 +53,7 @@ "channels = (int) [ 1, MAX ], " \ "rate = (int) [ 1, MAX ]" -GST_BOILERPLATE (GstWebMMux, gst_webm_mux, GstMatroskaMux, - GST_TYPE_MATROSKA_MUX); +G_DEFINE_TYPE (GstWebMMux, gst_webm_mux, GST_TYPE_MATROSKA_MUX); static GstStaticPadTemplate webm_src_templ = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -77,11 +76,6 @@ GST_STATIC_PAD_TEMPLATE ("audio_%u", ); static void -gst_webm_mux_base_init (gpointer g_class) -{ -} - -static void gst_webm_mux_class_init (GstWebMMuxClass * klass) { GstElementClass *gstelement_class = (GstElementClass *) klass; @@ -99,7 +93,7 @@ gst_webm_mux_class_init (GstWebMMuxClass * klass) } static void -gst_webm_mux_init (GstWebMMux * mux, GstWebMMuxClass * g_class) +gst_webm_mux_init (GstWebMMux * mux) { GST_MATROSKA_MUX (mux)->doctype = GST_MATROSKA_DOCTYPE_WEBM; } diff --git a/tests/check/elements/matroskamux.c b/tests/check/elements/matroskamux.c index c8bcbd5..887f91f 100644 --- a/tests/check/elements/matroskamux.c +++ b/tests/check/elements/matroskamux.c @@ -163,6 +163,7 @@ static GstElement * setup_matroskamux (GstStaticPadTemplate * srctemplate) { GstElement *matroskamux; + GstSegment segment; GST_DEBUG ("setup_matroskamux"); matroskamux = gst_check_setup_element ("matroskamux"); @@ -170,6 +171,14 @@ setup_matroskamux (GstStaticPadTemplate * srctemplate) mysrcpad = setup_src_pad (matroskamux, srctemplate, NULL); mysinkpad = setup_sink_pad (matroskamux, &sinktemplate, NULL); + fail_unless (gst_element_set_state (matroskamux, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + gst_segment_init (&segment, GST_FORMAT_TIME); + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_segment (&segment)), "Segment event rejected"); + return matroskamux; } @@ -187,8 +196,8 @@ cleanup_matroskamux (GstElement * matroskamux) static void check_buffer_data (GstBuffer * buffer, void *data, size_t data_size) { - fail_unless (GST_BUFFER_SIZE (buffer) == data_size); - fail_unless (memcmp (data, GST_BUFFER_DATA (buffer), data_size) == 0); + fail_unless (gst_buffer_get_size (buffer) == data_size); + fail_unless (gst_buffer_memcmp (buffer, 0, data, data_size) == 0); } GST_START_TEST (test_ebml_header) @@ -207,11 +216,8 @@ GST_START_TEST (test_ebml_header) }; matroskamux = setup_matroskamux (&srcac3template); - fail_unless (gst_element_set_state (matroskamux, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - inbuffer = gst_buffer_new_and_alloc (1); + inbuffer = gst_buffer_new_allocate (NULL, 1, 0); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); num_buffers = g_list_length (buffers); @@ -259,14 +265,12 @@ GST_START_TEST (test_vorbis_header) }; matroskamux = setup_matroskamux (&srcvorbistemplate); - fail_unless (gst_element_set_state (matroskamux, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - inbuffer = gst_buffer_new_and_alloc (1); caps = gst_caps_from_string (VORBIS_CAPS_STRING); - gst_buffer_set_caps (inbuffer, caps); + fail_unless (gst_pad_set_caps (mysrcpad, caps)); gst_caps_unref (caps); + + inbuffer = gst_buffer_new_allocate (NULL, 1, 0); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); @@ -274,14 +278,16 @@ GST_START_TEST (test_vorbis_header) for (i = 0; i < num_buffers; ++i) { gint j; + gsize buffer_size; outbuffer = GST_BUFFER (buffers->data); fail_if (outbuffer == NULL); + buffer_size = gst_buffer_get_size (outbuffer); buffers = g_list_remove (buffers, outbuffer); - if (!vorbis_header_found && GST_BUFFER_SIZE (outbuffer) >= sizeof (data)) { - for (j = 0; j <= GST_BUFFER_SIZE (outbuffer) - sizeof (data); j++) { - if (memcmp (GST_BUFFER_DATA (outbuffer) + j, data, sizeof (data)) == 0) { + if (!vorbis_header_found && buffer_size >= sizeof (data)) { + for (j = 0; j <= buffer_size - sizeof (data); j++) { + if (gst_buffer_memcmp (outbuffer, j, data, sizeof (data)) == 0) { vorbis_header_found = TRUE; break; } @@ -307,6 +313,7 @@ GST_START_TEST (test_block_group) { GstElement *matroskamux; GstBuffer *inbuffer, *outbuffer; + guint8 *indata; GstCaps *caps; int num_buffers; int i; @@ -317,16 +324,14 @@ GST_START_TEST (test_block_group) guint8 data1[] = { 0x42 }; matroskamux = setup_matroskamux (&srcac3template); - fail_unless (gst_element_set_state (matroskamux, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - /* Generate the header */ - inbuffer = gst_buffer_new_and_alloc (1); - GST_BUFFER_TIMESTAMP (inbuffer) = 0; caps = gst_caps_from_string (AC3_CAPS_STRING); - gst_buffer_set_caps (inbuffer, caps); + fail_unless (gst_pad_set_caps (mysrcpad, caps)); gst_caps_unref (caps); + + /* Generate the header */ + inbuffer = gst_buffer_new_allocate (NULL, 1, 0); + GST_BUFFER_TIMESTAMP (inbuffer) = 0; ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); @@ -346,12 +351,10 @@ GST_START_TEST (test_block_group) buffers = NULL; /* Now push a buffer */ - inbuffer = gst_buffer_new_and_alloc (1); - GST_BUFFER_DATA (inbuffer)[0] = 0x42; + indata = g_malloc (1); + inbuffer = gst_buffer_new_wrapped (indata, 1); + indata[0] = 0x42; GST_BUFFER_TIMESTAMP (inbuffer) = 1000000; - caps = gst_caps_from_string (AC3_CAPS_STRING); - gst_buffer_set_caps (inbuffer, caps); - gst_caps_unref (caps); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); @@ -396,11 +399,8 @@ GST_START_TEST (test_reset) int i; matroskamux = setup_matroskamux (&srcac3template); - fail_unless (gst_element_set_state (matroskamux, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - inbuffer = gst_buffer_new_and_alloc (1); + inbuffer = gst_buffer_new_allocate (NULL, 1, 0); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); num_buffers = g_list_length (buffers); @@ -414,7 +414,7 @@ GST_START_TEST (test_reset) GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, "could not set to playing"); - inbuffer = gst_buffer_new_and_alloc (1); + inbuffer = gst_buffer_new_allocate (NULL, 1, 0); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); num_buffers = g_list_length (buffers); -- 2.7.4