Пример #1
0
int qSpeexDecode(QSpeexCodecPtr handle, void* inputBytes, int inputSize, void* outputSamples, int outputSize)
{
	int offset, remaining;
	short *out = (short*)outputSamples;
	
	/* If there is no input to read, we certainly can't read it. */
	if (inputBytes != NULL) {
		speex_bits_read_from(&handle->decBits, inputBytes, inputSize);
	}
	
	for (offset=0; offset<outputSize; offset+=handle->frameSize) {
		if (inputBytes != NULL) {
			if (!speex_bits_remaining(&handle->decBits)) {
				// Ran out of input data
				return 2;
			}
			speex_decode_int(handle->decState, &handle->decBits, out+offset);
		}
		else {
			/* Extrapolate output-buffer based on current decoder state. */
			speex_decode_int(handle->decState, NULL, out+offset);		
		}
	}
	remaining = speex_bits_remaining(&handle->decBits);
	if (remaining >= 8) {
		/* If less than a byte is left over, that's OK. */
		fprintf(stderr, "qSpeexDecode(): %d bits left over\n", remaining);
		return 1; // Still have encoded bits left over
	}
	else return 0; // A-OK!!
}
Пример #2
0
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;
}
Пример #3
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;
    }
}
Пример #4
0
int Speex_2_Pcm16( unsigned char* out_buf, unsigned char* in_buf, 
		   unsigned int size,
		   unsigned int channels, unsigned int rate, long h_codec )
{
  SpeexState* ss;
  short* pcm = (short*) out_buf;
  int frames_out  = 0;

  ss = (SpeexState*) h_codec;
  if (!ss || channels!=1)
    return -1;
    
  speex_bits_read_from(&ss->decoder.bits, (char*)in_buf, size);

  /* We don't know where frame boundaries are,
     but the minimum frame size is 43 */
  while (speex_bits_remaining(&ss->decoder.bits)>40) {
    int ret;
	
    ret = speex_decode_int(ss->decoder.state, &ss->decoder.bits, pcm);
    pcm+= ss->frame_size;
	
    if (ret==-2) {
      ERROR("while calling speex_decode\n");
      return -1;
    }
	
    if (ret==-1) break;
	
    frames_out++;  
  }
    
  return frames_out*ss->frame_size*sizeof(short);
}
Пример #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
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
tsk_size_t tdav_codec_speex_decode(tmedia_codec_t* self, const void* in_data, tsk_size_t in_size, void** out_data, tsk_size_t* out_max_size, const tsk_object_t* proto_hdr)
{
	int ret;
	tsk_size_t out_size = 0;
	tdav_codec_speex_t* speex = (tdav_codec_speex_t*)self;

	if(!self || !in_data || !in_size || !out_data){
		TSK_DEBUG_ERROR("Invalid parameter");
		return 0;
	}

	// initializes the bit-stream 
	speex_bits_read_from(&speex->decoder.bits, (char*)in_data, in_size);

	do{
		// performs decode() 
		if((ret = speex_decode_int(speex->decoder.state, &speex->decoder.bits, speex->decoder.buffer))){
			TSK_DEBUG_ERROR("Failed to decode the buffer. retcode=%d", ret);
			break;
		}

		if(*out_max_size <(out_size + speex->decoder.size)){
			if((*out_data = tsk_realloc(*out_data, (out_size + speex->decoder.size)))){
				*out_max_size = (out_size + speex->decoder.size);
			}
			else{
				*out_max_size = 0;
				return 0;
			}
		}

		// copy output buffer 
		memcpy(&((uint8_t*)*out_data)[out_size], speex->decoder.buffer, speex->decoder.size);
		out_size += speex->decoder.size;
	}
	while(speex_bits_remaining(&speex->decoder.bits) >= 5);
	

	return out_size;
}
Пример #8
0
/*****************************************************************************
 * ProcessPacket: processes a Speex packet.
 *****************************************************************************/
