mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 14:26:43 +00:00
theora: If no header packets in stream, look for them in the caps
Makes theora work in cases where the header packets are only in the caps (because theoradec was connected to oggdemux late and missed the beginning of the stream)
This commit is contained in:
parent
615118dea8
commit
f852f3bc75
1 changed files with 63 additions and 4 deletions
|
@ -418,7 +418,7 @@ theora_handle_type_packet (GstTheoraDec * dec)
|
|||
}
|
||||
/* theora has:
|
||||
*
|
||||
* width/height : dimension of the encoded frame
|
||||
* width/height : dimension of the encoded frame
|
||||
* pic_width/pic_height : dimension of the visible part
|
||||
* pic_x/pic_y : offset in encoded frame where visible part starts
|
||||
*/
|
||||
|
@ -559,6 +559,62 @@ header_read_error:
|
|||
}
|
||||
}
|
||||
|
||||
#define MIN_NUM_HEADERS 3
|
||||
static GstFlowReturn
|
||||
theoradec_handle_header_caps (GstTheoraDec * dec)
|
||||
{
|
||||
GstFlowReturn result = GST_CUSTOM_FLOW_DROP;
|
||||
GstCaps *caps;
|
||||
GstStructure *s = NULL;
|
||||
const GValue *array = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (dec, "Looking for Theora headers in caps");
|
||||
caps = gst_pad_get_current_caps (GST_VIDEO_DECODER_SINK_PAD (dec));
|
||||
if (caps)
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
if (s)
|
||||
array = gst_structure_get_value (s, "streamheader");
|
||||
|
||||
if (caps)
|
||||
gst_caps_unref (caps);
|
||||
|
||||
if (array && (gst_value_array_get_size (array) >= MIN_NUM_HEADERS)) {
|
||||
const GValue *value = NULL;
|
||||
GstBuffer *buf = NULL;
|
||||
gint i = 0;
|
||||
|
||||
while (result == GST_CUSTOM_FLOW_DROP
|
||||
&& i < gst_value_array_get_size (array)) {
|
||||
value = gst_value_array_get_value (array, i);
|
||||
buf = gst_value_get_buffer (value);
|
||||
if (!buf)
|
||||
goto null_buffer;
|
||||
GST_LOG_OBJECT (dec, "Submitting header packet");
|
||||
result = theora_dec_decode_buffer (dec, buf, NULL);
|
||||
i++;
|
||||
}
|
||||
} else
|
||||
goto array_error;
|
||||
|
||||
done:
|
||||
return (result !=
|
||||
GST_CUSTOM_FLOW_DROP ? GST_FLOW_NOT_NEGOTIATED : GST_FLOW_OK);
|
||||
|
||||
/* ERRORS */
|
||||
array_error:
|
||||
{
|
||||
GST_WARNING_OBJECT (dec, "streamheader array not found");
|
||||
result = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
null_buffer:
|
||||
{
|
||||
GST_WARNING_OBJECT (dec, "streamheader with null buffer received");
|
||||
result = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate buffer and copy image data into Y444 format */
|
||||
static GstFlowReturn
|
||||
theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf,
|
||||
|
@ -683,10 +739,13 @@ theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet,
|
|||
GstFlowReturn result;
|
||||
ogg_int64_t gp;
|
||||
|
||||
if (G_UNLIKELY (!dec->have_header))
|
||||
goto not_initialized;
|
||||
if (G_UNLIKELY (!dec->have_header)) {
|
||||
result = theoradec_handle_header_caps (dec);
|
||||
if (result != GST_FLOW_OK)
|
||||
goto not_initialized;
|
||||
}
|
||||
|
||||
/* the second most significant bit of the first data byte is cleared
|
||||
/* the second most significant bit of the first data byte is cleared
|
||||
* for keyframes. We can only check it if it's not a zero-length packet. */
|
||||
keyframe = packet->bytes && ((packet->packet[0] & 0x40) == 0);
|
||||
if (G_UNLIKELY (keyframe)) {
|
||||
|
|
Loading…
Reference in a new issue