ffmpeg 解碼音頻(aac、mp3)輸出pcm文件

ffmpeg 解碼音頻(aac、mp3)輸出pcm文件
播放pcm可以參考: ffplay -ar 48000 -ac 2 -f f32le out.pcm

main.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavutil/frame.h>
#include <libavutil/mem.h>
#include <libavcodec/avcodec.h>#define AUDIO_INBUF_SIZE    10240
#define AUDIO_REFILL_THRESH 4096static void decode(AVCodecContext* dec_ctx, AVPacket* pkt, AVFrame* frame, FILE *outfile)
{int i, ch;int ret, sample_size;int send_ret = 1;do{//傳入要解碼的packetret = avcodec_send_packet(dec_ctx, pkt);//AVERROR(EAGAIN) 傳入失敗,表示先要receive frame再重新send packetif(ret == AVERROR(EAGAIN)){send_ret = 0;fprintf(stderr, "avcodec_send_packet = AVERROR(EAGAIN)\n");}else if(ret < 0){char err[128] = {0};av_strerror(ret, err, 128);fprintf(stderr, "avcodec_send_packet = ret < 0 : %s\n", err);return;}while (ret >= 0){//調用avcodec_receive_frame會在內部首先調用av_frame_unref來釋放frame本來的數據//就是這次調用會將上次調用返回的frame數據釋放ret = avcodec_receive_frame(dec_ctx, frame);if(ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)return;else if(ret < 0){fprintf(stderr, "avcodec_receive_frame = ret < 0\n");exit(1);}//獲取采樣點占用的字節sample_size = av_get_bytes_per_sample(dec_ctx->sample_fmt);if(sample_size < 0){fprintf(stderr, "av_get_bytes_per_sample = sample_size < 0\n");exit(1);}//在第一幀的時候輸出一下音頻信息static int print_info = 1;if(print_info){print_info = 0;printf("ar-samplerate: %uHz\n", frame->sample_rate);printf("ac-channel: %u\n", frame->channels);printf("f-format: %u\n", frame->format);}//平面方式://LLLLRRRRLLLLRRRRLLLLRRRR      (LLLLRRRR這樣為一個音頻幀)//交錯方式://LRLRLRLRLRLRLRLRLR           (LR這樣為一個音頻樣本)//按交錯方式寫入(nb_samples這一幀多少樣本)for(i = 0; i < frame->nb_samples; i++){   //dec_ctx->channels 多少個通道的數據for(int channle = 0; channle < dec_ctx->channels; channle++){//frame->data[0] = L 通道//frame->data[1] = R 通道fwrite(frame->data[channle] + sample_size * i, 1, sample_size, outfile);}}}}while(!send_ret);}#define AAC 0
int main()
{const char* outfilename = "out.pcm";#if AACconst char* filename = "test.aac";
#elseconst char* filename = "test.mp3";
#endifconst AVCodec *codec;AVCodecContext *codec_ctx= NULL;AVCodecParserContext *parser = NULL;int len = 0;int ret = 0;FILE *infile = NULL;FILE *outfile = NULL;uint8_t inbuf[AUDIO_INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];uint8_t *data = NULL;size_t   data_size = 0;AVPacket *pkt = NULL;AVFrame *de_frame = NULL;//申請AVPacket本身的內存pkt = av_packet_alloc();//要使用的解碼器IDenum AVCodecID audio_codec_id = AV_CODEC_ID_AAC;if(strstr(filename, "aac") != NULL){audio_codec_id = AV_CODEC_ID_AAC;}else if(strstr(filename, ".mp3") != NULL){audio_codec_id = AV_CODEC_ID_MP3;}else{printf("audio_codec_id = AV_CODEC_ID_NONE\n");return 0;}//查找相應的解碼器codec = avcodec_find_decoder(audio_codec_id);if(!codec){printf("Codec not find!\n");return 0;}//根據解碼器ID獲取裸流的解析器parser = av_parser_init(codec->id);if(!parser){printf("Parser not find!\n");return 0;}//分配codec使用的上下文codec_ctx = avcodec_alloc_context3(codec);if(!codec_ctx){printf("avcodec_alloc_context3 failed!\n");return 0;}//將解碼器和解碼使用的上下文關聯if(avcodec_open2(codec_ctx, codec, NULL) < 0){printf("avcodec_open2 failed!\n");return 0;}//打開輸入文件infile = fopen(filename, "rb");if(!infile){printf("infile fopen failed!\n");return 0;}//輸出文件outfile = fopen(outfilename, "wb");if(!outfile){printf("outfilie fopen failed!\n");return 0;}int file_end = 0;//讀取文件開始解碼data = inbuf;data_size = fread(inbuf, 1, AUDIO_INBUF_SIZE, infile);de_frame = av_frame_alloc();while (data_size > 0){//獲取傳入到avcodec_send_packet一個packet的數據量//(一幀的量可能也會多幀的量,這里測試是一幀的量)ret = av_parser_parse2(parser, codec_ctx, &pkt->data, &pkt->size,data, data_size,AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);if(ret < 0){printf("av_parser_parser2 Error!\n");return 0;}//使用了多少數據做一個偏移data += ret;data_size -= ret;if(pkt->size)decode(codec_ctx, pkt, de_frame, outfile);//如果當前緩沖區中數據少于AUDIO_REFILL_THRESH就再讀//避免多次讀文件if((data_size < AUDIO_REFILL_THRESH) && !file_end ){//剩余數據移動緩沖區前memmove(inbuf, data, data_size);data = inbuf;//跨過已有數據存儲len = fread(data + data_size, 1, AUDIO_INBUF_SIZE - data_size, infile);if(len > 0)data_size += len;else if(len == 0){file_end = 1;printf("file end!\n");}}}//沖刷解碼器pkt->data = NULL;pkt->size = 0;decode(codec_ctx, pkt, de_frame, outfile);fclose(infile);fclose(outfile);avcodec_free_context(&codec_ctx);av_parser_close(parser);av_frame_free(&de_frame);av_packet_free(&pkt);printf("audio decoder end!\n");return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/379116.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/379116.shtml
英文地址,請注明出處:http://en.pswp.cn/news/379116.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Jquery getJSON()

getJSON與aspx 準備工作 Customer類 public class Customer{public int Unid { get; set; }public string CustomerName { get; set; }public string Memo { get; set; }public string Other { get; set; }}&#xff08;一&#xff09;ashx Customer customer new Customer { …

北京中信銀行總行地址_中信銀行拉薩分行舉行“存款保險標識”啟用和存款保險條例宣傳活動...

11月NOV中信銀行拉薩分行舉行“存款保險標識”啟用和《存款保險條例》宣傳活動揭牌啟用儀式111月Jul根據人民銀行和總行關于“存款保險標識”啟用工作相關要求&#xff0c;分行行領導高度重視“存款保險標識”啟用和《存款保險條例》宣傳活動工作&#xff0c;按照統一工作部署、…

Java ClassLoader getPackage()方法與示例

ClassLoader類的getPackage()方法 (ClassLoader Class getPackage() method) getPackage() method is available in java.lang package. getPackage()方法在java.lang包中可用。 getPackage() method is used to return the package that has been defined in ClassLoader or t…

C---編寫程序:求出1~1000之間能被7或12整除,但不能同時被二者整除的所有整數,將結果保存在數組中,要求程序數據的輸入、計算和輸出均使用函數實現。

編寫程序&#xff1a;求出1~1000之間能被7或12整除&#xff0c;但不能同時被二者整除的所有整數&#xff0c;將結果保存在數組中&#xff0c;要求程序數據的輸入、計算和輸出均使用函數實現。 編程思路&#xff1a;分別編寫函數input()、cal()、output()實現數據的輸入、計算和…

報告稱我國成最大移民輸出國 將形成投資產業鏈(關注)

時代特有的現象&#xff0c;我們應該予以關注 “現在國內房價這么高&#xff0c;政策也看不清&#xff0c;還不如逢高賣掉之前買的幾套房子&#xff0c;一兩套房子的錢辦個投資移民&#xff0c;趁還年輕&#xff0c;拿到綠卡后享受一下美國本國待遇的高等教育了。”廣州&#x…

轉整型_156.Ruby烘焙大理石豆沙吐司解鎖大理石花紋整型

好看又好吃的大理石豆沙面包。紅豆餡均勻分布在松軟細膩的面包體里&#xff0c;手撕著吃&#xff0c;一層層的甜美與溫柔&#xff5e;關于吐司面包&#xff0c;我公眾號里寫過白吐司(基礎款牛奶吐司&#xff0c;超綿鮮奶油吐司)和全麥吐司(基礎款50%全麥吐司&#xff0c;經典燕…

ffmpeg 解碼視頻(h264、mpeg2)輸出yuv420p文件

ffmpeg 解碼視頻&#xff08;h264、mpeg2&#xff09;輸出yuv420p文件 播放yuv可以參考&#xff1a;ffplay -pixel_format yuv420p -video_size 768x320 -framerate 25 out.yuv main.c #include <stdio.h> #include <stdlib.h> #include <string.h>#includ…

VS2010 快捷鍵 (空格顯示 綠點, Tab 顯示箭頭)

VS2010 有用的快捷鍵 &#xff1a; Ctrl r, ctrl w, 切換空格示。 轉載于:https://www.cnblogs.com/fengye87626/archive/2012/11/21/2780716.html

C---編寫程序:實現一個隨堂測試,能進行加減乘除運算。要求如下:(1)隨機產生兩個1~10的正整數,在屏幕上輸出題目,如:5+3=?(2)學生輸入答案,程序檢查學生輸入答案是否正確,若正確,

編寫程序&#xff1a;實現一個隨堂測試&#xff0c;能進行加減乘除運算。要求如下&#xff1a; 1&#xff09;隨機產生兩個1~10的正整數&#xff0c;在屏幕上輸出題目&#xff0c;如&#xff1a;53&#xff1f; 2&#xff09;學生輸入答案&#xff0c;程序檢查學生輸入答案是…

分析一下mp4格式的trak -> mdia -> minf -> stbl -> stts、stsc 這兩個box信息

分析一下mp4格式的trak -> mdia -> minf -> stbl -> stts、stsc 這兩個box信息 &#xff08;因為這兩個box在音頻trak和視頻trak 下都有的&#xff0c;而且都有一個數組的值是比較繞的&#xff09; 目錄&#xff1a;stts&#xff1a;記錄時間戳的&#xff0c;每個s…

利用SQL注入2分鐘入侵網站

說起流光、溯雪、亂刀&#xff0c;可以說是大名鼎鼎無人不知無人不曉&#xff0c;這些都是小榕哥的作品。每次一提起小榕哥來&#xff0c;我的崇拜景仰就如滔滔江水&#xff0c;連綿不絕~~~~&#xff08;又來了&#xff01;&#xff09; 讓我們崇拜的小榕哥最新又發布了SQL注入…

pip安裝deb_技術|如何在 Ubuntu 上安裝 pip

pip 是一個命令行工具&#xff0c;允許你安裝 Python 編寫的軟件包。 學習如何在 Ubuntu 上安裝 pip 以及如何使用它來安裝 Python 應用程序。有許多方法可以在 Ubuntu 上安裝軟件。 你可以從軟件中心安裝應用程序&#xff0c;也可以從下載的 DEB 文件、PPA(LCTT 譯注&#xff…

assubclass_Java類class asSubclass()方法及示例

assubclass類類asSubclass()方法 (Class class asSubclass() method) asSubclass() method is available in java.lang package. asSubclass()方法在java.lang包中可用。 asSubclass() method casts this Class object to denote a subclass of the class denoted by the given…

VB6.0 怎樣啟用控件comdlg32.ocx

VB6.0 怎樣啟用控件comdlg32.ocx 怎樣啟用控件comdlg32.ocx 2008-10-08 09:32 提問者&#xff1a; nefu_20061617 |瀏覽次數&#xff1a;1502次vbs文件中有代碼Set ComDlg CreateObject("MSComdlg.CommonDialog")運行時發生錯誤ActiveX 部件不能創建對象: MSComdlg.…

Python---爬蟲案例

例1、爬取公眾號文章中的圖片。 1&#xff0c;首先打開要獲取公眾號文章的地址 2&#xff0c;按下F12&#xff0c;再按Ctrl Shift C&#xff0c;然后鼠標移動到圖片位置&#xff0c;然后觀察控制臺中顯示圖片對應的代碼位置 3&#xff0c;分析該位置的代碼段 代碼段如下&…

WinCE驅動開發問題精華集錦(二)

轉自&#xff1a;http://hgh123.blog.163.com/blog/static/5980422120086183115543/ 感謝 我怎么能在PB左邊的定制平臺加進我的驅動呢&#xff1f; 兩種辦法&#xff1a; 1、在platform.bib或者project.bib的MODULES部分添加一條語句&#xff0c;例如&#xff1a; MyDriver.dll…

報錯Unable to resolve target android-5

報錯信息&#xff1a;Error:Unable to resolve target android-X&#xff08;X是一個數字&#xff09; 錯誤分析&#xff1a;這種錯誤一般大部分是SDK 版本不符所造成的&#xff0c;一般會在Ecplise工作空間導入項目時候出現此錯誤&#xff0c;一般提示&#xff1a;Error:Unabl…

matlab盒子分形維數_分形維數--matlab

一維曲線分形維數的matlab程序function DFractalDim(y,cellmax)%求輸入一維信號的計盒分形維數%y是一維信號%cellmax:方格子的最大邊長,可以取2的偶數次冪次(1,2,4,8...),取大于數據長度的偶數%D是y的計盒維數(一般情況下D>1),Dlim(log(N(e))/log(k/e)),if cellmaxerror(cel…

Java布爾類toString()方法及示例

Syntax: 句法&#xff1a; public String toString();public static String toString(boolean value);布爾類toString()方法 (Boolean class toString() method) toString() method is available in java.lang package. toString()方法在java.lang包中可用。 toString() metho…

pcm數據編碼成為aac格式文件(可以在酷狗播放)

pcm數據編碼成為aac格式文件&#xff08;可以在酷狗播放&#xff09; 關于其中的aac adts格式可以參考&#xff1a;AAC ADTS格式分析 main.c #include <stdio.h> #include <stdlib.h> #include <stdlib.h>#include <libavcodec/avcodec.h> #include …