Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2159726
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2012-10-25 09:29:33

     想根据教程An ffmpeg and SDL Tutorial  学习音视频解码,这个作为入门教程实在是太爽了,唯一有点不好的是,这个教程太老了使用现在的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读出的可能是多帧,但也是完整的,不存在半帧的情况。
[参考]

二、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. // A small sample program that shows how to use libavformat and libavcodec to
  5. // read video from a file.
  6. //
  7. // Use
  8. //
  9. // gcc -o tutorial01 tutorial01.c -lavformat -lavcodec -lz
  10. //
  11. // to build (assuming libavformat and libavcodec are correctly installed
  12. // your system).
  13. //
  14. // Run using
  15. //
  16. // tutorial01 myvideofile.mpg
  17. //
  18. // to write the first five frames from "myvideofile.mpg" to disk in PPM
  19. // format.
  20. #include <stdio.h>
  21. #include <libavformat/avformat.h>
  22. #include <libswscale/swscale.h>

  23. void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
  24.     FILE *pFile;
  25.     char szFilename[32];
  26.     int y;

  27.     // Open file
  28.     sprintf(szFilename, "frame%d.ppm", iFrame);
  29.     pFile=fopen(szFilename, "wb");
  30.     if(pFile==NULL)
  31.         return;

  32.     // Write header
  33.     fprintf(pFile, "P6\n%d %d\n255\n", width, height);

  34.     // Write pixel data
  35.     for(y=0; y<height; y++)
  36.         fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);

  37.     // Close file
  38.     fclose(pFile);
  39. }

  40. int main(int argc, char *argv[]) {
  41.     AVFormatContext *pFormatCtx;
  42.     int i, videoStream;
  43.     AVCodecContext *pCodecCtx;
  44.     AVCodec *pCodec;
  45.     AVFrame *pFrame;
  46.     AVFrame *pFrameRGB;
  47.     AVPacket packet;
  48.     int frameFinished;
  49.     int numBytes;
  50.     uint8_t *buffer;

  51.     if(argc < 2) {
  52.         printf("Please provide a movie file\n");
  53.         return -1;
  54.     }
  55.     // Register all formats and codecs
  56.     av_register_all();

  57.     pFormatCtx = avformat_alloc_context();
  58.     // Open video file
  59.     //if(av_open_input_file(&pFormatCtx, argv[1], NULL, 0, NULL)!=0)
  60.     if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0)
  61.         return -1; // Couldn't open file

  62.     // Retrieve stream information
  63.     if(avformat_find_stream_info(pFormatCtx,NULL)<0)
  64.         return -1; // Couldn't find stream information

  65.     // Dump information about file onto standard error
  66.     av_dump_format(pFormatCtx, 0, argv[1], 0);

  67.     // Find the first video stream
  68.     videoStream=-1;
  69.     for(i=0; i<pFormatCtx->nb_streams; i++)
  70.         if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO) {
  71.             videoStream=i;
  72.             break;
  73.         }
  74.     if(videoStream==-1)
  75.         return -1; // Didn't find a video stream

  76.     // Get a pointer to the codec context for the video stream
  77.     pCodecCtx=pFormatCtx->streams[videoStream]->codec;

  78.     // Find the decoder for the video stream
  79.     pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
  80.     if(pCodec==NULL) {
  81.         fprintf(stderr, "Unsupported codec!\n");
  82.         return -1; // Codec not found
  83.     }
  84.     // Open codec
  85.     if(avcodec_open2(pCodecCtx, pCodec, NULL)<0)
  86.         return -1; // Could not open codec

  87.     // Allocate video frame
  88.     pFrame=avcodec_alloc_frame();

  89.     // Allocate an AVFrame structure
  90.     pFrameRGB=avcodec_alloc_frame();
  91.     if(pFrameRGB==NULL)
  92.         return -1;

  93.     // Determine required buffer size and allocate buffer
  94.     numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,
  95.             pCodecCtx->height);
  96.     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

  97.     // Assign appropriate parts of buffer to image planes in pFrameRGB
  98.     // Note that pFrameRGB is an AVFrame, but AVFrame is a superset
  99.     // of AVPicture
  100.     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
  101.             pCodecCtx->width, pCodecCtx->height);

  102.     // Read frames and save first five frames to disk
  103.     i=0;
  104.     while(av_read_frame(pFormatCtx, &packet)>=0) {
  105.         // Is this a packet from the video stream?
  106.         if(packet.stream_index==videoStream) {
  107.             // Decode video frame
  108.             avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);

  109.             // Did we get a video frame?
  110.             if(frameFinished) {
  111.                 // Convert the image from its native format to RGB
  112.                 //img_convert((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
  113.                 static struct SwsContext * img_convert_ctx;
  114.                 //img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 聽PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
  115.                 //sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 聽0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);

  116.                 img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
  117.                 sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
  118.                 // Save the frame to disk
  119.                 if(++i<=5)
  120.                     SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height,
  121.                             i);
  122.             }
  123.         }

  124.         // Free the packet that was allocated by av_read_frame
  125.         av_free_packet(&packet);
  126.     }

  127.     // Free the RGB image
  128.     av_free(buffer);
  129.     av_free(pFrameRGB);

  130.     // Free the YUV frame
  131.     av_free(pFrame);

  132.     // Close the codec
  133.     avcodec_close(pCodecCtx);

  134.     // Close the video file
  135.     avformat_close_input(&pFormatCtx);

  136.     return 0;
  137. }
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. clean:
  9.     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


阅读(2853) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~