mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
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:
parent
6929876d74
commit
318d8ac686
3 changed files with 261 additions and 119 deletions
16
ChangeLog
16
ChangeLog
|
@ -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>
|
||||
|
||||
* gst/tags/gstvorbistag.c: (gst_vorbis_tag_add): make sure parsed
|
||||
|
|
|
@ -45,6 +45,7 @@ static void gst_asf_demux_init (GstASFDemux * asf_demux);
|
|||
static gboolean gst_asf_demux_send_event (GstElement * element,
|
||||
GstEvent * event);
|
||||
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 void gst_asf_demux_get_property (GObject * object,
|
||||
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_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);
|
||||
}
|
||||
|
||||
|
@ -251,7 +256,20 @@ gst_asf_demux_loop (GstElement * element)
|
|||
asf_demux = GST_ASF_DEMUX (element);
|
||||
|
||||
/* this is basically an infinite loop */
|
||||
switch (asf_demux->state) {
|
||||
case GST_ASF_DEMUX_STATE_HEADER:
|
||||
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
|
||||
|
@ -485,8 +503,13 @@ gst_asf_demux_process_file (GstASFDemux * asf_demux, guint64 * obj_size)
|
|||
|
||||
/* Get the rest of the header's header */
|
||||
_read_obj_file (asf_demux, &object);
|
||||
if (object.min_pktsize == 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;
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
gboolean correction;
|
||||
guint64 packets;
|
||||
guint64 packet;
|
||||
guint8 buf;
|
||||
guint32 sequence;
|
||||
guint32 packet_length;
|
||||
|
@ -770,15 +811,51 @@ gst_asf_demux_process_data (GstASFDemux * asf_demux, guint64 * obj_size)
|
|||
guint8 property;
|
||||
asf_packet_info packet_info;
|
||||
guint32 rsize;
|
||||
gint n;
|
||||
|
||||
/* Get the rest of the header */
|
||||
_read_obj_data (asf_demux, &object);
|
||||
packets = object.packets;
|
||||
/* handle seek, if any */
|
||||
if (GST_CLOCK_TIME_IS_VALID (asf_demux->seek_pending) &&
|
||||
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++) {
|
||||
GST_INFO ("\n\nProcess packet %" G_GUINT64_FORMAT, packet);
|
||||
if (gst_bytestream_seek (asf_demux->bs, packet_seek *
|
||||
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);
|
||||
rsize = 1;
|
||||
|
@ -850,7 +927,6 @@ gst_asf_demux_process_data (GstASFDemux * asf_demux, guint64 * obj_size)
|
|||
|
||||
if (packet_info.size_left > 0)
|
||||
gst_bytestream_flush (asf_demux->bs, packet_info.size_left);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1031,16 +1107,14 @@ gst_asf_demux_process_object (GstASFDemux * asf_demux)
|
|||
return gst_asf_demux_process_file (asf_demux, &obj_size);
|
||||
case ASF_OBJ_HEADER:
|
||||
return gst_asf_demux_process_header (asf_demux, &obj_size);
|
||||
case ASF_OBJ_CONCEAL_NONE:
|
||||
break;
|
||||
case ASF_OBJ_COMMENT:
|
||||
return gst_asf_demux_process_comment (asf_demux, &obj_size);
|
||||
case ASF_OBJ_HEAD1:
|
||||
return gst_asf_demux_process_header_ext (asf_demux, &obj_size);
|
||||
case ASF_OBJ_HEAD2:
|
||||
break;
|
||||
case ASF_OBJ_BITRATE_PROPS:
|
||||
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_CODEC_COMMENT:
|
||||
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 */
|
||||
GST_ELEMENT_ERROR (asf_demux, STREAM, DEMUX, (NULL),
|
||||
("Segment found for undefined stream: (%d)", id));
|
||||
GST_WARNING_OBJECT (asf_demux,
|
||||
"Segment found for undefined stream: (%d)", id);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1136,12 +1210,12 @@ gst_asf_demux_process_chunk (GstASFDemux * asf_demux,
|
|||
|
||||
if (!(stream =
|
||||
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,
|
||||
stream->frag_offset);
|
||||
|
||||
if (stream->frag_offset == 0) {
|
||||
if (segment_info->frag_offset == 0) {
|
||||
/* new packet */
|
||||
stream->sequence = segment_info->sequence;
|
||||
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, stream->sequence, segment_info->frag_offset,
|
||||
stream->frag_offset);
|
||||
if (segment_info->sequence == stream->sequence
|
||||
&& segment_info->frag_offset == stream->frag_offset) {
|
||||
if (segment_info->sequence == stream->sequence &&
|
||||
segment_info->frag_offset == stream->frag_offset) {
|
||||
GstBuffer *new_buffer;
|
||||
|
||||
/* continuing packet */
|
||||
|
@ -1174,18 +1248,21 @@ gst_asf_demux_process_chunk (GstASFDemux * asf_demux,
|
|||
stream->payload = new_buffer;
|
||||
} else {
|
||||
/* cannot continue current packet: free it */
|
||||
stream->frag_offset = 0;
|
||||
if (segment_info->frag_offset != 0) {
|
||||
if (stream->frag_offset != 0) {
|
||||
/* cannot create new packet */
|
||||
GST_DEBUG ("BUFFER: Freeing stream->payload (%p)", stream->payload);
|
||||
gst_buffer_unref (stream->payload);
|
||||
gst_bytestream_flush (bs, segment_info->chunk_size);
|
||||
packet_info->size_left -= segment_info->chunk_size;
|
||||
return TRUE;
|
||||
} else {
|
||||
/* create new packet */
|
||||
stream->sequence = segment_info->sequence;
|
||||
stream->frag_offset = 0;
|
||||
}
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
stream->frag_offset = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
gst_bytestream_flush (bs, segment_info->chunk_size);
|
||||
packet_info->size_left -= segment_info->chunk_size;
|
||||
|
||||
GST_DEBUG (" ");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -1238,27 +1327,17 @@ static gboolean
|
|||
gst_asf_demux_handle_sink_event (GstASFDemux * asf_demux,
|
||||
GstEvent * event, guint32 remaining)
|
||||
{
|
||||
GstEventType type;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN;
|
||||
|
||||
switch (type) {
|
||||
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;
|
||||
if (!event) {
|
||||
GST_ELEMENT_ERROR (asf_demux, RESOURCE, READ, (NULL), (NULL));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_EOS:
|
||||
gst_pad_event_default (asf_demux->sinkpad, event);
|
||||
return FALSE;
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
{
|
||||
gint i;
|
||||
|
@ -1285,7 +1364,8 @@ gst_asf_demux_handle_sink_event (GstASFDemux * asf_demux,
|
|||
GST_WARNING_OBJECT (asf_demux, "flush event");
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (asf_demux, "unhandled event %d", type);
|
||||
GST_WARNING_OBJECT (asf_demux, "unhandled event %d",
|
||||
GST_EVENT_TYPE (event));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1297,8 +1377,35 @@ gst_asf_demux_handle_sink_event (GstASFDemux * asf_demux,
|
|||
static gboolean
|
||||
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");
|
||||
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 *
|
||||
|
@ -1351,12 +1458,14 @@ gst_asf_demux_handle_src_query (GstPad * pad,
|
|||
*format = GST_FORMAT_TIME;
|
||||
/* fall through */
|
||||
case GST_FORMAT_TIME:
|
||||
*value = (GST_SECOND / 1000) * asf_demux->pts;
|
||||
*value = asf_demux->play_time;
|
||||
break;
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GST_QUERY_POSITION:
|
||||
switch (*format) {
|
||||
case GST_FORMAT_DEFAULT:
|
||||
|
@ -1367,7 +1476,10 @@ gst_asf_demux_handle_src_query (GstPad * pad,
|
|||
break;
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
res = FALSE;
|
||||
break;
|
||||
|
@ -1412,6 +1524,9 @@ gst_asf_demux_change_state (GstElement * element)
|
|||
for (i = 0; i < GST_ASF_DEMUX_NUM_AUDIO_PADS; i++) {
|
||||
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;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
break;
|
||||
|
|
|
@ -56,6 +56,12 @@ typedef struct
|
|||
GstBuffer *payload;
|
||||
} asf_stream_context;
|
||||
|
||||
typedef enum {
|
||||
GST_ASF_DEMUX_STATE_HEADER,
|
||||
GST_ASF_DEMUX_STATE_DATA,
|
||||
GST_ASF_DEMUX_STATE_EOS
|
||||
} GstAsfDemuxState;
|
||||
|
||||
struct _GstASFDemux {
|
||||
GstElement element;
|
||||
|
||||
|
@ -64,6 +70,11 @@ struct _GstASFDemux {
|
|||
|
||||
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_AUDIO_PADS 32
|
||||
#define GST_ASF_DEMUX_NUM_STREAMS 23
|
||||
|
@ -89,7 +100,7 @@ struct _GstASFDemux {
|
|||
|
||||
guint32 packet_size;
|
||||
guint32 timestamp;
|
||||
guint32 play_time;
|
||||
guint64 play_time;
|
||||
|
||||
guint64 preroll;
|
||||
guint64 pts;
|
||||
|
|
Loading…
Reference in a new issue