Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3518793
  • 博文数量: 864
  • 博客积分: 14125
  • 博客等级: 上将
  • 技术积分: 10634
  • 用 户 组: 普通用户
  • 注册时间: 2007-07-27 16:53
个人简介

https://github.com/zytc2009/BigTeam_learning

文章分类

全部博文(864)

文章存档

2023年(1)

2021年(1)

2019年(3)

2018年(1)

2017年(10)

2015年(3)

2014年(8)

2013年(3)

2012年(69)

2011年(103)

2010年(357)

2009年(283)

2008年(22)

分类: C/C++

2010-12-01 12:45:42

上一次分析到了av_url_read_fseek()函数,这一章从这里写起:
offset_t av_url_read_fseek(ByteIOContext *s,
        int stream_index, int64_t timestamp, int flags)
{
    URLContext *h = s->opaque;
    offset_t ret;
    if (!s->read_seek)
        return AVERROR(ENOSYS);
    ret = s->read_seek(h, stream_index, timestamp, flags);                 //上一次说过了
ByteIOContext结构的初始化,它指向的read_seek函数将被初始化
                                                                                                                  为avio.c函数中
av_url_read_seek函数,一会在往下看
    if(ret >= 0) {
        s->buf_ptr = s->buf_end; // Flush buffer                              //此处这行代码非常重要,用于刷新环形缓冲区,否则seek之前的数据包将可能会被滞留在缓冲区
        s->pos = s->seek(h, 0, SEEK_CUR);                                    //此处的seek至SEEK_CUR不知所云,我的代码测试结果是seek到正确位置后又退回至seek
                                                                                                         前的位置,相当于没有seek.所以我并没有初始化URLprotocol中的seek函数.

    }
    return ret;
}
现在我们已经接近了MMS协议内部的处理了,接着看一下
av_url_read_seek()函数,这个函数会被调用多次,每一次都会因为指向不同的URLProtocol而调用不同的协议:
offset_t av_url_read_seek(URLContext *h,
        int stream_index, int64_t timestamp, int flags)
{
    if (!h->prot->url_read_seek)                                                  //h->prot表示MMS协议,其指向的从这里来说是URLProtocol结构,目前来说是mms协议.
        return AVERROR(ENOSYS);
    return h->prot->url_read_seek(h, stream_index, timestamp, flags);                  
}

   这里要顺便提及一下,此函数同样也是tcp协议的调用函数,当然我们添加的seek功能并未循环调用此函数,但是我这里举例说一下MMS协议的read是循环调用了此函数的.我不细贴代码了,说一下过程:
   第一次调用此函数,h->prot为MMS协议,因此调用mms_read()函数(在mms.c中,也可以在asf.c中实 现).mms_read会再次调用此函数,但是这个函数中的h->prot将会变为tcp协议,从而使用tcp协议读取数据.大致是这样,详细见代 码!!!
    MMS协议中seek的命令是0x07,我也不细说了,翻阅文档就可以了.由于之前已经提到过seek函数的实现,也不打算贴很详细的代码,状态基的事情 呢,每个程序员都有自己的想法,我的贴出来也许还会被认为不高效,就自己琢磨吧!唯一需要在罗嗦一下的就是超时问题,超时使用select实现的:
  static int tcp_read(URLContext *h, uint8_t *buf, int size)
{
    TCPContext *s = h->priv_data;
    int len, fd_max, ret;
    fd_set rfds;
    struct timeval tv;

    for (;;) {
        fd_max = s->fd;
        FD_ZERO(&rfds);
        FD_SET(s->fd, &rfds);
        tv.tv_sec = 0;
        tv.tv_usec = 100 * 1000;
        ret = select(fd_max + 1, &rfds, NULL, NULL, &tv);
        if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
            len = recv(s->fd, buf, size, 0);
            if (len < 0) {
                if (ff_neterrno() != FF_NETERROR(EINTR) &&
                    ff_neterrno() != FF_NETERROR(EAGAIN))
                    return AVERROR(errno);
            } else return len;
        } else if (ret < 0) {
            return -1;
        }
    }
}
阅读(1952) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~