mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 15:27:07 +00:00
gst/asfdemux/: Refactor stream parse/activation a bit (stream activation heuristics are still the same though); some ...
Original commit message from CVS: * gst/asfdemux/asfheaders.h: * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_free_stream), (gst_asf_demux_reset), (gst_asf_demux_parse_data_object_start), (gst_asf_demux_loop), (gst_asf_demux_setup_pad), (gst_asf_demux_add_audio_stream), (gst_asf_demux_activate_stream), (gst_asf_demux_parse_stream_object), (gst_asf_demux_process_ext_stream_props), (gst_asf_demux_process_queued_extended_stream_objects), (gst_asf_demux_activate_ext_props_streams), (gst_asf_demux_process_object): * gst/asfdemux/gstasfdemux.h: Refactor stream parse/activation a bit (stream activation heuristics are still the same though); some more clean-ups.
This commit is contained in:
parent
9ca32166b2
commit
850c0fbab8
5 changed files with 244 additions and 190 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
2007-04-30 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* gst/asfdemux/asfheaders.h:
|
||||
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_free_stream),
|
||||
(gst_asf_demux_reset), (gst_asf_demux_parse_data_object_start),
|
||||
(gst_asf_demux_loop), (gst_asf_demux_setup_pad),
|
||||
(gst_asf_demux_add_audio_stream), (gst_asf_demux_activate_stream),
|
||||
(gst_asf_demux_parse_stream_object),
|
||||
(gst_asf_demux_process_ext_stream_props),
|
||||
(gst_asf_demux_process_queued_extended_stream_objects),
|
||||
(gst_asf_demux_activate_ext_props_streams),
|
||||
(gst_asf_demux_process_object):
|
||||
* gst/asfdemux/gstasfdemux.h:
|
||||
Refactor stream parse/activation a bit (stream activation heuristics
|
||||
are still the same though); some more clean-ups.
|
||||
|
||||
2007-04-28 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* win32/common/.cvsignore:
|
||||
|
|
2
common
2
common
|
@ -1 +1 @@
|
|||
Subproject commit a19d235c89d99ca7849078d501129f521e30d98d
|
||||
Subproject commit 61edc2dc7b8eba179d85a6545e46e0d65239e94d
|
|
@ -20,6 +20,8 @@
|
|||
#ifndef __ASFHEADERS_H__
|
||||
#define __ASFHEADERS_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
guint32 v1;
|
||||
guint32 v2;
|
||||
|
@ -68,17 +70,17 @@ typedef enum {
|
|||
ASF_OBJ_MARKER
|
||||
} AsfObjectID;
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
ASF_STREAM_UNDEFINED = 0,
|
||||
ASF_STREAM_VIDEO,
|
||||
ASF_STREAM_AUDIO
|
||||
};
|
||||
} AsfStreamType;
|
||||
|
||||
enum {
|
||||
typedef enum {
|
||||
ASF_CORRECTION_UNDEFINED = 0,
|
||||
ASF_CORRECTION_ON,
|
||||
ASF_CORRECTION_OFF
|
||||
};
|
||||
} AsfCorrectionType;
|
||||
|
||||
extern const ASFGuidHash asf_correction_guids[];
|
||||
|
||||
|
@ -93,43 +95,6 @@ guint32 gst_asf_identify_guid (const ASFGuidHash * guids,
|
|||
const gchar *gst_asf_get_guid_nick (const ASFGuidHash * guids,
|
||||
guint32 obj_id);
|
||||
|
||||
struct _asf_obj_ext_stream_properties {
|
||||
guint64 start_time;
|
||||
guint64 end_time;
|
||||
guint64 avg_time_per_frame;
|
||||
guint32 data_bitrate;
|
||||
guint32 buffer_size;
|
||||
guint32 intial_buf_fullness;
|
||||
guint32 data_bitrate2;
|
||||
guint32 buffer_size2;
|
||||
guint32 intial_buf_fullness2;
|
||||
guint32 max_obj_size;
|
||||
guint32 flags;
|
||||
guint16 stream_num;
|
||||
guint16 lang_idx;
|
||||
/* missing: stream names */
|
||||
/* missing: payload extension system stuff */
|
||||
|
||||
/* for delayed processing of these stream objects */
|
||||
guint8 *stream_obj_data;
|
||||
guint64 stream_obj_len;
|
||||
};
|
||||
|
||||
typedef struct _asf_obj_ext_stream_properties asf_obj_ext_stream_properties;
|
||||
|
||||
struct _asf_obj_stream {
|
||||
ASFGuid type;
|
||||
ASFGuid correction;
|
||||
guint64 time_offset;
|
||||
guint32 type_specific_size;
|
||||
guint32 stream_specific_size;
|
||||
guint8 id;
|
||||
guint8 encrypted;
|
||||
guint32 unknown2;
|
||||
};
|
||||
|
||||
typedef struct _asf_obj_stream asf_obj_stream;
|
||||
|
||||
struct _asf_stream_audio {
|
||||
guint16 codec_tag;
|
||||
guint16 channels;
|
||||
|
@ -198,4 +163,6 @@ struct _asf_segment_info {
|
|||
|
||||
typedef struct _asf_segment_info asf_segment_info;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __ASFHEADERS_H__ */
|
||||
|
|
|
@ -97,6 +97,7 @@ static gboolean gst_asf_demux_activate_pull (GstPad * sinkpad, gboolean active);
|
|||
static void gst_asf_demux_loop (GstASFDemux * demux);
|
||||
static void
|
||||
gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
|
||||
static void gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux);
|
||||
static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux);
|
||||
static void gst_asf_demux_pull_indices (GstASFDemux * demux);
|
||||
static GstFlowReturn gst_asf_demux_handle_data (GstASFDemux * demux,
|
||||
|
@ -154,7 +155,10 @@ gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
|
|||
stream->pending_tags = NULL;
|
||||
}
|
||||
if (stream->pad) {
|
||||
gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
|
||||
if (stream->active)
|
||||
gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
|
||||
else
|
||||
gst_object_unref (stream->pad);
|
||||
stream->pad = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +185,8 @@ gst_asf_demux_reset (GstASFDemux * demux)
|
|||
g_strfreev (demux->languages);
|
||||
demux->languages = NULL;
|
||||
demux->num_languages = 0;
|
||||
g_slist_foreach (demux->ext_stream_props, (GFunc) g_free, NULL);
|
||||
g_slist_foreach (demux->ext_stream_props, (GFunc) gst_mini_object_unref,
|
||||
NULL);
|
||||
g_slist_free (demux->ext_stream_props);
|
||||
demux->ext_stream_props = NULL;
|
||||
while (demux->num_streams > 0) {
|
||||
|
@ -844,6 +849,7 @@ gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data)
|
|||
|
||||
/* process pending stream objects and create pads for those */
|
||||
gst_asf_demux_process_queued_extended_stream_objects (demux);
|
||||
gst_asf_demux_activate_ext_props_streams (demux);
|
||||
gst_element_no_more_pads (GST_ELEMENT (demux));
|
||||
|
||||
GST_INFO_OBJECT (demux, "Stream has %" G_GUINT64_FORMAT " packets, "
|
||||
|
@ -1038,11 +1044,8 @@ gst_asf_demux_loop (GstASFDemux * demux)
|
|||
|
||||
/* FIXME: maybe we should just skip broken packets and error out only
|
||||
* after a few broken packets in a row? */
|
||||
if (!gst_asf_demux_parse_packet (demux, buf)) {
|
||||
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
|
||||
("Error parsing ASF packet %u", (guint) demux->packet));
|
||||
flow = GST_FLOW_ERROR;
|
||||
}
|
||||
if (!gst_asf_demux_parse_packet (demux, buf))
|
||||
goto parse_error;
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
|
@ -1102,6 +1105,14 @@ read_failed:
|
|||
gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
|
||||
goto pause;
|
||||
}
|
||||
parse_error:
|
||||
{
|
||||
gst_buffer_unref (buf);
|
||||
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
|
||||
("Error parsing ASF packet %u", (guint) demux->packet));
|
||||
gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
|
||||
goto pause;
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
|
@ -1271,28 +1282,6 @@ gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
|
|||
guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_asf_demux_get_obj_stream (asf_obj_stream * stream, guint8 ** p_data,
|
||||
guint64 * p_size)
|
||||
{
|
||||
guint16 flags;
|
||||
|
||||
if (*p_size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
|
||||
return FALSE;
|
||||
|
||||
gst_asf_demux_get_guid (&stream->type, p_data, p_size);
|
||||
gst_asf_demux_get_guid (&stream->correction, p_data, p_size);
|
||||
|
||||
stream->time_offset = gst_asf_demux_get_uint64 (p_data, p_size) * 100;
|
||||
stream->type_specific_size = gst_asf_demux_get_uint32 (p_data, p_size);
|
||||
stream->stream_specific_size = gst_asf_demux_get_uint32 (p_data, p_size);
|
||||
flags = gst_asf_demux_get_uint16 (p_data, p_size);
|
||||
stream->id = flags & 0x7f;
|
||||
stream->encrypted = (flags & 0x8000) << 15;
|
||||
stream->unknown2 = gst_asf_demux_get_uint32 (p_data, p_size);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_asf_demux_get_obj_data_correction (asf_obj_data_correction * object,
|
||||
guint8 ** p_data, guint64 * p_size)
|
||||
|
@ -1373,22 +1362,6 @@ gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static asf_obj_ext_stream_properties *
|
||||
gst_asf_demux_get_ext_stream_props_for_stream (GstASFDemux * demux, gint id)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = demux->ext_stream_props; l != NULL; l = l->next) {
|
||||
asf_obj_ext_stream_properties *esp;
|
||||
|
||||
esp = (asf_obj_ext_stream_properties *) l->data;
|
||||
if (esp->stream_num == id)
|
||||
return esp;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
|
||||
GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
|
||||
|
@ -1422,22 +1395,18 @@ gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
|
|||
|
||||
stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
|
||||
|
||||
|
||||
gst_pad_set_element_private (src_pad, stream);
|
||||
|
||||
GST_INFO ("Adding pad %s for stream %u with caps %" GST_PTR_FORMAT,
|
||||
GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
|
||||
GST_PAD_NAME (src_pad), demux->num_streams, caps);
|
||||
|
||||
++demux->num_streams;
|
||||
gst_pad_set_active (src_pad, TRUE);
|
||||
gst_element_add_pad (GST_ELEMENT (demux), src_pad);
|
||||
|
||||
stream->active = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_asf_demux_add_audio_stream (GstASFDemux * demux,
|
||||
asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
|
||||
{
|
||||
asf_obj_ext_stream_properties *ext_props;
|
||||
GstTagList *tags = NULL;
|
||||
GstBuffer *extradata = NULL;
|
||||
GstPad *src_pad;
|
||||
|
@ -1482,20 +1451,12 @@ gst_asf_demux_add_audio_stream (GstASFDemux * demux,
|
|||
g_free (codec_name);
|
||||
}
|
||||
|
||||
/* add language info if we have it */
|
||||
ext_props = gst_asf_demux_get_ext_stream_props_for_stream (demux, id);
|
||||
if (ext_props && ext_props->lang_idx < demux->num_languages) {
|
||||
if (tags == NULL)
|
||||
tags = gst_tag_list_new ();
|
||||
gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE,
|
||||
demux->languages[ext_props->lang_idx], NULL);
|
||||
}
|
||||
|
||||
if (extradata)
|
||||
gst_buffer_unref (extradata);
|
||||
|
||||
GST_INFO ("Adding audio stream %u codec %u (0x%04x), tags=%" GST_PTR_FORMAT,
|
||||
demux->num_video_streams, audio->codec_tag, audio->codec_tag, tags);
|
||||
GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
|
||||
GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
|
||||
audio->codec_tag, tags);
|
||||
|
||||
++demux->num_audio_streams;
|
||||
|
||||
|
@ -1561,25 +1522,57 @@ gst_asf_demux_add_video_stream (GstASFDemux * demux,
|
|||
gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_asf_demux_process_stream (GstASFDemux * demux, guint8 * data, guint64 size)
|
||||
static void
|
||||
gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
|
||||
{
|
||||
asf_obj_stream object;
|
||||
guint32 stream_id;
|
||||
guint32 correction;
|
||||
if (!stream->active) {
|
||||
GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
|
||||
GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
|
||||
gst_pad_set_active (stream->pad, TRUE);
|
||||
gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
|
||||
stream->active = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
static AsfStream *
|
||||
gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
|
||||
guint64 size)
|
||||
{
|
||||
AsfCorrectionType correction_type;
|
||||
AsfStreamType stream_type;
|
||||
GstClockTime time_offset;
|
||||
gboolean is_encrypted;
|
||||
guint16 stream_id;
|
||||
guint16 flags;
|
||||
ASFGuid guid;
|
||||
guint stream_specific_size;
|
||||
guint type_specific_size;
|
||||
guint unknown;
|
||||
|
||||
/* Get the rest of the header's header */
|
||||
if (!gst_asf_demux_get_obj_stream (&object, &data, &size))
|
||||
if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
|
||||
goto not_enough_data;
|
||||
|
||||
GST_DEBUG ("Found stream #%u", object.id);
|
||||
gst_asf_demux_get_guid (&guid, &data, &size);
|
||||
stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
|
||||
|
||||
/* Identify the stream type */
|
||||
stream_id = gst_asf_demux_identify_guid (asf_stream_guids, &object.type);
|
||||
correction =
|
||||
gst_asf_demux_identify_guid (asf_correction_guids, &object.correction);
|
||||
gst_asf_demux_get_guid (&guid, &data, &size);
|
||||
correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
|
||||
|
||||
switch (stream_id) {
|
||||
time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
|
||||
|
||||
type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
|
||||
stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
|
||||
|
||||
flags = gst_asf_demux_get_uint16 (&data, &size);
|
||||
stream_id = flags & 0x7f;
|
||||
is_encrypted = !!((flags & 0x8000) << 15);
|
||||
unknown = gst_asf_demux_get_uint32 (&data, &size);
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
|
||||
stream_id, GST_TIME_ARGS (time_offset));
|
||||
|
||||
switch (stream_type) {
|
||||
case ASF_STREAM_AUDIO:{
|
||||
asf_stream_audio audio_object;
|
||||
|
||||
|
@ -1589,10 +1582,10 @@ gst_asf_demux_process_stream (GstASFDemux * demux, guint8 * data, guint64 size)
|
|||
GST_INFO ("Object is an audio stream with %u bytes of additional data",
|
||||
audio_object.size);
|
||||
|
||||
gst_asf_demux_add_audio_stream (demux, &audio_object, object.id,
|
||||
gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
|
||||
&data, &size);
|
||||
|
||||
switch (correction) {
|
||||
switch (correction_type) {
|
||||
case ASF_CORRECTION_ON:{
|
||||
guint span, packet_size, chunk_size, data_size, silence_data;
|
||||
|
||||
|
@ -1642,22 +1635,16 @@ gst_asf_demux_process_stream (GstASFDemux * demux, guint8 * data, guint64 size)
|
|||
#endif
|
||||
break;
|
||||
}
|
||||
case ASF_CORRECTION_OFF:
|
||||
case ASF_CORRECTION_OFF:{
|
||||
GST_INFO ("Error correction off");
|
||||
#if 0
|
||||
/* gst_bytestream_flush (demux->bs, object.stream_specific_size); */
|
||||
#else
|
||||
/* FIXME: CHECKME */
|
||||
if (!gst_asf_demux_skip_bytes (object.stream_specific_size,
|
||||
&data, &size)) {
|
||||
if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
|
||||
goto not_enough_data;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
|
||||
("Audio stream using unknown error correction"));
|
||||
return GST_FLOW_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1681,25 +1668,25 @@ gst_asf_demux_process_stream (GstASFDemux * demux, guint8 * data, guint64 size)
|
|||
goto not_enough_data;
|
||||
}
|
||||
|
||||
gst_asf_demux_add_video_stream (demux, &video_format_object, object.id,
|
||||
gst_asf_demux_add_video_stream (demux, &video_format_object, stream_id,
|
||||
&data, &size);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
GST_WARNING_OBJECT (demux, "Unknown asf stream (id %08x)",
|
||||
(guint) stream_id);
|
||||
GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
|
||||
stream_id);
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
return gst_asf_demux_get_stream (demux, stream_id);
|
||||
|
||||
not_enough_data:
|
||||
{
|
||||
GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
|
||||
/* pretend it's ok, we'll error out later if we found no streams */
|
||||
return GST_FLOW_OK;
|
||||
/* we'll error out later if we found no streams */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2338,20 +2325,23 @@ static GstFlowReturn
|
|||
gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
|
||||
guint64 size)
|
||||
{
|
||||
AsfStreamExtProps esp;
|
||||
AsfStream *stream = NULL;
|
||||
AsfObject stream_obj;
|
||||
asf_obj_ext_stream_properties esp = { 0, };
|
||||
guint16 stream_name_count;
|
||||
guint16 payload_ext_sys_count;
|
||||
guint64 len;
|
||||
guint8 *stream_obj_data = NULL;
|
||||
guint8 *data_start = data;
|
||||
guint obj_size = (guint) size;
|
||||
guint i;
|
||||
guint i, stream_num;
|
||||
|
||||
if (size < 8 + 8 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + 2 + 2 + 8 + 2 + 2) /* 64 */
|
||||
if (size < 64)
|
||||
goto not_enough_data;
|
||||
|
||||
esp.start_time = gst_asf_demux_get_uint64 (&data, &size);
|
||||
esp.end_time = gst_asf_demux_get_uint64 (&data, &size);
|
||||
esp.valid = TRUE;
|
||||
esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
|
||||
esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
|
||||
esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
|
||||
esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
|
||||
esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
|
||||
|
@ -2360,20 +2350,20 @@ gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
|
|||
esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
|
||||
esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
|
||||
esp.flags = gst_asf_demux_get_uint32 (&data, &size);
|
||||
esp.stream_num = gst_asf_demux_get_uint16 (&data, &size);
|
||||
stream_num = gst_asf_demux_get_uint16 (&data, &size);
|
||||
esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
|
||||
esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
|
||||
esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size) * 100;
|
||||
stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
|
||||
payload_ext_sys_count = gst_asf_demux_get_uint16 (&data, &size);
|
||||
|
||||
GST_INFO ("start_time = %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (esp.start_time * GST_MSECOND));
|
||||
GST_TIME_ARGS (esp.start_time));
|
||||
GST_INFO ("end_time = %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (esp.end_time * GST_MSECOND));
|
||||
GST_TIME_ARGS (esp.end_time));
|
||||
GST_INFO ("flags = %08x", esp.flags);
|
||||
GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (esp.avg_time_per_frame * 100));
|
||||
GST_INFO ("stream number = %u", esp.stream_num);
|
||||
GST_TIME_ARGS (esp.avg_time_per_frame));
|
||||
GST_INFO ("stream number = %u", stream_num);
|
||||
GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
|
||||
(esp.lang_idx < demux->num_languages) ?
|
||||
GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
|
||||
|
@ -2408,9 +2398,13 @@ gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
|
|||
|
||||
GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
|
||||
|
||||
/* there might be an optional STREAM_INFO object here now */
|
||||
if (size == 0)
|
||||
/* there might be an optional STREAM_INFO object here now; if not, we
|
||||
* should have parsed the corresponding stream info object already (since
|
||||
* we are parsing the extended stream properties objects delayed) */
|
||||
if (size == 0) {
|
||||
stream = gst_asf_demux_get_stream (demux, stream_num);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* get size of the stream object */
|
||||
if (!asf_demux_peek_object (demux, data, size, &stream_obj))
|
||||
|
@ -2428,15 +2422,31 @@ gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
|
|||
/* process this stream object later after all the other 'normal' ones
|
||||
* have been processed (since the others are more important/non-hidden) */
|
||||
len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
|
||||
if (!gst_asf_demux_get_bytes (&esp.stream_obj_data, len, &data, &size))
|
||||
if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
|
||||
goto not_enough_data;
|
||||
|
||||
esp.stream_obj_len = len;
|
||||
/* parse stream object */
|
||||
stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
|
||||
g_free (stream_obj_data);
|
||||
|
||||
done:
|
||||
|
||||
demux->ext_stream_props = g_slist_append (demux->ext_stream_props,
|
||||
g_memdup (&esp, sizeof (esp)));
|
||||
if (stream) {
|
||||
stream->ext_props = esp;
|
||||
|
||||
/* add language info now if we have it */
|
||||
if (stream->ext_props.lang_idx < demux->num_languages) {
|
||||
if (stream->pending_tags == NULL)
|
||||
stream->pending_tags = gst_tag_list_new ();
|
||||
GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
|
||||
demux->languages[stream->ext_props.lang_idx]);
|
||||
gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
|
||||
GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
|
||||
|
@ -2493,37 +2503,66 @@ gst_asf_demux_pop_obj (GstASFDemux * demux)
|
|||
static void
|
||||
gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
|
||||
{
|
||||
GSList *l, *x;
|
||||
GSList *l;
|
||||
guint i;
|
||||
|
||||
GST_DEBUG_OBJECT (demux, "parsing %d stream objects embedded in extended "
|
||||
"stream properties", g_slist_length (demux->ext_stream_props));
|
||||
/* Parse the queued extended stream property objects and add the info
|
||||
* to the existing streams or add the new embedded streams, but without
|
||||
* activating them yet */
|
||||
GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
|
||||
g_slist_length (demux->ext_stream_props));
|
||||
|
||||
for (l = demux->ext_stream_props; l != NULL; l = l->next) {
|
||||
asf_obj_ext_stream_properties *esp;
|
||||
gboolean is_hidden = FALSE;
|
||||
guint8 *mes, i;
|
||||
for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
|
||||
GstBuffer *buf = GST_BUFFER (l->data);
|
||||
|
||||
esp = (asf_obj_ext_stream_properties *) l->data;
|
||||
GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
|
||||
gst_asf_demux_process_ext_stream_props (demux, GST_BUFFER_DATA (buf),
|
||||
GST_BUFFER_SIZE (buf));
|
||||
gst_buffer_unref (buf);
|
||||
}
|
||||
g_slist_free (demux->ext_stream_props);
|
||||
demux->ext_stream_props = NULL;
|
||||
}
|
||||
|
||||
GST_DEBUG ("Parsing queued extended stream with ID %d", esp->stream_num);
|
||||
static void
|
||||
gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
|
||||
{
|
||||
guint i, j;
|
||||
|
||||
for (i = 0; i < demux->num_streams; ++i) {
|
||||
AsfStream *stream;
|
||||
gboolean is_hidden;
|
||||
GSList *x;
|
||||
|
||||
stream = &demux->stream[i];
|
||||
|
||||
GST_LOG_OBJECT (demux, "checking stream %2u", stream->id);
|
||||
|
||||
if (stream->active) {
|
||||
GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
|
||||
continue;
|
||||
}
|
||||
|
||||
is_hidden = FALSE;
|
||||
for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
|
||||
guint8 *mes;
|
||||
|
||||
/* check for each mutual exclusion whether it affects this stream */
|
||||
for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
|
||||
if (*mes == esp->stream_num) {
|
||||
if (*mes == stream->id) {
|
||||
/* if yes, check if we've already added streams that are mutually
|
||||
* exclusive with the stream we're about to add */
|
||||
for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
|
||||
for (i = 0; i < demux->num_streams; ++i) {
|
||||
for (j = 0; j < demux->num_streams; ++j) {
|
||||
/* if the broadcast flag is set, assume the hidden streams aren't
|
||||
* actually streamed and hide them (or playbin won't work right),
|
||||
* otherwise assume their data is available */
|
||||
if (demux->stream[i].id == *mes && demux->broadcast) {
|
||||
if (demux->stream[j].id == *mes && demux->broadcast) {
|
||||
is_hidden = TRUE;
|
||||
GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
|
||||
"mutually exclusive with already existing stream ID %d, "
|
||||
"hiding stream", esp->stream_num, demux->stream[i].id);
|
||||
break;
|
||||
"hiding stream", stream->id, demux->stream[j].id);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2532,23 +2571,11 @@ gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
|
|||
}
|
||||
}
|
||||
|
||||
if (!is_hidden && esp->stream_obj_data != NULL) {
|
||||
guint64 len;
|
||||
guint8 *data;
|
||||
next:
|
||||
|
||||
data = esp->stream_obj_data;
|
||||
len = esp->stream_obj_len;
|
||||
|
||||
if (gst_asf_demux_process_stream (demux, data, len) != GST_FLOW_OK) {
|
||||
GST_WARNING_OBJECT (demux,
|
||||
"failed to parse stream object in extended "
|
||||
"stream properties object for stream %u", esp->stream_num);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (esp->stream_obj_data);
|
||||
esp->stream_obj_data = NULL;
|
||||
esp->stream_obj_data = 0;
|
||||
/* FIXME: we should do stream activation based on preroll data */
|
||||
if (!is_hidden)
|
||||
gst_asf_demux_activate_stream (demux, stream);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2576,9 +2603,16 @@ gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
|
|||
GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
|
||||
|
||||
switch (obj.id) {
|
||||
case ASF_OBJ_STREAM:
|
||||
ret = gst_asf_demux_process_stream (demux, *p_data, obj_data_size);
|
||||
case ASF_OBJ_STREAM:{
|
||||
AsfStream *stream;
|
||||
|
||||
stream =
|
||||
gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
|
||||
if (stream)
|
||||
gst_asf_demux_activate_stream (demux, stream);
|
||||
ret = GST_FLOW_OK;
|
||||
break;
|
||||
}
|
||||
case ASF_OBJ_FILE:
|
||||
ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
|
||||
break;
|
||||
|
@ -2601,11 +2635,18 @@ gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
|
|||
gst_asf_demux_process_ext_content_desc (demux, *p_data,
|
||||
obj_data_size);
|
||||
break;
|
||||
case ASF_OBJ_EXTENDED_STREAM_PROPS:
|
||||
ret =
|
||||
gst_asf_demux_process_ext_stream_props (demux, *p_data,
|
||||
obj_data_size);
|
||||
case ASF_OBJ_EXTENDED_STREAM_PROPS:{
|
||||
GstBuffer *buf;
|
||||
|
||||
/* process these later, we might not have parsed the corresponding
|
||||
* stream object yet */
|
||||
GST_LOG ("%s: queued for later parsing", demux->objpath);
|
||||
buf = gst_buffer_new_and_alloc (obj_data_size);
|
||||
memcpy (GST_BUFFER_DATA (buf), *p_data, obj_data_size);
|
||||
demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
|
||||
ret = GST_FLOW_OK;
|
||||
break;
|
||||
}
|
||||
case ASF_OBJ_LANGUAGE_LIST:
|
||||
ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
|
||||
break;
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#include <gst/gst.h>
|
||||
#include <gst/base/gstadapter.h>
|
||||
|
||||
#include "asfheaders.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GST_TYPE_ASF_DEMUX \
|
||||
|
@ -45,6 +47,31 @@ typedef struct _GstASFDemuxClass GstASFDemuxClass;
|
|||
|
||||
typedef struct
|
||||
{
|
||||
gboolean valid; /* TRUE if structure is valid/filled */
|
||||
|
||||
GstClockTime start_time;
|
||||
GstClockTime end_time;
|
||||
GstClockTime avg_time_per_frame;
|
||||
guint32 data_bitrate;
|
||||
guint32 buffer_size;
|
||||
guint32 intial_buf_fullness;
|
||||
guint32 data_bitrate2;
|
||||
guint32 buffer_size2;
|
||||
guint32 intial_buf_fullness2;
|
||||
guint32 max_obj_size;
|
||||
guint32 flags;
|
||||
guint16 lang_idx;
|
||||
|
||||
/* missing: stream names */
|
||||
/* missing: payload extension system stuff */
|
||||
} AsfStreamExtProps;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AsfStreamType type;
|
||||
|
||||
gboolean active; /* if the stream has been activated (pad added) */
|
||||
|
||||
GstPad *pad;
|
||||
guint16 id;
|
||||
guint32 frag_offset;
|
||||
|
@ -70,6 +97,9 @@ typedef struct
|
|||
GstFlowReturn last_flow; /* last flow return */
|
||||
GArray *payloads; /* pending payloads */
|
||||
|
||||
/* extended stream properties (optional) */
|
||||
AsfStreamExtProps ext_props;
|
||||
|
||||
} AsfStream;
|
||||
|
||||
typedef enum {
|
||||
|
@ -103,8 +133,8 @@ struct _GstASFDemux {
|
|||
gchar **languages;
|
||||
guint num_languages;
|
||||
|
||||
GSList *ext_stream_props;
|
||||
GSList *mut_ex_streams; /* mutually exclusive streams */
|
||||
GSList *ext_stream_props; /* for delayed processing (buffers) */
|
||||
GSList *mut_ex_streams; /* mutually exclusive streams */
|
||||
|
||||
guint32 num_audio_streams;
|
||||
guint32 num_video_streams;
|
||||
|
|
Loading…
Reference in a new issue