static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
                            block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block = *pp_block;

    if( p_block && p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
        Flush( p_dec );

    /* Date management */
    if( p_block && p_block->i_pts > VLC_TS_INVALID &&
        p_block->i_pts != date_Get( &p_sys->end_date ) )
    {
        date_Set( &p_sys->end_date, p_block->i_pts );
    }

    if( !date_Get( &p_sys->end_date ) )
    {
        /* We've just started the stream, wait for the first PTS. */
        if( p_block ) block_Release( p_block );
        return NULL;
    }

    *pp_block = NULL; /* To avoid being fed the same packet again */

    if( p_sys->b_packetizer )
    {
        if ( p_sys->p_header->frames_per_packet > 1 )
        {
            short *p_frame_holder = NULL;
            int i_bits_before = 0, i_bits_after = 0, i_bytes_in_speex_frame = 0,
                i_pcm_output_size = 0, i_bits_in_speex_frame = 0;
            block_t *p_new_block = NULL;

            i_pcm_output_size = p_sys->p_header->frame_size;
            p_frame_holder = (short*)xmalloc( sizeof(short)*i_pcm_output_size );

            speex_bits_read_from( &p_sys->bits, (char*)p_oggpacket->packet,
                p_oggpacket->bytes);
            i_bits_before = speex_bits_remaining( &p_sys->bits );
            speex_decode_int(p_sys->p_state, &p_sys->bits, p_frame_holder);
            i_bits_after = speex_bits_remaining( &p_sys->bits );

            i_bits_in_speex_frame = i_bits_before - i_bits_after;
            i_bytes_in_speex_frame = ( i_bits_in_speex_frame +
                (8 - (i_bits_in_speex_frame % 8)) )
                / 8;

            p_new_block = block_Alloc( i_bytes_in_speex_frame );
            memset( p_new_block->p_buffer, 0xff, i_bytes_in_speex_frame );

            /*
             * Copy the first frame in this packet to a new packet.
             */
            speex_bits_rewind( &p_sys->bits );
            speex_bits_write( &p_sys->bits,
                (char*)p_new_block->p_buffer,
                (int)i_bytes_in_speex_frame );

            /*
             * Move the remaining part of the original packet (subsequent
             * frames, if there are any) into the beginning
             * of the original packet so
             * they are preserved following the realloc.
             * Note: Any bits that
             * remain in the initial packet
             * are "filler" if they do not constitute
             * an entire byte.
             */
            if ( i_bits_after > 7 )
            {
                /* round-down since we rounded-up earlier (to include
             * the speex terminator code.
             */
                i_bytes_in_speex_frame--;
                speex_bits_write( &p_sys->bits,
                    (char*)p_block->p_buffer,
                    p_block->i_buffer - i_bytes_in_speex_frame );
                p_block = block_Realloc( p_block,
                    0,
                    p_block->i_buffer-i_bytes_in_speex_frame );
                *pp_block = p_block;
            }
            else
            {
                speex_bits_reset( &p_sys->bits );
            }

            free( p_frame_holder );
            return SendPacket( p_dec, p_new_block);
        }
        else
        {
                return SendPacket( p_dec, p_block );
        }
    }
    else
    {
        block_t *p_aout_buffer = DecodePacket( p_dec, p_oggpacket );

        if( p_block )
            block_Release( p_block );
        return p_aout_buffer;
    }
}
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;
  }
}
Пример #10
0
boost::uint8_t*
AudioDecoderSpeex::decode(const EncodedAudioFrame& input,
    boost::uint32_t& outputSize)
{
    speex_bits_read_from(&_speex_bits, reinterpret_cast<char*>(input.data.get()),
                         input.dataSize);

    std::vector<DecodedFrame*> decoded_frames;

    boost::uint32_t total_size = 0;

    while (speex_bits_remaining(&_speex_bits)) {

        boost::scoped_array<short> output( new short[_speex_framesize] );

        int rv = speex_decode_int(_speex_dec_state, &_speex_bits, output.get());
        if (rv != 0) {
            if (rv != -1) {
                log_error(_("Corrupt Speex stream!"));
            }

            break;
        }

        
        boost::int16_t* conv_data = 0;

#ifdef RESAMPLING_SPEEX
		spx_uint32_t conv_size = 0;
        conv_data = new boost::int16_t[_target_frame_size];
        memset(conv_data, 0, _target_frame_size * 2);

        spx_uint32_t in_size = _speex_framesize;

        // Our input format is mono and we want to expand to stereo. Speex
        // won't do this for us, but we can ask it to skip a sample after
        // writing one, so all we have to do is duplicate the samples.
        speex_resampler_set_output_stride(_resampler, 2);
        conv_size = _target_frame_size; // Assuming this hould be samples.

        int err = speex_resampler_process_int(_resampler, 0 /* mono */, output.get(), &in_size, conv_data, &conv_size);
        if (err != RESAMPLER_ERR_SUCCESS) {
            log_error(_("Failed to resample Speex frame."));
            delete [] conv_data;
            continue;
        }

        // The returned size is the number of *mono* samples returned.
        conv_size *= 2;

        // Now, duplicate all the samples so we get a stereo sound.
        for (boost::uint32_t i = 0; i < conv_size; i += 2) {
            conv_data[i+1] = conv_data[i];
        }

        // Our interface requires returning the audio size in bytes.
        conv_size *= sizeof(boost::int16_t);
#else
        int outsize = 0;
        AudioResampler::convert_raw_data(&conv_data, &outsize, output.get(), 
            _speex_framesize /* sample count*/, 2 /* sample size */,
            16000, false /* stereo */, 44100 /* new rate */,
            true /* convert to stereo */);
        boost::uint32_t conv_size = outsize;
#endif
        total_size += conv_size;

        decoded_frames.push_back(new DecodedFrame(conv_data, conv_size));
    }

    outputSize = total_size;

    // We have to jump through hoops because decode() requires as much
    // data to be returned as possible.
    boost::uint8_t* rv = new boost::uint8_t[total_size];
    boost::uint8_t* ptr = rv;

    for (std::vector<DecodedFrame*>::iterator it = decoded_frames.begin(),
         end = decoded_frames.end(); it != end; ++it) {
        DecodedFrame* frame = *it;

        memcpy(ptr, frame->data.get(), frame->size);

        ptr += frame->size;

        delete frame;
    }

    outputSize = total_size;

    return rv;
}
Пример #11
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;
  }
}
Пример #12
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;
  }
}
Пример #13
0
int AudioStreamPlaybackSpeex::mix(int16_t *p_buffer, int p_frames) {

	//printf("update, loops %i, read ofs %i\n", (int)loops, read_ofs);
	//printf("playing %i, paused %i\n", (int)playing, (int)paused);

	if (!active || !playing || !data.size())
		return 0;

	/*
	if (read_ofs >= data.size()) {
		if (loops) {
			reload();
			++loop_count;
		} else {
			return;
		};
	};
	*/

	int todo = p_frames;
	if (todo < page_size) {
		return 0;
	};

	int eos = 0;

	while (todo > page_size) {

		int ret = 0;
		while ((todo > page_size && packets_available && !eos) || (ret = ogg_sync_pageout(&oy, &og)) == 1) {

			if (!packets_available) {
				/*Add page to the bitstream*/
				ogg_stream_pagein(&os, &og);
				page_granule = ogg_page_granulepos(&og);
				page_nb_packets = ogg_page_packets(&og);
				packet_no = 0;
				if (page_granule > 0 && frame_size) {
					skip_samples = page_nb_packets * frame_size * nframes - (page_granule - last_granule);
					if (ogg_page_eos(&og))
						skip_samples = -skip_samples;
					/*else if (!ogg_page_bos(&og))
					skip_samples = 0;*/
				} else {
					skip_samples = 0;
				}

				last_granule = page_granule;
				packets_available = true;
			}
			/*Extract all available packets*/
			while (todo > page_size && !eos) {

				if (ogg_stream_packetout(&os, &op) != 1) {
					packets_available = false;
					break;
				}

				packet_no++;

				/*End of stream condition*/
				if (op.e_o_s)
					eos = 1;

				/*Copy Ogg packet to Speex bitstream*/
				speex_bits_read_from(&bits, (char *)op.packet, op.bytes);

				for (int j = 0; j != nframes; j++) {

					int16_t *out = p_buffer;

					int ret;
					/*Decode frame*/
					ret = speex_decode_int(st, &bits, out);

					/*for (i=0;i<frame_size*channels;i++)
					  printf ("%d\n", (int)output[i]);*/

					if (ret == -1) {
						printf("decode returned -1\n");
						break;
					};
					if (ret == -2) {
						OS::get_singleton()->printerr("Decoding error: corrupted stream?\n");
						break;
					}
					if (speex_bits_remaining(&bits) < 0) {
						OS::get_singleton()->printerr("Decoding overflow: corrupted stream?\n");
						break;
					}
					//if (channels==2)
					//	speex_decode_stereo_int(output, frame_size, &stereo);

					/*Convert to short and save to output file*/
					for (int i = 0; i < frame_size * stream_channels; i++) {
						out[i] = le_short(out[i]);
					}

					{

						int new_frame_size = frame_size;

						/*printf ("packet %d %d\n", packet_no, skip_samples);*/
						if (packet_no == 1 && j == 0 && skip_samples > 0) {
							/*printf ("chopping first packet\n");*/
							new_frame_size -= skip_samples;
						}
						if (packet_no == page_nb_packets && skip_samples < 0) {
							int packet_length = nframes * frame_size + skip_samples;
							new_frame_size = packet_length - j * frame_size;
							if (new_frame_size < 0)
								new_frame_size = 0;
							if (new_frame_size > frame_size)
								new_frame_size = frame_size;
							/*printf ("chopping end: %d %d %d\n", new_frame_size, packet_length, packet_no);*/
						}

						p_buffer += new_frame_size * stream_channels;
						todo -= new_frame_size;
					}
				}
			};
		};
		//todo = get_todo();

		//todo is still greater than page size, can write more
		if (todo > page_size || eos) {
			if (read_ofs < data.size()) {

				//char *buf;
				int nb_read = MIN(data.size() - read_ofs, READ_CHUNK);

				/*Get the ogg buffer for writing*/
				char *ogg_dst = ogg_sync_buffer(&oy, nb_read);
				/*Read bitstream from input file*/
				copymem(ogg_dst, &data[read_ofs], nb_read);
				read_ofs += nb_read;
				ogg_sync_wrote(&oy, nb_read);
			} else {
				if (loops) {
					reload();
					++loop_count;
					//break;
				} else {
					playing = false;
					unload();
					break;
				};
			}
		};
	};

	return p_frames - todo;
};
Пример #14
0
int universal_speex_decode(void* handle, const void* pCodedData, 
                          unsigned cbCodedPacketSize, void* pAudioBuffer, 
                          unsigned cbBufferSize, unsigned *pcbDecodedSize, 
                          const struct RtpHeader* pRtpHeader)
{
   SpeexBits bits;
   struct speex_codec_data_decoder *mpSpeexDec = 
      (struct speex_codec_data_decoder *)handle;
   assert(handle != NULL);

   if (mpSpeexDec->mNumSamplesPerFrame > cbBufferSize)
   {
      return RPLG_INVALID_ARGUMENT;
   }

   /* Reset number of decoded samples */
   *pcbDecodedSize = 0;

   /* Decode incoming packet if present. Do PLC if no packet. */
   if (pCodedData)
   {
      /* Prepare data for Speex decoder */
      speex_bits_set_bit_buffer(&bits,(char*)pCodedData, cbCodedPacketSize);

      /* Decode while there are something to decode and enough space
      * for decoded data. */
      while (cbBufferSize >= mpSpeexDec->mNumSamplesPerFrame &&
             (speex_bits_remaining(&bits) > 0))
      {
         int res;

         /* Decode frame */
         res = speex_decode_int(mpSpeexDec->mpDecoderState, &bits,
                                ((spx_int16_t*)pAudioBuffer)+(*pcbDecodedSize));
         if (res == 0)
         {
            /* Update number of decoded and available samples on success */
            *pcbDecodedSize += mpSpeexDec->mNumSamplesPerFrame;
            cbBufferSize -= mpSpeexDec->mNumSamplesPerFrame;
         }
         else
         {
            /* If it's the end of the stream or corrupted stream just return */
            break;
         }
      }
   }
   else
   {
      int res;

      /* Do PLC */
      res = speex_decode_int(mpSpeexDec->mpDecoderState, NULL,
                             ((spx_int16_t*)pAudioBuffer)+(*pcbDecodedSize));
      if (res == 0)
      {
         /* Update number of decoded and available samples on success */
         *pcbDecodedSize += mpSpeexDec->mNumSamplesPerFrame;
      }
      else
      {
         /* This mustn't happen for lost packet, but who knows... */
         return RPLG_FAILED;
      }
   }

   return RPLG_SUCCESS;
}
Пример #15
0
JNIEXPORT int JNICALL FUNCSPEEX(decodeRemaining)(JNIEnv* env, jobject obj) {
	return speex_bits_remaining(&dbits);
}
Пример #16
0
UInt32 OggSpeexDecoder::ReadAudio(AudioBufferList *bufferList, UInt32 frameCount)
{
	if(!IsOpen() || NULL == bufferList || bufferList->mNumberBuffers != mFormat.mChannelsPerFrame || 0 == frameCount)
		return 0;

	UInt32 framesRead = 0;
	
	// Reset output buffer data size
	for(UInt32 i = 0; i < bufferList->mNumberBuffers; ++i)
		bufferList->mBuffers[i].mDataByteSize = 0;

	for(;;) {
		
		UInt32	framesRemaining	= frameCount - framesRead;
		UInt32	framesToSkip	= static_cast<UInt32>(bufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesInBuffer	= static_cast<UInt32>(mBufferList->mBuffers[0].mDataByteSize / sizeof(float));
		UInt32	framesToCopy	= std::min(framesInBuffer, framesRemaining);
		
		// Copy data from the buffer to output
		for(UInt32 i = 0; i < mBufferList->mNumberBuffers; ++i) {
			float *floatBuffer = static_cast<float *>(bufferList->mBuffers[i].mData);
			memcpy(floatBuffer + framesToSkip, mBufferList->mBuffers[i].mData, framesToCopy * sizeof(float));
			bufferList->mBuffers[i].mDataByteSize += static_cast<UInt32>(framesToCopy * sizeof(float));
			
			// Move remaining data in buffer to beginning
			if(framesToCopy != framesInBuffer) {
				floatBuffer = static_cast<float *>(mBufferList->mBuffers[i].mData);
				memmove(floatBuffer, floatBuffer + framesToCopy, (framesInBuffer - framesToCopy) * sizeof(float));
			}
			
			mBufferList->mBuffers[i].mDataByteSize -= static_cast<UInt32>(framesToCopy * sizeof(float));
		}
		
		framesRead += framesToCopy;
		
		// All requested frames were read
		if(framesRead == frameCount)
			break;
		
		// EOS reached
		if(mSpeexEOSReached)
			break;

		// Attempt to process the desired number of packets
		unsigned packetsDesired = 1;
		while(0 < packetsDesired && !mSpeexEOSReached) {

			// Process any packets in the current page
			while(0 < packetsDesired && !mSpeexEOSReached) {

				// Grab a packet from the streaming layer
				ogg_packet oggPacket;
				int result = ogg_stream_packetout(&mOggStreamState, &oggPacket);
				if(-1 == result) {
					LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding error: Ogg loss of streaming");
					break;
				}
				
				// If result is 0, there is insufficient data to assemble a packet
				if(0 == result)
					break;

				// Otherwise, we got a valid packet for processing
				if(1 == result) {
					if(5 <= oggPacket.bytes && !memcmp(oggPacket.packet, "Speex", 5))
						mSpeexSerialNumber = mOggStreamState.serialno;
					
					if(-1 == mSpeexSerialNumber || mOggStreamState.serialno != mSpeexSerialNumber)
						break;
					
					// Ignore the following:
					//  - Speex comments in packet #2
					//  - Extra headers (optionally) in packets 3+
					if(1 != mOggPacketCount && 1 + mExtraSpeexHeaderCount <= mOggPacketCount) {
						// Detect Speex EOS
						if(oggPacket.e_o_s && mOggStreamState.serialno == mSpeexSerialNumber)
							mSpeexEOSReached = true;

						// SPEEX_GET_FRAME_SIZE is in samples
						spx_int32_t speexFrameSize;
						speex_decoder_ctl(mSpeexDecoder, SPEEX_GET_FRAME_SIZE, &speexFrameSize);
						float buffer [(2 == mFormat.mChannelsPerFrame) ? 2 * speexFrameSize : speexFrameSize];
						
						// Copy the Ogg packet to the Speex bitstream
						speex_bits_read_from(&mSpeexBits, (char *)oggPacket.packet, static_cast<int>(oggPacket.bytes));
						
						// Decode each frame in the Speex packet
						for(spx_int32_t i = 0; i < mSpeexFramesPerOggPacket; ++i) {
							
							result = speex_decode(mSpeexDecoder, &mSpeexBits, buffer);

							// -1 indicates EOS
							if(-1 == result)
								break;
							else if(-2 == result) {
								LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding error: possible corrupted stream");
								break;
							}
							
							if(0 > speex_bits_remaining(&mSpeexBits)) {
								LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Ogg Speex decoding overflow: possible corrupted stream");
								break;
							}
							
							// Normalize the values
							float maxSampleValue = 1u << 15;
							vDSP_vsdiv(buffer, 1, &maxSampleValue, buffer, 1, speexFrameSize);

							// Copy the frames from the decoding buffer to the output buffer, skipping over any frames already decoded
							framesInBuffer = static_cast<UInt32>(mBufferList->mBuffers[0].mDataByteSize / sizeof(float));
							memcpy(static_cast<float *>(mBufferList->mBuffers[0].mData) + framesInBuffer, buffer, speexFrameSize * sizeof(float));
							mBufferList->mBuffers[0].mDataByteSize += static_cast<UInt32>(speexFrameSize * sizeof(float));
							
							// Process stereo channel, if present
							if(2 == mFormat.mChannelsPerFrame) {
								speex_decode_stereo(buffer, speexFrameSize, mSpeexStereoState);
								vDSP_vsdiv(buffer + speexFrameSize, 1, &maxSampleValue, buffer + speexFrameSize, 1, speexFrameSize);

								memcpy(static_cast<float *>(mBufferList->mBuffers[1].mData) + framesInBuffer, buffer + speexFrameSize, speexFrameSize * sizeof(float));
								mBufferList->mBuffers[1].mDataByteSize += static_cast<UInt32>(speexFrameSize * sizeof(float));
							}
							
							// Packet processing finished
							--packetsDesired;
						}
					}

					++mOggPacketCount;
				}
			}
			
			// Grab a new Ogg page for processing, if necessary
			if(!mSpeexEOSReached && 0 < packetsDesired) {
				while(1 != ogg_sync_pageout(&mOggSyncState, &mOggPage)) {
					// Get the ogg buffer for writing
					char *data = ogg_sync_buffer(&mOggSyncState, READ_SIZE_BYTES);
					
					// Read bitstream from input file
					ssize_t bytesRead = GetInputSource()->Read(data, READ_SIZE_BYTES);
					if(-1 == bytesRead) {
						LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Unable to read from the input file");
						break;
					}
					
					ogg_sync_wrote(&mOggSyncState, bytesRead);

					// No more data available from input file
					if(0 == bytesRead)
						break;
				}
				
				// Ensure all Ogg streams are read
				if(ogg_page_serialno(&mOggPage) != mOggStreamState.serialno)
					ogg_stream_reset_serialno(&mOggStreamState, ogg_page_serialno(&mOggPage));

				// Get the resultant Ogg page
				int result = ogg_stream_pagein(&mOggStreamState, &mOggPage);
				if(0 != result) {
					LOGGER_ERR("org.sbooth.AudioEngine.AudioDecoder.OggSpeex", "Error reading Ogg page");
					break;
				}
			}
		}
	}
	
	mCurrentFrame += framesRead;

	if(0 == framesRead && mSpeexEOSReached)
		mTotalFrames = mCurrentFrame;

	return framesRead;
}
Пример #17
0
/* This function will iterate frames & submodes in the Speex bits.
 * Returns 0 if a frame found, otherwise returns -1.
 */
int speex_get_next_frame(SpeexBits *bits)
{
    static const int inband_skip_table[NB_SUBMODES] =
       {1, 1, 4, 4, 4, 4, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 };
    static const int wb_skip_table[SB_SUBMODES] =
       {SB_SUBMODE_BITS+1, 36, 112, 192, 352, -1, -1, -1};

    unsigned submode;
    unsigned nb_count = 0;

    while (speex_bits_remaining(bits) >= 5) {
	unsigned wb_count = 0;
	unsigned bit_ptr = bits->bitPtr;
	unsigned char_ptr = bits->charPtr;

	/* WB frame */
	while ((speex_bits_remaining(bits) >= 4)
	    && speex_bits_unpack_unsigned(bits, 1))
	{
	    int advance;

	    submode = speex_bits_unpack_unsigned(bits, 3);
	    advance = wb_skip_table[submode];
	    if (advance < 0) {
		TRACE__((THIS_FUNC, "Invalid mode encountered. "
			 "The stream is corrupted."));
		return -1;
	    } 
	    TRACE__((THIS_FUNC, "WB layer skipped: %d bits", advance));
	    advance -= (SB_SUBMODE_BITS+1);
	    speex_bits_advance(bits, advance);

	    bit_ptr = bits->bitPtr;
	    char_ptr = bits->charPtr;

	    /* Consecutive subband frames may not exceed 2 frames */
	    if (++wb_count > 2)
		return -1;
	}

	/* End of bits, return the frame */
	if (speex_bits_remaining(bits) < 4) {
	    TRACE__((THIS_FUNC, "End of stream"));
	    return 0;
	}

	/* Stop iteration, return the frame */
	if (nb_count > 0) {
	    bits->bitPtr = bit_ptr;
	    bits->charPtr = char_ptr;
	    return 0;
	}

	/* Get control bits */
	submode = speex_bits_unpack_unsigned(bits, 4);
	TRACE__((THIS_FUNC, "Control bits: %d at %d", 
		 submode, bits->charPtr*8+bits->bitPtr));

	if (submode == 15) {
	    TRACE__((THIS_FUNC, "Found submode: terminator"));
	    return -1;
	} else if (submode == 14) {
	    /* in-band signal; next 4 bits contain signal id */
	    submode = speex_bits_unpack_unsigned(bits, 4);
	    TRACE__((THIS_FUNC, "Found submode: in-band %d bits", 
		     inband_skip_table[submode]));
	    speex_bits_advance(bits, inband_skip_table[submode]);
	} else if (submode == 13) {
	    /* user in-band; next 5 bits contain msg len */
	    submode = speex_bits_unpack_unsigned(bits, 5);
	    TRACE__((THIS_FUNC, "Found submode: user-band %d bytes", submode));
	    speex_bits_advance(bits, submode * 8);
	} else if (submode > 8) {
	    TRACE__((THIS_FUNC, "Unknown sub-mode %d", submode));
	    return -1;
	} else {
	    /* NB frame */
	    unsigned int advance = submode;
	    speex_mode_query(&speex_nb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance);
	    if (advance < 0) {
		TRACE__((THIS_FUNC, "Invalid mode encountered. "
			 "The stream is corrupted."));
		return -1;
	    }
	    TRACE__((THIS_FUNC, "Submode %d: %d bits", submode, advance));
	    advance -= (NB_SUBMODE_BITS+1);
	    speex_bits_advance(bits, advance);

	    ++nb_count;
	}
    }

    return 0;
}
Пример #18
0
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;
}
Пример #19
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(&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;
}
Пример #20
0
static void dec_process(MSFilter *f){
	DecState *s=(DecState*)f->data;
	mblk_t *im;
	mblk_t *om;
	int err=-2;
	SpeexBits bits;
	int bytes=s->frsz*2;
	bool_t bits_initd=FALSE;

	while((im=ms_queue_get(f->inputs[0]))!=NULL){
		int rem_bits=(im->b_wptr-im->b_rptr)*8;

		if (!bits_initd) {
			speex_bits_init(&bits);
			bits_initd=TRUE;
		}else speex_bits_reset(&bits);

		speex_bits_read_from(&bits,(char*)im->b_rptr,im->b_wptr-im->b_rptr);

		/* support for multiple frame  in one RTP packet */
 		do{
			om=allocb(bytes,0);
			mblk_meta_copy(im, om);
			err=speex_decode_int(s->state,&bits,(int16_t*)om->b_wptr);
			om->b_wptr+=bytes;

			if (err==0){
				ms_queue_put(f->outputs[0],om);
				if (s->sample_time==0) s->sample_time=f->ticker->time;
				s->sample_time+=20;
				if (s->plc_count>0){
					// ms_warning("Did speex packet loss concealment during %i ms",s->plc_count*20);
					s->plc_count=0;
				}

			}else {
				if (err==-1)
					ms_warning("speex end of stream");
				else if (err==-2)
					ms_warning("speex corrupted stream");
				freemsg(om);
			}
		}while((rem_bits= speex_bits_remaining(&bits))>10);
		freemsg(im);
	}
	if (s->plc && s->sample_time!=0 && f->ticker->time>=s->sample_time){
		/* we should output a frame but no packet were decoded
		 thus do packet loss concealment*/
		om=allocb(bytes,0);
		err=speex_decode_int(s->state,NULL,(int16_t*)om->b_wptr);
		om->b_wptr+=bytes;
		mblk_set_plc_flag(om, 1);
		ms_queue_put(f->outputs[0],om);

		s->sample_time+=20;
		s->plc_count++;
		if (s->plc_count>=plc_max){
			s->sample_time=0;
		}
	}
	if (bits_initd) speex_bits_destroy(&bits);
}