ffmpeg中的http协议相关代码阅读笔记

今天闲来无事,尝试看了下ffmpeg中的相关http协议传输处理代码

先简单说下这个代码在整个仓库里面的位置:

ffmpeg/libavformat/http.h

ffmpeg/libavformat/http.c

avoi.h中的函数调用分析

avoi.h是ffmpeg中libavformat/目录下的一个重要的头文件,这个文件主要处理 了一些传输协议的传输封装。他的封装过程是通过函数指针来实现的。

可以先看http.c文件中的最后一个结构体:

URLProtocol http_protocol = {

"http",

http_open,

http_read,

http_write,

http_seek,

http_close,

.url_get_file_handle = http_get_file_handle,

.priv_data_size = sizeof(HTTPContext),

.priv_data_class = &httpcontext_class,

};

URLProtocol这个结构是在avoi.h中一个很重要的结构,他的存在的意义就是为了统一接口,可以在avoi.h中查到他的定义:

typedef struct URLProtocol {

const char *name;

int (*url_open)(URLContext *h, const char *url, int flags);

int (*url_read)(URLContext *h, unsigned char *buf, int size);

int (*url_write)(URLContext *h, const unsigned char *buf, int size);

int64_t (*url_seek)(URLContext *h, int64_t pos, int whence);

int (*url_close)(URLContext *h);

struct URLProtocol *next;

int (*url_read_pause)(URLContext *h, int pause);

int64_t (*url_read_seek)(URLContext *h, int stream_index,

int64_t timestamp, int flags);

int (*url_get_file_handle)(URLContext *h);

int priv_data_size;

const AVClass *priv_data_class;

} URLProtocol;

针对http.c文件处理的http协议,最主要的就是实现URLProtocol中的函数指针,至于每个函数的具体意义,相信看命名就可以知道。

那么avoi.h中的函数又是怎么使用到这个内容的呢?这就可以从avoi.h中的几个函数看出来:

int url_open();

int url_read();

int url_write();

int64_t url_seek(URLContext *h, int64_t pos, int whence);
int url_close(URLContext *h);
找其中的一个分析,url_open:
int url_open(URLContext **puc, const char *filename, int flags)
{
int ret = url_alloc(puc, filename, flags);
if (ret)
return ret;
ret = url_connect(*puc);
if (!ret)
return 0;
url_close(*puc);
*puc = NULL;
return ret;
}

url_open函数中使用到了url_alloc, url_connect, url_close,折伞个函数可能会在不同的情况下进行使用,由于代码太多,就不贴了,仅记录如下
url_alloc函数:
  • 处理协议探测,如果url参数中没有正常的协议,就默认填上"file://"然后作为文件协议处理
  • 处理探测的过程是在所有的已经注册上的协议链表中搜索对应名称的协议,这个名称,就是URLProtocol.name
  • 如果探测成功会把puc,即URLContext结构体也帮忙分配好,并作为参数out

url_connect:

  • 和url_open函数一样,url_connect会调用协议中的http_open函数进行http请求初始化: uc->prot->url_open()
  • url_connect返回非零值代表失败

url_close:

  • 如果url_connect失败,返回是非0值,就会调用url_close,并返回整个url_open函数失败

http.c文件的一些关键点分析

http_open函数

http_open函数会尝试调用其中的http_open_cnx,然后http_open_cnx会调用静态成员函数http_connect来进行http请求,其中所有的请求发送都是通过http_write函数来进行的。

http_read函数

相关的函数:

http_read, http_getline, http_getc

http_getc会有个1024的缓冲区,如果发现缓冲区满了才会继续读取,如果没有慢就每次读缓冲区里面的一个字符

static int http_getc(HTTPContext *s)

{

int len;

if (s->buf_ptr >= s->buf_end) {

len = url_read(s->hd, s->buffer, BUFFER_SIZE);

if (len < 0) {

return AVERROR(EIO);

} else if (len == 0) {

return -1;

} else {

s->buf_ptr = s->buffer;

s->buf_end = s->buffer + len;

}

}

return *s->buf_ptr++;

}

HTTP协议中数据发送和接受的处理

http.c函数的URLProtocol结构体中有个PrivateData的指针,这个指针存储了http协议中的一些内部使用到的数据变量,内部处理的数据变量结构体如下:

typedef struct {

const AVClass *class;

URLContext *hd;

unsigned char buffer[BUFFER_SIZE], *buf_ptr, *buf_end;

int line_count;

int http_code;

int64_t chunksize;      /**< Used if "Transfer-Encoding: chunked" otherwise -1. */

int64_t off, filesize;

char location[MAX_URL_SIZE];

HTTPAuthState auth_state;

unsigned char headers[BUFFER_SIZE];

int willclose;          /**< Set if the server correctly handles Connection: close and will close the connection after feeding us the content. */

} HTTPContext;

