修正wme输出的ASF流数据
前言
Windows Media Encoder是Microsoft Media Serial中的编码、转换工具,其支持将不同的文件转换成wmv/a格式,同时他也支持直接通过硬件设备(如声卡、摄像头等)采集数据,输出wmv/a格式。在输出方面wme支持直接存入文件,推送到wms(Microsoft Media Service),或推送到本地端口功能。然而推送到本地端口的数据并不完全符合asf 规范。
问题提出
在ASF Specfication中定义ASF文件的package的大小是固定的,这就导致有一部分(实际上是大部分)package达不到package的标准尺寸,因此需要一些填充字节来增长package的大小,使其符合header object中定义的package size。 我们知道,在wme的向本地推送数据时,实际上其数据包采用的是wms Http Streaming protocol,为了减少网络占用,wme推送http streaming数据时并没有推送这些填充字节,因为如果我们自己编写程序将http streaming数据转存到文件时,就必须对这些数据进行修正,这正在本文所关注的问题。
方案
首先,我们需要分析asf文件的头数据,找出其package的大小,然后,逐个分析每个package,如果其大小小于头中设定的大小,就需要进行修正。
对数据进行修复,就必须理解asf specification中的相关说明,根据5.2ASF Data package definition一节可知,数据包的组成如下:
我们所要做的就是根据Error Correction Data和Payload Parsing Information填充Padding Data,并修改data package中相应的数据(主要是Padding Length和Package Length字段)。实际上,Erro Corection Data都是存在的。
根据asf specification可知:
Error Correction Data
Payload parsing information
首先,我们要根据Error Correction Data的第一个字节(Error Correction Data Flags)了解Error Correction Data是否存在,以及其长度。检查Flags第8位是否为1(flags & 0x80 = 0x80),即可确定是否存在;如果存在,其低4位保存了Error Correcton Data Length(flags & 0x0f)。
然后跳过Error Correction Data,开始分析Payload parsing information。逐个分析Packet Length、Sequence、Padding Length的类型和大小。通常情况下,sequence是不存在的,其Length type flags中的值为00,Packet Length在某些情况下存在。分析方法如下:
Packet Length Type:flags & 0x60 >> 5
Sequence Type:flags & 0x06 >> 1
Padding Length Type: flags & 0x18 >>3
Type定义如下:
虽然这个图是针对Sequence的,但这个定义对三个字段的含义是相同。
经过以上分析,即可确定Packet Length字段、Padding Length字段是否存在,其类型是什么(BYTE、WORD、DWORD?),对应的修改Packet Length字段为asf header中定义的长度,然后修改Padding Length为asf header中的长度-本package的长度,在package后边添加填充字节即可。
示例代码(C#)
if (data.Length < AsfHeader.MaxPacketSize) //需要修正
{
int iPaddingOffset = 0;
int iPaddingLength = 0;
int iParserStart = 0;
//Error Correction
if ((data[0] & 0x80) == 0x80) //Error Correction 存在
{
iPaddingOffset += (data[0] & 0x0f) + 1/*first byte.error correction flags*/;
iParserStart = iPaddingOffset;
}
int c;
//取得Packet Length type
c = (data[iParserStart] & 0x60) >> 5;
switch (c)
{
case 0: // does not exist
break;
case 1: // byte
iPaddingOffset += 1;
//fix length
break;
case 2: //word
iPaddingOffset += 2;
//fix length
Array.Copy(BitConverter.GetBytes((ushort)mHeader.AsfHeader.MaxPacketSize), 0,data,iPaddingOffset,2);
break;
case 3: //dword
iPaddingOffset += 4;
//fix length
Array.Copy(BitConverter.GetBytes(mHeader.AsfHeader.MaxPacketSize), 0, data, iPaddingOffset -2, 4);
break;
}
//取得Sequence type
c = (data[iParserStart] & 0x06) >> 1;
switch (c)
{
case 0: // does not exist
break;
case 1: // byte
iPaddingOffset += 1;
break;
case 2: //word
iPaddingOffset += 2;
break;
case 3: //dword
iPaddingOffset += 4;
break;
}
//取得Padding Length type
c = (data[iParserStart] & 0x18) >> 3;
switch (c)
{
case 0: // does not exist
break;
case 1: // byte
iPaddingLength = 1;
break;
case 2: //word
iPaddingLength = 2;
break;
case 3: //dword
iPaddingLength = 4;
break;
}
int iPaddings = (int)(AsfHeader.MaxPacketSize - data.Length);
iPaddingOffset += 2;//skip payload parser information
switch (iPaddingLength)
{
case 0:
break;
case 1:
data[iPaddingOffset] = (byte)iPaddings;
break;
case 2:
Array.Copy(BitConverter.GetBytes((ushort)iPaddings), 0, data, iPaddingOffset, iPaddingLength);
break;
case 3:
Array.Copy(BitConverter.GetBytes((uint)iPaddings), 0, data, iPaddingOffset, iPaddingLength);
break;
}
chunk.Data = new byte[AsfHeader.MaxPacketSize];
//chunk.Data.Initialize();
Array.Copy(data, chunk.Data, data.Length);
chunk.Length = (ushort)chunk.Data.Length;
}
else
{
chunk.Data = data;
}
参考资料
ASF Specification
转载于:https://www.cnblogs.com/Ankh/archive/2007/08/09/849019.html
修正wme输出的ASF流数据相关推荐
- 输入H.264流,输出封装格式流
//H264ToContainer_Win32.h extern "C" {//@param format_name 输出流的格式名//@param r_frame_rate 输入 ...
- 大数据-07-Spark之流数据
摘自 http://dblab.xmu.edu.cn/blog/1084-2/ 简介 DStream是Spark Streaming的编程模型,DStream的操作包括输入.转换和输出. Spark ...
- 基于matplotlib.animation和python的流数据动态监控原型
流数据动态监控原型的内容概述 开发环境:Python3.6 代码行数:不到40行代码 代码风格:详细注解 代码特点:一定能跑起来 附加资料:带详细注释的九个animation实例 Decay The ...
- 11 编程指南_流数据
Flink 的流数据 API 编程指南 Flink 的流数据处理程序是常规的程序 ,通过再流数据上,实现了各种转换 (比如 过滤, 更新中间状态, 定义窗口, 聚合).流数据可以来之多种数据源 (比如 ...
- 通过ffmpeg实时读取宇视摄像头的高清帧流数据,并保存4张图片进行4合一照片的生成。
通过ffmpeg实时读取宇视摄像头的高清帧流数据,并保存4张图片进行4合一照片的生成. FFmpeg视频解码过程 通常来说,FFmpeg的视频解码过程有以下几个步骤: 注册所支持的所有的文件(容器)格 ...
- 实时行情难处理?睿凝资本选择DolphinDB解决流数据难题
睿凝资本 CEO 王睿.CTO Jack 最初了解到DolphinDB是知乎的一条测评贴.作为KDB+的多年老用户,我对于这家对标KDB+.测评结果优秀的国产时序数据库非常感兴趣.读帖不久,前公司恰好 ...
- 黑马程序员_JAVA之IO流的(转换流,数据输入输出流等)
------- android培训.java培训.期待与您交流!---------- IO流: 笔记内容:转换流,字节输入输出流,数据输入输出流,内存操作流,随机访问流 打印流,对象序列化流,Prop ...
- 解决 HttpServletRequest 流数据不可重复读
背景介绍 甲方客户的生产系统,有安全风险预警和安全事件快速溯源要求,需要做一套日志管理规范. 要求我们接入的系统,要对用户登录.注册.密码修改等重要场景,严格按照提供的格式,输出相应的日志. 后续通过 ...
- 树莓派4B摄像头推出流数据
树莓派4B摄像头推出流数据 树莓派摄像头调试 排线连接 摄像头权限激活 测试摄像头功能 树莓派原生推http流 使用vlc打开网络串流 树莓派原生推rtsp流 使用vlc打开网络串流 启动异常处理 f ...
最新文章
- 主席树 | 莫队 ---- Codeforces Round #716 (Div. 2) D. Cut and Stick [主席树or莫队优化] 区间众数问题(静态)
- 找最大公约数和最小公倍数(c语言实现)
- bitnami-redmine Apache服务启动不起来
- 了解JVM运行时的内存分配
- php实现注册登陆验证
- 红帽Linux7怎么修改网卡名称,新安装的Centos 7系统怎么将网卡名称改为eth0?
- OpenStack精华问答 | OpenStack的网络类型有哪些?
- Java中遭遇NaN
- appassembler-maven-plugin插件打包本地依赖的jar
- go1.5源代码安装
- Golang 中map与GC“纠缠不清”的关系
- 织梦后台登陆不上提示验证码不正确
- 手机uc7.2java版下载_UC浏览器 JAVA
- 双因素认证令牌_安全令牌:防止双因素令牌认证攻击
- 20220609 C++版的ends_with
- 给技术经理找了几款Docker开源镜像仓库,为什么经理选中了Sonatype Nexus(下)
- 网络安全 - 一名合格的Web安全工程师之成长路径
- vue 环信im 发送图片、接收图片
- CSS transform中的rotate设置旋转中心
- ad hoc java_Java并发编程--线程封闭(Ad-hoc封闭 栈封闭 ThreadLocal)
热门文章
- 基于pygame的射击小游戏制作(五)绘制开始按钮
- numpy(4)-计算数据异常值
- 【数学基础】运筹学:拉格朗日乘子法和KKT条件(上)
- 【算法】吴忠强:刷LeetCode的正确姿势!
- 【深度学习】李沐《动手学深度学习》的PyTorch实现已完成
- Ubuntu18.04+CUDA10.2 深度学习开发环境配置指南
- 【实战】用机器学习来提升你的用户增长:(三、预测客户的终生价值)
- 【实战】使用pyecharts绘制词云图-淘宝商品评论展示
- AAAI2021论文合集汇总!(持续更新)
- 网易云信荣获2021年度智慧教育典型案例奖项,并入选《智慧教育发展及产业图谱研究报告》...