文件夹

1 初衷

2 ts demux的功能介绍

1 初衷


之前打算给dtplayer加入一些亮点功能,最初的想法是:bt下载播放 + hls支持

bt下载因为以来libtorrent库,尽管搞懂了怎样加入,但须要改动libtorrent库来集成,

若将libtorrent集成到代码中,会将代码变得庞大,框架清晰度会变差,随机临时取消了bt功能的开发/

后面開始加入hls支持,hls支持打算加入例如以下模块: stream - hls   demuxer - ts  decoder - h264 这样加上之前的faad

对于特定网络流就能够不依赖ffmpeg来播放了。

ts demuxer便是第一步功能。

凭借之前对ts的理解,感觉应该比較快完毕的,当时从github中找到了一个开源的ts解析库:https://github.com/nevali/tsdemux

但不幸的是这个库仅仅提供了 section的解析功能,并没有提供读取es包的功能。遂打算自行将这部分功能补全。

代码: https://github.com/peterfuture/dtplayer/blob/dev-ts/dtdemux/demuxer/demuxer_ts.c

2 ts demux的功能

ts demux符合dtplayer demuxer的标准接口,

先看下定义:


demuxer_wrapper_t demuxer_ts = {

.name = "ts demuxer",

.id = DEMUXER_TS,

.probe = ts_probe,

.open = ts_open,

.read_frame = ts_read_frame,

.setup_info = ts_setup_info,

.seek_frame = ts_seek_frame,

.close = ts_close

};

以下依次介绍各个功能。

2.1 probe


static int ts_probe(demuxer_wrapper_t *wrapper, dt_buffer_t *probe_buf)

{

const uint8_t *buf = probe_buf->data;

const uint8_t *end = buf + probe_buf->level - 7;

if(probe_buf->level < 10)

return 0;

int retry_times = 100;

for(; buf < end; buf++)

{

uint32_t header = DT_RB8(buf);

if((header&0xFF) != 0x47)

{

if(retry_times-- == 0)

return 0;

continue;

}

//found 0x47

if(buf+188 > end)

return 0;

header = DT_RB8(buf+188);

if((header & 0xFF) == 0x47)

{

dt_info(TAG,"ts detect \n");

return 1;

}

else

return 0;

}

return 0;

}

这里实现了一个比較简单的probe功能,先找到同步字0x47,若后面188字节后面也是0x47,则觉得是ts流,临时probe有些流还不能解析

主要问题有: a 有些流的包大小并非188, 这样的流会出错 b 单纯的仅仅推断一次会有偶然性的问题

但这些修正起来比較简单,因为功能还未实现,这里仅仅介绍思想,还有面会完好

2 ts_open

这里是解析ts头信息,主要功能包含:

pat解析

pmt解析

stream 信息解析: duration - bitrate

es信息解析:audio: channel-samplerate-bps  video: width-height-fmt

这里代码比較多就仅仅说下思想,感兴趣的自己去读代码就能够了

首先pat pmt的解析是通过之前说的开源库完毕的,通过解析pat pmt能够得到文件里有几个流,各自是什么格式

得到后一般若有video stream,则以video为參考来计算流信息(正确的做法是找到流的pcr_pid,也就是參考流来计算,但普通情况下參考流都是video)

计算duration: 首先找到第一帧的pts , 然后找到最后一帧的pts, 通过pts差距得到duration

计算bitrate: 有了stream size和 duration, 直接计算得到bitrate

当中计算pts的时候,这里介绍下,详细代码在ts/stream.c中,是后面我自己加的

if(packet->payloadlen > 0 && packet->unitstart)

{

uint8_t *pcrbuf = packet->payload;

int len = pcrbuf[0];

if(len <= 0 || len > 183)	//broken from the stream layer or invalid

goto QUIT;

pcrbuf++;

int flags = pcrbuf[0];

int has_pcr;

has_pcr = flags & 0x10;

pcrbuf++;

if(!has_pcr)

goto QUIT;

int64_t pcr = -1;

int64_t pcr_ext = -1;

unsigned int v = 0;

//v = (uint32_t)pcrbuf[3]<<24 | pcrbuf[2]<<16 |	pcrbuf[1]<<8 |pcrbuf[0];

v = (uint32_t)pcrbuf[0]<<24 | pcrbuf[1]<<16 |	pcrbuf[2]<<8 |pcrbuf[3];

pcr = ((int64_t)v<<1) | (pcrbuf[4] >> 7);

pcr_ext = (pcrbuf[4] & 0x01) << 8;

pcr_ext |= pcrbuf[5];

pcr = pcr * 300 + pcr_ext

packet->pts = pcr / 300;

//printf("get pts:%lld \n",pcr);

}

