Ejemplo n.º 1
0
// Filter len bytes of input, put result into outbuf.
static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf,
                          int len)
{
    int error = 0;

    struct mp_audio config;
    mp_audio_buffer_get_format(da->decode_buffer, &config);

    while (mp_audio_buffer_samples(da->decode_buffer) < len) {
        int maxlen = mp_audio_buffer_get_write_available(da->decode_buffer);
        if (maxlen < DECODE_MAX_UNIT)
            break;
        struct mp_audio buffer;
        mp_audio_buffer_get_write_buffer(da->decode_buffer, maxlen, &buffer);
        buffer.samples = 0;
        error = da->ad_driver->decode_audio(da, &buffer, maxlen);
        if (error < 0)
            break;
        // Commit the data just read as valid data
        mp_audio_buffer_finish_write(da->decode_buffer, buffer.samples);
        // Format change
        if (!mp_audio_config_equals(&da->decoded, &config)) {
            // If there are still samples left in the buffer, let them drain
            // first, and don't signal a format change to the caller yet.
            if (mp_audio_buffer_samples(da->decode_buffer) > 0)
                break;
            error = -2;
            break;
        }
    }

    // Filter
    struct mp_audio filter_input;
    mp_audio_buffer_peek(da->decode_buffer, &filter_input);
    filter_input.rate = da->afilter->input.rate; // due to playback speed change
    len = MPMIN(filter_input.samples, len);
    filter_input.samples = len;

    struct mp_audio *filter_output = af_play(da->afilter, &filter_input);
    if (!filter_output)
        return -1;
    mp_audio_buffer_append(outbuf, filter_output);

    // remove processed data from decoder buffer:
    mp_audio_buffer_skip(da->decode_buffer, len);

    // Assume the filter chain is drained from old data at this point.
    // (If not, the remaining old data is discarded.)
    if (error == -2)
        reinit_audio_buffer(da);

    return error;
}
Ejemplo n.º 2
0
static int filter_n_bytes(sh_audio_t *sh, struct bstr *outbuf, int len)
{
    assert(len-1 + sh->audio_out_minsize <= sh->a_buffer_size);

    int error = 0;

    // Decode more bytes if needed
    int old_samplerate = sh->samplerate;
    int old_channels = sh->channels;
    int old_sample_format = sh->sample_format;
    while (sh->a_buffer_len < len) {
	unsigned char *buf = sh->a_buffer + sh->a_buffer_len;
	int minlen = len - sh->a_buffer_len;
	int maxlen = sh->a_buffer_size - sh->a_buffer_len;
	int ret = sh->ad_driver->decode_audio(sh, buf, minlen, maxlen);
	int format_change = sh->samplerate != old_samplerate
                            || sh->channels != old_channels
                            || sh->sample_format != old_sample_format;
	if (ret <= 0 || format_change) {
	    error = format_change ? -2 : -1;
            // samples from format-changing call get discarded too
	    len = sh->a_buffer_len;
	    break;
	}
	sh->a_buffer_len += ret;
    }

    // Filter
    af_data_t filter_input = {
	.audio = sh->a_buffer,
	.len = len,
	.rate = sh->samplerate,
	.nch = sh->channels,
	.format = sh->sample_format
    };
    af_fix_parameters(&filter_input);
    af_data_t *filter_output = af_play(sh->afilter, &filter_input);
    if (!filter_output)
	return -1;
    set_min_out_buffer_size(outbuf, outbuf->len + filter_output->len);
    memcpy(outbuf->start + outbuf->len, filter_output->audio,
           filter_output->len);
    outbuf->len += filter_output->len;

    // remove processed data from decoder buffer:
    sh->a_buffer_len -= len;
    memmove(sh->a_buffer, sh->a_buffer + len, sh->a_buffer_len);

    return error;
}

/* Try to get at least minlen decoded+filtered bytes in outbuf
 * (total length including possible existing data).
 * Return 0 on success, -1 on error/EOF (not distinguished).
 * In the former case outbuf->len is always >= minlen on return.
 * In case of EOF/error it might or might not be.
 * Outbuf.start must be talloc-allocated, and will be reallocated
 * if needed to fit all filter output. */
