广播传输相关的项目,需求是UDP发送TS到IP/ASI网关,网关经过ASI输出到激励器,再由激励器通过射频天线输出,接收端为终端机顶盒。

  因为以前没有怎么接触过广播相关的东西,一开始认为用C#写个UDP的程序将TS发出即可。TS的规范是每188个字节为一个packet,我用固定码率计算出100毫秒要发送的packet的个数,发送一定量的packet后如果还未到100毫秒则进行等待,超过100毫秒则重新发送下一组packet。但测试发现,发送的数据可以到达网关,但激励器却接收不到。在网关上看到有ASI输出的码率但不是太精确。所幸手头上有一个伙伴公司用VC写的TS发送测试工具,该工具发送的码率可以正确到达激励器并被机顶盒接收。于是想到用wireshark抓包工具抓包看一下和我的程序有什么区别。

  经过抓发发现伙伴公司写的TS发送工具发送packet十分均匀,而我的程序发送的时间间隔则有跳跃。后来想到,发送的时间如果不均匀,可能会造成设备缓冲区溢出发生,所以无法正确接收。我的程序是一下子吧固定的一组包全部发出去,然后等待,但伙伴公司的工具则是每个包固定的发送时间,可以肯定我写的程序,发送TS时,packet没有均匀的离开发送端,造成码率错误。知道了问题,那么如何修改呢?抓包工具看到,每个包发送的时间及间隔的最小单位是微秒,然而sleep及普通的定时器是无法做到微秒级的精确计时的。

  于是求助度娘了解到,要像达到精确计时就需要获取CPU的相关计时信息进行精确计算。于是参考VC上精确计时和别人的文章找到了精确到微妙级计时的方法。【参考[.NET] 如何用C#做高精度计时器>http://blog.csdn.net/cloudhsu/article/details/5773043】。

namespace AccurateTimer{
/// <summary>
/// 消息结构体
/// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct MSG
{
public IntPtr handle;
public uint msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public System.Drawing.Point p;
} /// <summary>
/// 定时函数
/// </summary>
public class AccurateTimer
{ //调用系统API获取CPU时钟相关信息
public static bool IsTimeBeginPeriod = false; const int PM_REMOVE = 0x0001; [DllImport("user32.dll", SetLastError = true)]
static extern bool PeekMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin,
uint wMsgFilterMax, uint wRemoveMsg); [DllImport("user32.dll", SetLastError = true)]
static extern bool TranslateMessage(ref MSG lpMsg); [DllImport("user32.dll", SetLastError = true)]
static extern bool DispatchMessage(ref MSG lpMsg); [DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueryPerformanceCounter(ref Int64 count); [DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueryPerformanceFrequency(ref Int64 frequency); public static int GetTimeTick()
{
return Environment.TickCount;
} //参数_wait_count:要等待的时间,根据时间内部换算可换成秒,毫秒或微秒,_wait_count2:实际回传的等待时间,精度不大于1微妙 public static void AccurateSleep(int _wait_count, ref double _wait_count2)
{
Int64 t_i8Frequency = ;
Int64 t_i8StartTime = ;
Int64 t_i8EndTime = ;
//double t_r8PassedMSec = 0;
MSG msg;
AccurateTimer.QueryPerformanceCounter(ref t_i8StartTime);
AccurateTimer.QueryPerformanceFrequency(ref t_i8Frequency);
do
{
if (AccurateTimer.PeekMessage(out msg, IntPtr.Zero, , , PM_REMOVE))
{
AccurateTimer.TranslateMessage(ref msg);
AccurateTimer.DispatchMessage(ref msg);
}
AccurateTimer.QueryPerformanceCounter(ref t_i8EndTime);
//*1000000 微妙 1000毫秒 1秒=1000毫秒=1000000微妙
//等待时计算,乘于1000是毫秒,乘于1000000则是微妙
_wait_count2= ((double)(t_i8EndTime - t_i8StartTime) / (double)t_i8Frequency) * ;
} while (t_r8PassedMSec <=_wait_count);
}
}
}

  于是修改程序,根据码率计算出平均每个packet发送使用的微妙数:

//100毫秒内需要发送的packet数量,4000000为发送的码率,TS_OVER_IP_SIZE为固定的常量188

          double _packet_count =  / ) / (TS_OVER_IP_SIZE * );

          //发送间隔计算,每个包发送的毫秒数乘1000即是微秒

          int _duration = (int)(( / _packet_count)*);

编译程序,测试通过。不过要说C#本身的托管机制,代码执行效率自然比不上VC,所以实际到达设备的码率还是有一定误差的,但对我来说是不影响业务的使用。

