oggstream: reject Ogg/Opus streams with nonsensical preskip/granpos setup

As the spec mandates.
This commit is contained in:
Vincent Penquerc'h 2012-06-06 11:01:13 +01:00
parent bc221fba78
commit 078dd2e896
3 changed files with 46 additions and 2 deletions

View file

@ -556,8 +556,15 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
out_offset_end = -1;
} else {
if (packet->granulepos != -1) {
pad->current_granule = gst_ogg_stream_granulepos_to_granule (&pad->map,
gint64 granule = gst_ogg_stream_granulepos_to_granule (&pad->map,
packet->granulepos);
if (granule < 0) {
GST_ERROR_OBJECT (ogg,
"granulepos %" G_GINT64_FORMAT " yielded granule %" G_GINT64_FORMAT,
packet->granulepos, granule);
return GST_FLOW_ERROR;
}
pad->current_granule = granule;
pad->keyframe_granule =
gst_ogg_stream_granulepos_to_key_granule (&pad->map,
packet->granulepos);
@ -866,6 +873,11 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
if (granule != -1) {
GST_DEBUG_OBJECT (ogg, "%p has granulepos %" G_GINT64_FORMAT, pad, granule);
pad->current_granule = granule;
} else if (granule != -1) {
GST_ERROR_OBJECT (ogg,
"granulepos %" G_GINT64_FORMAT " yielded granule %" G_GINT64_FORMAT,
packet->granulepos, granule);
return GST_FLOW_ERROR;
}
/* restart header packet count when seeing a b_o_s page;
@ -903,6 +915,12 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
granule = gst_ogg_stream_granulepos_to_granule (&pad->map,
packet->granulepos);
if (granule < 0) {
GST_ERROR_OBJECT (ogg,
"granulepos %" G_GINT64_FORMAT " yielded granule %"
G_GINT64_FORMAT, packet->granulepos, granule);
return GST_FLOW_ERROR;
}
if (granule > pad->map.accumulated_granule)
start_granule = granule - pad->map.accumulated_granule;

View file

@ -1873,6 +1873,7 @@ setup_opus_mapper (GstOggStream * pad, ogg_packet * packet)
pad->granulerate_d = 1;
pad->granuleshift = 0;
pad->n_header_packets = 2;
pad->first_granpos = -1;
/* pre-skip is in samples at 48000 Hz, which matches granule one for one */
pad->granule_offset = -GST_READ_UINT16_LE (packet->packet + 10);
@ -1890,6 +1891,29 @@ is_header_opus (GstOggStream * pad, ogg_packet * packet)
return packet->bytes >= 8 && !memcmp (packet->packet, "Opus", 4);
}
static gint64
granulepos_to_granule_opus (GstOggStream * pad, gint64 granulepos)
{
if (granulepos == -1)
return -1;
/* We must reject some particular cases for the first granpos */
if (pad->first_granpos < 0 || granulepos < pad->first_granpos)
pad->first_granpos = granulepos;
if (pad->first_granpos == granulepos) {
if (granulepos < -pad->granule_offset) {
GST_ERROR ("Invalid Opus stream: first granulepos (%" G_GINT64_FORMAT
") less than preskip (%" G_GINT64_FORMAT ")", granulepos,
-pad->granule_offset);
return -1;
}
}
return granulepos;
}
static gint64
packet_duration_opus (GstOggStream * pad, ogg_packet * packet)
{
@ -2147,7 +2171,7 @@ const GstOggMap mappers[] = {
"OpusHead", 8, 0,
"audio/x-opus",
setup_opus_mapper,
granulepos_to_granule_default,
granulepos_to_granule_opus,
granule_to_granulepos_default,
NULL,
NULL,

View file

@ -93,6 +93,8 @@ struct _GstOggStream
gboolean theora_has_zero_keyoffset;
/* VP8 stuff */
gboolean is_vp8;
/* opus stuff */
gint64 first_granpos;
/* OGM stuff */
gboolean is_ogm;
gboolean is_ogm_text;