?本地TS播放過程
本地M3U8播放過程
?http工作流程
?
?http分兩個步驟
1、獲取m3u8文件,這個是在哪里開始讀的?
2、獲取data數(shù)據(jù),這個是從http_read開始讀,可以通過修改這里實現(xiàn)buffer數(shù)據(jù)和引擎對接
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
獲取真正數(shù)據(jù)
調(diào)試過程
1、demo測試
通過URL傳m3u8索引文件夾,真正TS數(shù)據(jù)通過讀取本地文件來獲取
修改:
http_buf_read
?即可
2、m3u8通過buffer方式獲取
先拿到m3u8數(shù)據(jù)
hls以及能解析得到playlist,但是獲取第一個block數(shù)據(jù)后還會去獲取m3u8的數(shù)據(jù),也就是之前的m3u8的connect還沒斷開
通過log看到header少了Connection:?close,以及一個回車,通過添加Connection:?close解決了m3u8會多次連接的問題,但會出現(xiàn)
?導(dǎo)致這個原因是因為讀完第一個block后,沒繼續(xù)讀下個block?
去掉之前私有協(xié)議的seek邏輯,在ijk_mediasource_readAt函數(shù)里去掉if?(pointer_pos?!=?position?)
這么修改后,能播放了,看到希望咯
3、播放10左右,就把索引表的所有TS讀完了,啥情況?
是因為ffurl_read有阻塞?而ijk_mediasource_readAt沒有阻塞?
下面分析ffurl_read文章來源:http://www.zghlxwxcb.cn/news/detail-820447.html
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()文章來源地址http://www.zghlxwxcb.cn/news/detail-820447.html
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,則循環(huán),這里size_min=1
if (ff_check_interrupt(&h->interrupt_callback))//檢查是否結(jié)束
return AVERROR_EXIT;
ret = transfer_func(h, buf + len, size - len);//拉取數(shù)據(jù)
if (ret == AVERROR(EINTR))//出錯,繼續(xù)
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;
}
到了這里,關(guān)于ffmpeg本地TS和M3U8播放流程及調(diào)試過程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!