专栏首页悟空被FFmpeg玩使用 FFmpeg 开发播放器基础 (一)

使用 FFmpeg 开发播放器基础 (一)

使用 FFmpeg 开发播放器基础

第一节 使用 ffmpeg 解码视频文件 作者:ChinaFFmpeg 孙悟空

使用 ffmpeg 解码多媒体文件之前,首先需要了解一些基本的概念:

容器:多媒体文件中包含视频与音频部分,将音频与视频封装在容器内,封装的形式为容器标准中所规定的格式,除了音频编码数据,视频编码数据,文字编码数据以外,还有一些用来格式化这些数据的字段,组成了容器;

编码器:多媒体文件中包含了视频编码部分与音频编码部分,都为容器所包含;

了解了以上基本概念后,下面看一下解码视频文件的基本步骤:

  1. 打开视频文件
  2. 从视频文件中打开视频流
  3. 从视频流中读取视频信息到视频帧里面
  4. 如果读取视频真没有完成,就继续从视频流中读取视频信息到视频帧里面
  5. 对视频帧进行操作,例如解码,绘制到屏幕,保存文件等
  6. 继续从视频流中读取视频信息到视频帧里面

在执行第2步之前,首先要注意,如果希望使用 ffmpeg 第一步要注册 ffmpeg 的函数,注册完成以后才能够顺利的使用 ffmpeg;

点击(此处)折叠或打开

  1. av_register_all()

通过这个函数,将ffmpeg中的avformat/avcodec/avfilter等模块全部注册完成了;

接下来就可以打开视频文件;

点击(此处)折叠或打开

  1. avformat_open_input()

通过该函数打开视频文件,分析对应的文件的信息,将信息填充进AVFormatContext中,填充完毕以后,可以获得视频流信息;

点击(此处)折叠或打开

  1. av_find_stream_info()

获得到了视频信息之后,可以知道视频中含多少路视频流,一路视频流用一路视频流的解流方式进行解流,例如音频流,例如视频流,例如字幕流等这里只讲述视频流;当或得到视频流信息后,既可根据对应的视频流的类型进行解码,例如h264,则会根据查找对应的解码器进行获得解码器的信息;

点击(此处)折叠或打开

  1. avcodec_find_decoder()

或得到解码器信息后,则可以将解码器打开;

点击(此处)折叠或打开

  1. avcodec_open()

打开解码器以后就可以根据解码信息将对应的frame数据进行读取,本文档来自于http://bbs.chinaffmpeg.com孙悟空读取的时候,每一个frame都需要右地方存储,所以,需要申请frame内存空间;

点击(此处)折叠或打开

  1. avcodec_alloc_frame()

申请完成之后则开始进行了读取视频frame,然后解frame操作;

点击(此处)折叠或打开

  1. av_read_frame();
  2. avcodec_decode_video()

点击(此处)折叠或打开

  1. av_read_frame();
  2. avcodec_decode_video()

av_read_frame会将数据从format中读取出来存储入packet中,然后使用avcodec_decode_video来对packet的data进行解码,然后将对应的解码后的数据存入frame中,frame中的数据可以存储入文件中,也可以直接绘制到屏幕上;

将数据存储入文件中的代码实例如下:

点击(此处)折叠或打开

  1. #include <libavcodec/avcodec.h>
  2. #include <libavformat/avformat.h>
  3. #include <libswscale/swscale.h>
  4. #include <stdio.h>
  5. void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) {
  6.   FILE *pFile;
  7.   char szFilename[32];
  8. int y;
  9.   // Open file
  10.   sprintf(szFilename, "frame%d.ppm", iFrame);
  11.   pFile = fopen(szFilename, "wb");
  12. if (pFile == NULL)
  13.     return;
  14.   // Write header
  15.   fprintf(pFile, "P6\n%d %d\n255\n", width, height);
  16.   // Write pixel data
  17. for (y = 0; y < height; y++)
  18.     fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile);
  19.   // Close file
  20.   fclose(pFile);
  21. }
  22. int main(int argc, char *argv[])
  23. {
  24.   AVFormatContext *pFormatCtx = NULL;
  25. int i = 0;
  26. int videoStream = 0;
  27.   AVCodecContext *pCodecCtx = NULL;
  28.   AVCodec *pCodec = NULL;
  29.   AVFrame *pFrame = NULL;
  30.   AVFrame *pFrameRGB = NULL;
  31.   AVPacket packet;
  32. int frameFinished;
  33. int numBytes;
  34.   uint8_t *buffer = NULL;
  35.   AVDictionary *optionsDict = NULL;
  36. struct SwsContext *sws_ctx = NULL;
  37. if(argc < 2) {
  38.     printf("Please provide a movie file\n");
  39.     return -1;
  40.   }
  41.   // Register all formats and codecs
  42.   av_register_all();
  43.   // Open video file
  44. if(avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) != 0)
  45.     return -1; // Couldn't open file
  46.   // Retrieve stream information
  47.   if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
  48.     return -1; // Couldn't find stream information
  49.   // Dump information about file onto standard error
  50.   av_dump_format(pFormatCtx, 0, argv[1], 0);
  51.   // Find the first video stream
  52.   videoStream=-1;
  53. for(i = 0; i < pFormatCtx->nb_streams; i++)
  54. if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  55.       videoStream = i;
  56.       break;
  57.     }
  58. if(videoStream == -1)
  59.     return -1; // Didn

