Ejemplo n.º 1
0
void _ffmpegPostAudioFrame(struct GBAAVStream* stream, int32_t left, int32_t right) {
	struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
	if (!encoder->context || !encoder->audioCodec) {
		return;
	}

	encoder->audioBuffer[encoder->currentAudioSample * 2] = left;
	encoder->audioBuffer[encoder->currentAudioSample * 2 + 1] = right;

	++encoder->currentAudioFrame;
	++encoder->currentAudioSample;

	if ((encoder->currentAudioSample * 4) < encoder->audioBufferSize) {
		return;
	}
	encoder->currentAudioSample = 0;

	int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt);
	avresample_convert(encoder->resampleContext,
		0, 0, 0,
		(uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4);
	if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) {
		return;
	}
#if LIBAVCODEC_VERSION_MAJOR >= 55
	av_frame_make_writable(encoder->audioFrame);
#endif
	avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize);

	AVRational timeBase = { 1, PREFERRED_SAMPLE_RATE };
	encoder->audioFrame->pts = encoder->nextAudioPts;
	encoder->nextAudioPts = av_rescale_q(encoder->currentAudioFrame, timeBase, encoder->audioStream->time_base);

	AVPacket packet;
	av_init_packet(&packet);
	packet.data = 0;
	packet.size = 0;
	int gotData;
	avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData);
	if (gotData) {
		if (encoder->absf) {
			AVPacket tempPacket = packet;
			int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0,
				&tempPacket.data, &tempPacket.size,
				packet.data, packet.size, 0);
			if (success > 0) {
#if LIBAVUTIL_VERSION_MAJOR >= 53
				tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0);
#endif
				av_free_packet(&packet);
			}
			packet = tempPacket;
		}
		packet.stream_index = encoder->audioStream->index;
		av_interleaved_write_frame(encoder->context, &packet);
	}
	av_free_packet(&packet);
}
Ejemplo n.º 2
0
static int control(struct af_instance *af, int cmd, void *arg)
{
    struct af_resample *s = af->priv;

    switch (cmd) {
    case AF_CONTROL_REINIT: {
        struct mp_audio *in = arg;
        struct mp_audio *out = af->data;
        struct mp_audio orig_in = *in;

        if (((out->rate    == in->rate) || (out->rate == 0)) &&
            (out->format   == in->format) &&
            (mp_chmap_equals(&out->channels, &in->channels) || out->nch == 0) &&
            s->allow_detach && s->playback_speed == 1.0)
            return AF_DETACH;

        if (out->rate == 0)
            out->rate = in->rate;

        if (mp_chmap_is_empty(&out->channels))
            mp_audio_set_channels(out, &in->channels);

        if (af_to_avformat(in->format) == AV_SAMPLE_FMT_NONE)
            mp_audio_set_format(in, AF_FORMAT_FLOAT);
        if (check_output_conversion(out->format) == AV_SAMPLE_FMT_NONE)
            mp_audio_set_format(out, in->format);

        int r = ((in->format == orig_in.format) &&
                mp_chmap_equals(&in->channels, &orig_in.channels))
                ? AF_OK : AF_FALSE;

        if (r == AF_OK)
            r = configure_lavrr(af, in, out, true);
        return r;
    }
    case AF_CONTROL_SET_PLAYBACK_SPEED_RESAMPLE: {
        s->playback_speed = *(double *)arg;
        return AF_OK;
    }
    case AF_CONTROL_RESET:
        if (s->avrctx) {
#if HAVE_LIBSWRESAMPLE
            swr_close(s->avrctx);
            if (swr_init(s->avrctx) < 0) {
                close_lavrr(af);
                return AF_ERROR;
            }
#else
            while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
#endif
        }
        return AF_OK;
    }
    return AF_UNKNOWN;
}
Ejemplo n.º 3
0
static int
android_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;
  SLresult result;



  float gain = audio_master_mute ? 0.0f : (d->d_gain * audio_master_volume);
  if(gain != d->d_last_set_vol) {
    d->d_last_set_vol = gain;

    int mb = lroundf(2000.f * log10f(gain));
    mb = MAX(mb, SL_MILLIBEL_MIN);
    (*d->d_vif)->SetVolumeLevel(d->d_vif, mb);
  }

  if(d->d_avail_buffers == 0)
    return 1;

  assert(samples <= ad->ad_tile_size);

  void *pcm = d->d_pcmbuf + (d->d_pcmbuf_offset * d->d_pcmbuf_size);

  uint8_t *data[8] = {0};
  data[0] = pcm;
  int r = avresample_read(ad->ad_avr, data, ad->ad_tile_size);
  result = (*d->d_bif)->Enqueue(d->d_bif, pcm, r * d->d_framesize);

  d->d_avail_buffers--;
  d->d_pcmbuf_offset++;

  if(d->d_pcmbuf_offset == d->d_pcmbuf_num_buffers)
    d->d_pcmbuf_offset = 0;

  if(pts != AV_NOPTS_VALUE) {

    media_pipe_t *mp = ad->ad_mp;
    hts_mutex_lock(&mp->mp_clock_mutex);

    int delay = 42666; // 2 * 1024 samples in 48kHz

    mp->mp_audio_clock = pts - delay;
    mp->mp_audio_clock_epoch = epoch;
    mp->mp_audio_clock_avtime = arch_get_avtime();

    hts_mutex_unlock(&mp->mp_clock_mutex);
  }

  if(result)
    TRACE(TRACE_ERROR, "SLES", "Enqueue failed 0x%x", result);

  return 0;
}
Ejemplo n.º 4
0
static int
alsa_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;
  media_pipe_t *mp = ad->ad_mp;
  int c;

 retry:
  c = snd_pcm_wait(d->h, 100);
  if(c >= 0) {
    c = snd_pcm_avail_update(d->h);
  }
  if(c == -EPIPE) {
    snd_pcm_prepare(d->h);
    usleep(100000);
    TRACE(TRACE_DEBUG, "ALSA", "Audio underrun");
    d->samples = 0;
    goto retry;
  }

  c = MIN(d->max_frames_per_write, c);

  uint8_t *planes[8] = {0};
  planes[0] = d->tmp;
  c = avresample_read(ad->ad_avr, planes, c);
  
  snd_pcm_status_t *status;
  int err;
  snd_pcm_status_alloca(&status);
  if ((err = snd_pcm_status(d->h, status)) >= 0) {

    if(pts != AV_NOPTS_VALUE) {
      snd_htimestamp_t hts;
      snd_pcm_status_get_trigger_htstamp(status, &hts);
      int64_t ts = hts.tv_sec * 1000000LL + hts.tv_nsec / 1000;
      ts += d->samples * 1000000LL / ad->ad_out_sample_rate;

      hts_mutex_lock(&mp->mp_clock_mutex);
      mp->mp_audio_clock_avtime = ts;
      mp->mp_audio_clock = pts;
      mp->mp_audio_clock_epoch = epoch;
      hts_mutex_unlock(&mp->mp_clock_mutex);
    }
  }

  snd_pcm_sframes_t fr;
  if(!snd_pcm_delay(d->h, &fr))
    ad->ad_delay = 1000000L * fr / ad->ad_out_sample_rate;

  c = snd_pcm_writei(d->h, d->tmp, c);
  d->samples += c;
  return 0;
}
Ejemplo n.º 5
0
static void handle_trimming(AVFilterContext *ctx)
{
    ASyncContext *s = ctx->priv;

    if (s->pts < s->first_pts) {
        int delta = FFMIN(s->first_pts - s->pts, avresample_available(s->avr));
        av_log(ctx, AV_LOG_VERBOSE, "Trimming %d samples from start\n",
               delta);
        avresample_read(s->avr, NULL, delta);
        s->pts += delta;
    } else if (s->first_frame)
        s->pts = s->first_pts;
}
Ejemplo n.º 6
0
static int
android_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;
  SLresult result;

  if(d->d_avail_buffers == 0)
    return 1;

  assert(samples <= ad->ad_tile_size);

  void *pcm = d->d_pcmbuf + (d->d_pcmbuf_offset * d->d_pcmbuf_size);

  uint8_t *data[8] = {0};
  data[0] = pcm;
  int r = avresample_read(ad->ad_avr, data, ad->ad_tile_size);
  result = (*d->d_bif)->Enqueue(d->d_bif, pcm, r * d->d_framesize);

  d->d_avail_buffers--;
  d->d_pcmbuf_offset++;

  if(d->d_pcmbuf_offset == d->d_pcmbuf_num_buffers)
    d->d_pcmbuf_offset = 0;

  if(pts != AV_NOPTS_VALUE) {

    media_pipe_t *mp = ad->ad_mp;
    hts_mutex_lock(&mp->mp_clock_mutex);

    int delay = 42666; // 2 * 1024 samples in 48kHz

    mp->mp_audio_clock = pts - delay;
    mp->mp_audio_clock_epoch = epoch;
    mp->mp_audio_clock_avtime = showtime_get_avtime();

    hts_mutex_unlock(&mp->mp_clock_mutex);
  }

  if(result)
    TRACE(TRACE_ERROR, "SLES", "Enqueue failed 0x%x", result);

  return 0;
}
Ejemplo n.º 7
0
void AudioConverter::feedEncoder()
{
	int gotFrame = 0, err;
	uint8_t *output;
	int out_linesize;
	int avail;

	if (!m_encoderInitialized)
		initEncoder();
	
	assert(m_avpktOutUsed == m_avpktOut.size);

	do
	{
		avail = avresample_available(m_resampler);
		av_samples_alloc(&output, &out_linesize, m_destinationFormat.mChannelsPerFrame, avail, m_encoder->sample_fmt, 0);

		if (avresample_read(m_resampler, &output, avail) != avail)
			throw std::runtime_error("avresample_read() failed");
	
		av_init_packet(&m_avpktOut);
		m_avpktOut.data = 0;
		m_avpktOut.size = 0;
		m_avpktOutUsed = 0;

		LOG << "Got " << avail << " samples\n";
		err = avcodec_fill_audio_frame(m_audioFrame, m_encoder->channels,
				m_encoder->sample_fmt, output, avail * m_destinationFormat.mChannelsPerFrame * (m_destinationFormat.mBitsPerChannel / 8),
				m_destinationFormat.mChannelsPerFrame * (m_destinationFormat.mBitsPerChannel / 8));
		
		if (err < 0)
			throw std::runtime_error("avcodec_fill_audio_frame() failed");

		// Encode PCM data
		err = avcodec_encode_audio2(m_encoder, &m_avpktOut, m_audioFrame, &gotFrame);
		av_freep(&output);
		
		if (err < 0)
			throw std::runtime_error("avcodec_encode_audio2() failed");
	}
	while(!gotFrame);
}
Ejemplo n.º 8
0
static int
nacl_audio_deliver(audio_decoder_t *ad, int samples, int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;

  pthread_mutex_lock(&d->mutex);

  while((d->rdptr & SLOTMASK) == (d->wrptr & SLOTMASK) &&
        d->wrptr != d->rdptr)
    pthread_cond_wait(&d->cond, &d->mutex);

  pthread_mutex_unlock(&d->mutex);

  int off = (d->wrptr & SLOTMASK) * 2 * d->ad.ad_tile_size;

  uint8_t *data[8] = {0};
  data[0] = (uint8_t *)(d->samples + off);
  avresample_read(ad->ad_avr, data, samples);
  d->wrptr++;

  if(pts != AV_NOPTS_VALUE) {

    int64_t delay = d->fifo_latency + d->nacl_latency * 1000000.0;
    ad->ad_delay = delay;

    media_pipe_t *mp = ad->ad_mp;

    hts_mutex_lock(&mp->mp_clock_mutex);
    mp->mp_audio_clock_avtime = arch_get_avtime();
    mp->mp_audio_clock_epoch = epoch;
    mp->mp_audio_clock = pts - delay;
    hts_mutex_unlock(&mp->mp_clock_mutex);
  }

  return 0;
}
Ejemplo n.º 9
0
static void drop_all_output(struct af_resample *s)
{
    while (avresample_read(s->avrctx, NULL, 1000) > 0) {}
}
Ejemplo n.º 10
0
void *
audio_decode_thread(void *aux)
{
  audio_decoder_t *ad = aux;
  const audio_class_t *ac = ad->ad_ac;
  int run = 1;
  media_pipe_t *mp = ad->ad_mp;
  media_queue_t *mq = &mp->mp_audio;
  media_buf_t *mb;
  int blocked = 0;

  if(ac->ac_init != NULL)
    ac->ac_init(ad);

  ad->ad_discontinuity = 1;

  hts_mutex_lock(&mp->mp_mutex);

  while(run) {

    int avail;
    
    if(ad->ad_spdif_muxer != NULL) {
      avail = ad->ad_spdif_frame_size;
    } else {
      avail = ad->ad_avr != NULL ? avresample_available(ad->ad_avr) : 0;
    }
    media_buf_t *data = TAILQ_FIRST(&mq->mq_q_data);
    media_buf_t *ctrl = TAILQ_FIRST(&mq->mq_q_ctrl);

    if(avail >= ad->ad_tile_size && blocked == 0 && !ad->ad_paused && !ctrl) {
      assert(avail != 0);

      int samples = MIN(ad->ad_tile_size, avail);
      int r;

      if(ac->ac_deliver_locked != NULL) {
        r = ac->ac_deliver_locked(ad, samples, ad->ad_pts, ad->ad_epoch);
        if(r) {
          hts_cond_wait(&mq->mq_avail, &mp->mp_mutex);
          continue;
        }
      } else {
        hts_mutex_unlock(&mp->mp_mutex);
        r = ac->ac_deliver_unlocked(ad, samples, ad->ad_pts, ad->ad_epoch);
        hts_mutex_lock(&mp->mp_mutex);
      }

      if(r) {
	blocked = 1;
      } else {
	ad->ad_pts = AV_NOPTS_VALUE;
      }
      continue;
    }

    if(ctrl != NULL) {
      TAILQ_REMOVE(&mq->mq_q_ctrl, ctrl, mb_link);
      mb = ctrl;
    } else if(data != NULL && avail < ad->ad_tile_size) {
      TAILQ_REMOVE(&mq->mq_q_data, data, mb_link);
      mb = data;
    } else {
      hts_cond_wait(&mq->mq_avail, &mp->mp_mutex);
      continue;
    }

    mq->mq_packets_current--;
    mp->mp_buffer_current -= mb->mb_size;
    mq_update_stats(mp, mq);
    hts_cond_signal(&mp->mp_backpressure);

    if(mb->mb_data_type == MB_CTRL_UNBLOCK) {
      assert(blocked);
      blocked = 0;
    } else if(ad->ad_mode == AUDIO_MODE_CODED && 
	      ac->ac_deliver_coded_locked != NULL &&
	      mb->mb_data_type == MB_AUDIO) {

      ac->ac_deliver_coded_locked(ad, mb->mb_data, mb->mb_size,
				  mb->mb_pts, mb->mb_epoch);

    } else {

      hts_mutex_unlock(&mp->mp_mutex);

      switch(mb->mb_data_type) {
      case MB_AUDIO:
	audio_process_audio(ad, mb);
	break;

      case MB_SET_PROP_STRING:
        prop_set_string(mb->mb_prop, (void *)mb->mb_data);
	break;

      case MB_CTRL_SET_VOLUME_MULTIPLIER:
        ad->ad_vol_scale = mb->mb_float;
	if(ac->ac_set_volume != NULL)
	  ac->ac_set_volume(ad, ad->ad_vol_scale);
        break;

      case MB_CTRL_PAUSE:
	ad->ad_paused = 1;
	if(ac->ac_pause)
	  ac->ac_pause(ad);
	break;

      case MB_CTRL_PLAY:
	ad->ad_paused = 0;
	if(ac->ac_play)
	  ac->ac_play(ad);
	break;

      case MB_CTRL_FLUSH:
        // Reset some error reporting filters
        ad->ad_channel_layout_fail = 0;
        ad->ad_sample_rate_fail = 0;

	if(ac->ac_flush)
	  ac->ac_flush(ad);
	ad->ad_pts = AV_NOPTS_VALUE;

	if(mp->mp_seek_audio_done != NULL)
	  mp->mp_seek_audio_done(mp);
	ad->ad_discontinuity = 1;

	if(ad->ad_avr != NULL) {
	  avresample_read(ad->ad_avr, NULL, avresample_available(ad->ad_avr));
	  assert(avresample_available(ad->ad_avr) == 0);
	}
	break;

      case MB_CTRL_EXIT:
	run = 0;
	break;

      default:
	abort();
      }

      hts_mutex_lock(&mp->mp_mutex);
    }
    media_buf_free_locked(mp, mb);
  }

  hts_mutex_unlock(&mp->mp_mutex);

  if(ac->ac_fini != NULL)
    ac->ac_fini(ad);
  return NULL;
}
Ejemplo n.º 11
0
void _ffmpegPostAudioFrame(struct mAVStream* stream, int16_t left, int16_t right) {
	struct FFmpegEncoder* encoder = (struct FFmpegEncoder*) stream;
	if (!encoder->context || !encoder->audioCodec) {
		return;
	}

	if (encoder->absf && !left) {
		// XXX: AVBSF doesn't like silence. Figure out why.
		left = 1;
	}

	encoder->audioBuffer[encoder->currentAudioSample * 2] = left;
	encoder->audioBuffer[encoder->currentAudioSample * 2 + 1] = right;

	++encoder->currentAudioSample;

	if (encoder->currentAudioSample * 4 < encoder->audioBufferSize) {
		return;
	}

	int channelSize = 2 * av_get_bytes_per_sample(encoder->audio->sample_fmt);
	encoder->currentAudioSample = 0;
#ifdef USE_LIBAVRESAMPLE
	avresample_convert(encoder->resampleContext, 0, 0, 0,
	                   (uint8_t**) &encoder->audioBuffer, 0, encoder->audioBufferSize / 4);

	if (avresample_available(encoder->resampleContext) < encoder->audioFrame->nb_samples) {
		return;
	}
#if LIBAVCODEC_VERSION_MAJOR >= 55
	av_frame_make_writable(encoder->audioFrame);
#endif
	int samples = avresample_read(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize);
#else
#if LIBAVCODEC_VERSION_MAJOR >= 55
	av_frame_make_writable(encoder->audioFrame);
#endif
	if (swr_get_out_samples(encoder->resampleContext, encoder->audioBufferSize / 4) < encoder->audioFrame->nb_samples) {
		swr_convert(encoder->resampleContext, NULL, 0, (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
		return;
	}
	int samples = swr_convert(encoder->resampleContext, encoder->audioFrame->data, encoder->postaudioBufferSize / channelSize,
	                          (const uint8_t**) &encoder->audioBuffer, encoder->audioBufferSize / 4);
#endif

	encoder->audioFrame->pts = av_rescale_q(encoder->currentAudioFrame, encoder->audio->time_base, encoder->audioStream->time_base);
	encoder->currentAudioFrame += samples;

	AVPacket packet;
	av_init_packet(&packet);
	packet.data = 0;
	packet.size = 0;
	packet.pts = encoder->audioFrame->pts;

	int gotData;
#ifdef FFMPEG_USE_PACKETS
	avcodec_send_frame(encoder->audio, encoder->audioFrame);
	gotData = avcodec_receive_packet(encoder->audio, &packet);
	gotData = (gotData == 0) && packet.size;
#else
	avcodec_encode_audio2(encoder->audio, &packet, encoder->audioFrame, &gotData);
#endif
	if (gotData) {
		if (encoder->absf) {
			AVPacket tempPacket;

#ifdef FFMPEG_USE_NEW_BSF
			int success = av_bsf_send_packet(encoder->absf, &packet);
			if (success >= 0) {
				success = av_bsf_receive_packet(encoder->absf, &tempPacket);
			}
#else
			int success = av_bitstream_filter_filter(encoder->absf, encoder->audio, 0,
			    &tempPacket.data, &tempPacket.size,
			    packet.data, packet.size, 0);
#endif

			if (success >= 0) {
#if LIBAVUTIL_VERSION_MAJOR >= 53
				tempPacket.buf = av_buffer_create(tempPacket.data, tempPacket.size, av_buffer_default_free, 0, 0);
#endif

#ifdef FFMPEG_USE_PACKET_UNREF
				av_packet_move_ref(&packet, &tempPacket);
#else
				av_free_packet(&packet);
				packet = tempPacket;
#endif

				packet.stream_index = encoder->audioStream->index;
				av_interleaved_write_frame(encoder->context, &packet);
			}
		} else {
			packet.stream_index = encoder->audioStream->index;
			av_interleaved_write_frame(encoder->context, &packet);
		}
	}
#ifdef FFMPEG_USE_PACKET_UNREF
	av_packet_unref(&packet);
#else
	av_free_packet(&packet);
#endif
}
Ejemplo n.º 12
0
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
{
    AVFilterContext  *ctx = inlink->dst;
    ASyncContext       *s = ctx->priv;
    AVFilterLink *outlink = ctx->outputs[0];
    int nb_channels = av_get_channel_layout_nb_channels(buf->channel_layout);
    int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts :
                  av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
    int out_size, ret;
    int64_t delta;
    int64_t new_pts;

    /* buffer data until we get the next timestamp */
    if (s->pts == AV_NOPTS_VALUE || pts == AV_NOPTS_VALUE) {
        if (pts != AV_NOPTS_VALUE) {
            s->pts = pts - get_delay(s);
        }
        return write_to_fifo(s, buf);
    }

    if (s->first_pts != AV_NOPTS_VALUE) {
        handle_trimming(ctx);
        if (!avresample_available(s->avr))
            return write_to_fifo(s, buf);
    }

    /* when we have two timestamps, compute how many samples would we have
     * to add/remove to get proper sync between data and timestamps */
    delta    = pts - s->pts - get_delay(s);
    out_size = avresample_available(s->avr);

    if (llabs(delta) > s->min_delta ||
        (s->first_frame && delta && s->first_pts != AV_NOPTS_VALUE)) {
        av_log(ctx, AV_LOG_VERBOSE, "Discontinuity - %"PRId64" samples.\n", delta);
        out_size = av_clipl_int32((int64_t)out_size + delta);
    } else {
        if (s->resample) {
            // adjust the compensation if delta is non-zero
            int delay = get_delay(s);
            int comp = s->comp + av_clip(delta * inlink->sample_rate / delay,
                                         -s->max_comp, s->max_comp);
            if (comp != s->comp) {
                av_log(ctx, AV_LOG_VERBOSE, "Compensating %d samples per second.\n", comp);
                if (avresample_set_compensation(s->avr, comp, inlink->sample_rate) == 0) {
                    s->comp = comp;
                }
            }
        }
        // adjust PTS to avoid monotonicity errors with input PTS jitter
        pts -= delta;
        delta = 0;
    }

    if (out_size > 0) {
        AVFrame *buf_out = ff_get_audio_buffer(outlink, out_size);
        if (!buf_out) {
            ret = AVERROR(ENOMEM);
            goto fail;
        }

        if (s->first_frame && delta > 0) {
            int planar = av_sample_fmt_is_planar(buf_out->format);
            int planes = planar ?  nb_channels : 1;
            int block_size = av_get_bytes_per_sample(buf_out->format) *
                             (planar ? 1 : nb_channels);

            int ch;

            av_samples_set_silence(buf_out->extended_data, 0, delta,
                                   nb_channels, buf->format);

            for (ch = 0; ch < planes; ch++)
                buf_out->extended_data[ch] += delta * block_size;

            avresample_read(s->avr, buf_out->extended_data, out_size);

            for (ch = 0; ch < planes; ch++)
                buf_out->extended_data[ch] -= delta * block_size;
        } else {
            avresample_read(s->avr, buf_out->extended_data, out_size);

            if (delta > 0) {
                av_samples_set_silence(buf_out->extended_data, out_size - delta,
                                       delta, nb_channels, buf->format);
            }
        }
        buf_out->pts = s->pts;
        ret = ff_filter_frame(outlink, buf_out);
        if (ret < 0)
            goto fail;
        s->got_output = 1;
    } else if (avresample_available(s->avr)) {
        av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
               "whole buffer.\n");
    }

    /* drain any remaining buffered data */
    avresample_read(s->avr, NULL, avresample_available(s->avr));

    new_pts = pts - avresample_get_delay(s->avr);
    /* check for s->pts monotonicity */
    if (new_pts > s->pts) {
        s->pts = new_pts;
        ret = avresample_convert(s->avr, NULL, 0, 0, buf->extended_data,
                                 buf->linesize[0], buf->nb_samples);
    } else {
        av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
               "whole buffer.\n");
        ret = 0;
    }

    s->first_frame = 0;
fail:
    av_frame_free(&buf);

    return ret;
}
Ejemplo n.º 13
0
static void *start_encoder( void *ptr )
{
    obe_aud_enc_params_t *enc_params = ptr;
    obe_t *h = enc_params->h;
    obe_encoder_t *encoder = enc_params->encoder;
    obe_output_stream_t *stream = enc_params->stream;
    obe_raw_frame_t *raw_frame;
    obe_coded_frame_t *coded_frame;
    void *audio_buf = NULL;
    int64_t cur_pts = -1, pts_increment;
    int i, frame_size, ret, got_pkt, num_frames = 0, total_size = 0, audio_buf_len;
    AVFifoBuffer *out_fifo = NULL;
    AVAudioResampleContext *avr = NULL;
    AVPacket pkt;
    AVCodecContext *codec = NULL;
    AVFrame *frame = NULL;
    AVDictionary *opts = NULL;
    char is_latm[2];

    avcodec_register_all();

    codec = avcodec_alloc_context3( NULL );
    if( !codec )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    for( i = 0; lavc_encoders[i].obe_name != -1; i++ )
    {
        if( lavc_encoders[i].obe_name == stream->stream_format )
            break;
    }

    if( lavc_encoders[i].obe_name == -1 )
    {
        fprintf( stderr, "[lavc] Could not find encoder1\n" );
        goto finish;
    }

    AVCodec *enc = avcodec_find_encoder( lavc_encoders[i].lavc_name );
    if( !enc )
    {
        fprintf( stderr, "[lavc] Could not find encoder2\n" );
        goto finish;
    }

    if( enc->sample_fmts[0] == -1 )
    {
        fprintf( stderr, "[lavc] No valid sample formats\n" );
        goto finish;
    }

    codec->sample_rate = enc_params->sample_rate;
    codec->bit_rate = stream->bitrate * 1000;
    codec->sample_fmt = enc->sample_fmts[0];
    codec->channels = av_get_channel_layout_nb_channels( stream->channel_layout );
    codec->channel_layout = stream->channel_layout;
    codec->time_base.num = 1;
    codec->time_base.den = OBE_CLOCK;
    codec->profile = stream->aac_opts.aac_profile == AAC_HE_V2 ? FF_PROFILE_AAC_HE_V2 :
                     stream->aac_opts.aac_profile == AAC_HE_V1 ? FF_PROFILE_AAC_HE :
                     FF_PROFILE_AAC_LOW;

    snprintf( is_latm, sizeof(is_latm), "%i", stream->aac_opts.latm_output );
    av_dict_set( &opts, "latm", is_latm, 0 );
    av_dict_set( &opts, "header_period", "2", 0 );

    if( avcodec_open2( codec, enc, &opts ) < 0 )
    {
        fprintf( stderr, "[lavc] Could not open encoder\n" );
        goto finish;
    }

    avr = avresample_alloc_context();
    if( !avr )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    av_opt_set_int( avr, "in_channel_layout",   codec->channel_layout, 0 );
    av_opt_set_int( avr, "in_sample_fmt",       enc_params->input_sample_format, 0 );
    av_opt_set_int( avr, "in_sample_rate",      enc_params->sample_rate, 0 );
    av_opt_set_int( avr, "out_channel_layout",  codec->channel_layout, 0 );
    av_opt_set_int( avr, "out_sample_fmt",      codec->sample_fmt,     0 );
    av_opt_set_int( avr, "dither_method",       AV_RESAMPLE_DITHER_TRIANGULAR_NS, 0 );

    if( avresample_open( avr ) < 0 )
    {
        fprintf( stderr, "Could not open AVResample\n" );
        goto finish;
    }

    /* The number of samples per E-AC3 frame is unknown until the encoder is ready */
    if( stream->stream_format == AUDIO_E_AC_3 || stream->stream_format == AUDIO_AAC )
    {
        pthread_mutex_lock( &encoder->queue.mutex );
        encoder->is_ready = 1;
        encoder->num_samples = codec->frame_size;
        /* Broadcast because input and muxer can be stuck waiting for encoder */
        pthread_cond_broadcast( &encoder->queue.in_cv );
        pthread_mutex_unlock( &encoder->queue.mutex );
    }

    frame_size = (double)codec->frame_size * 125 * stream->bitrate *
                 enc_params->frames_per_pes / enc_params->sample_rate;
    /* NB: libfdk-aac already doubles the frame size appropriately */
    pts_increment = (double)codec->frame_size * OBE_CLOCK * enc_params->frames_per_pes / enc_params->sample_rate;

    out_fifo = av_fifo_alloc( frame_size );
    if( !out_fifo )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    audio_buf_len = codec->frame_size * av_get_bytes_per_sample( codec->sample_fmt ) * codec->channels;
    audio_buf = av_malloc( audio_buf_len );
    if( !audio_buf )
    {
        fprintf( stderr, "Malloc failed\n" );
        goto finish;
    }

    frame = avcodec_alloc_frame();
    if( !frame )
    {
        fprintf( stderr, "Could not allocate frame\n" );
        goto finish;
    }

    while( 1 )
    {
        /* TODO: detect bitrate or channel reconfig */
        pthread_mutex_lock( &encoder->queue.mutex );

        while( !encoder->queue.size && !encoder->cancel_thread )
            pthread_cond_wait( &encoder->queue.in_cv, &encoder->queue.mutex );

        if( encoder->cancel_thread )
        {
            pthread_mutex_unlock( &encoder->queue.mutex );
            goto finish;
        }

        raw_frame = encoder->queue.queue[0];
        pthread_mutex_unlock( &encoder->queue.mutex );

        if( cur_pts == -1 )
            cur_pts = raw_frame->pts;

        if( avresample_convert( avr, NULL, 0, raw_frame->audio_frame.num_samples, raw_frame->audio_frame.audio_data,
                                raw_frame->audio_frame.linesize, raw_frame->audio_frame.num_samples ) < 0 )
        {
            syslog( LOG_ERR, "[lavc] Sample format conversion failed\n" );
            break;
        }

        raw_frame->release_data( raw_frame );
        raw_frame->release_frame( raw_frame );
        remove_from_queue( &encoder->queue );

        while( avresample_available( avr ) >= codec->frame_size )
        {
            got_pkt = 0;
            avcodec_get_frame_defaults( frame );
            frame->nb_samples = codec->frame_size;
            avresample_read( avr, &audio_buf, codec->frame_size );

            if( avcodec_fill_audio_frame( frame, codec->channels, codec->sample_fmt, audio_buf, audio_buf_len, 0 ) < 0 )
            {
                syslog( LOG_ERR, "[lavc] Could not fill audio frame\n" );
                break;
            }

            av_init_packet( &pkt );
            pkt.data = NULL;
            pkt.size = 0;

            ret = avcodec_encode_audio2( codec, &pkt, frame, &got_pkt );
            if( ret < 0 )
            {
                syslog( LOG_ERR, "[lavc] Audio encoding failed\n" );
                goto finish;
            }

            if( !got_pkt )
                continue;

            total_size += pkt.size;
            num_frames++;

            if( av_fifo_realloc2( out_fifo, av_fifo_size( out_fifo ) + pkt.size ) < 0 )
            {
                syslog( LOG_ERR, "Malloc failed\n" );
                break;
            }

            av_fifo_generic_write( out_fifo, pkt.data, pkt.size, NULL );
            obe_free_packet( &pkt );

            if( num_frames == enc_params->frames_per_pes )
            {
                coded_frame = new_coded_frame( encoder->output_stream_id, total_size );
                if( !coded_frame )
                {
                    syslog( LOG_ERR, "Malloc failed\n" );
                    goto finish;
                }

                av_fifo_generic_read( out_fifo, coded_frame->data, total_size, NULL );

                coded_frame->pts = cur_pts;
                coded_frame->random_access = 1; /* Every frame output is a random access point */
                add_to_queue( &h->mux_queue, coded_frame );

                /* We need to generate PTS because frame sizes have changed */
                cur_pts += pts_increment;
                total_size = num_frames = 0;
            }
        }
    }

finish:
    if( frame )
       avcodec_free_frame( &frame );

    if( audio_buf )
        av_free( audio_buf );

    if( out_fifo )
        av_fifo_free( out_fifo );

    if( avr )
        avresample_free( &avr );

    if( codec )
    {
        avcodec_close( codec );
        av_free( codec );
    }

    free( enc_params );

    return NULL;
}
Ejemplo n.º 14
0
static int
pulseaudio_audio_deliver(audio_decoder_t *ad, int samples,
			 int64_t pts, int epoch)
{
  decoder_t *d = (decoder_t *)ad;
  size_t bytes;

  if(ad->ad_spdif_muxer != NULL) {
    bytes = ad->ad_spdif_frame_size;
  } else {
    bytes = samples * d->framesize;
  }

  void *buf;
  assert(d->s != NULL);

  pa_threaded_mainloop_lock(mainloop);

  int writable = pa_stream_writable_size(d->s);
  if(writable == 0) {
    d->blocked = 1;
    pa_threaded_mainloop_unlock(mainloop);
    return 1; 
  }

  pa_stream_begin_write(d->s, &buf, &bytes);
  assert(bytes > 0);

  if(ad->ad_spdif_muxer != NULL) {
    memcpy(buf, ad->ad_spdif_frame, ad->ad_spdif_frame_size);
  } else {
    int rsamples = bytes / d->framesize;
    uint8_t *data[8] = {0};
    data[0] = (uint8_t *)buf;
    assert(rsamples <= samples);
    avresample_read(ad->ad_avr, data, rsamples);
  }

  if(pts != AV_NOPTS_VALUE) {

    media_pipe_t *mp = ad->ad_mp;
    hts_mutex_lock(&mp->mp_clock_mutex);

    const pa_timing_info *ti = pa_stream_get_timing_info(d->s);
    if(ti != NULL) {
      mp->mp_audio_clock_avtime = 
	ti->timestamp.tv_sec * 1000000LL + ti->timestamp.tv_usec;

      int64_t busec = pa_bytes_to_usec(ti->write_index - ti->read_index,
				       &d->ss);

      int64_t delay = ti->sink_usec + busec + ti->transport_usec;
      mp->mp_audio_clock = pts - delay;
      mp->mp_audio_clock_epoch = epoch;
    }
    hts_mutex_unlock(&mp->mp_clock_mutex);
  }

  pa_stream_write(d->s, buf, bytes, NULL, 0LL, PA_SEEK_RELATIVE);
  ad->ad_spdif_frame_size = 0;

  pa_threaded_mainloop_unlock(mainloop);
  return 0;
}
Ejemplo n.º 15
0
/*
 * encode one audio frame and send it to the muxer
 * return 1 when encoding is finished, 0 otherwise
 */