这里是去掉了ts包开头的四个字节,首先看是否是一帧的开头,若是的话推断是否有pcr flag

若有则直接解析,解析方法比較简单,依照标准就可以

这里介绍下ts的编码參考时钟为:27M HZ,而pts的单位与时间s的换算为:90000

因此获取參考时间(也就是上面的pcr后),换算为pts的计算方式为: pts = pcr * 9000 / 27000000 = pcr / 300

这里得到的就直接是pts了。

另一个问题是:这里直接解析es流貌似不能获取 视频: width height  音频:channel samplerate等信息,

对于ffmpeg来讲没有问题,因此在av_find_stream_info中能够通过decode one frame来获取, 但dtplayer框架上是不方便直接启动解码器的

对于mplayer 的ts 也是没有decode的,知道的同学能够指导下最好,不胜感激,否则得自己扒mplayer的代码了。

3 ts_setup_info

这里根据ts_open获取的信息,来setup dtplayer的media info

然后选择av视频流就能够了,比較简单

4 ts_read_frame

这里比較重要,也是花了比較多时间的地方,一開始的时候,以为拿到av的pid后,后面直接组装数据就能够了

流程为: 解析ts包获取pid -> 若是选择的pid,直接将payload保存下来,通过简单的推断是否是unit_start来推断是否读取到了完整帧 --> 返回完整帧

但实际情况并非这样,保存在ts包中的是实际的pes包,而不是es流,在读包的时候须要将pes包头去掉

这里參考ffmpeg进行了模拟,详细代码在:handle_ts_pkt中,详细逻辑不说了,仅仅是更正自己的一个认知误区

只是这里还有个问题,读取的数据包会掺杂错误信息: 经过跟代码,大体定位了问题,在解析pes包头的时候,是能够知道这个包的大小的

但读取ts包的时候都是依照188,即payload通常是184字节,这样非常有可能就超过了pes包的大小

此时应该怎样处理: 若仅仅读取固定大小凑足包大小返回,则声音是错的

若将全部payload都打包进去,则播放过程会有杂音。

这里还须要研究下。有熟悉的同学也请指教

5 ts_seek

这里seek就比較简单了,尽管还未完毕,但思想能够说下,參考ffmpeg,一句bitrate seek到某个位置,读取ts包,计算pts

若不匹配,则依照二分查找算法,继续seek

来达到seek的目的。(后面会实现)

这里ts demux仅仅是为了实现一个简单的功能,给后面基于dtplayer开发简单的应用的开发人员提供便利: 若服务端也自己做的话,能够非常方便的改造dtplayer中的ts demux达到字节的要求,

同一时候去掉了ffmpeg的负担,岂不非常方便,这也是dtplayer会一直遵循的目标。

github:https://github.com/avplayer/dtplayer   # C++

github:https://github.com/peterfuture/dtplayer # C

bug report: peter_future@outlook.com

blog: http://blog.csdn.net/dtplayer

bbs: http://avboost.com/

wiki: http://wiki.avplayer.org/Dtplayer

因为后面随着开发的进行文章会进行细节的更新,因此为了保证读者随时读到最新的内容,文章禁止转载,多谢大家支持!

