theoraparse: be smarter when queuing headers

Look at the first byte of the buffer data (if we can) to decide if the packet is
a header packet or not instead of counting packets.
This commit is contained in:
Wim Taymans 2009-03-13 15:27:51 +01:00
parent 51b5f33c3c
commit 9def0d8c61
2 changed files with 45 additions and 18 deletions

View file

@ -54,7 +54,6 @@ struct _GstTheoraParse {
GstPad * sinkpad;
GstPad * srcpad;
guint packetno;
gboolean send_streamheader;
gboolean streamheader_received;
gboolean is_old_bitstream;

View file

@ -270,7 +270,9 @@ theora_parse_set_header_on_caps (GstTheoraParse * parse, GstCaps * caps)
g_value_init (&array, GST_TYPE_ARRAY);
for (i = 0; i < 3; i++) {
g_assert (bufs[i]);
if (bufs[i] == NULL)
continue;
bufs[i] = gst_buffer_make_metadata_writable (bufs[i]);
GST_BUFFER_FLAG_SET (bufs[i], GST_BUFFER_FLAG_IN_CAPS);
@ -320,6 +322,9 @@ theora_parse_set_streamheader (GstTheoraParse * parse)
int ret;
buf = parse->streamheader[i];
if (buf == NULL)
continue;
gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
packet.packet = GST_BUFFER_DATA (buf);
@ -375,10 +380,12 @@ theora_parse_push_headers (GstTheoraParse * parse)
/* ignore return values, we pass along the result of pushing data packets only
*/
for (i = 0; i < 3; i++)
gst_pad_push (parse->srcpad, gst_buffer_ref (parse->streamheader[i]));
for (i = 0; i < 3; i++) {
GstBuffer *buf;
parse->send_streamheader = FALSE;
if ((buf = parse->streamheader[i]))
gst_pad_push (parse->srcpad, gst_buffer_ref (buf));
}
}
static void
@ -568,7 +575,18 @@ theora_parse_drain_queue (GstTheoraParse * parse, gint64 granulepos)
parse_granulepos (parse, granulepos, &keyframe, &frame);
GST_DEBUG ("draining queue of length %d",
g_queue_get_length (parse->buffer_queue));
GST_LOG_OBJECT (parse, "gp %" G_GINT64_FORMAT ", kf %" G_GINT64_FORMAT
", frame %" G_GINT64_FORMAT, granulepos, keyframe, frame);
prev_frame = frame - g_queue_get_length (parse->buffer_queue);
GST_LOG_OBJECT (parse,
"new prev %" G_GINT64_FORMAT ", prev %" G_GINT64_FORMAT, prev_frame,
parse->prev_frame);
if (prev_frame < parse->prev_frame) {
GST_WARNING ("jumped %" G_GINT64_FORMAT
" frames backwards! not sure what to do here",
@ -583,9 +601,6 @@ theora_parse_drain_queue (GstTheoraParse * parse, gint64 granulepos)
parse->prev_frame = prev_frame;
}
GST_DEBUG ("draining queue of length %d",
g_queue_get_length (parse->buffer_queue));
while (!g_queue_is_empty (parse->buffer_queue)) {
GstBuffer *buf;
@ -635,24 +650,38 @@ static GstFlowReturn
theora_parse_chain (GstPad * pad, GstBuffer * buffer)
{
GstFlowReturn ret;
GstBuffer *buf;
GstTheoraParse *parse;
guint8 *data;
guint size;
gboolean have_header;
parse = GST_THEORA_PARSE (gst_pad_get_parent (pad));
buf = GST_BUFFER (buffer);
parse->packetno++;
data = GST_BUFFER_DATA (buffer);
size = GST_BUFFER_SIZE (buffer);
if (parse->packetno <= 3) {
/* if 1 <= packetno <= 3, it's streamheader,
* so put it on the streamheader list and return */
parse->streamheader[parse->packetno - 1] = buf;
have_header = FALSE;
if (size >= 1) {
if (data[0] & 0x80)
have_header = TRUE;
}
if (have_header) {
if (parse->send_streamheader) {
/* we need to collect the headers still */
/* so put it on the streamheader list and return */
if (data[0] >= 0x80 && data[0] <= 0x82)
parse->streamheader[data[0] - 0x80] = buffer;
}
ret = GST_FLOW_OK;
} else {
if (parse->send_streamheader)
/* data packet, push the headers we collected before */
if (parse->send_streamheader) {
theora_parse_push_headers (parse);
parse->send_streamheader = FALSE;
}
ret = theora_parse_queue_buffer (parse, buf);
ret = theora_parse_queue_buffer (parse, buffer);
}
gst_object_unref (parse);
@ -876,7 +905,6 @@ theora_parse_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_READY_TO_PAUSED:
theora_info_init (&parse->info);
theora_comment_init (&parse->comment);
parse->packetno = 0;
parse->send_streamheader = TRUE;
parse->buffer_queue = g_queue_new ();
parse->event_queue = g_queue_new ();