使用 FFmpeg 开发播放器基础--使用 ffmpeg 解码视频文件
原:http://blog.chinaunix.net/uid-11344913-id-4282729.html使用 ffmpeg 解码多媒体文件之前,首先需要了解一些基本的概念:容器:多媒体文件中包含视频与音频部分,将音频与视频封装在容器内,封装的形式为容器标准中所规定的格式,除了音频编码数据,视频编码数据,文字编码数据以外,还有一些用来格式化这些数据的字段,组成了容器;
原:http://blog.chinaunix.net/uid-11344913-id-4282729.html
使用 ffmpeg 解码多媒体文件之前,首先需要了解一些基本的概念:
容器:多媒体文件中包含视频与音频部分,将音频与视频封装在容器内,封装的形式为容器标准中所规定的格式,除了音频编码数据,视频编码数据,文字编码数据以外,还有一些用来格式化这些数据的字段,组成了容器;
编码器:多媒体文件中包含了视频编码部分与音频编码部分,都为容器所包含;
了解了以上基本概念后,下面看一下解码视频文件的基本步骤:
- 打开视频文件
- 从视频文件中打开视频流
- 从视频流中读取视频信息到视频帧里面
- 如果读取视频真没有完成,就继续从视频流中读取视频信息到视频帧里面
- 对视频帧进行操作,例如解码,绘制到屏幕,保存文件等
- 继续从视频流中读取视频信息到视频帧里面
在执行第2步之前,首先要注意,如果希望使用 ffmpeg 第一步要注册 ffmpeg 的函数,注册完成以后才能够顺利的使用 ffmpeg;
点击(此处)折叠或打开
- av_register_all()
通过这个函数,将ffmpeg中的avformat/avcodec/avfilter等模块全部注册完成了;
接下来就可以打开视频文件;
点击(此处)折叠或打开
-
avformat_open_input()
通过该函数打开视频文件,分析对应的文件的信息,将信息填充进AVFormatContext中,填充完毕以后,可以获得视频流信息;
点击(此处)折叠或打开
- av_find_stream_info()
获得到了视频信息之后,可以知道视频中含多少路视频流,一路视频流用一路视频流的解流方式进行解流,例如音频流,例如视频流,例如字幕流等这里只讲述视频流;当或得到视频流信息后,既可根据对应的视频流的类型进行解码,例如h264,则会根据查找对应的解码器进行获得解码器的信息;
点击(此处)折叠或打开
- avcodec_find_decoder()
或得到解码器信息后,则可以将解码器打开;
点击(此处)折叠或打开
- avcodec_open()
打开解码器以后就可以根据解码信息将对应的frame数据进行读取,本文档来自于http://bbs.chinaffmpeg.com孙悟空读取的时候,每一个frame都需要右地方存储,所以,需要申请frame内存空间;
点击(此处)折叠或打开
- avcodec_alloc_frame()
申请完成之后则开始进行了读取视频frame,然后解frame操作;
点击(此处)折叠或打开
- av_read_frame();
- avcodec_decode_video()
点击(此处)折叠或打开
- av_read_frame();
- avcodec_decode_video()
av_read_frame会将数据从format中读取出来存储入packet中,然后使用avcodec_decode_video来对packet的data进行解码,然后将对应的解码后的数据存入frame中,frame中的数据可以存储入文件中,也可以直接绘制到屏幕上;
将数据存储入文件中的代码实例如下:
点击(此处)折叠或打开
- #include <libavcodec/avcodec.h>
- #include <libavformat/avformat.h>
- #include <libswscale/swscale.h>
-
- #include <stdio.h>
-
- void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
- FILE *pFile;
- char szFilename[32];
- int y;
- // Open file
- sprintf(szFilename, "frame%d.ppm", iFrame);
- pFile = fopen(szFilename, "wb");
- if (pFile == NULL)
- return;
- // Write header
- fprintf(pFile, "P6\n%d %d\n255\n", width, height);
- // Write pixel data
- for (y = 0; y < height; y++)
- fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile);
- // Close file
- fclose(pFile);
- }
-
- int main(int argc, char *argv[])
- {
- AVFormatContext *pFormatCtx = NULL;
- int i = 0;
- int videoStream = 0;
- AVCodecContext *pCodecCtx = NULL;
- AVCodec *pCodec = NULL;
- AVFrame *pFrame = NULL;
- AVFrame *pFrameRGB = NULL;
- AVPacket packet;
- int frameFinished;
- int numBytes;
- uint8_t *buffer = NULL;
-
- AVDictionary *optionsDict = NULL;
- struct SwsContext *sws_ctx = NULL;
- if(argc < 2) {
- printf("Please provide a movie file\n");
- return -1;
- }
- // Register all formats and codecs
- av_register_all();
- // Open video file
- if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)
- return -1; // Couldn't open file
- // Retrieve stream information
- if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
- return -1; // Couldn't find stream information
- // Dump information about file onto standard error
- av_dump_format(pFormatCtx, 0, argv[1], 0);
- // Find the first video stream
- videoStream=-1;
- for(i = 0; i < pFormatCtx->nb_streams; i++)
- if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
- videoStream = i;
- break;
- }
- if(videoStream == -1)
- return -1; // Didn
点击(此处)折叠或打开
- gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.o
- gcc -Wall -ggdb test.o -L/usr/local/lib -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -framework QTKit -framework Foundation -framework QuartzCore -framework CoreVideo -framework Foundation -framework AVFoundation -framework CoreMedia -framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore -liconv -L/usr//lib -lSDLmain -lSDL -Wl,-framework,Cocoa -lm -lbz2 -lz-pthread -o test
Linux下编译方法如下:
点击(此处)折叠或打开
- gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.o
- gcc -Wall -ggdb test.o -o test -L/usr/local/lib -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavuti -lm -lbz2 -lz -pthread
点击(此处)折叠或打开
- gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.o
- gcc -Wall -ggdb test.o -o test -L/usr/local/lib -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavuti -lm -lbz2 -lz -pthread
点击(此处)折叠或打开
- ffmpeg version N-63027-g9e58677 Copyright (c) 2000-2014 the FFmpeg developers
- built on Jun 1 2014 17:05:37 with Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
- configuration: --prefix=/usr/local/
- libavutil 52. 81.100 / 52. 81.100
- libavcodec 55. 60.103 / 55. 60.103
- libavformat 55. 37.102 / 55. 37.102
- libavdevice 55. 13.101 / 55. 13.101
- libavfilter 4. 5.100 / 4. 5.100
- libswscale 2. 6.100 / 2. 6.100
- libswresample 0. 18.100 / 0. 18.100
更多推荐
所有评论(0)