mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +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 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 \
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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, ×tamp);
|
gst_event_parse_qos (event, NULL, &proportion, &diff, ×tamp);
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue