mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
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:
parent
eeaa9e0bbc
commit
17240ac9ec
14 changed files with 850 additions and 815 deletions
|
@ -314,7 +314,7 @@ dnl *** plug-ins to include ***
|
|||
dnl Non ported plugins (non-dependant, then dependant)
|
||||
dnl Make sure you have a space before and after all plugins
|
||||
GST_PLUGINS_NONPORTED="deinterlace flx goom2k1 \
|
||||
imagefreeze interleave matroska monoscope smpte \
|
||||
imagefreeze interleave monoscope smpte \
|
||||
videobox videomixer \
|
||||
cairo cairo_gobject dv1394 gdk_pixbuf libdv libpng \
|
||||
oss oss4 shout2 \
|
||||
|
|
|
@ -164,6 +164,7 @@ gst_ebml_read_init (GstEbmlRead * ebml, GstElement * el, GstBuffer * buf,
|
|||
guint64 offset)
|
||||
{
|
||||
GstEbmlMaster m;
|
||||
gsize buf_size;
|
||||
|
||||
g_return_if_fail (el);
|
||||
g_return_if_fail (buf);
|
||||
|
@ -171,9 +172,10 @@ gst_ebml_read_init (GstEbmlRead * ebml, GstElement * el, GstBuffer * buf,
|
|||
ebml->el = el;
|
||||
ebml->offset = offset;
|
||||
ebml->buf = buf;
|
||||
ebml->buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ);
|
||||
ebml->readers = g_array_sized_new (FALSE, FALSE, sizeof (GstEbmlMaster), 10);
|
||||
m.offset = ebml->offset;
|
||||
gst_byte_reader_init (&m.br, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
gst_byte_reader_init (&m.br, ebml->buf_data, buf_size);
|
||||
g_array_append_val (ebml->readers, m);
|
||||
}
|
||||
|
||||
|
@ -183,8 +185,10 @@ gst_ebml_read_clear (GstEbmlRead * ebml)
|
|||
if (ebml->readers)
|
||||
g_array_free (ebml->readers, TRUE);
|
||||
ebml->readers = NULL;
|
||||
if (ebml->buf)
|
||||
if (ebml->buf) {
|
||||
gst_buffer_unmap (ebml->buf, ebml->buf_data, -1);
|
||||
gst_buffer_unref (ebml->buf);
|
||||
}
|
||||
ebml->buf = NULL;
|
||||
ebml->el = NULL;
|
||||
}
|
||||
|
@ -334,7 +338,8 @@ gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf)
|
|||
|
||||
offset = gst_ebml_read_get_pos (ebml) - ebml->offset;
|
||||
if (G_LIKELY (gst_byte_reader_skip (gst_ebml_read_br (ebml), length))) {
|
||||
*buf = gst_buffer_create_sub (ebml->buf, offset, length);
|
||||
*buf = gst_buffer_copy_region (ebml->buf, GST_BUFFER_COPY_ALL,
|
||||
offset, length);
|
||||
} else {
|
||||
*buf = NULL;
|
||||
return GST_FLOW_PARSE;
|
||||
|
|
|
@ -54,6 +54,7 @@ typedef struct _GstEbmlRead {
|
|||
GstElement *el;
|
||||
|
||||
GstBuffer *buf;
|
||||
gpointer buf_data;
|
||||
guint64 offset;
|
||||
|
||||
GArray *readers;
|
||||
|
|
|
@ -33,18 +33,14 @@
|
|||
GST_DEBUG_CATEGORY_STATIC (gst_ebml_write_debug);
|
||||
#define GST_CAT_DEFAULT gst_ebml_write_debug
|
||||
|
||||
#define _do_init(thing) \
|
||||
#define _do_init \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_ebml_write_debug, "ebmlwrite", 0, "Write EBML structured data")
|
||||
GST_BOILERPLATE_FULL (GstEbmlWrite, gst_ebml_write, GstObject, GST_TYPE_OBJECT,
|
||||
#define parent_class gst_ebml_write_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstEbmlWrite, gst_ebml_write, GST_TYPE_OBJECT,
|
||||
_do_init);
|
||||
|
||||
static void gst_ebml_write_finalize (GObject * object);
|
||||
|
||||
static void
|
||||
gst_ebml_write_base_init (gpointer g_class)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ebml_write_class_init (GstEbmlWriteClass * klass)
|
||||
{
|
||||
|
@ -54,11 +50,11 @@ gst_ebml_write_class_init (GstEbmlWriteClass * klass)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_ebml_write_init (GstEbmlWrite * ebml, GstEbmlWriteClass * klass)
|
||||
gst_ebml_write_init (GstEbmlWrite * ebml)
|
||||
{
|
||||
ebml->srcpad = NULL;
|
||||
ebml->pos = 0;
|
||||
ebml->last_pos = G_MAXUINT64; /* force newsegment event */
|
||||
ebml->last_pos = G_MAXUINT64; /* force segment event */
|
||||
|
||||
ebml->cache = NULL;
|
||||
ebml->streamheader = NULL;
|
||||
|
@ -89,7 +85,7 @@ gst_ebml_write_finalize (GObject * object)
|
|||
ebml->caps = NULL;
|
||||
}
|
||||
|
||||
GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
||||
|
@ -126,7 +122,7 @@ void
|
|||
gst_ebml_write_reset (GstEbmlWrite * ebml)
|
||||
{
|
||||
ebml->pos = 0;
|
||||
ebml->last_pos = G_MAXUINT64; /* force newsegment event */
|
||||
ebml->last_pos = G_MAXUINT64; /* force segment event */
|
||||
|
||||
if (ebml->cache) {
|
||||
gst_byte_writer_free (ebml->cache);
|
||||
|
@ -182,7 +178,7 @@ gst_ebml_stop_streamheader (GstEbmlWrite * ebml)
|
|||
|
||||
buffer = gst_byte_writer_free_and_get_buffer (ebml->streamheader);
|
||||
ebml->streamheader = NULL;
|
||||
GST_DEBUG ("Streamheader was size %d", GST_BUFFER_SIZE (buffer));
|
||||
GST_DEBUG ("Streamheader was size %d", gst_buffer_get_size (buffer));
|
||||
|
||||
ebml->writing_streamheader = FALSE;
|
||||
return buffer;
|
||||
|
@ -211,14 +207,19 @@ gst_ebml_write_set_cache (GstEbmlWrite * ebml, guint size)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_ebml_writer_send_new_segment_event (GstEbmlWrite * ebml, guint64 new_pos)
|
||||
gst_ebml_writer_send_segment_event (GstEbmlWrite * ebml, guint64 new_pos)
|
||||
{
|
||||
GstSegment segment;
|
||||
gboolean res;
|
||||
|
||||
GST_INFO ("seeking to %" G_GUINT64_FORMAT, new_pos);
|
||||
|
||||
res = gst_pad_push_event (ebml->srcpad,
|
||||
gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, new_pos, -1, 0));
|
||||
gst_segment_init (&segment, GST_FORMAT_BYTES);
|
||||
segment.start = new_pos;
|
||||
segment.stop = -1;
|
||||
segment.position = 0;
|
||||
|
||||
res = gst_pad_push_event (ebml->srcpad, gst_event_new_segment (&segment));
|
||||
|
||||
if (!res)
|
||||
GST_WARNING ("seek to %" G_GUINT64_FORMAT "failed", new_pos);
|
||||
|
@ -244,14 +245,13 @@ gst_ebml_write_flush_cache (GstEbmlWrite * ebml, gboolean is_keyframe,
|
|||
|
||||
buffer = gst_byte_writer_free_and_get_buffer (ebml->cache);
|
||||
ebml->cache = NULL;
|
||||
GST_DEBUG ("Flushing cache of size %d", GST_BUFFER_SIZE (buffer));
|
||||
gst_buffer_set_caps (buffer, ebml->caps);
|
||||
GST_DEBUG ("Flushing cache of size %d", gst_buffer_get_size (buffer));
|
||||
GST_BUFFER_TIMESTAMP (buffer) = timestamp;
|
||||
GST_BUFFER_OFFSET (buffer) = ebml->pos - GST_BUFFER_SIZE (buffer);
|
||||
GST_BUFFER_OFFSET (buffer) = ebml->pos - gst_buffer_get_size (buffer);
|
||||
GST_BUFFER_OFFSET_END (buffer) = ebml->pos;
|
||||
if (ebml->last_write_result == GST_FLOW_OK) {
|
||||
if (GST_BUFFER_OFFSET (buffer) != ebml->last_pos) {
|
||||
gst_ebml_writer_send_new_segment_event (ebml, GST_BUFFER_OFFSET (buffer));
|
||||
gst_ebml_writer_send_segment_event (ebml, GST_BUFFER_OFFSET (buffer));
|
||||
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
|
||||
}
|
||||
if (ebml->writing_streamheader) {
|
||||
|
@ -290,7 +290,7 @@ gst_ebml_write_element_new (GstEbmlWrite * ebml, guint8 ** data_out, guint size)
|
|||
buf = gst_buffer_new_and_alloc (size);
|
||||
GST_BUFFER_TIMESTAMP (buf) = ebml->timestamp;
|
||||
|
||||
*data_out = GST_BUFFER_DATA (buf);
|
||||
*data_out = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
@ -408,31 +408,33 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf,
|
|||
{
|
||||
guint data_size;
|
||||
|
||||
if (!buf_data)
|
||||
buf_data = GST_BUFFER_DATA (buf);
|
||||
|
||||
if (buf_data_end) {
|
||||
if (buf_data_end)
|
||||
data_size = buf_data_end - buf_data;
|
||||
GST_BUFFER_SIZE (buf) = data_size;
|
||||
} else {
|
||||
data_size = GST_BUFFER_SIZE (buf);
|
||||
}
|
||||
else
|
||||
data_size = gst_buffer_get_size (buf);
|
||||
|
||||
ebml->pos += data_size;
|
||||
|
||||
/* if there's no cache, then don't push it! */
|
||||
if (ebml->writing_streamheader) {
|
||||
if (!buf_data)
|
||||
buf_data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
|
||||
gst_byte_writer_put_data (ebml->streamheader, buf_data, data_size);
|
||||
}
|
||||
if (ebml->cache) {
|
||||
if (!buf_data)
|
||||
buf_data = gst_buffer_map (buf, NULL, NULL, GST_MAP_WRITE);
|
||||
gst_byte_writer_put_data (ebml->cache, buf_data, data_size);
|
||||
gst_buffer_unmap (buf, buf_data, -1);
|
||||
gst_buffer_unref (buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf_data)
|
||||
gst_buffer_unmap (buf, buf_data, -1);
|
||||
|
||||
if (ebml->last_write_result == GST_FLOW_OK) {
|
||||
buf = gst_buffer_make_metadata_writable (buf);
|
||||
gst_buffer_set_caps (buf, ebml->caps);
|
||||
buf = gst_buffer_make_writable (buf);
|
||||
GST_BUFFER_OFFSET (buf) = ebml->pos - data_size;
|
||||
GST_BUFFER_OFFSET_END (buf) = ebml->pos;
|
||||
if (ebml->writing_streamheader) {
|
||||
|
@ -441,7 +443,7 @@ gst_ebml_write_element_push (GstEbmlWrite * ebml, GstBuffer * buf,
|
|||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
|
||||
if (GST_BUFFER_OFFSET (buf) != ebml->last_pos) {
|
||||
gst_ebml_writer_send_new_segment_event (ebml, GST_BUFFER_OFFSET (buf));
|
||||
gst_ebml_writer_send_segment_event (ebml, GST_BUFFER_OFFSET (buf));
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
||||
}
|
||||
ebml->last_pos = ebml->pos;
|
||||
|
@ -730,12 +732,12 @@ gst_ebml_write_master_finish_full (GstEbmlWrite * ebml, guint64 startpos,
|
|||
guint64 extra_size)
|
||||
{
|
||||
guint64 pos = ebml->pos;
|
||||
GstBuffer *buf;
|
||||
guint8 *data = g_malloc (8);
|
||||
GstBuffer *buf = gst_buffer_new_wrapped (data, 8);
|
||||
|
||||
gst_ebml_write_seek (ebml, startpos);
|
||||
|
||||
buf = gst_buffer_new_and_alloc (8);
|
||||
GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf),
|
||||
GST_WRITE_UINT64_BE (data,
|
||||
(G_GINT64_CONSTANT (1) << 56) | (pos - startpos - 8 + extra_size));
|
||||
|
||||
gst_ebml_write_element_push (ebml, buf, NULL, NULL);
|
||||
|
@ -835,11 +837,12 @@ void
|
|||
gst_ebml_replace_uint (GstEbmlWrite * ebml, guint64 pos, guint64 num)
|
||||
{
|
||||
guint64 oldpos = ebml->pos;
|
||||
GstBuffer *buf = gst_buffer_new_and_alloc (8);
|
||||
guint8 *data_start, *data_end;
|
||||
GstBuffer *buf;
|
||||
|
||||
data_start = GST_BUFFER_DATA (buf);
|
||||
data_start = g_malloc (8);
|
||||
data_end = data_start;
|
||||
buf = gst_buffer_new_wrapped (data_start, 8);
|
||||
|
||||
gst_ebml_write_seek (ebml, pos);
|
||||
gst_ebml_write_set_uint (&data_end, num, 8);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -87,7 +87,7 @@ typedef struct _GstMatroskaDemux {
|
|||
gboolean building_index;
|
||||
guint64 index_offset;
|
||||
GstEvent *seek_event;
|
||||
gboolean need_newsegment;
|
||||
gboolean need_segment;
|
||||
|
||||
/* reverse playback */
|
||||
GArray *seek_index;
|
||||
|
|
|
@ -486,10 +486,10 @@ struct _GstMatroskaTrackContext {
|
|||
|
||||
/* some often-used info */
|
||||
gchar *codec_id, *codec_name, *name, *language;
|
||||
guint8 *codec_priv;
|
||||
guint codec_priv_size;
|
||||
guint8 *codec_state;
|
||||
guint codec_state_size;
|
||||
gpointer codec_priv;
|
||||
gsize codec_priv_size;
|
||||
gpointer codec_state;
|
||||
gsize codec_state_size;
|
||||
GstMatroskaTrackType type;
|
||||
guint uid, num;
|
||||
GstMatroskaTrackFlags flags;
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gst/audio/audio.h>
|
||||
#include <gst/riff/riff-media.h>
|
||||
#include <gst/tag/tag.h>
|
||||
|
||||
|
@ -126,8 +127,8 @@ static GstStaticPadTemplate videosink_templ =
|
|||
COMMON_VIDEO_CAPS "; "
|
||||
"video/x-vp8, "
|
||||
COMMON_VIDEO_CAPS "; "
|
||||
"video/x-raw-yuv, "
|
||||
"format = (fourcc) { YUY2, I420, YV12, UYVY, AYUV }, "
|
||||
"video/x-raw, "
|
||||
"format = (string) { YUY2, I420, YV12, UYVY, AYUV }, "
|
||||
COMMON_VIDEO_CAPS "; "
|
||||
"video/x-wmv, " "wmvversion = (int) [ 1, 3 ], " COMMON_VIDEO_CAPS)
|
||||
);
|
||||
|
@ -163,32 +164,8 @@ static GstStaticPadTemplate audiosink_templ =
|
|||
COMMON_AUDIO_CAPS "; "
|
||||
"audio/x-speex, "
|
||||
COMMON_AUDIO_CAPS "; "
|
||||
"audio/x-raw-int, "
|
||||
"width = (int) 8, "
|
||||
"depth = (int) 8, "
|
||||
"signed = (boolean) false, "
|
||||
COMMON_AUDIO_CAPS ";"
|
||||
"audio/x-raw-int, "
|
||||
"width = (int) 16, "
|
||||
"depth = (int) 16, "
|
||||
"endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, "
|
||||
"signed = (boolean) true, "
|
||||
COMMON_AUDIO_CAPS ";"
|
||||
"audio/x-raw-int, "
|
||||
"width = (int) 24, "
|
||||
"depth = (int) 24, "
|
||||
"endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, "
|
||||
"signed = (boolean) true, "
|
||||
COMMON_AUDIO_CAPS ";"
|
||||
"audio/x-raw-int, "
|
||||
"width = (int) 32, "
|
||||
"depth = (int) 32, "
|
||||
"endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, "
|
||||
"signed = (boolean) true, "
|
||||
COMMON_AUDIO_CAPS ";"
|
||||
"audio/x-raw-float, "
|
||||
"width = (int) [ 32, 64 ], "
|
||||
"endianness = (int) LITTLE_ENDIAN, "
|
||||
"audio/x-raw, "
|
||||
"format = (string) { U8, S16BE, S16LE, S24BE, S24LE, S32BE, S32LE, F32LE, F64LE }, "
|
||||
COMMON_AUDIO_CAPS ";"
|
||||
"audio/x-tta, "
|
||||
"width = (int) { 8, 16, 24 }, "
|
||||
|
@ -213,10 +190,9 @@ GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
|
|||
static GArray *used_uids;
|
||||
G_LOCK_DEFINE_STATIC (used_uids);
|
||||
|
||||
static void gst_matroska_mux_add_interfaces (GType type);
|
||||
|
||||
GST_BOILERPLATE_FULL (GstMatroskaMux, gst_matroska_mux, GstElement,
|
||||
GST_TYPE_ELEMENT, gst_matroska_mux_add_interfaces);
|
||||
#define parent_class gst_matroska_mux_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstMatroskaMux, gst_matroska_mux, GST_TYPE_ELEMENT,
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
|
||||
|
||||
/* Matroska muxer destructor */
|
||||
static void gst_matroska_mux_finalize (GObject * object);
|
||||
|
@ -227,9 +203,9 @@ gst_matroska_mux_collected (GstCollectPads * pads, gpointer user_data);
|
|||
|
||||
/* pad functions */
|
||||
static gboolean gst_matroska_mux_handle_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
GstObject * parent, GstEvent * event);
|
||||
static GstPad *gst_matroska_mux_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * name);
|
||||
GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
|
||||
static void gst_matroska_mux_release_pad (GstElement * element, GstPad * pad);
|
||||
|
||||
/* gst internal change state handler */
|
||||
|
@ -262,19 +238,6 @@ static void
|
|||
gst_matroska_mux_write_simple_tag (const GstTagList * list, const gchar * tag,
|
||||
gpointer data);
|
||||
|
||||
static void
|
||||
gst_matroska_mux_add_interfaces (GType type)
|
||||
{
|
||||
static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
|
||||
|
||||
g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, &tag_setter_info);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_matroska_mux_base_init (gpointer g_class)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
|
||||
{
|
||||
|
@ -343,12 +306,12 @@ gst_matroska_mux_class_init (GstMatroskaMuxClass * klass)
|
|||
* Matroska muxer constructor.
|
||||
*/
|
||||
static void
|
||||
gst_matroska_mux_init (GstMatroskaMux * mux, GstMatroskaMuxClass * g_class)
|
||||
gst_matroska_mux_init (GstMatroskaMux * mux)
|
||||
{
|
||||
GstPadTemplate *templ;
|
||||
|
||||
templ =
|
||||
gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src");
|
||||
gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (mux), "src");
|
||||
mux->srcpad = gst_pad_new_from_template (templ, "src");
|
||||
|
||||
gst_pad_set_event_function (mux->srcpad, gst_matroska_mux_handle_src_event);
|
||||
|
@ -586,7 +549,8 @@ gst_matroska_mux_reset (GstElement * element)
|
|||
* Returns: #TRUE on success.
|
||||
*/
|
||||
static gboolean
|
||||
gst_matroska_mux_handle_src_event (GstPad * pad, GstEvent * event)
|
||||
gst_matroska_mux_handle_src_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event)
|
||||
{
|
||||
GstEventType type;
|
||||
|
||||
|
@ -600,7 +564,7 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstEvent * event)
|
|||
break;
|
||||
}
|
||||
|
||||
return gst_pad_event_default (pad, event);
|
||||
return gst_pad_event_default (pad, parent, event);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -613,17 +577,27 @@ gst_matroska_mux_handle_src_event (GstPad * pad, GstEvent * event)
|
|||
* Returns: #TRUE on success.
|
||||
*/
|
||||
static gboolean
|
||||
gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||
gst_matroska_mux_handle_sink_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event)
|
||||
{
|
||||
GstMatroskaTrackContext *context;
|
||||
GstMatroskaPad *collect_pad;
|
||||
GstMatroskaMux *mux;
|
||||
GstMatroskaMux *mux = GST_MATROSKA_MUX (parent);
|
||||
GstTagList *list;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
mux = GST_MATROSKA_MUX (gst_pad_get_parent (pad));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_CAPS:{
|
||||
GstCaps *caps;
|
||||
|
||||
collect_pad = (GstMatroskaPad *) gst_pad_get_element_private (pad);
|
||||
gst_event_parse_caps (event, &caps);
|
||||
|
||||
ret = collect_pad->capsfunc (pad, caps);
|
||||
gst_event_unref (event);
|
||||
event = NULL;
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_TAG:{
|
||||
gchar *lang = NULL;
|
||||
|
||||
|
@ -658,12 +632,11 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
event = NULL;
|
||||
break;
|
||||
}
|
||||
case GST_EVENT_NEWSEGMENT:{
|
||||
GstFormat format;
|
||||
case GST_EVENT_SEGMENT:{
|
||||
const GstSegment *segment;
|
||||
|
||||
gst_event_parse_new_segment (event, NULL, NULL, &format, NULL, NULL,
|
||||
NULL);
|
||||
if (format != GST_FORMAT_TIME) {
|
||||
gst_event_parse_segment (event, &segment);
|
||||
if (segment->format != GST_FORMAT_TIME) {
|
||||
ret = FALSE;
|
||||
gst_event_unref (event);
|
||||
event = NULL;
|
||||
|
@ -687,9 +660,7 @@ gst_matroska_mux_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
|
||||
/* now GstCollectPads can take care of the rest, e.g. EOS */
|
||||
if (event)
|
||||
ret = mux->collect_event (pad, event);
|
||||
|
||||
gst_object_unref (mux);
|
||||
ret = mux->collect_event (pad, parent, event);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -714,7 +685,7 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GstStructure *structure;
|
||||
const gchar *mimetype;
|
||||
const GValue *value = NULL;
|
||||
const GstBuffer *codec_buf = NULL;
|
||||
GstBuffer *codec_buf = NULL;
|
||||
gint width, height, pixel_width, pixel_height;
|
||||
gint fps_d, fps_n;
|
||||
gboolean interlaced = FALSE;
|
||||
|
@ -790,12 +761,17 @@ skip_details:
|
|||
/* extract codec_data, may turn out needed */
|
||||
value = gst_structure_get_value (structure, "codec_data");
|
||||
if (value)
|
||||
codec_buf = gst_value_get_buffer (value);
|
||||
codec_buf = (GstBuffer *) gst_value_get_buffer (value);
|
||||
|
||||
/* find type */
|
||||
if (!strcmp (mimetype, "video/x-raw-yuv")) {
|
||||
if (!strcmp (mimetype, "video/x-raw")) {
|
||||
const gchar *fstr;
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_UNCOMPRESSED);
|
||||
gst_structure_get_fourcc (structure, "format", &videocontext->fourcc);
|
||||
fstr = gst_structure_get_string (structure, "format");
|
||||
if (fstr && strlen (fstr) == 4)
|
||||
videocontext->fourcc = GST_STR_FOURCC (fstr);
|
||||
} else if (!strcmp (mimetype, "image/jpeg")) {
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MJPEG);
|
||||
} else if (!strcmp (mimetype, "video/x-xvid") /* MS/VfW compatibility cases */
|
||||
||!strcmp (mimetype, "video/x-huffyuv")
|
||||
|| !strcmp (mimetype, "video/x-divx")
|
||||
|
@ -848,9 +824,11 @@ skip_details:
|
|||
}
|
||||
} else if (!strcmp (mimetype, "video/x-wmv")) {
|
||||
gint wmvversion;
|
||||
guint32 format;
|
||||
if (gst_structure_get_fourcc (structure, "format", &format)) {
|
||||
fourcc = format;
|
||||
const gchar *fstr;
|
||||
|
||||
fstr = gst_structure_get_string (structure, "format");
|
||||
if (fstr && strlen (fstr) == 4) {
|
||||
fourcc = GST_STR_FOURCC (fstr);
|
||||
} else if (gst_structure_get_int (structure, "wmvversion", &wmvversion)) {
|
||||
if (wmvversion == 2) {
|
||||
fourcc = GST_MAKE_FOURCC ('W', 'M', 'V', '2');
|
||||
|
@ -879,11 +857,11 @@ skip_details:
|
|||
|
||||
/* process codec private/initialization data, if any */
|
||||
if (codec_buf) {
|
||||
size += GST_BUFFER_SIZE (codec_buf);
|
||||
size += gst_buffer_get_size (codec_buf);
|
||||
bih = g_realloc (bih, size);
|
||||
GST_WRITE_UINT32_LE (&bih->size, size);
|
||||
memcpy ((guint8 *) bih + sizeof (gst_riff_strf_vids),
|
||||
GST_BUFFER_DATA (codec_buf), GST_BUFFER_SIZE (codec_buf));
|
||||
gst_buffer_extract (codec_buf, 0,
|
||||
(guint8 *) bih + sizeof (gst_riff_strf_vids), -1);
|
||||
}
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_VFW_FOURCC);
|
||||
|
@ -900,10 +878,9 @@ skip_details:
|
|||
|
||||
/* Create avcC header */
|
||||
if (codec_buf != NULL) {
|
||||
context->codec_priv_size = GST_BUFFER_SIZE (codec_buf);
|
||||
context->codec_priv_size = gst_buffer_get_size (codec_buf);
|
||||
context->codec_priv = g_malloc0 (context->codec_priv_size);
|
||||
memcpy (context->codec_priv, GST_BUFFER_DATA (codec_buf),
|
||||
context->codec_priv_size);
|
||||
gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
|
||||
}
|
||||
} else if (!strcmp (mimetype, "video/x-theora")) {
|
||||
const GValue *streamheader;
|
||||
|
@ -946,10 +923,9 @@ skip_details:
|
|||
|
||||
/* global headers may be in codec data */
|
||||
if (codec_buf != NULL) {
|
||||
context->codec_priv_size = GST_BUFFER_SIZE (codec_buf);
|
||||
context->codec_priv_size = gst_buffer_get_size (codec_buf);
|
||||
context->codec_priv = g_malloc0 (context->codec_priv_size);
|
||||
memcpy (context->codec_priv, GST_BUFFER_DATA (codec_buf),
|
||||
context->codec_priv_size);
|
||||
gst_buffer_extract (codec_buf, 0, context->codec_priv, -1);
|
||||
}
|
||||
} else if (!strcmp (mimetype, "video/x-msmpeg")) {
|
||||
msmpeg43:
|
||||
|
@ -984,10 +960,10 @@ skip_details:
|
|||
|
||||
GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
|
||||
|
||||
priv_data_size = GST_BUFFER_SIZE (codec_data_buf);
|
||||
priv_data_size = gst_buffer_get_size (codec_data_buf);
|
||||
priv_data = g_malloc0 (priv_data_size);
|
||||
|
||||
memcpy (priv_data, GST_BUFFER_DATA (codec_data_buf), priv_data_size);
|
||||
gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
|
||||
|
||||
context->codec_priv = priv_data;
|
||||
context->codec_priv_size = priv_data_size;
|
||||
|
@ -1045,12 +1021,12 @@ xiphN_streamheader_to_codecdata (const GValue * streamheader,
|
|||
priv_data_size = 1;
|
||||
if (bufarr->len > 0) {
|
||||
for (i = 0; i < bufarr->len - 1; i++) {
|
||||
priv_data_size += GST_BUFFER_SIZE (buf[i]) / 0xff + 1;
|
||||
priv_data_size += gst_buffer_get_size (buf[i]) / 0xff + 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < bufarr->len; ++i) {
|
||||
priv_data_size += GST_BUFFER_SIZE (buf[i]);
|
||||
priv_data_size += gst_buffer_get_size (buf[i]);
|
||||
}
|
||||
|
||||
priv_data = g_malloc0 (priv_data_size);
|
||||
|
@ -1060,17 +1036,16 @@ xiphN_streamheader_to_codecdata (const GValue * streamheader,
|
|||
|
||||
if (bufarr->len > 0) {
|
||||
for (bufi = 0; bufi < bufarr->len - 1; bufi++) {
|
||||
for (i = 0; i < GST_BUFFER_SIZE (buf[bufi]) / 0xff; ++i) {
|
||||
for (i = 0; i < gst_buffer_get_size (buf[bufi]) / 0xff; ++i) {
|
||||
priv_data[offset++] = 0xff;
|
||||
}
|
||||
priv_data[offset++] = GST_BUFFER_SIZE (buf[bufi]) % 0xff;
|
||||
priv_data[offset++] = gst_buffer_get_size (buf[bufi]) % 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < bufarr->len; ++i) {
|
||||
memcpy (priv_data + offset, GST_BUFFER_DATA (buf[i]),
|
||||
GST_BUFFER_SIZE (buf[i]));
|
||||
offset += GST_BUFFER_SIZE (buf[i]);
|
||||
gst_buffer_extract (buf[i], 0, priv_data + offset, -1);
|
||||
offset += gst_buffer_get_size (buf[i]);
|
||||
}
|
||||
|
||||
context->codec_priv = priv_data;
|
||||
|
@ -1116,17 +1091,19 @@ vorbis_streamheader_to_codecdata (const GValue * streamheader,
|
|||
if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
|
||||
return FALSE;
|
||||
|
||||
if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 4) {
|
||||
if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 4) {
|
||||
GST_WARNING ("First vorbis header too small, ignoring");
|
||||
} else {
|
||||
if (memcmp (GST_BUFFER_DATA (buf0) + 1, "vorbis", 6) == 0) {
|
||||
if (gst_buffer_memcmp (buf0, 1, "vorbis", 6) == 0) {
|
||||
GstMatroskaTrackAudioContext *audiocontext;
|
||||
guint8 *hdr;
|
||||
guint8 *data, *hdr;
|
||||
|
||||
hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 4;
|
||||
data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ);
|
||||
hdr = data + 1 + 6 + 4;
|
||||
audiocontext = (GstMatroskaTrackAudioContext *) context;
|
||||
audiocontext->channels = GST_READ_UINT8 (hdr);
|
||||
audiocontext->samplerate = GST_READ_UINT32_LE (hdr + 1);
|
||||
gst_buffer_unmap (buf0, data, -1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1145,16 +1122,17 @@ theora_streamheader_to_codecdata (const GValue * streamheader,
|
|||
if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, 3))
|
||||
return FALSE;
|
||||
|
||||
if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 1 + 6 + 26) {
|
||||
if (buf0 == NULL || gst_buffer_get_size (buf0) < 1 + 6 + 26) {
|
||||
GST_WARNING ("First theora header too small, ignoring");
|
||||
} else if (memcmp (GST_BUFFER_DATA (buf0), "\200theora\003\002", 9) != 0) {
|
||||
} else if (gst_buffer_memcmp (buf0, 0, "\200theora\003\002", 9) != 0) {
|
||||
GST_WARNING ("First header not a theora identification header, ignoring");
|
||||
} else {
|
||||
GstMatroskaTrackVideoContext *videocontext;
|
||||
guint fps_num, fps_denom, par_num, par_denom;
|
||||
guint8 *hdr;
|
||||
guint8 *data, *hdr;
|
||||
|
||||
hdr = GST_BUFFER_DATA (buf0) + 1 + 6 + 3 + 2 + 2;
|
||||
data = gst_buffer_map (buf0, NULL, NULL, GST_MAP_READ);
|
||||
hdr = data + 1 + 6 + 3 + 2 + 2;
|
||||
|
||||
videocontext = (GstMatroskaTrackVideoContext *) context;
|
||||
videocontext->pixel_width = GST_READ_UINT32_BE (hdr) >> 8;
|
||||
|
@ -1185,6 +1163,8 @@ theora_streamheader_to_codecdata (const GValue * streamheader,
|
|||
videocontext->display_height = 0;
|
||||
}
|
||||
hdr += 3 + 3;
|
||||
|
||||
gst_buffer_unmap (buf0, data, -1);
|
||||
}
|
||||
|
||||
if (buf0)
|
||||
|
@ -1202,9 +1182,9 @@ kate_streamheader_to_codecdata (const GValue * streamheader,
|
|||
if (!xiphN_streamheader_to_codecdata (streamheader, context, &buf0, -1))
|
||||
return FALSE;
|
||||
|
||||
if (buf0 == NULL || GST_BUFFER_SIZE (buf0) < 64) { /* Kate ID header is 64 bytes */
|
||||
if (buf0 == NULL || gst_buffer_get_size (buf0) < 64) { /* Kate ID header is 64 bytes */
|
||||
GST_WARNING ("First kate header too small, ignoring");
|
||||
} else if (memcmp (GST_BUFFER_DATA (buf0), "\200kate\0\0\0", 8) != 0) {
|
||||
} else if (gst_buffer_memcmp (buf0, 0, "\200kate\0\0\0", 8) != 0) {
|
||||
GST_WARNING ("First header not a kate identification header, ignoring");
|
||||
}
|
||||
|
||||
|
@ -1245,19 +1225,19 @@ flac_streamheader_to_codecdata (const GValue * streamheader,
|
|||
buffer = g_value_peek_pointer (bufval);
|
||||
|
||||
/* Need at least OggFLAC mapping header, fLaC marker and STREAMINFO block */
|
||||
if (GST_BUFFER_SIZE (buffer) < 9 + 4 + 4 + 34
|
||||
|| memcmp (GST_BUFFER_DATA (buffer) + 1, "FLAC", 4) != 0
|
||||
|| memcmp (GST_BUFFER_DATA (buffer) + 9, "fLaC", 4) != 0) {
|
||||
if (gst_buffer_get_size (buffer) < 9 + 4 + 4 + 34
|
||||
|| gst_buffer_memcmp (buffer, 1, "FLAC", 4) != 0
|
||||
|| gst_buffer_memcmp (buffer, 9, "fLaC", 4) != 0) {
|
||||
GST_WARNING ("Invalid streamheader for FLAC");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
context->codec_priv = g_malloc (GST_BUFFER_SIZE (buffer) - 9);
|
||||
context->codec_priv_size = GST_BUFFER_SIZE (buffer) - 9;
|
||||
memcpy (context->codec_priv, GST_BUFFER_DATA (buffer) + 9,
|
||||
GST_BUFFER_SIZE (buffer) - 9);
|
||||
context->codec_priv_size = gst_buffer_get_size (buffer) - 9;
|
||||
context->codec_priv = g_malloc (context->codec_priv_size);
|
||||
gst_buffer_extract (buffer, 9, context->codec_priv, -1);
|
||||
|
||||
for (i = 1; i < bufarr->len; i++) {
|
||||
guint old_size;
|
||||
bufval = &g_array_index (bufarr, GValue, i);
|
||||
|
||||
if (G_VALUE_TYPE (bufval) != GST_TYPE_BUFFER) {
|
||||
|
@ -1270,13 +1250,13 @@ flac_streamheader_to_codecdata (const GValue * streamheader,
|
|||
|
||||
buffer = g_value_peek_pointer (bufval);
|
||||
|
||||
context->codec_priv =
|
||||
g_realloc (context->codec_priv,
|
||||
context->codec_priv_size + GST_BUFFER_SIZE (buffer));
|
||||
memcpy ((guint8 *) context->codec_priv + context->codec_priv_size,
|
||||
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
|
||||
context->codec_priv_size =
|
||||
context->codec_priv_size + GST_BUFFER_SIZE (buffer);
|
||||
old_size = context->codec_priv_size;
|
||||
context->codec_priv_size += gst_buffer_get_size (buffer);
|
||||
|
||||
context->codec_priv = g_realloc (context->codec_priv,
|
||||
context->codec_priv_size);
|
||||
gst_buffer_extract (buffer, 0,
|
||||
(guint8 *) context->codec_priv + old_size, -1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -1289,6 +1269,7 @@ speex_streamheader_to_codecdata (const GValue * streamheader,
|
|||
GArray *bufarr;
|
||||
GValue *bufval;
|
||||
GstBuffer *buffer;
|
||||
guint old_size;
|
||||
|
||||
if (streamheader == NULL || G_VALUE_TYPE (streamheader) != GST_TYPE_ARRAY) {
|
||||
GST_WARNING ("No or invalid streamheader field in the caps");
|
||||
|
@ -1311,16 +1292,15 @@ speex_streamheader_to_codecdata (const GValue * streamheader,
|
|||
|
||||
buffer = g_value_peek_pointer (bufval);
|
||||
|
||||
if (GST_BUFFER_SIZE (buffer) < 80
|
||||
|| memcmp (GST_BUFFER_DATA (buffer), "Speex ", 8) != 0) {
|
||||
if (gst_buffer_get_size (buffer) < 80
|
||||
|| gst_buffer_memcmp (buffer, 0, "Speex ", 8) != 0) {
|
||||
GST_WARNING ("Invalid streamheader for Speex");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
context->codec_priv = g_malloc (GST_BUFFER_SIZE (buffer));
|
||||
context->codec_priv_size = GST_BUFFER_SIZE (buffer);
|
||||
memcpy (context->codec_priv, GST_BUFFER_DATA (buffer),
|
||||
GST_BUFFER_SIZE (buffer));
|
||||
context->codec_priv_size = gst_buffer_get_size (buffer);
|
||||
context->codec_priv = g_malloc (context->codec_priv_size);
|
||||
gst_buffer_extract (buffer, 0, context->codec_priv, -1);
|
||||
|
||||
bufval = &g_array_index (bufarr, GValue, 1);
|
||||
|
||||
|
@ -1334,28 +1314,26 @@ speex_streamheader_to_codecdata (const GValue * streamheader,
|
|||
|
||||
buffer = g_value_peek_pointer (bufval);
|
||||
|
||||
context->codec_priv =
|
||||
g_realloc (context->codec_priv,
|
||||
context->codec_priv_size + GST_BUFFER_SIZE (buffer));
|
||||
memcpy ((guint8 *) context->codec_priv + context->codec_priv_size,
|
||||
GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer));
|
||||
context->codec_priv_size =
|
||||
context->codec_priv_size + GST_BUFFER_SIZE (buffer);
|
||||
old_size = context->codec_priv_size;
|
||||
context->codec_priv_size += gst_buffer_get_size (buffer);
|
||||
context->codec_priv = g_realloc (context->codec_priv,
|
||||
context->codec_priv_size);
|
||||
gst_buffer_extract (buffer, 0, (guint8 *) context->codec_priv + old_size, -1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const gchar *
|
||||
aac_codec_data_to_codec_id (const GstBuffer * buf)
|
||||
aac_codec_data_to_codec_id (GstBuffer * buf)
|
||||
{
|
||||
const gchar *result;
|
||||
gint profile;
|
||||
guint8 profile;
|
||||
|
||||
/* default to MAIN */
|
||||
profile = 1;
|
||||
|
||||
if (GST_BUFFER_SIZE (buf) >= 2) {
|
||||
profile = GST_READ_UINT8 (GST_BUFFER_DATA (buf));
|
||||
if (gst_buffer_get_size (buf) >= 2) {
|
||||
gst_buffer_extract (buf, 0, &profile, 1);
|
||||
profile >>= 3;
|
||||
}
|
||||
|
||||
|
@ -1401,7 +1379,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
gint samplerate = 0, channels = 0;
|
||||
GstStructure *structure;
|
||||
const GValue *codec_data = NULL;
|
||||
const GstBuffer *buf = NULL;
|
||||
GstBuffer *buf = NULL;
|
||||
const gchar *stream_format = NULL;
|
||||
|
||||
mux = GST_MATROSKA_MUX (GST_PAD_PARENT (pad));
|
||||
|
@ -1513,51 +1491,45 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
default:
|
||||
goto refuse_caps;
|
||||
}
|
||||
} else if (!strcmp (mimetype, "audio/x-raw-int")) {
|
||||
gint width, depth;
|
||||
gint endianness = G_LITTLE_ENDIAN;
|
||||
gboolean signedness = TRUE;
|
||||
} else if (!strcmp (mimetype, "audio/x-raw")) {
|
||||
GstAudioInfo info;
|
||||
|
||||
if (!gst_structure_get_int (structure, "width", &width) ||
|
||||
!gst_structure_get_int (structure, "depth", &depth) ||
|
||||
!gst_structure_get_boolean (structure, "signed", &signedness)) {
|
||||
GST_DEBUG_OBJECT (mux, "broken caps, width/depth/signed field missing");
|
||||
gst_audio_info_init (&info);
|
||||
if (!gst_audio_info_from_caps (&info, caps)) {
|
||||
GST_DEBUG_OBJECT (mux,
|
||||
"broken caps, rejected by gst_audio_info_from_caps");
|
||||
goto refuse_caps;
|
||||
}
|
||||
|
||||
if (depth > 8 &&
|
||||
!gst_structure_get_int (structure, "endianness", &endianness)) {
|
||||
GST_DEBUG_OBJECT (mux, "broken caps, no endianness specified");
|
||||
goto refuse_caps;
|
||||
switch (GST_AUDIO_INFO_FORMAT (&info)) {
|
||||
case GST_AUDIO_FORMAT_U8:
|
||||
case GST_AUDIO_FORMAT_S16BE:
|
||||
case GST_AUDIO_FORMAT_S16LE:
|
||||
case GST_AUDIO_FORMAT_S24BE:
|
||||
case GST_AUDIO_FORMAT_S24LE:
|
||||
case GST_AUDIO_FORMAT_S32BE:
|
||||
case GST_AUDIO_FORMAT_S32LE:
|
||||
if (GST_AUDIO_INFO_WIDTH (&info) != GST_AUDIO_INFO_DEPTH (&info)) {
|
||||
GST_DEBUG_OBJECT (mux, "width must be same as depth!");
|
||||
goto refuse_caps;
|
||||
}
|
||||
if (GST_AUDIO_INFO_IS_BIG_ENDIAN (&info))
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_BE);
|
||||
else
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_PCM_INT_LE);
|
||||
break;
|
||||
|
||||
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) {
|
||||
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);
|
||||
audiocontext->bitdepth = GST_AUDIO_INFO_WIDTH (&info);
|
||||
|
||||
} else if (!strcmp (mimetype, "audio/x-vorbis")) {
|
||||
const GValue *streamheader;
|
||||
|
@ -1650,10 +1622,10 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
|
||||
GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
|
||||
|
||||
priv_data_size = GST_BUFFER_SIZE (codec_data_buf);
|
||||
priv_data_size = gst_buffer_get_size (codec_data_buf);
|
||||
priv_data = g_malloc0 (priv_data_size);
|
||||
|
||||
memcpy (priv_data, GST_BUFFER_DATA (codec_data_buf), priv_data_size);
|
||||
gst_buffer_extract (codec_data_buf, 0, priv_data, -1);
|
||||
|
||||
context->codec_priv = priv_data;
|
||||
context->codec_priv_size = priv_data_size;
|
||||
|
@ -1717,7 +1689,7 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
|
||||
codec_priv_size = WAVEFORMATEX_SIZE;
|
||||
if (buf)
|
||||
codec_priv_size += GST_BUFFER_SIZE (buf);
|
||||
codec_priv_size += gst_buffer_get_size (buf);
|
||||
|
||||
/* serialize waveformatex structure */
|
||||
codec_priv = g_malloc0 (codec_priv_size);
|
||||
|
@ -1728,14 +1700,14 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
GST_WRITE_UINT16_LE (codec_priv + 12, block_align);
|
||||
GST_WRITE_UINT16_LE (codec_priv + 14, 0);
|
||||
if (buf)
|
||||
GST_WRITE_UINT16_LE (codec_priv + 16, GST_BUFFER_SIZE (buf));
|
||||
GST_WRITE_UINT16_LE (codec_priv + 16, gst_buffer_get_size (buf));
|
||||
else
|
||||
GST_WRITE_UINT16_LE (codec_priv + 16, 0);
|
||||
|
||||
/* process codec private/initialization data, if any */
|
||||
if (buf) {
|
||||
memcpy ((guint8 *) codec_priv + WAVEFORMATEX_SIZE,
|
||||
GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
|
||||
gst_buffer_extract (buf, 0,
|
||||
(guint8 *) codec_priv + WAVEFORMATEX_SIZE, -1);
|
||||
}
|
||||
|
||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_ACM);
|
||||
|
@ -1839,7 +1811,7 @@ gst_matroska_mux_subtitle_pad_setcaps (GstPad * pad, GstCaps * caps)
|
|||
*/
|
||||
static GstPad *
|
||||
gst_matroska_mux_request_new_pad (GstElement * element,
|
||||
GstPadTemplate * templ, const gchar * req_name)
|
||||
GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
|
||||
{
|
||||
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
|
||||
GstMatroskaMux *mux = GST_MATROSKA_MUX (element);
|
||||
|
@ -1847,7 +1819,7 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
GstPad *newpad = NULL;
|
||||
gchar *name = NULL;
|
||||
const gchar *pad_name = NULL;
|
||||
GstPadSetCapsFunction setcapsfunc = NULL;
|
||||
GstMatroskaCapsFunc capsfunc = NULL;
|
||||
GstMatroskaTrackContext *context = NULL;
|
||||
gint pad_id;
|
||||
|
||||
|
@ -1860,7 +1832,7 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
name = g_strdup_printf ("audio_%u", mux->num_a_streams++);
|
||||
pad_name = name;
|
||||
}
|
||||
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
|
||||
capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_audio_pad_setcaps);
|
||||
context = (GstMatroskaTrackContext *)
|
||||
g_new0 (GstMatroskaTrackAudioContext, 1);
|
||||
context->type = GST_MATROSKA_TRACK_TYPE_AUDIO;
|
||||
|
@ -1874,7 +1846,7 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
name = g_strdup_printf ("video_%u", mux->num_v_streams++);
|
||||
pad_name = name;
|
||||
}
|
||||
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
|
||||
capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_video_pad_setcaps);
|
||||
context = (GstMatroskaTrackContext *)
|
||||
g_new0 (GstMatroskaTrackVideoContext, 1);
|
||||
context->type = GST_MATROSKA_TRACK_TYPE_VIDEO;
|
||||
|
@ -1888,7 +1860,7 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
name = g_strdup_printf ("subtitle_%u", mux->num_t_streams++);
|
||||
pad_name = name;
|
||||
}
|
||||
setcapsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
|
||||
capsfunc = GST_DEBUG_FUNCPTR (gst_matroska_mux_subtitle_pad_setcaps);
|
||||
context = (GstMatroskaTrackContext *)
|
||||
g_new0 (GstMatroskaTrackSubtitleContext, 1);
|
||||
context->type = GST_MATROSKA_TRACK_TYPE_SUBTITLE;
|
||||
|
@ -1920,7 +1892,7 @@ gst_matroska_mux_request_new_pad (GstElement * element,
|
|||
gst_pad_set_event_function (newpad,
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_mux_handle_sink_event));
|
||||
|
||||
gst_pad_set_setcaps_function (newpad, setcapsfunc);
|
||||
collect_pad->capsfunc = capsfunc;
|
||||
gst_pad_set_active (newpad, TRUE);
|
||||
if (!gst_element_add_pad (element, newpad))
|
||||
goto pad_add_failed;
|
||||
|
@ -2109,9 +2081,9 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
|||
GTimeVal time = { 0, 0 };
|
||||
|
||||
if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
|
||||
ebml->caps = gst_caps_new_simple ("video/webm", NULL);
|
||||
ebml->caps = gst_caps_new_empty_simple ("video/webm");
|
||||
} else {
|
||||
ebml->caps = gst_caps_new_simple ("video/x-matroska", NULL);
|
||||
ebml->caps = gst_caps_new_empty_simple ("video/x-matroska");
|
||||
}
|
||||
/* we start with a EBML header */
|
||||
doctype = mux->doctype;
|
||||
|
@ -2176,7 +2148,6 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
|||
for (collected = mux->collect->data; collected;
|
||||
collected = g_slist_next (collected)) {
|
||||
GstMatroskaPad *collect_pad;
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
GstPad *thepad;
|
||||
gint64 trackduration;
|
||||
|
||||
|
@ -2185,7 +2156,7 @@ gst_matroska_mux_start (GstMatroskaMux * mux)
|
|||
|
||||
/* Query the total length of the track. */
|
||||
GST_DEBUG_OBJECT (thepad, "querying peer duration");
|
||||
if (gst_pad_query_peer_duration (thepad, &format, &trackduration)) {
|
||||
if (gst_pad_peer_query_duration (thepad, GST_FORMAT_TIME, &trackduration)) {
|
||||
GST_DEBUG_OBJECT (thepad, "duration: %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (trackduration));
|
||||
if (trackduration != GST_CLOCK_TIME_NONE && trackduration > duration) {
|
||||
|
@ -2503,7 +2474,7 @@ gst_matroska_mux_best_pad (GstMatroskaMux * mux, gboolean * popped)
|
|||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (collect_pad->buffer)),
|
||||
GST_TIME_ARGS (time));
|
||||
collect_pad->buffer =
|
||||
gst_buffer_make_metadata_writable (collect_pad->buffer);
|
||||
gst_buffer_make_writable (collect_pad->buffer);
|
||||
GST_BUFFER_TIMESTAMP (collect_pad->buffer) = time;
|
||||
}
|
||||
}
|
||||
|
@ -2539,15 +2510,16 @@ gst_matroska_mux_create_buffer_header (GstMatroskaTrackContext * track,
|
|||
gint16 relative_timestamp, int flags)
|
||||
{
|
||||
GstBuffer *hdr;
|
||||
guint8 *data = g_malloc (4);
|
||||
|
||||
hdr = gst_buffer_new_and_alloc (4);
|
||||
hdr = gst_buffer_new_wrapped (data, 4);
|
||||
/* track num - FIXME: what if num >= 0x80 (unlikely)? */
|
||||
GST_BUFFER_DATA (hdr)[0] = track->num | 0x80;
|
||||
data[0] = track->num | 0x80;
|
||||
/* time relative to clustertime */
|
||||
GST_WRITE_UINT16_BE (GST_BUFFER_DATA (hdr) + 1, relative_timestamp);
|
||||
GST_WRITE_UINT16_BE (data + 1, relative_timestamp);
|
||||
|
||||
/* flags */
|
||||
GST_BUFFER_DATA (hdr)[3] = flags;
|
||||
data[3] = flags;
|
||||
|
||||
return hdr;
|
||||
}
|
||||
|
@ -2562,14 +2534,18 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
|
|||
{
|
||||
GstMatroskaTrackVideoContext *ctx =
|
||||
(GstMatroskaTrackVideoContext *) collect_pad->track;
|
||||
const guint8 *data = GST_BUFFER_DATA (buf);
|
||||
guint size = GST_BUFFER_SIZE (buf);
|
||||
guint8 *buf_data, *data;
|
||||
gsize size;
|
||||
guint8 parse_code;
|
||||
guint32 next_parse_offset;
|
||||
GstBuffer *ret = NULL;
|
||||
gboolean is_muxing_unit = FALSE;
|
||||
|
||||
if (GST_BUFFER_SIZE (buf) < 13) {
|
||||
buf_data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
data = buf_data;
|
||||
|
||||
if (size < 13) {
|
||||
gst_buffer_unmap (buf, buf_data, -1);
|
||||
gst_buffer_unref (buf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2577,6 +2553,7 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
|
|||
/* Check if this buffer contains a picture or end-of-sequence packet */
|
||||
while (size >= 13) {
|
||||
if (GST_READ_UINT32_BE (data) != 0x42424344 /* 'BBCD' */ ) {
|
||||
gst_buffer_unmap (buf, buf_data, -1);
|
||||
gst_buffer_unref (buf);
|
||||
return ret;
|
||||
}
|
||||
|
@ -2607,12 +2584,13 @@ gst_matroska_mux_handle_dirac_packet (GstMatroskaMux * mux,
|
|||
else
|
||||
ctx->dirac_unit = gst_buffer_ref (buf);
|
||||
|
||||
gst_buffer_unmap (buf, buf_data, -1);
|
||||
|
||||
if (is_muxing_unit) {
|
||||
ret = gst_buffer_make_metadata_writable (ctx->dirac_unit);
|
||||
ret = gst_buffer_make_writable (ctx->dirac_unit);
|
||||
ctx->dirac_unit = NULL;
|
||||
gst_buffer_copy_metadata (ret, buf,
|
||||
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
|
||||
GST_BUFFER_COPY_CAPS);
|
||||
gst_buffer_copy_into (ret, buf,
|
||||
GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
|
||||
gst_buffer_unref (buf);
|
||||
} else {
|
||||
gst_buffer_unref (buf);
|
||||
|
@ -2634,9 +2612,9 @@ gst_matroska_mux_stop_streamheader (GstMatroskaMux * mux)
|
|||
|
||||
streamheader_buffer = gst_ebml_stop_streamheader (ebml);
|
||||
if (!strcmp (mux->doctype, GST_MATROSKA_DOCTYPE_WEBM)) {
|
||||
caps = gst_caps_new_simple ("video/webm", NULL);
|
||||
caps = gst_caps_new_empty_simple ("video/webm");
|
||||
} else {
|
||||
caps = gst_caps_new_simple ("video/x-matroska", NULL);
|
||||
caps = gst_caps_new_empty_simple ("video/x-matroska");
|
||||
}
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
g_value_init (&streamheader, GST_TYPE_ARRAY);
|
||||
|
@ -2836,14 +2814,14 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
|
|||
relative_timestamp, flags);
|
||||
gst_ebml_write_set_cache (ebml, 0x40);
|
||||
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_SIMPLEBLOCK,
|
||||
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
||||
gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
|
||||
gst_ebml_write_buffer (ebml, hdr);
|
||||
gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
|
||||
gst_ebml_write_buffer (ebml, buf);
|
||||
|
||||
return gst_ebml_last_write_result (ebml);
|
||||
} else {
|
||||
gst_ebml_write_set_cache (ebml, GST_BUFFER_SIZE (buf) * 2);
|
||||
gst_ebml_write_set_cache (ebml, gst_buffer_get_size (buf) * 2);
|
||||
/* write and call order slightly unnatural,
|
||||
* but avoids seek and minizes pushing */
|
||||
blockgroup = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_BLOCKGROUP);
|
||||
|
@ -2853,9 +2831,10 @@ gst_matroska_mux_write_data (GstMatroskaMux * mux, GstMatroskaPad * collect_pad)
|
|||
if (write_duration)
|
||||
gst_ebml_write_uint (ebml, GST_MATROSKA_ID_BLOCKDURATION, block_duration);
|
||||
gst_ebml_write_buffer_header (ebml, GST_MATROSKA_ID_BLOCK,
|
||||
GST_BUFFER_SIZE (buf) + GST_BUFFER_SIZE (hdr));
|
||||
gst_buffer_get_size (buf) + gst_buffer_get_size (hdr));
|
||||
gst_ebml_write_buffer (ebml, hdr);
|
||||
gst_ebml_write_master_finish_full (ebml, blockgroup, GST_BUFFER_SIZE (buf));
|
||||
gst_ebml_write_master_finish_full (ebml, blockgroup,
|
||||
gst_buffer_get_size (buf));
|
||||
gst_ebml_write_flush_cache (ebml, FALSE, GST_BUFFER_TIMESTAMP (buf));
|
||||
gst_ebml_write_buffer (ebml, buf);
|
||||
|
||||
|
|
|
@ -53,10 +53,13 @@ typedef struct _GstMatroskaMetaSeekIndex {
|
|||
guint64 pos;
|
||||
} GstMatroskaMetaSeekIndex;
|
||||
|
||||
typedef gboolean (*GstMatroskaCapsFunc) (GstPad *pad, GstCaps *caps);
|
||||
|
||||
/* all information needed for one matroska stream */
|
||||
typedef struct
|
||||
{
|
||||
GstCollectData collect; /* we extend the CollectData */
|
||||
GstMatroskaCapsFunc capsfunc;
|
||||
GstMatroskaTrackContext *track;
|
||||
|
||||
GstBuffer *buffer; /* the queued buffer for this pad */
|
||||
|
|
|
@ -111,16 +111,14 @@ static gboolean gst_matroska_parse_element_query (GstElement * element,
|
|||
static gboolean gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
|
||||
GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_matroska_parse_handle_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
static const GstQueryType *gst_matroska_parse_get_src_query_types (GstPad *
|
||||
pad);
|
||||
GstObject * parent, GstEvent * event);
|
||||
static gboolean gst_matroska_parse_handle_src_query (GstPad * pad,
|
||||
GstQuery * query);
|
||||
GstObject * parent, GstQuery * query);
|
||||
|
||||
static gboolean gst_matroska_parse_handle_sink_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
GstObject * parent, GstEvent * event);
|
||||
static GstFlowReturn gst_matroska_parse_chain (GstPad * pad,
|
||||
GstBuffer * buffer);
|
||||
GstObject * parent, GstBuffer * buffer);
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_matroska_parse_change_state (GstElement * element,
|
||||
|
@ -135,24 +133,8 @@ static gboolean perform_seek_to_offset (GstMatroskaParse * parse,
|
|||
guint64 offset);
|
||||
|
||||
GType gst_matroska_parse_get_type (void);
|
||||
GST_BOILERPLATE (GstMatroskaParse, gst_matroska_parse, GstElement,
|
||||
GST_TYPE_ELEMENT);
|
||||
|
||||
static void
|
||||
gst_matroska_parse_base_init (gpointer klass)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&src_templ));
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
gst_static_pad_template_get (&sink_templ));
|
||||
|
||||
gst_element_class_set_details_simple (element_class, "Matroska parser",
|
||||
"Codec/Parser",
|
||||
"Parses Matroska/WebM streams into video/audio/subtitles",
|
||||
"GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
|
||||
}
|
||||
#define parent_class gst_matroska_parse_parent_class
|
||||
G_DEFINE_TYPE (GstMatroskaParse, gst_matroska_parse, GST_TYPE_ELEMENT);
|
||||
|
||||
static void
|
||||
gst_matroska_parse_finalize (GObject * object)
|
||||
|
@ -196,11 +178,20 @@ gst_matroska_parse_class_init (GstMatroskaParseClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_matroska_parse_set_index);
|
||||
gstelement_class->get_index =
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_parse_get_index);
|
||||
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&src_templ));
|
||||
gst_element_class_add_pad_template (gstelement_class,
|
||||
gst_static_pad_template_get (&sink_templ));
|
||||
|
||||
gst_element_class_set_details_simple (gstelement_class,
|
||||
"Matroska parser", "Codec/Parser",
|
||||
"Parses Matroska/WebM streams into video/audio/subtitles",
|
||||
"GStreamer maintainers <gstreamer-devel@lists.sourceforge.net>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_matroska_parse_init (GstMatroskaParse * parse,
|
||||
GstMatroskaParseClass * klass)
|
||||
gst_matroska_parse_init (GstMatroskaParse * parse)
|
||||
{
|
||||
parse->common.sinkpad = gst_pad_new_from_static_template (&sink_templ,
|
||||
"sink");
|
||||
|
@ -213,8 +204,6 @@ gst_matroska_parse_init (GstMatroskaParse * parse,
|
|||
parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src");
|
||||
gst_pad_set_event_function (parse->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_event));
|
||||
gst_pad_set_query_type_function (parse->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_parse_get_src_query_types));
|
||||
gst_pad_set_query_function (parse->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_matroska_parse_handle_src_query));
|
||||
gst_pad_use_fixed_caps (parse->srcpad);
|
||||
|
@ -374,7 +363,7 @@ gst_matroska_parse_reset (GstElement * element)
|
|||
if (parse->common.global_tags) {
|
||||
gst_tag_list_free (parse->common.global_tags);
|
||||
}
|
||||
parse->common.global_tags = gst_tag_list_new ();
|
||||
parse->common.global_tags = gst_tag_list_new_empty ();
|
||||
|
||||
if (parse->common.cached_buffer) {
|
||||
gst_buffer_unref (parse->common.cached_buffer);
|
||||
|
@ -1078,19 +1067,6 @@ gst_matroska_parse_add_stream (GstMatroskaParse * parse, GstEbmlRead * ebml)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static const GstQueryType *
|
||||
gst_matroska_parse_get_src_query_types (GstPad * pad)
|
||||
{
|
||||
static const GstQueryType query_types[] = {
|
||||
GST_QUERY_POSITION,
|
||||
GST_QUERY_DURATION,
|
||||
GST_QUERY_SEEKING,
|
||||
0
|
||||
};
|
||||
|
||||
return query_types;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
|
||||
GstQuery * query)
|
||||
|
@ -1115,7 +1091,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
|
|||
gst_query_set_position (query, GST_FORMAT_TIME, context->pos);
|
||||
else
|
||||
gst_query_set_position (query, GST_FORMAT_TIME,
|
||||
parse->common.segment.last_stop);
|
||||
parse->common.segment.position);
|
||||
GST_OBJECT_UNLOCK (parse);
|
||||
} else if (format == GST_FORMAT_DEFAULT && context
|
||||
&& context->default_duration) {
|
||||
|
@ -1175,7 +1151,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad,
|
|||
break;
|
||||
}
|
||||
default:
|
||||
res = gst_pad_query_default (pad, query);
|
||||
res = gst_pad_query_default (pad, (GstObject *) parse, query);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1189,15 +1165,14 @@ gst_matroska_parse_element_query (GstElement * element, GstQuery * query)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_matroska_parse_handle_src_query (GstPad * pad, GstQuery * query)
|
||||
gst_matroska_parse_handle_src_query (GstPad * pad, GstObject * parent,
|
||||
GstQuery * query)
|
||||
{
|
||||
gboolean ret;
|
||||
GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
|
||||
GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
|
||||
|
||||
ret = gst_matroska_parse_query (parse, pad, query);
|
||||
|
||||
gst_object_unref (parse);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1248,6 +1223,8 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
|
|||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
const guint chunk = 64 * 1024;
|
||||
GstBuffer *buf = NULL;
|
||||
gpointer data;
|
||||
gsize size;
|
||||
guint64 length;
|
||||
guint32 id;
|
||||
guint needed;
|
||||
|
@ -1263,13 +1240,13 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
|
|||
if (ret != GST_FLOW_OK)
|
||||
break;
|
||||
GST_DEBUG_OBJECT (parse, "read buffer size %d at offset %" G_GINT64_FORMAT,
|
||||
GST_BUFFER_SIZE (buf), newpos);
|
||||
gst_byte_reader_init_from_buffer (&reader, buf);
|
||||
gst_buffer_get_size (buf), newpos);
|
||||
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||
gst_byte_reader_init (&reader, data, size);
|
||||
cluster_pos = 0;
|
||||
resume:
|
||||
cluster_pos = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff,
|
||||
GST_MATROSKA_ID_CLUSTER, cluster_pos,
|
||||
GST_BUFFER_SIZE (buf) - cluster_pos);
|
||||
GST_MATROSKA_ID_CLUSTER, cluster_pos, size - cluster_pos);
|
||||
if (cluster_pos >= 0) {
|
||||
newpos += cluster_pos;
|
||||
GST_DEBUG_OBJECT (parse,
|
||||
|
@ -1311,13 +1288,15 @@ gst_matroska_parse_search_cluster (GstMatroskaParse * parse, gint64 * pos)
|
|||
goto resume;
|
||||
} else {
|
||||
/* partial cluster id may have been in tail of buffer */
|
||||
newpos += MAX (GST_BUFFER_SIZE (buf), 4) - 3;
|
||||
newpos += MAX (size, 4) - 3;
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
gst_buffer_unref (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
gst_buffer_unmap (buf, data, size);
|
||||
gst_buffer_unref (buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
@ -1362,7 +1341,7 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
|
|||
|
||||
if (event) {
|
||||
GST_DEBUG_OBJECT (parse, "configuring seek");
|
||||
gst_segment_set_seek (&seeksegment, rate, format, flags,
|
||||
gst_segment_do_seek (&seeksegment, rate, format, flags,
|
||||
cur_type, cur, stop_type, stop, &update);
|
||||
}
|
||||
|
||||
|
@ -1371,7 +1350,7 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse,
|
|||
/* check sanity before we start flushing and all that */
|
||||
GST_OBJECT_LOCK (parse);
|
||||
if ((entry = gst_matroska_read_common_do_index_seek (&parse->common, track,
|
||||
seeksegment.last_stop, &parse->seek_index, &parse->seek_entry)) ==
|
||||
seeksegment.position, &parse->seek_index, &parse->seek_entry)) ==
|
||||
NULL) {
|
||||
/* pull mode without index can scan later on */
|
||||
GST_DEBUG_OBJECT (parse, "No matching seek entry in index");
|
||||
|
@ -1473,9 +1452,10 @@ gst_matroska_parse_handle_seek_push (GstMatroskaParse * parse, GstPad * pad,
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
|
||||
gst_matroska_parse_handle_src_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event)
|
||||
{
|
||||
GstMatroskaParse *parse = GST_MATROSKA_PARSE (gst_pad_get_parent (pad));
|
||||
GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
|
||||
gboolean res = TRUE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
|
@ -1499,7 +1479,7 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
|
|||
GstClockTimeDiff diff;
|
||||
GstClockTime timestamp;
|
||||
|
||||
gst_event_parse_qos (event, &proportion, &diff, ×tamp);
|
||||
gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
|
||||
|
||||
GST_OBJECT_LOCK (parse);
|
||||
videocontext->earliest_time = timestamp + diff;
|
||||
|
@ -1522,8 +1502,6 @@ gst_matroska_parse_handle_src_event (GstPad * pad, GstEvent * event)
|
|||
break;
|
||||
}
|
||||
|
||||
gst_object_unref (parse);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1635,6 +1613,8 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
|
|||
guint32 id;
|
||||
guint64 block_duration = 0;
|
||||
GstBuffer *buf = NULL;
|
||||
gpointer buf_data = NULL;
|
||||
gsize buf_size = 0;
|
||||
gint stream_num = -1, n, laces = 0;
|
||||
guint size = 0;
|
||||
gint *lace_size = NULL;
|
||||
|
@ -1668,8 +1648,10 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
|
|||
if ((ret = gst_ebml_read_buffer (ebml, &id, &buf)) != GST_FLOW_OK)
|
||||
break;
|
||||
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
buf_data = gst_buffer_map (buf, &buf_size, NULL, GST_MAP_READ);
|
||||
|
||||
data = buf_data;
|
||||
size = buf_size;
|
||||
|
||||
/* first byte(s): blocknum */
|
||||
if ((n = gst_matroska_ebmlnum_uint (data, size, &num)) < 0)
|
||||
|
@ -1873,18 +1855,18 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
|
|||
}
|
||||
/* need to refresh segment info ASAP */
|
||||
if (GST_CLOCK_TIME_IS_VALID (lace_time) && parse->need_newsegment) {
|
||||
GstSegment segment;
|
||||
GST_DEBUG_OBJECT (parse,
|
||||
"generating segment starting at %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (lace_time));
|
||||
/* pretend we seeked here */
|
||||
gst_segment_set_seek (&parse->common.segment, parse->common.segment.rate,
|
||||
gst_segment_do_seek (&parse->common.segment, parse->common.segment.rate,
|
||||
GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time,
|
||||
GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL);
|
||||
/* now convey our segment notion downstream */
|
||||
gst_matroska_parse_send_event (parse, gst_event_new_new_segment (FALSE,
|
||||
parse->common.segment.rate, parse->common.segment.format,
|
||||
parse->common.segment.start, parse->common.segment.stop,
|
||||
parse->common.segment.start));
|
||||
segment = parse->common.segment;
|
||||
segment.position = segment.start;
|
||||
gst_matroska_parse_send_event (parse, gst_event_new_segment (&segment));
|
||||
parse->need_newsegment = FALSE;
|
||||
}
|
||||
|
||||
|
@ -2134,8 +2116,10 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse,
|
|||
}
|
||||
|
||||
done:
|
||||
if (buf)
|
||||
if (buf) {
|
||||
gst_buffer_unmap (buf, buf_data, buf_size);
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
g_free (lace_size);
|
||||
|
||||
return ret;
|
||||
|
@ -2419,10 +2403,9 @@ gst_matroska_parse_check_seekability (GstMatroskaParse * parse)
|
|||
|
||||
/* try harder to query upstream size if we didn't get it the first time */
|
||||
if (seekable && stop == -1) {
|
||||
GstFormat fmt = GST_FORMAT_BYTES;
|
||||
|
||||
GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop");
|
||||
gst_pad_query_peer_duration (parse->common.sinkpad, &fmt, &stop);
|
||||
gst_pad_peer_query_duration (parse->common.sinkpad, GST_FORMAT_BYTES,
|
||||
&stop);
|
||||
}
|
||||
|
||||
/* if upstream doesn't know the size, it's likely that it's not seekable in
|
||||
|
@ -2506,14 +2489,15 @@ gst_matroska_parse_accumulate_streamheader (GstMatroskaParse * parse,
|
|||
GstBuffer *buf;
|
||||
|
||||
buf = gst_buffer_span (parse->streamheader, 0, buffer,
|
||||
GST_BUFFER_SIZE (parse->streamheader) + GST_BUFFER_SIZE (buffer));
|
||||
gst_buffer_get_size (parse->streamheader) +
|
||||
gst_buffer_get_size (buffer));
|
||||
gst_buffer_unref (parse->streamheader);
|
||||
parse->streamheader = buf;
|
||||
} else {
|
||||
parse->streamheader = gst_buffer_ref (buffer);
|
||||
}
|
||||
|
||||
GST_DEBUG ("%d", GST_BUFFER_SIZE (parse->streamheader));
|
||||
GST_DEBUG ("%d", gst_buffer_get_size (parse->streamheader));
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
|
@ -2529,7 +2513,7 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
|
|||
GValue bufval = { 0 };
|
||||
GstBuffer *buf;
|
||||
|
||||
caps = gst_caps_new_simple ("video/x-matroska", NULL);
|
||||
caps = gst_caps_new_empty_simple ("video/x-matroska");
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
g_value_init (&streamheader, GST_TYPE_ARRAY);
|
||||
g_value_init (&bufval, GST_TYPE_BUFFER);
|
||||
|
@ -2545,7 +2529,6 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
|
|||
gst_pad_set_caps (parse->srcpad, caps);
|
||||
|
||||
buf = gst_buffer_copy (parse->streamheader);
|
||||
gst_buffer_set_caps (buf, caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
||||
|
@ -2567,7 +2550,6 @@ gst_matroska_parse_output (GstMatroskaParse * parse, GstBuffer * buffer,
|
|||
} else {
|
||||
GST_BUFFER_TIMESTAMP (buffer) = parse->last_timestamp;
|
||||
}
|
||||
gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad));
|
||||
ret = gst_pad_push (parse->srcpad, gst_buffer_ref (buffer));
|
||||
|
||||
return ret;
|
||||
|
@ -3028,9 +3010,9 @@ perform_seek_to_offset (GstMatroskaParse * parse, guint64 offset)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_matroska_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||
gst_matroska_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
|
||||
{
|
||||
GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
|
||||
GstMatroskaParse *parse = GST_MATROSKA_PARSE (parent);
|
||||
guint available;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
guint needed = 0;
|
||||
|
@ -3075,7 +3057,8 @@ next:
|
|||
}
|
||||
|
||||
static gboolean
|
||||
gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
|
||||
gst_matroska_parse_handle_sink_event (GstPad * pad, GstObject * parent,
|
||||
GstEvent * event)
|
||||
{
|
||||
gboolean res = TRUE;
|
||||
GstMatroskaParse *parse = GST_MATROSKA_PARSE (GST_PAD_PARENT (pad));
|
||||
|
@ -3084,23 +3067,15 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
"have event type %s: %p on sink pad", GST_EVENT_TYPE_NAME (event), event);
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
case GST_EVENT_SEGMENT:
|
||||
{
|
||||
GstFormat format;
|
||||
gdouble rate, arate;
|
||||
gint64 start, stop, time = 0;
|
||||
gboolean update;
|
||||
GstSegment segment;
|
||||
const GstSegment *segment;
|
||||
|
||||
/* some debug output */
|
||||
gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||
&start, &stop, &time);
|
||||
gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
|
||||
start, stop, time);
|
||||
gst_event_parse_segment (event, &segment);
|
||||
GST_DEBUG_OBJECT (parse,
|
||||
"received format %d newsegment %" GST_SEGMENT_FORMAT, format,
|
||||
&segment);
|
||||
"received format %d newsegment %" GST_SEGMENT_FORMAT,
|
||||
segment->format, segment);
|
||||
|
||||
if (parse->common.state < GST_MATROSKA_READ_STATE_DATA) {
|
||||
GST_DEBUG_OBJECT (parse, "still starting");
|
||||
|
@ -3108,7 +3083,7 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
}
|
||||
|
||||
/* we only expect a BYTE segment, e.g. following a seek */
|
||||
if (format != GST_FORMAT_BYTES) {
|
||||
if (segment->format != GST_FORMAT_BYTES) {
|
||||
GST_DEBUG_OBJECT (parse, "unsupported segment format, ignoring");
|
||||
goto exit;
|
||||
}
|
||||
|
@ -3117,15 +3092,15 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
/* clear current segment leftover */
|
||||
gst_adapter_clear (parse->common.adapter);
|
||||
/* and some streaming setup */
|
||||
parse->common.offset = start;
|
||||
parse->common.offset = segment->start;
|
||||
/* do not know where we are;
|
||||
* need to come across a cluster and generate newsegment */
|
||||
parse->common.segment.last_stop = GST_CLOCK_TIME_NONE;
|
||||
parse->common.segment.position = GST_CLOCK_TIME_NONE;
|
||||
parse->cluster_time = GST_CLOCK_TIME_NONE;
|
||||
parse->cluster_offset = 0;
|
||||
parse->need_newsegment = TRUE;
|
||||
/* but keep some of the upstream segment */
|
||||
parse->common.segment.rate = rate;
|
||||
parse->common.segment.rate = segment->rate;
|
||||
exit:
|
||||
/* chain will send initial newsegment after pads have been added,
|
||||
* or otherwise come up with one */
|
||||
|
@ -3155,13 +3130,13 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event)
|
|||
gst_matroska_read_common_reset_streams (&parse->common,
|
||||
GST_CLOCK_TIME_NONE, TRUE);
|
||||
GST_OBJECT_UNLOCK (parse);
|
||||
parse->common.segment.last_stop = GST_CLOCK_TIME_NONE;
|
||||
parse->common.segment.position = GST_CLOCK_TIME_NONE;
|
||||
parse->cluster_time = GST_CLOCK_TIME_NONE;
|
||||
parse->cluster_offset = 0;
|
||||
/* fall-through */
|
||||
}
|
||||
default:
|
||||
res = gst_pad_event_default (pad, event);
|
||||
res = gst_pad_event_default (pad, parent, event);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ GST_DEBUG_CATEGORY (matroskareadcommon_debug);
|
|||
|
||||
static gboolean
|
||||
gst_matroska_decompress_data (GstMatroskaTrackEncoding * enc,
|
||||
guint8 ** data_out, guint * size_out,
|
||||
gpointer * data_out, gsize * size_out,
|
||||
GstMatroskaTrackCompressionAlgorithm algo)
|
||||
{
|
||||
guint8 *new_data = NULL;
|
||||
|
@ -237,8 +237,8 @@ gst_matroska_decode_content_encodings (GArray * encodings)
|
|||
for (i = 0; i < encodings->len; i++) {
|
||||
GstMatroskaTrackEncoding *enc =
|
||||
&g_array_index (encodings, GstMatroskaTrackEncoding, i);
|
||||
guint8 *data = NULL;
|
||||
guint size;
|
||||
gpointer data = NULL;
|
||||
gsize size;
|
||||
|
||||
if ((enc->scope & GST_MATROSKA_TRACK_ENCODING_SCOPE_NEXT_CONTENT_ENCODING)
|
||||
== 0)
|
||||
|
@ -270,11 +270,11 @@ gst_matroska_decode_content_encodings (GArray * encodings)
|
|||
}
|
||||
|
||||
gboolean
|
||||
gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
|
||||
guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
|
||||
gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
|
||||
gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free)
|
||||
{
|
||||
guint8 *data;
|
||||
guint size;
|
||||
gpointer data;
|
||||
gsize size;
|
||||
gboolean ret = TRUE;
|
||||
gint i;
|
||||
|
||||
|
@ -288,8 +288,8 @@ gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
|
|||
for (i = 0; i < encodings->len; i++) {
|
||||
GstMatroskaTrackEncoding *enc =
|
||||
&g_array_index (encodings, GstMatroskaTrackEncoding, i);
|
||||
guint8 *new_data = NULL;
|
||||
guint new_size = 0;
|
||||
gpointer new_data = NULL;
|
||||
gsize new_size = 0;
|
||||
|
||||
if ((enc->scope & scope) == 0)
|
||||
continue;
|
||||
|
@ -430,21 +430,31 @@ gst_matroska_read_common_found_global_tag (GstMatroskaReadCommon * common,
|
|||
gst_tag_list_insert (common->global_tags, taglist, GST_TAG_MERGE_APPEND);
|
||||
gst_tag_list_free (taglist);
|
||||
} else {
|
||||
GstEvent *tag_event = gst_event_new_tag (taglist);
|
||||
gint i;
|
||||
|
||||
/* hm, already sent, no need to cache and wait anymore */
|
||||
GST_DEBUG_OBJECT (common, "Sending late global tags %" GST_PTR_FORMAT,
|
||||
taglist);
|
||||
gst_element_found_tags (el, taglist);
|
||||
|
||||
for (i = 0; i < common->src->len; i++) {
|
||||
GstMatroskaTrackContext *stream;
|
||||
|
||||
stream = g_ptr_array_index (common->src, i);
|
||||
gst_pad_push_event (stream->pad, gst_event_ref (tag_event));
|
||||
}
|
||||
|
||||
gst_event_unref (tag_event);
|
||||
}
|
||||
}
|
||||
|
||||
gint64
|
||||
gst_matroska_read_common_get_length (GstMatroskaReadCommon * common)
|
||||
{
|
||||
GstFormat fmt = GST_FORMAT_BYTES;
|
||||
gint64 end = -1;
|
||||
|
||||
if (!gst_pad_query_peer_duration (common->sinkpad, &fmt, &end) ||
|
||||
fmt != GST_FORMAT_BYTES || end < 0)
|
||||
if (!gst_pad_peer_query_duration (common->sinkpad, GST_FORMAT_BYTES,
|
||||
&end) || end < 0)
|
||||
GST_DEBUG_OBJECT (common, "no upstream length");
|
||||
|
||||
return end;
|
||||
|
@ -569,7 +579,7 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
|
|||
if (filename && mimetype && data && datalen > 0) {
|
||||
GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
|
||||
GstBuffer *tagbuffer = NULL;
|
||||
GstCaps *caps;
|
||||
/* GstCaps *caps; */
|
||||
gchar *filename_lc = g_utf8_strdown (filename, -1);
|
||||
|
||||
GST_DEBUG_OBJECT (common, "Creating tag for attachment with "
|
||||
|
@ -600,31 +610,32 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common,
|
|||
|
||||
if (!tagbuffer)
|
||||
image_type = GST_TAG_IMAGE_TYPE_NONE;
|
||||
else
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
/* if this failed create an attachment buffer */
|
||||
if (!tagbuffer) {
|
||||
tagbuffer = gst_buffer_new_and_alloc (datalen);
|
||||
tagbuffer = gst_buffer_new_wrapped (g_memdup (data, datalen), datalen);
|
||||
|
||||
memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen);
|
||||
GST_BUFFER_SIZE (tagbuffer) = datalen;
|
||||
|
||||
caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL);
|
||||
if (caps == NULL)
|
||||
caps = gst_caps_new_simple (mimetype, NULL);
|
||||
gst_buffer_set_caps (tagbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
/* FIXME: We can't attach caps to buffers in 0.11. */
|
||||
/* caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); */
|
||||
/* if (caps == NULL) */
|
||||
/* caps = gst_caps_new_simple (mimetype, NULL); */
|
||||
/* gst_buffer_set_caps (tagbuffer, caps); */
|
||||
/* gst_caps_unref (caps); */
|
||||
}
|
||||
|
||||
/* FIXME: We can't attach caps to buffers in 0.11. */
|
||||
/* Set filename and description on the caps */
|
||||
caps = GST_BUFFER_CAPS (tagbuffer);
|
||||
gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL);
|
||||
if (description)
|
||||
gst_caps_set_simple (caps, "description", G_TYPE_STRING, description,
|
||||
NULL);
|
||||
/* caps = GST_BUFFER_CAPS (tagbuffer); */
|
||||
/* gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); */
|
||||
/* if (description) */
|
||||
/* gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, */
|
||||
/* NULL); */
|
||||
|
||||
GST_DEBUG_OBJECT (common,
|
||||
"Created attachment buffer with caps: %" GST_PTR_FORMAT, caps);
|
||||
/* GST_DEBUG_OBJECT (common, */
|
||||
/* "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); */
|
||||
|
||||
/* and append to the tag list */
|
||||
if (image_type != GST_TAG_IMAGE_TYPE_NONE)
|
||||
|
@ -658,7 +669,7 @@ gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common,
|
|||
return ret;
|
||||
}
|
||||
|
||||
taglist = gst_tag_list_new ();
|
||||
taglist = gst_tag_list_new_empty ();
|
||||
|
||||
while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
|
||||
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
|
||||
|
@ -1280,9 +1291,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
|
|||
break;
|
||||
|
||||
GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text));
|
||||
taglist = gst_tag_list_new ();
|
||||
gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text,
|
||||
NULL);
|
||||
taglist = gst_tag_list_new (GST_TAG_TITLE, text, NULL);
|
||||
gst_matroska_read_common_found_global_tag (common, el, taglist);
|
||||
g_free (text);
|
||||
break;
|
||||
|
@ -1313,7 +1322,7 @@ gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common,
|
|||
dur_u = gst_gdouble_to_guint64 (dur_f *
|
||||
gst_guint64_to_gdouble (common->time_scale));
|
||||
if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64)
|
||||
gst_segment_set_duration (&common->segment, GST_FORMAT_TIME, dur_u);
|
||||
common->segment.duration = dur_u;
|
||||
}
|
||||
|
||||
DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret);
|
||||
|
@ -1518,7 +1527,7 @@ gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common,
|
|||
return ret;
|
||||
}
|
||||
|
||||
taglist = gst_tag_list_new ();
|
||||
taglist = gst_tag_list_new_empty ();
|
||||
|
||||
while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) {
|
||||
if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK)
|
||||
|
@ -1551,7 +1560,8 @@ static GstFlowReturn
|
|||
gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint
|
||||
peek, const guint8 ** data)
|
||||
{
|
||||
*data = gst_adapter_peek (common->adapter, peek);
|
||||
/* Caller needs to gst_adapter_unmap. */
|
||||
*data = gst_adapter_map (common->adapter, peek);
|
||||
if (*data == NULL)
|
||||
return GST_FLOW_UNEXPECTED;
|
||||
|
||||
|
@ -1571,19 +1581,26 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
|
|||
* We do it mainly to avoid pulling buffers of 1 byte all the time */
|
||||
if (common->cached_buffer) {
|
||||
guint64 cache_offset = GST_BUFFER_OFFSET (common->cached_buffer);
|
||||
guint cache_size = GST_BUFFER_SIZE (common->cached_buffer);
|
||||
gsize cache_size = gst_buffer_get_size (common->cached_buffer);
|
||||
|
||||
if (cache_offset <= common->offset &&
|
||||
(common->offset + size) <= (cache_offset + cache_size)) {
|
||||
if (p_buf)
|
||||
*p_buf = gst_buffer_create_sub (common->cached_buffer,
|
||||
common->offset - cache_offset, size);
|
||||
if (bytes)
|
||||
*bytes = GST_BUFFER_DATA (common->cached_buffer) + common->offset -
|
||||
cache_offset;
|
||||
*p_buf = gst_buffer_copy_region (common->cached_buffer,
|
||||
GST_BUFFER_COPY_ALL, common->offset - cache_offset, size);
|
||||
if (bytes) {
|
||||
if (!common->cached_data)
|
||||
common->cached_data = gst_buffer_map (common->cached_buffer,
|
||||
NULL, NULL, GST_MAP_READ);
|
||||
*bytes = common->cached_data + common->offset - cache_offset;
|
||||
}
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
/* not enough data in the cache, free cache and get a new one */
|
||||
if (common->cached_data) {
|
||||
gst_buffer_unmap (common->cached_buffer, common->cached_data, -1);
|
||||
common->cached_data = NULL;
|
||||
}
|
||||
gst_buffer_unref (common->cached_buffer);
|
||||
common->cached_buffer = NULL;
|
||||
}
|
||||
|
@ -1596,11 +1613,15 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (GST_BUFFER_SIZE (common->cached_buffer) >= size) {
|
||||
if (gst_buffer_get_size (common->cached_buffer) >= size) {
|
||||
if (p_buf)
|
||||
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
|
||||
if (bytes)
|
||||
*bytes = GST_BUFFER_DATA (common->cached_buffer);
|
||||
*p_buf = gst_buffer_copy_region (common->cached_buffer,
|
||||
GST_BUFFER_COPY_ALL, 0, size);
|
||||
if (bytes) {
|
||||
common->cached_data = gst_buffer_map (common->cached_buffer,
|
||||
NULL, NULL, GST_MAP_READ);
|
||||
*bytes = common->cached_data;
|
||||
}
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
@ -1621,10 +1642,10 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (GST_BUFFER_SIZE (common->cached_buffer) < size) {
|
||||
if (gst_buffer_get_size (common->cached_buffer) < size) {
|
||||
GST_WARNING_OBJECT (common, "Dropping short buffer at offset %"
|
||||
G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", common->offset,
|
||||
size, GST_BUFFER_SIZE (common->cached_buffer));
|
||||
size, gst_buffer_get_size (common->cached_buffer));
|
||||
|
||||
gst_buffer_unref (common->cached_buffer);
|
||||
common->cached_buffer = NULL;
|
||||
|
@ -1636,9 +1657,13 @@ gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * common, guint64
|
|||
}
|
||||
|
||||
if (p_buf)
|
||||
*p_buf = gst_buffer_create_sub (common->cached_buffer, 0, size);
|
||||
if (bytes)
|
||||
*bytes = GST_BUFFER_DATA (common->cached_buffer);
|
||||
*p_buf = gst_buffer_copy_region (common->cached_buffer,
|
||||
GST_BUFFER_COPY_ALL, 0, size);
|
||||
if (bytes) {
|
||||
common->cached_data = gst_buffer_map (common->cached_buffer,
|
||||
NULL, NULL, GST_MAP_READ);
|
||||
*bytes = common->cached_data;
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
@ -1664,9 +1689,15 @@ GstFlowReturn
|
|||
gst_matroska_read_common_peek_id_length_push (GstMatroskaReadCommon * common,
|
||||
GstElement * el, guint32 * _id, guint64 * _length, guint * _needed)
|
||||
{
|
||||
return gst_ebml_peek_id_length (_id, _length, _needed,
|
||||
GstFlowReturn ret;
|
||||
|
||||
ret = gst_ebml_peek_id_length (_id, _length, _needed,
|
||||
(GstPeekData) gst_matroska_read_common_peek_adapter, (gpointer) common,
|
||||
el, common->offset);
|
||||
|
||||
gst_adapter_unmap (common->adapter);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
|
|
|
@ -81,6 +81,7 @@ typedef struct _GstMatroskaReadCommon {
|
|||
|
||||
/* pull mode caching */
|
||||
GstBuffer *cached_buffer;
|
||||
guint8 *cached_data;
|
||||
|
||||
/* push and pull mode */
|
||||
guint64 offset;
|
||||
|
@ -90,8 +91,8 @@ typedef struct _GstMatroskaReadCommon {
|
|||
} GstMatroskaReadCommon;
|
||||
|
||||
GstFlowReturn gst_matroska_decode_content_encodings (GArray * encodings);
|
||||
gboolean gst_matroska_decode_data (GArray * encodings, guint8 ** data_out,
|
||||
guint * size_out, GstMatroskaTrackEncodingScope scope, gboolean free);
|
||||
gboolean gst_matroska_decode_data (GArray * encodings, gpointer * data_out,
|
||||
gsize * size_out, GstMatroskaTrackEncodingScope scope, gboolean free);
|
||||
gint gst_matroska_index_seek_find (GstMatroskaIndex * i1, GstClockTime * time,
|
||||
gpointer user_data);
|
||||
GstMatroskaIndex * gst_matroska_read_common_do_index_seek (
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
* ]| This pipeline re-encodes a video file of any format into a WebM file.
|
||||
* |[
|
||||
* gst-launch-0.10 webmmux name=mux ! filesink location=test.webm \
|
||||
* videotestsrc num-buffers=250 ! video/x-raw-yuv,framerate=25/1 ! ffmpegcolorspace ! vp8enc ! queue ! mux.video_0 \
|
||||
* audiotestsrc samplesperbuffer=44100 num-buffers=10 ! audio/x-raw-float,rate=44100 ! vorbisenc ! queue ! mux.audio_0
|
||||
* videotestsrc num-buffers=250 ! video/x-raw,framerate=25/1 ! ffmpegcolorspace ! vp8enc ! queue ! mux.video_0 \
|
||||
* audiotestsrc samplesperbuffer=44100 num-buffers=10 ! audio/x-raw,rate=44100 ! vorbisenc ! queue ! mux.audio_0
|
||||
* ]| This pipeline muxes a test video and a sine wave into a WebM file.
|
||||
* </refsect2>
|
||||
*/
|
||||
|
@ -53,8 +53,7 @@
|
|||
"channels = (int) [ 1, MAX ], " \
|
||||
"rate = (int) [ 1, MAX ]"
|
||||
|
||||
GST_BOILERPLATE (GstWebMMux, gst_webm_mux, GstMatroskaMux,
|
||||
GST_TYPE_MATROSKA_MUX);
|
||||
G_DEFINE_TYPE (GstWebMMux, gst_webm_mux, GST_TYPE_MATROSKA_MUX);
|
||||
|
||||
static GstStaticPadTemplate webm_src_templ = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
|
@ -76,11 +75,6 @@ GST_STATIC_PAD_TEMPLATE ("audio_%u",
|
|||
GST_STATIC_CAPS ("audio/x-vorbis, " COMMON_AUDIO_CAPS)
|
||||
);
|
||||
|
||||
static void
|
||||
gst_webm_mux_base_init (gpointer g_class)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gst_webm_mux_class_init (GstWebMMuxClass * klass)
|
||||
{
|
||||
|
@ -99,7 +93,7 @@ gst_webm_mux_class_init (GstWebMMuxClass * klass)
|
|||
}
|
||||
|
||||
static void
|
||||
gst_webm_mux_init (GstWebMMux * mux, GstWebMMuxClass * g_class)
|
||||
gst_webm_mux_init (GstWebMMux * mux)
|
||||
{
|
||||
GST_MATROSKA_MUX (mux)->doctype = GST_MATROSKA_DOCTYPE_WEBM;
|
||||
}
|
||||
|
|
|
@ -163,6 +163,7 @@ static GstElement *
|
|||
setup_matroskamux (GstStaticPadTemplate * srctemplate)
|
||||
{
|
||||
GstElement *matroskamux;
|
||||
GstSegment segment;
|
||||
|
||||
GST_DEBUG ("setup_matroskamux");
|
||||
matroskamux = gst_check_setup_element ("matroskamux");
|
||||
|
@ -170,6 +171,14 @@ setup_matroskamux (GstStaticPadTemplate * srctemplate)
|
|||
mysrcpad = setup_src_pad (matroskamux, srctemplate, NULL);
|
||||
mysinkpad = setup_sink_pad (matroskamux, &sinktemplate, NULL);
|
||||
|
||||
fail_unless (gst_element_set_state (matroskamux,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||
fail_unless (gst_pad_push_event (mysrcpad,
|
||||
gst_event_new_segment (&segment)), "Segment event rejected");
|
||||
|
||||
return matroskamux;
|
||||
}
|
||||
|
||||
|
@ -187,8 +196,8 @@ cleanup_matroskamux (GstElement * matroskamux)
|
|||
static void
|
||||
check_buffer_data (GstBuffer * buffer, void *data, size_t data_size)
|
||||
{
|
||||
fail_unless (GST_BUFFER_SIZE (buffer) == data_size);
|
||||
fail_unless (memcmp (data, GST_BUFFER_DATA (buffer), data_size) == 0);
|
||||
fail_unless (gst_buffer_get_size (buffer) == data_size);
|
||||
fail_unless (gst_buffer_memcmp (buffer, 0, data, data_size) == 0);
|
||||
}
|
||||
|
||||
GST_START_TEST (test_ebml_header)
|
||||
|
@ -207,11 +216,8 @@ GST_START_TEST (test_ebml_header)
|
|||
};
|
||||
|
||||
matroskamux = setup_matroskamux (&srcac3template);
|
||||
fail_unless (gst_element_set_state (matroskamux,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (1);
|
||||
inbuffer = gst_buffer_new_allocate (NULL, 1, 0);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
num_buffers = g_list_length (buffers);
|
||||
|
@ -259,14 +265,12 @@ GST_START_TEST (test_vorbis_header)
|
|||
};
|
||||
|
||||
matroskamux = setup_matroskamux (&srcvorbistemplate);
|
||||
fail_unless (gst_element_set_state (matroskamux,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (1);
|
||||
caps = gst_caps_from_string (VORBIS_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
fail_unless (gst_pad_set_caps (mysrcpad, caps));
|
||||
gst_caps_unref (caps);
|
||||
|
||||
inbuffer = gst_buffer_new_allocate (NULL, 1, 0);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
|
@ -274,14 +278,16 @@ GST_START_TEST (test_vorbis_header)
|
|||
|
||||
for (i = 0; i < num_buffers; ++i) {
|
||||
gint j;
|
||||
gsize buffer_size;
|
||||
|
||||
outbuffer = GST_BUFFER (buffers->data);
|
||||
fail_if (outbuffer == NULL);
|
||||
buffer_size = gst_buffer_get_size (outbuffer);
|
||||
buffers = g_list_remove (buffers, outbuffer);
|
||||
|
||||
if (!vorbis_header_found && GST_BUFFER_SIZE (outbuffer) >= sizeof (data)) {
|
||||
for (j = 0; j <= GST_BUFFER_SIZE (outbuffer) - sizeof (data); j++) {
|
||||
if (memcmp (GST_BUFFER_DATA (outbuffer) + j, data, sizeof (data)) == 0) {
|
||||
if (!vorbis_header_found && buffer_size >= sizeof (data)) {
|
||||
for (j = 0; j <= buffer_size - sizeof (data); j++) {
|
||||
if (gst_buffer_memcmp (outbuffer, j, data, sizeof (data)) == 0) {
|
||||
vorbis_header_found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
@ -307,6 +313,7 @@ GST_START_TEST (test_block_group)
|
|||
{
|
||||
GstElement *matroskamux;
|
||||
GstBuffer *inbuffer, *outbuffer;
|
||||
guint8 *indata;
|
||||
GstCaps *caps;
|
||||
int num_buffers;
|
||||
int i;
|
||||
|
@ -317,16 +324,14 @@ GST_START_TEST (test_block_group)
|
|||
guint8 data1[] = { 0x42 };
|
||||
|
||||
matroskamux = setup_matroskamux (&srcac3template);
|
||||
fail_unless (gst_element_set_state (matroskamux,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
caps = gst_caps_from_string (AC3_CAPS_STRING);
|
||||
fail_unless (gst_pad_set_caps (mysrcpad, caps));
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* Generate the header */
|
||||
inbuffer = gst_buffer_new_and_alloc (1);
|
||||
inbuffer = gst_buffer_new_allocate (NULL, 1, 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);
|
||||
|
||||
fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK);
|
||||
|
@ -346,12 +351,10 @@ GST_START_TEST (test_block_group)
|
|||
buffers = NULL;
|
||||
|
||||
/* Now push a buffer */
|
||||
inbuffer = gst_buffer_new_and_alloc (1);
|
||||
GST_BUFFER_DATA (inbuffer)[0] = 0x42;
|
||||
indata = g_malloc (1);
|
||||
inbuffer = gst_buffer_new_wrapped (indata, 1);
|
||||
indata[0] = 0x42;
|
||||
GST_BUFFER_TIMESTAMP (inbuffer) = 1000000;
|
||||
caps = gst_caps_from_string (AC3_CAPS_STRING);
|
||||
gst_buffer_set_caps (inbuffer, caps);
|
||||
gst_caps_unref (caps);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
|
@ -396,11 +399,8 @@ GST_START_TEST (test_reset)
|
|||
int i;
|
||||
|
||||
matroskamux = setup_matroskamux (&srcac3template);
|
||||
fail_unless (gst_element_set_state (matroskamux,
|
||||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (1);
|
||||
inbuffer = gst_buffer_new_allocate (NULL, 1, 0);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
num_buffers = g_list_length (buffers);
|
||||
|
@ -414,7 +414,7 @@ GST_START_TEST (test_reset)
|
|||
GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
|
||||
"could not set to playing");
|
||||
|
||||
inbuffer = gst_buffer_new_and_alloc (1);
|
||||
inbuffer = gst_buffer_new_allocate (NULL, 1, 0);
|
||||
ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
|
||||
fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
|
||||
num_buffers = g_list_length (buffers);
|
||||
|
|
Loading…
Reference in a new issue