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); }
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; }
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; }
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; }
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; }
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; }
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); }
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; }
static void drop_all_output(struct af_resample *s) { while (avresample_read(s->avrctx, NULL, 1000) > 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; }
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 }
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; }
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; }
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; }
/* * 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; }