Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,长修远,我们不能没有钱
随笔 - 172, 文章 - 0, 评论 - 257, 引用 - 0
数据加载中……

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

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 (*!= '\0' && *!= ':') { // 未结束, 并未遇到分隔符':'
        if (!isalpha(*p)) // 如果不是英文字母
            goto file_proto;
        if ((- proto_str) < sizeof(proto_str) - 1)
            *q++ = *p; // 记录协议字符串
        p++;
    }

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

    file_proto:
        strcpy(proto_str, "file"); // 文件协议
    } else {
        *= '\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);

    *= 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;
}

@import url(http://www.cppblog.com/cutesoft_client/cuteeditor/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);

posted on 2012-12-14 01:34 Khan 阅读(1160) 评论(0)  编辑 收藏 引用 所属分类: GCC/G++跨平台开发


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理