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
如此,该程序顺利完成。
- ffmpeg学习(一)
- ffmpeg学习(一)
- FFMPEG学习【libavfilter】(一)
- FFMPEG学习【libavdevice】(一)
- FFMpeg学习(一):19 ffmpeg commands for all needs
- ffmpeg和SDL学习笔记(一)
- ffmpeg和SDL学习笔记(一)
- FFMPEG学习【libavcodec】:实用函数(一)
- FFMPEG学习【libavutil】:Memory Management(一)
- FFMPEG学习【libavutil】:数据结构(一)
- FFMPEG学习【libavutil】:音频相关(一)
- ffmpeg和SDL学习笔记(一)
- FFmpeg 学习笔记(一)
- FFmpeg编程学习笔记一
- [ffmpeg]学习(一)Mac上的编译
- ffmpeg学习一:启动篇(学习计划与环境搭建)
- FFMPEG学习【libavcodec】:核心函数以及结构体(一)
- An ffmpeg and SDL Tutorial 学习笔记(一)
- robotium 初体验
- django ckeditor 使用
- [新奇周边] 内置2400mAh电量 可以充电的手机壳上市【转载:今日头条】
- 推荐引擎算法学习导论
- yuv420
- ffmpeg学习(一)
- Oracle 11g客户端及PLSQL Developer配置
- UVa11212 - Editing a Book
- spring 核心内容
- 第二届Alictf-初赛第四题
- robotium自动化测试简介
- linux下普通用户获取sudo
- Android中自定义通用Json解释器
- Android自定义控件系列二:自定义开关按钮(一)