ffmpeg学习(一)

来源:互联网 发布:日本女腿粗 知乎 编辑:程序博客网 时间:2024/05/29 04:40

由于之前偶尔接触ffmpeg,但都没有深入的研究ffmpeg,所以打算一步步学习ffmpeg,写出我的学习过程,也希望各位高手能给于指点,给我提供更加便捷的学习之路。有一起学习的朋友,希望能多多交流。

1. ffmpeg编译(Ubuntu或者centos平台)

这里不多说,百度到处都是;

2. ffmpeg入门很难,各种资料很多,但一开始就各种专业函数其实很难理解,我在网上参考参考别人的代码做了一个读取264文件的例子。(frame没用到,我没删掉。)

////g++ read264.cpp  -lavcodec#include <stdio.h>#include <string.h>#include "Read.h"#include <iostream>using namespace std;#define BUFFLEN 1024#define in_buffer_size  4096extern "C"{#include "libavcodec/avcodec.h"AVCodec *pCodec;AVCodecContext *pCodecCtx= NULL;AVCodecParserContext *pCodecParserCtx=NULL;AVFrame   *pFrame;FILE *fp_in;uint8_t in_buffer[in_buffer_size + FF_INPUT_BUFFER_PADDING_SIZE];int cur_size;uint8_t *cur_ptr;AVPacket packet;enum AVCodecID codec_id=AV_CODEC_ID_H264;int first_time = 1;struct SwsContext *img_convert_ctx;int Read264(char* filepath_in ){    int ret;    avcodec_register_all();    pCodec = avcodec_find_decoder(codec_id);    if (!pCodec)     {           fprintf(stderr, "Codec not found\n");        exit(1);                   }    pCodecCtx = avcodec_alloc_context3(pCodec);    if (!pCodecCtx)    {        printf("Could not allocate video codec context\n");        return -1;    }    pCodecParserCtx=av_parser_init(codec_id);    if (!pCodecParserCtx){        printf("Could not allocate video parser context\n");        return -1;    }        if(pCodec->capabilities&CODEC_CAP_TRUNCATED)        pCodecCtx->flags|= CODEC_FLAG_TRUNCATED; /* we do not send complete frames */    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)     {        printf("Could not open codec\n");        return -1;                  }    //Input File    fp_in = fopen(filepath_in, "rb");    if (!fp_in)         {        printf("Could not open input stream\n");        return -1;    }        pFrame = av_frame_alloc();    av_init_packet(&packet);     int frameNum = 0;    while(1)    {        cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);        if (cur_size == 0)            break;        cur_ptr = in_buffer;        while (cur_size>0)        {            int len = <strong>av_parser_parse2</strong>(pCodecParserCtx, pCodecCtx, &packet.data, &packet.size, cur_ptr , cur_size , AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);            cur_ptr += len;            cur_size -= len;            if(packet.size==0)                continue;            //for one frame            printf("frame: %d ", frameNum++);            //Some Info from AVCodecParserContext            printf("Packet Size:%6d\t",packet.size);            switch(pCodecParserCtx->pict_type)            {                case AV_PICTURE_TYPE_I: printf("Type: I\t");break;                case AV_PICTURE_TYPE_P: printf("Type: P\t");break;                case AV_PICTURE_TYPE_B: printf("Type: B\t");break;                default: printf("Type: Other\t");break;            }            cout<<endl;        }        }    fclose(fp_in);    av_parser_close(pCodecParserCtx);    av_frame_free(&pFrame);    avcodec_close(pCodecCtx);                                                                                                                                               av_free(pCodecCtx);    return 0;}}int main(int argc, char** argv){    int ret;    char filepath_in[] = "test.264";    ret = Read264(filepath_in);    if(ret < 0)    {        printf("Read error!");        return -1;    }    return 0;}

这个例子用于读取264码流文件,并解析出帧类型I/P/B,计算帧数。

解析函数是

int av_parser_parse2 (AVCodecParserContext *s, AVCodecContext *avctx, uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size, int64_t pts, int64_t dts, int64_t pos)

程序调用时为:

int len = av_parser_parse2(pCodecParserCtx, pCodecCtx, &packet.data, &packet.size, cur_ptr , cur_size , AV_NOPTS_VALUE, AV_NOPTS_VALUE, AV_NOPTS_VALUE);


如果要查看函数的话,我建议去官网上找到avcodec.h文件查看,因为浏览网页的方式很方便,一目了然

http://ffmpeg.org/doxygen/2.6/libavcodec_2avcodec_8h.html

找到后也不需要点进去看函数内容,只需要看参数就可以了。如果要仔细研究,雷神博客:

http://blog.csdn.net/leixiaohua1020/article/details/12679719

(1) pCodecParserCtx

//定义

AVCodecParserContext *pCodecParserCtx=NULL;//初始化pCodecParserCtx=av_parser_init(codec_id);    if (!pCodecParserCtx){        printf("Could not allocate video parser context\n");        return -1;    }
</pre>
(2)初始化时的参数
<pre name="code" class="html">codec_id
//定义enum AVCodecID codec_id=AV_CODEC_ID_H264;

如果是其他格式的,可查看AVCodecID枚举类型,找到对应的类型。

(3) 参数2

<pre name="code" class="html">pCodecCtx
//定义:

AVCodecContext *pCodecCtx= NULL;

//初始化

    pCodecCtx = avcodec_alloc_context3(pCodec);    if (!pCodecCtx)    {        printf("Could not allocate video codec context\n");        return -1;    }

初始化的参数pCodec:(编解码器)

 pCodec = avcodec_find_decoder(codec_id);    if (!pCodec)     {           fprintf(stderr, "Codec not found\n");        exit(1);                   }
(4) 参数3和:4:&packet.data;  &packet.size  输出buffer

AVPacket packet;//初始化av_init_packet(&packet); 
(5) 参数5和6: cur_ptr(当前指针)、cur_size(内容长度)

int cur_size;uint8_t *cur_ptr;cur_ptr = in_buffer;inbuffer:        cur_size = fread(in_buffer, 1, in_buffer_size, fp_in);

然后调用av_parser_parse2函数,完成码流解析。

解析后的帧类型在第一个参数中:

pCodecParserCtx->pict_type

如此,该程序顺利完成。



0 0
原创粉丝点击