MP3转码PCM

支持aac和mp3转码,主要是dst_nb_sample的计算,aac大致为1024,MP3为1152,

static int dst_nb_samples = 0;
#define SWR
int encoding(const char *in_file, const char *out_file)
{
    //注册所有的工具
    av_register_all();
 
    AVFormatContext *fmt_ctx = NULL;
    AVCodecContext  *cod_ctx = NULL;
    AVCodec         *cod   = NULL;
	int nRet;
 
    //分配一个avformat
    fmt_ctx = avformat_alloc_context();
    if (fmt_ctx == NULL)
        printf("alloc fail");
 
    //打开文件,解封装
    if (avformat_open_input(&fmt_ctx, in_file, NULL, NULL) != 0)
        printf("open fail");
 
    //查找文件的相关流信息
    if (avformat_find_stream_info(fmt_ctx, NULL) < 0)
        printf("find stream fail");
 
    //输出格式信息
    av_dump_format(fmt_ctx, 0, in_file, 0);
 
    //查找解码信息
    int stream_index = -1;
    for (int i = 0; i < fmt_ctx->nb_streams; i++)
        if (fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
            stream_index = i;
            break;
        }
 
    if (stream_index == -1)
        printf("find stream fail");
 
    //保存解码器
    cod_ctx = fmt_ctx->streams[stream_index]->codec;
    cod = avcodec_find_decoder(cod_ctx->codec_id);
 
    if (cod == NULL)
        printf("find codec fail");
 
    if (avcodec_open2(cod_ctx, cod, NULL) < 0)
        printf("can't open codec");
 
    FILE *out_fb = NULL;
    out_fb = fopen(out_file, "wb");
 
    //创建packet,用于存储解码前的数据
    AVPacket *packet = (AVPacket *)malloc(sizeof(AVPacket));
    av_init_packet(packet);
 
    //设置转码后输出相关参数
#ifdef SWR
    //采样的布局方式
    uint64_t out_channel_layout = AV_CH_LAYOUT_MONO;
    //采样个数
    int out_nb_samples = 1024;
    //采样格式
    enum AVSampleFormat  sample_fmt = AV_SAMPLE_FMT_S16;
    //采样率
    int out_sample_rate = 48000;

    //通道数
    int out_channels = av_get_channel_layout_nb_channels(out_channel_layout);
    printf("%d\n",out_channels);
    //创建buffer
    int buffer_size = av_samples_get_buffer_size(NULL, out_channels, out_nb_samples, sample_fmt, 1);
 
 
    //注意要用av_malloc
    uint8_t *buffer = (uint8_t *)av_malloc(MAX_AUDIO_FRAME_SIZE * 2);
 
    int64_t in_channel_layout = av_get_default_channel_layout(cod_ctx->channels);
    //打开转码器
    struct SwrContext *convert_ctx = swr_alloc();
    //设置转码参数
    convert_ctx = swr_alloc_set_opts(convert_ctx, out_channel_layout, sample_fmt, out_sample_rate, \
            in_channel_layout, cod_ctx->sample_fmt, cod_ctx->sample_rate, 0, NULL);
    //初始化转码器
    swr_init(convert_ctx);
#endif

	//创建Frame,用于存储解码后的数据
    AVFrame *frame = av_frame_alloc();
 
    int got_picture;
	
    //while循环,每次读取一帧,并转码 
 
    while (av_read_frame(fmt_ctx, packet) >= 0) {
 
        if (packet->stream_index == stream_index) {

		#if 1
            //解码声音
            if (avcodec_decode_audio4(cod_ctx, frame, &got_picture, packet) < 0) {
                printf("decode error");
                return -1;
            }
 
            if (got_picture > 0) {
#ifdef SWR
				//计算输出sample个数,支持aac和mp3转码
				nRet = av_rescale_rnd(swr_get_delay(convert_ctx, frame->sample_rate) + frame->nb_samples, frame->sample_rate, frame->sample_rate, AVRounding(1));
				if(nRet != dst_nb_samples)
				{
					dst_nb_samples = nRet;
					buffer_size = av_samples_get_buffer_size(NULL, out_channels, dst_nb_samples, sample_fmt, 1);
				}
				
				buffer_size = av_samples_get_buffer_size(NULL, out_channels, dst_nb_samples, sample_fmt, 1);
                //转码
                swr_convert(convert_ctx, &buffer, MAX_AUDIO_FRAME_SIZE, (const uint8_t **)frame->data, frame->nb_samples);
 
                printf("pts:%10lld\t packet size:%d buffer_size %d\n", packet->pts, packet->size, buffer_size);
 
                fwrite(buffer, 1, buffer_size, out_fb);
#else
                short * ptr = (short *)frame->extended_data[0];
				for(int i=0; i< frame->nb_samples; i++)
				{
					fwrite(ptr++, sizeof(short), 1, out_fb);
				}
#endif

            }
            got_picture=0;
			
		#endif
		
        }
 
        av_free_packet(packet);
    }

#ifdef SWR
    swr_free(&convert_ctx);
#endif
 
    fclose(out_fb);
 
    return 0;
}

参考资料:

0,https://www.cnblogs.com/wangguchangqing/p/5851490.html

1,https://blog.csdn.net/u010029439/article/details/84403306

2,http://blog.chinaunix.net/uid-11344913-id-3930864.html

你可能感兴趣的:(C语言)