ts demuxer的加入记录的更多相关文章

  1. Python爬虫入门教程 51-100 Python3爬虫通过m3u8文件下载ts视频-Python爬虫6操作

    什么是m3u8文件 M3U8文件是指UTF-8编码格式的M3U文件. M3U文件是记录了一个索引纯文本文件, 打开它时播放软件并不是播放它,而是根据它的索引找到对应的音视频文件的网络地址进行在线播放. ...

  2. 使用php来访问操作sql server

    使用php来访问操作sql server 在此分成三步走: 第一部:查看配置,下载文件 首先查看自己的php和sql server版本 Php文件输入echo PHP_VERSION  运行脚本就可以 ...

  3. records.config文件参数解释

    # Process Records Config File # # <RECORD-TYPE> <NAME> <TYPE> <VALUE (till end ...

  4. Mysql基准测试详细解说(根据慕课网:《打造扛得住Mysql数据库架构》视频课程实时笔录)

    什么是基准测试 基准测试是一种测量和评估软件性能指标的活动用于建立某个时刻的性能基准,以便当系统发生软硬件变化时重新进行基准测试以及评估变化对性能的影响. 我们可以这样认为:基准测试是针对系统设置的一 ...

  5. Android 音视频开发学习思路

    Android 音视频开发这块目前的确没有比较系统的教程或者书籍,网上的博客文章也都是比较零散的.只能通过一点点的学习和积累把这块的知识串联积累起来. 初级入门篇: Android 音视频开发(一) ...

  6. typescript-koa-postgresql 实现一个简单的rest风格服务器 —— typescript 开发环境配置

    最近需要用 nodeJS 写一个后台程序,为了能够获得 IDE 的更多代码提示,决定用 typescript 来编写,随便也学习下 ts,在这记录下实现过程. 1.新建文件夹 typescript-k ...

  7. 日志统计|2018年蓝桥杯B组题解析第八题-fishers

    标题:日志统计 小明维护着一个程序员论坛.现在他收集了一份"点赞"日志,日志共有N行.其中每一行的格式是: ts id 表示在ts时刻编号id的帖子收到一个"赞" ...

  8. 使用PHP结合Ffmpeg快速搭建流媒体服务实践

    一.背景 笔者想将自己收藏的一些电影放到网站上可以用来随时播放,不过遇到了一个问题,便是如果直接将MP4文件放放到网站目录当中,手机端必须下载整个视频才可以播放,而如果跨外网传输,这实在是不太现实. ...

  9. BFS(四):搜索状态判重

    在采用广度优先算法进行搜索时,一个需要重点注意的是在搜索过程中判重和去重.前面介绍的几个例子中,判重都较简单,如采用vis[]数组,若vis[i]==0,则i未访问过,i入队列:若vis[i]!=0, ...

随机推荐

  1. Java Web学习总结(7)——HttpServletRequest对象

    一.HttpServletRequest介绍 HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象 ...

  2. 哈夫曼树的介绍 ---java实现

    一.     什么是哈夫曼树 是一种带权路径长度最短的二叉树,也称最优二叉树 带权路径长度:WPL=(W1*L1+W2*L2+W3*L3+...+ Wn*Ln) N个权值Wi(i=1,2,...n)构 ...

  3. R语言-回归

    定义: 回归是统计学的核心,它其实是一个广义的概念,通常指那些用一个或多个预测变量来预测响应变量.既:从一堆数据中获取最优模型参数 1.线性回归 1.1简单线性回归 案例:女性预测身高和体重的关系 结 ...

  4. t_user is not mapped [from t_user as u where u.loginname = :loginname and u.password =:password]

    转自:https://blog.csdn.net/u010876380/article/details/52714539 错误: Struts Problem Report Struts has de ...

  5. (转)kvm虚拟机中,如何给子系统更换光盘

    转自:http://www.cnblogs.com/york-hust/archive/2012/06/12/2546334.html 启动kvm后,在kvm窗口中,按下CTRL+ALT+2,切换至q ...

  6. python3 turtle画正方形、矩形、正方体、五角星、奥运五环

    python3 环境 turtle模块 分别画出 正方形.矩形.正方体.五角星.奥运五环 #!/usr/bin/env python # -*- coding:utf-8 -*- # Author:H ...

  7. (转)nginx的root和alias指令的区别

    转自 http://www.cnblogs.com/tintin1926/archive/2012/07/11/2586813.html nginx配置下有两个指定目录的执行,root和alias   ...

  8. php实现 计算字符串的距离

    php实现 计算字符串的距离 一.总结 一句话总结:解决dp问题最好的方法是什么:分析出状态后 实例+画表. 1.解决dp问题最好的方法是什么? 分析出状态后 实例+画表 2.画图的好处? 画出来表之 ...

  9. Nginx+Tomcat搭建高性能负载均衡集群的实现方法

    一.    目标实现高性能负载均衡的Tomcat集群: 二.步骤 1.首先下载Nginx,要下载稳定版: 2.然后解压两个Tomcat,分别命名为apache-tomcat-6.0.33-1和apac ...

  10. linux下实现监控进程网络带宽

    嗯,近期都在网易游戏实习,所以貌似有段时间没有上来写点东西了... 来网易游戏实习最基本的目的事实上就是想知道在游戏公司里面工作都是些什么内容,毕竟自己曾经也没有接触过游戏公司.. 还比較的好奇.. ...