gst/asfdemux/: Some clean-ups and small fixes: rename asf_stream_context structure to

Original commit message from CVS:
* gst/asfdemux/asfheaders.h:
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_free_stream),
(gst_asf_demux_seek_index_lookup),
(gst_asf_demux_handle_seek_event), (gst_asf_demux_get_stream),
(gst_asf_demux_setup_pad), (gst_asf_demux_add_video_stream),
(gst_asf_demux_process_ext_content_desc),
(gst_asf_demux_process_file), (gst_asf_demux_descramble_segment),
(gst_asf_demux_push_buffer), (gst_asf_demux_process_chunk),
(gst_asf_demux_process_segment), (gst_asf_demux_handle_data):
* gst/asfdemux/gstasfdemux.h:
Some clean-ups and small fixes: rename asf_stream_context structure to
AsfStream; inline some three-line utility functions that are only used
once anyway and get rid of their associated helper structs; make debug
category global so that it is used by the debug statements in the other
file as well; simplify gst_asf_demux_get_stream(); fix accidental
implicit initialisation of stream->last_buffer_timestamp to 0, which
would lead to missing timestamps on the first buffer; put fourcc format
into video caps to make certain proprietary wmv decoders happy (for the
case of WMVA in particular); play_time is offset by preroll as well, so
fix overreporting of duration for some files.
This commit is contained in:
Tim-Philipp Müller 2007-04-20 17:32:00 +00:00
parent 9ff45f3d88
commit 07f692085f
5 changed files with 90 additions and 73 deletions

View file

@ -1,3 +1,26 @@
2007-04-20 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_seek_index_lookup),
(gst_asf_demux_handle_seek_event), (gst_asf_demux_get_stream),
(gst_asf_demux_setup_pad), (gst_asf_demux_add_video_stream),
(gst_asf_demux_process_ext_content_desc),
(gst_asf_demux_process_file), (gst_asf_demux_descramble_segment),
(gst_asf_demux_push_buffer), (gst_asf_demux_process_chunk),
(gst_asf_demux_process_segment), (gst_asf_demux_handle_data):
* gst/asfdemux/gstasfdemux.h:
Some clean-ups and small fixes: rename asf_stream_context structure to
AsfStream; inline some three-line utility functions that are only used
once anyway and get rid of their associated helper structs; make debug
category global so that it is used by the debug statements in the other
file as well; simplify gst_asf_demux_get_stream(); fix accidental
implicit initialisation of stream->last_buffer_timestamp to 0, which
would lead to missing timestamps on the first buffer; put fourcc format
into video caps to make certain proprietary wmv decoders happy (for the
case of WMVA in particular); play_time is offset by preroll as well, so
fix overreporting of duration for some files.
2007-04-17 Tim-Philipp Müller <tim at centricular dot net> 2007-04-17 Tim-Philipp Müller <tim at centricular dot net>
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_handle_seek_event), * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_handle_seek_event),

2
common

@ -1 +1 @@
Subproject commit 9097e252e477e18182f08a032d8860bdee9a0416 Subproject commit 765d03a88492fb4ac81d70457f671f3a109e93de

View file

