static GstFlowReturn gst_speex_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf) { GstFlowReturn res; GstSpeexDec *dec; /* no fancy draining */ if (G_UNLIKELY (!buf)) return GST_FLOW_OK; dec = GST_SPEEX_DEC (bdec); /* If we have the streamheader and vorbiscomment from the caps already * ignore them here */ if (dec->streamheader && dec->vorbiscomment) { if (GST_BUFFER_SIZE (dec->streamheader) == GST_BUFFER_SIZE (buf) && memcmp (GST_BUFFER_DATA (dec->streamheader), GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)) == 0) { GST_DEBUG_OBJECT (dec, "found streamheader"); gst_audio_decoder_finish_frame (bdec, NULL, 1); res = GST_FLOW_OK; } else if (GST_BUFFER_SIZE (dec->vorbiscomment) == GST_BUFFER_SIZE (buf) && memcmp (GST_BUFFER_DATA (dec->vorbiscomment), GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)) == 0) { GST_DEBUG_OBJECT (dec, "found vorbiscomments"); gst_audio_decoder_finish_frame (bdec, NULL, 1); res = GST_FLOW_OK; } else { res = gst_speex_dec_parse_data (dec, buf); } } else { /* Otherwise fall back to packet counting and assume that the * first two packets are the headers. */ switch (dec->packetno) { case 0: GST_DEBUG_OBJECT (dec, "counted streamheader"); res = gst_speex_dec_parse_header (dec, buf); gst_audio_decoder_finish_frame (bdec, NULL, 1); break; case 1: GST_DEBUG_OBJECT (dec, "counted vorbiscomments"); res = gst_speex_dec_parse_comments (dec, buf); gst_audio_decoder_finish_frame (bdec, NULL, 1); break; default: { res = gst_speex_dec_parse_data (dec, buf); break; } } } dec->packetno++; return res; }
static gboolean gst_speex_dec_set_format (GstAudioDecoder * bdec, GstCaps * caps) { GstSpeexDec *dec = GST_SPEEX_DEC (bdec); gboolean ret = TRUE; GstStructure *s; const GValue *streamheader; s = gst_caps_get_structure (caps, 0); if ((streamheader = gst_structure_get_value (s, "streamheader")) && G_VALUE_HOLDS (streamheader, GST_TYPE_ARRAY) && gst_value_array_get_size (streamheader) >= 2) { const GValue *header, *vorbiscomment; GstBuffer *buf; GstFlowReturn res = GST_FLOW_OK; header = gst_value_array_get_value (streamheader, 0); if (header && G_VALUE_HOLDS (header, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (header); res = gst_speex_dec_parse_header (dec, buf); if (res != GST_FLOW_OK) goto done; gst_buffer_replace (&dec->streamheader, buf); } vorbiscomment = gst_value_array_get_value (streamheader, 1); if (vorbiscomment && G_VALUE_HOLDS (vorbiscomment, GST_TYPE_BUFFER)) { buf = gst_value_get_buffer (vorbiscomment); res = gst_speex_dec_parse_comments (dec, buf); if (res != GST_FLOW_OK) goto done; gst_buffer_replace (&dec->vorbiscomment, buf); } } done: return ret; }
static GstFlowReturn gst_speex_dec_handle_frame (GstAudioDecoder * bdec, GstBuffer * buf) { GstFlowReturn res = GST_FLOW_OK; GstSpeexDec *dec; gboolean header_packet = FALSE; /* no fancy draining */ if (G_UNLIKELY (!buf)) return GST_FLOW_OK; dec = GST_SPEEX_DEC (bdec); switch (dec->packetno) { case 0: GST_DEBUG_OBJECT (dec, "expecting streamheader"); header_packet = TRUE; if (!memcmp_buffers (dec->streamheader, buf)) { res = gst_speex_dec_parse_header (dec, buf); if (res == GST_FLOW_NO_HEADER) { header_packet = FALSE; GST_INFO_OBJECT (dec, "No streamheader in first buffer"); if (dec->streamheader == NULL) { GST_ERROR_OBJECT (dec, "Can't proceed without a header"); return GST_FLOW_ERROR; } else { GST_INFO_OBJECT (dec, "Using streamheader from caps"); } } /* we prefer "inband" streamheaders to the ones in caps */ if (res == GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "found streamheader"); gst_buffer_replace (&dec->streamheader, buf); } } break; case 1: GST_DEBUG_OBJECT (dec, "expecting vorbiscomment"); header_packet = TRUE; if (!memcmp_buffers (dec->vorbiscomment, buf)) { res = gst_speex_dec_parse_comments (dec, buf); if (res == GST_FLOW_NO_HEADER) { header_packet = FALSE; GST_INFO_OBJECT (dec, "No vorbisheader in second buffer"); } if (res == GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "found vorbiscomment"); gst_buffer_replace (&dec->vorbiscomment, buf); } } break; default: break; } if (header_packet) gst_audio_decoder_finish_frame (bdec, NULL, 1); else res = gst_speex_dec_parse_data (dec, buf); dec->packetno++; return res; }