织梦CMS - 轻松建站从此开始!

罗索

ffmpeg学习---1Making Screencaps

落鹤生 发布于 2013-04-22 21:19 点击:次 
想根据教程An ffmpeg and SDL Tutorial http://dranger.com/ffmpeg/tutorial01.html 学 习音视频解码,这个作为入门教程实在是太爽了,唯一有点不好的是,这个教程太老了使用现在的ffmpeg1.0的库是编译不过的(不过SDL变化比较 小)。所以修改代码使之符合现有的库,这
TAG:

想根据教程An ffmpeg and SDL Tutorial http://dranger.com/ffmpeg/tutorial01.html 学 习音视频解码,这个作为入门教程实在是太爽了,唯一有点不好的是,这个教程太老了使用现在的ffmpeg1.0的库是编译不过的(不过SDL变化比较 小)。所以修改代码使之符合现有的库,这样印象比较深刻。目前可以下到的ffmpeg的最新版本是ffmpeg-1.0,SDL的最新版本是SDL- 1.2.15.tar.gz,在ubuntu 12.04上进行开发。

一、环境搭建
    下载ffmpeg-1.0.tar.bz2与SDL-1.2.15.tar.gz,并分别解压到/home/sun/code/目录下
     ffmpeg       --> 源码: /home/sun/code/ffmpeg-1.0   --> 安装: /home/sun/code/ffmpeg-1.0/install
     SDL-1.2.15 -->源码: /home/sun/code/SDL-1.2.15  --> 安装: /home/sun/code/SDL-1.2.15/install 
1.1 编译
SDL编译:
  1. sun@ubuntu:~/code/SDL-1.2.15$ ./configure --prefix=/home/sun/code/SDL-1.2.15/install  
  2. sun@ubuntu:~/code/SDL-1.2.15$ make && make install

ffmpeg编译:

  1. sun@ubuntu:~/code/ffmpeg-1.0$ ./configure --prefix=/home/sun/code/ffmpeg-1.0/install --enable-memalign-hack --enable-shared --disable-yasm ;
  2. sun@ubuntu:~/code/ffmpeg-1.0$ make && make install
  3. 如果想在ffmpeg编译的同时也编译出ffplay,需要先安装SDL库


注意:av_read_frame读出的完整的帧,不是包,在函数内部已经保证了帧的完整性。对于视频,av_read_frame读出的就是完整的一帧视频,不会是半帧或多帧;对于音频,av_read_frame读出的可能是多帧,但也是完整的,不存在半帧的情况。
[参考]http://www.chinavideo.org/viewthread.php?tid=11104

