[FFmpeg-user] convert video 2 mp3

(忍)不轻云 449127727 at qq.com
Wed Dec 11 08:02:37 CET 2013


#include<stdio.h>
#include<stdlib.h>
#include<libavcodec/avcodec.h>
#include<libavformat/avformat.h>
#include<libswscale/swscale.h>
#include<libswresample/swresample.h>
#include<libavutil/avutil.h>
#include<libavutil/opt.h>


/*
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
*/












static int ao_strm_idx( AVFormatContext *fmt_ctx )
{
	int i = 0;
	int audio_stream_idx = -1;
	//流媒体的metadata
	//Read packets of a media file to get stream information.
	if (avformat_find_stream_info(fmt_ctx, NULL) < 0)
	{
		printf("%s\n","can not find stream information!");
		return -1;
	} 




	//这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息
	//查找第一个音频流
	for (i=0; i<fmt_ctx->nb_streams; i++) 
	{		
		if ( fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) 
		{
			audio_stream_idx = i;
			break;
		}
	}


	return audio_stream_idx;
}






static int get_format_from_sample_fmt(const char **fmt,
                                      enum AVSampleFormat sample_fmt)
{
    int i;
    struct sample_fmt_entry {
        enum AVSampleFormat sample_fmt; const char *fmt_be, *fmt_le;
    } sample_fmt_entries[] = {
        { AV_SAMPLE_FMT_U8,  "u8",    "u8"    },
        { AV_SAMPLE_FMT_S16, "s16be", "s16le" },
        { AV_SAMPLE_FMT_S32, "s32be", "s32le" },
        { AV_SAMPLE_FMT_FLT, "f32be", "f32le" },
        { AV_SAMPLE_FMT_DBL, "f64be", "f64le" },
    };
    *fmt = NULL;


    for (i = 0; i < FF_ARRAY_ELEMS(sample_fmt_entries); i++) {
        struct sample_fmt_entry *entry = &sample_fmt_entries[i];
        if (sample_fmt == entry->sample_fmt) {
            *fmt = AV_NE(entry->fmt_be, entry->fmt_le);
            return 0;
        }
    }


    fprintf(stderr,
            "Sample format %s not supported as output format\n",
            av_get_sample_fmt_name(sample_fmt));
    return AVERROR(EINVAL);
}


/**
 * Fill dst buffer with nb_samples, generated starting from t.
 */
void fill_samples(double *dst, int nb_samples, int nb_channels, int sample_rate, double *t)
{
    int i, j;
    double tincr = 1.0 / sample_rate, *dstp = dst;
    const double c = 2 * M_PI * 440.0;


    /* generate sin tone with 440Hz frequency and duplicated channels */
    for (i = 0; i < nb_samples; i++) {
        *dstp = sin(c * *t);
        for (j = 1; j < nb_channels; j++)
            dstp[j] = dstp[0];
        dstp += nb_channels;
        *t += tincr;
    }
}