C# 广播TS流精确计时发送的更多相关文章

  1. 使用VLC发送TS流与播放TS流

    使用VLC发送TS流与播放TS流 一.如何使用VLC发送TS流 1.添加一个文件至VLC 2.选择串流,继续 3.选择UDP,点击添加 4.输入地址及端口 5.选择h.264+mp3(TS) 6.ne ...

  2. TS流格式(转)

    一 从TS流开始 数字电视机顶盒接收到的是一段段的码流,我们称之为TS(Transport Stream,传输流),每个TS流都携带一些信息,如Video.Audio以及我们需要学习的PAT.PMT等 ...

  3. TS流PAT/PMT详解

    一 从TS流开始 从MPEG-2到DVB,看着看着突然就出现了一大堆表格,什么PAT.PMT.CAT……如此多的表该怎样深入了解呢? 我们知道,数字电视机顶盒接收到的是一段段的码流,我们称之为TS(T ...

  4. TS流解析 二 *****

    1.TS格式介绍 TS:全称为MPEG2-TS.TS即"Transport Stream"的缩写.它是分包发送的,每一个包长为188字节(还有192和204个字节的包).包的结构为 ...

  5. TS流解析 一

    一 从TS流开始 数字电视机顶盒接收到的是一段段的码流,我们称之为TS(Transport Stream,传输流),每个TS流都携带一些信息,如Video.Audio以及我们需要学习的PAT.PMT等 ...

  6. 从TS流到PAT和PMT

    转自:https://blog.csdn.net/rongdeguoqian/article/details/18214627 一 从TS流开始 最近开始学习数字电视机顶盒的开发,从MPEG-2到DV ...

  7. 自己动手写RTP服务器——用RTP协议传输TS流

    上一篇文章我们介绍了关于RTP协议的知识,那么我们现在就自己写一个简单的传输TS流媒体的RTP服务器吧. 预备知识 关于TS流的格式:TS流封装的具体格式请参考文档ISO/IEC 13818-1.这里 ...

  8. TS流文件

    简单介绍编辑 随着从HDTV录制的高清节目在网上的流传,烧友们对TS这个名词大概已经不陌生了.但随之而来就是怎样播放.怎样加入字幕等等的一系列问题.本文将重点介绍一下这方面的应用操作. 先来简要介绍一 ...

  9. 使用vlc实现视频TS流的推送

    鉴于Mpeg TS流播放的需求,使用 VLC作为Server来实现输出Mpeg TS    本文仅涉及如何使用VLC的Command来实现作为视频流Server通常可以使用下述四种方式来推送Mpeg ...

随机推荐

  1. C/C++:Unions 联合

    原文:http://msdn.microsoft.com/en-us/library/5dxy4b7b(v=vs.80).aspx 联合是用户定义的数据或类类型,在任何时间里,它只包含成员列表中的一个 ...

  2. macbook安装mysql

    一.官网下载dmg文件 二.双击安装dmg文件,一路next: 三.

  3. [{},{}]怎么转换成json

    例如:有这样的字符串[{"CityId":18,"CityName":"西安","ProvinceId":27,&quo ...

  4. [转]JS基础之undefined与null的区别

    在JavaScript开发中,被人问到:null与undefined到底有啥区别? 一时间不好回答,特别是undefined,因为这涉及到undefined的实现原理.于是,细想之后,写下本文,请各位 ...

  5. linux管理员切换与管理员密码第一次设置

    在终端输入su - root回车来切回到超级管理员,Ubuntu的默认超级管理员root密码是随机的,即每次开机都有一个新的root密码.我们可以在终端输入命令 sudo passwd,然后输入当前用 ...

  6. Python学习笔记捌——面向对象高级编程

    __slots__特殊变量的使用: 由于Python是动态语言,允许先编写类,然后在创建实例的时候添加属性或者方法:而__slots__特殊变量就是,限制往类里添加属性的: 在创建类的时候,使用__s ...

  7. Java中的日期处理类

    在Java中可以使用Date类和Calendar类来处理日期 但是Date类很多方法都过时了,推荐使用Canlendar类来处理日期,并对日期的格式化做了介绍.下面的部分将会逐一介绍 Date类 Ja ...

  8. [LA] 3644 - X-Plosives [并查集]

    A secret service developed a new kind of explosive that attain its volatile property only when a spe ...

  9. [TYVJ] P1001 第K极值

    第K极值   背景 Background 成成第一次模拟赛 第一道    描述 Description 给定一个长度为N(0<n<=10000)的序列,保证每一个序列中的数字a[i]是小于 ...

  10. Blogger支持Mobile行动版网页 - Blog透视镜

    目前几乎人人都使用行动装置像是Pad,智能型手机等,而Blogger也针对此类的使用者,推出支持Mobile行动版网页,提供简单清爽的页面,方便在小屏幕上的阅读,在设定上也相当的简单,同时还可以在计算 ...