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;
}
示例#2
0
/*****************************************************************************
 * 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;
    }
}
示例#3
0
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;
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
文件: speex.c 项目: FOSSRIT/baresip
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;
}
示例#7
0
文件: speex.c 项目: lyzkov/rockbox
/* 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(&param);

        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;
  }
}
示例#9
0
文件: speex.c 项目: paranojik/multitv
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;
}
示例#10
0
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;
  }
}
示例#11
0
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;
  }
}
示例#12
0
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;
}
示例#13
0
文件: speex.c 项目: jonsafari/mocp
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;
}