OSX下编译方法如下:

点击(此处)折叠或打开

  1. gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.o
  2. 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下编译方法如下:

点击(此处)折叠或打开

  1. gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.o
  2. gcc -Wall -ggdb test.o -o test -L/usr/local/lib -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavuti -lm -lbz2 -lz -pthread

点击(此处)折叠或打开

  1. gcc -Wall -ggdb test.c -I/usr/include/SDL/ -c -o test.o
  2. gcc -Wall -ggdb test.o -o test -L/usr/local/lib -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavuti -lm -lbz2 -lz -pthread

点击(此处)折叠或打开

  1. ffmpeg version N-63027-g9e58677 Copyright (c) 2000-2014 the FFmpeg developers
  2.   built on Jun 1 2014 17:05:37 with Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
  3.   configuration: --prefix=/usr/local/
  4.   libavutil 52. 81.100 / 52. 81.100
  5.   libavcodec 55. 60.103 / 55. 60.103
  6.   libavformat 55. 37.102 / 55. 37.102
  7.   libavdevice 55. 13.101 / 55. 13.101
  8.   libavfilter 4. 5.100 / 4. 5.100
  9.   libswscale 2. 6.100 / 2. 6.100
  10.   libswresample 0. 18.100 / 0. 18.100

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 统计某文件中某关键词出现个数

    用户3765803
  • 在64位机上编译,运行一个多线程程序出现的libgcc_s.so.1的问题的解决

    起初编译的时候是这样的 gcc test.c -o test -lpthread 然后运行test的时候提示如下错误 libgcc_s.so.1 ...

    用户3765803
  • gluster增加xlator操作(一)

    前面已经介绍过,glusterfs中主线为xlator,几乎每一个大的功能点,或者性能,都可以以xlator形式参与进glusterfs中,那么xlator...

    用户3765803
  • 使用多种工具组合进行分布式超参数优化

    在这篇文章中,我介绍如何使用工具组合来加速超参数优化任务。这里提供了Ubuntu的说明,但可以合理地应用于任何*nix系统。

    AiTechYun
  • 美媒:这个领域中国认真起来,美国估计会输,中国拥有倾覆性优势

    12月6日,全球最大投资风险咨询公司Eurasia Group发表了有关中国人工智能领域的白皮书,指出如果2017年中国AI产业只是预热和炒作,那2018年中国...

    企鹅号小编
  • 当 Vue 处理数组与处理纯对象的方式一样

    当给数组设置 length 时,如果大于数组本身长度,新元素则会以 empty 填充,如下所示:

    三毛
  • MSDN 杂志 Windows 8 特刊

    Windows 运行时: 使用 Windows 运行时改变应用程序开发的面貌 Windows 运行时是创建 Windows 应用商店应用程序的核心。 了解它如何...

    张善友
  • 真格基金顾旻曼:数据是下一代的石油,AI是下一代的电

    在前不久达观数据主办的“2018长三角人工智能应用创新张江峰会”上,真格基金董事总经理顾旻曼现场分享了《AI创业投资观察》的主题演讲。

    达观数据
  • 漆远:小数据学习和模型压缩存挑战,场景成为 AI 技术发展关键

    【新智元导读】蚂蚁金服副总裁、首席科学家漆远博士在新智元2017开源·生态AI技术峰会上阐释了 AI 技术在金融场景中的应用和巨大价值。漆远特别强调了场景化对于...

    新智元
  • java项目 远程debug

    AVA项目无法像PHP那样可以随时修改文件内容进行调试,调试可以借助eclipse,本地代码的话很容易在本地debug,但如果代码已经打包部署在linux上呢?...

    千往

扫码关注云+社区

领取腾讯云代金券