int main(int argc, const char *argv[])
{




	AVFormatContext *fmt_ctx = NULL;
	AVCodecContext *audio_dec_ctx = NULL;
	AVCodec *codec;
	AVPacket avpkt;
	AVFrame *decoded_frame;
	int ret;
    const char *fmt;














	
	FILE *audio_dst_fd;
	int dst_bufsize;
	int got_frame = 0, audio_stream_idx = -1;
	//int audio_frame_count;
	const char *src_filename = argv[1];
	const char *dst_filename = argv[2];
	
	//注册所有容器
	av_register_all();
	//打开
	if( avformat_open_input( &fmt_ctx, src_filename, NULL, NULL ) < 0 ) 
	{
		printf( "can not open [%s]!\n", src_filename );
		return -1;
	}








	audio_stream_idx = ao_strm_idx( fmt_ctx );
	//查找结果
	if ( audio_stream_idx == -1 )  
	{
		printf( "can not find audio stream in [%s]\n", src_filename );
		return -1; // Didn't find a video stream
	}










	// Find a registered decoder with a matching codec ID.
	audio_dec_ctx = fmt_ctx->streams[audio_stream_idx]->codec; 
	codec = avcodec_find_decoder( audio_dec_ctx->codec_id );
	if ( codec == NULL )
	{
		fprintf(stderr, "Unsupported codec!\n");
		return -1; // Codec not found
	}
	// 使用解码器是否可以打开
	if ( avcodec_open2( audio_dec_ctx, codec, NULL ) < 0 ) 
	{
		printf( "can not opened by decoder!\n" );
		return -1; // Could not open codec
	}












	audio_dst_fd = fopen( dst_filename, "wb" );
	if ( !audio_dst_fd ) 
	{
		av_free( audio_dec_ctx );
		printf( "can not open [%s] errro!\n", dst_filename );
		return -1;
	}










//	int64_t src_ch_layout = AV_CH_LAYOUT_STEREO;
//	int src_rate = 48000;
//	enum AVSampleFormat src_sample_fmt = AV_SAMPLE_FMT_DBL;	///< 采格格式
//	int src_nb_channels = 0;
//	src_nb_channels = av_get_channel_layout_nb_channels( src_ch_layout );
	int64_t src_ch_layout = audio_dec_ctx->channel_layout;
	int src_rate = audio_dec_ctx->sample_rate;
	enum AVSampleFormat src_sample_fmt = audio_dec_ctx->sample_fmt;
	int src_nb_channels = 0;
	src_nb_channels = av_get_channel_layout_nb_channels( src_ch_layout );
	int src_nb_samples = 1024;
	uint8_t **src_data = NULL;
	int src_linesize;
	av_samples_alloc_array_and_samples( &src_data, &src_linesize, src_nb_channels, src_nb_samples, src_sample_fmt, 0 );		///< 审请缓冲区




	int64_t dst_ch_layout = AV_CH_LAYOUT_SURROUND;			///< 声道格式 http://baike.baidu.com/link?url=UKDnMkAW4OEll0uLCfUvKgHRy_9PipzEWr11h078sLkakT7JcwNg3-KHLsoeoGal
	int dst_rate = 44100;									///< 声道采样频率
	enum AVSampleFormat dst_sample_fmt = AV_SAMPLE_FMT_S16;	///< 采格格式
	int dst_nb_channels = 0;
	dst_nb_channels = av_get_channel_layout_nb_channels( dst_ch_layout );
	int dst_nb_samples, max_dst_nb_samples;
	max_dst_nb_samples = dst_nb_samples = av_rescale_rnd( src_nb_samples, dst_rate, src_rate, AV_ROUND_UP );
	uint8_t ** dst_data = NULL;								///< 数据包地址
	int dst_linesize;										///< 数据包大小
	av_samples_alloc_array_and_samples( &dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0 );		///< 审请缓冲区




	struct SwrContext *swr_ctx = 0;
	swr_ctx = swr_alloc();
    if (!swr_ctx) {
        printf( "Could not allocate resampler context\n" );
		return -1;
    }	
	av_opt_set_int( swr_ctx, "in_channel_layout", src_ch_layout, 0 );
	av_opt_set_int( swr_ctx, "in_sample_rate", src_rate, 0 );
	av_opt_set_sample_fmt( swr_ctx, "in_sample_fmt", src_sample_fmt, 0 );
	
	av_opt_set_int( swr_ctx, "out_channel_layout", dst_ch_layout, 0 );
	av_opt_set_int( swr_ctx, "out_sample_rate", dst_rate, 0 );
	av_opt_set_sample_fmt( swr_ctx, "out_sample_fmt", dst_sample_fmt, 0 );






    /* initialize the resampling context */
    if ( (ret = swr_init(swr_ctx)) < 0 ) 
	{
        fprintf(stderr, "Failed to initialize the resampling context\n");
        return -1;
    }








    double t = 0;
    do {
        /* generate synthetic audio */
        fill_samples((double *)src_data[0], src_nb_samples, src_nb_channels, src_rate, &t);


        /* compute destination number of samples */
        dst_nb_samples = av_rescale_rnd(swr_get_delay(swr_ctx, src_rate) +
                                        src_nb_samples, dst_rate, src_rate, AV_ROUND_UP);
        if (dst_nb_samples > max_dst_nb_samples) {
            av_free(dst_data[0]);
            ret = av_samples_alloc(dst_data, &dst_linesize, dst_nb_channels,
                                   dst_nb_samples, dst_sample_fmt, 1);
            if (ret < 0)
                break;
            max_dst_nb_samples = dst_nb_samples;
        }


        /* convert to destination format */
        ret = swr_convert(swr_ctx, dst_data, dst_nb_samples, (const uint8_t **)src_data, src_nb_samples);
        if (ret < 0) {
            fprintf(stderr, "Error while converting\n");
            //goto end;
        }
        dst_bufsize = av_samples_get_buffer_size(&dst_linesize, dst_nb_channels,
                                                 ret, dst_sample_fmt, 1);
        printf("t:%f in:%d out:%d\n", t, src_nb_samples, ret);
        fwrite(dst_data[0], 1, dst_bufsize, audio_dst_fd);
    } while (t < 10);


    if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt)) < 0)
			return -1;
   //     goto end;
    fprintf(stderr, "Resampling succeeded. Play the output file with the command:\n"
            "ffplay -f %s -channel_layout %"PRId64" -channels %d -ar %d %s\n",
            fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename);








    if (audio_dst_fd)
        fclose(audio_dst_fd);
	
   // if (src_data)
   //     av_freep(&src_data[0]);
    av_freep(&src_data);


    if (dst_data)
        av_freep(&dst_data[0]);
    av_freep(&dst_data);


    swr_free(&swr_ctx);
    return ret < 0;
}



l want to resample one audito,like "./ff-02 test.mp3 other_audiofile";
the file cann't be play; what is wrong?


More information about the ffmpeg-user mailing list