本地TS播放过程
本地M3U8播放过程
http工作流程
http分两个步骤
1、获取m3u8文件,这个是在哪里开始读的?
2、获取data数据,这个是从http_read开始读,可以通过修改这里实现buffer数据和引擎对接
3、s->user_agent,s->off,s->end_off,s->seekable这些是什么时候赋值的?
从 http_get_line获取到
4、需要修改的几个地方
1)http_get_line->ffurl_read
获取header
这个就模拟,主要是拿到长度
2)http_buf_read->ffurl_read
获取真正数据
调试过程
1、demo测试
通过URL传m3u8索引文件夹,真正TS数据通过读取本地文件来获取
修改:
http_buf_read
即可
2、m3u8通过buffer方式获取
先拿到m3u8数据
hls以及能解析得到playlist,但是获取第一个block数据后还会去获取m3u8的数据,也就是之前的m3u8的connect还没断开
通过log看到header少了Connection: close,以及一个回车,通过添加Connection: close解决了m3u8会多次连接的问题,但会出现
导致这个原因是因为读完第一个block后,没继续读下个block?
去掉之前私有协议的seek逻辑,在ijk_mediasource_readAt函数里去掉if (pointer_pos != position )
这么修改后,能播放了,看到希望咯
3、播放10左右,就把索引表的所有TS读完了,啥情况?
是因为ffurl_read有阻塞?而ijk_mediasource_readAt没有阻塞?
下面分析ffurl_read
int ffurl_read(URLContext *h, unsigned char *buf, int size)
{if (!(h->flags & AVIO_FLAG_READ))return AVERROR(EIO);return retry_transfer_wrapper(h, buf, size, 1, h->prot->url_read);
}
ffurl_read() -> retry_transfer_wrapper()
static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,int size, int size_min,int (*transfer_func)(URLContext *h,uint8_t *buf,int size))
{int ret, len;int fast_retries = 5;int64_t wait_since = 0;len = 0;while (len < size_min) {//如果len小于size_min,则循环,这里size_min=1if (ff_check_interrupt(&h->interrupt_callback))//检查是否结束return AVERROR_EXIT;ret = transfer_func(h, buf + len, size - len);//拉取数据if (ret == AVERROR(EINTR))//出错,继续continue;if (h->flags & AVIO_FLAG_NONBLOCK)return ret;if (ret == AVERROR(EAGAIN)) {//从新再来ret = 0;if (fast_retries) {//初始值5,尝试5次,5次后fast_retries--;} else {//睡眠方式尝试if (h->rw_timeout) {if (!wait_since)wait_since = av_gettime_relative();else if (av_gettime_relative() > wait_since + h->rw_timeout)return AVERROR(EIO);}av_usleep(1000);//开始睡眠1000us}} else if (ret < 1)return (ret < 0 && ret != AVERROR_EOF) ? ret : len;if (ret) {fast_retries = FFMAX(fast_retries, 2);wait_since = 0;}len += ret;}return len;
}