windows下使用FFmpeg進行音頻轉換程式

來源:互聯網
上載者:User

開發環境: windows 7

FFmpeg版本: 0.8 

FFmpeg windows下的動態連結程式庫:

http://url.cn/IJJwo3

對於FFmpeg的版本,需要注意的是,舊的版本很多介面在新的版本中已經廢棄,我的程式是在僅僅是針對FFmpeg-0.8版本。

支援的音頻格式:
目前測試程式支援amr, wav(CodecID: GSM_MS), wav(PCM), 3gp, 3gpp, aac, mp3格式間的相互轉換。

以前有寫過一個aac轉wav的程式,工程檔案可以直接下載的,初次在windows下使用FFmpeg的童鞋,就參考這篇文章提供的VS2008工程檔案,進行配置FFmpeg庫檔案和標頭檔的配置,在這裡我就不上傳VS2008工程,直接附cpp。

通過ffmpeg將aac格式轉換成wav格式

音頻測試檔案:
http://url.cn/GXOAx5

extern "C"{#include "libavformat/avformat.h"#include "libavcodec/avcodec.h"#include "libavutil/fifo.h"};#include <stdio.h>/* 單通道下,每個sample所佔的位元組數AV_SAMPLE_FMT_FLT = 4bytesAV_SAMPLE_FMT_S16 = 2bytes*/static int g_in_bytes = 2;static int g_out_bytes = 2;AVCodecContext* output_decode_init(AVCodecContext* in_cctx, AVFormatContext* out_fctx, int codec_id);int output_decode_open(AVCodecContext* cc);int main(){AVFormatContext* in_fctx;AVCodecContext* in_cctx;AVCodec* in_codec;const char* in_filename;const char* out_filename;char* decoded_buf;char* output_buf;char* resample_buf;char* before_encoding_buf;int ret = 0;in_filename = "H:\\FileSample\\input\\input.aac";out_filename = "output/aac2mp3.mp3";decoded_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);output_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE);resample_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); before_encoding_buf = (char*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); avcodec_register_all();av_register_all();in_fctx = avformat_alloc_context();ret = av_open_input_file(&in_fctx, in_filename, NULL, 0, NULL);if ( ret != 0 ){printf("open input audio file[%s] fail\n", in_filename);return -1;}ret = av_find_stream_info(in_fctx);if ( ret < 0 ){printf("find stream in audio file[%s] fail\n", in_filename);return -1;}dump_format(in_fctx, 0, in_filename, 0);//這裡我們假設,如果一個檔案包含多個音頻流,//只對第一個音頻流做轉碼,而對於視頻流則忽略int i;int ast_index = -1;for (i = 0; i<(int)in_fctx->nb_streams; ++i){if (in_fctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO){ast_index = i;break;}}if (ast_index == -1){printf("there is not any audio stream in file[%s]\n", in_filename);return 0;}else{printf("find audio stream in file[%s]\n", in_filename);}in_cctx = in_fctx->streams[ast_index]->codec;//in_cctx->codec_id = CODEC_ID_GSM;in_codec = avcodec_find_decoder(in_cctx->codec_id);if (!in_codec){printf("find decoder for codec_id[%d] fail, file[%s]\n", in_cctx->codec_id, in_filename);return -1;}ret = avcodec_open(in_cctx, in_codec);if (ret >= 0){printf("open codec[name:%s] for stream[idx:%d] of file[%s]\n", in_codec->name, ast_index, in_filename);}// 輸出部分初始化AVOutputFormat* out_fmt;AVFormatContext* out_fctx;AVCodecContext* out_cctx = NULL;out_fmt = av_guess_format(NULL, out_filename, NULL);if (!out_fmt){printf("Could not deduce output format from file extension: using MPEG-3.\n");out_fmt = av_guess_format("mp3", NULL, NULL);}if (!out_fmt){fprintf(stderr, "Could not find suitable output format\n");exit(1);}out_fctx = avformat_alloc_context();if (!out_fctx){fprintf(stderr, "avformat_alloc_context fail\n");exit(1);}out_fctx->oformat = out_fmt;out_cctx = output_decode_init(in_cctx, out_fctx, out_fmt->audio_codec);if (!out_cctx){fprintf(stderr, "output_codec_init fail\n");exit(1);}/* set the output parameters (must be done even if no parameters). */if (av_set_parameters(out_fctx, NULL) < 0) {fprintf(stderr, "Invalid output format parameters\n");exit(1);}dump_format(out_fctx, 0, out_filename, 1);output_decode_open(out_cctx);/* open the output file */if (!(out_fmt->flags & AVFMT_NOFILE)) {if (url_fopen(&out_fctx->pb, out_filename, URL_WRONLY) < 0){fprintf(stderr, "Could not open '%s'\n", out_filename);exit(1);}}/* write the stream header, if any */if(av_write_header(out_fctx) < 0){fprintf(stderr, "Could not write header for output file\n");return -1;}int decoded_size;AVPacket in_packet;AVPacket out_packet;ReSampleContext *rs_ctx = NULL;/*參考連結:http://hi.baidu.com/wg_wang/item/34396781d20b4b1ec316270b兩點需要注意:(1) 從輸入檔案中按幀讀取資料,解碼,按照輸出檔案的要求,編碼,並按幀寫入到輸出檔案中。在這裡,由於sample_rate和channels可能不同,需要對音頻資料進行重採樣。(2) 由於不同編碼類別型對一幀音訊資料要求不同,可能需要將輸入資料儲存起來,直到夠輸出的編碼使用,或者,一幀的輸入資料可能需要被多次輸出。這樣,要求初始化重採樣以及libavutil提供的fifo(libavutils/fifo.h聲明)以臨時儲存資料。舉個例子:aac的frame_size=1024,mp3的frame_size=1152。若不用這個fifo,則產生的mp3檔案是有問題的*/// 設定從採樣rs_ctx = av_audio_resample_init(out_cctx->channels, in_cctx->channels,out_cctx->sample_rate, in_cctx->sample_rate,out_cctx->sample_fmt, in_cctx->sample_fmt,16, 10, 0, 0.8);AVFifoBuffer *iofifo;iofifo = av_fifo_alloc(AVCODEC_MAX_AUDIO_FRAME_SIZE*2);av_init_packet(&in_packet);av_init_packet(&out_packet);while (av_read_frame(in_fctx, &in_packet) >= 0){while (in_packet.size > 0){int used_size;decoded_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;used_size = avcodec_decode_audio3(in_cctx, (int16_t *)decoded_buf, &decoded_size, &in_packet);if (used_size < 0){printf("avcodec_decode_audio3 fail\n");exit(1);}int bs, frame_bytes;bs = audio_resample(rs_ctx, (short *)resample_buf, (short *)decoded_buf, decoded_size/(in_cctx->channels*g_in_bytes));ret = av_fifo_generic_write(iofifo, (uint8_t *)resample_buf, bs*out_cctx->channels*g_out_bytes, NULL);//ret = av_fifo_generic_write(iofifo, (uint8_t *)decoded_buf, in_cctx->frame_size*in_cctx->channels*g_out_bytes, NULL);frame_bytes = out_cctx->frame_size * g_out_bytes * out_cctx->channels;while(av_fifo_size(iofifo) >= frame_bytes){ret = av_fifo_generic_read(iofifo, before_encoding_buf, frame_bytes, NULL);out_packet.size = avcodec_encode_audio(out_cctx, (uint8_t*)output_buf, frame_bytes, (short *)before_encoding_buf);out_packet.data = (uint8_t *)output_buf;av_write_frame(out_fctx, &out_packet);}in_packet.size -= used_size;in_packet.data += used_size;}}/* write the trailer, if any */av_write_trailer(out_fctx);if (!(out_fmt->flags & AVFMT_NOFILE)) {/* close the output file */url_fclose(out_fctx->pb);}}int output_decode_open(AVCodecContext* cc){AVCodec *codec;/* find the audio encoder */codec = avcodec_find_encoder(cc->codec_id);if (!codec) {fprintf(stderr, "codec not found\n");exit(1);}/* open it */if (avcodec_open(cc, codec) < 0) {fprintf(stderr, "could not open audio codec\n");exit(1);}return 0;}AVCodecContext* output_decode_init(AVCodecContext* in_cctx, AVFormatContext* out_fctx, int codec_id){AVCodecContext *cc;AVStream *st;st = av_new_stream(out_fctx, 0);if (!st) {fprintf(stderr, "Could not alloc stream\n");exit(1);}cc = st->codec;cc->codec_id = (CodecID)codec_id;cc->codec_type = AVMEDIA_TYPE_AUDIO;/*    google keep的錄音筆記的sample_fmt的格式為AV_SAMPLE_FMT_FLT*/cc->sample_fmt = AV_SAMPLE_FMT_S16;  // 預設採用AV_SAMPLE_FMT_S16//cc->sample_fmt = in_cctx->sample_fmt;if (in_cctx->sample_fmt == AV_SAMPLE_FMT_FLT){g_in_bytes = 4;}if (cc->sample_fmt == AV_SAMPLE_FMT_S16){g_out_bytes = 2;}if (codec_id == CODEC_ID_AMR_NB){cc->channels = 1;cc->bit_rate = 12200;}else{cc->channels = in_cctx->channels;cc->bit_rate = in_cctx->bit_rate;}//cc->sample_rate = in_cctx->sample_rate;//cc->sample_rate = 44100;cc->sample_rate = 8000;return cc;}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.