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.
This commit is contained in:
René Stadler 2011-11-26 10:01:07 +01:00
parent eeaa9e0bbc
commit 17240ac9ec
14 changed files with 850 additions and 815 deletions

View file

@ -314,7 +314,7 @@ dnl *** plug-ins to include ***
dnl Non ported plugins (non-dependant, then dependant) dnl Non ported plugins (non-dependant, then dependant)
dnl Make sure you have a space before and after all plugins dnl Make sure you have a space before and after all plugins
GST_PLUGINS_NONPORTED="deinterlace flx goom2k1 \ GST_PLUGINS_NONPORTED="deinterlace flx goom2k1 \
imagefreeze interleave matroska monoscope smpte \ imagefreeze interleave monoscope smpte \
videobox videomixer \ videobox videomixer \
cairo cairo_gobject dv1394 gdk_pixbuf libdv libpng \ cairo cairo_gobject dv1394 gdk_pixbuf libdv libpng \
oss oss4 shout2 \ oss oss4 shout2 \

View file

@ -164,6 +164,7 @@ gst_ebml_read_init (GstEbmlRead * ebml, GstElement * el, GstBuffer * buf,
guint64 offset) guint64 offset)
{ {
GstEbmlMaster m; GstEbmlMaster m;
gsize buf_size;
g_return_if_fail (el); g_return_if_fail (el);
g_return_if_fail (buf); g_return_if_fail (buf);
@ -171,9 +172,10 @@ gst_ebml_read_init (GstEbmlRead * ebml, GstElement * el, GstBuffer * buf,
ebml->el = el; ebml->el = el;
ebml->offset = offset; ebml->offset = offset;
ebml->buf = buf; 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); ebml->readers = g_array_sized_new (FALSE, FALSE, sizeof (GstEbmlMaster), 10);
m.offset = ebml->offset; 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); g_array_append_val (ebml->readers, m);
} }
@ -183,8 +185,10 @@ gst_ebml_read_clear (GstEbmlRead * ebml)
if (ebml->readers) if (ebml->readers)
g_array_free (ebml->readers, TRUE); g_array_free (ebml->readers, TRUE);
ebml->readers = NULL; ebml->readers = NULL;
if (ebml->buf) if (ebml->buf) {
gst_buffer_unmap (ebml->buf, ebml->buf_data, -1);
gst_buffer_unref (ebml->buf); gst_buffer_unref (ebml->buf);
}
ebml->buf = NULL; ebml->buf = NULL;
ebml->el = 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; offset = gst_ebml_read_get_pos (ebml) - ebml->offset;
if (G_LIKELY (gst_byte_reader_skip (gst_ebml_read_br (ebml), length))) { 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 { } else {
*buf = NULL; *buf = NULL;
return GST_FLOW_PARSE; return GST_FLOW_PARSE;

View file

@ -54,6 +54,7 @@ typedef struct _GstEbmlRead {
GstElement *el; GstElement *el;
GstBuffer *buf; GstBuffer *buf;
gpointer buf_data;
guint64 offset; guint64 offset;
GArray *readers; GArray *readers;

View file

@ -33,18 +33,14 @@
GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug); GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug);
#define GST_CAT_DEFAULT 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_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); _do_init);
static void gst_ebml_write_finalize (GObject * object); static void gst_ebml_write_finalize (GObject * object);
static void
gst_ebml_write_base_init (gpointer g_class)
{
}
static void static void
gst_ebml_write_class_init (GstEbmlWriteClass * klass) gst_ebml_write_class_init (GstEbmlWriteClass * klass)
{ {
@ -54,11 +50,11 @@ gst_ebml_write_class_init (GstEbmlWriteClass * klass)
} }
static void static void
gst_ebml_write_init (GstEbmlWrite * ebml, GstEbmlWriteClass * klass) gst_ebml_write_init (GstEbmlWrite * ebml)
{ {
ebml->srcpad = NULL; ebml->srcpad = NULL;
ebml->pos = 0; ebml->pos = 0;
ebml->last_pos = G_MAXUINT64; /* force newsegment event */ ebml->last_pos = G_MAXUINT64; /* force segment event */
ebml->cache = NULL; ebml->cache = NULL;
ebml->streamheader = NULL; ebml->streamheader = NULL;
@ -89,7 +85,7 @@ gst_ebml_write_finalize (GObject * object)
ebml->caps = NULL; 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) gst_ebml_write_reset (GstEbmlWrite * ebml)
{ {
ebml->pos = 0; ebml->pos = 0;
ebml->last_pos = G_MAXUINT64; /* force newsegment event */ ebml->last_pos = G_MAXUINT64; /* force segment event */
if (ebml->cache) { if (ebml->cache) {
gst_byte_writer_free (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); buffer = gst_byte_writer_free_and_get_buffer (ebml->streamheader);
ebml->streamheader = NULL; 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; ebml->writing_streamheader = FALSE;
return buffer; return buffer;
@ -211,14 +207,19 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
} }
static gboolean 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; gboolean res;
GST_INFO ("seeking to %" G_GUINT64_FORMAT, new_pos); GST_INFO ("seeking to %" G_GUINT64_FORMAT, new_pos);
res = gst_pad_push_event (ebml->srcpad, gst_segment_init (&segment, GST_FORMAT_BYTES);
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, new_pos, -1, 0)); segment.start = new_pos;
segment.stop = -1;
segment.position = 0;
res = gst_pad_push_event (ebml->srcpad, gst_event_new_segment (&segment));
if (!res) if (!res)
GST_WARNING ("seek to %" G_GUINT64_FORMAT "failed", new_pos); 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); buffer = gst_byte_writer_free_and_get_buffer (ebml->cache);
ebml->cache = NULL; ebml->cache = NULL;
GST_DEBUG ("Flushing cache of size %d", GST_BUFFER_SIZE (buffer)); GST_DEBUG ("Flushing cache of size %d", gst_buffer_get_size (buffer));
gst_buffer_set_caps (buffer, ebml->caps);
GST_BUFFER_TIMESTAMP (buffer) = timestamp; 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; GST_BUFFER_OFFSET_END (buffer) = ebml->pos;
if (ebml->last_write_result == GST_FLOW_OK) { if (ebml->last_write_result == GST_FLOW_OK) {
if (GST_BUFFER_OFFSET (buffer) != ebml->last_pos) { 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); GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
} }
if (ebml->writing_streamheader) { 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); buf = gst_buffer_new_and_alloc (size);
GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp; 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; return buf;
} }
@ -408,31 +408,33 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf,
{ {
guint data_size; guint data_size;
if (!buf_data) if (buf_data_end)
buf_data = GST_BUFFER_DATA (buf);
if (buf_data_end) {
data_size = buf_data_end - buf_data; data_size = buf_data_end - buf_data;
GST_BUFFER_SIZE (buf) = data_size; else
} else { data_size = gst_buffer_get_size (buf);
data_size = GST_BUFFER_SIZE (buf);
}
ebml->pos += data_size; ebml->pos += data_size;
/* if there's no cache, then don't push it! */ /* if there's no cache, then don't push it! */
if (ebml->writing_streamheader) { 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); gst_byte_writer_put_data (ebml->streamheader, buf_data, data_size);
} }
if (ebml->cache) { 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_byte_writer_put_data (ebml->cache, buf_data, data_size);
gst_buffer_unmap (buf, buf_data, -1);
gst_buffer_unref (buf); gst_buffer_unref (buf);
return; return;
} }
if (buf_data)
gst_buffer_unmap (buf, buf_data, -1);
if (ebml->last_write_result == GST_FLOW_OK) { if (ebml->last_write_result == GST_FLOW_OK) {
buf = gst_buffer_make_metadata_writable (buf); buf = gst_buffer_make_writable (buf);
gst_buffer_set_caps (buf, ebml->caps);
GST_BUFFER_OFFSET (buf) = ebml->pos - data_size; GST_BUFFER_OFFSET (buf) = ebml->pos - data_size;
GST_BUFFER_OFFSET_END (buf) = ebml->pos; GST_BUFFER_OFFSET_END (buf) = ebml->pos;
if (ebml->writing_streamheader) { 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); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
if (GST_BUFFER_OFFSET (buf) != ebml->last_pos) { 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); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
} }
ebml->last_pos = ebml->pos; ebml->last_pos = ebml->pos;
@ -730,12 +732,12 @@ gst_ebml_write_master_finish_full (GstEbmlWrite * ebml, guint64 startpos,
guint64 extra_size) guint64 extra_size)
{ {
guint64 pos = ebml->pos; 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); gst_ebml_write_seek (ebml, startpos);
buf = gst_buffer_new_and_alloc (8); GST_WRITE_UINT64_BE (data,
GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf),
(G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size)); (G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size));
gst_ebml_write_element_push (ebml, buf, NULL, NULL); gst_ebml_write_element_push (ebml, buf, NULL, NULL);
@ -835,11 +837,12 @@ void
gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num) gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
{ {
guint64 oldpos = ebml->pos; guint64 oldpos = ebml->pos;
GstBuffer *buf = gst_buffer_new_and_alloc (8);
guint8 *data_start, *data_end; guint8 *data_start, *data_end;
GstBuffer *buf;
data_start = GST_BUFFER_DATA (buf); data_start = g_malloc (8);
data_end = data_start; data_end = data_start;
buf = gst_buffer_new_wrapped (data_start, 8);
gst_ebml_write_seek (ebml, pos); gst_ebml_write_seek (ebml, pos);
gst_ebml_write_set_uint (&data_end, num, 8); gst_ebml_write_set_uint (&data_end, num, 8);

File diff suppressed because it is too large Load diff

View file

@ -87,7 +87,7 @@ typedef struct _GstMatroskaDemux {
gboolean building_index; gboolean building_index;
guint64 index_offset; guint64 index_offset;
GstEvent *seek_event; GstEvent *seek_event;
gboolean need_newsegment; gboolean need_segment;
/* reverse playback */ /* reverse playback */
GArray *seek_index; GArray *seek_index;

View file

@ -486,10 +486,10 @@ struct _GstMatroskaTrackContext {
/* some often-used info */ /* some often-used info */
gchar *codec_id, *codec_name, *name, *language; gchar *codec_id, *codec_name, *name, *language;
guint8 *codec_priv; gpointer codec_priv;
guint codec_priv_size; gsize codec_priv_size;
guint8 *codec_state; gpointer codec_state;
guint codec_state_size; gsize codec_state_size;
GstMatroskaTrackType type; GstMatroskaTrackType type;
guint uid, num; guint uid, num;
GstMatroskaTrackFlags flags; GstMatroskaTrackFlags flags;

View file

@ -49,6 +49,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <gst/audio/audio.h>
#include <gst/riff/riff-media.h> #include <gst/riff/riff-media.h>
#include <gst/tag/tag.h> #include <gst/tag/tag.h>
@ -126,8 +127,8 @@ static GstStaticPadTemplate videosink_templ =
COMMON_VIDEO_CAPS "; " COMMON_VIDEO_CAPS "; "
"video/x-vp8, " "video/x-vp8, "
COMMON_VIDEO_CAPS "; " COMMON_VIDEO_CAPS "; "
"video/x-raw-yuv, " "video/x-raw, "
"format = (fourcc) { YUY2, I420, YV12, UYVY, AYUV }, " "format = (string) { YUY2, I420, YV12, UYVY, AYUV }, "
COMMON_VIDEO_CAPS "; " COMMON_VIDEO_CAPS "; "
"video/x-wmv, " "wmvversion = (int) [ 1, 3 ], " COMMON_VIDEO_CAPS) "video/x-wmv, " "wmvversion = (int) [ 1, 3 ], " COMMON_VIDEO_CAPS)
); );
@ -163,32 +164,8 @@ static GstStaticPadTemplate audiosink_templ =
COMMON_AUDIO_CAPS "; " COMMON_AUDIO_CAPS "; "
"audio/x-speex, " "audio/x-speex, "
COMMON_AUDIO_CAPS "; " COMMON_AUDIO_CAPS "; "
"audio/x-raw-int, " "audio/x-raw, "
"width = (int) 8, " "format = (string) { U8, S16BE, S16LE, S24BE, S24LE, S32BE, S32LE, F32LE, F64LE }, "
"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, "
COMMON_AUDIO_CAPS ";" COMMON_AUDIO_CAPS ";"
"audio/x-tta, " "audio/x-tta, "
"width = (int) { 8, 16, 24 }, " "width = (int) { 8, 16, 24 }, "
@ -213,10 +190,9 @@ GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
static GArray *used_uids; static GArray *used_uids;
G_LOCK_DEFINE_STATIC (used_uids); G_LOCK_DEFINE_STATIC (used_uids);
static void gst_matroska_mux_add_interfaces (GType type); #define parent_class gst_matroska_mux_parent_class
G_DEFINE_TYPE_WITH_CODE (GstMatroskaMux, gst_matroska_mux, GST_TYPE_ELEMENT,
GST_BOILERPLATE_FULL (GstMatroskaMux, gst_matroska_mux, GstElement, G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
GST_TYPE_ELEMENT, gst_matroska_mux_add_interfaces);
/* Matroska muxer destructor */ /* Matroska muxer destructor */
static void gst_matroska_mux_finalize (GObject * object); static void gst_matroska_mux_finalize (GObject * object);
@ -227,9 +203,9 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data);
/* pad functions */ /* pad functions */
static gboolean gst_matroska_mux_handle_src_event (GstPad * pad, 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, 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); static void gst_matroska_mux_release_pad (GstElement * element, GstPad * pad);
/* gst internal change state handler */ /* gst internal change state handler */
@ -262,19 +238,6 @@ static void
gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag, gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
gpointer data); 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 static void
gst_matroska_mux_class_init (GstMatroskaMuxClass * klass) gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
{ {
@ -343,12 +306,12 @@ gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
* Matroska muxer constructor. * Matroska muxer constructor.
*/ */
static void static void
gst_matroska_mux_init (GstMatroskaMux * mux, GstMatroskaMuxClass * g_class) gst_matroska_mux_init (GstMatroskaMux * mux)
{ {
GstPadTemplate *templ; GstPadTemplate *templ;
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"); mux->srcpad = gst_pad_new_from_template (templ, "src");
gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event); 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. * Returns: #TRUE on success.
*/ */
static gboolean 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; GstEventType type;
@ -600,7 +564,7 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstEvent * event)
break; 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. * Returns: #TRUE on success.
*/ */
static gboolean 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; GstMatroskaTrackContext *context;
GstMatroskaPad *collect_pad; GstMatroskaPad *collect_pad;
GstMatroskaMux *mux; GstMatroskaMux *mux = GST_MATROSKA_MUX (parent);
GstTagList *list; GstTagList *list;
gboolean ret = TRUE; gboolean ret = TRUE;
mux = GST_MATROSKA_MUX (gst_pad_get_parent (pad));
switch (GST_EVENT_TYPE (event)) { 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:{ case GST_EVENT_TAG:{
gchar *lang = NULL; gchar *lang = NULL;
@ -658,12 +632,11 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event)
event = NULL; event = NULL;
break; break;
} }
case GST_EVENT_NEWSEGMENT:{ case GST_EVENT_SEGMENT:{
GstFormat format; const GstSegment *segment;
gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL, gst_event_parse_segment (event, &segment);
NULL); if (segment->format != GST_FORMAT_TIME) {
if (format != GST_FORMAT_TIME) {
ret = FALSE; ret = FALSE;
gst_event_unref (event); gst_event_unref (event);
event = NULL; 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 */ /* now GstCollectPads can take care of the rest, e.g. EOS */
if (event) if (event)
ret = mux->collect_event (pad, event); ret = mux->collect_event (pad, parent, event);
gst_object_unref (mux);
return ret; return ret;
} }
@ -714,7 +685,7 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
GstStructure *structure; GstStructure *structure;
const gchar *mimetype; const gchar *mimetype;
const GValue *value = NULL; const GValue *value = NULL;
const GstBuffer *codec_buf = NULL; GstBuffer *codec_buf = NULL;
gint width, height, pixel_width, pixel_height; gint width, height, pixel_width, pixel_height;
gint fps_d, fps_n; gint fps_d, fps_n;
gboolean interlaced = FALSE; gboolean interlaced = FALSE;
@ -790,12 +761,17 @@ skip_details:
/* extract codec_data, may turn out needed */ /* extract codec_data, may turn out needed */
value = gst_structure_get_value (structure, "codec_data"); value = gst_structure_get_value (structure, "codec_data");
if (value) if (value)
codec_buf = gst_value_get_buffer (value); codec_buf = (GstBuffer *) gst_value_get_buffer (value);
/* find type */ /* 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); 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 */ } else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
||!strcmp (mimetype, "video/x-huffyuv") ||!strcmp (mimetype, "video/x-huffyuv")
|| !strcmp (mimetype, "video/x-divx") || !strcmp (mimetype, "video/x-divx")
@ -848,9 +824,11 @@ skip_details:
} }
} else if (!strcmp (mimetype, "video/x-wmv")) { } else if (!strcmp (mimetype, "video/x-wmv")) {
gint wmvversion; gint wmvversion;
guint32 format; const gchar *fstr;
if (gst_structure_get_fourcc (structure, "format", &format)) {
fourcc = format; 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)) { } else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
if (wmvversion == 2) { if (wmvversion == 2) {
fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2'); fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2');
@ -879,11 +857,11 @@ skip_details:
/* process codec private/initialization data, if any */ /* process codec private/initialization data, if any */
if (codec_buf) { if (codec_buf) {
size += GST_BUFFER_SIZE (codec_buf); size += gst_buffer_get_size (codec_buf);
bih = g_realloc (bih, size); bih = g_realloc (bih, size);
GST_WRITE_UINT32_LE (&bih->size, size); GST_WRITE_UINT32_LE (&bih->size, size);
memcpy ((guint8 *) bih + sizeof (gst_riff_strf_vids), gst_buffer_extract (codec_buf, 0,
GST_BUFFER_DATA (codec_buf), GST_BUFFER_SIZE (codec_buf)); (guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
} }
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC); context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
@ -900,10 +878,9 @@ skip_details:
/* Create avcC header */ /* Create avcC header */
if (codec_buf != NULL) { 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); context->codec_priv = g_malloc0 (context->codec_priv_size);
memcpy (context->codec_priv, GST_BUFFER_DATA (codec_buf), gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
context->codec_priv_size);
} }
} else if (!strcmp (mimetype, "video/x-theora")) { } else if (!strcmp (mimetype, "video/x-theora")) {
const GValue *streamheader; const GValue *streamheader;
@ -946,10 +923,9 @@ skip_details:
/* global headers may be in codec data */ /* global headers may be in codec data */
if (codec_buf != NULL) { 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); context->codec_priv = g_malloc0 (context->codec_priv_size);
memcpy (context->codec_priv, GST_BUFFER_DATA (codec_buf), gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
context->codec_priv_size);
} }
} else if (!strcmp (mimetype, "video/x-msmpeg")) { } else if (!strcmp (mimetype, "video/x-msmpeg")) {
msmpeg43: msmpeg43:
@ -984,10 +960,10 @@ skip_details:
GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data); 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); 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 = priv_data;
context->codec_priv_size = priv_data_size; context->codec_priv_size = priv_data_size;
@ -1045,12 +1021,12 @@ xiphN_streamheader_to_codecdata (const GValue * streamheader,
priv_data_size = 1; priv_data_size = 1;
if (bufarr->len > 0) { if (bufarr->len > 0) {
for (i = 0; i < bufarr->len - 1; i++) { 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) { 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); priv_data = g_malloc0 (priv_data_size);
@ -1060,17 +1036,16 @@ xiphN_streamheader_to_codecdata (const GValue * streamheader,
if (bufarr->len > 0) { if (bufarr->len > 0) {
for (bufi = 0; bufi < bufarr->len - 1; bufi++) { 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++] = 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) { for (i = 0; i < bufarr->len; ++i) {
memcpy (priv_data + offset, GST_BUFFER_DATA (buf[i]), gst_buffer_extract (buf[i], 0, priv_data + offset, -1);
GST_BUFFER_SIZE (buf[i])); offset += gst_buffer_get_size (buf[i]);
offset += GST_BUFFER_SIZE (buf[i]);
} }
context->codec_priv = priv_data; 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)) if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
return FALSE; 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"); GST_WARNING ("First vorbis header too small, ignoring");
} else { } else {
if (memcmp (GST_BUFFER_DATA (buf0) + 1, "vorbis", 6) == 0) { if (gst_buffer_memcmp (buf0, 1, "vorbis", 6) == 0) {
GstMatroskaTrackAudioContext *audiocontext; 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 = (GstMatroskaTrackAudioContext *) context;
audiocontext->channels = GST_READ_UINT8 (hdr); audiocontext->channels = GST_READ_UINT8 (hdr);
audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1); 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)) if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
return FALSE; 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"); 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"); GST_WARNING ("First header not a theora identification header, ignoring");
} else { } else {
GstMatroskaTrackVideoContext *videocontext; GstMatroskaTrackVideoContext *videocontext;
guint fps_num, fps_denom, par_num, par_denom; 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 = (GstMatroskaTrackVideoContext *) context;
videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8; videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8;
@ -1185,6 +1163,8 @@ theora_streamheader_to_codecdata (const GValue * streamheader,
videocontext->display_height = 0; videocontext->display_height = 0;
} }
hdr += 3 + 3; hdr += 3 + 3;
gst_buffer_unmap (buf0, data, -1);
} }
if (buf0) if (buf0)
@ -1202,9 +1182,9 @@ kate_streamheader_to_codecdata (const GValue * streamheader,
if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1)) if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1))
return FALSE; 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"); 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"); 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); buffer = g_value_peek_pointer (bufval);
/* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */ /* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */
if (GST_BUFFER_SIZE (buffer) < 9 + 4 + 4 + 34 if (gst_buffer_get_size (buffer) < 9 + 4 + 4 + 34
|| memcmp (GST_BUFFER_DATA (buffer) + 1, "FLAC", 4) != 0 || gst_buffer_memcmp (buffer, 1, "FLAC", 4) != 0
|| memcmp (GST_BUFFER_DATA (buffer) + 9, "fLaC", 4) != 0) { || gst_buffer_memcmp (buffer, 9, "fLaC", 4) != 0) {
GST_WARNING ("Invalid streamheader for FLAC"); GST_WARNING ("Invalid streamheader for FLAC");
return FALSE; return FALSE;
} }
context->codec_priv = g_malloc (GST_BUFFER_SIZE (buffer) - 9); context->codec_priv_size = gst_buffer_get_size (buffer) - 9;
context->codec_priv_size = GST_BUFFER_SIZE (buffer) - 9; context->codec_priv = g_malloc (context->codec_priv_size);
memcpy (context->codec_priv, GST_BUFFER_DATA (buffer) + 9, gst_buffer_extract (buffer, 9, context->codec_priv, -1);
GST_BUFFER_SIZE (buffer) - 9);
for (i = 1; i < bufarr->len; i++) { for (i = 1; i < bufarr->len; i++) {
guint old_size;
bufval = &g_array_index (bufarr, GValue, i); bufval = &g_array_index (bufarr, GValue, i);
if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) { 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); buffer = g_value_peek_pointer (bufval);
context->codec_priv = old_size = context->codec_priv_size;
g_realloc (context->codec_priv, context->codec_priv_size += gst_buffer_get_size (buffer);
context->codec_priv_size + GST_BUFFER_SIZE (buffer));
memcpy ((guint8 *) context->codec_priv + context->codec_priv_size, context->codec_priv = g_realloc (context->codec_priv,
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); context->codec_priv_size);
context->codec_priv_size = gst_buffer_extract (buffer, 0,
context->codec_priv_size + GST_BUFFER_SIZE (buffer); (guint8 *) context->codec_priv + old_size, -1);
} }
return TRUE; return TRUE;
@ -1289,6 +1269,7 @@ speex_streamheader_to_codecdata (const GValue * streamheader,
GArray *bufarr; GArray *bufarr;
GValue *bufval; GValue *bufval;
GstBuffer *buffer; GstBuffer *buffer;
guint old_size;
if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) { if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
GST_WARNING ("No or invalid streamheader field in the caps"); 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); buffer = g_value_peek_pointer (bufval);
if (GST_BUFFER_SIZE (buffer) < 80 if (gst_buffer_get_size (buffer) < 80
|| memcmp (GST_BUFFER_DATA (buffer), "Speex ", 8) != 0) { || gst_buffer_memcmp (buffer, 0, "Speex ", 8) != 0) {
GST_WARNING ("Invalid streamheader for Speex"); GST_WARNING ("Invalid streamheader for Speex");
return FALSE; return FALSE;
} }
context->codec_priv = g_malloc (GST_BUFFER_SIZE (buffer)); context->codec_priv_size = gst_buffer_get_size (buffer);
context->codec_priv_size = GST_BUFFER_SIZE (buffer); context->codec_priv = g_malloc (context->codec_priv_size);
memcpy (context->codec_priv, GST_BUFFER_DATA (buffer), gst_buffer_extract (buffer, 0, context->codec_priv, -1);
GST_BUFFER_SIZE (buffer));
bufval = &g_array_index (bufarr, GValue, 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); buffer = g_value_peek_pointer (bufval);
context->codec_priv = old_size = context->codec_priv_size;
g_realloc (context->codec_priv, context->codec_priv_size += gst_buffer_get_size (buffer);
context->codec_priv_size + GST_BUFFER_SIZE (buffer)); context->codec_priv = g_realloc (context->codec_priv,
memcpy ((guint8 *) context->codec_priv + context->codec_priv_size, context->codec_priv_size);
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); gst_buffer_extract (buffer, 0, (guint8 *) context->codec_priv + old_size, -1);
context->codec_priv_size =
context->codec_priv_size + GST_BUFFER_SIZE (buffer);
return TRUE; return TRUE;
} }
static const gchar * static const gchar *
aac_codec_data_to_codec_id (const GstBuffer * buf) aac_codec_data_to_codec_id (GstBuffer * buf)
{ {
const gchar *result; const gchar *result;
gint profile; guint8 profile;
/* default to MAIN */ /* default to MAIN */
profile = 1; profile = 1;
if (GST_BUFFER_SIZE (buf) >= 2) { if (gst_buffer_get_size (buf) >= 2) {
profile = GST_READ_UINT8 (GST_BUFFER_DATA (buf)); gst_buffer_extract (buf, 0, &profile, 1);
profile >>= 3; profile >>= 3;
} }
@ -1401,7 +1379,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
gint samplerate = 0, channels = 0; gint samplerate = 0, channels = 0;
GstStructure *structure; GstStructure *structure;
const GValue *codec_data = NULL; const GValue *codec_data = NULL;
const GstBuffer *buf = NULL; GstBuffer *buf = NULL;
const gchar *stream_format = NULL; const gchar *stream_format = NULL;
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad)); mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
@ -1513,51 +1491,45 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
default: default:
goto refuse_caps; goto refuse_caps;
} }
} else if (!strcmp (mimetype, "audio/x-raw-int")) { } else if (!strcmp (mimetype, "audio/x-raw")) {
gint width, depth; GstAudioInfo info;
gint endianness = G_LITTLE_ENDIAN;
gboolean signedness = TRUE;
if (!gst_structure_get_int (structure, "width", &width) || gst_audio_info_init (&info);
!gst_structure_get_int (structure, "depth", &depth) || if (!gst_audio_info_from_caps (&info, caps)) {
!gst_structure_get_boolean (structure, "signed", &signedness)) { GST_DEBUG_OBJECT (mux,
GST_DEBUG_OBJECT (mux, "broken caps, width/depth/signed field missing"); "broken caps, rejected by gst_audio_info_from_caps");
goto refuse_caps; goto refuse_caps;
} }
if (depth > 8 && switch (GST_AUDIO_INFO_FORMAT (&info)) {
!gst_structure_get_int (structure, "endianness", &endianness)) { case GST_AUDIO_FORMAT_U8:
GST_DEBUG_OBJECT (mux, "broken caps, no endianness specified"); case GST_AUDIO_FORMAT_S16BE:
goto refuse_caps; 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;
case GST_AUDIO_FORMAT_F32LE:
case GST_AUDIO_FORMAT_F64LE:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
break;
default:
GST_DEBUG_OBJECT (mux, "wrong format in raw audio caps");
goto refuse_caps;
} }
if (width != depth) { audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
GST_DEBUG_OBJECT (mux, "width must be same as depth!");
goto refuse_caps;
}
/* 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");
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);
} else if (!strcmp (mimetype, "audio/x-raw-float")) {
gint width;
if (!gst_structure_get_int (structure, "width", &width)) {
GST_DEBUG_OBJECT (mux, "broken caps, width field missing");
goto refuse_caps;
}
audiocontext->bitdepth = width;
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_FLOAT);
} else if (!strcmp (mimetype, "audio/x-vorbis")) { } else if (!strcmp (mimetype, "audio/x-vorbis")) {
const GValue *streamheader; 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); 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); 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 = priv_data;
context->codec_priv_size = priv_data_size; 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; codec_priv_size = WAVEFORMATEX_SIZE;
if (buf) if (buf)
codec_priv_size += GST_BUFFER_SIZE (buf); codec_priv_size += gst_buffer_get_size (buf);
/* serialize waveformatex structure */ /* serialize waveformatex structure */
codec_priv = g_malloc0 (codec_priv_size); 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 + 12, block_align);
GST_WRITE_UINT16_LE (codec_priv + 14, 0); GST_WRITE_UINT16_LE (codec_priv + 14, 0);
if (buf) 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 else
GST_WRITE_UINT16_LE (codec_priv + 16, 0); GST_WRITE_UINT16_LE (codec_priv + 16, 0);
/* process codec private/initialization data, if any */ /* process codec private/initialization data, if any */
if (buf) { if (buf) {
memcpy ((guint8 *) codec_priv + WAVEFORMATEX_SIZE, gst_buffer_extract (buf, 0,
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); (guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
} }
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM); 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 * static GstPad *
gst_matroska_mux_request_new_pad (GstElement * element, 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); GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
GstMatroskaMux *mux = GST_MATROSKA_MUX (element); GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
@ -1847,7 +1819,7 @@ gst_matroska_mux_request_new_pad (GstElement * element,
GstPad *newpad = NULL; GstPad *newpad = NULL;
gchar *name = NULL; gchar *name = NULL;
const gchar *pad_name = NULL; const gchar *pad_name = NULL;
GstPadSetCapsFunction setcapsfunc = NULL; GstMatroskaCapsFunc capsfunc = NULL;
GstMatroskaTrackContext *context = NULL; GstMatroskaTrackContext *context = NULL;
gint pad_id; 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++); name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
pad_name = name; 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 *) context = (GstMatroskaTrackContext *)
g_new0 (GstMatroskaTrackAudioContext, 1); g_new0 (GstMatroskaTrackAudioContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_AUDIO; 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++); name = g_strdup_printf ("video_%u", mux->num_v_streams++);
pad_name = name; 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 *) context = (GstMatroskaTrackContext *)
g_new0 (GstMatroskaTrackVideoContext, 1); g_new0 (GstMatroskaTrackVideoContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_VIDEO; 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++); name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
pad_name = name; 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 *) context = (GstMatroskaTrackContext *)
g_new0 (GstMatroskaTrackSubtitleContext, 1); g_new0 (GstMatroskaTrackSubtitleContext, 1);
context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE; 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_pad_set_event_function (newpad,
GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event)); 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); gst_pad_set_active (newpad, TRUE);
if (!gst_element_add_pad (element, newpad)) if (!gst_element_add_pad (element, newpad))
goto pad_add_failed; goto pad_add_failed;
@ -2109,9 +2081,9 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
GTimeVal time = { 0, 0 }; GTimeVal time = { 0, 0 };
if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) { 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 { } 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 */ /* we start with a EBML header */
doctype = mux->doctype; doctype = mux->doctype;
@ -2176,7 +2148,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
for (collected = mux->collect->data; collected; for (collected = mux->collect->data; collected;
collected = g_slist_next (collected)) { collected = g_slist_next (collected)) {
GstMatroskaPad *collect_pad; GstMatroskaPad *collect_pad;
GstFormat format = GST_FORMAT_TIME;
GstPad *thepad; GstPad *thepad;
gint64 trackduration; gint64 trackduration;
@ -2185,7 +2156,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
/* Query the total length of the track. */ /* Query the total length of the track. */
GST_DEBUG_OBJECT (thepad, "querying peer duration"); 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_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
GST_TIME_ARGS (trackduration)); GST_TIME_ARGS (trackduration));
if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) { 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 (GST_BUFFER_TIMESTAMP (collect_pad->buffer)),
GST_TIME_ARGS (time)); GST_TIME_ARGS (time));
collect_pad->buffer = 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; GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time;
} }
} }
@ -2539,15 +2510,16 @@ gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
gint16 relative_timestamp, int flags) gint16 relative_timestamp, int flags)
{ {
GstBuffer *hdr; 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)? */ /* 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 */ /* time relative to clustertime */
GST_WRITE_UINT16_BE (GST_BUFFER_DATA (hdr) + 1, relative_timestamp); GST_WRITE_UINT16_BE (data + 1, relative_timestamp);
/* flags */ /* flags */
GST_BUFFER_DATA (hdr)[3] = flags; data[3] = flags;
return hdr; return hdr;
} }
@ -2562,14 +2534,18 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
{ {
GstMatroskaTrackVideoContext *ctx = GstMatroskaTrackVideoContext *ctx =
(GstMatroskaTrackVideoContext *) collect_pad->track; (GstMatroskaTrackVideoContext *) collect_pad->track;
const guint8 *data = GST_BUFFER_DATA (buf); guint8 *buf_data, *data;
guint size = GST_BUFFER_SIZE (buf); gsize size;
guint8 parse_code; guint8 parse_code;
guint32 next_parse_offset; guint32 next_parse_offset;
GstBuffer *ret = NULL; GstBuffer *ret = NULL;
gboolean is_muxing_unit = FALSE; 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); gst_buffer_unref (buf);
return ret; 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 */ /* Check if this buffer contains a picture or end-of-sequence packet */
while (size >= 13) { while (size >= 13) {
if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) { if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
gst_buffer_unmap (buf, buf_data, -1);
gst_buffer_unref (buf); gst_buffer_unref (buf);
return ret; return ret;
} }
@ -2607,12 +2584,13 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
else else
ctx->dirac_unit = gst_buffer_ref (buf); ctx->dirac_unit = gst_buffer_ref (buf);
gst_buffer_unmap (buf, buf_data, -1);
if (is_muxing_unit) { 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; ctx->dirac_unit = NULL;
gst_buffer_copy_metadata (ret, buf, gst_buffer_copy_into (ret, buf,
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
GST_BUFFER_COPY_CAPS);
gst_buffer_unref (buf); gst_buffer_unref (buf);
} else { } else {
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -2634,9 +2612,9 @@ gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
streamheader_buffer = gst_ebml_stop_streamheader (ebml); streamheader_buffer = gst_ebml_stop_streamheader (ebml);
if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) { 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 { } 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); s = gst_caps_get_structure (caps, 0);
g_value_init (&streamheader, GST_TYPE_ARRAY); g_value_init (&streamheader, GST_TYPE_ARRAY);
@ -2836,14 +2814,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
relative_timestamp, flags); relative_timestamp, flags);
gst_ebml_write_set_cache (ebml, 0x40); gst_ebml_write_set_cache (ebml, 0x40);
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK, 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_buffer (ebml, hdr);
gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf)); gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
gst_ebml_write_buffer (ebml, buf); gst_ebml_write_buffer (ebml, buf);
return gst_ebml_last_write_result (ebml); return gst_ebml_last_write_result (ebml);
} else { } 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, /* write and call order slightly unnatural,
* but avoids seek and minizes pushing */ * but avoids seek and minizes pushing */
blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP); 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) if (write_duration)
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration); gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK, 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_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_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
gst_ebml_write_buffer (ebml, buf); gst_ebml_write_buffer (ebml, buf);

