gst/asfdemux/gstasfdemux.*: You know Chimaira? "I - HATE - EVERYTHING". Yeah, that's what this feels like. I think we...

Original commit message from CVS:
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_init),
(gst_asf_demux_loop), (gst_asf_demux_process_file),
(gst_asf_demux_process_data), (gst_asf_demux_handle_data),
(gst_asf_demux_process_object), (gst_asf_demux_get_stream),
(gst_asf_demux_process_chunk), (gst_asf_demux_handle_sink_event),
(gst_asf_demux_handle_src_event), (gst_asf_demux_handle_src_query),
(gst_asf_demux_change_state):
* gst/asfdemux/gstasfdemux.h:
You know Chimaira? "I - HATE - EVERYTHING". Yeah, that's what this
feels like. I think we should set a new requirement for demuxers
from now on to implement sane loop functions, data loops, query
and seek functions before first commit into CVS. And this commit
fixes all of the above.
This commit is contained in:
Ronald S. Bultje 2004-06-10 04:23:03 +00:00
parent 6929876d74
commit 318d8ac686
3 changed files with 261 additions and 119 deletions

View file

@ -1,3 +1,19 @@
2004-06-10 Ronald Bultje <rbultje@ronald.bitfreak.net>
* gst/asfdemux/gstasfdemux.c: (gst_asf_demux_init),
(gst_asf_demux_loop), (gst_asf_demux_process_file),
(gst_asf_demux_process_data), (gst_asf_demux_handle_data),
(gst_asf_demux_process_object), (gst_asf_demux_get_stream),
(gst_asf_demux_process_chunk), (gst_asf_demux_handle_sink_event),
(gst_asf_demux_handle_src_event), (gst_asf_demux_handle_src_query),
(gst_asf_demux_change_state):
* gst/asfdemux/gstasfdemux.h:
You know Chimaira? "I - HATE - EVERYTHING". Yeah, that's what this
feels like. I think we should set a new requirement for demuxers
from now on to implement sane loop functions, data loops, query
and seek functions before first commit into CVS. And this commit
fixes all of the above.
2004-06-10 Christophe Fergeau <teuf@gnome.org> 2004-06-10 Christophe Fergeau <teuf@gnome.org>
* gst/tags/gstvorbistag.c: (gst_vorbis_tag_add): make sure parsed * gst/tags/gstvorbistag.c: (gst_vorbis_tag_add): make sure parsed

View file

