gboolean gst_opus_header_is_id_header (GstBuffer * buf) { gsize size = gst_buffer_get_size (buf); guint8 *data = NULL; guint8 version, channels, channel_mapping_family, n_streams, n_stereo_streams; gboolean ret = FALSE; GstMapInfo map; if (size < 19) goto beach; if (!gst_opus_header_is_header (buf, "OpusHead", 8)) goto beach; gst_buffer_map (buf, &map, GST_MAP_READ); data = map.data; size = map.size; version = data[8]; if (version >= 0x0f) /* major version >=0 is what we grok */ goto beach; channels = data[9]; if (channels == 0) goto beach; channel_mapping_family = data[18]; if (channel_mapping_family == 0) { if (channels > 2) goto beach; } else { channels = data[9]; if (size < 21 + channels) goto beach; n_streams = data[19]; n_stereo_streams = data[20]; if (n_streams == 0) goto beach; if (n_stereo_streams > n_streams) goto beach; if (n_streams + n_stereo_streams > 255) goto beach; } ret = TRUE; beach: if (data) gst_buffer_unmap (buf, &map); return ret; }
static GstFlowReturn gst_opus_dec_handle_frame (GstAudioDecoder * adec, GstBuffer * buf) { GstFlowReturn res; GstOpusDec *dec; /* no fancy draining */ if (G_UNLIKELY (!buf)) return GST_FLOW_OK; dec = GST_OPUS_DEC (adec); GST_LOG_OBJECT (dec, "Got buffer ts %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); /* If we have the streamheader and vorbiscomment from the caps already * ignore them here */ if (dec->streamheader && dec->vorbiscomment) { if (memcmp_buffers (dec->streamheader, buf)) { GST_DEBUG_OBJECT (dec, "found streamheader"); gst_audio_decoder_finish_frame (adec, NULL, 1); res = GST_FLOW_OK; } else if (memcmp_buffers (dec->vorbiscomment, buf)) { GST_DEBUG_OBJECT (dec, "found vorbiscomments"); gst_audio_decoder_finish_frame (adec, NULL, 1); res = GST_FLOW_OK; } else { res = opus_dec_chain_parse_data (dec, buf); } } else { /* Otherwise fall back to packet counting and assume that the * first two packets might be the headers, checking magic. */ switch (dec->packetno) { case 0: if (gst_opus_header_is_header (buf, "OpusHead", 8)) { GST_DEBUG_OBJECT (dec, "found streamheader"); res = gst_opus_dec_parse_header (dec, buf); gst_audio_decoder_finish_frame (adec, NULL, 1); } else { res = opus_dec_chain_parse_data (dec, buf); } break; case 1: if (gst_opus_header_is_header (buf, "OpusTags", 8)) { GST_DEBUG_OBJECT (dec, "counted vorbiscomments"); res = gst_opus_dec_parse_comments (dec, buf); gst_audio_decoder_finish_frame (adec, NULL, 1); } else { res = opus_dec_chain_parse_data (dec, buf); } break; default: { res = opus_dec_chain_parse_data (dec, buf); break; } } } dec->packetno++; return res; }
gboolean gst_opus_header_is_comment_header (GstBuffer * buf) { return gst_opus_header_is_header (buf, "OpusTags", 8); }