int decode_audio(sh_audio_t *sh_audio, struct bstr *outbuf, int minlen)
{
    // Indicates that a filter seems to be buffering large amounts of data
    int huge_filter_buffer = 0;
    // Decoded audio must be cut at boundaries of this many bytes
    int unitsize = sh_audio->channels * sh_audio->samplesize * 16;

    /* Filter output size will be about filter_multiplier times input size.
     * If some filter buffers audio in big blocks this might only hold
     * as average over time. */
    double filter_multiplier = af_calc_filter_multiplier(sh_audio->afilter);

    /* If the decoder set audio_out_minsize then it can do the equivalent of
     * "while (output_len < target_len) output_len += audio_out_minsize;",
     * so we must guarantee there is at least audio_out_minsize-1 bytes
     * more space in the output buffer than the minimum length we try to
     * decode. */
    int max_decode_len = sh_audio->a_buffer_size - sh_audio->audio_out_minsize;
    max_decode_len -= max_decode_len % unitsize;

    while (outbuf->len < minlen) {
	int declen = (minlen - outbuf->len) / filter_multiplier
	    + (unitsize << 5); // some extra for possible filter buffering
	if (huge_filter_buffer)
	/* Some filter must be doing significant buffering if the estimated
	 * input length didn't produce enough output from filters.
	 * Feed the filters 2k bytes at a time until we have enough output.
	 * Very small amounts could make filtering inefficient while large
	 * amounts can make MPlayer demux the file unnecessarily far ahead
	 * to get audio data and buffer video frames in memory while doing
	 * so. However the performance impact of either is probably not too
	 * significant as long as the value is not completely insane. */
	    declen = 2000;
	declen -= declen % unitsize;
	if (declen > max_decode_len)
	    declen = max_decode_len;
	else
	    /* if this iteration does not fill buffer, we must have lots
	     * of buffering in filters */
	    huge_filter_buffer = 1;
	int res = filter_n_bytes(sh_audio, outbuf, declen);
	if (res < 0)
	    return res;
    }
    return 0;
}
Ejemplo n.º 3
0
int decode_audio(sh_audio_t *sh_audio,unsigned char *buf,int minlen,int maxlen)
{
  int declen;
  af_data_t  afd;  // filter input
  af_data_t* pafd; // filter output
  ad_functions_t* mpadec = sh_audio->ad_driver;

  if(!sh_audio->inited) return -1; // no codec
  if(!sh_audio->afilter){
      // no filter, just decode:
      // FIXME: don't drop initial decoded data in a_buffer!
      return mpadec->decode_audio(sh_audio,buf,minlen,maxlen);
  }
  
//  declen=af_inputlen(sh_audio->afilter,minlen);
  declen=af_calc_insize_constrained(sh_audio->afilter,minlen,maxlen,
      sh_audio->a_buffer_size-sh_audio->audio_out_minsize);

  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\ndecaudio: minlen=%d maxlen=%d declen=%d (max=%d)\n",
      minlen, maxlen, declen, sh_audio->a_buffer_size);

  if(declen<=0) return -1; // error!

  // limit declen to buffer size: - DONE by af_calc_insize_constrained
//  if(declen>sh_audio->a_buffer_size) declen=sh_audio->a_buffer_size;

  // decode if needed:
  while(declen>sh_audio->a_buffer_len){
      int len=declen-sh_audio->a_buffer_len;
      int maxlen=sh_audio->a_buffer_size-sh_audio->a_buffer_len;

      mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"decaudio: decoding %d bytes, max: %d (%d)\n",
        len, maxlen, sh_audio->audio_out_minsize);

      // When a decoder sets audio_out_minsize that should guarantee it can
      // write up to audio_out_minsize bytes at a time until total >= minlen
      // without checking maxlen. Thus maxlen must be at least minlen +
      // audio_out_minsize. Check that to guard against buffer overflows.
      if (maxlen < len + sh_audio->audio_out_minsize)
	  break;
      // not enough decoded data waiting, decode 'len' bytes more:
      len=mpadec->decode_audio(sh_audio,
          sh_audio->a_buffer+sh_audio->a_buffer_len, len, maxlen);
      if(len<=0) break; // EOF?
      sh_audio->a_buffer_len+=len;
  }
  if(declen>sh_audio->a_buffer_len)
    declen=sh_audio->a_buffer_len; // still no enough data (EOF) :(

  // round to whole samples:
//  declen/=sh_audio->samplesize*sh_audio->channels;
//  declen*=sh_audio->samplesize*sh_audio->channels;

  // run the filters:
  afd.audio=sh_audio->a_buffer;
  afd.len=declen;
  afd.rate=sh_audio->samplerate;
  afd.nch=sh_audio->channels;
  afd.format=sh_audio->sample_format;
  af_fix_parameters(&afd);
  //pafd=&afd;
//  printf("\nAF: %d --> ",declen);
  pafd=af_play(sh_audio->afilter,&afd);
//  printf("%d  \n",pafd->len);

  if(!pafd) return -1; // error

  mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"decaudio: declen=%d out=%d (max %d)\n",
      declen, pafd->len, maxlen);
  
  // copy filter==>out:
  if(maxlen < pafd->len) {
    af_stream_t *afs = sh_audio->afilter;
    maxlen -= maxlen % (afs->output.nch * afs->output.bps);
    mp_msg(MSGT_DECAUDIO,MSGL_WARN,"%i bytes of audio data lost due to buffer overflow, len = %i\n", pafd->len - maxlen,pafd->len);
  }
  else
    maxlen=pafd->len;
  memmove(buf, pafd->audio, maxlen);
  
  // remove processed data from decoder buffer:
  sh_audio->a_buffer_len-=declen;
  if(sh_audio->a_buffer_len>0)
    memmove(sh_audio->a_buffer, sh_audio->a_buffer+declen, sh_audio->a_buffer_len);
  
  return maxlen;
}