您的位置:首页 > 其它

ffmpeg分析系列之五(打开输入的文件)

2013-09-06 15:09 330 查看
1. 打开文件:

if (!fmt || !(fmt->flags & AVFMT_NOFILE)) {
因 fmt == NULL, 上面成立, 再看下面的代码:

ByteIOContext *pb = NULL; //
字节IO上下文

if ((err=url_fopen(&pb, filename, URL_RDONLY)) < 0) { //
只读方式打开输入的文件

goto fail;

}

if (buf_size > 0) { //
因 buf_size == 0, 不成立

url_setbufsize(pb, buf_size);

}
进入url_fopen函数:

int url_fopen(ByteIOContext **s, //
输出参数: 字节IO上下文

const char *filename, //
文件名

int flags) // 标志

{

URLContext *h; // URL(统一资源定位)上下文

int err;

err = url_open(&h, filename, flags); //
打开URL

if (err < 0)

return err;

err = url_fdopen(s, h); //
用URL上下文打开字节IO上下文

if (err < 0) {

url_close(h);

return err;

}

return 0;

}
进入url_open函数:

int url_open(URLContext **puc, // 输出参数: URL上下文

const char *filename, //
文件名

int flags) //
标志

{

URLProtocol *up;

const char *p;

char proto_str[128], *q;

// 提取协议

p = filename;

q = proto_str;

while (*p != '\0' && *p != ':') { //
未结束, 并未遇到分隔符':'

if (!isalpha(*p)) //
如果不是英文字母

goto file_proto;

if ((q - proto_str) < sizeof(proto_str) - 1)

*q++ = *p; //
记录协议字符串

p++;

}

if (*p == '\0' || is_dos_path(filename)) { //
如果上面是因为结束而跳出, 或且文件名是DOS路径

file_proto:

strcpy(proto_str, "file"); //
文件协议

} else {

*q = '\0'; //
追加结束符

}

up = first_protocol;

while (up != NULL) {

if (!strcmp(proto_str, up->name)) //
协议匹配

return url_open_protocol (puc, up, filename, flags); //
用这个协议打开URL

up = up->next;

}

*puc = NULL;

return AVERROR(ENOENT);

}
进入url_open_protocol函数:

int url_open_protocol (URLContext **puc, // 输出参数: URL上下文

struct URLProtocol *up, //
URL协议

const char *filename, //
文件名

int flags) // 标志

{

URLContext *uc;

int err;

// 网络初始化

#if CONFIG_NETWORK

if (!ff_network_init())

return AVERROR(EIO);

#endif

// 分配URL上下文并加上文件名的存储空间

uc = av_mallocz(sizeof(URLContext) + strlen(filename) + 1);

if (!uc) {

err = AVERROR(ENOMEM);

goto fail;

}

// 初始化URL上下文

#if LIBAVFORMAT_VERSION_MAJOR >= 53

uc->av_class = &urlcontext_class;

#endif

// 记录文件名

uc->filename = (char *) &uc[1];

strcpy(uc->filename, filename);

uc->prot = up; //
URL协议

uc->flags = flags; //
标志

uc->is_streamed = 0; //
默认不是流, 可以在up->url_open函数里修改

uc->max_packet_size = 0; // 包最大多大, 默认为0, 可以在up->url_open函数里修改

// 打开URL

err = up->url_open(uc, filename, flags);

if (err < 0) {

av_free(uc);

goto fail;

}

if( (flags & (URL_WRONLY | URL_RDWR)) // 如果以可写方式打开

|| !strcmp(up->name, "file")) // 或且是文件协议

// 如果不是流并且不可以url_seek

if(!uc->is_streamed && url_seek(uc, 0, SEEK_SET) < 0)

uc->is_streamed= 1; // 强制为流

// 输出参数: URL上下文

*puc = uc;

return 0;

fail:

*puc = NULL;

#if CONFIG_NETWORK

ff_network_close();

#endif

return err;

}
先来看看url_get_max_packet_size函数

int url_get_max_packet_size(URLContext *h)

{

return h->max_packet_size; //
包最大多大, 被上面初始化为0

}
进入url_fdopen函数:

int url_fdopen(

ByteIOContext **s, //
输出参数: 字节IO上下文

URLContext *h) //
URL上下文

{

uint8_t *buffer;

int buffer_size, max_packet_size;

max_packet_size = url_get_max_packet_size(h);

if (max_packet_size) {

buffer_size = max_packet_size;

} else {

buffer_size = IO_BUFFER_SIZE; // 缓冲大小为IO_BUFFER_SIZE

}

buffer = av_malloc(buffer_size); //
分配缓冲

if (!buffer)

return AVERROR(ENOMEM);

*s = av_mallocz(sizeof(ByteIOContext)); //
分配字节IO上下文

if(!*s) {

av_free(buffer);

return AVERROR(ENOMEM);

}

if (init_put_byte(*s, buffer, buffer_size,

(h->flags & URL_WRONLY || h->flags & URL_RDWR), h,

url_read, url_write, url_seek) < 0) {

av_free(buffer);

av_freep(s);

return AVERROR(EIO);

}

(*s)->is_streamed = h->is_streamed; //
是否为流

(*s)->max_packet_size = max_packet_size; // 包最大多大

if(h->prot) {

(*s)->read_pause = (int (*)(void *, int))h->prot->url_read_pause; //
读暂停函数

(*s)->read_seek = (int64_t (*)(void *, int, int64_t, int))h->prot->url_read_seek; //
读seek函数

}

return 0;

}

进入init_put_byte函数:

int init_put_byte(ByteIOContext *s, //
字节IO上下文

unsigned char *buffer, //
缓冲

int buffer_size, // 缓冲的大小

int write_flag, // 写标志

void *opaque, //
URL上下文

int (*read_packet)(void *opaque, uint8_t *buf, int buf_size), //
读包

int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),//
写包

int64_t (*seek)(void *opaque, int64_t offset, int whence)) //
调整文件指针

{

s->buffer = buffer;

s->buffer_size = buffer_size;

s->buf_ptr = buffer;

s->opaque = opaque;

url_resetbuf(s, write_flag ? URL_WRONLY : URL_RDONLY);

s->write_packet = write_packet;

s->read_packet = read_packet;

s->seek = seek;

s->pos = 0;

s->must_flush = 0;

s->eof_reached = 0;

s->error = 0;

s->is_streamed = 0;

s->max_packet_size = 0;

s->update_checksum= NULL;

if(!read_packet && !write_flag){

s->pos = buffer_size;

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

}

s->read_pause = NULL;

s->read_seek = NULL;

return 0;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: