ffmpeg 学习: 004-参考文档进行的开发
背景
在学习ffmpeg时,由于文档老旧以及ffmpeg新旧版本对于一些api的改动,导致学习受阻。
本来可以直接下载老的库,使用老的源码进行学习,但本人觉得,一味地守旧并不是一种好的方法。
ffmpeg 文档:
思路
由于对于FFmpeg的了解还比较皮毛,所以我们使用一些旧的例程,将提示过时的方法改为新的方法。
首先,我们查看一份过时的例程
下面的代码基于 ffmpeg v4.0 编译,为了保证编译通过,已经事先做了小部分的更改。
// ffmpeg v4.0
#include <stdio.h>
#define __STDC_CONSTANT_MACROS
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libswscale/swscale.h>
//#include <libavutil/imgutils.h>
#ifdef __cplusplus
};
#endif
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;
    fprintf(pFile, "p6 \n %d %d\n", width, height);
    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;
    }
    av_register_all();
    avformat_network_init();
    pFormatCtx = avformat_alloc_context();
    // Open the media file and read the header
    if (avformat_open_input(&pFormatCtx, argv[1], NULL,NULL)!=0)
    {
        printf("Couldn't open file\n");
        return -1;
    }
    // retrieve stream information
    if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
        return -1;
    // dump information about file into stand error
    av_dump_format(pFormatCtx, -1, argv[1], 0);
    // Find the first video stream
    videoStream = -1;
    for(i =0; i< pFormatCtx->nb_streams; i++)
    {
        if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            videoStream = i;
            printf("First stream is [%d]\n", videoStream);
            break;
        }
    }
    if (videoStream == -1)
        return -1;
    // Get a pointer to the codec context for the video stream
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
    if(pCodec == NULL)
    {
        fprintf(stderr, "unsupported codec\n");
        return -1;
    }
    // Open codec
    if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
        return -1;
    // allocate video frame
    pFrame = av_frame_alloc();
    if (NULL == pFrame) return -1;
    // allocate an avframe structure
    pFrameRGB = av_frame_alloc();
    if(pFrameRGB == NULL) return -1;
    // Determine required buffer size and allocate buffer
    numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
    printf("avpicture isze is %d\n", numBytes);
    buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
    avpicture_fill((AVPicture *)pFrameRGB, buffer, AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
    i = 0;
    while(av_read_frame(pFormatCtx, &packet) >= 0)
    {
        if(packet.stream_index ==videoStream)
        {
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
            if(frameFinished)
            {
                struct SwsContext * img_convert_ctx = NULL;
                img_convert_ctx = sws_getCachedContext(img_convert_ctx, pCodecCtx->width, pCodecCtx->height,
                    pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB24, SWS_BICUBIC,
                    NULL, NULL, NULL);
                if (!img_convert_ctx)
                {
                    fprintf(stderr, "Cannot initalize sws conversion context\n");
                    exit (-1);
                }
                sws_scale(img_convert_ctx, pFrame->data,
                          pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
                if(i ++ < 50)
                    SaveFrame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
            }
        }
        av_packet_unref(&packet);
    }
    // Free the RGB image
    av_free(buffer);
    av_free(pFrameRGB);
    av_free(pFrame);
    avcodec_close(pCodecCtx);
    //av_close_input_file(pFormatCtx);
    avformat_close_input(&pFormatCtx);
    return 0;
}
编译,除了一堆警告以外,没有什么错误。
开始修改
先将每一个警告消除。
变量类型的不匹配
for(i =0; i< pFormatCtx->nb_streams; i++)出现问题
查阅有关的数据结构发现,是变量类型不匹配,将i改成 uint。成员改名
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)提示codec过气
同样,查阅以后,将codec修改为codecpar处理方式不同
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
之前的版本
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
之后的版本
    pCodecCtx = avcodec_alloc_context3(NULL);
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;
    if (pCodecCtx == NULL)
    {
        // printf("Could not allocate AVCodecContext\n");
        return -1;
    }  
     if (pFormatCtx->streams[i]/*视音频流*/->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        // 处理音频
    }
    avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar);
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;
- 过气函数 
avpicture_get_size
官方文档已经在 libavcodec/avcodec.h 说明: 
/**
 * @deprecated use av_image_get_buffer_size() instead.
 */
attribute_deprecated int avpicture_get_size(enum AVPixelFormat pix_fmt, int width, int height);
由于没有在文档中很快找到 av_image_get_buffer_size,于是我在 头文件目录下搜索grep -nR av_image_get_buffer_size,找到是 libavutil这里的函数
libavcodec/avcodec.h:5650: * @deprecated use av_image_get_buffer_size() instead.
libavutil/imgutils.h:181:int av_image_get_buffer_size(enum AVPixelFormat pix_fmt, int width, int height, int align);
libavutil/imgutils.h:186: * av_image_get_buffer_size() can be used to compute the required size
												
											ffmpeg 学习: 004-参考文档进行的开发的更多相关文章
- Mongoose学习参考文档——基础篇
		
Mongoose学习参考文档 前言:本学习参考文档仅供参考,如有问题,师请雅正 一.快速通道 1.1 名词解释 Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力 Model ...
 - [转载]正则表达式参考文档 - Regular Expression Syntax Reference.
		
正则表达式参考文档 - Regular Expression Syntax Reference. [原创文章,转载请保留或注明出处:http://www.regexlab.com/zh/regref. ...
 - MongoDB学习笔记:文档Crud Shell
		
MongoDB学习笔记:文档Crud Shell 文档插入 一.插入语法 db.collection.insertOne() 将单个文档插入到集合中.db.collection.insertMan ...
 - 数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
		
数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
 - css参考文档; 官方英文说明!!   1  margin padding 百分比参照物     2 margin值为auto时的说明 3 div在div里垂直居中方法 4 dispaly:flex说明
		
css参考文档 http://css.doyoe.com/ 两篇很好的文章:(下面的css官方英文说明链接 有时间可以研究下 http://www.w3.org/TR/css3-box/ ...
 - oracle数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1)
		
数据库 PSU,SPU(CPU),Bundle Patches 和 Patchsets 补丁号码快速参考 (文档 ID 1922396.1) 文档内容 用途 详细信息 Patchsets ...
 - html5 兼容参考文档 与  浏览器hack兼容参考文档
		
移动端兼容参考文档 http://mobilehtml5.org/ 浏览器hack http://browserhacks.com/ 附上部分截图
 - phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法
		
phpmyadmin-您可能正在上传很大的文件,请参考文档来寻找解决方法 实这个很简单的只要更改php.ini里三个配置即可.(见下面加粗部分,改成你自己的需求即可) ; Maximum allo ...
 - m_Orchestrate learning system---四、多看参考文档很多事情很轻松就解决了
		
m_Orchestrate learning system---四.多看参考文档很多事情很轻松就解决了 一.总结 一句话总结:多看参考文档啊 1.面包屑导航如何实现? 1 <ol class=& ...
 
随机推荐
- springboot 打包成jar
			
1.pom.xml配置 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins< ...
 - Website's Game source code
			
A Darkroom by doublespeakgames <!DOCTYPE html> <html itemscope itemtype="https://schem ...
 - 实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例)
			
实现纸牌游戏的随机抽牌洗牌过程(item系列几个内置方法的实例) 1.namedtuple:命名元组,可以创建一个没有方法只有属性的类 from collections import namedtup ...
 - TensorFlow 训练只用cpu
			
os.environ["CUDA_VISIBLE_DEVICES"] = ""
 - C++查找指定路径下的特定类型的文件
			
转载:https://www.cnblogs.com/tinaluo/p/6824674.html 例子:找到C盘中所有后缀为exe的文件(不包括文件夹下的exe文件) #include<std ...
 - How to add VTL tapes on DD6300 & label them into "Oracle_VTL" pool
			
Dear all , This is liulei , I was back so , How to add VTL tapes on DD6300 & label them into ...
 - 「luogu4366」最短路
			
「luogu4366」最短路 传送门 直接连边显然不行,考虑优化. 根据异或的结合律和交换律等优秀性质,我们每次只让当前点向只有一位之别的另一个点连边,然后就直接跑最短路. 注意点数会很多,所以用配对 ...
 - MySQL  之存储引擎与数据类型与数据约束
			
一.存储引擎场景 1.InnoDB 用于事务处理应用程序,支持外键和行级锁.如果应用对事物的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包括很多更新和删除操作,那 ...
 - 列举mvc ActionResult的返回值
			
8.列举ASP.NET MVC ActionResult的返回值有几种类型? 主要有View(视图).PartialView(部分视图).Content(内容).Json(Json字符串).Javas ...
 - 2020.2.19   restful的学习
			
restful Api 设计要素 3-8 如何设计Restful Api 资源路径(url),HTTP动词,过滤信息(做分页),状态码,错误处理,返回结果 3-9 初始化运行参数 3-10 ...