ffmpeg的IO操作

 

ffmpeg 可以通过IO操作将数据读取和存储在文件或网络中
作为数据的读取和写入地址,数据被存放在file,http,

ffmpeg 不仅可以编解常用的音视频格式,还可以将数据导入/导出到各种媒介中。
当进行数据压缩时,流媒体数据可以从文件中获取,也可以借助各种专用网络协议从网络中获取。
当进行数据解压时,数据可以存放在文件中,也可以通过网路协议发送到远端。

在ffmpeg中针对不同媒介的数据操作方法被抽象为url_xxx,并记录在结构体 URLProtocol 中。
以文件操作为例:

/libavformat/file.c
URLProtocol ff_file_protocol = {
    .name                = "file",
    .url_open            = file_open,
    .url_read            = file_read,
    .url_write           = file_write,
    .url_seek            = file_seek,
    .url_close           = file_close,
    .url_get_file_handle = file_get_handle,
    .url_check           = file_check,
};
再比如网络协议rtsp操作:
/libavformat/rtpproto.c
URLProtocol ff_rtp_protocol = {
    .name                = "rtp",
    .url_open            = rtp_open,
    .url_read            = rtp_read,
    .url_write           = rtp_write,
    .url_close           = rtp_close,
    .url_get_file_handle = rtp_get_file_handle,
};

这些操作集通过REGISTER_PROTOCOL ();被注册到系统中,以ffplayer为例,
av_register_all 会负责调用REGISTER_PROTOCOL()注册操作集

为了保证IO 操作的一致性,ffmpeg  muxer/demuxer 调用函数一组avio_xxx 进行io操作,包括:
avio_rxxx()
avio_wxxx()
avio_open()
avio_close()

...

它们实际上是对
url_open
url_read
url_write
url_cloge

...


的更高一层的抽象,使用avio_xxx 将隔离具体媒介的差异。

avio_rxx 和avio_wxxx  间接的调用ffurl_write 和 ffurl_read,实现读写操作。
而avio_open 则根据文件名判断并实现avio_rxx ,avio_wxxx 和 不同媒介的操作函数 ffurl_read, ffurl_read 之间的邦定。

 

avio_rxx 和avio_wxxx函数实际上只是对内存缓冲区中的数据进行操作,当缓冲区数据不足或将要溢出时,
调用flush_buffer() 或 fill_buffer() 把数据读写到媒介中。

avio_rxxx() 调用fill_buffer(AVIOContext *s)
avio_wxxx() 调用flush_buffer(AVIOContext *s)

flush_buffer() 的实现主要通过回调函数s->write_packet
fill_buffer()  的实现主要通过回调函数s->read_packet


在调用avio_open时:
1.  ffurl_open 通过解析文件名,找出对应的操作集  URLProtocol
2.  ffio_fdopen 调用ffio_init_context 把 URLProtocol 中的
ffurl_read ,ffurl_write , ffurl_seek注册到AVIOContext 结构体中
成为将回调函数write_packet ,read_packet和 seek

你可能感兴趣的:(ffmpeg的IO操作)