static int process_audio_stream(AVFormatContext *oc, OutputStream *ost)
{
    AVFrame *frame;
    int got_output = 0;
    int ret;

    frame = get_audio_frame(ost);
    got_output |= !!frame;

    /* feed the data to lavr */
    if (frame) {
        ret = avresample_convert(ost->avr, NULL, 0, 0,
                                 frame->extended_data, frame->linesize[0],
                                 frame->nb_samples);
        if (ret < 0) {
            fprintf(stderr, "Error feeding audio data to the resampler\n");
            exit(1);
        }
    }

    while ((frame && avresample_available(ost->avr) >= ost->frame->nb_samples) ||
           (!frame && avresample_get_out_samples(ost->avr, 0))) {
        /* when we pass a frame to the encoder, it may keep a reference to it
         * internally;
         * make sure we do not overwrite it here
         */
        ret = av_frame_make_writable(ost->frame);
        if (ret < 0)
            exit(1);

        /* the difference between the two avresample calls here is that the
         * first one just reads the already converted data that is buffered in
         * the lavr output buffer, while the second one also flushes the
         * resampler */
        if (frame) {
            ret = avresample_read(ost->avr, ost->frame->extended_data,
                                  ost->frame->nb_samples);
        } else {
            ret = avresample_convert(ost->avr, ost->frame->extended_data,
                                     ost->frame->linesize[0], ost->frame->nb_samples,
                                     NULL, 0, 0);
        }

        if (ret < 0) {
            fprintf(stderr, "Error while resampling\n");
            exit(1);
        } else if (frame && ret != ost->frame->nb_samples) {
            fprintf(stderr, "Too few samples returned from lavr\n");
            exit(1);
        }

        ost->frame->nb_samples = ret;

        ost->frame->pts        = ost->next_pts;
        ost->next_pts         += ost->frame->nb_samples;

        got_output |= encode_audio_frame(oc, ost, ret ? ost->frame : NULL);
    }

    return !got_output;
}