@ -174,13 +174,6 @@ struct _asf_obj_data_correction {
typedef struct _asf_obj_data_correction asf_obj_data_correction; typedef struct _asf_obj_data_correction asf_obj_data_correction;
struct _asf_obj_data_packet {
guint8 flags;
guint8 property;
};
typedef struct _asf_obj_data_packet asf_obj_data_packet;
struct _asf_packet_info { struct _asf_packet_info {
guint32 padsize; guint32 padsize;
guint8 replicsizetype; guint8 replicsizetype;
@ -205,11 +198,4 @@ struct _asf_segment_info {
typedef struct _asf_segment_info asf_segment_info; typedef struct _asf_segment_info asf_segment_info;
struct _asf_replicated_data {
guint32 object_size;
guint32 frag_timestamp;
};
typedef struct _asf_replicated_data asf_replicated_data;
#endif /* __ASFHEADERS_H__ */ #endif /* __ASFHEADERS_H__ */

View file

@ -76,8 +76,7 @@ GST_STATIC_PAD_TEMPLATE ("video_%02d",
(flow == ASF_FLOW_NEED_MORE_DATA) ? \ (flow == ASF_FLOW_NEED_MORE_DATA) ? \
"need-more-data" : gst_flow_get_name (flow) "need-more-data" : gst_flow_get_name (flow)
GST_DEBUG_CATEGORY_STATIC (asf_debug); GST_DEBUG_CATEGORY (asf_debug);
#define GST_CAT_DEFAULT asf_debug
static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element, static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element,
GstStateChange transition); GstStateChange transition);
@ -144,7 +143,7 @@ gst_asf_demux_class_init (GstASFDemuxClass * klass)
} }
static void static void
gst_asf_demux_free_stream (GstASFDemux * demux, asf_stream_context * stream) gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
{ {
gst_buffer_replace (&stream->cache, NULL); gst_buffer_replace (&stream->cache, NULL);
gst_buffer_replace (&stream->payload, NULL); gst_buffer_replace (&stream->payload, NULL);
@ -336,8 +335,9 @@ gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
*packet = demux->sidx_entries[idx]; *packet = demux->sidx_entries[idx];
GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u", GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
GST_TIME_ARGS (seek_time), *packet); GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
GST_TIME_ARGS (demux->sidx_interval * idx));
return TRUE; return TRUE;
} }
@ -440,6 +440,8 @@ gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
seek_time = segment.start; seek_time = segment.start;
/* FIXME: should check the KEY_UNIT flag; need to adjust last_stop to
* real start of data and segment_start to indexed time for key unit seek*/
if (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time)) { if (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time)) {
/* Hackety hack, this sucks. We just seek to an earlier position /* Hackety hack, this sucks. We just seek to an earlier position
* and let the sinks throw away the stuff before the segment start */ * and let the sinks throw away the stuff before the segment start */
@ -1183,18 +1185,6 @@ gst_asf_demux_get_obj_stream (asf_obj_stream * stream, guint8 ** p_data,
return TRUE; return TRUE;
} }
static gboolean
gst_asf_demux_get_replicated_data (asf_replicated_data * rep, guint8 ** p_data,
guint64 * p_size)
{
if (*p_size < (4 + 4))
return FALSE;
rep->object_size = gst_asf_demux_get_uint32 (p_data, p_size);
rep->frag_timestamp = gst_asf_demux_get_uint32 (p_data, p_size);
return TRUE;
}
static gboolean static gboolean
gst_asf_demux_get_obj_data_correction (asf_obj_data_correction * object, gst_asf_demux_get_obj_data_correction (asf_obj_data_correction * object,
guint8 ** p_data, guint64 * p_size) guint8 ** p_data, guint64 * p_size)
@ -1261,23 +1251,17 @@ gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
return TRUE; return TRUE;
} }
static asf_stream_context * AsfStream *
gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id) gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
{ {
guint8 i; guint i;
asf_stream_context *stream;
for (i = 0; i < demux->num_streams; i++) { for (i = 0; i < demux->num_streams; i++) {
stream = &demux->stream[i]; if (demux->stream[i].id == id)
if (stream->id == id) {
/* We've found the one with the matching id */
return &demux->stream[i]; return &demux->stream[i];
}
} }
/* Base case if we haven't found one at all */
GST_WARNING ("Segment found for undefined stream: (%d)", id); GST_WARNING ("Segment found for undefined stream: (%d)", id);
return NULL; return NULL;
} }
@ -1301,7 +1285,7 @@ static void
gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad, 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, GstTagList * tags)
{ {
asf_stream_context *stream; AsfStream *stream;
gst_pad_use_fixed_caps (src_pad); gst_pad_use_fixed_caps (src_pad);
gst_pad_set_caps (src_pad, caps); gst_pad_set_caps (src_pad, caps);
@ -1322,6 +1306,7 @@ gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
stream->delay = 0; stream->delay = 0;
stream->first_pts = GST_CLOCK_TIME_NONE; stream->first_pts = GST_CLOCK_TIME_NONE;
stream->last_pts = GST_CLOCK_TIME_NONE; stream->last_pts = GST_CLOCK_TIME_NONE;
stream->last_buffer_timestamp = GST_CLOCK_TIME_NONE;
stream->fps_known = !is_video; /* bit hacky for audio */ stream->fps_known = !is_video; /* bit hacky for audio */
stream->is_video = is_video; stream->is_video = is_video;
stream->pending_tags = tags; stream->pending_tags = tags;
@ -1442,6 +1427,9 @@ gst_asf_demux_add_video_stream (GstASFDemux * demux,
GST_TYPE_FOURCC, video->tag, NULL); GST_TYPE_FOURCC, video->tag, NULL);
} }
/* add fourcc format to caps, some proprietary decoders seem to need it */
gst_caps_set_simple (caps, "format", GST_TYPE_FOURCC, video->tag, NULL);
if (codec_name) { if (codec_name) {
tags = gst_tag_list_new (); tags = gst_tag_list_new ();
gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC, gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
@ -1766,6 +1754,7 @@ gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
} else { } else {
g_value_init (&tag_value, G_TYPE_STRING); g_value_init (&tag_value, G_TYPE_STRING);
g_value_set_string (&tag_value, value_utf8); g_value_set_string (&tag_value, value_utf8);
/* FIXME: convert to target value type if required */
} }
} else if (value_utf8 == NULL) { } else if (value_utf8 == NULL) {
GST_WARNING ("Failed to convert string value to UTF8, skipping"); GST_WARNING ("Failed to convert string value to UTF8, skipping");
@ -1893,7 +1882,10 @@ gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
demux->packet_size = max_pktsize; demux->packet_size = max_pktsize;
/* FIXME: do we need send_time as well? what is it? */ /* FIXME: do we need send_time as well? what is it? */
demux->play_time = (guint64) play_time *(GST_SECOND / 10000000); if ((play_time * 100) >= (preroll * GST_MSECOND))
demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
else
demux->play_time = 0;
demux->preroll = preroll; demux->preroll = preroll;
@ -1902,7 +1894,8 @@ gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
GST_DEBUG_OBJECT (demux, GST_DEBUG_OBJECT (demux,
"play_time %" GST_TIME_FORMAT " preroll %" GST_TIME_FORMAT, "play_time %" GST_TIME_FORMAT " preroll %" GST_TIME_FORMAT,
GST_TIME_ARGS (demux->play_time), GST_TIME_ARGS (demux->preroll)); GST_TIME_ARGS (demux->play_time),
GST_TIME_ARGS (demux->preroll * GST_MSECOND));
if (demux->play_time > 0) { if (demux->play_time > 0) {
gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME, gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME,
@ -2556,7 +2549,7 @@ error_encrypted:
static void static void
gst_asf_demux_descramble_segment (GstASFDemux * demux, gst_asf_demux_descramble_segment (GstASFDemux * demux,
asf_segment_info * segment_info, asf_stream_context * stream) asf_segment_info * segment_info, AsfStream * stream)
{ {
GstBuffer *scrambled_buffer; GstBuffer *scrambled_buffer;
GstBuffer *descrambled_buffer; GstBuffer *descrambled_buffer;
@ -2644,7 +2637,7 @@ gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
} }
static GstFlowReturn static GstFlowReturn
gst_asf_demux_push_buffer (GstASFDemux * demux, asf_stream_context * stream, gst_asf_demux_push_buffer (GstASFDemux * demux, AsfStream * stream,
GstBuffer * buf) GstBuffer * buf)
{ {
GstFlowReturn ret; GstFlowReturn ret;
@ -2703,7 +2696,7 @@ gst_asf_demux_process_chunk (GstASFDemux * demux,
guint8 ** p_data, guint64 * p_size) guint8 ** p_data, guint64 * p_size)
{ {
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
asf_stream_context *stream; AsfStream *stream;
GstBuffer *buffer; GstBuffer *buffer;
stream = gst_asf_demux_get_stream (demux, segment_info->stream_number); stream = gst_asf_demux_get_stream (demux, segment_info->stream_number);
@ -2931,7 +2924,7 @@ gst_asf_demux_process_segment (GstASFDemux * demux,
/* FIXME: check (doesn't work) */ /* FIXME: check (doesn't work) */
#if 0 #if 0
{ {
asf_stream_context *stream; AsfStream *stream;
stream = gst_asf_demux_get_stream (demux, segment_info.stream_number); stream = gst_asf_demux_get_stream (demux, segment_info.stream_number);
if (stream && stream->last_pts == GST_CLOCK_TIME_NONE && if (stream && stream->last_pts == GST_CLOCK_TIME_NONE &&
@ -2971,38 +2964,35 @@ gst_asf_demux_process_segment (GstASFDemux * demux,
segment_info.sequence, segment_info.frag_offset, replic_size); segment_info.sequence, segment_info.frag_offset, replic_size);
if (replic_size > 1) { if (replic_size > 1) {
asf_replicated_data replicated_data_header;
segment_info.compressed = FALSE; segment_info.compressed = FALSE;
/* It's uncompressed with replic data */ /* It's uncompressed with replic data */
if (!gst_asf_demux_get_replicated_data (&replicated_data_header, p_data, if (*p_size < (4 + 4))
p_size)) goto short_repdata;
return ASF_FLOW_NEED_MORE_DATA;
/* { segment_info.segment_size = gst_asf_demux_get_uint32 (p_data, p_size);
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), segment_info.frag_timestamp = gst_asf_demux_get_uint32 (p_data, p_size);
("The payload has replicated data but the size is less than 8"));
return GST_FLOW_ERROR; GST_LOG ("frag_timestamp: %" GST_TIME_FORMAT,
} GST_TIME_ARGS (segment_info.frag_timestamp * GST_MSECOND));
*/
segment_info.frag_timestamp = replicated_data_header.frag_timestamp;
segment_info.segment_size = replicated_data_header.object_size;
if (replic_size > 8) { if (replic_size > 8) {
if (!gst_asf_demux_skip_bytes ((replic_size - 8), p_data, p_size)) if (!gst_asf_demux_skip_bytes ((replic_size - 8), p_data, p_size))
return ASF_FLOW_NEED_MORE_DATA; return ASF_FLOW_NEED_MORE_DATA;
} }
} else if (replic_size == 1) {
/* It's compressed */
segment_info.compressed = TRUE;
if (*p_size < 1)
return ASF_FLOW_NEED_MORE_DATA;
time_delta = gst_asf_demux_get_uint8 (p_data, p_size);
GST_DEBUG ("time_delta = %u", time_delta);
time_start = segment_info.frag_offset;
segment_info.frag_offset = 0;
segment_info.frag_timestamp = time_start; /* was: demux->timestamp */
} else { } else {
if (replic_size == 1) { segment_info.compressed = FALSE;
/* It's compressed */
segment_info.compressed = TRUE;
if (*p_size < 1)
return ASF_FLOW_NEED_MORE_DATA;
time_delta = gst_asf_demux_get_uint8 (p_data, p_size);
GST_DEBUG ("time_delta = %u", time_delta);
} else {
segment_info.compressed = FALSE;
}
time_start = segment_info.frag_offset; time_start = segment_info.frag_offset;
segment_info.frag_offset = 0; segment_info.frag_offset = 0;
@ -3073,6 +3063,20 @@ gst_asf_demux_process_segment (GstASFDemux * demux,
} }
return ret; return ret;
/* ERRORS */
short_repdata:
{
if (replic_size < 8) {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
("payload has replicated data, but size is less than 8"));
} else {
GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
("payload has %u bytes of replicated data, but size is only %u",
replic_size, (guint) * p_size));
}
return GST_FLOW_ERROR;
}
} }
static GstFlowReturn static GstFlowReturn
@ -3168,6 +3172,7 @@ gst_asf_demux_handle_data (GstASFDemux * demux, guint8 ** p_data,
return ASF_FLOW_NEED_MORE_DATA; return ASF_FLOW_NEED_MORE_DATA;
} }
/* FIXME: isn't this the send time, ie. not the presentation time? (tpm) */
demux->timestamp = gst_asf_demux_get_uint32 (p_data, p_size); demux->timestamp = gst_asf_demux_get_uint32 (p_data, p_size);
duration = gst_asf_demux_get_uint16 (p_data, p_size); duration = gst_asf_demux_get_uint16 (p_data, p_size);

View file

@ -37,6 +37,9 @@ G_BEGIN_DECLS
#define GST_IS_ASF_DEMUX_CLASS(klass) \ #define GST_IS_ASF_DEMUX_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ASF_DEMUX)) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ASF_DEMUX))
GST_DEBUG_CATEGORY_EXTERN (asf_debug);
#define GST_CAT_DEFAULT asf_debug
typedef struct _GstASFDemux GstASFDemux; typedef struct _GstASFDemux GstASFDemux;
typedef struct _GstASFDemuxClass GstASFDemuxClass; typedef struct _GstASFDemuxClass GstASFDemuxClass;
@ -62,7 +65,7 @@ typedef struct
GstTagList *pending_tags; GstTagList *pending_tags;
gboolean discont; gboolean discont;
} asf_stream_context; } AsfStream;
typedef enum { typedef enum {
GST_ASF_DEMUX_STATE_HEADER, GST_ASF_DEMUX_STATE_HEADER,
@ -101,7 +104,7 @@ struct _GstASFDemux {
guint32 num_audio_streams; guint32 num_audio_streams;
guint32 num_video_streams; guint32 num_video_streams;
guint32 num_streams; guint32 num_streams;
asf_stream_context stream[GST_ASF_DEMUX_NUM_STREAMS]; AsfStream stream[GST_ASF_DEMUX_NUM_STREAMS];
guint32 packet_size; guint32 packet_size;
guint32 timestamp; /* in milliseconds */ guint32 timestamp; /* in milliseconds */