/** * Convert the input audio samples into the output sample format. * The conversion happens on a per-frame basis, the size of which is specified * by frame_size. */ static int convert_samples(uint8_t **input_data, uint8_t **converted_data, const int frame_size, AVAudioResampleContext *resample_context) { int error; /** Convert the samples using the resampler. */ if ((error = avresample_convert(resample_context, converted_data, 0, frame_size, input_data, 0, frame_size)) < 0) { fprintf(stderr, "Could not convert input samples (error '%s')\n", get_error_text(error)); return error; } /** * Perform a sanity check so that the number of converted samples is * not greater than the number of samples to be converted. * If the sample rates differ, this case has to be handled differently */ if (avresample_available(resample_context)) { fprintf(stderr, "Converted samples left over\n"); return AVERROR_EXIT; } return 0; }
int resample_audio( AVAudioResampleContext *avr, audio_samples_t *out, audio_samples_t *in ) { /* Don't call this function over different block aligns. */ uint8_t *out_orig = *out->data; int out_channels = get_channel_layout_nb_channels( out->channel_layout ); int block_align = av_get_bytes_per_sample( out->sample_format ) * out_channels; int request_sample_count = out->sample_count; if( avresample_available( avr ) > 0 ) { int resampled_count = avresample_read( avr, out->data, request_sample_count ); if( resampled_count < 0 ) return 0; request_sample_count -= resampled_count; *out->data += resampled_count * block_align; } uint8_t **in_data = in->sample_count > 0 ? in->data : NULL; int in_channels = get_channel_layout_nb_channels( in->channel_layout ); int in_linesize = get_linesize( in_channels, in->sample_count, in->sample_format ); int out_linesize = get_linesize( out_channels, request_sample_count, out->sample_format ); int resampled_count = avresample_convert( avr, out->data, out_linesize, request_sample_count, in_data, in_linesize, in->sample_count ); if( resampled_count < 0 ) return 0; *out->data += resampled_count * block_align; return *out->data - out_orig; }
static inline void BEL_ST_DoResample(uint32_t *outConsumed, uint32_t *outProduced, BE_ST_SndSample_T *inPtr, BE_ST_SndSample_T *outPtr, uint32_t numOfAvailInputSamples, uint32_t maxSamplesToOutput) { // Just some type differences #ifdef REFKEEN_RESAMPLER_LIBSOXR size_t samples_consumed, samples_produced; #elif (defined REFKEEN_RESAMPLER_NONE) || (defined REFKEEN_RESAMPLER_LIBSPEEXDSP) || (defined REFKEEN_RESAMPLER_LIBSAMPLERATE) uint32_t samples_consumed, samples_produced; #elif (defined REFKEEN_RESAMPLER_LIBSWRESAMPLE) || (defined REFKEEN_RESAMPLER_LIBAVRESAMPLE) || (defined REFKEEN_RESAMPLER_LIBAVCODEC) || (defined REFKEEN_RESAMPLER_LIBRESAMPLE) int samples_consumed, samples_produced; #endif #ifndef REFKEEN_RESAMPLER_NONE if (g_refKeenCfg.useResampler) { #if (defined REFKEEN_RESAMPLER_LIBSWRESAMPLE) samples_consumed = numOfAvailInputSamples; const uint8_t * inPtrs[] = { inPtr, NULL }; uint8_t *outPtrs[] = { outPtr, NULL }; samples_produced = swr_convert(g_sdlSwrContext, outPtrs, maxSamplesToOutput, inPtrs, numOfAvailInputSamples); #elif (defined REFKEEN_RESAMPLER_LIBAVRESAMPLE) samples_consumed = numOfAvailInputSamples; // Previously generated output samples may be queued, and we should read them separately int pending_produced_samples = avresample_available(g_sdlAvAudioResampleContext); if (pending_produced_samples > 0) { samples_produced = BE_Cross_TypedMin(int, maxSamplesToOutput, pending_produced_samples); avresample_read(g_sdlAvAudioResampleContext, &outPtr, samples_produced); outPtr += sizeof(BE_ST_SndSample_T)*samples_produced; }
int64_t swr_get_delay(struct SwrContext *s, int64_t base) { int64_t in_sr, out_sr; av_opt_get_int(s, "in_sample_rate", 0, &in_sr); av_opt_get_int(s, "out_sample_rate", 0, &out_sr); return av_rescale_rnd(avresample_available(s), base, out_sr, AV_ROUND_UP) + av_rescale_rnd(avresample_get_delay(s), base, in_sr, AV_ROUND_UP); }
int CMixer::CalcOutSamples(int in_samples) { if (m_in_samplerate == m_out_samplerate) { return in_samples; } else { return avresample_available(m_pAVRCxt) + (int)((__int64)(avresample_get_delay(m_pAVRCxt) + in_samples) * m_out_samplerate / m_in_samplerate); } }
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 void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf) { AVFilterContext *ctx = inlink->dst; ResampleContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; if (s->avr) { AVFilterBufferRef *buf_out; int delay, nb_samples, ret; /* maximum possible samples lavr can output */ delay = avresample_get_delay(s->avr); nb_samples = av_rescale_rnd(buf->audio->nb_samples + delay, outlink->sample_rate, inlink->sample_rate, AV_ROUND_UP); buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples); ret = avresample_convert(s->avr, (void**)buf_out->extended_data, buf_out->linesize[0], nb_samples, (void**)buf->extended_data, buf->linesize[0], buf->audio->nb_samples); av_assert0(!avresample_available(s->avr)); if (s->next_pts == AV_NOPTS_VALUE) { if (buf->pts == AV_NOPTS_VALUE) { av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, " "assuming 0.\n"); s->next_pts = 0; } else s->next_pts = av_rescale_q(buf->pts, inlink->time_base, outlink->time_base); } if (ret > 0) { buf_out->audio->nb_samples = ret; if (buf->pts != AV_NOPTS_VALUE) { buf_out->pts = av_rescale_q(buf->pts, inlink->time_base, outlink->time_base) - av_rescale(delay, outlink->sample_rate, inlink->sample_rate); } else buf_out->pts = s->next_pts; s->next_pts = buf_out->pts + buf_out->audio->nb_samples; ff_filter_samples(outlink, buf_out); } avfilter_unref_buffer(buf); } else ff_filter_samples(outlink, buf); }
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 struct mp_audio *play(struct af_instance *af, struct mp_audio *data) { struct af_resample *s = af->priv; struct mp_audio *in = data; struct mp_audio *out = af->data; out->samples = avresample_available(s->avrctx) + av_rescale_rnd(get_delay(s) + in->samples, s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP); mp_audio_realloc_min(out, out->samples); af->delay = get_delay(s) / (double)s->ctx.in_rate; #if !USE_SET_CHANNEL_MAPPING do_reorder(in, s->reorder_in); #endif if (out->samples) { out->samples = avresample_convert(s->avrctx, (uint8_t **) out->planes, out->samples * out->sstride, out->samples, (uint8_t **) in->planes, in->samples * in->sstride, in->samples); if (out->samples < 0) return NULL; // error } *data = *out; #if USE_SET_CHANNEL_MAPPING if (needs_reorder(s->reorder_out, out->nch)) { if (af_fmt_is_planar(out->format)) { reorder_planes(data, s->reorder_out); } else { int out_size = out->samples * out->sstride; if (talloc_get_size(s->reorder_buffer) < out_size) s->reorder_buffer = talloc_realloc_size(s, s->reorder_buffer, out_size); data->planes[0] = s->reorder_buffer; int out_samples = avresample_convert(s->avrctx_out, (uint8_t **) data->planes, out_size, out->samples, (uint8_t **) out->planes, out_size, out->samples); assert(out_samples == data->samples); } } #else do_reorder(data, s->reorder_out); #endif return data; }
AudioBufferPtr AudioDecoderThread::resampleAudio(char* pDecodedData, int framesDecoded, int currentSampleFormat) { if (!m_pResampleContext) { #ifdef LIBAVRESAMPLE_VERSION m_pResampleContext = avresample_alloc_context(); av_opt_set_int(m_pResampleContext, "in_channel_layout", av_get_default_channel_layout(m_pStream->codec->channels), 0); av_opt_set_int(m_pResampleContext, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(m_pResampleContext, "in_sample_rate", m_InputSampleRate, 0); av_opt_set_int(m_pResampleContext, "out_sample_rate", m_AP.m_SampleRate, 0); av_opt_set_int(m_pResampleContext, "in_sample_fmt", (AVSampleFormat)currentSampleFormat, 0); av_opt_set_int(m_pResampleContext, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0); int err = avresample_open(m_pResampleContext); AVG_ASSERT(err >= 0); #else m_pResampleContext = av_audio_resample_init(m_AP.m_Channels, m_pStream->codec->channels, m_AP.m_SampleRate, m_InputSampleRate, AV_SAMPLE_FMT_S16, (AVSampleFormat)currentSampleFormat, 16, 10, 0, 0.8); #endif AVG_ASSERT(m_pResampleContext); } #ifdef LIBAVRESAMPLE_VERSION uint8_t *pResampledData; int leftoverSamples = avresample_available(m_pResampleContext); int framesAvailable = leftoverSamples + av_rescale_rnd(avresample_get_delay(m_pResampleContext) + framesDecoded, m_AP.m_SampleRate, m_InputSampleRate, AV_ROUND_UP); av_samples_alloc(&pResampledData, 0, 2, framesAvailable, AV_SAMPLE_FMT_S16, 0); int framesResampled = avresample_convert(m_pResampleContext, &pResampledData, 0, framesAvailable, (uint8_t**)&pDecodedData, 0, framesDecoded); AudioBufferPtr pBuffer(new AudioBuffer(framesResampled, m_AP)); memcpy(pBuffer->getData(), pResampledData, framesResampled*m_AP.m_Channels*sizeof(short)); av_freep(&pResampledData); #else short pResampledData[AVCODEC_MAX_AUDIO_FRAME_SIZE/2]; int framesResampled = audio_resample(m_pResampleContext, pResampledData, (short*)pDecodedData, framesDecoded); AudioBufferPtr pBuffer(new AudioBuffer(framesResampled, m_AP)); memcpy(pBuffer->getData(), pResampledData, framesResampled*m_AP.m_Channels*sizeof(short)); #endif return pBuffer; }
static struct mp_audio *play(struct af_instance *af, struct mp_audio *data) { struct af_resample *s = af->priv; struct mp_audio *in = data; struct mp_audio *out = af->data; int in_size = data->len; int in_samples = in_size / (data->bps * data->nch); int out_samples = avresample_available(s->avrctx) + av_rescale_rnd(get_delay(s) + in_samples, s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP); int out_size = out->bps * out_samples * out->nch; if (talloc_get_size(out->audio) < out_size) out->audio = talloc_realloc_size(out, out->audio, out_size); af->delay = out->bps * av_rescale_rnd(get_delay(s), s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP); #if !USE_SET_CHANNEL_MAPPING reorder_channels(data->audio, s->reorder_in, data->bps, data->nch, in_samples); #endif out_samples = avresample_convert(s->avrctx, (uint8_t **) &out->audio, out_size, out_samples, (uint8_t **) &in->audio, in_size, in_samples); *data = *out; #if USE_SET_CHANNEL_MAPPING if (needs_reorder(s->reorder_out, out->nch)) { if (talloc_get_size(s->reorder_buffer) < out_size) s->reorder_buffer = talloc_realloc_size(s, s->reorder_buffer, out_size); data->audio = s->reorder_buffer; out_samples = avresample_convert(s->avrctx_out, (uint8_t **) &data->audio, out_size, out_samples, (uint8_t **) &out->audio, out_size, out_samples); } #else reorder_channels(data->audio, s->reorder_out, out->bps, out->nch, out_samples); #endif data->len = out->bps * out_samples * out->nch; return data; }
int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples) { int64_t samples = avresample_get_delay(avr) + (int64_t)in_nb_samples; if (avr->resample_needed) { samples = av_rescale_rnd(samples, avr->out_sample_rate, avr->in_sample_rate, AV_ROUND_UP); } samples += avresample_available(avr); if (samples > INT_MAX) return AVERROR(EINVAL); return samples; }
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); }
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; }
static void audio_process_audio(audio_decoder_t *ad, media_buf_t *mb) { const audio_class_t *ac = ad->ad_ac; AVFrame *frame = ad->ad_frame; media_pipe_t *mp = ad->ad_mp; media_queue_t *mq = &mp->mp_audio; int r; int got_frame; if(mb->mb_skip || mb->mb_stream != mq->mq_stream) return; while(mb->mb_size) { if(mb->mb_cw == NULL) { frame->sample_rate = mb->mb_rate; frame->format = AV_SAMPLE_FMT_S16; switch(mb->mb_channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; frame->nb_samples = mb->mb_size / 2; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = mb->mb_size / 4; break; default: abort(); } frame->data[0] = mb->mb_data; frame->linesize[0] = 0; r = mb->mb_size; got_frame = 1; } else { media_codec_t *mc = mb->mb_cw; AVCodecContext *ctx = mc->ctx; if(mc->codec_id != ad->ad_in_codec_id) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); TRACE(TRACE_DEBUG, "audio", "Codec changed to %s (0x%x)", codec ? codec->name : "???", mc->codec_id); ad->ad_in_codec_id = mc->codec_id; ad->ad_in_sample_rate = 0; audio_cleanup_spdif_muxer(ad); ad->ad_mode = ac->ac_get_mode != NULL ? ac->ac_get_mode(ad, mc->codec_id, ctx ? ctx->extradata : NULL, ctx ? ctx->extradata_size : 0) : AUDIO_MODE_PCM; if(ad->ad_mode == AUDIO_MODE_SPDIF) { audio_setup_spdif_muxer(ad, codec, mq); } else if(ad->ad_mode == AUDIO_MODE_CODED) { hts_mutex_lock(&mp->mp_mutex); ac->ac_deliver_coded_locked(ad, mb->mb_data, mb->mb_size, mb->mb_pts, mb->mb_epoch); hts_mutex_unlock(&mp->mp_mutex); return; } } if(ad->ad_spdif_muxer != NULL) { mb->mb_pkt.stream_index = 0; ad->ad_pts = mb->mb_pts; ad->ad_epoch = mb->mb_epoch; mb->mb_pts = AV_NOPTS_VALUE; mb->mb_dts = AV_NOPTS_VALUE; av_write_frame(ad->ad_spdif_muxer, &mb->mb_pkt); avio_flush(ad->ad_spdif_muxer->pb); return; } if(ad->ad_mode == AUDIO_MODE_CODED) { ad->ad_pts = mb->mb_pts; ad->ad_epoch = mb->mb_epoch; } if(ctx == NULL) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); assert(codec != NULL); // Checked in libav.c ctx = mc->ctx = avcodec_alloc_context3(codec); if(ad->ad_stereo_downmix) ctx->request_channel_layout = AV_CH_LAYOUT_STEREO; if(avcodec_open2(mc->ctx, codec, NULL) < 0) { av_freep(&mc->ctx); return; } } r = avcodec_decode_audio4(ctx, frame, &got_frame, &mb->mb_pkt); if(r < 0) return; if(frame->sample_rate == 0) { frame->sample_rate = ctx->sample_rate; if(frame->sample_rate == 0 && mb->mb_cw->fmt_ctx) frame->sample_rate = mb->mb_cw->fmt_ctx->sample_rate; if(frame->sample_rate == 0) { if(!ad->ad_sample_rate_fail) { ad->ad_sample_rate_fail = 1; TRACE(TRACE_ERROR, "Audio", "Unable to determine sample rate"); } return; } } if(frame->channel_layout == 0) { frame->channel_layout = av_get_default_channel_layout(ctx->channels); if(frame->channel_layout == 0) { if(!ad->ad_channel_layout_fail) { ad->ad_channel_layout_fail = 1; TRACE(TRACE_ERROR, "Audio", "Unable to map %d channels to channel layout"); } return; } } if(mp->mp_stats) mp_set_mq_meta(mq, ctx->codec, ctx); } if(mb->mb_pts != PTS_UNSET) { int od = 0, id = 0; if(ad->ad_avr != NULL) { od = avresample_available(ad->ad_avr) * 1000000LL / ad->ad_out_sample_rate; id = avresample_get_delay(ad->ad_avr) * 1000000LL / frame->sample_rate; } ad->ad_pts = mb->mb_pts - od - id; ad->ad_epoch = mb->mb_epoch; if(mb->mb_drive_clock) mp_set_current_time(mp, mb->mb_pts - ad->ad_delay, mb->mb_epoch, mb->mb_delta); mb->mb_pts = PTS_UNSET; // No longer valid } mb->mb_data += r; mb->mb_size -= r; if(got_frame) { if(frame->sample_rate != ad->ad_in_sample_rate || frame->format != ad->ad_in_sample_format || frame->channel_layout != ad->ad_in_channel_layout || ad->ad_want_reconfig) { ad->ad_want_reconfig = 0; ad->ad_in_sample_rate = frame->sample_rate; ad->ad_in_sample_format = frame->format; ad->ad_in_channel_layout = frame->channel_layout; ac->ac_reconfig(ad); if(ad->ad_avr == NULL) ad->ad_avr = avresample_alloc_context(); else avresample_close(ad->ad_avr); av_opt_set_int(ad->ad_avr, "in_sample_fmt", ad->ad_in_sample_format, 0); av_opt_set_int(ad->ad_avr, "in_sample_rate", ad->ad_in_sample_rate, 0); av_opt_set_int(ad->ad_avr, "in_channel_layout", ad->ad_in_channel_layout, 0); av_opt_set_int(ad->ad_avr, "out_sample_fmt", ad->ad_out_sample_format, 0); av_opt_set_int(ad->ad_avr, "out_sample_rate", ad->ad_out_sample_rate, 0); av_opt_set_int(ad->ad_avr, "out_channel_layout", ad->ad_out_channel_layout, 0); char buf1[128]; char buf2[128]; av_get_channel_layout_string(buf1, sizeof(buf1), -1, ad->ad_in_channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, ad->ad_out_channel_layout); TRACE(TRACE_DEBUG, "Audio", "Converting from [%s %dHz %s] to [%s %dHz %s]", buf1, ad->ad_in_sample_rate, av_get_sample_fmt_name(ad->ad_in_sample_format), buf2, ad->ad_out_sample_rate, av_get_sample_fmt_name(ad->ad_out_sample_format)); if(avresample_open(ad->ad_avr)) { TRACE(TRACE_ERROR, "Audio", "Unable to open resampler"); avresample_free(&ad->ad_avr); } prop_set(mp->mp_prop_ctrl, "canAdjustVolume", PROP_SET_INT, 1); if(ac->ac_set_volume != NULL) ac->ac_set_volume(ad, ad->ad_vol_scale); } if(ad->ad_avr != NULL) { avresample_convert(ad->ad_avr, NULL, 0, 0, frame->data, frame->linesize[0], frame->nb_samples); } else { int delay = 1000000LL * frame->nb_samples / frame->sample_rate; usleep(delay); } } } }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; ResampleContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; int ret; if (s->avr) { AVFrame *out; int delay, nb_samples; /* maximum possible samples lavr can output */ delay = avresample_get_delay(s->avr); nb_samples = avresample_get_out_samples(s->avr, in->nb_samples); out = ff_get_audio_buffer(outlink, nb_samples); if (!out) { ret = AVERROR(ENOMEM); goto fail; } ret = avresample_convert(s->avr, out->extended_data, out->linesize[0], nb_samples, in->extended_data, in->linesize[0], in->nb_samples); if (ret <= 0) { av_frame_free(&out); if (ret < 0) goto fail; } av_assert0(!avresample_available(s->avr)); if (s->next_pts == AV_NOPTS_VALUE) { if (in->pts == AV_NOPTS_VALUE) { av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, " "assuming 0.\n"); s->next_pts = 0; } else s->next_pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); } if (ret > 0) { out->nb_samples = ret; ret = av_frame_copy_props(out, in); if (ret < 0) { av_frame_free(&out); goto fail; } out->sample_rate = outlink->sample_rate; /* Only convert in->pts if there is a discontinuous jump. This ensures that out->pts tracks the number of samples actually output by the resampler in the absence of such a jump. Otherwise, the rounding in av_rescale_q() and av_rescale() causes off-by-1 errors. */ if (in->pts != AV_NOPTS_VALUE && in->pts != s->next_in_pts) { out->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base) - av_rescale(delay, outlink->sample_rate, inlink->sample_rate); } else out->pts = s->next_pts; s->next_pts = out->pts + out->nb_samples; s->next_in_pts = in->pts + in->nb_samples; ret = ff_filter_frame(outlink, out); s->got_output = 1; } fail: av_frame_free(&in); } else { in->format = outlink->format; ret = ff_filter_frame(outlink, in); s->got_output = 1; } return ret; }
/* * 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; }
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); hts_mutex_lock(&mp->mp_mutex); while(run) { int 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) { assert(avail != 0); assert(ad->ad_avr != NULL); 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; } ad->ad_pts = AV_NOPTS_VALUE; 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; continue; } 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 < 16384) { 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 { hts_mutex_unlock(&mp->mp_mutex); switch(mb->mb_data_type) { case MB_AUDIO: audio_process_audio(ad, mb); 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: if(ac->ac_flush) ac->ac_flush(ad); ad->ad_pts = AV_NOPTS_VALUE; 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; }
OSStatus AudioConverter::fillComplex(AudioConverterComplexInputDataProc dataProc, void* opaque, UInt32* ioOutputDataPacketSize, AudioBufferList *outOutputData, AudioStreamPacketDescription* outPacketDescription) { AVFrame* srcaudio; srcaudio = av_frame_alloc(); av_frame_unref(srcaudio); try { for (uint32_t i = 0; i < outOutputData->mNumberBuffers; i++) { UInt32 origSize = outOutputData->mBuffers[i].mDataByteSize; UInt32& newSize = outOutputData->mBuffers[i].mDataByteSize; newSize = 0; while (newSize < origSize) { if (m_avpktOutUsed < m_avpktOut.size) { LOG << "case 1 (used " << m_avpktOutUsed << " from " << m_avpktOut.size << ")\n"; // Feed output from previous conversion while (m_avpktOutUsed < m_avpktOut.size && newSize < origSize) { // Output data int tocopy = std::min<int>(m_avpktOut.size - m_avpktOutUsed, origSize - newSize); memcpy(((char*) outOutputData->mBuffers[i].mData) + newSize, m_avpktOut.data + m_avpktOutUsed, tocopy); newSize += tocopy; m_avpktOutUsed += tocopy; } if (m_avpktOutUsed >= m_avpktOut.size) { m_avpktOutUsed = 0; av_free_packet(&m_avpktOut); } } else if (!m_resampler || avresample_available(m_resampler) == 0) { LOG << "case 2\n"; feedDecoder(dataProc, opaque, srcaudio); if (avresample_available(m_resampler) == 0) goto end; } else { LOG << "case 3\n"; feedEncoder(); } } } end: av_frame_free(&srcaudio); } catch (const std::exception& e) { ERROR() << "Exception: " << e.what(); av_frame_free(&srcaudio); } catch (OSStatus err) { ERROR() << "OSStatus error: " << err; av_frame_free(&srcaudio); return err; } return noErr; }
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 void audio_process_audio(audio_decoder_t *ad, media_buf_t *mb) { const audio_class_t *ac = ad->ad_ac; AVFrame *frame = ad->ad_frame; media_pipe_t *mp = ad->ad_mp; media_queue_t *mq = &mp->mp_audio; int r; int got_frame; AVPacket avpkt; int offset = 0; if(mb->mb_skip || mb->mb_stream != mq->mq_stream) return; while(offset < mb->mb_size) { if(mb->mb_cw == NULL) { frame->sample_rate = mb->mb_rate; frame->format = AV_SAMPLE_FMT_S16; switch(mb->mb_channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; frame->nb_samples = mb->mb_size / 2; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = mb->mb_size / 4; break; default: abort(); } frame->data[0] = mb->mb_data; frame->linesize[0] = 0; r = mb->mb_size; got_frame = 1; } else { av_init_packet(&avpkt); avpkt.data = mb->mb_data + offset; avpkt.size = mb->mb_size - offset; r = avcodec_decode_audio4(mb->mb_cw->codec_ctx, frame, &got_frame, &avpkt); if(r < 0) return; if(frame->sample_rate == 0) frame->sample_rate = mb->mb_cw->codec_ctx->sample_rate; if(frame->sample_rate == 0) return; if(mp->mp_stats) mp_set_mq_meta(mq, mb->mb_cw->codec, mb->mb_cw->codec_ctx); } if(offset == 0 && mb->mb_pts != AV_NOPTS_VALUE) { int od = 0, id = 0; if(ad->ad_avr != NULL) { od = avresample_available(ad->ad_avr) * 1000000LL / ad->ad_out_sample_rate; id = avresample_get_delay(ad->ad_avr) * 1000000LL / frame->sample_rate; } ad->ad_pts = mb->mb_pts - od - id; ad->ad_epoch = mb->mb_epoch; // printf("od=%-20d id=%-20d PTS=%-20ld oPTS=%-20ld\n", // od, id, mb->mb_pts, pts); if(mb->mb_drive_clock) mp_set_current_time(mp, mb->mb_pts - ad->ad_delay, mb->mb_epoch, mb->mb_delta); } offset += r; if(got_frame) { if(frame->sample_rate != ad->ad_in_sample_rate || frame->format != ad->ad_in_sample_format || frame->channel_layout != ad->ad_in_channel_layout) { ad->ad_in_sample_rate = frame->sample_rate; ad->ad_in_sample_format = frame->format; ad->ad_in_channel_layout = frame->channel_layout; ac->ac_reconfig(ad); if(ad->ad_avr == NULL) ad->ad_avr = avresample_alloc_context(); else avresample_close(ad->ad_avr); av_opt_set_int(ad->ad_avr, "in_sample_fmt", ad->ad_in_sample_format, 0); av_opt_set_int(ad->ad_avr, "in_sample_rate", ad->ad_in_sample_rate, 0); av_opt_set_int(ad->ad_avr, "in_channel_layout", ad->ad_in_channel_layout, 0); av_opt_set_int(ad->ad_avr, "out_sample_fmt", ad->ad_out_sample_format, 0); av_opt_set_int(ad->ad_avr, "out_sample_rate", ad->ad_out_sample_rate, 0); av_opt_set_int(ad->ad_avr, "out_channel_layout", ad->ad_out_channel_layout, 0); char buf1[128]; char buf2[128]; av_get_channel_layout_string(buf1, sizeof(buf1), -1, ad->ad_in_channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, ad->ad_out_channel_layout); TRACE(TRACE_DEBUG, "Audio", "Converting from [%s %dHz %s] to [%s %dHz %s]", buf1, ad->ad_in_sample_rate, av_get_sample_fmt_name(ad->ad_in_sample_format), buf2, ad->ad_out_sample_rate, av_get_sample_fmt_name(ad->ad_out_sample_format)); if(avresample_open(ad->ad_avr)) { TRACE(TRACE_ERROR, "AudioQueue", "Unable to open resampler"); avresample_free(&ad->ad_avr); } } if(ad->ad_avr != NULL) avresample_convert(ad->ad_avr, NULL, 0, 0, frame->data, frame->linesize[0], frame->nb_samples); } } }
/* get amount of data currently buffered, in samples */ static int64_t get_delay(ASyncContext *s) { return avresample_available(s->avr) + avresample_get_delay(s->avr); }
static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; ResampleContext *s = ctx->priv; AVFilterLink *outlink = ctx->outputs[0]; int ret; if (s->avr) { AVFrame *out; int delay, nb_samples; /* maximum possible samples lavr can output */ delay = avresample_get_delay(s->avr); nb_samples = av_rescale_rnd(in->nb_samples + delay, outlink->sample_rate, inlink->sample_rate, AV_ROUND_UP); out = ff_get_audio_buffer(outlink, nb_samples); if (!out) { ret = AVERROR(ENOMEM); goto fail; } ret = avresample_convert(s->avr, out->extended_data, out->linesize[0], nb_samples, in->extended_data, in->linesize[0], in->nb_samples); if (ret <= 0) { av_frame_free(&out); if (ret < 0) goto fail; } av_assert0(!avresample_available(s->avr)); if (s->next_pts == AV_NOPTS_VALUE) { if (in->pts == AV_NOPTS_VALUE) { av_log(ctx, AV_LOG_WARNING, "First timestamp is missing, " "assuming 0.\n"); s->next_pts = 0; } else s->next_pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base); } if (ret > 0) { out->nb_samples = ret; if (in->pts != AV_NOPTS_VALUE) { out->pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base) - av_rescale(delay, outlink->sample_rate, inlink->sample_rate); } else out->pts = s->next_pts; s->next_pts = out->pts + out->nb_samples; ret = ff_filter_frame(outlink, out); s->got_output = 1; } fail: av_frame_free(&in); } else { in->format = outlink->format; ret = ff_filter_frame(outlink, in); s->got_output = 1; } return ret; }
static double get_delay(struct af_resample *s) { return avresample_get_delay(s->avrctx) / (double)s->in_rate + avresample_available(s->avrctx) / (double)s->out_rate; }
static void audio_process_audio(audio_decoder_t *ad, media_buf_t *mb) { const audio_class_t *ac = ad->ad_ac; AVFrame *frame = ad->ad_frame; media_pipe_t *mp = ad->ad_mp; media_queue_t *mq = &mp->mp_audio; int r; int got_frame; AVPacket avpkt; int offset = 0; if(mb->mb_skip || mb->mb_stream != mq->mq_stream) return; while(offset < mb->mb_size) { if(mb->mb_cw == NULL) { frame->sample_rate = mb->mb_rate; frame->format = AV_SAMPLE_FMT_S16; switch(mb->mb_channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; frame->nb_samples = mb->mb_size / 2; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; frame->nb_samples = mb->mb_size / 4; break; default: abort(); } frame->data[0] = mb->mb_data; frame->linesize[0] = 0; r = mb->mb_size; got_frame = 1; } else { media_codec_t *mc = mb->mb_cw; AVCodecContext *ctx = mc->ctx; if(mc->codec_id != ad->ad_in_codec_id) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); TRACE(TRACE_DEBUG, "audio", "Codec changed to %s", codec ? codec->name : "???"); ad->ad_in_codec_id = mc->codec_id; audio_cleanup_spdif_muxer(ad); if(ac->ac_check_passthru != NULL && codec != NULL && ac->ac_check_passthru(ad, mc->codec_id)) { audio_setup_spdif_muxer(ad, codec, mq); } } av_init_packet(&avpkt); avpkt.data = mb->mb_data + offset; avpkt.size = mb->mb_size - offset; if(ad->ad_spdif_muxer != NULL) { av_write_frame(ad->ad_spdif_muxer, &avpkt); avio_flush(ad->ad_spdif_muxer->pb); ad->ad_pts = mb->mb_pts; ad->ad_epoch = mb->mb_epoch; return; } if(ctx == NULL) { AVCodec *codec = avcodec_find_decoder(mc->codec_id); assert(codec != NULL); // Checked in libav.c ctx = mc->ctx = avcodec_alloc_context3(codec); if(ad->ad_stereo_downmix) ctx->request_channels = 2; if(avcodec_open2(mc->ctx, codec, NULL) < 0) { av_freep(&mc->ctx); return; } } r = avcodec_decode_audio4(ctx, frame, &got_frame, &avpkt); if(r < 0) return; if(frame->sample_rate == 0) { frame->sample_rate = ctx->sample_rate; if(frame->sample_rate == 0 && mb->mb_cw->fmt_ctx) frame->sample_rate = mb->mb_cw->fmt_ctx->sample_rate; if(frame->sample_rate == 0) return; } if(frame->channel_layout == 0) { switch(ctx->channels) { case 1: frame->channel_layout = AV_CH_LAYOUT_MONO; break; case 2: frame->channel_layout = AV_CH_LAYOUT_STEREO; break; default: return; } } if(mp->mp_stats) mp_set_mq_meta(mq, ctx->codec, ctx); } if(offset == 0 && mb->mb_pts != AV_NOPTS_VALUE) { int od = 0, id = 0; if(ad->ad_avr != NULL) { od = avresample_available(ad->ad_avr) * 1000000LL / ad->ad_out_sample_rate; id = avresample_get_delay(ad->ad_avr) * 1000000LL / frame->sample_rate; } ad->ad_pts = mb->mb_pts - od - id; ad->ad_epoch = mb->mb_epoch; // printf("od=%-20d id=%-20d PTS=%-20ld oPTS=%-20ld\n", // od, id, mb->mb_pts, pts); if(mb->mb_drive_clock) mp_set_current_time(mp, mb->mb_pts - ad->ad_delay, mb->mb_epoch, mb->mb_delta); } offset += r; if(got_frame) { if(frame->sample_rate != ad->ad_in_sample_rate || frame->format != ad->ad_in_sample_format || frame->channel_layout != ad->ad_in_channel_layout) { ad->ad_in_sample_rate = frame->sample_rate; ad->ad_in_sample_format = frame->format; ad->ad_in_channel_layout = frame->channel_layout; ac->ac_reconfig(ad); if(ad->ad_avr == NULL) ad->ad_avr = avresample_alloc_context(); else avresample_close(ad->ad_avr); av_opt_set_int(ad->ad_avr, "in_sample_fmt", ad->ad_in_sample_format, 0); av_opt_set_int(ad->ad_avr, "in_sample_rate", ad->ad_in_sample_rate, 0); av_opt_set_int(ad->ad_avr, "in_channel_layout", ad->ad_in_channel_layout, 0); av_opt_set_int(ad->ad_avr, "out_sample_fmt", ad->ad_out_sample_format, 0); av_opt_set_int(ad->ad_avr, "out_sample_rate", ad->ad_out_sample_rate, 0); av_opt_set_int(ad->ad_avr, "out_channel_layout", ad->ad_out_channel_layout, 0); char buf1[128]; char buf2[128]; av_get_channel_layout_string(buf1, sizeof(buf1), -1, ad->ad_in_channel_layout); av_get_channel_layout_string(buf2, sizeof(buf2), -1, ad->ad_out_channel_layout); TRACE(TRACE_DEBUG, "Audio", "Converting from [%s %dHz %s] to [%s %dHz %s]", buf1, ad->ad_in_sample_rate, av_get_sample_fmt_name(ad->ad_in_sample_format), buf2, ad->ad_out_sample_rate, av_get_sample_fmt_name(ad->ad_out_sample_format)); if(avresample_open(ad->ad_avr)) { TRACE(TRACE_ERROR, "AudioQueue", "Unable to open resampler"); avresample_free(&ad->ad_avr); } if(ac->ac_set_volume != NULL) { prop_set(mp->mp_prop_ctrl, "canAdjustVolume", PROP_SET_INT, 1); ac->ac_set_volume(ad, ad->ad_vol_scale); } } if(ad->ad_avr != NULL) avresample_convert(ad->ad_avr, NULL, 0, 0, frame->data, frame->linesize[0], frame->nb_samples); } } }