static int get_out_samples(struct af_resample *s, int in_samples) { #if LIBSWRESAMPLE_VERSION_MAJOR > 1 || LIBSWRESAMPLE_VERSION_MINOR >= 2 return swr_get_out_samples(s->avrctx, in_samples); #else return av_rescale_rnd(in_samples, s->ctx.out_rate, s->ctx.in_rate, AV_ROUND_UP) + swr_get_delay(s->avrctx, s->ctx.out_rate); #endif }
static int get_out_samples(struct af_resample *s, int in_samples) { return swr_get_out_samples(s->avrctx, in_samples); }
int attribute_align_arg swr_convert(struct SwrContext *s, uint8_t *out_arg[SWR_CH_MAX], int out_count, const uint8_t *in_arg [SWR_CH_MAX], int in_count){ AudioData * in= &s->in; AudioData *out= &s->out; int av_unused max_output; if (!swr_is_initialized(s)) { av_log(s, AV_LOG_ERROR, "Context has not been initialized\n"); return AVERROR(EINVAL); } #if defined(ASSERT_LEVEL) && ASSERT_LEVEL >1 max_output = swr_get_out_samples(s, in_count); #endif while(s->drop_output > 0){ int ret; uint8_t *tmp_arg[SWR_CH_MAX]; #define MAX_DROP_STEP 16384 if((ret=swri_realloc_audio(&s->drop_temp, FFMIN(s->drop_output, MAX_DROP_STEP)))<0) return ret; reversefill_audiodata(&s->drop_temp, tmp_arg); s->drop_output *= -1; //FIXME find a less hackish solution ret = swr_convert(s, tmp_arg, FFMIN(-s->drop_output, MAX_DROP_STEP), in_arg, in_count); //FIXME optimize but this is as good as never called so maybe it doesn't matter s->drop_output *= -1; in_count = 0; if(ret>0) { s->drop_output -= ret; if (!s->drop_output && !out_arg) return 0; continue; } av_assert0(s->drop_output); return 0; } if(!in_arg){ if(s->resample){ if (!s->flushed) s->resampler->flush(s); s->resample_in_constraint = 0; s->flushed = 1; }else if(!s->in_buffer_count){ return 0; } }else fill_audiodata(in , (void*)in_arg); fill_audiodata(out, out_arg); if(s->resample){ int ret = swr_convert_internal(s, out, out_count, in, in_count); if(ret>0 && !s->drop_output) s->outpts += ret * (int64_t)s->in_sample_rate; av_assert2(max_output < 0 || ret < 0 || ret <= max_output); return ret; }else{ AudioData tmp= *in; int ret2=0; int ret, size; size = FFMIN(out_count, s->in_buffer_count); if(size){ buf_set(&tmp, &s->in_buffer, s->in_buffer_index); ret= swr_convert_internal(s, out, size, &tmp, size); if(ret<0) return ret; ret2= ret; s->in_buffer_count -= ret; s->in_buffer_index += ret; buf_set(out, out, ret); out_count -= ret; if(!s->in_buffer_count) s->in_buffer_index = 0; } if(in_count){ size= s->in_buffer_index + s->in_buffer_count + in_count - out_count; if(in_count > out_count) { //FIXME move after swr_convert_internal if( size > s->in_buffer.count && s->in_buffer_count + in_count - out_count <= s->in_buffer_index){ buf_set(&tmp, &s->in_buffer, s->in_buffer_index); copy(&s->in_buffer, &tmp, s->in_buffer_count); s->in_buffer_index=0; }else if((ret=swri_realloc_audio(&s->in_buffer, size)) < 0) return ret; } if(out_count){ size = FFMIN(in_count, out_count); ret= swr_convert_internal(s, out, size, in, size); if(ret<0) return ret; buf_set(in, in, ret); in_count -= ret; ret2 += ret; } if(in_count){ buf_set(&tmp, &s->in_buffer, s->in_buffer_index + s->in_buffer_count); copy(&tmp, in, in_count); s->in_buffer_count += in_count; } } if(ret2>0 && !s->drop_output) s->outpts += ret2 * (int64_t)s->in_sample_rate; av_assert2(max_output < 0 || ret2 < 0 || ret2 <= max_output); return ret2; } }
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 }