可以看到一个比较重要的信息是:该私有的内部数据中竟然也有一个URLContext,那这个是什么呢?这个URLContext的协议又是什么呢?我通过阅读代码发现这个URLContext就是指向的tcp协议,用来通过tcp读取和返回数据。很感慨阿。这样很简单的就可以同时支持http,tcp协议,而且把tcp,udp协议封装起来以后,基本上其他的像rtsp, mms等协议也可以通过制定他们自己的内在协议来处理了。

在http.c中的http_open_cnx函数中有一句代码:

ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);

这样就很好的把http的底层tcp协议比较好的串接起来

总结

通过看ffmpeg的代码,总结了下,其实ffmpeg本身并不是很神秘,他本身只是提供了一个很好的很平等并可以无线扩展的架构。而在ffmpeg这个架构上,才能有很多codec, decodec和mutex, io, protocol很好的共存处理。

很欣赏,能作这个完美架构的大师,只有这种完美的架构才能吸引更多的开源爱好着去研究ffmpeg的代码,并不断的丰富它!

ffmpeg中的http协议相关代码阅读笔记相关推荐

  1. ffmpeg 代码阅读笔记1/2

    ffmpeg 代码阅读笔记1/2 ============================================================ 0. ffmpeg 主流程 ======== ...

  2. VINS-Mono代码阅读笔记(十):vins_estimator中的非线性优化

    本篇笔记紧接着VINS-Mono代码阅读笔记(九):vins_estimator中的相机-IMU对齐,初始化完成之后就获得了要优化的变量的初始值,后边就是做后端优化处理了.这部分对应论文中第VI部分, ...

  3. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  4. linux 协议栈 位置,[置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  5. [原创]fetchmail代码阅读笔记---ESMTP的认证方式

    fetchmail代码阅读笔记---ESMTP的认证方式 作者: 默难 ( monnand@gmail.com ) 0    引言 fetchmail是Eric S. Raymond组织编写的一款全功 ...

  6. BNN Pytorch代码阅读笔记

    BNN Pytorch代码阅读笔记 这篇博客来写一下我对BNN(二值化神经网络)pytorch代码的理解,我是第一次阅读项目代码,所以想仔细的自己写一遍,把细节理解透彻,希望也能帮到大家! 论文链接: ...

  7. leveldb代码阅读笔记(一)

    leveldb代码阅读笔记 above all leveldb是一个单机的键值存储的内存数据库,其内部使用了 LSM tree 作为底层存储结构,支持多版本数据控制,代码设计巧妙且简洁高效,十分值得作 ...

  8. ORB-SLAM2代码阅读笔记(五):Tracking线程3——Track函数中单目相机初始化

    Table of Contents 1.特征点匹配相关理论简介 2.ORB-SLAM2中特征匹配代码分析 (1)Tracking线程中的状态机 (2)单目相机初始化函数MonocularInitial ...

  9. 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(九)—— 预测与校验

    系列目录: 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(一)--数据 菜鸟笔记-DuReader阅读理解基线模型代码阅读笔记(二)-- 介绍及分词 菜鸟笔记-DuReader阅读理解基线模 ...

最新文章

  1. KVM虚拟机内无agent情况下的监控方法
  2. ubuntu 16.04 挂载新硬盘
  3. linux下IPROTO_TCP,TCP/IP协议栈在Linux内核中的运行时序分析
  4. linux中公钥和私钥的区别以及关系
  5. Android 创建与解析XML(三)—— Sax方式
  6. php使用框架优缺点,PHP四大主流框架的优缺点总结(上)
  7. PHP学习笔记五(命名空间)
  8. 外贸必备——各国常用搜索引擎
  9. python 对 excel 进行合并与去重操作
  10. 2019做报表用什么软件:报表类型,产品推荐
  11. python程序猿_python程序员指南 pdf下载
  12. plc串口通讯 qt_Qt 编写串口调试助手
  13. Flask-token-werkzeufg
  14. Ubuntu18.04安装教程——超详细的图文教程
  15. 闲聊ROOT权限——ROOT权限的前世今生
  16. 《企业自主搞定ERP》试读:第三章-成功案例
  17. 山西将部署5万个5G基站,并对5G基站进行电价补贴
  18. 工厂模式实现及使用场景--java
  19. BZOJ 3131 [Sdoi2013]淘金
  20. 君子签:用区块链技术打造电子签约全生态闭环服务

热门文章

  1. TextBox控件的使用,MaskedTextBox控件的使用
  2. excel的字符串拼接和某列全部填一样的值
  3. Java编程基础30——SE经典案例
  4. nfs 和rpcbind的关系
  5. #两台主机之间通信时为什么要用IP地址,而不直接用硬件地址?
  6. Til the Cows Come Home(最短路-Dijkstra)
  7. android游戏开发--三国无双(一)
  8. cuteftp上传文件失败,提示权限失败
  9. cic曲线是什么_国际经济学6章经济增长与国际贸易.ppt
  10. 【客服系统】在线客服系统源码外贸聊天通讯带翻译多语言支持网页安卓苹果打包封装APP