static int libspeex_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibSpeexContext *s = avctx->priv_data; int16_t *output = data, *end; int i, num_samples; num_samples = s->frame_size * avctx->channels; end = output + *data_size / sizeof(*output); speex_bits_read_from(&s->bits, buf, buf_size); for (i = 0; speex_bits_remaining(&s->bits) && output + num_samples < end; i++) { int ret = speex_decode_int(s->dec_state, &s->bits, output); if (ret <= -2) { av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n"); return -1; } else if (ret == -1) // end of stream break; if (avctx->channels == 2) speex_decode_stereo_int(output, s->frame_size, &s->stereo); output += num_samples; } avctx->frame_size = s->frame_size * i; *data_size = avctx->channels * avctx->frame_size * sizeof(*output); return buf_size; }
/***************************************************************************** * DecodePacket: decodes a Speex packet. *****************************************************************************/ static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ) { decoder_sys_t *p_sys = p_dec->p_sys; if( p_oggpacket->bytes ) { /* Copy Ogg packet to Speex bitstream */ speex_bits_read_from( &p_sys->bits, (char *)p_oggpacket->packet, p_oggpacket->bytes ); p_sys->i_frame_in_packet = 0; } /* Decode one frame at a time */ if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet ) { block_t *p_aout_buffer; if( p_sys->p_header->frame_size == 0 ) return NULL; p_aout_buffer = decoder_NewAudioBuffer( p_dec, p_sys->p_header->frame_size ); if( !p_aout_buffer ) { return NULL; } switch( speex_decode_int( p_sys->p_state, &p_sys->bits, (int16_t *)p_aout_buffer->p_buffer ) ) { case -2: msg_Err( p_dec, "decoding error: corrupted stream?" ); case -1: /* End of stream */ return NULL; } if( speex_bits_remaining( &p_sys->bits ) < 0 ) { msg_Err( p_dec, "decoding overflow: corrupted stream?" ); } if( p_sys->p_header->nb_channels == 2 ) speex_decode_stereo_int( (int16_t *)p_aout_buffer->p_buffer, p_sys->p_header->frame_size, &p_sys->stereo ); /* Date management */ p_aout_buffer->i_pts = date_Get( &p_sys->end_date ); p_aout_buffer->i_length = date_Increment( &p_sys->end_date, p_sys->p_header->frame_size ) - p_aout_buffer->i_pts; p_sys->i_frame_in_packet++; return p_aout_buffer; } else { return NULL; } }
static int decode_audio(sh_audio_t *sh, unsigned char *buf, int minlen, int maxlen) { double pts; context_t *ctx = sh->context; int len, framelen, framesamples; char *packet; int i, err; speex_decoder_ctl(ctx->dec_context, SPEEX_GET_FRAME_SIZE, &framesamples); framelen = framesamples * ctx->hdr->nb_channels * sizeof(short); if (maxlen < ctx->hdr->frames_per_packet * framelen) { mp_msg(MSGT_DECAUDIO, MSGL_V, "maxlen too small in decode_audio\n"); return -1; } len = ds_get_packet_pts(sh->ds, (unsigned char **)&packet, &pts); if (len <= 0) return -1; if (sh->pts == MP_NOPTS_VALUE) sh->pts = 0; if (pts != MP_NOPTS_VALUE) { sh->pts = pts; sh->pts_bytes = 0; } speex_bits_read_from(&ctx->bits, packet, len); i = ctx->hdr->frames_per_packet; do { err = speex_decode_int(ctx->dec_context, &ctx->bits, (short *)buf); if (err == -2) mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error decoding file.\n"); if (ctx->hdr->nb_channels == 2) speex_decode_stereo_int((short *)buf, framesamples, &ctx->stereo); buf = &buf[framelen]; } while (--i > 0); sh->pts_bytes += ctx->hdr->frames_per_packet * framelen; return ctx->hdr->frames_per_packet * framelen; }
Boolean CASpeexDecoder::GenerateFrames() { Boolean ret = true; int result; mBDCStatus = kBDCStatusOK; SpeexFramePacket &sfp = mSpeexFPList.front(); speex_bits_read_from(&mSpeexBits, reinterpret_cast<char*> (mBDCBuffer.GetData()), sfp.bytes); if (sfp.frames > 0 && (sfp.frames - mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet > 0)) { UInt32 zeroBytes = mOutputFormat.FramesToBytes(sfp.frames - mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet); memset(mOutBuffer + mOutBufferUsedSize, 0, zeroBytes); mOutBufferUsedSize += zeroBytes; } for (SInt32 i = 0; i < mSpeexHeader.frames_per_packet; i++) { if (mOutputFormat.mFormatFlags & kAudioFormatFlagsNativeFloatPacked != 0) result = speex_decode(mSpeexDecoderState, &mSpeexBits, reinterpret_cast<float*> (mOutBuffer + mOutBufferUsedSize)); else result = speex_decode_int(mSpeexDecoderState, &mSpeexBits, reinterpret_cast<spx_int16_t*> (mOutBuffer + mOutBufferUsedSize)); if (result < 0) { mBDCStatus = kBDCStatusAbort; return false; } if (mSpeexHeader.nb_channels == 2) { if (mOutputFormat.mFormatFlags & kAudioFormatFlagsNativeFloatPacked != 0) speex_decode_stereo(reinterpret_cast<float*> (mOutBuffer + mOutBufferUsedSize), mSpeexHeader.frame_size, &mSpeexStereoState); else speex_decode_stereo_int(reinterpret_cast<spx_int16_t*> (mOutBuffer + mOutBufferUsedSize), mSpeexHeader.frame_size, &mSpeexStereoState); } mOutBufferUsedSize += mOutputFormat.FramesToBytes(mSpeexHeader.frame_size); } if (sfp.frames == 0) { mNumFrames += mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet; } else if (sfp.frames > 0) { mNumFrames += sfp.frames; if (mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet - sfp.frames != 0) mOutBufferStart += mOutputFormat.FramesToBytes(mSpeexHeader.frame_size * mSpeexHeader.frames_per_packet - sfp.frames); } else { mNumFrames -= sfp.frames; } mBDCBuffer.Zap(sfp.bytes); mSpeexFPList.erase(mSpeexFPList.begin()); return ret; }
static int libspeex_decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, AVPacket *avpkt) { uint8_t *buf = avpkt->data; int buf_size = avpkt->size; LibSpeexContext *s = avctx->priv_data; AVFrame *frame = data; int16_t *output; int ret, consumed = 0; /* get output buffer */ frame->nb_samples = s->frame_size; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return ret; } output = (int16_t *)frame->data[0]; /* if there is not enough data left for the smallest possible frame or the next 5 bits are a terminator code, reset the libspeex buffer using the current packet, otherwise ignore the current packet and keep decoding frames from the libspeex buffer. */ if (speex_bits_remaining(&s->bits) < 5 || speex_bits_peek_unsigned(&s->bits, 5) == 0xF) { /* check for flush packet */ if (!buf || !buf_size) { *got_frame_ptr = 0; return buf_size; } /* set new buffer */ speex_bits_read_from(&s->bits, buf, buf_size); consumed = buf_size; } /* decode a single frame */ ret = speex_decode_int(s->dec_state, &s->bits, output); if (ret <= -2) { av_log(avctx, AV_LOG_ERROR, "Error decoding Speex frame.\n"); return AVERROR_INVALIDDATA; } if (avctx->channels == 2) speex_decode_stereo_int(output, s->frame_size, &s->stereo); *got_frame_ptr = 1; return consumed; }
static int decode(struct audec_state *st, int16_t *sampv, size_t *sampc, const uint8_t *buf, size_t len) { const size_t n = st->channels * st->frame_size; size_t i = 0; /* Read into bit-stream */ speex_bits_read_from(&st->bits, (char *)buf, (int)len); /* Handle multiple Speex frames in one RTP packet */ while (speex_bits_remaining(&st->bits) >= MIN_FRAME_SIZE) { int ret; if (*sampc < n) return ENOMEM; ret = speex_decode_int(st->dec, &st->bits, (int16_t *)&sampv[i]); if (ret < 0) { if (-1 == ret) { } else if (-2 == ret) { warning("speex: decode: corrupt stream\n"); } else { warning("speex: decode: speex_decode_int:" " ret=%d\n", ret); } break; } /* Transforms a mono frame into a stereo frame using intensity stereo info */ if (2 == st->channels) { speex_decode_stereo_int((int16_t *)&sampv[i], st->frame_size, &st->stereo); } i += n; *sampc -= n; } *sampc = i; return 0; }
/* this is called for each file to process */ enum codec_status codec_run(void) { int error = CODEC_ERROR; SpeexBits bits; int eof = 0; spx_ogg_sync_state oy; spx_ogg_page og; spx_ogg_packet op; spx_ogg_stream_state os; spx_int64_t page_granule = 0; spx_int64_t cur_granule = 0; int enh_enabled = 1; int nframes = 2; int eos = 0; SpeexStereoState *stereo; int channels = -1; int samplerate = ci->id3->frequency; int extra_headers = 0; int stream_init = 0; /* rockbox: comment 'set but unused' variables int page_nb_packets; */ int frame_size; int packet_count = 0; int lookahead; int headerssize = 0; unsigned long strtoffset = ci->id3->offset; void *st = NULL; int j = 0; intptr_t param; memset(&bits, 0, sizeof(bits)); memset(&oy, 0, sizeof(oy)); /* Ogg handling still uses mallocs, so reset the malloc buffer per track */ if (codec_init()) { goto exit; } ci->seek_buffer(0); ci->set_elapsed(0); stereo = speex_stereo_state_init(); spx_ogg_sync_init(&oy); spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE); codec_set_replaygain(ci->id3); eof = 0; while (!eof) { enum codec_command_action action = ci->get_command(¶m); if (action == CODEC_ACTION_HALT) break; /*seek (seeks to the page before the position) */ if (action == CODEC_ACTION_SEEK_TIME) { if(samplerate!=0&&packet_count>1){ LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n", ((spx_int64_t)param/1000) * (spx_int64_t)samplerate, page_granule, param, (page_granule/samplerate)*1000, samplerate); speex_seek_page_granule(((spx_int64_t)param/1000) * (spx_int64_t)samplerate, page_granule, &oy, headerssize); } ci->set_elapsed(param); ci->seek_complete(); } next_page: /*Get the ogg buffer for writing*/ if(get_more_data(&oy)<1){/*read error*/ goto done; } /* Loop for all complete pages we got (most likely only one) */ while (spx_ogg_sync_pageout(&oy, &og) == 1) { int packet_no; if (stream_init == 0) { spx_ogg_stream_init(&os, spx_ogg_page_serialno(&og)); stream_init = 1; } /* Add page to the bitstream */ spx_ogg_stream_pagein(&os, &og); page_granule = spx_ogg_page_granulepos(&og); /* page_nb_packets = spx_ogg_page_packets(&og); */ cur_granule = page_granule; /* Extract all available packets */ packet_no=0; while (!eos && spx_ogg_stream_packetout(&os, &op)==1){ /* If first packet, process as Speex header */ if (packet_count==0){ st = process_header(&op, enh_enabled, &frame_size, &samplerate, &nframes, &channels, stereo, &extra_headers); speex_decoder_ctl(st, SPEEX_GET_LOOKAHEAD, &lookahead); if (!nframes) nframes=1; if (!st){ goto done; } ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); ci->configure(DSP_SET_SAMPLE_DEPTH, 16); if (channels == 2) { ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); } else if (channels == 1) { ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); } /* Speex header in its own page, add the whole page headersize */ headerssize += og.header_len+og.body_len; } else if (packet_count<=1+extra_headers){ /* add packet to headersize */ headerssize += op.bytes; /* Ignore extra headers */ } else { if (packet_count <= 2+extra_headers) { if (strtoffset) { ci->seek_buffer(strtoffset); spx_ogg_sync_reset(&oy); packet_count++; goto next_page; } } packet_no++; if (op.e_o_s) /* End of stream condition */ eos=1; /* Set Speex bitstream to point to Ogg packet */ speex_bits_set_bit_buffer(&bits, (char *)op.packet, op.bytes); for (j = 0; j != nframes; j++){ int ret; /* Decode frame */ ret = speex_decode_int(st, &bits, output); if (ret == -1) break; if (ret == -2) break; if (speex_bits_remaining(&bits) < 0) break; if (channels == 2) speex_decode_stereo_int(output, frame_size, stereo); if (frame_size > 0) { spx_int16_t *frame_start = output + lookahead; if (channels == 2) frame_start += lookahead; ci->pcmbuf_insert(frame_start, NULL, frame_size - lookahead); lookahead = 0; /* 2 bytes/sample */ cur_granule += frame_size / 2; ci->set_offset((long) ci->curpos); ci->set_elapsed((samplerate == 0) ? 0 : cur_granule * 1000 / samplerate); } } } packet_count++; } } } error = CODEC_OK; done: /* Clean things up for the next track */ speex_bits_destroy(&bits); if (st) speex_decoder_destroy(st); if (stream_init) spx_ogg_stream_destroy(&os); spx_ogg_sync_destroy(&oy); exit: return error; }
static GstFlowReturn gst_speex_dec_parse_data (GstSpeexDec * dec, GstBuffer * buf) { GstFlowReturn res = GST_FLOW_OK; gint i, fpp; guint size; guint8 *data; SpeexBits *bits; if (!dec->frame_duration) goto not_negotiated; if (G_LIKELY (GST_BUFFER_SIZE (buf))) { data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); /* send data to the bitstream */ speex_bits_read_from (&dec->bits, (char *) data, size); fpp = dec->header->frames_per_packet; bits = &dec->bits; GST_DEBUG_OBJECT (dec, "received buffer of size %u, fpp %d, %d bits", size, fpp, speex_bits_remaining (bits)); } else { /* FIXME ? actually consider how much concealment is needed */ /* concealment data, pass NULL as the bits parameters */ GST_DEBUG_OBJECT (dec, "creating concealment data"); fpp = dec->header->frames_per_packet; bits = NULL; } /* now decode each frame, catering for unknown number of them (e.g. rtp) */ for (i = 0; i < fpp; i++) { GstBuffer *outbuf; gint16 *out_data; gint ret; GST_LOG_OBJECT (dec, "decoding frame %d/%d, %d bits remaining", i, fpp, bits ? speex_bits_remaining (bits) : -1); res = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2, GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (dec)), &outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } out_data = (gint16 *) GST_BUFFER_DATA (outbuf); ret = speex_decode_int (dec->state, bits, out_data); if (ret == -1) { /* uh? end of stream */ if (fpp == 0 && speex_bits_remaining (bits) < 8) { /* if we did not know how many frames to expect, then we get this at the end if there are leftover bits to pad to the next byte */ GST_DEBUG_OBJECT (dec, "Discarding leftover bits"); } else { GST_WARNING_OBJECT (dec, "Unexpected end of stream found"); } gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } else if (ret == -2) { GST_WARNING_OBJECT (dec, "Decoding error: corrupted stream?"); gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } if (bits && speex_bits_remaining (bits) < 0) { GST_WARNING_OBJECT (dec, "Decoding overflow: corrupted stream?"); gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } if (dec->header->nb_channels == 2) speex_decode_stereo_int (out_data, dec->frame_size, dec->stereo); res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); break; } } return res; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), ("decoder not initialized")); return GST_FLOW_NOT_NEGOTIATED; } }
static int speex_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t* buf, int buf_size) { SpeexContext *s = avctx->priv_data; int ret, bits_remaining, used = 0, bits_remaining_before; av_log(avctx,AV_LOG_DEBUG,"speexdec: out: %p %p(%d), in: %p, %d\n", data, data_size, data_size?*data_size:0,buf,buf_size); if (data) { /* we'll save this info to log later */ bits_remaining_before = bits_remaining = speex_bits_remaining(&s->bits); *data_size = 0; /* We are not interpolating a frame */ if (buf) { if (bits_remaining > 0) { speex_bits_read_whole_bytes(&s->bits, (char*) buf, buf_size); } else { /*Copy buf to Speex bitstream*/ speex_bits_read_from(&s->bits, (char*) buf, buf_size); } } // end if we are not interpolating a frame ret = speex_decode_int(s->st, buf ? &s->bits : NULL, data); switch (ret) { case -2: av_log(avctx, AV_LOG_ERROR, "Error: corrupted speex stream\n"); speex_bits_reset(&s->bits); return -1; case -1: /* no frame has been decoded, return bytes used */ //av_log(avctx, AV_LOG_INFO, "Warning: no samples have been decoded (end of stream)\n"); speex_bits_rewind(&s->bits); return buf_size; default: if (buf) { /* Calculate how many bytes we've used */ bits_remaining = speex_bits_remaining(&s->bits); if (bits_remaining < 0) { //av_log(avctx, AV_LOG_DEBUG, "Warning: decoding overflow, need more data (%d used)\n", buf_size); speex_bits_rewind(&s->bits); return buf_size; } used = buf_size - (bits_remaining / 8); } else { av_log(avctx, AV_LOG_DEBUG, "Info: interpolating a lost frame\n"); } *data_size = avctx->frame_size * avctx->channels * sizeof(short); if (avctx->channels == 2) speex_decode_stereo_int(data, avctx->frame_size, &s->stereo); if (avctx->debug & FF_DEBUG_BITSTREAM) { int bitrate; speex_decoder_ctl(s->st, SPEEX_GET_BITRATE, &bitrate); av_log(avctx, AV_LOG_DEBUG, "Speex: decoder used: %d/%d bytes, output: %d bytes, bitrate: %d bps (remaining in stream: %.1f bytes after %d bits)\n", used, buf_size, *data_size, bitrate, (float) bits_remaining / 8, bits_remaining_before); } speex_bits_reset(&s->bits); break; } } else { speex_bits_reset(&s->bits); } return used; }
static GstFlowReturn speex_dec_chain_parse_data (GstSpeexDec * dec, GstBuffer * buf, GstClockTime timestamp, GstClockTime duration) { GstFlowReturn res = GST_FLOW_OK; gint i, fpp; guint size; guint8 *data; SpeexBits *bits; if (!dec->frame_duration) goto not_negotiated; if (timestamp != -1) { dec->segment.last_stop = timestamp; } else { timestamp = dec->segment.last_stop; } if (buf) { data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); /* send data to the bitstream */ speex_bits_read_from (&dec->bits, (char *) data, size); fpp = 0; bits = &dec->bits; GST_DEBUG_OBJECT (dec, "received buffer of size %u, fpp %d", size, fpp); } else { /* concealment data, pass NULL as the bits parameters */ GST_DEBUG_OBJECT (dec, "creating concealment data"); fpp = dec->header->frames_per_packet; bits = NULL; } /* now decode each frame, catering for unknown number of them (e.g. rtp) */ for (i = 0; (!fpp || i < fpp) && (!bits || speex_bits_remaining (bits) > 0); i++) { GstBuffer *outbuf; gint16 *out_data; gint ret; GST_LOG_OBJECT (dec, "decoding frame %d/%d", i, fpp); res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2, GST_PAD_CAPS (dec->srcpad), &outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } out_data = (gint16 *) GST_BUFFER_DATA (outbuf); ret = speex_decode_int (dec->state, bits, out_data); if (ret == -1) { /* uh? end of stream */ GST_WARNING_OBJECT (dec, "Unexpected end of stream found"); gst_buffer_unref (outbuf); outbuf = NULL; break; } else if (ret == -2) { GST_WARNING_OBJECT (dec, "Decoding error: corrupted stream?"); gst_buffer_unref (outbuf); outbuf = NULL; break; } if (bits && speex_bits_remaining (bits) < 0) { GST_WARNING_OBJECT (dec, "Decoding overflow: corrupted stream?"); gst_buffer_unref (outbuf); outbuf = NULL; break; } if (dec->header->nb_channels == 2) speex_decode_stereo_int (out_data, dec->frame_size, dec->stereo); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = dec->frame_duration; dec->segment.last_stop += dec->frame_duration; timestamp = dec->segment.last_stop; GST_LOG_OBJECT (dec, "pushing buffer with ts=%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp), GST_TIME_ARGS (dec->frame_duration)); res = gst_pad_push (dec->srcpad, outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); break; } } return res; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), ("decoder not initialized")); return GST_FLOW_NOT_NEGOTIATED; } }
static GstFlowReturn gst_speex_dec_parse_data (GstSpeexDec * dec, GstBuffer * buf) { GstFlowReturn res = GST_FLOW_OK; gint i, fpp; SpeexBits *bits; GstMapInfo map; if (!dec->frame_duration) goto not_negotiated; if (G_LIKELY (gst_buffer_get_size (buf))) { /* send data to the bitstream */ gst_buffer_map (buf, &map, GST_MAP_READ); speex_bits_read_from (&dec->bits, (gchar *) map.data, map.size); gst_buffer_unmap (buf, &map); fpp = dec->header->frames_per_packet; bits = &dec->bits; GST_DEBUG_OBJECT (dec, "received buffer of size %" G_GSIZE_FORMAT ", fpp %d, %d bits", map.size, fpp, speex_bits_remaining (bits)); } else { /* FIXME ? actually consider how much concealment is needed */ /* concealment data, pass NULL as the bits parameters */ GST_DEBUG_OBJECT (dec, "creating concealment data"); fpp = dec->header->frames_per_packet; bits = NULL; } /* now decode each frame, catering for unknown number of them (e.g. rtp) */ for (i = 0; i < fpp; i++) { GstBuffer *outbuf; gboolean corrupted = FALSE; gint ret; GST_LOG_OBJECT (dec, "decoding frame %d/%d, %d bits remaining", i, fpp, bits ? speex_bits_remaining (bits) : -1); #if 0 res = gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD (dec), GST_BUFFER_OFFSET_NONE, dec->frame_size * dec->header->nb_channels * 2, GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (dec)), &outbuf); if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "buf alloc flow: %s", gst_flow_get_name (res)); return res; } #endif /* FIXME, we can use a bufferpool because we have fixed size buffers. We * could also use an allocator */ outbuf = gst_buffer_new_allocate (NULL, dec->frame_size * dec->header->nb_channels * 2, NULL); gst_buffer_map (outbuf, &map, GST_MAP_WRITE); ret = speex_decode_int (dec->state, bits, (spx_int16_t *) map.data); if (ret == -1) { /* uh? end of stream */ GST_WARNING_OBJECT (dec, "Unexpected end of stream found"); corrupted = TRUE; } else if (ret == -2) { GST_WARNING_OBJECT (dec, "Decoding error: corrupted stream?"); corrupted = TRUE; } if (bits && speex_bits_remaining (bits) < 0) { GST_WARNING_OBJECT (dec, "Decoding overflow: corrupted stream?"); corrupted = TRUE; } if (dec->header->nb_channels == 2) speex_decode_stereo_int ((spx_int16_t *) map.data, dec->frame_size, dec->stereo); gst_buffer_unmap (outbuf, &map); if (!corrupted) { res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), outbuf, 1); } else { res = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (dec), NULL, 1); gst_buffer_unref (outbuf); } if (res != GST_FLOW_OK) { GST_DEBUG_OBJECT (dec, "flow: %s", gst_flow_get_name (res)); break; } } return res; /* ERRORS */ not_negotiated: { GST_ELEMENT_ERROR (dec, CORE, NEGOTIATION, (NULL), ("decoder not initialized")); return GST_FLOW_NOT_NEGOTIATED; } }
int do_decode(int client, int server, esd_format_t format, int speed, char* ident) { /* Decoder specific variables */ void *dec_state; SpeexBits bits; const SpeexMode* mode = NULL; int frame_size, frame_size2; SpeexCallback callback; SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT; unsigned int do_sync_seq; /* Configuration variables */ /* FIXME: Depend on NX setting and read from network */ int modeID = SPEEX_MODEID_UWB; /* Encoder initialisation */ speex_bits_init(&bits); mode = speex_lib_get_mode (modeID); dec_state=speex_decoder_init(mode); speex_decoder_ctl(dec_state, SPEEX_SET_SAMPLING_RATE, &speed); if (format & ESD_STEREO) { callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; callback.data = &stereo; speex_decoder_ctl(dec_state, SPEEX_SET_HANDLER, &callback); } speex_decoder_ctl(dec_state, SPEEX_GET_FRAME_SIZE, &frame_size); frame_size2=frame_size*((format & ESD_STEREO)?2:1); /* Lower the latency a bit */ //do_sockopts(client, 200); do_sockopts(server, frame_size2 * (((format & ESD_BITS16)?16:8) / 8)); //esd_set_socket_buffers(server, format, speed, 44100); // /* Get do_sync_seq from encoder */ if (do_read_complete(client, &do_sync_seq, sizeof(do_sync_seq)) != sizeof(do_sync_seq)) goto out; /* Main decoding loop */ while (1) { unsigned int seqNr = 0; int nbBytes; char input[MAX_FRAME_BYTES+1]; short output[MAX_FRAME_SIZE+1]; if (do_read_complete(client, &seqNr, sizeof(seqNr)) != sizeof(seqNr)) break; #ifdef DEBUG fprintf(stderr, "SeqNr: %d\n", seqNr); #endif if (seqNr % do_sync_seq == 0) if (write(client, &seqNr, sizeof(seqNr)) != sizeof(seqNr)) break; if (do_read_complete(client, &nbBytes, sizeof(nbBytes)) != sizeof(nbBytes)) break; if (do_read_complete(client, input, nbBytes) != nbBytes) break; speex_bits_read_from(&bits, input, nbBytes); speex_decode_int(dec_state, &bits, output); if (format & ESD_STEREO) speex_decode_stereo_int(output, frame_size, &stereo); if (do_write_samples(server, output, frame_size2, ((format & ESD_BITS16)?16:8)) != frame_size2) break; } out: /* Decoder shutdown */ speex_bits_destroy(&bits); speex_decoder_destroy(dec_state); return 0; }
static int spx_decode (void *prv_data, char *sound_buf, int nbytes, struct sound_params *sound_params) { struct spx_data *data = (struct spx_data *)prv_data; int bytes_requested = nbytes; int16_t *out = (int16_t *)sound_buf; sound_params->channels = data->nchannels; sound_params->rate = data->rate; sound_params->fmt = SFMT_S16 | SFMT_NE; while (nbytes) { int j; /* First see if there is anything left in the output buffer and * empty it out */ if (data->output_left > 0) { int to_copy = nbytes / sizeof(int16_t); to_copy = MIN(data->output_left, to_copy); memcpy (out, data->output + data->output_start, to_copy * sizeof(int16_t)); out += to_copy; data->output_start += to_copy; data->output_left -= to_copy; nbytes -= to_copy * sizeof(int16_t); } else if (ogg_stream_packetout (&data->os, &data->op) == 1) { int16_t *temp_output = data->output; /* Decode some more samples */ /* Copy Ogg packet to Speex bitstream */ speex_bits_read_from (&data->bits, (char*)data->op.packet, data->op.bytes); for (j = 0; j < data->frames_per_packet; j++) { /* Decode frame */ speex_decode_int (data->st, &data->bits, temp_output); if (data->nchannels == 2) speex_decode_stereo_int (temp_output, data->frame_size, &data->stereo); speex_decoder_ctl (data->st, SPEEX_GET_BITRATE, &data->bitrate); /*data->samples_decoded += data->frame_size;*/ temp_output += data->frame_size * data->nchannels; } /*logit ("Read %d bytes from page", data->frame_size * data->nchannels * data->frames_per_packet);*/ data->output_start = 0; data->output_left = data->frame_size * data->nchannels * data->frames_per_packet; } else if (ogg_sync_pageout(&data->oy, &data->og) == 1) { /* Read in another ogg page */ ogg_stream_pagein (&data->os, &data->og); debug ("Granulepos: %"PRId64, ogg_page_granulepos(&data->og)); } else if (!io_eof(data->stream)) { /* Finally, pull in some more data and try again on the next pass */ get_more_data (data); } else break; } return bytes_requested - nbytes; }