You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
2.9 KiB

/************************************************************************
** 此文件实现了 URLProtocol 抽象层广义文件操作函数,
** 由于 URLProtocol 是底层其他具体文件(file,pipe 等)的简单封装,
** 这一层只是一个中转站,大部分函数都是简单中转到底层的具体实现函数
/************************************************************************/
#include "../berrno.h"
#include "avformat.h"
/* ffmpeg可以支持多种协议,用链表把所有支持的协议串起来 */
URLProtocol *first_protocol = NULL;
/* 注册协议(所谓协议就是输入数据的载体:文件、套接字等形式) */
int register_protocol(URLProtocol *protocol)
{
URLProtocol **p;
p = &first_protocol;
while (*p != NULL)
p = &(*p)->next;
*p = protocol;
protocol->next = NULL;
return 0;
}
/* 打开URL */
int url_open(URLContext **puc, const char *filename, int flags)
{
// 上下文
URLContext *uc;
// 协议及操作
URLProtocol *up;
const char *p;
// 协议字符串
char proto_str[128], *q;
int err;
p = filename;
q = proto_str;
// 确定协议的名字
while (*p != '\0' && *p != ':')
{
if (!isalpha(*p)) // protocols can only contain alphabetic chars
goto file_proto;
if ((q - proto_str) < sizeof(proto_str) - 1)
*q++ = *p;
p++;
}
// if the protocol has length 1, we consider it is a dos drive
if (*p == '\0' || (q - proto_str) <= 1)
{
file_proto:
strcpy(proto_str, "file");
}
else
{
*q = '\0';
}
up = first_protocol;
// 寻找合适协议
while (up != NULL)
{
if (!strcmp(proto_str, up->name))
goto found;
up = up->next;
}
err = - ENOENT;
goto fail;
found:
// URL上下文
uc = av_malloc(sizeof(URLContext) + strlen(filename));
if (!uc)
{
err = - ENOMEM;
goto fail;
}
strcpy(uc->filename, filename);
uc->prot = up;
uc->flags = flags;
uc->max_packet_size = 0; // default: stream file
// 打开URL
err = up->url_open(uc, filename, flags);
if (err < 0)
{
av_free(uc);
*puc = NULL;
return err;
}
*puc = uc;
return 0;
fail:
*puc = NULL;
return err;
}
/* 读取数据 */
int url_read(URLContext *h, unsigned char *buf, int size)
{
int ret;
if (h->flags &URL_WRONLY)
return AVERROR_IO;
ret = h->prot->url_read(h, buf, size);
return ret;
}
/* 在广义文件中跳转 */
offset_t url_seek(URLContext *h, offset_t pos, int whence)
{
offset_t ret;
if (!h->prot->url_seek)
return - EPIPE;
ret = h->prot->url_seek(h, pos, whence);
return ret;
}
/* 关闭URL */
int url_close(URLContext *h)
{
int ret;
ret = h->prot->url_close(h);
av_free(h);
return ret;
}
int url_get_max_packet_size(URLContext *h)
{
return h->max_packet_size;
}