首页 > 代码库 > ffmpeg+sdl教程----------编写一个简单的播放器1
ffmpeg+sdl教程----------编写一个简单的播放器1
来源:http://blog.csdn.net/mu399/article/details/5813561
最近在研究ffmpeg,由于详细介绍ffmpeg的文档资料很少,有人就说了学习ffmpeg的最好办法就是看一些可以正常工作的代码,当你看懂 了ffmpeg.c和ffplay.c两个文件就算入门了,但是这两个文件相当恐怖啊,一个4300行,一个3200行,初学者难免看着难免头晕吃力,可 以先从简单的开始,比如output-example.c和api-example.c,然后再去网上找点稍微复杂点的例子来看
我觉得这个(http://dranger.com/ffmpeg/tutorial01.html)教程很好,由浅入深,而最终代码也不过一千行多一点,非常适合像我这样的初学者,决定整理一下这个教程,方便以后查看
首先是编译环境的搭建,先下载两个压缩包FFmpeg-full-SDK-3.2.rar和SDL-devel-1.2.14-VC8.zip,再下载一 个工程压缩包output_example_me(这个压缩包可以通过关键字“ffmpeg output-example”找到)。
第一步,编译output_example_me中的工程
解压output_example_me中的工程,我用的是vc2005编译的这个工程,也可用vc6.0来编译,如果编译成功了,运行程序会生成一个自 定义文件名的视频音频文件,这个文件通过简单的算法生成了规则变换的图像和声音(图像是几个有渐变色的斜放色条像左移动,声音很难听),至此ffmpeg 的环境就算搭建好了,可以成功编译http://dranger.com/ffmpeg/tutorial01.html的第一个例子了,要成功编译后面的例子需要SDL的支持。
第二步,为工程导入SDL库,具体步骤可以通过搜索“vc SDL使用”找到相关教程,如果导入不成功可以为工程添加依赖项:
工程-->选项-->链接器-->输入-->附加依赖项:SDL.lib SDLmain.lib avcodec.lib avdevice.lib avfilter.lib avformat.lib avutil.lib swscale.lib
例1的程序功能是把一个视频文件的前5帧导出为ppm格式的文件,ppm格式的文件可以通过ACDSee等软件打开
下面是例1的完整代码:
- // tutorial01.c
- // Code based on a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de)
- // Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1
- // A small sample program that shows how to use libavformat and libavcodec to
- // read video from a file.
- //
- // Use
- //
- // gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lz
- //
- // to build (assuming libavformat and libavcodec are correctly installed
- // your system).
- //
- // Run using
- //
- // tutorial01 myvideofile.mpg
- //
- // to write the first five frames from "myvideofile.mpg" to disk in PPM
- // format.
- #include "libavformat/avformat.h"
- #include "libswscale/swscale.h"
- #include <stdio.h>
- #include <math.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;
- int i, videoStream;
- AVCodecContext *pCodecCtx;
- AVCodec *pCodec;
- AVFrame *pFrame;
- AVFrame *pFrameRGB;
- AVPacket packet;
- int frameFinished;
- int numBytes;
- uint8_t *buffer;
- if(argc < 2)
- {
- printf("Please provide a movie file/n");
- return -1;
- }
- // Register all formats and codecs
- av_register_all();
- // Open video file
- if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
- return -1; // Couldn‘t open file
- // Retrieve stream information
- if(av_find_stream_info(pFormatCtx)<0)
- return -1; // Couldn‘t find stream information
- // Dump information about file onto standard error
- 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==CODEC_TYPE_VIDEO)
- {
- videoStream=i;
- break;
- }
- if(videoStream==-1)
- return -1; // Didn‘t find a video stream
- // Get a pointer to the codec context for the video stream
- pCodecCtx=pFormatCtx->streams[videoStream]->codec;
- // Find the decoder for the video stream
- pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
- if(pCodec==NULL)
- {
- fprintf(stderr, "Unsupported codec!/n");
- return -1; // Codec not found
- }
- // Open codec
- if(avcodec_open(pCodecCtx, pCodec)<0)
- return -1; // Could not open codec
- // Allocate video frame
- pFrame=avcodec_alloc_frame();
- // Allocate an AVFrame structure
- pFrameRGB=avcodec_alloc_frame();
- if(pFrameRGB==NULL)
- return -1;
- // Determine required buffer size and allocate buffer
- numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
- pCodecCtx->height);
- buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
- // Assign appropriate parts of buffer to image planes in pFrameRGB
- // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
- // of AVPicture
- avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
- pCodecCtx->width, pCodecCtx->height);
- static struct SwsContext *img_convert_ctx;
- if (img_convert_ctx == NULL)
- {
- img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
- pCodecCtx->pix_fmt,
- pCodecCtx->width, pCodecCtx->height,
- PIX_FMT_RGB24,
- SWS_BICUBIC, NULL, NULL, NULL);
- if (img_convert_ctx == NULL)
- {
- fprintf(stderr, "Cannot initialize the conversion context/n");
- return 0;
- }
- }
- // Read frames and save first five frames to disk
- i=0;
- while(av_read_frame(pFormatCtx, &packet)>=0)
- {
- // Is this a packet from the video stream?
- if(packet.stream_index==videoStream)
- {
- // Decode video frame
- avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,
- packet.data, packet.size);
- // Did we get a video frame?
- if(frameFinished)
- {
- // Convert the image from its native format to RGB
- sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,
- 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
- // Save the frame to disk
- if(++i<=5)
- SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height,i);
- }
- }
- // Free the packet that was allocated by av_read_frame
- av_free_packet(&packet);
- }
- // Free the RGB image
- av_free(buffer);
- av_free(pFrameRGB);
- // Free the YUV frame
- av_free(pFrame);
- // Close the codec
- avcodec_close(pCodecCtx);
- // Close the video file
- av_close_input_file(pFormatCtx);
- return 0;
- }
output-example.c在linux下编译的参数为
gcc -g -o exa output-example.c -lavformat -lswscale `sdl-config --cflags --libs`
ffmpeg+sdl教程----------编写一个简单的播放器1