ffmpeg重采样resample包含AVAudioFifo(三)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhuweigangzwg/article/details/72624857

ffmpeg重采样resample包含AVAudioFifo(三)

本篇文章记录ffmpeg重采样和AVAudioFifo一起用的实现,如果看完整的流程请看这边文章:http://blog.csdn.net/zhuweigangzwg/article/details/72481966,本文只讲重采样和AVAudioFifo的用法,具体看代码注释。

SwrContext * ffmpeg_init_pcm_resample(Out_stream_info * out_stream_info,AVFrame *in_frame, AVFrame *out_frame)
{
	SwrContext * swr_ctx = NULL;  
	swr_ctx = swr_alloc();  
	if (!swr_ctx)  
	{  
		printf("swr_alloc error \n");  
		return NULL;  
	}  
	AVCodecContext * audio_dec_ctx = m_icodec->streams[m_in_audio_stream_idx]->codec;  
	AVSampleFormat sample_fmt;  
	sample_fmt = (AVSampleFormat)out_stream_info->m_dwBitsPerSample; //样本  
	int out_channel_layout = av_get_default_channel_layout(out_stream_info->m_dwChannelCount);
	if (audio_dec_ctx->channel_layout == 0)  
	{  
		audio_dec_ctx->channel_layout = av_get_default_channel_layout(m_icodec->streams[m_in_audio_stream_idx]->codec->channels);  
	}  
	/* set options */  
	av_opt_set_int(swr_ctx, "in_channel_layout",    audio_dec_ctx->channel_layout, 0);  
	av_opt_set_int(swr_ctx, "in_sample_rate",       audio_dec_ctx->sample_rate, 0);  
	av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", audio_dec_ctx->sample_fmt, 0);  
	av_opt_set_int(swr_ctx, "out_channel_layout",   out_channel_layout, 0);   
	av_opt_set_int(swr_ctx, "out_sample_rate",       out_stream_info->m_dwFrequency, 0);  
	av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", sample_fmt, 0);  
	swr_init(swr_ctx);  

	int64_t src_nb_samples = in_frame->nb_samples; 
	//计算输出的samples 和采样率有关 例如:48000转44100,samples则是从1152转为1059,除法
	out_frame->nb_samples = av_rescale_rnd(src_nb_samples, out_stream_info->m_dwFrequency, audio_dec_ctx->sample_rate, AV_ROUND_UP);

	int ret = av_samples_alloc(out_frame->data, &out_frame->linesize[0],   
		out_stream_info->m_dwChannelCount, out_frame->nb_samples,out_stream_info->m_oaudio_st->codec->sample_fmt,1);  
	if (ret < 0)  
	{  
		return NULL;  
	}  

	out_stream_info->m_audiofifo  = av_audio_fifo_alloc(out_stream_info->m_oaudio_st->codec->sample_fmt, out_stream_info->m_oaudio_st->codec->channels,  
		out_frame->nb_samples);   

	return swr_ctx;  
}

int ffmpeg_preform_pcm_resample(Out_stream_info * out_stream_info,SwrContext * pSwrCtx,AVFrame *in_frame, AVFrame *out_frame)
{
	int ret = 0;
	int samples_out_per_size = 0;              //转换之后的samples大小
  
	if (pSwrCtx != NULL)   
	{  
		//这里注意下samples_out_per_size这个值和 out_frame->nb_samples这个值有时候不一样,ffmpeg里面做了策略不是问题。
		samples_out_per_size = swr_convert(pSwrCtx, out_frame->data, out_frame->nb_samples,   
			(const uint8_t**)in_frame->data, in_frame->nb_samples);  
		if (samples_out_per_size < 0)  
		{  
			return -1;  
		}  

		AVCodecContext * audio_dec_ctx = m_icodec->streams[m_in_audio_stream_idx]->codec; 

		int buffersize_in = av_samples_get_buffer_size(&in_frame->linesize[0],audio_dec_ctx->channels,  
			in_frame->nb_samples, audio_dec_ctx->sample_fmt, 1);

		//修改分包内存  
		int buffersize_out = av_samples_get_buffer_size(&out_frame->linesize[0], out_stream_info->m_oaudio_st->codec->channels,  
			samples_out_per_size, out_stream_info->m_oaudio_st->codec->sample_fmt, 1); 

		int fifo_size = av_audio_fifo_size(out_stream_info->m_audiofifo);  
		fifo_size = av_audio_fifo_realloc(out_stream_info->m_audiofifo, av_audio_fifo_size(out_stream_info->m_audiofifo) + out_frame->nb_samples);  
		av_audio_fifo_write(out_stream_info->m_audiofifo,(void **)out_frame->data,samples_out_per_size);  
		fifo_size = av_audio_fifo_size(out_stream_info->m_audiofifo); 

		out_frame->pkt_pts = in_frame->pkt_pts;  
		out_frame->pkt_dts = in_frame->pkt_dts;  
		//有时pkt_pts和pkt_dts不同,并且pkt_pts是编码前的dts,这里要给avframe传入pkt_dts而不能用pkt_pts  
		//out_frame->pts = out_frame->pkt_pts;  
		out_frame->pts = in_frame->pkt_dts;  

		//测试用
		if (out_stream_info->user_stream_id ==11)
		{
			if (pcm_file == NULL)
			{
				pcm_file = fopen("11.pcm","wb");
			}
			int wtiresize = fwrite(out_frame->data[0],buffersize_out,1, pcm_file);
			fflush(pcm_file);
		}
	}  
	ret = 1;
	return ret;
}

void ffmpeg_uinit_pcm_resample(SwrContext * swr_ctx,AVAudioFifo * audiofifo)
{ 
	if (swr_ctx)  
	{  
		swr_free(&swr_ctx);  
		swr_ctx = NULL;  
	}  
	if(audiofifo)  
	{  
		av_audio_fifo_free(audiofifo);  
		audiofifo = NULL;  
	}     
}

存储的声音波形pcm如下:


运行后转码文件如下效果:



 
 

 
 

如有错误请指正:

交流请加QQ群:62054820
QQ:379969650.


猜你喜欢

转载自blog.csdn.net/zhuweigangzwg/article/details/72624857