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);
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;
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;
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);
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)
{
"OpusHead", 8, 0,
"audio/x-opus",
setup_opus_mapper,
- granulepos_to_granule_default,
+ granulepos_to_granule_opus,
granule_to_granulepos_default,
NULL,
NULL,