View file

@ -53,10 +53,13 @@ typedef struct _GstMatroskaMetaSeekIndex {
guint64 pos; guint64 pos;
} GstMatroskaMetaSeekIndex; } GstMatroskaMetaSeekIndex;
typedef gboolean (*GstMatroskaCapsFunc) (GstPad *pad, GstCaps *caps);
/* all information needed for one matroska stream */ /* all information needed for one matroska stream */
typedef struct typedef struct
{ {
GstCollectData collect; /* we extend the CollectData */ GstCollectData collect; /* we extend the CollectData */
GstMatroskaCapsFunc capsfunc;
GstMatroskaTrackContext *track; GstMatroskaTrackContext *track;
GstBuffer *buffer; /* the queued buffer for this pad */ GstBuffer *buffer; /* the queued buffer for this pad */

View file

@ -111,16 +111,14 @@ static gboolean gst_matroska_parse_element_query (GstElement * element,
static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse, static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
GstPad * pad, GstEvent * event); GstPad * pad, GstEvent * event);
static gboolean gst_matroska_parse_handle_src_event (GstPad * pad, static gboolean gst_matroska_parse_handle_src_event (GstPad * pad,
GstEvent * event); GstObject * parent, GstEvent * event);
static const GstQueryType *gst_matroska_parse_get_src_query_types (GstPad *
pad);
static gboolean gst_matroska_parse_handle_src_query (GstPad * pad, 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, static gboolean gst_matroska_parse_handle_sink_event (GstPad * pad,
GstEvent * event); GstObject * parent, GstEvent * event);
static GstFlowReturn gst_matroska_parse_chain (GstPad * pad, static GstFlowReturn gst_matroska_parse_chain (GstPad * pad,
GstBuffer * buffer); GstObject * parent, GstBuffer * buffer);
static GstStateChangeReturn static GstStateChangeReturn
gst_matroska_parse_change_state (GstElement * element, gst_matroska_parse_change_state (GstElement * element,
@ -135,24 +133,8 @@ static gboolean perform_seek_to_offset (GstMatroskaParse * parse,
guint64 offset); guint64 offset);
GType gst_matroska_parse_get_type (void); GType gst_matroska_parse_get_type (void);
GST_BOILERPLATE (GstMatroskaParse, gst_matroska_parse, GstElement, #define parent_class gst_matroska_parse_parent_class
GST_TYPE_ELEMENT); G_DEFINE_TYPE (GstMatroskaParse, gst_matroska_parse, 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 <gstreamer-devel@lists.sourceforge.net>");
}
static void static void
gst_matroska_parse_finalize (GObject * object) 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); GST_DEBUG_FUNCPTR (gst_matroska_parse_set_index);
gstelement_class->get_index = gstelement_class->get_index =
GST_DEBUG_FUNCPTR (gst_matroska_parse_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 <gstreamer-devel@lists.sourceforge.net>");
} }
static void static void
gst_matroska_parse_init (GstMatroskaParse * parse, gst_matroska_parse_init (GstMatroskaParse * parse)
GstMatroskaParseClass * klass)
{ {
parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ, parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ,
"sink"); "sink");
@ -213,8 +204,6 @@ gst_matroska_parse_init (GstMatroskaParse * parse,
parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src"); parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
gst_pad_set_event_function (parse->srcpad, gst_pad_set_event_function (parse->srcpad,
GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_event)); 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_pad_set_query_function (parse->srcpad,
GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query)); GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query));
gst_pad_use_fixed_caps (parse->srcpad); gst_pad_use_fixed_caps (parse->srcpad);
@ -374,7 +363,7 @@ gst_matroska_parse_reset (GstElement * element)
if (parse->common.global_tags) { if (parse->common.global_tags) {
gst_tag_list_free (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) { if (parse->common.cached_buffer) {
gst_buffer_unref (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; 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 static gboolean
gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad, gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
GstQuery * query) GstQuery * query)
@ -1115,7 +1091,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
gst_query_set_position (query, GST_FORMAT_TIME, context->pos); gst_query_set_position (query, GST_FORMAT_TIME, context->pos);
else else
gst_query_set_position (query, GST_FORMAT_TIME, gst_query_set_position (query, GST_FORMAT_TIME,
parse->common.segment.last_stop); parse->common.segment.position);
GST_OBJECT_UNLOCK (parse); GST_OBJECT_UNLOCK (parse);
} else if (format == GST_FORMAT_DEFAULT && context } else if (format == GST_FORMAT_DEFAULT && context
&& context->default_duration) { && context->default_duration) {
@ -1175,7 +1151,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
break; break;
} }
default: default:
res = gst_pad_query_default (pad, query); res = gst_pad_query_default (pad, (GstObject *) parse, query);
break; break;
} }
@ -1189,15 +1165,14 @@ gst_matroska_parse_element_query (GstElement * element, GstQuery * query)
} }
static gboolean 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; 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); ret = gst_matroska_parse_query (parse, pad, query);
gst_object_unref (parse);
return ret; return ret;
} }
@ -1248,6 +1223,8 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
const guint chunk = 64 * 1024; const guint chunk = 64 * 1024;
GstBuffer *buf = NULL; GstBuffer *buf = NULL;
gpointer data;
gsize size;
guint64 length; guint64 length;
guint32 id; guint32 id;
guint needed; guint needed;
@ -1263,13 +1240,13 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
break; break;
GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT, GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT,
GST_BUFFER_SIZE (buf), newpos); gst_buffer_get_size (buf), newpos);
gst_byte_reader_init_from_buffer (&reader, buf); data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
gst_byte_reader_init (&reader, data, size);
cluster_pos = 0; cluster_pos = 0;
resume: resume:
cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
GST_MATROSKA_ID_CLUSTER, cluster_pos, GST_MATROSKA_ID_CLUSTER, cluster_pos, size - cluster_pos);
GST_BUFFER_SIZE (buf) - cluster_pos);
if (cluster_pos >= 0) { if (cluster_pos >= 0) {
newpos += cluster_pos; newpos += cluster_pos;
GST_DEBUG_OBJECT (parse, GST_DEBUG_OBJECT (parse,
@ -1311,13 +1288,15 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
goto resume; goto resume;
} else { } else {
/* partial cluster id may have been in tail of buffer */ /* 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); gst_buffer_unref (buf);
buf = NULL; buf = NULL;
} }
} }
if (buf) { if (buf) {
gst_buffer_unmap (buf, data, size);
gst_buffer_unref (buf); gst_buffer_unref (buf);
buf = NULL; buf = NULL;
} }
@ -1362,7 +1341,7 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
if (event) { if (event) {
GST_DEBUG_OBJECT (parse, "configuring seek"); 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); 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 */ /* check sanity before we start flushing and all that */
GST_OBJECT_LOCK (parse); GST_OBJECT_LOCK (parse);
if ((entry = gst_matroska_read_common_do_index_seek (&parse->common, track, 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) { NULL) {
/* pull mode without index can scan later on */ /* pull mode without index can scan later on */
GST_DEBUG_OBJECT (parse, "No matching seek entry in index"); 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 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; gboolean res = TRUE;
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
@ -1499,7 +1479,7 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
GstClockTimeDiff diff; GstClockTimeDiff diff;
GstClockTime timestamp; GstClockTime timestamp;
gst_event_parse_qos (event, &proportion, &diff, &timestamp); gst_event_parse_qos (event, NULL, &proportion, &diff, &timestamp);
GST_OBJECT_LOCK (parse); GST_OBJECT_LOCK (parse);
videocontext->earliest_time = timestamp + diff; videocontext->earliest_time = timestamp + diff;
@ -1522,8 +1502,6 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
break; break;
} }
gst_object_unref (parse);
return res; return res;
} }
@ -1635,6 +1613,8 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
guint32 id; guint32 id;
guint64 block_duration = 0; guint64 block_duration = 0;
GstBuffer *buf = NULL; GstBuffer *buf = NULL;
gpointer buf_data = NULL;
gsize buf_size = 0;
gint stream_num = -1, n, laces = 0; gint stream_num = -1, n, laces = 0;
guint size = 0; guint size = 0;
gint *lace_size = NULL; 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) if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
break; break;
data = GST_BUFFER_DATA (buf); buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ);
size = GST_BUFFER_SIZE (buf);
data = buf_data;
size = buf_size;
/* first byte(s): blocknum */ /* first byte(s): blocknum */
if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0) 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 */ /* need to refresh segment info ASAP */
if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) { if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) {
GstSegment segment;
GST_DEBUG_OBJECT (parse, GST_DEBUG_OBJECT (parse,
"generating segment starting at %" GST_TIME_FORMAT, "generating segment starting at %" GST_TIME_FORMAT,
GST_TIME_ARGS (lace_time)); GST_TIME_ARGS (lace_time));
/* pretend we seeked here */ /* 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_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time,
GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL); GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL);
/* now convey our segment notion downstream */ /* now convey our segment notion downstream */
gst_matroska_parse_send_event (parse, gst_event_new_new_segment (FALSE, segment = parse->common.segment;
parse->common.segment.rate, parse->common.segment.format, segment.position = segment.start;
parse->common.segment.start, parse->common.segment.stop, gst_matroska_parse_send_event (parse, gst_event_new_segment (&segment));
parse->common.segment.start));
parse->need_newsegment = FALSE; parse->need_newsegment = FALSE;
} }
@ -2134,8 +2116,10 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
} }
done: done:
if (buf) if (buf) {
gst_buffer_unmap (buf, buf_data, buf_size);
gst_buffer_unref (buf); gst_buffer_unref (buf);
}
g_free (lace_size); g_free (lace_size);
return ret; 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 */ /* try harder to query upstream size if we didn't get it the first time */
if (seekable && stop == -1) { if (seekable && stop == -1) {
GstFormat fmt = GST_FORMAT_BYTES;
GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop"); 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 /* 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; GstBuffer *buf;
buf = gst_buffer_span (parse->streamheader, 0, buffer, 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); gst_buffer_unref (parse->streamheader);
parse->streamheader = buf; parse->streamheader = buf;
} else { } else {
parse->streamheader = gst_buffer_ref (buffer); 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 static GstFlowReturn
@ -2529,7 +2513,7 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
GValue bufval = { 0 }; GValue bufval = { 0 };
GstBuffer *buf; 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); s = gst_caps_get_structure (caps, 0);
g_value_init (&streamheader, GST_TYPE_ARRAY); g_value_init (&streamheader, GST_TYPE_ARRAY);
g_value_init (&bufval, GST_TYPE_BUFFER); 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); gst_pad_set_caps (parse->srcpad, caps);
buf = gst_buffer_copy (parse->streamheader); buf = gst_buffer_copy (parse->streamheader);
gst_buffer_set_caps (buf, caps);
gst_caps_unref (caps); gst_caps_unref (caps);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
@ -2567,7 +2550,6 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
} else { } else {
GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp; 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)); ret = gst_pad_push (parse->srcpad, gst_buffer_ref (buffer));
return ret; return ret;
@ -3028,9 +3010,9 @@ perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
} }
static GstFlowReturn 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; guint available;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
guint needed = 0; guint needed = 0;
@ -3075,7 +3057,8 @@ next:
} }
static gboolean 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; gboolean res = TRUE;
GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad)); 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); "have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT: case GST_EVENT_SEGMENT:
{ {
GstFormat format; const GstSegment *segment;
gdouble rate, arate;
gint64 start, stop, time = 0;
gboolean update;
GstSegment segment;
/* some debug output */ /* some debug output */
gst_segment_init (&segment, GST_FORMAT_UNDEFINED); gst_event_parse_segment (event, &segment);
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_DEBUG_OBJECT (parse, GST_DEBUG_OBJECT (parse,
"received format %d newsegment %" GST_SEGMENT_FORMAT, format, "received format %d newsegment %" GST_SEGMENT_FORMAT,
&segment); segment->format, segment);
if (parse->common.state < GST_MATROSKA_READ_STATE_DATA) { if (parse->common.state < GST_MATROSKA_READ_STATE_DATA) {
GST_DEBUG_OBJECT (parse, "still starting"); 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 */ /* 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"); GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring");
goto exit; goto exit;
} }
@ -3117,15 +3092,15 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
/* clear current segment leftover */ /* clear current segment leftover */
gst_adapter_clear (parse->common.adapter); gst_adapter_clear (parse->common.adapter);
/* and some streaming setup */ /* and some streaming setup */
parse->common.offset = start; parse->common.offset = segment->start;
/* do not know where we are; /* do not know where we are;
* need to come across a cluster and generate newsegment */ * 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_time = GST_CLOCK_TIME_NONE;
parse->cluster_offset = 0; parse->cluster_offset = 0;
parse->need_newsegment = TRUE; parse->need_newsegment = TRUE;
/* but keep some of the upstream segment */ /* but keep some of the upstream segment */
parse->common.segment.rate = rate; parse->common.segment.rate = segment->rate;
exit: exit:
/* chain will send initial newsegment after pads have been added, /* chain will send initial newsegment after pads have been added,
* or otherwise come up with one */ * 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_matroska_read_common_reset_streams (&parse->common,
GST_CLOCK_TIME_NONE, TRUE); GST_CLOCK_TIME_NONE, TRUE);
GST_OBJECT_UNLOCK (parse); 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_time = GST_CLOCK_TIME_NONE;
parse->cluster_offset = 0; parse->cluster_offset = 0;
/* fall-through */ /* fall-through */
} }
default: default:
res = gst_pad_event_default (pad, event); res = gst_pad_event_default (pad, parent, event);
break; break;
} }

