summaryrefslogtreecommitdiff
path: root/gst
diff options
context:
space:
mode:
authorThiago Santos <thiagoss@osg.samsung.com>2014-08-21 12:09:23 -0300
committerThiago Santos <thiagoss@osg.samsung.com>2014-08-27 10:54:18 -0300
commit2863d9ae0039ddd27b4b98ceaaa1f4ed3a2eb3d6 (patch)
tree184b041e13e500ed5b18545d7cf2d271ca491760 /gst
parent2402349d13d2e6b095b871ca6b89db87192e6432 (diff)
asfdemux: if video is h264, check the codec_data for bytestream data
For bytestream we don't want to expose it as codec_data but rather as streamheader as it is not out-of-band data but data that should be prepended to the beginning of the stream before the other buffers. https://bugzilla.gnome.org/show_bug.cgi?id=735070
Diffstat (limited to 'gst')
-rw-r--r--gst/asfdemux/gstasfdemux.c62
-rw-r--r--gst/asfdemux/gstasfdemux.h3
2 files changed, 62 insertions, 3 deletions
diff --git a/gst/asfdemux/gstasfdemux.c b/gst/asfdemux/gstasfdemux.c
index a6432fcd..d9e1c19f 100644
--- a/gst/asfdemux/gstasfdemux.c
+++ b/gst/asfdemux/gstasfdemux.c
@@ -147,6 +147,10 @@ gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
gst_tag_list_unref (stream->pending_tags);
stream->pending_tags = NULL;
}
+ if (stream->streamheader) {
+ gst_buffer_unref (stream->streamheader);
+ stream->streamheader = NULL;
+ }
if (stream->pad) {
if (stream->active) {
gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
@@ -525,6 +529,7 @@ gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
for (n = 0; n < demux->num_streams; n++) {
demux->stream[n].discont = TRUE;
+ demux->stream[n].first_buffer = TRUE;
while (demux->stream[n].payloads->len > 0) {
AsfPayload *payload;
@@ -1707,6 +1712,15 @@ gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
payload->buf);
if (stream->active) {
+ if (G_UNLIKELY (stream->first_buffer)) {
+ if (stream->streamheader != NULL) {
+ GST_DEBUG_OBJECT (stream->pad,
+ "Pushing streamheader before first buffer");
+ gst_pad_push (stream->pad, gst_buffer_ref (stream->streamheader));
+ }
+ stream->first_buffer = FALSE;
+ }
+
ret = gst_pad_push (stream->pad, payload->buf);
ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
} else {
@@ -2339,7 +2353,8 @@ gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
static AsfStream *
gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
- GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
+ GstCaps * caps, guint16 id, gboolean is_video, GstBuffer * streamheader,
+ GstTagList * tags)
{
AsfStream *stream;
@@ -2359,6 +2374,12 @@ gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
stream->is_video = is_video;
stream->pending_tags = tags;
stream->discont = TRUE;
+ stream->first_buffer = TRUE;
+ stream->streamheader = streamheader;
+ if (stream->streamheader) {
+ stream->streamheader = gst_buffer_make_writable (streamheader);
+ GST_BUFFER_FLAG_SET (stream->streamheader, GST_BUFFER_FLAG_HEADER);
+ }
if (is_video) {
GstStructure *st;
gint par_x, par_y;
@@ -2383,6 +2404,22 @@ gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
return stream;
}
+static void
+gst_asf_demux_add_stream_headers_to_caps (GstASFDemux * demux,
+ GstBuffer * buffer, GstStructure * structure)
+{
+ GValue arr_val = G_VALUE_INIT;
+ GValue buf_val = G_VALUE_INIT;
+
+ g_value_init (&arr_val, GST_TYPE_ARRAY);
+ g_value_init (&buf_val, GST_TYPE_BUFFER);
+
+ gst_value_set_buffer (&buf_val, buffer);
+ gst_value_array_append_and_take_value (&arr_val, &buf_val);
+
+ gst_structure_take_value (structure, "streamheader", &arr_val);
+}
+
static AsfStream *
gst_asf_demux_add_audio_stream (GstASFDemux * demux,
asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
@@ -2439,7 +2476,7 @@ gst_asf_demux_add_audio_stream (GstASFDemux * demux,
++demux->num_audio_streams;
- return gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, tags);
+ return gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, NULL, tags);
}
static AsfStream *
@@ -2456,6 +2493,7 @@ gst_asf_demux_add_video_stream (GstASFDemux * demux,
gchar *name = NULL;
gchar *codec_name = NULL;
gint size_left = video->size - 40;
+ GstBuffer *streamheader = NULL;
/* Create the video pad */
name = g_strdup_printf ("video_%u", demux->num_video_streams);
@@ -2513,6 +2551,23 @@ gst_asf_demux_add_video_stream (GstASFDemux * demux,
str = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
g_free (str);
+
+ /* check if h264 has codec_data (avc) or streamheaders (bytestream) */
+ } else if (gst_structure_has_name (caps_s, "video/x-h264")) {
+ const GValue *value = gst_structure_get_value (caps_s, "codec_data");
+ GstBuffer *buf = gst_value_get_buffer (value);
+ GstMapInfo mapinfo;
+
+ if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
+ if (mapinfo.size >= 4 && GST_READ_UINT32_BE (mapinfo.data) == 1) {
+ /* this looks like a bytestream start */
+ streamheader = gst_buffer_ref (buf);
+ gst_asf_demux_add_stream_headers_to_caps (demux, buf, caps_s);
+ gst_structure_remove_field (caps_s, "codec_data");
+ }
+
+ gst_buffer_unmap (buf, &mapinfo);
+ }
}
if (codec_name) {
@@ -2529,7 +2584,8 @@ gst_asf_demux_add_video_stream (GstASFDemux * demux,
++demux->num_video_streams;
- return gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
+ return gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE,
+ streamheader, tags);
}
static void
diff --git a/gst/asfdemux/gstasfdemux.h b/gst/asfdemux/gstasfdemux.h
index 46e1e13c..6ef8c560 100644
--- a/gst/asfdemux/gstasfdemux.h
+++ b/gst/asfdemux/gstasfdemux.h
@@ -96,9 +96,12 @@ typedef struct
GstCaps *caps;
+ GstBuffer *streamheader;
+
GstTagList *pending_tags;
gboolean discont;
+ gboolean first_buffer;
/* Descrambler settings */
guint8 span;