二、Tutorial 01: Making Screencaps
1. 1screencaps.c
  1. // tutorial01.c
  2. // Code based on a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de)
  3. // Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1
  4.  
  5. // A small sample program that shows how to use libavformat and libavcodec to
  6. // read video from a file.
  7. //
  8. // Use
  9. //
  10. // gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lz
  11. //
  12. // to build (assuming libavformat and libavcodec are correctly installed
  13. // your system).
  14. //
  15. // Run using
  16. //
  17. // tutorial01 myvideofile.mpg
  18. //
  19. // to write the first five frames from "myvideofile.mpg" to disk in PPM
  20. // format.
  21. #include <stdio.h>
  22. #include <libavformat/avformat.h>
  23. #include <libswscale/swscale.h>
  24.  
  25. void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
  26.     FILE *pFile;
  27.     char szFilename[32];
  28.     int y;
  29.  
  30.     // Open file
  31.     sprintf(szFilename, "frame%d.ppm", iFrame);
  32.     pFile=fopen(szFilename, "wb");
  33.     if(pFile==NULL)
  34.         return;
  35.  
  36.     // Write header
  37.     fprintf(pFile, "P6\n%d %d\n255\n", width, height);
  38.  
  39.     // Write pixel data
  40.     for(y=0; y<height; y++)
  41.         fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
  42.  
  43.     // Close file
  44.     fclose(pFile);
  45. }
  46.  
  47. int main(int argc, char *argv[]) {
  48.     AVFormatContext *pFormatCtx;
  49.     int i, videoStream;
  50.     AVCodecContext *pCodecCtx;
  51.     AVCodec *pCodec;
  52.     AVFrame *pFrame;
  53.     AVFrame *pFrameRGB;
  54.     AVPacket packet;
  55.     int frameFinished;
  56.     int numBytes;
  57.     uint8_t *buffer;
  58.  
  59.     if(argc < 2) {
  60.         printf("Please provide a movie file\n");
  61.         return -1;
  62.     }
  63.     // Register all formats and codecs
  64.     av_register_all();
  65.  
  66.     pFormatCtx = avformat_alloc_context();
  67.     // Open video file
  68.     //if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
  69.     if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)
  70.         return -1; // Couldn't open file
  71.  
  72.     // Retrieve stream information
  73.     if(avformat_find_stream_info(pFormatCtx,NULL)<0)
  74.         return -1; // Couldn't find stream information
  75.  
  76.     // Dump information about file onto standard error
  77.     av_dump_format(pFormatCtx, 0, argv[1], 0);
  78.  
  79.     // Find the first video stream
  80.     videoStream=-1;
  81.     for(i=0; i<pFormatCtx->nb_streams; i++)
  82.         if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
  83.             videoStream=i;
  84.             break;
  85.         }
  86.     if(videoStream==-1)
  87.         return -1; // Didn't find a video stream
  88.  
  89.     // Get a pointer to the codec context for the video stream
  90.     pCodecCtx=pFormatCtx->streams[videoStream]->codec;
  91.  
  92.     // Find the decoder for the video stream
  93.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  94.     if(pCodec==NULL) {
  95.         fprintf(stderr, "Unsupported codec!\n");
  96.         return -1; // Codec not found
  97.     }
  98.     // Open codec
  99.     if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
  100.         return -1; // Could not open codec
  101.  
  102.     // Allocate video frame
  103.     pFrame=avcodec_alloc_frame();
  104.  
  105.     // Allocate an AVFrame structure
  106.     pFrameRGB=avcodec_alloc_frame();
  107.     if(pFrameRGB==NULL)
  108.         return -1;
  109.  
  110.     // Determine required buffer size and allocate buffer
  111.     numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
  112.             pCodecCtx->height);
  113.     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
  114.  
  115.     // Assign appropriate parts of buffer to image planes in pFrameRGB
  116.     // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
  117.     // of AVPicture
  118.     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
  119.             pCodecCtx->width, pCodecCtx->height);
  120.  
  121.     // Read frames and save first five frames to disk
  122.     i=0;
  123.     while(av_read_frame(pFormatCtx, &packet)>=0) {
  124.         // Is this a packet from the video stream?
  125.         if(packet.stream_index==videoStream) {
  126.             // Decode video frame
  127.             avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
  128.  
  129.             // Did we get a video frame?
  130.             if(frameFinished) {
  131.                 // Convert the image from its native format to RGB
  132.                 //img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
  133.                 static struct SwsContext * img_convert_ctx;
  134.                 //img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 聽PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
  135.                 //sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 聽0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
  136.  
  137.                 img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
  138.                 sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
  139.                 // Save the frame to disk
  140.                 if(++i<=5)
  141.                     SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height,
  142.                             i);
  143.             }
  144.         }
  145.  
  146.         // Free the packet that was allocated by av_read_frame
  147.         av_free_packet(&packet);
  148.     }
  149.  
  150.     // Free the RGB image
  151.     av_free(buffer);
  152.     av_free(pFrameRGB);
  153.  
  154.     // Free the YUV frame
  155.     av_free(pFrame);
  156.  
  157.     // Close the codec
  158.     avcodec_close(pCodecCtx);
  159.  
  160.     // Close the video file
  161.     avformat_close_input(&pFormatCtx);
  162.  
  163.     return 0;
  164. }
2. Makefile
  1. CC=gcc
  2. CFLAGS=-g -I/home/sun/code/ffmpeg-1.0/install/include
  3. LDFLAGS = -L/home/sun/code/ffmpeg-1.0/install/lib/ -lavutil -lavformat -lavcodec -lavutil -lm -lswscale
  4. TARGETS=1screencaps
  5. all: $(TARGETS)
  6. 1screencaps:1screencaps.c
  7.     $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
  8.  
  9. clean:
  10.     rm -rf $(TARGETS)

3. 要想运行还需要把运行时库的搜索路径加上去

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/sun/code/ffmpeg-1.0/install/lib/:/home/sun/code/SDL-1.2.15/install/lib
(wangcong02345)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201304/16603.html]
本文出处:chinaunix 作者:wangcong02345 原文
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
相关文章
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容