View file

@ -58,7 +58,7 @@ GST_DEBUG_CATEGORY (matroskareadcommon_debug);
static gboolean static gboolean
gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc, gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
guint8 ** data_out, guint * size_out, gpointer * data_out, gsize * size_out,
GstMatroskaTrackCompressionAlgorithm algo) GstMatroskaTrackCompressionAlgorithm algo)
{ {
guint8 *new_data = NULL; guint8 *new_data = NULL;
@ -237,8 +237,8 @@ gst_matroska_decode_content_encodings (GArray * encodings)
for (i = 0; i < encodings->len; i++) { for (i = 0; i < encodings->len; i++) {
GstMatroskaTrackEncoding *enc = GstMatroskaTrackEncoding *enc =
&g_array_index (encodings, GstMatroskaTrackEncoding, i); &g_array_index (encodings, GstMatroskaTrackEncoding, i);
guint8 *data = NULL; gpointer data = NULL;
guint size; gsize size;
if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING) if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
== 0) == 0)
@ -270,11 +270,11 @@ gst_matroska_decode_content_encodings (GArray * encodings)
} }
gboolean gboolean
gst_matroska_decode_data (GArray * encodings, guint8 ** data_out, gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free) gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
{ {
guint8 *data; gpointer data;
guint size; gsize size;
gboolean ret = TRUE; gboolean ret = TRUE;
gint i; gint i;
@ -288,8 +288,8 @@ gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
for (i = 0; i < encodings->len; i++) { for (i = 0; i < encodings->len; i++) {
GstMatroskaTrackEncoding *enc = GstMatroskaTrackEncoding *enc =
&g_array_index (encodings, GstMatroskaTrackEncoding, i); &g_array_index (encodings, GstMatroskaTrackEncoding, i);
guint8 *new_data = NULL; gpointer new_data = NULL;
guint new_size = 0; gsize new_size = 0;
if ((enc->scope & scope) == 0) if ((enc->scope & scope) == 0)
continue; 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_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
gst_tag_list_free (taglist); gst_tag_list_free (taglist);
} else { } else {
GstEvent *tag_event = gst_event_new_tag (taglist);
gint i;
/* hm, already sent, no need to cache and wait anymore */ /* hm, already sent, no need to cache and wait anymore */
GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT, GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT,
taglist); 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 gint64
gst_matroska_read_common_get_length (GstMatroskaReadCommon * common) gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
{ {
GstFormat fmt = GST_FORMAT_BYTES;
gint64 end = -1; gint64 end = -1;
if (!gst_pad_query_peer_duration (common->sinkpad, &fmt, &end) || if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
fmt != GST_FORMAT_BYTES || end < 0) &end) || end < 0)
GST_DEBUG_OBJECT (common, "no upstream length"); GST_DEBUG_OBJECT (common, "no upstream length");
return end; return end;
@ -569,7 +579,7 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
if (filename && mimetype && data && datalen > 0) { if (filename && mimetype && data && datalen > 0) {
GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE; GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
GstBuffer *tagbuffer = NULL; GstBuffer *tagbuffer = NULL;
GstCaps *caps; /* GstCaps *caps; */
gchar *filename_lc = g_utf8_strdown (filename, -1); gchar *filename_lc = g_utf8_strdown (filename, -1);
GST_DEBUG_OBJECT (common, "Creating tag for attachment with " GST_DEBUG_OBJECT (common, "Creating tag for attachment with "
@ -600,31 +610,32 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
if (!tagbuffer) if (!tagbuffer)
image_type = GST_TAG_IMAGE_TYPE_NONE; image_type = GST_TAG_IMAGE_TYPE_NONE;
else
data = NULL;
} }
/* if this failed create an attachment buffer */ /* if this failed create an attachment buffer */
if (!tagbuffer) { if (!tagbuffer) {
tagbuffer = gst_buffer_new_and_alloc (datalen); tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen); /* FIXME: We can't attach caps to buffers in 0.11. */
GST_BUFFER_SIZE (tagbuffer) = datalen; /* caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); */
/* if (caps == NULL) */
caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); /* caps = gst_caps_new_simple (mimetype, NULL); */
if (caps == NULL) /* gst_buffer_set_caps (tagbuffer, caps); */
caps = gst_caps_new_simple (mimetype, NULL); /* gst_caps_unref (caps); */
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 */ /* Set filename and description on the caps */
caps = GST_BUFFER_CAPS (tagbuffer); /* caps = GST_BUFFER_CAPS (tagbuffer); */
gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); /* gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); */
if (description) /* if (description) */
gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, /* gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, */
NULL); /* NULL); */
GST_DEBUG_OBJECT (common, /* GST_DEBUG_OBJECT (common, */
"Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); /* "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); */
/* and append to the tag list */ /* and append to the tag list */
if (image_type != GST_TAG_IMAGE_TYPE_NONE) if (image_type != GST_TAG_IMAGE_TYPE_NONE)
@ -658,7 +669,7 @@ gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
return ret; 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)) { while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
@ -1280,9 +1291,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
break; break;
GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text)); GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text));
taglist = gst_tag_list_new (); taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text,
NULL);
gst_matroska_read_common_found_global_tag (common, el, taglist); gst_matroska_read_common_found_global_tag (common, el, taglist);
g_free (text); g_free (text);
break; break;
@ -1313,7 +1322,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
dur_u = gst_gdouble_to_guint64 (dur_f * dur_u = gst_gdouble_to_guint64 (dur_f *
gst_guint64_to_gdouble (common->time_scale)); gst_guint64_to_gdouble (common->time_scale));
if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64) 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); DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
@ -1518,7 +1527,7 @@ gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
return ret; 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)) { while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) 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 gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
peek, const guint8 ** data) 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) if (*data == NULL)
return GST_FLOW_UNEXPECTED; 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 */ * We do it mainly to avoid pulling buffers of 1 byte all the time */
if (common->cached_buffer) { if (common->cached_buffer) {
guint64 cache_offset = GST_BUFFER_OFFSET (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 && if (cache_offset <= common->offset &&
(common->offset + size) <= (cache_offset + cache_size)) { (common->offset + size) <= (cache_offset + cache_size)) {
if (p_buf) if (p_buf)
*p_buf = gst_buffer_create_sub (common->cached_buffer, *p_buf = gst_buffer_copy_region (common->cached_buffer,
common->offset - cache_offset, size); GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
if (bytes) if (bytes) {
*bytes = GST_BUFFER_DATA (common->cached_buffer) + common->offset - if (!common->cached_data)
cache_offset; 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; return GST_FLOW_OK;
} }
/* not enough data in the cache, free cache and get a new one */ /* 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); gst_buffer_unref (common->cached_buffer);
common->cached_buffer = NULL; common->cached_buffer = NULL;
} }
@ -1596,11 +1613,15 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
return ret; return ret;
} }
if (GST_BUFFER_SIZE (common->cached_buffer) >= size) { if (gst_buffer_get_size (common->cached_buffer) >= size) {
if (p_buf) if (p_buf)
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size); *p_buf = gst_buffer_copy_region (common->cached_buffer,
if (bytes) GST_BUFFER_COPY_ALL, 0, size);
*bytes = GST_BUFFER_DATA (common->cached_buffer); if (bytes) {
common->cached_data = gst_buffer_map (common->cached_buffer,
NULL, NULL, GST_MAP_READ);
*bytes = common->cached_data;
}
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -1621,10 +1642,10 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
return ret; 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 %" GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", common->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); gst_buffer_unref (common->cached_buffer);
common->cached_buffer = NULL; common->cached_buffer = NULL;
@ -1636,9 +1657,13 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
} }
if (p_buf) if (p_buf)
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size); *p_buf = gst_buffer_copy_region (common->cached_buffer,
if (bytes) GST_BUFFER_COPY_ALL, 0, size);
*bytes = GST_BUFFER_DATA (common->cached_buffer); if (bytes) {
common->cached_data = gst_buffer_map (common->cached_buffer,
NULL, NULL, GST_MAP_READ);
*bytes = common->cached_data;
}
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -1664,9 +1689,15 @@ GstFlowReturn
gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common, gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
GstElement * el, guint32 * _id, guint64 * _length, guint * _needed) 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, (GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
el, common->offset); el, common->offset);
gst_adapter_unmap (common->adapter);
return ret;
} }
static GstFlowReturn static GstFlowReturn

View file

@ -81,6 +81,7 @@ typedef struct _GstMatroskaReadCommon {
/* pull mode caching */ /* pull mode caching */
GstBuffer *cached_buffer; GstBuffer *cached_buffer;
guint8 *cached_data;
/* push and pull mode */ /* push and pull mode */
guint64 offset; guint64 offset;
@ -90,8 +91,8 @@ typedef struct _GstMatroskaReadCommon {
} GstMatroskaReadCommon; } GstMatroskaReadCommon;
GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings); GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings);
gboolean gst_matroska_decode_data (GArray * encodings, guint8 ** data_out, gboolean gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free); gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free);
gint gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time, gint gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
gpointer user_data); gpointer user_data);
GstMatroskaIndex * gst_matroska_read_common_do_index_seek ( GstMatroskaIndex * gst_matroska_read_common_do_index_seek (

View file

@ -32,8 +32,8 @@
* ]| This pipeline re-encodes a video file of any format into a WebM file. * ]| 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 \ * 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 \ * 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-float,rate=44100 ! vorbisenc ! queue ! mux.audio_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. * ]| This pipeline muxes a test video and a sine wave into a WebM file.
* </refsect2> * </refsect2>
*/ */
@ -53,8 +53,7 @@
"channels = (int) [ 1, MAX ], " \ "channels = (int) [ 1, MAX ], " \
"rate = (int) [ 1, MAX ]" "rate = (int) [ 1, MAX ]"
GST_BOILERPLATE (GstWebMMux, gst_webm_mux, GstMatroskaMux, G_DEFINE_TYPE (GstWebMMux, gst_webm_mux, GST_TYPE_MATROSKA_MUX);
GST_TYPE_MATROSKA_MUX);
static GstStaticPadTemplate webm_src_templ = GST_STATIC_PAD_TEMPLATE ("src", static GstStaticPadTemplate webm_src_templ = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
@ -76,11 +75,6 @@ GST_STATIC_PAD_TEMPLATE ("audio_%u",
GST_STATIC_CAPS ("audio/x-vorbis, " COMMON_AUDIO_CAPS) GST_STATIC_CAPS ("audio/x-vorbis, " COMMON_AUDIO_CAPS)
); );
static void
gst_webm_mux_base_init (gpointer g_class)
{
}
static void static void
gst_webm_mux_class_init (GstWebMMuxClass * klass) gst_webm_mux_class_init (GstWebMMuxClass * klass)
{ {
@ -99,7 +93,7 @@ gst_webm_mux_class_init (GstWebMMuxClass * klass)
} }
static void 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; GST_MATROSKA_MUX (mux)->doctype = GST_MATROSKA_DOCTYPE_WEBM;
} }