@ -45,6 +45,7 @@ static void gst_asf_demux_init (GstASFDemux * asf_demux);
static gboolean gst_asf_demux_send_event (GstElement * element, static gboolean gst_asf_demux_send_event (GstElement * element,
GstEvent * event); GstEvent * event);
static void gst_asf_demux_loop (GstElement * element); static void gst_asf_demux_loop (GstElement * element);
static gboolean gst_asf_demux_handle_data (GstASFDemux * asf_demux);
static gboolean gst_asf_demux_process_object (GstASFDemux * asf_demux); static gboolean gst_asf_demux_process_object (GstASFDemux * asf_demux);
static void gst_asf_demux_get_property (GObject * object, static void gst_asf_demux_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec); guint prop_id, GValue * value, GParamSpec * pspec);
@ -210,6 +211,10 @@ gst_asf_demux_init (GstASFDemux * asf_demux)
asf_demux->num_video_streams = 0; asf_demux->num_video_streams = 0;
asf_demux->num_streams = 0; asf_demux->num_streams = 0;
asf_demux->state = GST_ASF_DEMUX_STATE_HEADER;
asf_demux->seek_pending = GST_CLOCK_TIME_NONE;
asf_demux->seek_discont = FALSE;
GST_FLAG_SET (asf_demux, GST_ELEMENT_EVENT_AWARE); GST_FLAG_SET (asf_demux, GST_ELEMENT_EVENT_AWARE);
} }
@ -251,7 +256,20 @@ gst_asf_demux_loop (GstElement * element)
asf_demux = GST_ASF_DEMUX (element); asf_demux = GST_ASF_DEMUX (element);
/* this is basically an infinite loop */ /* this is basically an infinite loop */
switch (asf_demux->state) {
case GST_ASF_DEMUX_STATE_HEADER:
gst_asf_demux_process_object (asf_demux); gst_asf_demux_process_object (asf_demux);
break;
case GST_ASF_DEMUX_STATE_DATA:
gst_asf_demux_handle_data (asf_demux);
break;
case GST_ASF_DEMUX_STATE_EOS:
gst_pad_event_default (asf_demux->sinkpad, gst_event_new (GST_EVENT_EOS));
break;
default:
g_assert_not_reached ();
break;
}
} }
static guint32 static guint32
@ -485,8 +503,13 @@ gst_asf_demux_process_file (GstASFDemux * asf_demux, guint64 * obj_size)
/* Get the rest of the header's header */ /* Get the rest of the header's header */
_read_obj_file (asf_demux, &object); _read_obj_file (asf_demux, &object);
if (object.min_pktsize == object.max_pktsize)
asf_demux->packet_size = object.max_pktsize; asf_demux->packet_size = object.max_pktsize;
asf_demux->play_time = (guint32) object.play_time / 10; else {
asf_demux->packet_size = (guint32) - 1;
GST_WARNING_OBJECT (asf_demux, "Non-const packet size, seeking disabled");
}
asf_demux->play_time = (guint64) object.play_time * (GST_SECOND / 10000000);
asf_demux->preroll = object.preroll; asf_demux->preroll = object.preroll;
GST_INFO ("Object is a file with %" G_GUINT64_FORMAT " data packets", GST_INFO ("Object is a file with %" G_GUINT64_FORMAT " data packets",
@ -756,10 +779,28 @@ static gboolean
gst_asf_demux_process_data (GstASFDemux * asf_demux, guint64 * obj_size) gst_asf_demux_process_data (GstASFDemux * asf_demux, guint64 * obj_size)
{ {
asf_obj_data object; asf_obj_data object;
/* Get the rest of the header */
_read_obj_data (asf_demux, &object);
GST_INFO ("Object is data with %" G_GUINT64_FORMAT " packets",
object.packets);
gst_element_no_more_pads (GST_ELEMENT (asf_demux));
asf_demux->state = GST_ASF_DEMUX_STATE_DATA;
asf_demux->packet = 0;
asf_demux->num_packets = object.packets;
asf_demux->data_size = *obj_size;
asf_demux->data_offset = gst_bytestream_tell (asf_demux->bs);
return TRUE;
}
static gboolean
gst_asf_demux_handle_data (GstASFDemux * asf_demux)
{
asf_obj_data_packet packet_properties_object; asf_obj_data_packet packet_properties_object;
gboolean correction; gboolean correction;
guint64 packets;
guint64 packet;
guint8 buf; guint8 buf;
guint32 sequence; guint32 sequence;
guint32 packet_length; guint32 packet_length;
@ -770,15 +811,51 @@ gst_asf_demux_process_data (GstASFDemux * asf_demux, guint64 * obj_size)
guint8 property; guint8 property;
asf_packet_info packet_info; asf_packet_info packet_info;
guint32 rsize; guint32 rsize;
gint n;
/* Get the rest of the header */ /* handle seek, if any */
_read_obj_data (asf_demux, &object); if (GST_CLOCK_TIME_IS_VALID (asf_demux->seek_pending) &&
packets = object.packets; asf_demux->packet_size != 0) {
guint64 packet_seek = asf_demux->num_packets *
asf_demux->seek_pending / asf_demux->play_time;
GST_INFO ("Object is data with %" G_GUINT64_FORMAT " packets", packets); if (packet_seek > asf_demux->num_packets)
packet_seek = asf_demux->num_packets;
for (packet = 0; packet < packets; packet++) { if (gst_bytestream_seek (asf_demux->bs, packet_seek *
GST_INFO ("\n\nProcess packet %" G_GUINT64_FORMAT, packet); asf_demux->packet_size + asf_demux->data_offset,
GST_SEEK_METHOD_SET)) {
asf_demux->packet = packet_seek;
for (n = 0; n < asf_demux->num_streams; n++) {
if (asf_demux->stream[n].frag_offset > 0) {
gst_buffer_unref (asf_demux->stream[n].payload);
asf_demux->stream[n].frag_offset = 0;
}
}
asf_demux->seek_discont = TRUE;
}
asf_demux->seek_pending = GST_CLOCK_TIME_NONE;
}
GST_INFO ("Process packet");
if (asf_demux->packet++ >= asf_demux->num_packets) {
GstEvent *event;
guint32 remaining;
gst_bytestream_flush (asf_demux->bs, 0xFFFFFF);
gst_bytestream_get_status (asf_demux->bs, &remaining, &event);
if (!event || GST_EVENT_TYPE (event) != GST_EVENT_EOS)
g_warning ("No EOS");
if (event)
gst_event_unref (event);
return gst_asf_demux_handle_sink_event (asf_demux,
gst_event_new (GST_EVENT_EOS), 0);
}
_read_uint8 (asf_demux, &buf); _read_uint8 (asf_demux, &buf);
rsize = 1; rsize = 1;
@ -850,7 +927,6 @@ gst_asf_demux_process_data (GstASFDemux * asf_demux, guint64 * obj_size)
if (packet_info.size_left > 0) if (packet_info.size_left > 0)
gst_bytestream_flush (asf_demux->bs, packet_info.size_left); gst_bytestream_flush (asf_demux->bs, packet_info.size_left);
}
return TRUE; return TRUE;
} }
@ -1031,16 +1107,14 @@ gst_asf_demux_process_object (GstASFDemux * asf_demux)
return gst_asf_demux_process_file (asf_demux, &obj_size); return gst_asf_demux_process_file (asf_demux, &obj_size);
case ASF_OBJ_HEADER: case ASF_OBJ_HEADER:
return gst_asf_demux_process_header (asf_demux, &obj_size); return gst_asf_demux_process_header (asf_demux, &obj_size);
case ASF_OBJ_CONCEAL_NONE:
break;
case ASF_OBJ_COMMENT: case ASF_OBJ_COMMENT:
return gst_asf_demux_process_comment (asf_demux, &obj_size); return gst_asf_demux_process_comment (asf_demux, &obj_size);
case ASF_OBJ_HEAD1: case ASF_OBJ_HEAD1:
return gst_asf_demux_process_header_ext (asf_demux, &obj_size); return gst_asf_demux_process_header_ext (asf_demux, &obj_size);
case ASF_OBJ_HEAD2:
break;
case ASF_OBJ_BITRATE_PROPS: case ASF_OBJ_BITRATE_PROPS:
return gst_asf_demux_process_bitrate_props_object (asf_demux, &obj_size); return gst_asf_demux_process_bitrate_props_object (asf_demux, &obj_size);
case ASF_OBJ_CONCEAL_NONE:
case ASF_OBJ_HEAD2:
case ASF_OBJ_UNDEFINED: case ASF_OBJ_UNDEFINED:
case ASF_OBJ_CODEC_COMMENT: case ASF_OBJ_CODEC_COMMENT:
case ASF_OBJ_INDEX: case ASF_OBJ_INDEX:
@ -1074,8 +1148,8 @@ gst_asf_demux_get_stream (GstASFDemux * asf_demux, guint16 id)
} }
/* Base case if we haven't found one at all */ /* Base case if we haven't found one at all */
GST_ELEMENT_ERROR (asf_demux, STREAM, DEMUX, (NULL), GST_WARNING_OBJECT (asf_demux,
("Segment found for undefined stream: (%d)", id)); "Segment found for undefined stream: (%d)", id);
return NULL; return NULL;
} }
@ -1136,12 +1210,12 @@ gst_asf_demux_process_chunk (GstASFDemux * asf_demux,
if (!(stream = if (!(stream =
gst_asf_demux_get_stream (asf_demux, segment_info->stream_number))) gst_asf_demux_get_stream (asf_demux, segment_info->stream_number)))
return FALSE; goto done;
GST_DEBUG ("Processing chunk of size %u (fo = %d)", segment_info->chunk_size, GST_DEBUG ("Processing chunk of size %u (fo = %d)", segment_info->chunk_size,
stream->frag_offset); stream->frag_offset);
if (stream->frag_offset == 0) { if (segment_info->frag_offset == 0) {
/* new packet */ /* new packet */
stream->sequence = segment_info->sequence; stream->sequence = segment_info->sequence;
asf_demux->pts = segment_info->frag_timestamp - asf_demux->preroll; asf_demux->pts = segment_info->frag_timestamp - asf_demux->preroll;
@ -1154,8 +1228,8 @@ gst_asf_demux_process_chunk (GstASFDemux * asf_demux,
("segment_info->sequence = %d, stream->sequence = %d, segment_info->frag_offset = %d, stream->frag_offset = %d", ("segment_info->sequence = %d, stream->sequence = %d, segment_info->frag_offset = %d, stream->frag_offset = %d",
segment_info->sequence, stream->sequence, segment_info->frag_offset, segment_info->sequence, stream->sequence, segment_info->frag_offset,
stream->frag_offset); stream->frag_offset);
if (segment_info->sequence == stream->sequence if (segment_info->sequence == stream->sequence &&
&& segment_info->frag_offset == stream->frag_offset) { segment_info->frag_offset == stream->frag_offset) {
GstBuffer *new_buffer; GstBuffer *new_buffer;
/* continuing packet */ /* continuing packet */
@ -1174,18 +1248,21 @@ gst_asf_demux_process_chunk (GstASFDemux * asf_demux,
stream->payload = new_buffer; stream->payload = new_buffer;
} else { } else {
/* cannot continue current packet: free it */ /* cannot continue current packet: free it */
stream->frag_offset = 0; if (stream->frag_offset != 0) {
if (segment_info->frag_offset != 0) {
/* cannot create new packet */ /* cannot create new packet */
GST_DEBUG ("BUFFER: Freeing stream->payload (%p)", stream->payload); GST_DEBUG ("BUFFER: Freeing stream->payload (%p)", stream->payload);
gst_buffer_unref (stream->payload); gst_buffer_unref (stream->payload);
gst_bytestream_flush (bs, segment_info->chunk_size); gst_bytestream_flush (bs, segment_info->chunk_size);
packet_info->size_left -= segment_info->chunk_size; packet_info->size_left -= segment_info->chunk_size;
return TRUE; stream->frag_offset = 0;
} else {
/* create new packet */
stream->sequence = segment_info->sequence;
} }
asf_demux->pts = segment_info->frag_timestamp - asf_demux->preroll;
goto done;
//return TRUE;
//} else {
/* create new packet */
//stream->sequence = segment_info->sequence;
//}
} }
} }
@ -1216,17 +1293,29 @@ gst_asf_demux_process_chunk (GstASFDemux * asf_demux,
segment_info->chunk_size); segment_info->chunk_size);
GST_INFO ("Pushing pad"); GST_INFO ("Pushing pad");
if (asf_demux->seek_discont) {
if (asf_demux->seek_flush) {
gst_pad_event_default (asf_demux->sinkpad,
gst_event_new (GST_EVENT_FLUSH));
}
gst_pad_event_default (asf_demux->sinkpad,
gst_event_new_discontinuous (FALSE, GST_FORMAT_TIME,
GST_BUFFER_TIMESTAMP (stream->payload), GST_FORMAT_UNDEFINED));
asf_demux->seek_discont = FALSE;
}
gst_pad_push (stream->pad, GST_DATA (stream->payload)); gst_pad_push (stream->pad, GST_DATA (stream->payload));
} }
stream->frag_offset = 0; stream->frag_offset = 0;
} }
done:
gst_bytestream_flush (bs, segment_info->chunk_size); gst_bytestream_flush (bs, segment_info->chunk_size);
packet_info->size_left -= segment_info->chunk_size; packet_info->size_left -= segment_info->chunk_size;
GST_DEBUG (" ");
return TRUE; return TRUE;
} }
@ -1238,27 +1327,17 @@ static gboolean
gst_asf_demux_handle_sink_event (GstASFDemux * asf_demux, gst_asf_demux_handle_sink_event (GstASFDemux * asf_demux,
GstEvent * event, guint32 remaining) GstEvent * event, guint32 remaining)
{ {
GstEventType type;
gboolean ret = TRUE; gboolean ret = TRUE;
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; if (!event) {
GST_ELEMENT_ERROR (asf_demux, RESOURCE, READ, (NULL), (NULL));
switch (type) { return FALSE;
case GST_EVENT_EOS:{
asf_stream_context *stream;
GstEvent *event = gst_event_new (GST_EVENT_EOS);
gint n;
for (n = 0; n < asf_demux->num_streams; n++) {
stream = &asf_demux->stream[n];
gst_pad_push (stream->pad, GST_DATA (gst_event_ref (event)));
}
gst_event_unref (event);
gst_bytestream_flush (asf_demux->bs, remaining);
gst_element_set_eos (GST_ELEMENT (asf_demux));
ret = FALSE;
break;
} }
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
gst_pad_event_default (asf_demux->sinkpad, event);
return FALSE;
case GST_EVENT_DISCONTINUOUS: case GST_EVENT_DISCONTINUOUS:
{ {
gint i; gint i;
@ -1285,7 +1364,8 @@ gst_asf_demux_handle_sink_event (GstASFDemux * asf_demux,
GST_WARNING_OBJECT (asf_demux, "flush event"); GST_WARNING_OBJECT (asf_demux, "flush event");
break; break;
default: default:
GST_WARNING_OBJECT (asf_demux, "unhandled event %d", type); GST_WARNING_OBJECT (asf_demux, "unhandled event %d",
GST_EVENT_TYPE (event));
break; break;
} }
@ -1297,8 +1377,35 @@ gst_asf_demux_handle_sink_event (GstASFDemux * asf_demux,
static gboolean static gboolean
gst_asf_demux_handle_src_event (GstPad * pad, GstEvent * event) gst_asf_demux_handle_src_event (GstPad * pad, GstEvent * event)
{ {
gboolean res = TRUE;
GstASFDemux *asf_demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
GST_DEBUG ("asfdemux: handle_src_event"); GST_DEBUG ("asfdemux: handle_src_event");
return FALSE;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
switch (GST_EVENT_SEEK_FORMAT (event)) {
case GST_FORMAT_BYTES:
case GST_FORMAT_DEFAULT:
res = FALSE;
break;
case GST_FORMAT_TIME:
asf_demux->seek_pending = GST_EVENT_SEEK_OFFSET (event);
asf_demux->seek_flush = (GST_EVENT_SEEK_FLAGS (event) &
GST_SEEK_FLAG_FLUSH) ? TRUE : FALSE;
break;
default:
res = FALSE;
break;
}
break;
default:
res = FALSE;
break;
}
return res;
} }
static const GstEventMask * static const GstEventMask *
@ -1351,12 +1458,14 @@ gst_asf_demux_handle_src_query (GstPad * pad,
*format = GST_FORMAT_TIME; *format = GST_FORMAT_TIME;
/* fall through */ /* fall through */
case GST_FORMAT_TIME: case GST_FORMAT_TIME:
*value = (GST_SECOND / 1000) * asf_demux->pts; *value = asf_demux->play_time;
break; break;
default: default:
res = FALSE; res = FALSE;
break;
} }
break; break;
case GST_QUERY_POSITION: case GST_QUERY_POSITION:
switch (*format) { switch (*format) {
case GST_FORMAT_DEFAULT: case GST_FORMAT_DEFAULT:
@ -1367,7 +1476,10 @@ gst_asf_demux_handle_src_query (GstPad * pad,
break; break;
default: default:
res = FALSE; res = FALSE;
break;
} }
break;
default: default:
res = FALSE; res = FALSE;
break; break;
@ -1412,6 +1524,9 @@ gst_asf_demux_change_state (GstElement * element)
for (i = 0; i < GST_ASF_DEMUX_NUM_AUDIO_PADS; i++) { for (i = 0; i < GST_ASF_DEMUX_NUM_AUDIO_PADS; i++) {
asf_demux->audio_PTS[i] = 0; asf_demux->audio_PTS[i] = 0;
} }
asf_demux->state = GST_ASF_DEMUX_STATE_HEADER;
asf_demux->seek_pending = GST_CLOCK_TIME_NONE;
asf_demux->seek_discont = FALSE;
break; break;
case GST_STATE_READY_TO_NULL: case GST_STATE_READY_TO_NULL:
break; break;

View file

@ -56,6 +56,12 @@ typedef struct
GstBuffer *payload; GstBuffer *payload;
} asf_stream_context; } asf_stream_context;
typedef enum {
GST_ASF_DEMUX_STATE_HEADER,
GST_ASF_DEMUX_STATE_DATA,
GST_ASF_DEMUX_STATE_EOS
} GstAsfDemuxState;
struct _GstASFDemux { struct _GstASFDemux {
GstElement element; GstElement element;
@ -64,6 +70,11 @@ struct _GstASFDemux {
GstByteStream *bs; GstByteStream *bs;
GstAsfDemuxState state;
guint64 data_offset, num_packets, packet, data_size;
guint64 seek_pending;
gboolean seek_flush, seek_discont;
#define GST_ASF_DEMUX_NUM_VIDEO_PADS 16 #define GST_ASF_DEMUX_NUM_VIDEO_PADS 16
#define GST_ASF_DEMUX_NUM_AUDIO_PADS 32 #define GST_ASF_DEMUX_NUM_AUDIO_PADS 32
#define GST_ASF_DEMUX_NUM_STREAMS 23 #define GST_ASF_DEMUX_NUM_STREAMS 23
@ -89,7 +100,7 @@ struct _GstASFDemux {
guint32 packet_size; guint32 packet_size;
guint32 timestamp; guint32 timestamp;
guint32 play_time; guint64 play_time;
guint64 preroll; guint64 preroll;
guint64 pts; guint64 pts;