首先第一件事情就是開一個視頻文件並從中獲得流。咱們要作的第一件事情就是使用av_register_all();來初始化libavformat/libavcodec: 這一步註冊庫中含有的全部可用的文件格式和編碼器,這樣當打開一個文件時,它們纔可以自動選擇相應的文件格式和編碼器。av_register_all()只需調用一次,因此,要放在初始化代碼中。也能夠僅僅註冊我的的文件格式和編碼。html
下一步,打開文件:ide
AVFormatContext *pFormatCtx;
const char *filename="myvideo.mpg";
av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL); // 打開視頻文件
最後三個參數描述了文件格式,緩衝區大小(size)和格式參數;咱們經過簡單地指明NULL或0告訴 libavformat 去自動探測文件格式而且使用默認的緩衝區大小。這裏的格式參數指的是視頻輸出參數,好比寬高的座標。函數
下一步,咱們須要取出包含在文件中的流信息:
編碼
- av_find_stream_info(pFormatCtx); // 取出流信息
-
- AVFormatContext 結構體
-
- dump_format(pFormatCtx, 0, filename, false);//咱們能夠使用這個函數把獲取到得參數所有輸出。
-
- for(i=0; i<pFormatCtx->nb_streams; i++) //區分視頻流和音頻流
- if(pFormatCtx->streams->codec.codec_type==CODEC_TYPE_VIDEO) //找到視頻流,這裏也能夠換成音頻
- {
- videoStream=i;
- break;
- }
接下來就須要尋找解碼器spa
- AVCodec *pCodec;
- pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
-
- avcodec_open(pCodecCtx, pCodec); // 打開解碼器
給視頻幀分配空間以便存儲解碼後的圖片:.net
- AVFrame *pFrame;
- pFrame=avcodec_alloc_frame();
/////////////////////////////////////////開始解碼///////////////////////////////////////////指針
第一步固然是讀數據:code
咱們將要作的是經過讀取包來讀取整個視頻流,而後把它解碼成幀,最後轉換格式而且保存。orm
- while(av_read_frame(pFormatCtx, &packet)>=0) { //讀數據
-
- if(packet.stream_index==videoStream){ //判斷是否視頻流
-
- avcodec_decode_video(pCodecCtx,pFrame, &frameFinished,
-
- packet.data, packet.size); //解碼
-
- if(frameFinished) {
-
- img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24,(AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width,pCodecCtx->height);//轉換 }
-
- SaveFrame(pFrameRGB, pCodecCtx->width,pCodecCtx->height, i); //保存數據
-
- av_free_packet(&packet); //釋放
av_read_frame()讀取一個包而且把它保存到AVPacket結構體中。這些數據能夠在後面經過av_free_packet()來釋 放。函數avcodec_decode_video()把包轉換爲幀。然而當解碼一個包的時候,咱們可能沒有獲得咱們須要的關於幀的信息。所以,當咱們獲得下一幀的時候,avcodec_decode_video()爲咱們設置了幀結束標誌frameFinished。最後,咱們使用 img_convert()函數來把幀從原始格式(pCodecCtx->pix_fmt)轉換成爲RGB格式。要記住,你能夠把一個 AVFrame結構體的指針轉換爲AVPicture結構體的指針。最後,咱們把幀和高度寬度信息傳遞給咱們的SaveFrame函數。視頻
原文地址