View file

@ -163,6 +163,7 @@ static GstElement *
setup_matroskamux (GstStaticPadTemplate * srctemplate) setup_matroskamux (GstStaticPadTemplate * srctemplate)
{ {
GstElement *matroskamux; GstElement *matroskamux;
GstSegment segment;
GST_DEBUG ("setup_matroskamux"); GST_DEBUG ("setup_matroskamux");
matroskamux = gst_check_setup_element ("matroskamux"); matroskamux = gst_check_setup_element ("matroskamux");
@ -170,6 +171,14 @@ setup_matroskamux (GstStaticPadTemplate * srctemplate)
mysrcpad = setup_src_pad (matroskamux, srctemplate, NULL); mysrcpad = setup_src_pad (matroskamux, srctemplate, NULL);
mysinkpad = setup_sink_pad (matroskamux, &sinktemplate, 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; return matroskamux;
} }
@ -187,8 +196,8 @@ cleanup_matroskamux (GstElement * matroskamux)
static void static void
check_buffer_data (GstBuffer * buffer, void *data, size_t data_size) check_buffer_data (GstBuffer * buffer, void *data, size_t data_size)
{ {
fail_unless (GST_BUFFER_SIZE (buffer) == data_size); fail_unless (gst_buffer_get_size (buffer) == data_size);
fail_unless (memcmp (data, GST_BUFFER_DATA (buffer), data_size) == 0); fail_unless (gst_buffer_memcmp (buffer, 0, data, data_size) == 0);
} }
GST_START_TEST (test_ebml_header) GST_START_TEST (test_ebml_header)
@ -207,11 +216,8 @@ GST_START_TEST (test_ebml_header)
}; };
matroskamux = setup_matroskamux (&srcac3template); 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); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
num_buffers = g_list_length (buffers); num_buffers = g_list_length (buffers);
@ -259,14 +265,12 @@ GST_START_TEST (test_vorbis_header)
}; };
matroskamux = setup_matroskamux (&srcvorbistemplate); 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); 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); gst_caps_unref (caps);
inbuffer = gst_buffer_new_allocate (NULL, 1, 0);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); 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) { for (i = 0; i < num_buffers; ++i) {
gint j; gint j;
gsize buffer_size;
outbuffer = GST_BUFFER (buffers->data); outbuffer = GST_BUFFER (buffers->data);
fail_if (outbuffer == NULL); fail_if (outbuffer == NULL);
buffer_size = gst_buffer_get_size (outbuffer);
buffers = g_list_remove (buffers, outbuffer); buffers = g_list_remove (buffers, outbuffer);
if (!vorbis_header_found && GST_BUFFER_SIZE (outbuffer) >= sizeof (data)) { if (!vorbis_header_found && buffer_size >= sizeof (data)) {
for (j = 0; j <= GST_BUFFER_SIZE (outbuffer) - sizeof (data); j++) { for (j = 0; j <= buffer_size - sizeof (data); j++) {
if (memcmp (GST_BUFFER_DATA (outbuffer) + j, data, sizeof (data)) == 0) { if (gst_buffer_memcmp (outbuffer, j, data, sizeof (data)) == 0) {
vorbis_header_found = TRUE; vorbis_header_found = TRUE;
break; break;
} }
@ -307,6 +313,7 @@ GST_START_TEST (test_block_group)
{ {
GstElement *matroskamux; GstElement *matroskamux;
GstBuffer *inbuffer, *outbuffer; GstBuffer *inbuffer, *outbuffer;
guint8 *indata;
GstCaps *caps; GstCaps *caps;
int num_buffers; int num_buffers;
int i; int i;
@ -317,16 +324,14 @@ GST_START_TEST (test_block_group)
guint8 data1[] = { 0x42 }; guint8 data1[] = { 0x42 };
matroskamux = setup_matroskamux (&srcac3template); matroskamux = setup_matroskamux (&srcac3template);
fail_unless (gst_element_set_state (matroskamux,
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, caps = gst_caps_from_string (AC3_CAPS_STRING);
"could not set to playing"); fail_unless (gst_pad_set_caps (mysrcpad, caps));
gst_caps_unref (caps);
/* Generate the header */ /* Generate the header */
inbuffer = gst_buffer_new_and_alloc (1); inbuffer = gst_buffer_new_allocate (NULL, 1, 0);
GST_BUFFER_TIMESTAMP (inbuffer) = 0; GST_BUFFER_TIMESTAMP (inbuffer) = 0;
caps = gst_caps_from_string (AC3_CAPS_STRING);
gst_buffer_set_caps (inbuffer, caps);
gst_caps_unref (caps);
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
@ -346,12 +351,10 @@ GST_START_TEST (test_block_group)
buffers = NULL; buffers = NULL;
/* Now push a buffer */ /* Now push a buffer */
inbuffer = gst_buffer_new_and_alloc (1); indata = g_malloc (1);
GST_BUFFER_DATA (inbuffer)[0] = 0x42; inbuffer = gst_buffer_new_wrapped (indata, 1);
indata[0] = 0x42;
GST_BUFFER_TIMESTAMP (inbuffer) = 1000000; 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); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
@ -396,11 +399,8 @@ GST_START_TEST (test_reset)
int i; int i;
matroskamux = setup_matroskamux (&srcac3template); 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); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
num_buffers = g_list_length (buffers); num_buffers = g_list_length (buffers);
@ -414,7 +414,7 @@ GST_START_TEST (test_reset)
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
"could not set to playing"); "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); ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
num_buffers = g_list_length (buffers); num_buffers = g_list_length (buffers);