C# 广播TS流精确计时发送
广播传输相关的项目,需求是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流精确计时发送的更多相关文章
- 使用VLC发送TS流与播放TS流
使用VLC发送TS流与播放TS流 一.如何使用VLC发送TS流 1.添加一个文件至VLC 2.选择串流,继续 3.选择UDP,点击添加 4.输入地址及端口 5.选择h.264+mp3(TS) 6.ne ...
- TS流格式(转)
一 从TS流开始 数字电视机顶盒接收到的是一段段的码流,我们称之为TS(Transport Stream,传输流),每个TS流都携带一些信息,如Video.Audio以及我们需要学习的PAT.PMT等 ...
- TS流PAT/PMT详解
一 从TS流开始 从MPEG-2到DVB,看着看着突然就出现了一大堆表格,什么PAT.PMT.CAT……如此多的表该怎样深入了解呢? 我们知道,数字电视机顶盒接收到的是一段段的码流,我们称之为TS(T ...
- TS流解析 二 *****
1.TS格式介绍 TS:全称为MPEG2-TS.TS即"Transport Stream"的缩写.它是分包发送的,每一个包长为188字节(还有192和204个字节的包).包的结构为 ...
- TS流解析 一
一 从TS流开始 数字电视机顶盒接收到的是一段段的码流,我们称之为TS(Transport Stream,传输流),每个TS流都携带一些信息,如Video.Audio以及我们需要学习的PAT.PMT等 ...
- 从TS流到PAT和PMT
转自:https://blog.csdn.net/rongdeguoqian/article/details/18214627 一 从TS流开始 最近开始学习数字电视机顶盒的开发,从MPEG-2到DV ...
- 自己动手写RTP服务器——用RTP协议传输TS流
上一篇文章我们介绍了关于RTP协议的知识,那么我们现在就自己写一个简单的传输TS流媒体的RTP服务器吧. 预备知识 关于TS流的格式:TS流封装的具体格式请参考文档ISO/IEC 13818-1.这里 ...
- TS流文件
简单介绍编辑 随着从HDTV录制的高清节目在网上的流传,烧友们对TS这个名词大概已经不陌生了.但随之而来就是怎样播放.怎样加入字幕等等的一系列问题.本文将重点介绍一下这方面的应用操作. 先来简要介绍一 ...
- 使用vlc实现视频TS流的推送
鉴于Mpeg TS流播放的需求,使用 VLC作为Server来实现输出Mpeg TS 本文仅涉及如何使用VLC的Command来实现作为视频流Server通常可以使用下述四种方式来推送Mpeg ...
随机推荐
- C#获取客户端相关信息
1.获取Uri参数 2.获取客户端操作系统.浏览器信息 3.获取客户端分辨率 4.C#判断用户是手机访问还是PC访问
- set用法总结
set集合用于存放不重复的元素 template <class Key, class Compare = less<Key>, class Alloc = alloc> cla ...
- python 杂记
class TestA(object): def __init__(self): print("A is initing"); def foo(self): print(" ...
- deb包处理
1.卸载 dqpg -l 查看信息 dqpg -r ****** 卸载 2.安装 dqpg -i ...............deb
- win32下用VC扩展PHP全过程
闲着无聊,打算开发一些PHP组件来玩玩,由于在家没有工作环境,遂打算在win32(我的环境是vista)用VC开发DLL模块,费话不 多说了,进入正题: 一.已经在机器上安装PHP环境的就略过,否则先 ...
- 图形用户界面入门:EasyGui - 零基础入门学习Python035
图形用户界面入门:EasyGui 让编程改变世界 Change the world by program 今天我们来谈谈图形用户界面编程,也就是我们常说的GUI(Graphical User Inte ...
- Memory Region
A program's memory usage typically includes four different regions: Code -- The region where the pro ...
- 痛并快乐的造轮子之旅:awk访问数据库之旅
俺是一枚悲催的数据统计程序员,从先辈的手里接收了这样的代码: #! /bin/sh alias statdb="mysql -h 192.168.1.1 -u stat -paaa stat ...
- bzoj1750 [Usaco2005 qua]Apple Catching
Description It is a little known fact that cows love apples. Farmer John has two apple trees (which ...
- IT人员应该怎么跳槽
中国的程序员只有两个状态,刚跳槽和准备跳槽. 中国IT行业的快速发展对IT从业人员的需求不断扩大,记得08年刚毕业的时候,在帝都找一个3k的工作都让我特别满足,现在仅能写出”hello world ...