static GstFlowReturn opus_dec_chain (GstPad * pad, GstBuffer * buf) { GstFlowReturn res; GstOpusDec *dec; dec = GST_OPUS_DEC (gst_pad_get_parent (pad)); if (GST_BUFFER_IS_DISCONT (buf)) { dec->discont = TRUE; } res = opus_dec_chain_parse_data (dec, buf, GST_BUFFER_TIMESTAMP (buf), GST_BUFFER_DURATION (buf)); //done: dec->packetno++; gst_buffer_unref (buf); gst_object_unref (dec); return res; }
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; }
static gboolean opus_dec_sink_event (GstPad * pad, GstEvent * event) { GstOpusDec *dec; gboolean ret = FALSE; dec = GST_OPUS_DEC (gst_pad_get_parent (pad)); GST_LOG_OBJECT (dec, "handling %s event", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT:{ GstFormat format; gdouble rate, arate; gint64 start, stop, time; gboolean update; gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); if (format != GST_FORMAT_TIME) goto newseg_wrong_format; if (rate <= 0.0) goto newseg_wrong_rate; if (update) { /* time progressed without data, see if we can fill the gap with * some concealment data */ if (dec->segment.last_stop < start) { GstClockTime duration; duration = start - dec->segment.last_stop; opus_dec_chain_parse_data (dec, NULL, dec->segment.last_stop, duration); } } /* now configure the values */ gst_segment_set_newsegment_full (&dec->segment, update, rate, arate, GST_FORMAT_TIME, start, stop, time); dec->granulepos = -1; GST_DEBUG_OBJECT (dec, "segment now: cur = %" GST_TIME_FORMAT " [%" GST_TIME_FORMAT " - %" GST_TIME_FORMAT "]", GST_TIME_ARGS (dec->segment.last_stop), GST_TIME_ARGS (dec->segment.start), GST_TIME_ARGS (dec->segment.stop)); ret = gst_pad_push_event (dec->srcpad, event); break; } default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (dec); return ret; /* ERRORS */ newseg_wrong_format: { GST_DEBUG_OBJECT (dec, "received non TIME newsegment"); gst_object_unref (dec); return FALSE; } newseg_wrong_rate: { GST_DEBUG_OBJECT (dec, "negative rates not supported yet"); gst_object_unref (dec); return FALSE; } }