使用 FFmpeg 开发播放器基础第一节 使用 ffmpeg 解码视频文件作者:ChinaFFmpeg 孙悟空使用 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)    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; // DidnOSX下编译方法如下:点击(此处)折叠或打开gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.ogcc -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 testLinux下编译方法如下:点击(此处)折叠或打开gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.ogcc -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.ogcc -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
09-30 21:51
查看更多