﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-elva-随笔分类-MPEG</title><link>http://www.cppblog.com/elva/category/8814.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 31 May 2013 07:29:05 GMT</lastBuildDate><pubDate>Fri, 31 May 2013 07:29:05 GMT</pubDate><ttl>60</ttl><item><title>TS OVER IP的多画面合成</title><link>http://www.cppblog.com/elva/archive/2013/05/31/200717.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 31 May 2013 06:52:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2013/05/31/200717.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/200717.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2013/05/31/200717.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/200717.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/200717.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 许久没写博客了，似乎现在也很难静下心来去写东西，倒也不是心情浮躁，以前的写blog用来收集网上文章，记录自己的一些经验，后来假设了自己的文件服务器，用wiz做了笔记的server,收集什么东西用wiz就完成了，自己记录点经验也不在乎格式，也都没拿出来分享。这次辛辛苦苦做完一个项目，其中遇到一些问题，没有网络上的资料自己是很难解决的。因此整理点东西，与大家分享，也不能总受之与人吧。<br /><br /><div>&nbsp;&nbsp;&nbsp; 终于做完了多画面合成的项目，颇有心得，其间也遇到一些问题，没有网络上的资料自己是很难解决的，但也不是所有东西都能在网上找到办法，使用ffmpeg遇到太多问题，许多只能通过阅读源码解决。如今做完了，拿出来与众分享。<br />画面合成器是将多个承载于UDP的TS流（MPTS，SPTS）解码，将解码后图像缩放成小画面，再将各个源合并成2x2,3x3,4x4等方式，实现电视墙的效果。<br />项目的需求是这样的：<br />1.UDP输入UDP输出<br />2.提供源切换的接口，客户会再某个时刻换掉某个源<br />3.良好的异常处理，某个UDP源断流或恢复不影响现有节目。这不是客户的要求，但有过大型项目经验的人知道，这是一定要考虑的<br />从实现层面来讲，需要以下技术点：<br />1.UDP单播组播接收<br />2.TS封装的H264与MPEG2视频解码为YUV<br />3.YUV缩放<br />4.YUV画面拼接<br />5.合成后的YUV压缩为H264<br />6.压缩后的视频打包TS<br />7.打包后的TS通过UDP发送<br />8.发送时需要进行流控，保证VLC可正常播放。<br />这些技术点不算难，真正的难点在于统筹运作，N个源各自的解码后画面输出速度不同，虽然我们要求各源帧率相同。各解码线程画面输出虽整体相同，但肯定会忽高忽低。如果每个源都正常的话，我们可以等待每个源都有画面的时候才进行合成。但是我们需要考虑源断流与恢复，就不能一直等待某个源。其二，为了支持源切换，我们应该涉及好运作模式，实现无缝切换，但这些只是我特定 业务的需要，接下来只讲与ffmpeg相关技术。<br />先讲上面提到的8个技术点，UDP收发就不用说了，值得一提的是接收需要使用异步模式，这个在后面会提到。除了YUV画面拼接，其他都可以用ffmpeg sdk实现。因此主要讨论使用ffmpeg进行解码编码，这种技术文章其实很多，但他们一般只有简单的方案，对于这些比较常见的东西，我们也不做讨论，只讨论几个重点，而又缺乏资料的问题，主要有：<br />1.对解码及编码自定义io回掉。UDP接收及发送不通过ffmpeg实现。对于UDP源来说，ffmpeg对MPTS支持不好。对于输出UDP来说，ffmpeg没有流控<br /><br />有时我们希望ffmpeg的api打开的不是文件或某个协议的URL，直接传递数据缓冲给他，ffmpeg不支持传递数据指针给他，要求他编码或解码，这在ffmpeg api中的实现方式是IO回掉函数。他在需要的时候来调用你的函数来读取或写入。以解码为例，下面为示例代码：<br />AVIOContext *pb = avio_alloc_context(pbuf+1316, AVIO_BUF_SIZE-1316, 0, this, ReadDataCb, NULL, NULL);<br />if (av_probe_input_buffer(pb, &amp;pinFmt, "", NULL, 0, MAX_PROBE_SIZE) &lt; 0)<br />{<br />//error...<br />}<br />AVFormatContext *pFmtCt = avformat_alloc_context();<br />pFmtCt-&gt;pb = pb;<br />if (avformat_open_input(&amp;pFmtCt, "", pinFmt, NULL) &lt; 0)<br />{<br />//error...<br />}<br />读取回掉原型如下：<br />static int ReadDataCb(void *opaque, uint8_t *buf, int buf_size);<br />实现理念一般应该是除非想要停止解码，返回-1，否则返回数据长度。保证他读到数据<br /><br />不知道是出于内存对齐还是什么原因，<br />uint8_t *pbuf = (uint8_t *)calloc(AVIO_BUF_SIZE,1);<br />pb = avio_alloc_context(pbuf+1316, AVIO_BUF_SIZE-1316, 0, this, ReadDataCb, NULL, NULL);<br />的时候第一个参数直接传pbuf会崩溃，所以+1316<br />而若使用av_mallocz，虽可以直接传pbuf,却在av_free的时候崩溃，没有找到原因。<br /><br />2.由于需要实现切换，所以需要将某个源完全销毁，不产生内存泄露，不要小看这个问题，网上的很多代码是不对的。<br /><br />销毁 AVFormatContext<br />正确销毁方式：<br />/* close decoder for each stream */<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;for (int i = 0; i &lt; pFmtCt-&gt;nb_streams; i++)<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;if (pFmtCt-&gt;streams[i]-&gt;codec-&gt;codec_id != AV_CODEC_ID_NONE)<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;{<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;THREAD_MUTEX_LOCK(&amp;g_mutex_avcodec_oc);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;avcodec_close(pFmtCt-&gt;streams[i]-&gt;codec);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;THREAD_MUTEX_UNLOCK(&amp;g_mutex_avcodec_oc);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;}<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;avformat_close_input(&amp;pFmtCt);<br />&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;<br />销毁 AVIOContext<br />//不可使用avio_close<br />&nbsp;&nbsp; &nbsp;av_free(pb-&gt;buffer);<br />&nbsp;&nbsp; &nbsp;av_free(pb);<br /><br />销毁 AVFrame<br />AVFrame *pframe = avcodec_alloc_frame();<br />avcodec_free_frame(&amp;pframe);&nbsp;&nbsp; &nbsp;<br /><br /><br />3.多线程使用ffmpeg sdk问题<br />avcodec_open/avcodec_close不是线程安全的，必须进行全局加锁保护，或者其他同步方式。除了这两个函数外，由于av_find_stream_info内部调用了avcodec_open，也需要加锁。但av_find_stream_info有可能执行时间比较长，如果没特别的必要，可以不使用此函数。对于解码来说，有下面两个函数：<br />av_probe_input_buffer<br />avformat_open_input<br />大部分情况下已经可以正常解码了。<br /><br />关于压缩<br />ffmpeg压缩H264 TS时CBR并不好用，设置了mux_rate会导致TS封装出错。老老实实用VBR，不设置mux_rate<br />进行H264压缩时一个选项一定要设置的：<br />preset<br />在压缩效率和运算时间中平衡的预设值，可用选项：<br />ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow and placebo</div><br /><img src ="http://www.cppblog.com/elva/aggbug/200717.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2013-05-31 14:52 <a href="http://www.cppblog.com/elva/archive/2013/05/31/200717.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PAFF 和MBAFF  </title><link>http://www.cppblog.com/elva/archive/2012/04/18/171874.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 18 Apr 2012 07:59:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2012/04/18/171874.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/171874.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2012/04/18/171874.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/171874.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/171874.html</trackback:ping><description><![CDATA[<p>PAFF 和MBAFF：当对隔行扫描图像进行编码时，每帧包括两个场，由于两个场之间存在较大的扫描间隔，这样，对运动图像来说，帧中相邻两行之间的空间相关性相对于逐行扫描时就会减小，因此这时对两个场分别进行编码会更节省码流。对帧来说，存在三种可选的编码方式：将两场合并作为一帧进行编码(frame 方式)或将两场分别编码(field 方式)或将两场合并起来作为一帧，但不同的是将帧中垂直相邻的两个宏块合并为宏块对进行编码；前两种称为PAFF 编码，对运动区域进行编码时field 方式有效，对非运区域编码时，由于相邻两行有较大的相关性，因而frame 方式会更有效。当图像同时存在运动区域和非运动区域时，在MB 层次上，对运动区域采取field 方式，对非运动区域采取frame 方式会更加有效，这种方式就称为MBAFF，预测的单位是宏块对。 <br />&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在隔行扫描帧中，当有移动的对象或摄像机移动时，与逐行相比，两个相邻行倾向减少统计的相关性，这种情况应比每场分别压缩更为有效。为了达到高效率，H.264/AVC在编码帧时，有以下可选方案：</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 结合两场成一个完整帧，作为帧编码，称为帧模式。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 两场分别编码，称为场模式。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 结合两场成一个完整帧，作为帧压缩。在编码时，划分垂直相邻的两个宏块对成两个场宏块对或帧宏块，再进行编码。</p>
<p>&nbsp;&nbsp;&nbsp; 每帧图像可自适应选择3种模式之一进行编码。在前两种之间进行选择称为图像自适应帧/场编码（PAFF），当一帧作为两场编码时，每场划分为宏块，编码方式与帧编码方式很相似，主要有下面的例外：</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 运动补偿用参考场，而不是参考帧。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 变换系数的&#8220;之字型&#8221;扫描方式不同。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 宏块水平边沿去块滤波器的强度不选用&#8220;强&#8221;，因为场行在空间上是两倍帧行的距离。</p>
<p>&nbsp;&nbsp;&nbsp; 在研制H.264/AVC标准时，据报道，采用ITU-601分辨率，PAFF编码技术与帧编码相比可减少码率16%到20%。</p>
<p>&nbsp;&nbsp;&nbsp; 如果图像由运动区和非运动区混合组成，非运动区用帧模式、运动区用场模式是最有效的编码方法。因此每个垂直宏块对（16&#215;32）可独立选择编码（帧/场）模式。这种编码选择称为宏块自适应帧/场编码（MBAFF）。对于帧模式宏块对，每个宏块包含帧行，对于场模式宏块对，顶部宏块包含顶场行，底部宏块包含底场行。</p>
<p>&nbsp;&nbsp;&nbsp; 处理场宏块对的每个宏块与帧PAFF模式相似，然而，因为在MBAFF帧中发生场/帧宏块对混合，需要修改用作下列用途的方法：</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 之字型扫描。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 运动矢量预测。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 帧内预测模式的预测。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 帧内预测帧采样精度。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 去块效应滤波器。</p>
<p>&nbsp;&nbsp;&nbsp; &#9679; 上下文模型的熵编码。</p>
<p>&nbsp;&nbsp;&nbsp; 主要思想是尽可能保留多的空间一致性，MBAFF帧的空间相邻的规范相当复杂，下面讲到的空间相邻都是指非MBAFF帧。</p>
<p>&nbsp;&nbsp;&nbsp; MBAFF 和PAFF的另一个重要区别是：使用MBAFF方法，一个场不能使用同一帧的另一个场中的宏块作为运动补偿参考。这样，有时PAFF比MBAFF编码更有效，特别是在快速全局运动、变换场景、图像刷新等情况下。</p>
<p>&nbsp;&nbsp;&nbsp; 在开发MBAFF标准期间，据报道，采用ITU-601分辨率，MBAFF编码技术比PAFF相比可减少码率14%到16%。</p><img src ="http://www.cppblog.com/elva/aggbug/171874.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2012-04-18 15:59 <a href="http://www.cppblog.com/elva/archive/2012/04/18/171874.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>图像、帧、片、NALU</title><link>http://www.cppblog.com/elva/archive/2011/02/24/140579.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Thu, 24 Feb 2011 04:10:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2011/02/24/140579.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/140579.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2011/02/24/140579.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/140579.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/140579.html</trackback:ping><description><![CDATA[<div>图像、帧、片、NALU 是学习 H.264 的人常常感到困惑的一些概念，我在这里对自己的理解做一些阐述，欢迎大家讨论：<br><br><br>H.264 是一次概念的革新，它打破常规，<strong>完全没有 I 帧、P帧、B 帧的概念，也没有 IDR 帧的概念</strong>。对于 H.264 中出现的一些概念从大到小排序依次是：<strong>序列、图像、片组、片、NALU、宏块、亚宏块、块、像素</strong>。这里有几点值得说明：<br>（1）、在 H.264 协议中<strong>图像是个集合概念</strong>，顶<strong>场、底场、帧都可以称为图像</strong>（本文图像概念时都是集合概念）。因此我们可以知道，对于 H.264 协议来说，我们平常所熟悉的那些称呼，例如：<strong>I 帧、P 帧、B 帧等等，实际上都是我们把图像这个概念具体化和细小化了</strong>。我们<strong>在 H.264 里提到的&#8220;帧&#8221;通常就是指不分场的图像；<br></strong>（2）、如果<strong>不采用 FMO（灵活宏块排序）</strong> 机制，则<strong>一幅图像只有一个片组</strong>；<br>（3）、如果<strong>不使用多个片，则一个片组只有一个片</strong>；<br>（4）、如果<strong>不采用</strong> DP（<strong>数据分割</strong>）机制，则<strong>一个片就是一个 NALU</strong>，<strong>一个 NALU 也就是一个片</strong>。</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 否则，<strong>一个片由 三个 NALU 组成</strong>（即标准&#8220;表7-1&#8221;中 nal_unit_type 值为 2、3、4 的<strong>三个</strong> NALU 属于 一个片）； &nbsp;</div>
<div><strong>&nbsp;&nbsp; 2 编码条带数据分割块A&nbsp; slice_data_partition_a_layer_rbsp( )<br><br>&nbsp;&nbsp; 3 编码条带数据分割块B slice_data_partition_b_layer_rbsp( )<br><br>&nbsp;&nbsp; 4 编码条带数据分割块C slice_data_partition_c_layer_rbsp( )</strong></div>
<div>&nbsp;</div>
<div>（5）、以上所述的<strong>片和 NALU 的大小关系并不是抽象概念上的从属关系</strong>。从概念的<strong>从属关系</strong>上来看，<strong>NALU</strong>其实<strong>又是片的一个集合概念</strong>，例如：标准&#8220;表7-1&#8221;中 nal_unit_type 值为 5 的 NALU 包括 <strong>I 片或者 SI 片。<br></strong><br>&nbsp;&nbsp;&nbsp; <strong>一幅图像根据组成它的片类型来分</strong>，可以分为标准<strong>&#8220;表7-5&#8221;中的 8 种类型</strong>。我们平常应用中所最常见到的<strong>其实是这些类型</strong>的特例。例如：<strong>我们平常所谓的&#8220;I 帧&#8221;和&#8220;IDR 帧&#8221;，</strong>其实是 <strong>primary_pic_type 值为 0 的图像</strong>，我们平常所谓的&#8220;<strong>P帧&#8221;其实是 primary_pic_type 值为 1 的图像的特例</strong>，<strong>我们平常所谓的&#8220;B帧&#8221;其实是 primary_pic_type 值为 2 的图像的特例。<br></strong><br>&nbsp;&nbsp;&nbsp; <strong>一幅图像根据概念来分可以分为两种</strong>：<strong>IDR 图像和非 IDR 图像</strong>。一幅图像是否是 <strong>IDR 图像</strong>是由组成该<strong>图像的 NALU 决定的</strong>，如果组<strong>成该图像的 NALU 为标准&#8220;表7-1&#8221;中 nal_unit_type 值为 5 的 NALU</strong>，则该<strong>图像为 IDR 图像</strong>，否则为<strong>非 IDR 图像</strong>。这里也有几点值得说明：<br></div>
<div><strong>（1）、nal_unit_type 值为 5 的 NALU 只会出现在 IDR 图像中，而 IDR 图像中的所有 NALU 都是nal_unit_type 值为 5 的 NALU；<br></strong>（2）、我们以组成一<strong>幅图像的片的类型</strong>来区分该<strong>图像是否是 IDR 图像是错误</strong>的。</div>
<div>例如：<strong>一幅图像中的所有片都是 I 片并不代表这幅图像就是 IDR 图像</strong>。因为 I 片也可以从属于 nal_unit_type 值为 1 的 NALU <span style="COLOR: red">也即非IDR图像有可能全部包含I片</span>。只不过我们平常最常见到的形式是：所有片都是 I 片的图像就是 IDR 图像。其实这个时候 <strong>IDR 图像</strong>的概念也被我们具体化和细小化了。 <span style="COLOR: red">但IDR图像必定全部包含I片或SI片，不过<strong>只有用NALU的类型才能判断是不是IDR图像</strong></span><br><br>一幅图像由 <strong>1～N 个片组</strong>组成，而<strong>每一个片组</strong>又由一个或<strong>若干个片</strong>组成 <span style="COLOR: red">一个片由一个NALU或三个NALU（假如有数据分割）组成</span>。<strong>图像解码过程中总是按照片进行解码</strong>，然后按照片组将解码宏块重组成图像。从这种意义上讲，<strong>片实际是最大的解码单元</strong>。</div>
<div>&nbsp;</div>
<div><strong>一个片又包含哪些类型的宏块呢？</strong></div>
<div><strong>标准&#8220;表7-10&#8221;做了最好的说明。</strong></div>
<div>&nbsp;</div>
<div><strong>一个 I 宏块又分为哪些类型呢？</strong></div>
<div><strong>标准&#8220;表7-11&#8221;做了最好的说明。</strong></div>
<div>&nbsp;</div>
<div><strong>一个 P 宏块又分为哪些类型呢？</strong></div>
<div><strong>标准&#8220;表7-13&#8221;做了最好的说明。</strong></div>
<div>&nbsp;</div>
<div><strong>一个 B 宏块又分为哪些类型呢？</strong></div>
<div><strong>标准&#8220;表7-14&#8221;做了最好的说明。</strong></div>
<div>&nbsp;</div>
<div><strong>一个 P 宏块的亚宏块又分为哪些类型呢？</strong></div>
<div><strong>标准&#8220;表7-17&#8221;做了最好的说明。</strong></div>
<div>&nbsp;</div>
<div><strong>一个 B 宏块的亚宏块又分为哪些类型呢？</strong></div>
<div><strong>标准&#8220;表7-18&#8221;做了最好的说明。</strong></div>
<img src ="http://www.cppblog.com/elva/aggbug/140579.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2011-02-24 12:10 <a href="http://www.cppblog.com/elva/archive/2011/02/24/140579.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于MPEG2中的图像序列和图像组头GOP </title><link>http://www.cppblog.com/elva/archive/2011/02/23/140515.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 23 Feb 2011 06:26:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2011/02/23/140515.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/140515.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2011/02/23/140515.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/140515.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/140515.html</trackback:ping><description><![CDATA[<p><strong>图像序列</strong> </p>
<p>图像序列是由图像组构成的，是<strong>随机存取段落</strong>。 </p>
<p><strong>sequence_header_code</strong> &#8211; The sequence_header_code is the bit string &#8216;000001B3&#8217; in hexadecimal </p>
<p><strong>sequence_end_code</strong> &#8211; The sequence_end_code is the bit string &#8216;000001B7&#8217; in hexadecimal. </p>
<p>MPEG-2为了实现随机访问，在码流中会插入<strong>repeat_sequence_header</strong>,它可以插在I、P帧或GOP前面；假如是场编码，只能插在第一场前面。 </p>
<p><strong>图像组头</strong> </p>
<p>图像组（GOP）是为方便随机存取而加的，图像组是<strong>随机存取视频单位</strong>。一个GOP由一串IBP帧组成，起始为I帧。基准帧(I/P)的反复频率用<strong><font color=#ff0000>M</font></strong>表示，它描述为多少帧里出现一次I/P帧。GOP的长度是一个I帧到下一个I 帧的间隔，即多少帧里面出现一次I帧，一般用<strong><font color=#ff0000>N</font></strong>表示，这个长度是可变的，长GOP可以提供高的压缩比，但是会造成随机存取的延迟（必须等到下一个I帧）和误差的积累（P帧的误差传播）。一般是一秒内有两个I帧，用来作为随机存取的入口。在MPEG2中也没有规定GOP的结构，帧反复方式可以是IP，IB，IBP，IBBP，甚至全部是I帧。 </p>
<p>M=1 N=X：IPPP... </p>
<p>M=2 N=X：IBPBP... </p>
<p>M=3 N=X：IBBPBBP... </p>
<p>MPEG-2标准中的GOP语法结构如下： </p>
<p><a href="http://pkq4pa.bay.livefilestore.com/y1p1nWgBGrSyVaSBnMVwRQvB3vMLD9ZsPQqfveKu2xoIhumilG6qFElF48xDMq0kuYfMKWtNW1x7hPPnXw7-76BWhFeXFSTjFOC?PARTNER=WRITER"></a></p>
<p><strong>group_start_code</strong> &#8211; The group_start_code is the bit string &#8216;000001B8&#8217; in hexadecimal. </p>
<p><strong>closed_gop</strong> &#8211; This is a one-bit flag which indicates the nature of the predictions used in the first consecutive B-pictures (if any) immediately following the first coded I-frame following the group of picture header.closed_gop is set to &#8216;1&#8217; to indicate that these B-pictures have been encoded using only backward prediction or intracoding. </p>
<p><strong>broken_link</strong> &#8211; This is a one-bit flag which shall be set to &#8216;0&#8217; during encoding. It is set to &#8216;1&#8217; to indicate that the first<br>consecutive B-Pictures (if any) immediately following the first coded I-frame following the group of picture header may not be correctly decoded because the reference frame which is used for prediction is not available (because of the action of editing).A decoder may use this flag to avoid displaying frames that cannot be correctly decoded.</p>
<p><br></p>
http://lyj2682.spaces.live.com/blog/cns!177B1314D2038BE4!142.entry<br><br>
<img src ="http://www.cppblog.com/elva/aggbug/140515.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2011-02-23 14:26 <a href="http://www.cppblog.com/elva/archive/2011/02/23/140515.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>EasyICE使用教程</title><link>http://www.cppblog.com/elva/archive/2010/09/17/126855.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 17 Sep 2010 05:14:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/09/17/126855.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/126855.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/09/17/126855.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/126855.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/126855.html</trackback:ping><description><![CDATA[&nbsp;
<p align=center><span>EasyICE TS</span><span>流分析软件</span></p>
<p align=center><span>使用说明</span></p>
<p>&nbsp;</p>
<p><span>目录</span></p>
<p><span><a href="#_Toc272427029"><span><span>功能简介</span></span><span><span>... </span></span><span>2</span></a></span></p>
<p><span><a href="#_Toc272427030"><span><span>运行环境要求：</span></span><span><span>... </span></span><span>2</span></a></span></p>
<p><span><a href="#_Toc272427031"><span><span>详细介绍：</span></span><span><span>... </span></span><span>2</span></a></span></p>
<p><span><a href="#_Toc272427032"><span>A.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span><span>媒体播放：</span></span><span><span>... </span></span><span>3</span></a></span></p>
<p><span><a href="#_Toc272427033"><span>B.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span><span>媒体信息</span></span><span><span>... </span></span><span>4</span></a></span></p>
<p><span><a href="#_Toc272427034"><span>C.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>PSI/SI</span><span><span> </span></span><span>5</span></a></span></p>
<p><span><a href="#_Toc272427035"><span>D.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>PID</span><span><span>统计</span></span><span><span>... </span></span><span>6</span></a></span></p>
<p><span><a href="#_Toc272427036"><span>E.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span><span>图表</span></span><span><span>... </span></span><span>6</span></a></span></p>
<p><span><a href="#_Toc272427037"><span>1.</span><span><span>时间戳信息</span></span><span><span>... </span></span><span>7</span></a></span></p>
<p><span><a href="#_Toc272427038"><span>2.PCR</span><span><span>抖动</span></span><span><span>... </span></span><span>8</span></a></span></p>
<p><span><a href="#_Toc272427039"><span>3.GOP</span><span><span>列表</span></span><span><span>... </span></span><span>9</span></a></span></p>
<p><span><a href="#_Toc272427040"><span>4.GOP</span><span><span>抖动</span></span><span><span>... </span></span><span>10</span></a></span></p>
<p><span><a href="#_Toc272427041"><span>5.</span><span><span>码率抖动</span></span><span><span>... </span></span><span>11</span></a></span></p>
<p><span><a href="#_Toc272427042"><span>F.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span><span>数据包视图</span></span><span><span>... </span></span><span>12</span></a></span></p>
<p><span><a href="#_Toc272427043"><span>G.</span><span><span>&nbsp;&nbsp;&nbsp; </span></span><span><span>小工具</span></span><span><span>... </span></span><span>13</span></a></span></p>
<p><span><a href="#_Toc272427044"><span>1.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>PID</span><span><span>抽取</span></span><span><span>... </span></span><span>13</span></a></span></p>
<p><span><a href="#_Toc272427045"><span>2.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span><span>重设</span></span><span>PID</span><span><span>.. </span></span><span>13</span></a></span></p>
<p><span><a href="#_Toc272427046"><span>3.</span><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>204</span><span><span>转</span></span><span>188</span><span><span>. </span></span><span>14</span></a></span></p>
<p><span><a href="#_Toc272427047"><span><span>软件缺点</span></span><span><span>... </span></span><span>14</span></a></span></p>
<p><span><a href="#_Toc272427048"><span><span>其他说明</span></span><span><span>... </span></span><span>14</span></a></span></p>
<p><span><a href="#_Toc272427049"><span><span>问题报告</span></span><span><span>... </span></span><span>15</span></a></span></p>
<p><span><a href="#_Toc272427050"><span><span>后记</span></span><span><span>... </span></span><span>15</span></a></span></p>
<p>&nbsp;</p>
<span><br clear=all></span>
<p align=left>&nbsp;</p>
<p align=left>&nbsp;</p>
<h1><a name=_Toc272427029><span>功能简介</span></a></h1>
<p><span>本程序是一款</span><span>TS</span><span>文件静态分析工具，支持</span><span>188/204</span><span>、单路</span><span>/</span><span>多路节目</span><span> mpeg2/h.264</span><span>，分析模块齐全，支持特大文件，并具有一流的处理速度。其主要功能如下：</span></p>
<p><span><span>l&nbsp;</span></span><span>媒体播放</span></p>
<p><span><span>l&nbsp;</span></span><span>媒体详细信息</span></p>
<p><span><span>l&nbsp;</span></span><span>PID</span><span>统计</span></p>
<p><span><span>l&nbsp;</span></span><span>同步分析，</span><span>GOP</span><span>统计，码率变化分析</span></p>
<p><span><span>l&nbsp;</span></span><span>PSI/SI</span><span>解析</span></p>
<p><span><span>l&nbsp;</span></span><span>TS</span><span>包列表、十六进制显示，</span><span>TS</span><span>头，调整字段，</span><span>PES</span><span>首部解析</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1><a name=_Toc272427030><span>运行环境要求：</span></a></h1>
<p align=left><span>1.Windowns2000</span><span>以上操作系统</span></p>
<p align=left><span>2.IE6.0</span><span>以上</span></p>
<p align=left><span>3.</span><span>内存：</span><span>128M</span><span>以上</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h1><a name=_Toc272427031><span>详细介绍：</span></a></h1>
<p><span>选择打开一个</span><span>TS</span><span>文件：</span></p>
<p><span>通过菜单栏或工具栏打开，或将文件拖动到</span><span>EasyICE</span><span>，可以看到如下对话框</span></p>
<p>&nbsp;</p>
<p>&#160;</p>
<p><span>你可以在这里选择分析整个文件或部分数据</span></p>
<p>&nbsp;</p>
<h2><a name=_Toc272427032><span><span>A.<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>媒体播放：</span></a></h2>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/1.jpg" width=558 height=379></p>
<p>&nbsp;</p>
<p><span>当文件分析完毕，播放器窗口会被初始化，并处于暂停状态，单击播放按钮开始播放。</span></p>
<p><span>播控按钮：</span></p>
<p><span>依次为：播放、暂停、停止、降低播放速度、加大播放速度、逐帧播放</span></p>
<p><span>播放速度的调整分七个级别：</span></p>
<p><span>1/4</span><span>速、</span><span>1/3</span><span>速、</span><span>1/2</span><span>速、正常速度、</span><span>2</span><span>倍速、</span><span>3</span><span>倍速、四倍速</span></p>
<p><span>当前播放速度会在&#8220;质量&#8221;区显示</span></p>
<p><span>&#8220;节目&#8221;区列出了当前流中所含有的节目，单击即可播放选中节目，展开可以看到节目的三个</span><span>PID</span><span>：视频、音频、</span><span>PCR</span></p>
<p><span>&#8220;质量&#8221;区显示了当前播放媒体的简单信息，如播放速度等，但由于软件问题有些数据获取不到或存在问题，请以&#8220;媒体信息&#8221;栏检测结果为准。</span></p>
<p>&nbsp;</p>
<p><span>特别的，软件首先会查找流中的</span><span>PSI/SI</span><span>信息，如果存在，将按照</span><span>PSI/SI</span><span>信息解析，如果不存在，软件将自己尝试检测视音频</span><span>PID</span><span>及</span><span>PCRPID</span></p>
<p>&nbsp;</p>
<p><span>如果你没有看到播放器画面，表明软件没有找到视频流或没有找到</span><span>PCR</span></p>
<p>&nbsp;</p>
<h2><a name=_Toc272427033><span><span>B.<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>媒体信息</span></a></h2>
<p>&#160;</p>
<p>&nbsp;<img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/2.jpg" width=558 height=379></p>
<p><span>该模块显示了视频序列，音频帧的几乎所有参数，以及视音频流数量。具体不再叙述</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><a name=_Toc272427034><span><span>C.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>PSI/SI</span></a></h2>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/3.jpg" width=558 height=379></p>
<p>&nbsp;</p>
<p><span>此模块对所有的</span><span>PSI/SI</span><span>进行了解析，当流中存在</span><span>PSI/SI</span><span>数据时，会在此模块列出。在视图中点击鼠标右键，可以展开</span><span>/</span><span>折叠所有节点。</span></p>
<p>&nbsp;</p>
<h2><a name=_Toc272427035><span><span>D.<span>&nbsp;&nbsp;&nbsp; </span></span></span><span>PID</span></a><span><span>统计</span></span></h2>
<p>&#160;</p>
<p>&nbsp;<img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/pid.JPG" width=955 height=548></p>
<p><span>列出当前</span><span>TS</span><span>流中各个</span><span>PID</span><span>出现的数量及占用百分比，所属类型</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2><a name=_Toc272427036><span><span>E.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>图表</span></a></h2>
<p><span>当流中存在多路节目时，图标界面会显示一节节目选择对话框，单击可以显示相应节目图表</span></p>
<h3><a name=_Toc272427037><span>1.</span></a><span><span>时间戳信息</span></span></h3>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/4.jpg" width=558 height=379></p>
<p>&nbsp;</p>
<p><span>时间戳图表显示的是，</span><span>DTS</span><span>、</span><span>PTS</span><span>出现时，与</span><span>PCR</span><span>的采样。与&#8220;</span><span>PCR</span><span>抖动&#8221;图表相同的是，时间戳以</span><span>PCR</span><span>时钟为基准。</span><span>DTS</span><span>与</span><span>PTS</span><span>值取自视频流中的</span><span>I</span><span>帧。由于帧的编码顺序与显示顺序的关系，不取</span><span>B</span><span>、</span><span>P</span><span>或其他帧的</span><span>PTS</span><span>与</span><span>DTS</span><span>，否则时间就不是累加的。</span></p>
<p><span>滚动鼠标滚轮可以缩放</span><span>/</span><span>扩展图表显示，这里大约提供了</span><span>20</span><span>倍的扩展，如果你需要显示更小数量级的图表，可以在开始分析文件时选择少分析一些数据。</span></p>
<p><span>图像可以用鼠标拖动，来调整显示位置。</span></p>
<p><span>在图表上点击右键，可以选择将当前图标存储为</span><span>png/jpg</span><span>等格式的图片。</span></p>
<h3><a name=_Toc272427038><span>2.</span><span>PCR</span></a><span><span>抖动</span></span></h3>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/6.jpg" width=558 height=379></p>
<p>&nbsp;</p>
<p><span>DTS</span><span>与</span><span>PCR</span><span>、</span><span>PTS</span><span>与</span><span>PCR</span><span>的差值</span></p>
<p>&nbsp;</p>
<h3><a name=_Toc272427039><span>3.GOP</span></a><span><span>列表</span></span></h3>
<p>&#160;</p>
<p>&nbsp;</p>
<p><span>视频的</span><span>GOP</span><span>结构</span></p>
<p>&nbsp;</p>
<h3><a name=_Toc272427040><span>4.GOP</span></a><span><span>抖动</span></span></h3>
<p>&#160;</p>
<p>&nbsp;</p>
<p><span>GOP</span><span>结构变化</span></p>
<p>&nbsp;</p>
<h3><a name=_Toc272427041><span>5.</span></a><span><span>码率抖动</span></span></h3>
<p>&#160;</p>
<p><span>码率编码曲线，图中的每一个点为每次采样，码率计算方式为：两个</span><span>PCR</span><span>包之间的</span><span>TS</span><span>包数量除以时间</span></p>
<p>&nbsp;</p>
<h2><a name=_Toc272427042><span><span>F.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>数据包视图</span></a></h2>
<p><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/5.jpg" width=558 height=379></p>
<p>&nbsp;</p>
<p><span>数据包列表中显示了包</span><span>ID</span><span>，类型，</span><span>Payload</span><span>是否为真以及</span><span>PCR</span><span>等数据，点选某个条目，可以显示相应</span><span>TS</span><span>包的十六进制，及标示位等信息。</span></p>
<p><span>在数据包列表点击右键，可以执行上下翻页，或保存选中</span><span>TS</span><span>包等操作。</span></p>
<p><span>节点列表的包过滤器尚未实现。</span></p>
<p>&nbsp;</p>
<h2><a name=_Toc272427043><span><span>G.<span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>小工具</span></a></h2>
<h3><a name=_Toc272427044><span><span>1.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>PID</span></a><span><span>抽取</span></span></h3>
<p>&#160;</p>
<p><span>填入你要抽取出来的</span><span>PID</span><span>，如果有多个，以英文的逗号隔开。此处的</span><span>PID</span><span>要填十进制</span></p>
<h3><a name=_Toc272427045><span><span>2.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>重设</span><span>PID</span></a></h3>
<p>&#160;</p>
<p><span>填入要重设的原始及目的</span><span>PID</span><span>，值为十进制</span></p>
<h3><a name=_Toc272427046><span><span>3.<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span>204</span></a><span><span>转</span><span>188</span></span></h3>
<p>&#160;</p>
<p><span>204</span><span>包长的</span><span>TS</span><span>流转为</span><span>188</span><span>包长</span></p>
<p>&nbsp;</p>
<h1><a name=_Toc272427047><span>软件缺点</span></a></h1>
<p><span>相比同类的</span><span>TS</span><span>分析软件，本程序至少存在以下不足：</span></p>
<p><span><span>l&nbsp;</span></span><span>没有对描述子进行解析</span></p>
<p><span><span>l&nbsp;</span></span><span>没有对连续计数校验，</span><span>PCR</span><span>间隔校验等验证信息</span></p>
<p><span><span>l&nbsp;</span></span><span>没有对视频序列协议的解析</span></p>
<p><span><span>l&nbsp;</span></span><span>没有数据包查找功能</span></p>
<p><span><span>l&nbsp;</span></span><span>没有</span><span>PID</span><span>过滤功能，无法各</span><span>PID</span><span>的</span><span>TS</span><span>包分类显示</span></p>
<p><span><span>l&nbsp;</span></span><span>没有友好的语法分析</span></p>
<p><span><span>l&nbsp;</span></span><span>没有软复用功能</span></p>
<p><span><span>l&nbsp;</span></span><span>不支持加解扰</span></p>
<p>&nbsp;</p>
<h1><a name=_Toc272427048><span>其他说明</span></a></h1>
<p><span>软件的处理机制是，当流中存在</span><span>PSI/SI</span><span>信息时，对节目的分析将完全依照</span><span>PMT</span><span>对节目的说明，当不存在</span><span>PSI/SI</span><span>信息时，软件会自己判断流中是否含有音视频、</span><span>PCR</span><span>等信息，并对分析流类型。但是，一些特别的情况，例如不含有</span><span>PCR</span><span>信息，在&#8220;数据包&#8221;及&#8220;</span><span>PID</span><span>&#8221;视图中对包类型的显示会是&#8220;未知&#8221;状态，而&#8220;</span><span>MediaInfo</span><span>&#8221;视图对流的分析则是独立的，您应当以&#8220;</span><span>MediaInfo</span><span>&#8221;视图显示的结果为准。</span></p>
<h1><a name=_Toc272427049><span>问题报告</span></a></h1>
<p><span>当您在使用过程当中遇到问题，或发现软件</span><span>bug</span><span>，可以与我联系，请您将问题详细描述，最好再附加上遇到问题的</span><span>TS</span><span>流（</span><span>5-10M</span><span>即可），发邮件给我，我会尽快为您答复。</span></p>
<p>&nbsp;</p>
<h1><a name=_Toc272427050><span>后记</span></a></h1>
<p><span>自</span><span>2.2.1</span><span>版本起，软件将取消使用时间限制，因为我无法再保障更新速度。</span><span>EasyICE</span><span>是业余时间开发，一年多来消耗了太多的时间与精力，有时为了设计一种界面布局会考虑好几天，或者为了优化处理速度调整实现方式，甚至整个重构。虽然现在也不尽完美，但我一直在尽量地去做。很多理想的功能尚未实现，那些可能不再被添加了，实在没有时间。</span></p>
<p>&nbsp;</p>
<p><span>本软件供交流学习使用，您无须为此支付费用，但不得用于商业用途。</span></p>
<p><span>致谢：</span><span>Easy, hero, </span><span>介于</span><span>01, </span><span>师傅</span><span>:nooby</span></p>
<p>&nbsp;</p>
<p><span>版权所有：</span><span>Z</span><span>￠天使</span></p>
<p><span>Win</span><span>内核驱动开发</span><span>QQ</span><span>群：</span><span>75446994</span></p>
<p><span>视频编解码</span><span>QQ</span><span>群：</span><span>85390662</span></p>
<p><span>Email: </span><span><a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#104;&#97;&#110;&#103;&#120;&#105;&#110;&#106;&#105;&#97;&#110;&#49;&#57;&#55;&#50;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;"><span>shangxinjian1972@163.com</span></a></span></p>
<p>&nbsp;</p>
<p><span>2010/9/14 </span><span>于北京</span></p>
<img src ="http://www.cppblog.com/elva/aggbug/126855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-09-17 13:14 <a href="http://www.cppblog.com/elva/archive/2010/09/17/126855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LC wince WindowsMobile 编译过程（转）</title><link>http://www.cppblog.com/elva/archive/2010/08/14/123394.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 13 Aug 2010 17:01:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/08/14/123394.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/123394.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/08/14/123394.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/123394.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/123394.html</trackback:ping><description><![CDATA[<font  color="#9587FF" face="Arial, Helvetica, sans-serif" size="4"><span  style="font-size: 14px; line-height: 22px;">（一）搭建编译环境<br style="line-height: 22px; "><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">（1）安装Cygwin。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">下载地址：<a href="http://www.cygwin.com/setup.exe" target="_parent" style="line-height: 22px; text-decoration: none; color: rgb(255, 57, 248); ">http://www.cygwin.com/setup.exe</a></p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">以下选项为必选项（好象是不全），版本全按最新的，条件允许的话，可以全部安装。占用空间比较大。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">Archive&nbsp;<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;unzip (5.52-2)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;zip (2.32-2)<br style="line-height: 22px; ">Devel&nbsp;<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;autoconf (4-1 2.13-3 2.61-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;automake (2-1 1.10-1 1.4p6-4 1.5-2 1.63-3 1.7.9-3 1.8.5-3 1.9.6-2)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;binutils (20080624)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;cvs (1.11.22-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gcc (3.4.4-3)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gcc-core (3.4.4-3)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gcc-g++ (3.4.4-3)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gcc-mingw (20040810-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gcc-mingw-core (20050522-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gcc-mingw-g++ (20050522-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gdb (6.8-2)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gettext (0.15-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;gettext-devel (0.15-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;git (1.6.0.2-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;libiconv (1.11-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;libgcrypt-devel (1.41-4)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;libtool (1.5.27a-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;make (3.81-2)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;mingw-runtime (3.15.1-1)&nbsp;<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;nasm (2.02-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;patchutils (0.2.31-2)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;pkg-config (0.23a-2)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;subversion (1.5.2-1)<br style="line-height: 22px; ">Editor&nbsp;<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;vim (7.2-3)<br style="line-height: 22px; ">Libs&nbsp;<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;expat (2.0.1-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;libgcrypt (1.4.1-4)<br style="line-height: 22px; ">Web&nbsp;<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;curl (optional: for building extras/contrib) (7.16.3-1)<br style="line-height: 22px; ">&nbsp;&nbsp;&nbsp;&nbsp;wget (optional: for building extras/contrib) (1.11.3-1)</p><br style="line-height: 22px; ">（2）安装mingw32ce。<br style="line-height: 22px; "><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">下载地址：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><a href="http://cdnetworks-kr-2.dl.sourceforge.net/project/cegcc/cegcc/0.59.1/cegcc_mingw32ce_cygwin1.7_r1375.tar.bz2" style="line-height: 22px; text-decoration: none; color: rgb(255, 57, 248); ">http://cdnetworks-kr-2.dl.sourceforge.net/project/cegcc/cegcc/0.59.1/cegcc_mingw32ce_cygwin1.7_r1375.tar.bz2</a></p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">解压命令：tar xjf arm-mingw32ce-0.59.1.tar.bz2 -C</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">在windows下解压也行，但有的时候会少文件，最好用linux命令解压，解压完拷贝到/opt/mingw32ce&nbsp; (默认解压在当前目录，这个包是个压缩包，没有路径)。</p><br style="line-height: 22px; ">（3）安装第三方库。<br style="line-height: 22px; "><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">下载地址：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">http://download.videolan.org/pub/testing/contrib/contrib-20091114-wince-bin-gcc-4.1.0-runtime-3.15.2-only.tar.bz2</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">解压到：<br style="line-height: 22px; ">/usr/wince<br style="line-height: 22px; "></p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br style="line-height: 22px; ">注意一个问题：此处下载的库，一定要和VLC代码匹配。<br style="line-height: 22px; "></p><br style="line-height: 22px; ">（4）下载VLC代码。<br style="line-height: 22px; "><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">下载地址：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><a href="http://download.videolan.org/pub/videolan/vlc/1.0.5/vlc-1.0.5.tar.bz2" style="line-height: 22px; text-decoration: none; color: rgb(255, 57, 248); ">http://download.videolan.org/pub/videolan/vlc/1.0.5/vlc-1.0.5.tar.bz2</a></p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">解压目录：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">\home\UserName\vlc-1.0.5\</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">并且进入该目录执行：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">./bootstrap</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">一般没有错误，可能出现的错误：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">+ aclocal-1.9 -I m4&nbsp;<br style="line-height: 22px; ">/usr/bin/m4:configure.ac:4643: cannot create temporary file for diversion: Permission denied</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">autom4te-2.61: /usr/bin/m4 failed with exit status: 1&nbsp;<br style="line-height: 22px; ">aclocal-1.9: autom4te failed with exit status: 1</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">分析：杀毒软件有关系。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">解决方法：关闭杀毒软件重新运行./bootstrap。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">至此准备工作就完成。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;（二）配置编译选项<br style="line-height: 22px; "></p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">建立一个conf-vlc.sh文件，建议用UltraEdit打开，编辑，如果直接文本编辑的话最后编辑完的文件需要用</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">dos2unix conf-vlc.sh</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">转换脚本的编码格式。（注意行尾的空格和斜线，最后一行只有空格没有斜线）。文件的开始几行是设置一些路径，一般也不需要修改。后边部分主要是对VLC的功能的添加和删除。有很多选项都有默认值，具体请执行命令：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">./configure &#8211;help &gt; conf.txt</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">后，在conf.txt中查看具体选项设置说明。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">下面的列出的是，VLC1.0.5版本设置成功的conf-vlc.sh</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">PATH=/opt/mingw32ce/bin:$PATH \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">CPPFLAGS="-I/usr/wince/include -D_WIN32_WCE=0x0500" \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">LDFLAGS="-L/usr/wince/lib" \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">PKG_CONFIG_LIBDIR=/usr/wince/lib/pkgconfig \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">./configure --host=arm-mingw32ce \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --enable-dshow --enable-bda --disable-hal --disable-activex --disable-vlc \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --disable-directx --disable-dvdnav --disable-libgcrypt --enable-wingdi \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --disable-remoteosd --disable-sdl --disable-skins2 \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --disable-faad --enable-mad --enable-wingdi --enable-waveout \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --enable-mkv --enable-httpd --enable-libmpeg2 --enable-ogg \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --enable-live555 --enable-realrtsp --enable-bda \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --enable-ffmpeg --with-ffmpeg-mp3lame --with-ffmpeg-faac \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --with-ffmpeg-zlib --enable-faad --enable-flac --enable-theora \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --enable-csri --enable-libass --enable-asademux --enable-freetype=/usr/wince/freetype-2.3.12 \</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --enable-release --enable-disable --enable-optimizations --enable-sse --enable-mmx --enable-optimize-memory</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">编辑完conf-vlc.sh文件，执行脚本：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">./conf-vlc.sh</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">如果脚本遇到了类似Permission denied的错误，提升脚本的权限：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">chmod 777 configure-vlc01.sh<br style="line-height: 22px; ">如果还有错误，一般是对应的库没有，或者版本不对。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">见到以下内容说明脚本运行成功了。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">You can tune the compiler flags in vlc-config.&nbsp;<br style="line-height: 22px; ">To build vlc and its plugins, type `./compile' or `make'.</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">至此配置工作就完成了</p><br style="line-height: 22px; ">（三）编译代码<br style="line-height: 22px; "><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">执行命令：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">make</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">如果刚执行几行就出现错误，请重新设置PATH，命令：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">PATH=/opt/mingw32ce/bin:$PATH</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">如果中途遇到关键字atoll的错误，打开config.h搜索关键字atoll</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">注掉以下代码：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">#define HAVE_ATOLL 1</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">如果中途遇到关键字iconv的错误，打开config.h搜索关键字iconv</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">注掉以下代码：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">#define HAVE_ICONV 1</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">再遇其他错误，检查lib是否正确，实在不行将相关模块在<a name="OLE_LINK1" style="line-height: 22px; text-decoration: none; color: rgb(255, 57, 248); ">conf-vlc.sh</a></p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">中disable掉。（需要重新运行conf-vlc.sh）</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">最后打包。</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">执行：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">make package-wince</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">就能直接将生成的文件打包成vlc-1.0.5.zip</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">或者执行：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">make package-wince-base</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">得到一个vlc-1.0.5的目录</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">&nbsp;</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">至此我们就能得到我们要的DLLs了</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><br></p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; ">原地址：</p><p style="line-height: 22px; margin-top: 0px; margin-right: 0px; margin-bottom: 10px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-indent: 2em; "><a href="http://bk6.blog.163.com/blog/static/24498560201051193449196/">http://bk6.blog.163.com/blog/static/24498560201051193449196/</a></p></span></font>
<img src ="http://www.cppblog.com/elva/aggbug/123394.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-08-14 01:01 <a href="http://www.cppblog.com/elva/archive/2010/08/14/123394.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>RTSP协议</title><link>http://www.cppblog.com/elva/archive/2010/08/13/123313.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 13 Aug 2010 03:45:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/08/13/123313.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/123313.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/08/13/123313.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/123313.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/123313.html</trackback:ping><description><![CDATA[<font size="4">因为项目需要，学习了一下RTSP协议，为了防止以后忘记，就把学习过程和成果记载下来。期间参考了一些网上的资料，并分析了VLC的RTSP报文。</font><br><font size="4">&nbsp;&nbsp;&nbsp;
RTSP（Real Time Streaming Protocol，实时流协议），是由Real
Network和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议。RTSP提供一种可扩展的框架，能够提供可控制的，按需
传输的实时数据，比如音频和视频文件。源数据可以包括现场数据的反馈和存储的文件。RTSP对流媒体提供了诸如暂停，快进等控制，而它本身并不传输数
据，RTSP的作用相当于流媒体服务器的远程控制。传输数据可以通过传输层的TCP/UDP协议，RTSP也提供了基于RTP传输机制的一些有效的方法。<br>RTSP消息格式：<br>RTSP的消息有两大类，一是请求消息(request)，一是回应消息(response)，两种消息的格式不同。<br>请求消息：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 方法 URI RTSP版本 CR LF<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 消息头 CR LF CR LF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 消息体 CR LF<br>&nbsp;&nbsp; 其中方法包括OPTIONS回应中所有的命令，URI是接收方（服务端）的地址，例如：rtsp://192.168.22.136:5000/v0<br>RTSP版本一般都是RTSP/1.0。每行后面的CR LF表示回车换行，需要接收端有相应的解析，最后一个消息头需要有两个CR LF<br>回应消息：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RTSP版本 状态码 解释 CR LF<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 消息头 CR LF CR LF<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 消息体 CR LF<br>&nbsp;&nbsp;&nbsp; 其中RTSP版本一般都是RTSP/1.0，状态码是一个数值，200表示成功，解释是与状态码对应的文本解释。<br>简单的RTSP交互过程：<br>C表示RTSP客户端，S表示RTSP服务端<br>1.C-&gt;S：OPTIONS request&nbsp;&nbsp;&nbsp; //询问S有哪些方法可用<br>1.S-&gt;C：OPTIONS response&nbsp;&nbsp; //S回应信息中包括提供的所有可用方法<br><br>2.C-&gt;S：DESCRIBE request&nbsp;&nbsp; //要求得到S提供的媒体初始化描述信息<br>2.S-&gt;C：DESCRIBE response&nbsp; //S回应媒体初始化描述信息，主要是sdp<br>&nbsp;<br>3.C-&gt;S：SETUP request&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置会话的属性，以及传输模式，提醒S建立会话<br>3.S-&gt;C：SETUP response&nbsp;&nbsp;&nbsp;&nbsp; //S建立会话，返回会话标识符，以及会话相关信息<br>&nbsp;<br>4.C-&gt;S：PLAY request&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //C请求播放<br>4.S-&gt;C：PLAY response&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //S回应该请求的信息<br>&nbsp;<br>S-&gt;C：发送流媒体数据<br>5.C-&gt;S：TEARDOWN request&nbsp;&nbsp; //C请求关闭会话<br>5.S-&gt;C：TEARDOWN response&nbsp; //S回应该请求<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;
上述的过程是标准的、友好的rtsp流程，但实际的需求中并不一定按部就班来。其中第3和4步是必需的！第一步，只要服务器客户端约定好，有哪些方法可
用，则OPTIONS请求可以不要。第二步，如果我们有其他途径得到媒体初始化描述信息（比如http请求等等），则我们也不需要通过RTSP中的
DESCRIBE请求来完成。第五步，可以根据系统需求的设计来决定是否需要。<br>rtsp中常用方法：<br>1.OPTIONS<br>目的是得到服务器提供的可用方法：<br>OPTIONS rtsp://192.168.22.136:5000/v0 RTSP/1.0<br>CSeq: 1 //每个消息都有序号来标记，第一个包通常是OPTIONS请求消息<br>User-Agent: bestilyq //自定义的字符串<br>&nbsp;<br>服务器的回应信息包括提供的一些方法。例如：<br>RTSP/1.0 200 OK<br>Cseq: 1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //每个回应消息的cseq数值和请求消息的cseq相对应<br>Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY //服务器提供的可用的方法<br><br>2.DESCRIBE<br>C向S发起DESCRIBE请求，为了得到会话描述信息(SDP)：<br>DESCRIBE rtsp://192.168.20.136:5000/v0 RTSP/1.0<br>CSeq: 2<br>Accept: application/sdp<br>Authorization: Basic YWRtaW46YWRtaW4= //有认证，不需要认证时不需要该字段<br>User-Agent: bestilyq<br>&nbsp;<br>服务器回应一些对此会话的描述信息(sdp)：<br>RTSP/1.0 200 OK<br>Cseq: 2<br>Date: Sat Feb&nbsp; 5 22:49:39 2009 GMT<br>Content-Type: application/sdp<br>Content-Length: 182<br>&nbsp;<br>v=0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //以下都是sdp信息<br>o=- 0 0 IN IPV4 127.0.0.1<br>t=0 0<br>s=No Name<br>a=tool:libavformat<br>m=video 0 RTP/AVP 96 //m表示媒体描述，下面是对会话中视频通道的媒体描述<br>b=AS:2000<br>a=rtpmap:96 MP4V-ES/90000<br>a=fmtp:96 profile-level-id=1<br>a=control:streamid=0 //streamid＝0表示视频流用的是通道0<br><br>3.SETUP<br>客户端提醒服务器建立会话，并确定传输模式：<br>(1)TCP模式<br>SETUP rtsp://192.168.20.136:5000/v0/streamid=0 RTSP/1.0&nbsp;&nbsp;&nbsp; <br>CSeq: 3<br>Authorization: Basic YWRtaW46YWRtaW4=<br>Transport: RTP/AVP/TCP;unicast;interleaved=0-1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>User-Agent: bestilyq<br>(2)UDP模式<br>SETUP rtsp://192.168.20.136:5000/v0/streamid=0 </font><font size="4">RTSP/1.0<br></font><font size="4">CSeq: 3<br>Transport: RTP/AVP;unicast;client_port=3008-3009<br>Authorization: Basic YWRtaW46YWRtaW4=<br>User-Agent: bestilyq<br>&nbsp;&nbsp;&nbsp; URI中带有streamid＝0，表示对该通道进行设置。<br>&nbsp;&nbsp;&nbsp; Transport参数设置了传输模式。</font><font size="4">RTP/AVP/TCP表示通过TCP传输RTP包，</font><font size="4">RTP/AVP表示使用UDP传输RTP包。</font><font size="4">unicast表示单播。</font><font size="4">interleaved
值有两个：0和1，0表示RTP包，1表示RTCP包，接收端根据interleaved的值来区别是哪种数据包。client_port值有3008和
3009，3008表示客户端接收RTP包的端口，3009表示客户端接收RTCP包的端口，服务端要分别将RTP包和RTCP包发送到这两个端口。<br>&nbsp;<br>服务器回应信息：<br>(1)TCP模式<br>RTSP/1.0 200 OK<br>CSeq: 3<br>Date: Sat Feb&nbsp; 5 22:35:27 2009 GMT<br>Session: a522bbb4335617db<br>Transport: RTP/AVP/TCP;interleaved=0-1<br>(2)UDP模式<br>RTSP/1.0 200 OK<br>CSeq: 3<br>Date: Sat Feb&nbsp; 5 22:49:39 2009 GMT<br>Session: 01fa4ca2566a6301&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //服务器回应的会话标识符<br>Transport: RTP/AVP/UDP;unicast;client_port=3008-3009;server_port=1024-1025<br><br>4.PLAY<br>客户端发送播放请求：<br>PLAY rtsp://192.168.20.136:5000/v0 RTSP/1.0<br>CSeq: 4<br>Session: a522bbb4335617db&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //SETUP返回的会话标识符<br>Range: npt=0.000-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置播放时间的范围<br>User-Agent: bestilyq<br><br>服务器回应信息：<br>RTSP/1.0 200 OK<br>CSeq: 4<br>Date: Sat Feb&nbsp; 5 22:49:39 2009 GMT<br>Session: a522bbb4335617db<br><br>5.TEARDOWN<br>客户端发起关闭请求:<br>TEARDOWN rtsp://192.168.20.136:5000/v0 RTSP/1.0<br>CSeq: 5<br>Session: a522bbb4335617db<br>User-Agent: bestilyq<br><br>服务器回应:<br>RTSP/1.0 200 OK<br>Cseq: 5<br>Date: Sat Feb&nbsp; 5 22:49:47 2009 GMT<br>Session: a522bbb4335617db<br><br>&nbsp;&nbsp;&nbsp; 以上方法都是交互过程中最为常用的,其它还有一些重要的方法如GET_PARAMETER,SET_PARAMETER,PAUSE,REDIRECT等等。<br><br>ps：<br>sdp的格式<br>v=&lt;version&gt;<br>o=&lt;username&gt; &lt;session id&gt; &lt;version&gt; &lt;network type&gt; &lt;address type&gt; &lt;address&gt;<br>s=&lt;session name&gt;<br>i=&lt;session description&gt;<br>u=&lt;URI&gt;<br>e=&lt;email address&gt;<br>p=&lt;phone number&gt;<br>c=&lt;network type&gt; &lt;address type&gt; &lt;connection address&gt;<br>b=&lt;modifier&gt;:&lt;bandwidth-value&gt;<br>t=&lt;start time&gt; &lt;stop time&gt;<br>r=&lt;repeat interval&gt; &lt;active duration&gt; &lt;list of offsets from start-time&gt;<br>z=&lt;adjustment time&gt; &lt;offset&gt; &lt;adjustment time&gt; &lt;offset&gt; ....<br>k=&lt;method&gt;<br>k=&lt;method&gt;:&lt;encryption key&gt;<br>a=&lt;attribute&gt;<br>a=&lt;attribute&gt;:&lt;value&gt;<br>m=&lt;media&gt; &lt;port&gt; &lt;transport&gt; &lt;fmt list&gt;<br>v = （协议版本）<br>o = （所有者/创建者和会话标识符）<br>s = （会话名称）<br>i = * （会话信息）<br>u = * （URI 描述）<br>e = * （Email 地址）<br>p = * （电话号码）<br>c = * （连接信息）<br>b = * （带宽信息）<br>z = * （时间区域调整）<br>k = * （加密密钥）<br>a = * （0 个或多个会话属性行） <br>时间描述：<br>t = （会话活动时间）<br>r = * （0或多次重复次数）<br>媒体描述：<br>m = （媒体名称和传输地址）<br>i = * （媒体标题）<br>c = * （连接信息 — 如果包含在会话层则该字段可选）<br>b = * （带宽信息）<br>k = * （加密密钥）<br>a = * （0 个或多个媒体属性行）<br>带*为可选信息。<br><br>参考文章：rfc2326（rtsp）；rfc2327（sdp)<font size="4"> ；rfc</font></font><font size="4">3550（rtp/rtcp）</font>
<br><br>原帖地址：<br><a  href="http://blog.chinaunix.net/u2/77292/showart_1922940.html">http://blog.chinaunix.net/u2/77292/showart_1922940.html</a><br><br><img src ="http://www.cppblog.com/elva/aggbug/123313.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-08-13 11:45 <a href="http://www.cppblog.com/elva/archive/2010/08/13/123313.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IPB帧编码顺序（解码顺序）与显示顺序</title><link>http://www.cppblog.com/elva/archive/2010/06/21/118355.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Mon, 21 Jun 2010 05:05:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/06/21/118355.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/118355.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/06/21/118355.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/118355.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/118355.html</trackback:ping><description><![CDATA[<img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/530c5a8a2cdb1936c9fc7a6a.jpg" width=396 height=230><br>
<p>仅仅使用前一个显示的基准帧来编码的帧被称为&#8220;P帧&#8221;，同时使用前一个显示帧和未来帧作为基准帧进行编码的帧称为&#8220;B帧&#8221;。在通常的场景中，编解码器编码一个I帧，然后向前跳过几个帧，用编码I帧作为基准帧对一个未来P帧进行编码，然后跳回到I帧之后的下一个帧。编码的I帧和P帧之间的帧被编码为B帧。之后，编码器会再次跳过几个帧，使用第一个P帧作为基准帧编码另外一个P帧，然后再次跳回，用B帧填充显示序列中的空隙。这个过程不断继续，每12到15个P帧和B帧内插入一个新的I帧。例如，图1种给出了一个典型的视频帧序列。</p>
<p><span>通常，更换场景后的第一帧就是<span>I帧，I帧应当全帧传送。从压缩的程度来看，I画面的压缩量最少；P画面次之，它是以I画面为基础；B画面压缩最多。为了加大压缩比，通常在I帧后面相隔2帧（最多3帧）设置1个P帧，在I、P帧之间都是B帧，在两个P帧之间也是设置2～3帧B帧。B帧传送它与I帧或P帧之间的差值信息，或者P帧与后面P帧或I帧之间的差值信息，或者它与前后I、P帧或P、P帧平均值之间的差值信息。当主体内容变化愈大时，两个I画面之间的帧数值越小；当主体内容变化小时，I面画的间隔可以适当大一些。或者说，B帧、P帧所占比例越大，图像压缩比越高。一般两个I画面相隔13～15帧，相隔帧数不宜再多。</span></span></p>
<p><span>下面以<span>15帧为例，说明VCD图像帧的排列顺序。I、P、B三种画面的典型设置方式，对NTSC制共约需半秒时间。节目输入顺序是按实际出现顺序排列的，即I、B、B、P、B、B、P、B、B&#8230;&#8230;I、B、B、P&#8230;&#8230;；但为了解码时便于从I、P画面插补得到B画面，在编码录制节目时，将顺序改变了，即按照I、P、B、B&#8230;&#8230;顺序，即改为按原来0、3、1、2、6、4、5、9、7、8&#8230;的画面顺序。解码时先解出0帧、3帧，再由其插补预测计算得出1帧、2帧等等。为此，须在解码器内设置动态存储器，将I、P帧先解码并存储，再计算出各个B帧。不过最后输出时，还是应当按照实际播放顺序重组读出，按正确顺序输出。</span></span></p>
<br>
<div>音视频编码卡的视频编码算法从JPEG 发展到MPEG-1、MPEG-2、MPEG-4和H.264。JPEG是一种著名的图像压缩方法，最初由Joint Photographic Experts Group在1986年提出并于1992年正式成为ISO标准(ISO/IEC 10918),主要应用于静态图像压缩，如果把它用在运动图像压缩的时候，就是我们通常所说的Motion-JPEG，由于JPEG相当于MPEG的帧内压缩，因而没有去除时域上的冗余，所以在保证一定图像质量的时候，压缩比不高，通常只有10-30倍，但是它有一个固定的优点，就是延迟在40ms，实时性很好，所以在某些特殊应用的场合仍然可以看到它的踪影。MPEG运动图像编码技术标准是由Motion Picture Experts Group在1988年提出，并于1992年11月通过，1993年8月作为ISO/IEC 11172标准公布，这就是通常所说的MPEG-1。MPEG-1为了追求更高的压缩效率，更注重去除图像系列的时间冗余度。因此引入了I帧(帧内编码)、P帧(前向预测编码)、B帧(双向预测编码)。P帧由前一个I帧或P帧图像来预测，而B帧由前后的两个P帧或一个I帧和一个P帧来预测，因而编解码和帧的显示顺序有所不同，如图1所示<br><br>I B B P B B P&#8230;B B I&nbsp;&nbsp;&nbsp; I P B B P B B &#8230; I B B<br>1 2 3 4 5 6 7 &#8230;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1 4 2 3 7 5 6 &#8230;<br>&nbsp; (a) 显示顺序&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (b) 编解码顺序<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图 1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在此有两个问题需要说明：首先是插多少B 帧最合适？理论上说I、P之间插入的B帧越多，压缩比越高，但是编解码器所需的帧存储器也越大，因此实际应用中一般最多两个。其次，B帧的引入会增加编解码端的延迟，如果追求网络监视的时延，最好是不使用B帧。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MPEG-1标准的一个成功应用范例是小型激光视盘(VCD)。由于它的压缩比相对于M- JPEG大为提高，因而在数字监控系统中得到广泛的应用。但是并不是最适合数字监控系统的应用，主要表现在码率固定，代价是引起图像质量的抖动，而数字监控系统最需要的不是恒定码率，而是恒定质量。同时MPEG-1本身的技术限制，其压缩比也没有达到用户满意的程度。而2000年提出的MPEG-4不仅是一个非常开放的标准，而且增加了许多新的工具，以达到降低某些应用或图像场景中要求的图像质量所需的比特率。值得注意的是虽然大部分用来降低比特率的工具是为非实时应用开发的，无法使用到数字监控系统中，但是相对MPEG-1，由于使用半像素和1/4像素图像匹配、帧内预测、高级运动矢量预测等新的技术，因而采用MPEG-4的压缩标准之后，在PAL CIF 25fps情况下，大部分情况下码率在300k-500k的MPEG-4压缩图像质量超过1.25Mbit的MPEG-1图像，因而在数字监控系统中得到最广泛和成功的应用。<br></div>
<img src ="http://www.cppblog.com/elva/aggbug/118355.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-06-21 13:05 <a href="http://www.cppblog.com/elva/archive/2010/06/21/118355.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>视频解码中，缓冲区的上溢和下溢</title><link>http://www.cppblog.com/elva/archive/2010/06/18/118152.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 18 Jun 2010 03:27:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/06/18/118152.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/118152.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/06/18/118152.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/118152.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/118152.html</trackback:ping><description><![CDATA[使用硬件相似的数据处理.一般都是数据进来,处理后立即发出去的形式.所以一般有一个数据进,一个数据出,2个接口.<br><br>硬件处理基本都要求实时.数据进来,处理之后马上发处理,这个时间要求非常短,一般要求控制在好多毫秒以内,才能达到实时的要求.一般硬件每秒钟能够处理的数据大小,在设计的时候就固定了.不能像软件那样,可以通过增加CPU来提升处理能力.而且硬件的缓存的容量也是在设计的时候就固定了,不能像软件那样,随意申请内存来用.<br>所以硬件的缓存都不会太大.缓存的数据太大,会造成等待数据处理延时太高.达不到实时的要求.<br>硬件每秒能够处理的数据也是固定的.<br>硬件在处理数据的时候,一般是要等待缓冲区有足够的数据可以处理,然后开始处理.<br>如果数据输入的速度,固定保持在理想状态,那么缓冲区就会一直有数据供给硬件平稳的进行处理.<br>输入一直输入数据,硬件一直有数据在处理,输出一直在输出处理好的数据.缓冲区的数据容量,一直保持在某个范围.<br><br>如果指数据发送太快,硬件处理不过来,缓存已经装不下那么多数据,开始丢弃这些数据,放弃处理.这就是指上溢.<br>如果数据发送太慢,缓冲区的数据都处理空了,输入数据还没过来,硬件还在等待缓冲区有足够数据可以处理,输出接口就在要求发送处理好的数据出去,就是指下溢. 
<img src ="http://www.cppblog.com/elva/aggbug/118152.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-06-18 11:27 <a href="http://www.cppblog.com/elva/archive/2010/06/18/118152.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] FFMPEG 笔记</title><link>http://www.cppblog.com/elva/archive/2010/04/23/113336.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 23 Apr 2010 05:55:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/04/23/113336.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/113336.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/04/23/113336.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/113336.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/113336.html</trackback:ping><description><![CDATA[<span  style="font-family: verdana, sans-serif; font-size: 14px; line-height: 21px; "><pre><font size="3">1. encode yuv file<br><br>ffmpeg -s cif -vcodec mpeg4 -i paris.yuv paris.avi<br><br>-s 指定帧大小 cif 为 352x288，qcif 为 176x144，4cif 为 704x576<br>-vcodec 指定采用的编码器<br>-i 指定输入文件<br><br><br>2. output raw YUV420P file<br><br>ffmpeg -i paris.avi paris0.yuv<br><br><br>3. 将一段视频输出为图片序列<br><br>ffmpeg -i 1.avi cat%d.png -vcode png<br><br>-vcodec mjpeg<br>-vcodec ppm<br><br><br>ffmpeg -i 1.avi cat%04d.jpg -vcodec mjpeg -ss 0:1:2 -t 0:0:1<br><br>将1.avi视频 1分02秒 处开始，持续1秒长的视频输出为jpg的序列<br><br><br>ffmpeg -vcodec mjpeg -i 1.flv  test%02d.jpg  -ss 0:0:2 -t 0.001<br><br>-t 表示持续时间为0.001秒，这个命令相当于截取开始2秒处的一幅jpeg的图片<br><br><br>4. 多输入单输出<br><br>ffmpeg -i /tmp/a.wav -s 640x480 -i /tmp/a.yuv /tmp/a.mpg<br><br><br>5. 单输入多输出<br><br>ffmpeg -i /tmp/a.wav -ab 64 /tmp/a.mp2 -ab 128 /tmp/b.mp2 -map 0:0 -map 0:0<br><br>-map file:stream_index 指定哪一个输入流用于输出流，顺序对应<br><br><br>6. DVD to mpeg4<br><br>ffmpeg -i snatch_1.vob -f avi -vcodec mpeg4 -b 800 -g 300 -bf 2 -acodec mp2 -ab 128 snatch.avi<br><br>压制高品质mp4的参考参数：<br><br>'-mbd rd -flags +4mv+trell+aic -cmp 2 -subcmp 2 -g 300 -pass 1/2' <br><br>可以试试： '-bf 2', '-flags qprd', '-flags mv0', '-flags skiprd'<br><br><br>7. encode mpeg1/mpeg2<br><br>ffmpeg -i 1.avi -vcodec mpeg2video 2.mpg<br><br>注意mpeg2的codec为 mpeg2video<br><br>其他codec可以使用 ffmpeg -formats 查看<br><br>压制高品质mp1/mp2的参考参数：<br><br>'-mbd rd -flags +trell -cmp 2 -subcmp 2 -g 100 -pass 1/2' <br><br>注意，加 '-g 100' 可能会使某些解码器没法解码 <br><br>可以试试： '-bf 2', '-flags qprd', '-flags mv0', '-flags skiprd'<br><br><br>8. encode flv<br><br>ffmpeg -i 1.avi -ab 56 -ar 22050 -b 500 -r 15 1.flv<br><br><br>9. X 屏幕录像<br><br>FFmpeg can grab the X11 display.<br><br>ffmpeg -f x11grab -i :0.0 /tmp/out.mpg<br><br>0.0 is display.screen number of your X11 server, same as the DISPLAY environment variable.<br><br>ffmpeg -f x11grab -i :0.0+10,20 /tmp/out.mpg<br><br>0.0 is display.screen number of your X11 server, same as the DISPLAY environment variable. <br>10 is the x-offset and 20 the y-offset for the grabbing. <br><br><br>10. 音视频采集<br><br>ffmpeg -f audio_device -i /dev/dsp -f video4linux2 -i /dev/video0 /tmp/out.mpg<br><br>Note that you must activate the right video source and channel before launching FFmpeg with <br>any TV viewer such as xawtv (http://bytesex.org/xawtv/) by Gerd Knorr. You also have to set <br>the audio recording levels correctly with a standard mixer.<br><br><br>11. 常用选项<br><br>-i filename 输入文件<br><br>-f fmt 强迫采用格式fmt<br><br>-y 覆盖输出文件<br><br>-ss position 搜索到指定的时间处开始 [-]hh:mm:ss[.xxx]的格式也支持<br><br>-b bitrate 设置比特率，缺省200kb/s<br><br>-r fps 设置帧频 缺省25<br><br>-s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用：<br>	sqcif 128X96 qcif 176X144 cif 352X288 4cif 704X576<br><br>-vcodec codec 强制使用codec编解码方式。 如果用copy表示原始编解码数据必须被拷贝。<br><br>-sameq 使用同样视频质量作为源（VBR）<br><br>-g gop_size 设置图像组大小<br><br>-intra 仅适用帧内编码<br><br>-bf frames 使用frames B 帧，支持mpeg1,mpeg2,mpeg4<br><br>-ab bitrate 设置音频码率<br><br>-ar freq 设置音频采样率<br><br>-ac channels 设置通道 缺省为1<br><br>-an 不使能音频纪录<br><br>-acodec codec 使用codec编解码<br><br>-benchmark 为基准测试加入时间<br><br>-hex 倾倒每一个输入包<br><span style="font-family: Arial, Verdana, sans-serif; "><br><br>12. </span>mpayer 截图：<br><br>mplayer -ss START_TIME -noframedrop -nosound -vo jpeg -frames N NAME_OF_VIDEO_FILE<br><br>获取视频时长(seconds)：<br><br>mplayer -identify movie-filename -nosound -vc dummy -vo null | grep ID_LENGTH<br><br><br>13. 快速合并视频文件：<br><br>mencoder -oac copy -ovc copy -idx -o output.avi video1.avi video2.avi video3.avi</font><font size="3"> <br></font></pre></span>
<img src ="http://www.cppblog.com/elva/aggbug/113336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-04-23 13:55 <a href="http://www.cppblog.com/elva/archive/2010/04/23/113336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]H.264中的Slice和Slice Group</title><link>http://www.cppblog.com/elva/archive/2010/03/19/110083.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 19 Mar 2010 03:32:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/03/19/110083.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/110083.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/03/19/110083.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/110083.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/110083.html</trackback:ping><description><![CDATA[<h1 class="title_txt"><cite class="fav_csdnstylebykimi"> </cite>
</h1>
<div class="blogstory">
<script type="text/javascript">
                        document.body.oncopy = function() {
                            if (window.clipboardData) {
                                setTimeout(function() {
                                    var text = clipboardData.getData("text");
                                    if (text && text.length > 300) {
                                        text = text + "\r\n\n本文来自CSDN博客，转载请标明出处：" + location.href;
                                        clipboardData.setData("text", text);
                                    }
                                }, 100);
                            }
                        }
					</script>
<script type="text/javascript">                        function StorePage() { d = document; t = d.selection ? (d.selection.type != 'None' ? d.selection.createRange().text : '') : (d.getSelection ? d.getSelection() : ''); void (keyit = window.open('http://www.365key.com/storeit.aspx?t=' + escape(d.title) + '&u=' + escape(d.location.href) + '&c=' + escape(t), 'keyit', 'scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes')); keyit.focus(); }</script>
<p>图
像映射成Slice Group,就是把宏块或者宏块对进行映射成不同的Slice Group（Slice Group,0、Slice
Group,1等等），在不同的Slice Group中再进行分成Slice ，相对于Slice Group来说，Slice 包含Slice
Group内部按照光栅扫描顺序排列的整数个宏块或宏块对，但是若是相对于图像来说并不一定是按光栅扫描的顺序连续排列的，因为中间经过了图像到
Slice Group的映射。Slice Group的提出是为了采用FMO实现错误隐藏。若是采用映射，那么在同一Slice Group中的相邻宏块在实际图像中不一定是相邻的，
那么当某一个Slice Group内的Slice 的宏块发生丢包等错误的时候，就可以利用其他Slice
Group内的Slice的宏块对其进行预测恢复，因为其他Slice
Group中的宏块或宏块对与该丢失宏块或宏块对在位置上是相邻的，相关性最强，预测误差最小。当不采用Slice
Group的时候，若是Slice的宏块发生错误，那么就导致一部分空间位置相邻的宏块或宏块对无法解出，那么就得利用周边宏块或宏块对对其进行预测，这
样的预测效果随着越靠近出错区域中心越差。显然，采用Slice Group方法的预测效果要好。如图所示</p>
<p><br><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/sunnymov/EntryImages/20090826/%E5%BF%AB%E7%85%A7-1.jpg" alt="" height="267" width="741"></p>
<p><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/sunnymov/EntryImages/20090826/%E5%BF%AB%E7%85%A7-3.jpg" alt="" height="260" width="740"></p>
<p>若红色边框区域发生错误，也即某Slice0发生错误，那么上图中该区域宏块对应的原始图像的位置如左边所示，由Slice Group1恢复Slice Group0 ，由其空间相关性可知恢复效果应该会不错。</p>
<p>但是下图的情况就不一样了，两个片的空间相关性没那么强，恢复效果比上一种方法差。</p>
</div>
<br>原文链接<br><a target="_blank"  href="http://blog.csdn.net/sunnymov/archive/2009/08/26/4486922.aspx">http://blog.csdn.net/sunnymov/archive/2009/08/26/4486922.aspx</a><br><br><img src ="http://www.cppblog.com/elva/aggbug/110083.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-03-19 11:32 <a href="http://www.cppblog.com/elva/archive/2010/03/19/110083.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]H264与MPEG中I、P、B帧编码的不同</title><link>http://www.cppblog.com/elva/archive/2010/03/19/110082.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 19 Mar 2010 03:30:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/03/19/110082.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/110082.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/03/19/110082.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/110082.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/110082.html</trackback:ping><description><![CDATA[<br>
<div class="blogstory">
<script type="text/javascript">
                        document.body.oncopy = function() {
                            if (window.clipboardData) {
                                setTimeout(function() {
                                    var text = clipboardData.getData("text");
                                    if (text && text.length > 300) {
                                        text = text + "\r\n\n本文来自CSDN博客，转载请标明出处：" + location.href;
                                        clipboardData.setData("text", text);
                                    }
                                }, 100);
                            }
                        }
					</script>
<script type="text/javascript">                        function StorePage() { d = document; t = d.selection ? (d.selection.type != 'None' ? d.selection.createRange().text : '') : (d.getSelection ? d.getSelection() : ''); void (keyit = window.open('http://www.365key.com/storeit.aspx?t=' + escape(d.title) + '&u=' + escape(d.location.href) + '&c=' + escape(t), 'keyit', 'scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes')); keyit.focus(); }</script>
<div class="tit"><strong> 1、H264中I、P、B 帧编码的基本流程</strong> </div>
<div class="tit">
<table style="table-layout: fixed; width: 100%;" border="0">
    <tbody>
        <tr>
            <td>
            <div id="blog_text" class="cnt">
            <div style="font-size: 12px;">
            <p><strong> I 帧编码的基本流程为：<br></strong> (1) 进行帧内预测，决定所采用的帧内预测模式。<br>(2) 像素值减去预测值，得到残差。<br>(3) 对残差进行变换和量化。<br>(4) 变长编码和算术编码。<br>(5) 重构图像并滤波，得到的图像作为其它帧的参考帧。</p>
            <p><br><strong> P 帧和 B 帧编码的基本流程为：<br></strong> (1) 进行运动估计，计算采用帧间编码流程编码模式的率失真函数(节)值。P 帧<br>只参考前面的帧，B 帧可参考后面的帧。<br>*(2) 进行帧内预测，选取率失真函数值最小的帧内模式与帧间模式比较，确定<br>采用哪种编码模式。<br>(3) 计算实际值和预测值的差值。<br>(4) 对残差进行变换和量化。<br>(5) 熵编码，如果是帧间编码模式，编码运动矢量</p>
            <p><strong> 2、MPEG压缩中的 I、B、P帧</strong> </p>
            <p>首先,MPEG-1压缩的基本思想:帧内压缩和帧间压缩。<br>其次,时间相关性的统计分析:统计的结果表明,在间隔1~2帧的图像中,各像素只有10%以下的点,其亮度差值变化超过2%,而色度差值的变化只有1%以下。<br><br>采用的压缩方法: 分组:把几帧图像分为一组(GOP),为防止运动变化,帧数不宜取多。<br>1.定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;<br>2.预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;<br>3.数据传输:最后将I帧数据与预测的差值信息进行存储和传输。<br><br><strong> I帧:帧内编码帧<br></strong> I帧特点:<br>1.它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;<br>2.解码时仅用I帧的数据就可重构完整图像;<br>3.I帧描述了图像背景和运动主体的详情;<br>4.I帧不需要参考其他画面而生成;<br>5.I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);<br>6.I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;<br>7.I帧不需要考虑运动矢量;<br>8.I帧所占数据的信息量比较大。<br><br><strong> P帧:前向预测编码帧。</strong> <br>P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧&#8220;某点&#8221;的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧&#8220;某点&#8221;的预测值并与差值相加以得到P帧&#8220;某点&#8221;样值,从而可得到完整的P帧。<br>P帧特点:<br>1.P帧是I帧后面相隔1~2帧的编码帧;<br>2.P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);<br>3.解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;<br>4.P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;<br>5.P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;<br>6.由于P帧是参考帧,它可能造成解码错误的扩散;<br>7.由于是差值传送,P帧的压缩比较高。<br><br><strong> B帧:双向预测内插编码帧。</strong> <br>B帧的预测与重构<br>B帧以前面的I或P帧和后面的P帧为参考帧,&#8220;找出&#8221;B帧&#8220;某点&#8221;的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中&#8220;找出(算出)&#8221;预测值并与差值求和,得到B帧&#8220;某点&#8221;样值,从而可得到完整的B帧。<br>B帧特点<br>1.B帧是由前面的I或P帧和后面的P帧来进行预测的;<br>2.B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;<br>3.B帧是双向预测编码帧;<br>4.B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;<br>5.B帧不是参考帧,不会造成解码错误的扩散。<br><br>注:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧,至于图像中的哪一帧是I帧,是随机的,一但确定了I帧,以后的各帧就严格按规定顺序排列。</p>
            </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
</div>
</div>
<br><img src ="http://www.cppblog.com/elva/aggbug/110082.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-03-19 11:30 <a href="http://www.cppblog.com/elva/archive/2010/03/19/110082.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]帧、场编码的个人理解</title><link>http://www.cppblog.com/elva/archive/2010/03/19/110081.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 19 Mar 2010 03:27:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/03/19/110081.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/110081.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/03/19/110081.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/110081.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/110081.html</trackback:ping><description><![CDATA[

<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;"><span style="font-size: small;">一、概述</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-family: 宋体;"><span style="font-size: small;">原
始视频帧（最原始的视频数据）根据编码的需要，以不同的方式进行扫描产生两种视频帧：连续或隔行视频帧，隔行视频帧包括顶场和底场，连续（遂行）扫描的视
频帧与隔行扫描视频帧有着不同的特性和编码特征，产生了所谓的帧编码和场编码。一般情况下，遂行帧进行帧编码，隔行帧可在帧编码和场编码间选取。<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/sunnymov/EntryImages/20090817/%E5%BF%AB%E7%85%A7-2.jpg" alt="扫描格式" height="295" width="816"></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="color: black; font-family: 宋体;">在帧编码中，参考为帧图像，</span><span style="font-family: 宋体;">采用帧运动补偿，两个场是联合编码，</span><span style="color: black; font-family: 宋体;">；在场编码中，参考为场图像</span><span style="font-family: 宋体;">，两个场是分别编码，采用场运动补偿。</span></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><font face="宋体"><span style="font-size: small;"></span></font></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><br></p><font face="宋体"><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;">帧编码与场编码的选择</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;">1.对于运动激烈的情况，也就是画面变化快，画面中的人物、背景等等短时间里就会有很大的变化。这样，如果使用帧编码，由于相邻两行（一行在顶场，一行在底场）的扫描时间相差了许多（因为是隔行扫描），那么由于变化剧烈（画面在短时间内就会产生很大的差异），相邻行没有太多的相关性。而对于场图像来说，相邻行的扫描时间非常短，所以即使运动剧烈，但还是有很强的时间相关性。所以在这种情况下用场编码，就能去除时间上的冗余。</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><br></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;">2.对于相对静止没有什么变化的情况应该相对好理解，因为画面内容没有太大的变化，扫描时间的长短并不影响相关性。倒是帧场的相邻行由于是真正意义上的相邻，所以空间相关性肯定要比场的相邻行（其实是隔行）的空间相关性要大。那么在这种情况下使用帧编码，就能去除空间上的冗余。</p></font><p>&#160;</p><p><br></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;"><span style="font-size: small;">二、视频序列帧、场编码方式</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">1.</span></span><span style="font-family: 宋体;">固定帧编码</span><span lang="EN-US"><span style="font-family: Times New Roman;">(</span></span><span style="font-family: 宋体;">全帧</span><span lang="EN-US"><span style="font-family: Times New Roman;">)----</span></span><span style="font-family: 宋体;">视频序列的全部帧始终采用帧编码方式。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">2.</span></span><span style="font-family: 宋体;">固定场编码（全场）</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-family: 宋体;"><span style="font-size: small;">视频序列中帧被分成两个场独立编码。编码规则：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt;"><span style="font-family: Times New Roman;"><span lang="EN-US"><span><span style="font-size: small;">1.</span><span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US"><span style="font-size: small;">I</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">帧可编码成两个</span><span lang="EN-US"><span style="font-family: Times New Roman;">I</span></span><span style="font-family: 宋体;">场或一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">I</span></span><span style="font-family: 宋体;">场和一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">P</span></span><span style="font-family: 宋体;">场，即</span><span lang="EN-US"><span style="font-family: Times New Roman;">II</span></span><span style="font-family: 宋体;">、</span><span lang="EN-US"><span style="font-family: Times New Roman;">IP.</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt;"><span style="font-family: Times New Roman;"><span lang="EN-US"><span><span style="font-size: small;">2.</span><span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US"><span style="font-size: small;">P</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">帧可编码成两个</span><span lang="EN-US"><span style="font-family: Times New Roman;">P</span></span><span style="font-family: 宋体;">场或一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">P</span></span><span style="font-family: 宋体;">场和一个</span><span lang="EN-US"><span style="font-family: Times New Roman;">B</span></span><span style="font-family: 宋体;">场，即</span><span lang="EN-US"><span style="font-family: Times New Roman;">PP</span></span><span style="font-family: 宋体;">、</span><span lang="EN-US"><span style="font-family: Times New Roman;">PB.</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt;"><span style="font-family: Times New Roman;"><span lang="EN-US"><span><span style="font-size: small;">3.</span><span style="font-family: &quot;Times New Roman&quot;; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span lang="EN-US"><span style="font-size: small;">B</span></span></span><span style="font-size: small;"><span style="font-family: 宋体;">帧可编码成两个</span><span lang="EN-US"><span style="font-family: Times New Roman;">B</span></span><span style="font-family: 宋体;">场，即</span><span lang="EN-US"><span style="font-family: Times New Roman;">BB.</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">3.</span></span><span style="font-family: 宋体;">图像级帧、场自适应编码</span><span lang="EN-US"><span style="font-family: Times New Roman;"> (PAFF)</span></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-indent: 21pt;"><span style="font-size: small;"><span style="font-family: 宋体;">视频序列能被编码成一个帧或两个场，自适应选择原则是根据采用该种编码方式的每一帧的</span><span lang="EN-US"><span style="font-family: Times New Roman;">RD</span></span><span style="font-family: 宋体;">值。</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;">4.</span></span><span style="font-family: 宋体;">宏块级帧、场自适应（</span><span lang="EN-US"><span style="font-family: Times New Roman;">MBAFF</span></span><span style="font-family: 宋体;">）</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span><span style="font-family: Times New Roman;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span></span><span style="font-family: 宋体;">为了进一步提高编码效率，采用了宏块级帧场自适应</span><span lang="EN-US"><span style="font-family: Times New Roman;">.,</span></span><span style="font-family: 宋体;">宏块级采用了宏块对（</span><span lang="EN-US"><span style="font-family: Times New Roman;">MBP</span></span><span style="font-family: 宋体;">）为基本编码单元（如图</span><span lang="EN-US"><span style="font-family: Times New Roman;">2</span></span><span style="font-family: 宋体;">所示）</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">&nbsp;<img src="http://p.blog.csdn.net/images/p_blog_csdn_net/sunnymov/EntryImages/20090817/%E5%BF%AB%E7%85%A7-1.jpg" alt="MBP格式" height="282" width="826"></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"><span lang="EN-US"><span style="font-family: Times New Roman;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>H.264</span></span><span style="font-family: 宋体;">采用的</span><span lang="EN-US"><span style="font-family: Times New Roman;">MBAFF</span></span><span style="font-family: 宋体;">方案：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-size: small;"></span><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/sunnymov/EntryImages/20090817/%E5%BF%AB%E7%85%A7-3.jpg" alt="H.264 mbaff编码方案" height="339" width="519">&nbsp;</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;"><span style="font-size: small;">在图像中运动比较大的地方采用场编码，运动比较小的地方采用帧编码，编码顺序例子如下：</span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><span style="font-family: 宋体;"><span style="font-size: small;"><img src="http://p.blog.csdn.net/images/p_blog_csdn_net/sunnymov/EntryImages/20090817/%E5%BF%AB%E7%85%A7-4.jpg" alt="编码例子" height="332" width="462"></span></span></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><br></p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;">原文链接：</p>
<p class="MsoNormal" style="margin: 0cm 0cm 0pt;"><a target="_blank" href="http://blog.csdn.net/sunnymov/archive/2009/08/17/4454424.aspx">http://blog.csdn.net/sunnymov/archive/2009/08/17/4454424.aspx</a><br><span style="font-family: 宋体;"><span style="font-size: small;"></span></span></p><img src ="http://www.cppblog.com/elva/aggbug/110081.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-03-19 11:27 <a href="http://www.cppblog.com/elva/archive/2010/03/19/110081.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MPEG TS 分析工具 EasyICE 2.1.0.0 发布</title><link>http://www.cppblog.com/elva/archive/2010/01/06/104883.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 06 Jan 2010 02:29:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2010/01/06/104883.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/104883.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2010/01/06/104883.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/104883.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/104883.html</trackback:ping><description><![CDATA[<p>MPEG-TS分析的利器</p>
<p>本程序时一款TS静态分析工具，相信许多功能是令人欣喜的，譬如对大文件的支持，以及处理速度等等。软件处于不断完善中，将有更多优秀的地方以友好的方式添加进来。</p>
<p>功能简介：<br>1.TS包列表显示，没有条目限制<br>2.十六进制显示数据<br>3.TS头，调整字段，以及PES分析<br>4.保存单个数据包<br>5.对大文件的支持，可以支持几百G的文件<br>6.可选数据分析，选择只分析文件的某一部分数据<br>7.psi/si表分析<br>8.pid统计<br>9.同步分析，图表显示</p>
<p>&nbsp;</p>
<p>截图：<br><br><br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/packet.JPG" width=952 height=546>&nbsp;<br><br><br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/pcr.jpg" width=954 height=549><br><br><br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/pid.JPG" width=955 height=548><br><br><br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/psi.JPG" width=952 height=548><br><br><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/elva/rate.JPG" width=953 height=548><br></p>
<p><br></p>
<p>运行环境要求：<br>1.Windowns2000以上操作系统<br>2.IE6.0以上<br>3.内存：128M以上</p>
<p>如果您遇到什么问题，请提交作者信箱。<br><br><br>本软件供交流学习使用，您无须为此支付费用，但不得用于商业用途。<br>致谢：Easy, hero, 介于01, 师傅:nooby<br>版权所有：2010 Z￠天使<br><br>Win内核驱动开发QQ群：75446994<br>视频编解码QQ群：85390662<br>Email: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#104;&#97;&#110;&#103;&#120;&#105;&#110;&#106;&#105;&#97;&#110;&#49;&#57;&#55;&#50;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;">shangxinjian1972@163.com</a><br><br><br><a href="http://cid-b8e403d940afb9a3.skydrive.live.com/self.aspx/.Public/EasyICE%5E_2.1.0.0.rar/" target=_blank>下载地址<br></a></p>
<img src ="http://www.cppblog.com/elva/aggbug/104883.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2010-01-06 10:29 <a href="http://www.cppblog.com/elva/archive/2010/01/06/104883.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DVB业务信息PSI/SI综述</title><link>http://www.cppblog.com/elva/archive/2009/09/18/96616.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 18 Sep 2009 02:46:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2009/09/18/96616.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/96616.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2009/09/18/96616.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/96616.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/96616.html</trackback:ping><description><![CDATA[<span><span>
<p>一、SI信息的构成</p>
<p>1、信息构成</p>
<p>SI信息内容是按照network(网络)&#8594;transport strem（传输流）&#8594;service（业务）&#8594;event（事件）的分层顺序描述，如图1所示。SI数据信息是按照一定的数据结构进行存储的，这样一来才能达到方便、快捷地进行数据检索和提取。SI数据主要有：网络信息、传输流信息、业务信息、业务的事件信息等，并且大量的信息都是通过描述符来传输的，所以可用树状链表来存储数据，构成从网络、传输流、业务、事件的树状结构。机顶盒接收端的解析主要负责这些SI数据的重建。</p>
<p><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/5d026bee7f7d2211adafd528.jpg" border=0 small="0"></p>
<p>在数字电视系统中，为了能有效地从众多的数据包中组织起SI信息，而使用了很多的标识。有Network_id(网络标识)、Original_network_id(原始网络标识)、Transport_stream_id(传输流标识)、Service id(业务标识)、eventid_id(事件标识)、Bouquet_id(业务群组标识)。这些标识是作为信息查找定位用的，例如：要在一个TS里找出一个业务信息，就要知道这个业务信息在那个网络里、在哪个TS里和这个业务信息在这个流里的标识，这样一来，通过层层过滤，就能精确地定位描述这个业务信息的位置，并把它们找出来进行数据组织。图1就非常清楚地表明了这种查找思路。</p>
<p>一个网络信息由network_id来定位。</p>
<p>一个TS由network_id、Original_network_id、Transport_stream_id来定位，标明这个流在那个网络播发，它原属那个网络，并给它加上标识。</p>
<p>一个业务由network_id、Original_network_id、Transport_stream_id、service_id来定位，标明这个业务在那个网络播发，它原属那个网络和那个流，并给它加上标识。这体现在SDT表中。</p>
<p>一个事件由network_id、Original_network_id、Transport_stream_id、service_id、event_id来定位，标明这个事件在那个网络播发，它原属那个网络和那个流及那个业务，并给它加上标识。这体现在EIT表中。</p>
<p>据此，根据各个SI表的功能，各表的ID结构如下：</p>
<p>NIT：network_id、Original_network_id、Transport_stream_id 、service_id。</p>
<p>SDT：Original_network_id、Transport_stream_id 、service_id。</p>
<p>EIT：Original_network_id、Transport_stream_id 、service_id、event_id。</p>
<p>BAT：bouquet_id 、Original_network_id 、Transport_stream_id 、service_id。</p>
<p>另外，还有一个PID（包标识），它的作用是给每一个数据包打上一个标记，TS承载有视频数据、音频数据、PSI和SI信息数据、图文电视数据、字幕数据、数据广播数据、交互业务数据、CA系统的控制信息数据等等，除了PSI和SI信息数据和CA系统的控制信息数据外，其他的数据的PID都是通过PMT表给出的，CA系统的控制信息数据的PID是由CAT表给出的，而承载了PSI和SI信息的各种表的PID值是固定分配的。如下表</p>
<p>表&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; PID值</p>
<p>PAT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 0X0000<br>CAT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 0X0001<br>TSDT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; 0X0002<br>NIT、ST&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0X0010<br>SDT、BAT、ST&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0X0011<br>EIT、ST&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0X0012<br>RST、ST&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0X0013<br>TDT、TOT、ST&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0X0014<br>DIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0X001E<br>SIT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; 0X001F</p>
<p>由于这些表是分配了固定的PID值，所以机顶盒就可以根据这些PID值来辨认出是什么表，并读取表中的描述参数来生成EPG信息和完成各种数据的组织、解码出所需要的节目和信息。</p>
<p>2、表的构成</p>
<p>表是组成SI信息的一种数据结构。在TS中有很多不同节目的数据包，解码器如何确定哪个数据包属于某个节目？其答案就是在TS中的PSI和SI信息里，这些信息精确地指引出获得某节目与该节目数据包的PID之间的关系。</p>
<p>由MPEG-2定义的TS里面，数据包携带了两类信息：一是音、视频等素材的数据，二是PSI表。具有给定PID的数据包的有序排列就形成了TS流。PSI表里的承载的内容主要是TS（本节目流）的描述参数。由MPEG-2定义的PSI主要包含有三个表：PAT、PMT、CAT。每个表都可作为一个或多个TS包的净荷插入TS中传送。</p>
<div forimg="1"><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/f96571c9e811a0307e3e6f0b.jpg" border=0 small="0"><br>一个TS数据包的净荷为188个字节，当一个PSI/SI表的字节长度大于184字节时，就要对这个表进行分割，形成段（section）来传送。分段机制主要是将一个数据表分割成多个数据段。在PSI/SI表到TS包的转换过程中，段起到了中介的作用。由于一个数据包只有188字节，而段的长度是可变的，EIT表的段限长4096字节，其余PSI/SI表的段限长为1024字节。因此，一个段要分成几部分插入到TS包的净荷中。如图2所示。</div>
<div forimg="1">PSI/SI表的构成是：一个表由一个或多个子表构成，表用table_id来标识；不同的子表由table_id和table_id_extension来区分（具有相同的table_id和不同的table_id_extension）；一个子表由一个或多个段构成（具有相同的table_id和table_id_extension，不同section_number来区分）；每个段由多个TS数据包的数据组成。每个段具有一个完整的数据结构，表的重要参数----描述符在段里传送。图3所示是SDT表的结构。<br>
<div forimg="1"><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/739f49250902c0264d088d10.jpg" border=0 small="0"><br>
<div forimg="1">
<div forimg="1"><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/352d12b6d53f65d330add111.jpg" border=0 small="0"><br>（1024）时，可把子表分割成两个或更多个段， 并通过section_number来区分，如图3-1所示。</div>
<div forimg="1">不同的信息表在TS中通过PID来区分，具有相同PID的不同表由table_id（table_id是表标识）来区分，属于同一个table_id的不同子表由table_id_extension、版本号(version_number)进行区分，属于同一个子表的不同段由section_number区分。表的扩展标识符有：network_id、oringinal_network_id、boquet_id、tansport_stream_id、service_id等。</div>
<div forimg="1">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于NIT表的子表具有相同的table_id、network_id和version_number。</div>
<div forimg="1">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于BAT表的子表具有相同的table_id、bouquet_id和version_number。</div>
<div forimg="1">l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于SDT表的子表具有相同的table_id、oringinal_network_id、tansport_stream _id和version_number。</div>
<div forimg="1">
<p>l&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于EIT表的子表具有相同的table_id、oringinal_network_id、tansport_stream _id、 service_id和version_number。</p>
<p>&nbsp;&nbsp;&nbsp; 以EIT表为例。EIT的PID是0X0012，当它的table_id=0X4E时，EIT描述的是在当前TS中的当前/后续（EIT present/following）事件信息；table_id=0X4F时，EIT描述的是在其它TS中的当前/后续（EIT present/following）事件信息。这两个不同的描述形成了EIT的两个表。每个表分为两个段，一个段用来描述当前正在播放的事件，另一个段用来描述即将播放的事件。此时两个段的table_id、service_id、tansport_stream_id是相同的，但section_number不相同，section_number 0x00用来描述当前事件，section_number 0x01描述下一个事件。</p>
</div>
<div forimg="1">⑴ 网络描述表（NIT）的作用</div>
<div forimg="1">在MPEG2中由于并没有对NIT表进行定义，所以在PSI中NIT表内容是私有的，但在DVB中给NIT表作了明确的定义，所以NIT表是一个全局表，就是一个数字电视系统只对应两个NIT表，分别为当前网络表（table_id=0X40）和其他网络表（table_id=0X041），每个不同的网络视其频点数(1个TS=1个频点)的多少对应一个或多个子表，通过network_id来区分。</div>
<div forimg="1">
<p>&nbsp;&nbsp;&nbsp; NIT表主要是提供有关物理网络的信息，网络信息表传送本网络以及与此有关的其它网络的一些信息。每个网络都有唯一的识别符（network_id）。网络信息表主要携带：网络识别符(Network_ID)、网络名称、传输系统参数(有线传输系统参数包括：频率、调制方式、FEC外码、符号率、FEC内码)、节目业务类型及Service_ID等信息。机顶盒只要调谐到携带NIT表的传送流中，即可提取其它网络的参数，一般解码器便可根据提取出来的信息，自动搜索频道。</p>
<p>&nbsp;&nbsp;&nbsp; 这里说一说network_id和oringinal_network_id的分别。每个运营商都需要注册唯一的network_id，假设中央电视台的network_id=0X01，广州电视台的network_id=0X02&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 。当中央电视台直接播发自己的节目时，network_id=oringinal_network_id，如果由广州电视台转播中央电视台的节目时，那么network_id=0X02，oringinal_network_id=0X01。也就是说oringinal_network_id等于节目原发运营商的network_id。</p>
</div>
<div forimg="1">
<p>⑵&nbsp;&nbsp;&nbsp;&nbsp; 业务描述表（SDT）的作用</p>
</div>
<div forimg="1">
<p>SDT表是由DVB定义的，是一个SI表，因此它是一个全局表，一个数字电视系统对应两个SDT表，分别为当前流（actual transport）表（table_id=0X42）和其他流(other transport)表（table_id=0X46）。每一个TS对应一个子表（也有对应多个子表的，如同一个TS但业务来自不同的original_network），通过tansport_stream_id和original_network_id来区分。图4就是一个SDT表的构成图。从图可看出，这个SDT表由两个表组成，一个是当前流表，只有一个子表；另一个是其他流表，由三个子表组成，每个流对应一个子表。</p>
<div forimg="1">
<div forimg="1">
<p><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/dfb327000822eef1267fb5e6.jpg" border=0 small="0">&nbsp;<img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/d4360900ffa707211c9583ec.jpg" border=0 small="0">&nbsp;<img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/7d7009ed35a10a0063d09fef.jpg" border=0 small="0"></p>
<p>SDT表用于描述系统中业务的名称、业务提供者、是否有相应的事件描述表等方面的信息；业务描述表可以描述当前传输流，也可以描述其他传输流，这由表的Table_ID来区分。业务描述表提供了如下的信息：属于哪一个节目业务群；节目业务的类型，如PAL、NTSC、SECAM、调频广播、图文电视、准视频点播等；节目业务的提供者；可以接收该业务的国家和不可以接收该业务的国家；指向特定的链接信息；实现准视频点播的指导信息；实现多画面的控制信息；指示使用的加密系统；给出实现交互式回传信道的电话号码；提供多语种的节目业务名称和广播者以及私有数据。但最常用的是业务列表，即对业务名称的描述，如中央1台、广州新闻台、珠江台等等。</p>
<p>⑶&nbsp;&nbsp;&nbsp;&nbsp; 事件信息表（EIT）的作用</p>
<p>EIT表是由DVB定义的，是一个SI表，因此它是一个全局表，一个数字电视系统每一个业务对应两种EIT表。一是EIT present/following表（描述当前事件/后续事件），一个业务对应着一个EIT present/following表，EIT present/following表分为当前流表（table_id=0X4E）和其他流表（table_id=0X4F），每一个流通常对应6个（有6个业务）EIT present/following子表，每个子表由两个段组成，分别是EIT present段和EIT following段，section_number= 0x00的段描述当前播放的事件， section_number= 0x01段描述后续播放事件，图5所示。其他流表结构与当前流表相同；二是EIT schedule（时间表）表，一个业务最多可对应16个EIT schedule表，那么每个流通常最多可对应6（业务数）&#215;16=96个子表，每个子表由256个段组成（由于分段号是8个比特，所以最多只能有256个分段），。</p>
<p>对于EIT schedule表，它是用作描述一个业务在一段时间（可以是一天、一周，最大可以是64天，根据冗余带宽来进行设定）内所播放的节目安排，节目的播出安排是以时间和节目简介作为描述的。时间及内容是描述一个事件的最基本元素，例如：把一个业务所播放的每一个节目都看成是一个事件，那么每一个节目开始播放的时间和播放时间的长度及事件的内容就是该事件的基本元素，EIT schedule子表就是用这一基本元素来描述每一个事件并产生某一段时间内要发生的所有事件的列表，因此EIT schedule子表的信息量很大（EIT表的段限长4096字节），由256个section组成，所以又引入了segment（片段）的概念。把256个段分成32个segment；一个segment由8个section（分段）组成，每个segment可以描述3个小时的事件信息，也就是说，一个EIT schedule表由32个片段组成，每个片段由8个分段组成，通过section_number来区分，那么每个子表可描述32*3=96小时（4天）的事件信息，由于一个业务最多可对应着16个EIT schedule表，则对于一个业务来说最多可以描述16(0X50----0X5F)*4=64天的事件信息。这里，segment相当于一个事件组，section是事件组内具体的一个事件。EIT schedule表也分为当前流表（table_id=0X50---0X5F 共16个）和其他流表（table_id=0X60---0X6F 共16个）， EIT schedule表是可选的（即系统可以发送此表也可以不发送此表），事件信息按时间顺序排列。</p>
<p>EIT表包含事件或节目的有关数据，如事件的名称、开始时间、持续时间、运行状态等。事件信息表提供如下信息：节目段的标识号、起始时间、持续时间、播放状态、是否加密；指向特定信息的链接信息；节目段多语种的简短介绍；节目段的详细介绍；两段同样节目段的时间偏移；基本码流类型介绍，如视频的幅型比、伴音的类型、字幕的类型等；使用的加密系统介绍；节目类型介绍，如电影/戏剧、新闻、综艺、体育、少儿、音乐、艺术、社会政治、文教等；节目限定年龄的级别介绍；给出实现交互式回传信道的电话号码；为满足各节目段的码率而提供的缓存大小信息及私有数据。事件信息中提供了类似于广播电视报所提供的节目表的内容，根据EIT及其它表所提供的信息，可以做出各种EPG功能，如按节目类型检索、按时间检索及对某类节目的锁定等。可以说EIT表是提供EPG信息的主要表，也是结构最复杂的SI表。</p>
<p>在EIT present/following表中，每一事件都用一个event_id来标识它，每一个事件的顺序关系（当前正在发生的事件/后续发生的事件）就由EIT present/following来描述。</p>
<p>那么如何来识别当前正在发生的事情和后续发生的事情呢？那是通过event_id来标识的，如图5所示。图中event_id=0X49表示当前正在发生的事件；event_id=0X4A表示后续发生的事件。那么在当前事件完成进入后续事件时，此时的后续事件变成当前事件，后续事件将由一个新的事件代替。这一变化是使用version_number来加以描述的。例如：</p>
<p>当前播出 19：00----19：30 新闻联播 event_id=0X49；</p>
<p>后续播出 19：31----20：00 动画片 event_id=0X4A，此时version_number=0</p>
<p>设新的后续 21：01---21：45 曲艺节目。当新闻联播完成后，则变化为：</p>
<p>当前播出 19：31----20：00 动画片 event_id=0X49；</p>
<p>后续播出 21：01----21：45 曲艺节目 event_id=0X4A，此时version_number=1<br><span><br>图</span><span>6</span><span>是由</span><span>SDT</span><span>表和</span><span>EIT</span><span>表所产生的</span><span>EPG</span><span>信息，图</span><span>7</span><span>是由</span><span>EIT</span><span>表所产生的一个节目频道的节目播出时间表。<br><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/30cf94a96c02e496ca130cd1.jpg" border=0 small="0">&nbsp;&nbsp;&nbsp;</span><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/3fec5bf34bccfa34b17ec5d2.jpg" border=0 small="0">&nbsp;<img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/5807fedebe52a234485403df.jpg" border=0 small="0"></p>
<p><span>EIT</span><span>表是</span><span>SI</span><span>表中结构最复杂的表，图</span><span>8</span><span>是它的结构图。</span></p>
<p><span>机顶盒通常都有一个&#8220;节目指南&#8221;的按钮，按动它就可以读取</span><span>EIT&nbsp;</span><span><span>schedule</span></span><span><span>自表里的信息，显示某一个业务在某段时间内的所有事件列表。</span></span></p>
<p><span><span>⑷<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span></span><span>业务组关联表（</span><span>BAT</span><span>）的作用</span></p>
<p><span><span>BAT</span></span><span><span>表是由</span></span><span><span>DVB</span></span><span><span>定义的，是一个</span></span><span><span>SI</span></span><span><span>表，因此它是一个全局表，一个数字电视系统只对应一个</span></span><span><span>BAT</span></span><span><span>表，其</span></span><span><span>table_id=0X<st1:chmetcnv unitname="a" sourcevalue="4" hasspace="False" negative="False" numbertype="1" tcsc="0">4A</st1:chmetcnv></span></span><span><span>。一个节目类别对应一个段。</span></span><span>为了让受众能更方便地在众多的节目中寻找出自己喜欢的节目，往往需要提供一种把众多的节目频道进行分类的方法（一个类相当一个节目组）。例如把电影频道归为&#8220;家庭影院&#8221;的类别，把电视连续剧归为&#8220;电视剧场&#8221;的类别等等，</span><span>BAT</span><span>表就提供了这一功能，每一个类别都用一个</span><span>bouquet_id&nbsp;</span><span>来标识。它包括了节目业务名称（类别）及节目组所包含的节目清单（节目列表）。</span><span>BAT</span><span>表在</span><span>SI</span><span>信息中属于可选表。</span></p>
<p><span>BAT</span><span>表还支持一个特别的描述符，称为国家获得性描述符。此描述符的意义是：运营商可能出于运营的需要，把一些业务提供给特定（国家）的人群收看，而不希望给其他（其他国家）的人群收看，那么，就可以利用国家获得性这一描述符，在其他人群收看节目时不显示这些业务。这个描述符同样支持</span><span>SDT</span><span>表，不过在</span><span>SDT&nbsp;</span><span>表中指的是某一个业务，而不是一个业务组。所以，</span><span>BAT</span><span>表概括地说是提供给不同观众不同组合节目的一种方法。</span></p>
<p><span>⑸</span>&nbsp;<span>其他表</span></p>
<p><span>对于</span><span>PAT</span><span>、</span><span>PMT</span><span>和</span><span>CAT</span><span>表，都是由</span><span>MPEG-2</span><span>定义的，是</span><span>PSI</span><span>里面的表，所以这三个表都不是全局表，它们存在在每一个</span><span>TS</span><span>中。</span><span>PSI</span><span>信息使用这</span><span>3</span><span>个表来定义码流的结构，一个</span><span>TS</span><span>对应一个</span><span>PAT</span><span>表；一个</span><span>CA</span><span>系统和一个</span><span>TS</span><span>对应一个</span><span>CAT</span><span>表，</span><span>CAT</span><span>表的</span><span>PID</span><span>值总是</span><span>1</span><span>，每个</span><span>CAT</span><span>都只给出其所在流的</span><span>EMM</span><span>（包括携带组密钥的</span><span>EMM</span><span>和携带产品密钥的</span><span>EMM</span><span>）包的</span><span>PID</span><span>等信息；一个业务（节目频道）对应一个</span><span>PMT</span><span>表，一个</span><span>TS</span><span>对应多个</span><span>PMT</span><span>（视流中所携带的业务数而定）且只对应本流的业务。</span></p>
<p><span>PAT</span><span>的</span><span>PID</span><span>是</span><span>0</span><span>，它是</span><span>PSI</span><span>信息的根，要查找信息时首先必须从</span><span>PAT</span><span>开始，表中列出了传送码流中所有节目所对应的</span><span>PMT</span><span>的</span><span>PID</span><span>，可根据这些</span><span>PID</span><span>找到相应的</span><span>PMT</span><span>包。在</span><span>PMT</span><span>表中又可以找到与节目有关的所有基本码流，如视频、音频、</span><span>ECM</span><span>和数据等有关信息的</span><span>PID</span><span>，然后把这些标有这一</span><span>PID</span><span>的数据包组织起来通过解码，把节目或数据还原出来。</span></p>
<p><span>以上</span><span>PSI</span><span>的几个表和</span><span>NIT</span><span>表是解码所必需的表，而</span><span>SDT</span><span>和</span><span>EIT</span><span>是构成业务信息所必需的表。</span></p>
<p><span>SI</span><span>还有其他的表，如：</span><span>TDT</span><span>表，称为时间日期表，它给出了当前的时间和日期的信息，有时也可作为机顶盒解码时钟的更新；</span><span>RST</span><span>表，称为运行状态表，属于可选表，它用于快速更新某节目或某些节目的运行参数，</span><span>RST</span><span>只有在状态或节目变更时才发送一次；</span><span>ST</span><span>表，称为填充表，属于可选表，它用来替代不传送的表。</span></p>
<p><span>⑹</span>&nbsp;<span>描述符</span></p>
<p><span>描述符是用来携带节目要素和</span><span>TS</span><span>流等的各种参数的信息结构、语法与语义，描述符是</span><span>PSI/SI</span><span>表的构成主体，</span><span>PSI/SI</span><span>表的主要意义就是传送这些描述符，为机顶盒提供相关业务描述与运行参数，可以认为</span><span>SI</span><span>表是舟而描述符是舟上的货物。描述符的通用结构都是以</span><span>descriptor_tag (</span><span>描述符标记</span><span>)</span><span>字段与紧跟其后的</span><span>descriptor_length</span><span>（描述符长度）字段开始。每个</span><span>SI</span><span>表通常都使用特定的描述符，但也不限制这些描述符在其他表中使用。</span></p>
<p><span>描述符是随使用它的</span><span>SI</span><span>表一起发送的。</span></p>
<p><span>描述符以及在它们的</span><span>PSI/SI</span><span>表中的位置见下表<br></span></p>
<div forimg="1"><img src="http://hiphotos.baidu.com/kkndyyralf/pic/item/2d9b370b7bb84c3894ca6baa.jpg" border=0 small="0"><br>
<p><span>在</span><span>PSI/SI</span><span>表里，我们通常都看到一个循环语句，如：</span></p>
<p><span>for(I=0;I&lt;N;I++){</span></p>
<p><span>descriptor()</span></p>
<p><span>}</span></p>
<p><span>这个循环语句是用来引导机顶盒读取描述参数用的，以</span><span>SDT</span><span>子表为例，由于一个</span><span>SDT</span><span>子表里面包含了对多个业务的描述，每个业务的都使用了</span><span>Multilingual_service_name_descriptor</span><span>和</span><span>service_descriptor</span><span>描述符，也就是说一个</span><span>SDT</span><span>子表里同样的描述符被使用了多次（也可以理解为，一个描述符里存有多个描述参数），通过循环语句来对描述符进行重复有序的读取，来提取里面的描述参数，直到读完为止。</span></p>
<p><strong><span>网络信息表（</span><span>NIT</span></strong><strong><span>）的段数据结构：</span></strong></p>
<p><span>Netwok_information_section(){<span>&nbsp;</span></span><span>网络信息段</span></p>
<p><span>Table_id<span>&nbsp;&nbsp;&nbsp;</span>8bit<span>&nbsp;</span></span><span>表标识</span></p>
<p><span>Section_syntax_indicator<span>&nbsp;</span>1bit&nbsp;</span><span>段序列指示</span><span>(</span><span>标记位</span><span>),</span><span>此值</span><span>=1</span><span>时</span><span>,</span><span>规定从</span><span>section</span><span>第</span><span>43</span><span>位开始的</span><span>5</span><span>位是版本号</span></p>
<p><span>Reserved_future_use<span>&nbsp;</span>1bit<span>&nbsp;</span></span><span>保留将来使用字段</span></p>
<p><span>Reserved<span>&nbsp;&nbsp;&nbsp;</span>2bit<span>&nbsp;</span></span><span>保留字段</span></p>
<p><span>Section_length 12bit<span>&nbsp;</span></span><span>段长度</span></p>
<p><span>Network_id<span>&nbsp;</span>16bit<span>&nbsp;</span></span><span>网络标识</span></p>
<p><span>Reserved<span>&nbsp;&nbsp;&nbsp;</span>2bit<span>&nbsp;</span></span><span>保留字段</span></p>
<p><span>Version_number<span>&nbsp;&nbsp;&nbsp;</span>5bit<span>&nbsp;</span></span><span>表版本号，作为表更新机制</span></p>
<p><span>Current_next_indicator<span>&nbsp;</span>1bit<span>&nbsp;</span></span><span>当前</span><span>/</span><span>下一个有效指示位（标记位），表示当前表是否有效，如果</span><span>Current_next_indicator</span><span>为</span><span>1,</span><span>则当前表有效</span><span>;0</span><span>表示当前表无效</span><span>.</span></p>
<p><span>Section_number<span>&nbsp;</span>8bit<span>&nbsp;</span></span><span>当前段段号</span></p>
<p><span>Last_section_number<span>&nbsp;</span>8bit<span>&nbsp;</span></span><span>最后段号</span><span>(</span><span>反映了这个子表由多少个段组成，如其值为</span><span>0X01</span><span>那么表示这个子表由两个段组成</span><span>)</span></p>
<p><span>Reserved_future_use<span>&nbsp;&nbsp;&nbsp;</span>4bit<span>&nbsp;</span></span><span>保留将来使用字段</span></p>
<p><span>Network_description_length<span>&nbsp;</span>12bit<span>&nbsp;</span></span><span>网络描述符长度</span></p>
<p><span>For(I=0;I&lt;N;I++){<span>&nbsp;</span></span><span>获取网络</span></p>
<p><span>Descriptor()<span>&nbsp;&nbsp;&nbsp;</span></span><span>读取网络描述参数（网络名称描述符、连接描述符）</span></p>
<p><span>}</span></p>
<p><span>reserved_future_use<span>&nbsp;</span>4bit<span>&nbsp;</span></span><span>保留将来使用字段</span></p>
<p><span>transport_stream_loop_length<span>&nbsp;</span>12bit<span>&nbsp;</span></span><span>传输流循环长度</span></p>
<p><span>for(I=0;I&lt;N;I++){<span>&nbsp;</span></span><span>获取传输流（整个系统的传输流）</span></p>
<p><span>transport_stream_id<span>&nbsp;</span>16bit<span>&nbsp;</span></span><span>传输流标识</span></p>
<p><span>original_network_id<span>&nbsp;</span>16bit<span>&nbsp;</span></span><span>原始网络标识</span></p>
<p><span>reserved_future_use<span>&nbsp;</span>4bit<span>&nbsp;</span></span><span>保留将来使用字段</span></p>
<p><span>transport_descriptors_length<span>&nbsp;</span>12bit&nbsp;</span><span>传输描述符长度</span></p>
<p><span>for(j=0;j&lt;N;j++){<span>&nbsp;</span></span><span>获取传输流的描述子（有线传送系统描述符、业务列表描述符等）</span></p>
<p><span>descriptor()<span>&nbsp;</span></span><span>读取描述参数</span></p>
<p><span>}</span></p>
<p><span>}</span></p>
<p><span>CRC_32<span>&nbsp;</span>32bit<span>&nbsp;</span></span><span>循环校验码</span></p>
<p><span>}</span></p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</span></span>
<img src ="http://www.cppblog.com/elva/aggbug/96616.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2009-09-18 10:46 <a href="http://www.cppblog.com/elva/archive/2009/09/18/96616.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ffmpeg和mencoder的编译方法 </title><link>http://www.cppblog.com/elva/archive/2009/08/03/92025.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Mon, 03 Aug 2009 06:30:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2009/08/03/92025.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/92025.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2009/08/03/92025.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/92025.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/92025.html</trackback:ping><description><![CDATA[<span class=Apple-style-span style="WORD-SPACING: 0px; FONT: 16px Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px"><span class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana; TEXT-ALIGN: left">
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">**************ffmpeg的编译****************</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">1。首先获取ffmpeg 如果已经获取了ffmpeg的tar包那第一步可以跳过</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">很多人找不到怎么下载,其实之前ffmpeg可以通过cvs下载，不过最近他已经换成了更加强大的svn</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">如何使用SVN我这里不再介绍，网上还有大量的安装和使用的文章可以借鉴，这里简单罗列几个SVN辅助的软件：</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">SubVersion，从 http://subversion.tigris.org/ 下载，支持linux，我们这里就装这个</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">TortoiseSVN，从 http://tortoisesvn.tigris.org/ 下载，是很不错的SVN客户端程序，为windows外壳程序集成到windows资源管理器和文件管理系统的Subversion客户端，用起来很方便，commit动作变得就像Winrar右键压缩一样方便。</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>ok，先装subversion，记住最好之前装过apr和apr-util，在apache.org网站能下到</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">wget http://subversion.tigris.org/downloads/subversion-1.3.2.tar.gz<br>tar zvxf subversion-1.3.2.tar.gz<br>cd subversion-1.3.2<br>./configure --with-apr=/usr/local/apr-httpd --with-apr-util=/usr/local/apr-util-httpd/<br>make<br>make install</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>到此，我们就可以通过svn命令获取最新的ffmpeg了</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">你会发现在你所在的目录，自动出现一个ffmpeg的目录，就是你下载的源代码。</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>我们还不能这么快编译ffmpeg，应该如果要让ffmpeg支持更多格式的转换，还需做一些前期工作</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>2.支持mp3，linux当然是lame，下载解压<br>tar zxvf lame-3.97b3_.tar.gz<br>cd lame-3.97.1<br>./configure --prefix=/usr&nbsp; --enable-shared<br>make<br>make install<br>这里推荐尽量装在/usr下，默认是装在/usr/local下。这样ffmpeg编译都能顺利的找到库文件</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>3.支持Ogg和Vorbis:<br>as4你可以安装一下如下tar包<br>libvorbis, libvorbis-devel,libogg, libogg-devel<br>tar jxvf libvorbis-1.1.1-1-src.tar.bz2<br>cd libvorbis-1.1.1-1<br>./configure --prefix=/usr&nbsp; --enable-shared<br>make<br>make install<br>其他的（libvorbis-devel,libogg, libogg-devel这三个tar直接解压就可以了用tar jxvf libvorbis-devel.........)</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">4.支持xvid x264，现在最流行的两种高质量的压缩格式<br>xvid的编译安装<br>下载 http://downloads.xvid.org/downloads/xvidcore-1.1.0.tar.gz<br>tar zvxf xvidcore-1.1.0.tar.gz<br>cd xvidcore-1.1.0/build/generic/<br>./configure --prefix=/usr --enable-shared<br>make<br>make install</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>***在安装X264之前必须安装nasm-0.98.39.tar.bz2 不然X264装不上去***<br>下载nasm-0.98.39.tar.bz2<br>tar jxvf nasm-0.98.39.tar.bz2<br>cd nams-0.98.39<br>./configure --prefix=/usr --enable-shared<br>make<br>make install</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">下载 x264-snapshot.tar.bz2<br>tar jxvf&nbsp; x264-snapshot.tar.bz2<br>cd&nbsp; x264-snapshot.tar.bz2<br>./configure --prefix=/usr --enable-shared<br>make<br>make install</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>5.AC3和dts编码的支持<br>as4系统似乎已经支持ac3编码，编译的时候只要加--enable-a52 --enable-gpl参数就行</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">libdts-0.0.2.tar.gz编译参数<br>tar zxvf libdts-0.0.2.tar.gz&nbsp;<br>cd libdts-0.0.2<br>./configure --prefix=/usr --enable-shared<br>make<br>make install</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>6.mpg4 aac格式支持，由于服务器还针对手机用户服务，所以，类似aac，mpg4铃声格式的支持，我们也得做。这里我们安装faad2和faac就行<br>下载请到http://www.audiocoding.com/modules/mydownloads/</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">***先编译FAAD2，然后在编译FAAC。有个先后顺序的***</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">//////////////////////////FAAD2的编译\\\\\\\\\\\\\\\\\\\\\\\\\\\\<br>tar zxvf&nbsp; faad2-2.5.tar.gz<br>cd faad2<br>在编译FAAD2时可能出现的错误，参照你的错误现象去修改</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">错误现象：</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">cd faad2<br>[root@TServer faad2]# autoreconf&nbsp; -ivf<br>autoreconf: Entering directory `.'<br>autoreconf: configure.in: not using Gettext<br>autoreconf: running: aclocal --force<br>autoreconf: configure.in: tracing<br>autoreconf: running: libtoolize --copy --force<br>autoreconf: running: /usr/bin/autoconf --force<br>autoreconf: running: /usr/bin/autoheader --force<br>autoreconf: running: automake --add-missing --copy --force-missing<br>configure.in: installing `./install-sh'<br>configure.in: installing `./missing'<br>common/mp4ff/Makefile.am: installing `./compile'<br>common/mp4ff/Makefile.am: installing `./depcomp'<br>plugins/Makefile.am:12: required directory plugins/bmp does not exist<br>plugins/xmms/src/Makefile.am:2: libdir was already defined in condition TRUE, which includes condition HAVE_BMP ...<br>configure.in:10: ... `libdir' previously defined here<br>plugins/xmms/src/Makefile.am:8: libdir was already defined in condition TRUE, which includes condition !HAVE_BMP ...<br>configure.in:10: ... `libdir' previously defined here<br>Makefile.am: installing `./INSTALL'<br>autoreconf: automake failed with exit status: 1</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">解决方案：<br>只要把BMP相关的编译条件（一般都是以if-else形式存在的，注意要把整个块都删除）都remove，就好了。<br>操作如下：<br>[root@TServer faad2]# cd plugins/<br>[root@TServer plugins]# grep -lr BMP *<br>Makefile.am<br>xmms/src/libmp4.c<br>xmms/src/Makefile.am<br>[root@TServer plugins]# vi Makefile.am<br>if HAVE_MPEG4IP_PLUG<br>if HAVE_XMMS<br>SUBDIRS = xmms mpeg4ip<br>else<br>SUBDIRS = mpeg4ip<br>endif #HAVE_XMMS<br>else<br>if HAVE_XMMS<br>SUBDIRS = xmms<br>else<br>SUBDIRS =<br>endif #HAVE_XMMS<br>endif #HAVE_MPEG4IP_PLUG<br>~<br>~<br>~<br>~<br>~<br>~<br>~<br>"Makefile.am" [dos] 13L, 200C 已写入&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>[root@TServer plugins]# grep -lr BMP *<br>xmms/src/libmp4.c<br>xmms/src/Makefile.am<br>[root@TServer plugins]# vi xmms/src/libmp4.c<br>/*<br>&nbsp;* MP4/AAC decoder for xmms<br>&nbsp;*<br>&nbsp;* OPTIONNAL need<br>&nbsp;* --------------<br>&nbsp;* libid3 (3.8.x - www.id3.org)<br>*/</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">#include &lt;pthread.h&gt;<br>#include &lt;gtk/gtk.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;string.h&gt;</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">#include "neaacdec.h"<br>#include "mp4ff.h"</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">#define MP4_DESCRIPTION "MP4 &amp; MPEG2/4-AAC audio player - 1.2.x"<br>#define MP4_VERSION&nbsp;&nbsp;&nbsp;&nbsp; "ver. 0.5-faad2-version - 22 August 2004"<br>#define MP4_ABOUT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Written by ciberfred"<br>#define BUFFER_SIZE&nbsp;&nbsp;&nbsp;&nbsp; FAAD_MIN_STREAMSIZE*64</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">static void&nbsp;&nbsp;&nbsp;&nbsp; mp4_init(void);<br>static void&nbsp;&nbsp;&nbsp;&nbsp; mp4_about(void);<br>static void&nbsp;&nbsp;&nbsp;&nbsp; mp4_play(char *);<br>static void&nbsp;&nbsp;&nbsp;&nbsp; mp4_stop(void);<br>"xmms/src/libmp4.c" [dos] 574L, 15762C 已写入<br>[root@TServer plugins]# ls<br>in_mp4&nbsp; Makefile.am&nbsp; mpeg4ip&nbsp; QCD&nbsp; QCDMp4&nbsp; xmms<br>[root@TServer plugins]# grep -lr BMP *<br>xmms/src/Makefile.am<br>[root@TServer plugins]# vi xmms/src/Makefile.am<br>if HAVE_BMP<br>libdir=$(shell pkg-config --variable=input-plugin-dir bmp)<br>local_CFLAGS=$(shell pkg-config --cflags bmp)<br>local_LDFLAGS=$(shell pkg-config --libs bmp)<br>else<br>local_CFLAGS=`$(XMMS_CONFIG) --cflags` -Wall<br>local_LDFLAGS=`$(XMMS_CONFIG) --libs`<br>libdir = `$(XMMS_CONFIG) --input-plugin-dir`<br>endif #HAVE_BMP<br>lib_LTLIBRARIES = libmp4.la</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">libmp4_la_CFLAGS = $(local_CFLAGS) -Wall \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; -I$(top_srcdir)/include -I$(top_srcdir)/common/mp4ff</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">libmp4_la_LIBADD = $(top_builddir)/libfaad/libfaad.la \<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $(top_builddir)/common/mp4ff/libmp4ff.la</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">libmp4_la_LDFLAGS = -module -avoid-version $(local_LDFLAGS) -lpthread</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">libmp4_la_SOURCES = libmp4.c mp4_utils.c aac_utils.c<br>~<br>~<br>"xmms/src/Makefile.am" [dos] 11L, 373C 已写入<br>[root@TServer plugins]# cd ..<br>[root@TServer faad2]# grep -lr BMP *<br>configure.in<br>[root@TServer faad2]# vi configure.in<br>&nbsp; AM_CONDITIONAL([HAVE_BMP], true)<br>fi</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">if test x$WITHDRM = xyes; then<br>&nbsp; AC_DEFINE(DRM, 1, [Define if you want to use libfaad together with Digital Radio Mondiale (DRM)])<br>&nbsp; AC_DEFINE(DRM_PS, 1, [Define if you want support for Digital Radio Mondiale (DRM) parametric stereo])<br>fi</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">AC_CONFIG_FILES(libfaad/Makefile)<br>AC_CONFIG_FILES(common/Makefile)<br>AC_CONFIG_FILES(common/mp4ff/Makefile)<br>AC_CONFIG_FILES(plugins/Makefile)<br>AC_CONFIG_FILES(plugins/xmms/Makefile)<br>AC_CONFIG_FILES(plugins/xmms/src/Makefile)<br>AC_CONFIG_FILES(plugins/mpeg4ip/Makefile)<br>AC_CONFIG_FILES(faad2.spec)<br>AC_CONFIG_FILES(frontend/Makefile)<br>AC_CONFIG_FILES(Makefile)<br>已查找到文件结尾；再从开头继续查找<br>AC_PROG_MAKE_SET<br>AC_CHECK_PROGS(RPMBUILD, rpmbuild, rpm)</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">AM_CONFIG_HEADER(config.h)</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">AC_ARG_WITH(xmms,[&nbsp; --with-xmms&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compile XMMS-1 plugin],<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WITHXMMS=$withval, WITHXMMS=no)</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>AC_ARG_WITH(drm,[&nbsp; --with-drm&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compile libfaad with DRM support],<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WITHDRM=$withval, WITHDRM=no)</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">AC_ARG_WITH(mpeg4ip, [&nbsp; --with-mpeg4ip&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; compile mpeg4ip plugin],<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WITHMPEG4IP=$withval, WITHMPEG4IP=no)</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">dnl Checks for header files required for mp4.h<br>AC_HEADER_STDC<br>AC_CHECK_HEADERS(stdint.h inttypes.h)<br>AC_CHECK_HEADERS(mathf.h)<br>AC_CHECK_HEADERS(float.h)<br>/BMP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp; fi</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">&nbsp; AM_CONDITIONAL(HAVE_XMMS, true)<br>else<br>&nbsp;AC_MSG_NOTICE(no xmms build configured)<br>&nbsp;AM_CONDITIONAL(HAVE_XMMS, false)<br>fi</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">if test x$WITHDRM = xyes; then<br>&nbsp; AC_DEFINE(DRM, 1, [Define if you want to use libfaad together with Digital Radio Mondiale (DRM)])<br>&nbsp; AC_DEFINE(DRM_PS, 1, [Define if you want support for Digital Radio Mondiale (DRM) parametric stereo])<br>fi<br>AC_CONFIG_FILES(libfaad/Makefile)AC_CONFIG_FILES(common/Makefile)AC_CONFIG_FILES(common/mp4ff/Makefile)AC_CONFIG_FILES(plugins/Makefile)<br>AC_CONFIG_FILES(plugins/xmms/Makefile)<br>"configure.in" [dos] 131L, 3776C 已写入<br>[root@TServer faad2]# grep -lr BMP *<br>[root@TServer faad2]# ls<br>aacDECdrop&nbsp; common&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; faad2.spec.in&nbsp;&nbsp;&nbsp; libfaad&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; README<br>AUTHORS&nbsp;&nbsp;&nbsp;&nbsp; configure.in&nbsp; frontend&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Makefile.am&nbsp; README.linux<br>bootstrap&nbsp;&nbsp; COPYING&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; include&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; NEWS&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TODO<br>ChangeLog&nbsp;&nbsp; docs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; in_mpeg4aac.nsi&nbsp; plugins<br>[root@TServer faad2]# autoreconf -vir<br>/usr/bin/autoreconf: unrecognized option `-r'<br>Try `/usr/bin/autoreconf --help' for more information.<br>[root@TServer faad2]# autoreconf -vif<br>autoreconf: Entering directory `.'<br>autoreconf: configure.in: not using Gettext<br>autoreconf: running: aclocal --force<br>autoreconf: configure.in: tracing<br>autoreconf: running: libtoolize --copy --force<br>autoreconf: running: /usr/bin/autoconf --force<br>autoreconf: running: /usr/bin/autoheader --force<br>autoreconf: running: automake --add-missing --copy --force-missing<br>configure.in: installing `./install-sh'<br>configure.in: installing `./missing'<br>common/mp4ff/Makefile.am: installing `./compile'<br>common/mp4ff/Makefile.am: installing `./depcomp'<br>Makefile.am: installing `./INSTALL'<br>autoreconf: Leaving directory `.'</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">cd faad2<br>autoreconf -vif<br>./configure --prefix=/usr --with-mp4v2 --enable-shared<br>make<br>make install</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">////////////////faac的编译\\\\\\\\\\\\\\\\\\\\\\\\</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">cd faac<br>faac-1.25，有两个地方需要修改，一是m4 macro文件，另外一个是需要对文件的格式及权限作一下处理:<br>错误现象 1：<br>[root@TServer faac]# autoreconf -vif<br>autoreconf: Entering directory `.'<br>autoreconf: configure.in: not using Gettext<br>autoreconf: running: aclocal --force<br>configure.in:10: warning: underquoted definition of MY_DEFINE<br>&nbsp; run info '(automake)Extending aclocal'<br>&nbsp; or see http://sources.redhat.com/automake/automake.html#Extending-aclocal<br>autoreconf: configure.in: tracing<br>autoreconf: running: libtoolize --copy --force<br>configure.in:10: warning: underquoted definition of MY_DEFINE<br>&nbsp; run info '(automake)Extending aclocal'<br>&nbsp; or see http://sources.redhat.com/automake/automake.html#Extending-aclocal<br>autoreconf: running: /usr/bin/autoconf --force<br>autoreconf: running: /usr/bin/autoheader --force<br>autoreconf: running: automake --add-missing --copy --force-missing<br>autoreconf: Leaving directory `.'<br>[root@TServer faac]# grep MY_DEFINE *<br>configure.in:AC_DEFUN(MY_DEFINE, [ AC_DEFINE($1, 1, [define if needed]) ])<br>configure.in:AC_CHECK_DECL(strcasecmp, MY_DEFINE(HAVE_STRCASECMP))<br>configure.in:&nbsp;&nbsp;&nbsp;&nbsp; MY_DEFINE(HAVE_LIBMP4V2)<br>configure.in:AC_CHECK_DECL(strchr, MY_DEFINE(HAVE_STRCHR))<br>configure.in:AC_CHECK_DECL(memcpy, MY_DEFINE(HAVE_MEMCPY))<br>configure.in:AC_CHECK_DECL(strsep, MY_DEFINE(HAVE_STRSEP))</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>解决方案1：<br>[root@TServer faac]# grep MY_DEFINE *<br>configure.in:AC_DEFUN(MY_DEFINE, [ AC_DEFINE($1, 1, [define if needed]) ])<br>configure.in:AC_CHECK_DECL(strcasecmp, MY_DEFINE(HAVE_STRCASECMP))<br>configure.in:&nbsp;&nbsp;&nbsp;&nbsp; MY_DEFINE(HAVE_LIBMP4V2)<br>configure.in:AC_CHECK_DECL(strchr, MY_DEFINE(HAVE_STRCHR))<br>configure.in:AC_CHECK_DECL(memcpy, MY_DEFINE(HAVE_MEMCPY))<br>configure.in:AC_CHECK_DECL(strsep, MY_DEFINE(HAVE_STRSEP))</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">把configure.in文件中的AC_DEFUN(MY_DEFINE, [ AC_DEFINE($1, 1, [define if needed]) ])<br>修改为 AC_DEFUN([MY_DEFINE], [ AC_DEFINE($1, 1, [define if needed]) ])<br>然后就可以autoreconf -ivf了。</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">错误现象2：<br>./configure的时候，会出现以下错误：<br>configure: creating ./config.status<br>config.status: creating common/Makefile<br>config.status: creating common/mp4v2/Makefile<br>config.status: creating \<br>.infig.status: error: cannot find input file: \</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>这个问题是文件的格式问题造成的，可以用一下方法处理：<br>[root@TServer faac]#find . -type f | xargs dos2unix</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">[root@TServer faac]#chmod * 777 -R</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">处理之后，就可以安装了。<br>&nbsp;<br>chmod +x bootstrap<br>./bootstrap<br>./configure --prefix=/usr --with-mp4v2 --enable-shared<br>make<br>make install</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">7.支持3gp格式，这也是现在好多手机支持的格式，所以也得支持编译</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">编译的时候加上--enable-amr_nb --enable-amr_wb参数就行，根据编译系统的提示，所以我们得下载一</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">些编译3gp所需得文件。<br>先在ffmpeg-0.4.9-p20051120/libavcoder/建三个目录<br>mkdir -p amr<br>mkdir -p amr_float<br>mkdir -p amrwb_float</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">下载http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26073-530_ANSI_C_source_code.zip<br>解压以后把里面的文件都拷贝到libavcodec/amr</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">下载http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-530_ANSI-C_source_code.zip<br>解压以后把里面的文件都拷贝到libavcodec/amrwb_float</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">下载http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-540_ANSI_C_source_code.zip<br>解压以后把里面的文件都拷贝到libavcodec/amr_float</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">修改libavcodec/amr/makefile 找到CFLAGS = -Wall -pedantic-errors -I. $(CFLAGS_$(MODE)) -D$(VAD) 换成CFLAGS = -Wall -I. $(CFLAGS_$(MODE)) -D$(VAD) -DMMS_IO</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>8.编译ffmpeg-0.4.9-p20051120<br>tar xvf ffmpeg-0.4.9-p20051120.tar<br>cd ffmpeg-0.4.9-p20051120<br>./configure --prefix=/usr --enable-gpl --enable-shared --enable-mp3lame --enable-amr_nb --enable-amr_nb-fixed --enable-amr_wb --enable-amr_if2 --enable-libogg --enable-vorbis --enable-xvid --enable-a52 --enable-a52bin --enable-dts --enable-pp --enable-faad --enable-faadbin --enable-faac --enable-x264 --enable-pthreads --disable-ffserver --disable-ffplay --cpu=CPU<br>make<br>make install<br></p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>小修正一下，如果上面的configure不行，在我的机器上得这样，可能由于版本的关系，<br>./configure --enable-gpl --enable-nonfree --enable-pthreads --enable-libfaac --enable-libfaad --enable-libmp3lame&nbsp; --enable-libx264 --enable-libxvid --enable-x11grab --prefix=/usr --enable-shared<br><br>补充1：<br>要是说在当在cpu是x86的情况下，不能编译过去，如果你真编译不过去，可以试着加上--cpu=CPU</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">补充2：<br>当遇到编译ffmpeg出错时，找到vi ffmpeg/libavcodec/x264.c删除x4-&gt;params.rc.b_cbr = 1;这一行</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">到此，一个ffmpeg编译好了，不过目前管方的ffmpeg还不支持wma9和rmvb，不过网上有很多解决方法。</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">ffmpeg的转换参数：<br>ffmpeg -y -i test.mpeg -ac 1 -acodec amr_nb -ar 8000 -s 320x240 -b 128 -r 15 test.3gp</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>*************************mencoder的编译********************************</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">mencoder安装篇</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">1、下载主程序： MPlayer-1.0rc1.tar.bz2</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">2、下载essential-20061022.tar.bz2，安装：<br>tar vjxf essential-20061022.tar.bz2<br>mv essential-20061022 /usr/lib/codes<br>chmod 644 /usr/lib/codes/*<br>chown root.root /usr/lib/codes/*</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">3、下载windows-essential-20061022.zip，安装：<br>unzip windows-essential-20061022.zip<br>mv windows-essential-20061022 /usr/lib/wincodes<br>chmod 644 /usr/lib/wincodes/*<br>chown root.root /usr/lib/wincodes/*</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">4、安装mplayer</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">tar vjxf MPlayer-1.0rc1.tar.bz2<br>cd MPlayer-1.0rc1<br>./configure --prefix=/usr&nbsp; --with-codecsdir=/usr/lib/codecs/&nbsp;&nbsp; --language=zh_CN<br>make<br>make install<br>如果你需要使用mplayer在linux下播放视频，还需要加上--enable-gui(图形界面)，不过这样就要安装多很多东西了，这里我们只使用它的mencoder，所以--enable-gui可以省略</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>mencoder的配置参数：<br>./configure --prefix=/usr&nbsp; --with-codecsdir=/usr/lib/codecs/&nbsp;&nbsp;&nbsp;&nbsp; --language=zh_CN</p>
<p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><br>mencoder转换参数：<br>mencoder /var/www/woyo/image.woyo.com/%inputfile% -o /var/www/woyo/image.woyo.com/%outputfile%&nbsp;&nbsp; -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=300:mbd=2:last_pred=3:dia=2:cmp=3:vb_strategy=1 -sws 3 -vf scale=400:300&nbsp; -ofps 30 -srate 22050 -lavfopts i_certify_that_my_video_stream_does_not_use_b_frames</p>
</span></span>
<img src ="http://www.cppblog.com/elva/aggbug/92025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2009-08-03 14:30 <a href="http://www.cppblog.com/elva/archive/2009/08/03/92025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TR101-290: DVB 系统测量标准</title><link>http://www.cppblog.com/elva/archive/2009/06/17/87859.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 17 Jun 2009 02:24:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2009/06/17/87859.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/87859.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2009/06/17/87859.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/87859.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/87859.html</trackback:ping><description><![CDATA[<span  style="color: rgb(42, 42, 42); font-family: 宋体; font-size: 14px; line-height: 25px; ">TR101-290: DVB 系统测量标准<br>TR101-290: DVB 系统测量标准。TR 101-290 定义的三个优先级，是码流监测的一项主要内容。通过这三个优先级的监测，可以检验被监测的码流是否符合MPEG-2 和DVB标准。这三个优先级都包含许多不同的参数。<br><br>PSI/SI: 数字电视业务信息,由PSI和SI两部分构成。PSI是MPEG-2规定的，它由PAT、PMT、CAT和NIT 4个表构成，其中PAT、PMT表最为重要。SI是DVB标准规定的，它由BAT、SDT、EIT、RST、TDT、TOT、ST、SIT和DIT 9个表构成，其中 BAT、SDT、EIT 和 TDT 是强制性的。PSI/SI 由&#8220;表&#8221;和&#8220;描述符&#8221;构成。表是PSI/SI 的基本结构，针对特定用途，PSI/SI 中规定了一系列表来实现它；表由变量和描述符组成。描述符提供了更多的描述功能。<br><br>星座图: 星座显示是矢量示波器显示的数字等价形式，它可显示 QAM 信号的同相(I)分量和正交(Q)分量。符号是一个特定调制系统中所传输的最小信息成分。对于 QAM-64，一个符号代表 6 个位，在图上绘制为一个点。<br><br>BER位误码率:位误码率是发生误码的位数与传输的总位数之比。<br><br>MER:调制误差比, MER 将接收符号(代表调制图案中的一个数字值)的实际位置与其理想位置进行比较。当信号质量降低时，接收符号距离理想位置更远，MER 测量值将会减小。<br><br>EVM:误差矢量幅度, EVM测量类似于 MER，但表达形式不同。EVM 表达为 RMS 误差矢量幅度与最大符号幅度的百分比值。信号缺陷增加时，EVM 将会增大，而 MER 则会减小。EVM 是在IQ(同相与正交)星座图上检测到的载波与其理论上的准确位置之间的距离，是&#8220;误差信号矢量&#8221;与&#8220;最大信号幅度&#8221;之比，表达为 RMS 百分比值。<br><br>RS错误:表示经过Reed Solomon纠错（简称RS）后，出现错误bit的包数 。<br><br>频率偏移:实际中心频率和理论中心频率的偏移。<br><br>SR偏移:实际符码率和理论符码率的偏移。<br><br>频道IQ反转:星座图IQ向量是否反转。<br>根据DVB最新的TR101290测试标准将DVB/MPEG-2 TS流的测试错误指示分为3个等级，<br>第一等级是可正确解码所必须的几个参数；<br>第二等级是达到同步后可连续工作必须的参数和需要周期监测的参数；<br>第三等级是依赖于应用的几个参数<br><br>第一级共 6种错误，包括：同步丢失错误、同步字节错误、PAT 错误、连续计数错误、PMT错误及 PID错误。<br><br>（1）传送码流同步丢失：连续检测到连续 5 个正常同步视为同步，连续检测到 2 个以上不正确同步则为同步丢失错误。传输流失去同步，标志着传输过程中会有一部分数据丢失，直接影响解码后的画面的质量。<br><br>（2）同步字节错误：同步字节值不是 0X47。同步字节错误和同步丢失错误的区别在于同步字节错误传输数据仍是 188或 204 包长，但同步字头的 0X47被其他数字代替。这表明传输的部分数据有错误，严重时会导致解码器解不出信号。<br><br>（3）PAT 错误：标识节目相关表 PAT 的 PID 为 0x0000，PAT 错误包括标识 PAT 的 PID 没有至少 0.5 s出现一次，或者 PID为 0x0000 的包中无内容，或者 PID为 0x0000 的包的包头中的加密控制段不为 0。PAT 丢失或被加密，则解码器无法搜索到相应节目；PAT 超时，解码器工作时间延。&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;&nbsp;<wbr><br>（4）连续计数错误：TS包头中的连续计数器是为了随着每个具有相同 PID的 TS包的增加而增加，为解码器确定正确的解码顺序。TS包头连续计数不正确，表明当前传输流有丢包、包重叠、包顺序错现象，会导致解码器不能正确解码。<br><br>（5）PMT 错误：节目映射表 PMT 标识并指示了组成每路业务的流的位置，及每路业务的节目时钟参考（PCR）字段的位置。PMT 错误包括标识 PMT 的 PID 没有达到至少 0.5 s 出现一次，或者所有包含PMT 表的 PID的包的包头中的加密控制段不为 0。PMT 被加密，则解码器无法搜索到相应节目；PMT 超时，影响解码器切换节目时间。<br><br>（6）PID错误：检查是否每一个 PID都有码流，没有 PID就不能完成该路业务的解码。<br><br>第二级共 6 种错误，包括：传输错误、CRC 错误、PCR 间隔错误、PCR 抖动错误、PTS 错误及CAT 错误。&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;&nbsp;<wbr><br>（1）传输错误：TS包头中的传送包错误指示为&#8220;1&#8221;，表示在相关的传送包中至少有 1 个不可纠正的错误位，只有在错误被纠正之后，该位才能被重新置 0。而一旦有传送包错，就不再从错包中得出其他错误指示。<br><br>（2）CRC 错误：在 PSI和 SI的各种表中出现循环冗余检测码 CRC 出错，说明这些表中的信息有错，这时不再从出现错误的表中得出其他错误信息<br><br>（3）PCR 间隔错误：PCR 用于恢复接收端解码本地的 27 MHz 系统时钟，如果在没有特别指明的情况下，PCR 不连续发送时间一次超过 100 ms 或 PCR 整个发送间隔超过 40 ms，则导致接收端时钟抖动或者漂移，影响画面显示时间。<br><br>（4）PCR 抖动错误：PCR 的精度必须高于 500 ns 或 PCR 抖动量不得大于&#177;500 ns。PCR抖动过大，会影响到解码时钟抖动甚至失锁。<br><br>（5）PTS错误：播出时间标记 PTS重复发送时间大于 70 ms，则对帧图像正确显示产生影响。PTS只有在 TS未加扰时方能接收。<br><br>（6）CAT 错误：TS 包头中的加密控制段不为 0，但却没有相应的 PID 为 0x0001 的条件接收表 CAT，或在 PID 为 0x0001 的包中发现非 CAT 表。CAT 表将指出授权管理信息 EMM包的 PID并控制接收机的正确接收，如果 CAT表不正确，就不能正确接收。<br><br><br>第三级共 10种错误，包括：NIT 错误、SI重复率错误、缓冲器错误、非指定 PID错误、SDT错误、EIT 错误、RST 错误、TDT 错误、空缓冲器错误及数据延迟错误。<br><br>第三等级错误并非是TS传输流的致命错误，但会影响一些具体应用的正确实施。<br><br>NIT 标识错误或传输超时，会导致解码器无法正确显示网络状态信息。<br><br>SDT 标识错误或传输超时，会导致解码器无法正确显示信道节目的信息。<br><br>EIT 标识错误或传输超时，会导致解码器无法正确显示每套节目的相关服务信息。</span>
<img src ="http://www.cppblog.com/elva/aggbug/87859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2009-06-17 10:24 <a href="http://www.cppblog.com/elva/archive/2009/06/17/87859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] MPEG-2码流结构</title><link>http://www.cppblog.com/elva/archive/2009/03/05/75653.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Thu, 05 Mar 2009 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2009/03/05/75653.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/75653.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2009/03/05/75653.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/75653.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/75653.html</trackback:ping><description><![CDATA[&nbsp;在数字电视系统中，模拟视音频信号按照MPEG-2的标准，经过抽样、量化及压缩编码形成基本码流ES，基本码流ES是不分段的连续码流。把基本码流分割成段，并加上相应的头文件打包形成的打包基本码流PES，PES包和包之间可以是不连续的。在传输时将PES包再分段打成有固定长度188B的传送码流TS或可变长度的节目流包（PS包）。PES只是PS转换为TS或TS转换为PS的中间步骤或桥梁，时MPEG-2数据流互换的逻辑结构。TS和PS这两种码流分别适应于不同的场合应用，节目流PS适合在相对出错较少的环境下使用，其长度是变化的，而传送流TS能够把多个节目在基于一个或多个时间标识的基础上构成一个流，传送流适合于出错较多的场合下使用。用数据包传输的优点是：网络中信息可占用不同的连接线路和简单暂存。通过数据包交织把多个数据流复用成一个新的数据流。便于解码器按照相应顺序对数据包进行灵活的整理，从而，为数据流同步和复用奠定了基础。MPEG-2的结构可分为压缩层和系统层，其中ES属于压缩层，PES和TS/PS属于系统层。<br>在PES层，主要是在PES包头信息中加入PTS(显示时间标签)和DTS（解码时间标签）用于视频、音频同步。而在TS流中，TS包头加入了PCR(节目时钟参考)，用于解码器的系统时钟恢复。在节目流PS包头中加入SCR,它的作用与PCR域相似。<br>&nbsp;&nbsp;&nbsp; ES是编码视频数据流或音频数据流，每个ES都由若干个存取单元（AU）组成，每个视频AU或音频AU都是由头部和编码数据两部分组成，1个AU相当于编码的1幅视频图像或1个音频帧，也可以说，每个AU实际上是编码数据流的显示单元，即相当于解码的1幅视频图像或1个音频帧的取样。<br>&nbsp;&nbsp;&nbsp; 我们知道，MPEG-2对视频的压缩产生I帧、P帧、B帧。把帧顺序I1帧-P4帧-B2帧-B3帧-P7帧-B5帧-B6帧的编码ES，通过打包并在每个帧中插入PTS/DTS标志，变成PES。在插入PTS/DTS标志时，由于在B帧PTS和DTS是相等的，所以无须在B帧多插入DTS。而对于I帧和P帧，由于经过复用后数据包的顺序会发生变化，显示前一定要存储于视频解码器的从新排序缓存器中，经过从新排序后再显示，所以一定要同时插入PTS和DTS作为从新排序的依据。例如，解码器输入的图像帧顺序为I1-P4-B2-B3-P7-B5-B6，但显示时P4一定要在B2、B3之后，在PST和DTS的指引下，经过缓存器从新排序，以从建视频帧顺序为：I1-B2-B3-P4- P7-B5-B6。<br>&nbsp;&nbsp;&nbsp; 将PES包再打成更小的具固定长度的TS包时在其包头位置加入了PCR和PID(包标识)。PID的值是由用户确定的，解码器根据PID把TS（多节目传输流)上不同节目的TS包区分出来，以重建原来的ES。另外，TS的包头包含一个4bit的连续计数器，连续计数器可对PID包传送顺序计数，据计数器读数，接收端可判断是否有包丢失及包传送顺序错误。所以TS的包头具有同步、识别、检错等功能。&nbsp;
<img src ="http://www.cppblog.com/elva/aggbug/75653.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2009-03-05 17:15 <a href="http://www.cppblog.com/elva/archive/2009/03/05/75653.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]MPEG-2视频编码技术漫谈</title><link>http://www.cppblog.com/elva/archive/2009/03/05/75652.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Thu, 05 Mar 2009 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2009/03/05/75652.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/75652.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2009/03/05/75652.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/75652.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/75652.html</trackback:ping><description><![CDATA[近年来，电视领域里发生了一系列巨大的变化，会议电视、VCD、数字电视以及高清晰度电视(HDTV)等新技术和新系统正迅速走进我们的生活。与传统的模拟电视相比，这些新系统的突出特点是采用了全数字的图像/声音处理技术。随着这些数字电视系统的日益成熟和不断发展，针对不同的应用领域，一系列相应的数字视频音频编码标准也迅速地被制定并不断得到完善，其中包括： 应用于会议电视及可视电话的H.261，用于静止图像压缩的JPEG，用于VCD的MPEG-1和用于广播电视、DVD以及HDTV的MPEG-2。与此同时，数字演播室标准及数字电视的质量评价标准也被制定出来。与其它几种标准相比，MPEG-2制定的时间稍晚，但却具有以下几个突出特点：所支持的图像分辨率最高，包括符合ITU-RRec.601(CCIR601)格式的标准分辨率的数字电视和更高分辨率的HDTV。支持包括高速体育运动在内的活动图像。所支持的应用最为广泛，既包括存储媒体中的DVD，广播电视中的数字广播电视和HDTV，还可应用于交互式的点播视频(VOD)和准点播视频(NVOD)，此外，还能够适配于ATM这种新兴的宽带通信网。 <br><br>本文着重介绍一下MPEG-2的标准组成结构，演播室标准，质量评价标准，特别是视频压缩技术。 <br><br>MPEG简介 <br>PEG是活动图像专家组(MovingPictureExportsGroup)的缩写，于1988年成立。目前MPEG已颁布了两个活动图像及声音编码的正式国际标准，分别称为MPEG-1和MPEG-2。 <br><br>MPEG-1标准是：在数字存储介质中实现对活动图像和声音的压缩编码，编码码率最高为每秒1.5兆比特，标准的正式规范在ISO/IEC11172中。MPEG-1所支持的输入图像格式是SIF格式。SIF有525/625两种格式：352x240x30和352x288x25。MPEG-1是一个开放的，统一的标准，在商业上获得了巨大的成功。尽管其图像质量仅相当于VHS视频的质量，还不能满足广播级的要求，但已广泛应用于VCD等家庭视像产品中。 <br><br>MPEG-2标准是：针对标准数字电视和高清晰度电视在各种应用下的压缩方案和系统层的详细规定，编码码率从每秒3兆比特～100兆比特，标准的正式规范在ISO/IEC13818中。MPEG-2不是MPEG-1的简单升级，MPEG-2在系统和传送方面作了更加详细的规定和进一步的完善。MPEG-2特别适用于广播级的数字电视的编码和传送，被认定为SDTV和HDTV的编码标准。MPEG-2还专门规定了多路节目的复分接方式。此外，MPEG-2还兼顾了与ATM信元的适配问题。 <br><br>MPEG-2标准 <br>MPEG-2标准目前分为9个部分，统称为ISO/IEC13818国际标准。各部分的内容描述如下： <br>一部分－ISO/IEC13818-1，System：系统，描述多个视频，音频和数据基本码流合成传输码流和节目码流的方式。 <br>二部分－ISO/IEC13818-2，Video：视频，描述视频编码方法。 <br>三部分－ISO/IEC13818-3，Audio：音频，描述与MPEG-1音频标准反向兼容的音频编码方法。 <br>四部分－ISO/IEC13818-4，Compliance：符合测试，描述测试一个编码码流是否符合MPEG-2码流的方法。 <br>五部分－ISO/IEC13818-5，Software：软件，描述了MPEG-2标准的第一、二、三部分的软件实现方法。 <br>六部分－ISO/IEC13818-6，DSM-CC：数字存储媒体-命令与控制，描述交互式多媒体网络中服务器与用户间的会话信令集。 <br>上六个部分均已获得通过，成为正式的国际标准，并在数字电视等领域中得到了广泛的实际应用。此外，MPEG-2标准还有三个部分：第七部分规定不与MPEG-1音频反向兼容的多通道音频编码；第八部分现已停止；第九部分规定了传送码流的实时接口。 <br><br>1990年成立的ATM视频编码专家组与MPEG在ISO/IEC13818标准的第一和第二两个部分进行了合作，因此上述两个部分也成为ITU-T的<br>标准，分别为：ITU-TRec.H.220系统和ITU-TRec.H.262视频。 <br>下面我们主要讨论一下MPEG视频编码系统，即ISO/IEC13818-2部分。MPEG-2视频编码 <br><br>　MPEG-2视频编码标准是一个分等级的系列，按编码图像的分辨率分成四个&#8220;级(Levels)&#8221;；按所使用的编码工具的集合分成五个&#8220;类(Profiles)&#8221;。&#8220;级&#8221;与&#8220;类&#8221;的若干组合构成MPEG-2视频编码标准在某种特定应用下的子集：对某一输入格式的图像，采用特定集合的压缩编码工具，产生规定速率范围内的编码码流。在20种可能的组合中，目前有11种是已获通过的，称为MPEG-2适用点。 <br>-　我们知道，当前模拟电视存在着PAL、NTSC和SECAM三大制式并存的问题，因此，数字电视的输入格式标准试图将这三种制式统一起来，形成一种统一的数字演播室标准，这个标准就是CCIR601，现称ITU-RRec.BT601标准。MPEG-2中的四个输入图像格式&#8220;级&#8221;都是基于这个标准的。低级(LowLevel)的输入格式的像素是ITU-RRec.BT601格式的1/4，即352x240x30(代表图像帧频为每秒30帧，每帧图像的有效扫描行数为240行，每行的有效像素为352个)，或352x288x25。低级之上的主级(MainLevel)的输入图像格式完全符合ITU-RRec.BT601格式，即720x480x30或720x576x25。主级之上为HDTV范围，基本上为ITU-RRec.BT601格式的4倍，其中1440高级(High-1440Level)的图像宽高比为4:3，格式为1440x1080x30，高级(HighLevel)的图像宽高比为16:9，格式为1920x1080x30。 <br><br>　在MPEG-2的五个&#8220;类&#8221;中，较高的&#8220;类&#8221;意味着采用较多的编码工具集，对编码图像进行更精细的处理，在相同比特率下将得到较好的图像质量，当然实现的代价也较大。较高类编码除使用较低类的编码工具外，还使用了一些较低类没有使用的附加工具，因此，较高类的解码器除能解码用本类方法编码的图像外，也能解码用较低类方法编码的图像，即MPEG-2的&#8220;类&#8221;之间具有后向兼容性。简单类(SimpleProfile)使用最少的编码工具。主类(MainProfile)除使用所有简单类的编码工具外，还加入了一种双向预测的方法。信噪比可分级类(SNRScalableProfile)和空间可分级类(SpatiallyScalableProfile)提供了一种多级广播的方式，将图像的编码信息分为基本信息层和一个或多个次要信息层。基本信息层包含对图像解码至关重要的信息，解码器根据基本信息即可进行解码，但图像的质量较差。次要信息层中包含图像的细节。广播时对基本信息层加以较强的保护，使其具有较强的抗干扰能力。这样，在距离较近，接收条件较好的情况下，可以同时收到基本信息和次要信息，恢复出高质量的图像；而在距离较远，接收条件较差的条件下，仍能收到基本信息，恢复出图像，不至造成解码中断。高级类(HighProfile)实际上应用于比特率更高，要求更高的图像质量时，此外，前四个类在处理Y，U，V时是逐行顺序处理色差信号的，高级类中还提供同时处理色差信号的可能性。 <br><br>目前的标准数字电视采用的是MP@ML主类和主级，而HDTV采用的是MP@HL主类和高级。下面，我们以MP@ML为例来说明一下MPEG-2视频编码系统原理及关键技术。<br><br>MPEG-2视频编码系统原理及关键技术 <br>　概括地说，MPEG-2图像压缩的原理是利用了图像中的两种特性：空间相关性和时间相关性。一帧图像内的任何一个场景都是由若干像素点构成的，因此一个像素通常与它周围的某些像素在亮度和色度上存在一定的关系，这种关系叫作空间相关性；一个节目中的一个情节常常由若干帧连续图像组成的图像序列构成，一个图像序列中前后帧图像间也存在一定的关系，这种关系叫作时间相关性。这两种相关性使得图像中存在大量的冗余信息。如果我们能将这些冗余信息去除，只保留少量非相关信息进行传输，就可以大大节省传输频带。而接收机利用这些非相关信息，按照一定的解码算法，可以在保证一定的图像质量的前提下恢复原始图像。一个好的压缩编码方案就是能够最大限度地去除图像中的冗余信息。 <br><br>MPEG-2中编码图像被分为三类，分别称为I帧，P帧和B帧。 <br><br>----I帧图像采用帧内编码方式，即只利用了单帧图像内的空间相关性，而没有利用时间相关性。I帧主要用于接收机的初始化和信道的获取，以及节目的切换和插入，I帧图像的压缩倍数相对较低。I帧图像是周期性出现在图像序列中的，出现频率可由编码器选择。 <br><br>　P帧和B帧图像采用帧间编码方式，即同时利用了空间和时间上的相关性。P帧图像只采用前向时间预测，可以提高压缩效率和图像质量。P帧图像中可以包含帧内编码的部分，即P帧中的每一个宏块可以是前向预测，也可以是帧内编码。B帧图像采用双向时间预测，可以大大提高压缩倍数。值得注意的是，由于B帧图像采用了未来帧作为参考，因此MPEG-2编码码流中图像帧的传输顺序和显示顺序是不同的。 <br><br>MPEG-2的编码码流分为六个层次。 <br>　从上至下依次为：视频序列层(Sequence)，图像组层(GOP：GroupofPicture)，图像层(Picture)，像条层(Slice)，宏块层(MacroBlock)和像块层(Block)。从图1中可以看到，除宏块层和像块层外，上面四层中都有相应的起始码(SC：StartCode)，可用于因误码或其它原因收发两端失步时，解码器重新捕捉同步。因此一次失步将至少丢失一个像条的数据。 <br><br>　序列指构成某路节目的图像序列，序列起始码后的序列头中包含了图像尺寸，宽高比，图像速率等信息。序列扩展中包含了一些附加数据。为保证能随时进入图像序列，序列头是重复发送的。 <br><br>　序列层下是图像组层，一个图像组由相互间有预测和生成关系的一组I、P、B图像构成，但头一帧图像总是I帧。GOP头中包含了时间信息。 <br><br>　图像组层下是图像层，分为I、P、B三类。PIC头中包含了图像编码的类型和时间参考信息。 <br><br>　图像层下是像条层，一个像条包括一定数量的宏块，其顺序与扫描顺序一致。MP@ML中一个像条必须在同一宏块行内。 <br><br>　像条层下是宏块层。MPEG-2中定义了三种宏块结构：4:2:0宏块4:2:2宏块和4:4:4宏块，分别代表构成一个宏块的亮度像块和色差像块的数量关系。<br><br>　4:2:0宏块中包含四个亮度像块，一个Cb色差像块和一个Cr色差像块；4:2:2宏块中包含四个亮度像块，二个Cb色差像块和二个Cr色差像块；4:4:4宏块中包含四个亮度像块，四个Cb色差像块和四个Cr色差像块。这三种宏块结构实际上对应于三种亮度和色度的抽样方式。 <br><br>　在进行视频编码前，分量信号R、G、B被变换为亮度信号Y和色差信号Cb、Cr的形式。4:2:2格式中亮度信号的抽样频率为13.5MHz，两个色差信号的抽样频率均为6.75MHz，这样空间的抽样结构中亮度信号为每帧720x576样值，Cb，Cr都为360x576样值，即每行中每隔一个像素对色差信号抽一次样，如图3所示，○代表Y信号的抽样点，&#215;代表Cb，Cr信号的抽样点。 <br><br>　4:4:4格式中，亮度和色差信号的抽样频率都是13.5MHz，因此空间的抽样结构中亮度和色差信号都为每帧720x576样值。而4:2:0格式中，亮度信号的抽样频率13.5MHz，空间的抽样结构中亮度信号为每帧720x576样值，Cb，Cr都为360x288样值，即每隔一行对两个色差信号抽一次样，每抽样行中每隔一个像素对两个色差信号抽一次样。 <br><br>　通过上述分析不难计算出，4:2:0格式中，每四个Y信号的像块空间内的Cb，Cr样值分别构成一个Cb，Cr像块；4:2:2格式中，每四个Y信号的像块空间内的Cb，Cr样值分别构成两个Cb，Cr像块；而4:4:4格式中，每四个Y信号的像块空间内的Cb，Cr样值分别构成四个Cb，Cr像块。相应的宏块结构正是以此基础构成的。<br><br>　宏块层之下是像块层，像块是MPEG-2码流的最底层，是DCT变换的基本单元。MP@ML中一个像块由8x8个抽样值构成，同一像块内的抽样值必须全部是Y信号样值，或全部是Cb信号样值，或全部是Cr信号样值。另外，像块也用于表示8x8个抽样值经DCT变换后所生成的8x8个DCT系数。 <br><br>在帧内编码的情况下，编码图像仅经过DCT，量化器和比特流编码器即生成编码比特流，而不经过预测环处理。DCT直接应用于原始的图像数据。 <br><br>　在帧间编码的情况下，原始图像首先与帧存储器中的预测图像进行比较，计算出运动矢量，由此运动矢量和参考帧生成原始图像的预测图像。而后，将原始图像与预测像素差值所生成的差分图像数据进行DCT变换，再经过量化器和比特流编码器生成输出的编码比特流。 <br><br>　可见，帧内编码与帧间编码流程的区别在于是否经过预测环的处理。 <br>MPEG-2视频压缩方案中包含以下关键技术环节： <br>1、余弦变换DCT <br>　DCT是一种空间变换，在MPEG-2中DCT以8x8的像块为单位进行，生成的是8x8的DCT系数数据块。DCT变换的最大特点是对于一般的图像都能够将像块的能量集中于少数低频DCT系数上，即生成8x8DCT系数块中，仅左上角的少量低频系数数值较大，其余系数的数值很小，这样就可能只编码和传输少数系数而不严重影响图像质量。 <br>　DCT不能直接对图像产生压缩作用，但对图像的能量具有很好的集中效果，为压缩打下了基础。 <br><br>2、量化器 <br>　量化是针对DCT变换系数进行的，量化过程就是以某个量化步长去除DCT系数。量化步长的大小称为量化精度，量化步长越小，量化精度就越细，包含的信息越多，但所需的传输频带越高。不同的DCT变换系数对人类视觉感应的重要性是不同的，因此编码器根据视觉感应准则，对一个8x8的DCT变换块中的64个DCT变换系数采用不同的量化精度，以保证尽可能多地包含特定的DCT空间频率信息，又使量化精度不超过需要。DCT变换系数中，低频系数对视觉感应的重要性较高，因此分配的量化精度较细；高频系数对视觉感应的重要性较低，分配的量化精度较粗，通常情况下，一个DCT变换块中的大多数高频系数量化后都会变为零。 <br><br>3、之型扫描与游程编码 <br>　DCT变换产生的是一8x8的二维数组，为进行传输，还须将其转换为一维排列方式。有两种二维到一维的转换方式，或称扫描方式：之型扫描(Zig-Zag)和交替扫描，其中之型扫描是最常用的一种。由于经量化后，大多数非零DCT系数集中于8x8二维矩阵的左上角，即低频分量区，之型扫描后，这些非零DCT系数就集中于一维排列数组的前部，后面跟着长串的量化为零的DCT系数，这些就为游程编码创造了条件。 <br>-　游程编码中，只有非零系数被编码。一个非零系数的编码由两部分组成：前一部分表示非零系数前的连续零系数的数量(称为游程)，后一部分是那个非零系数。这样就把之型扫描的优点体现出来了，因为之型扫描在大多数情况下出现连零的机会比较多，游程编码的效率就比较高。当一维序列中的后部剩余的DCT系数都为零时，只要用一个&#8220;块结束&#8221;标志(EOB)来指示，就可结束这一8x8变换块的编码，产生的压缩效果是非常明显的。 <br><br>4、熵编码 <br>　量化仅生成了DCT系数的一种有效的离散表示，实际传输前，还须对其进行比特流编码，产生用于传输的数字比特流。简单的编码方法是采用定长码，即每个量化值以同样数目的比特表示，但这种方法的效率较低。而采用熵编码可以提高编码效率。熵编码是基于编码信号的统计特性，使得平均比特率下降。游程和非零系数既可独立的，也可联合的作熵编码。熵编码中使用较多的一种是霍夫曼编码，MPEG-2视频压缩系统中采用的就是霍夫曼编码。霍夫曼编码中，在确定了所有编码信号的概率后生产一个码表，对经常发生的大概率信号分配较少的比特表示，对不常发生的小概率信号分配较多的比特表示，使得整个码流的平均长度趋于最短。 <br><br>5、信道缓存 <br>　由于采用了熵编码，产生的比特流的速率是变化的，随着视频图像的统计特性变化。但大多数情况下传输系统分配的频带都是恒定的，因此在编码比特流进入信道前需设置信道缓存。信道缓存是一缓存器，以变比特率从熵编码器向里写入数据，以传输系统标称的恒定比特率向外读出，送入信道。缓存器的大小，或称容量是设定好的，但编码器的瞬时输出比特率常明显高于或低于传输系统的频带，这就有可能造成缓存器的上溢出或下溢出。因此缓存器须带有控制机制，通过反馈控制压缩算法，调整编码器的比特率，使得缓存器的写入数据速率与读出数据速率趋于平衡。缓存器对压缩算法的控制是通过控制量化器的量化步长实现的，当编码器的瞬时输出速率过高，缓存器将要上溢时，就使量化步长增大以降低编码数据速率，当然也相应增大了图像的损失；当编码器的瞬时输出速率过低，缓存器将要下溢出时，就使量化步长减小以提高编码数据速率。 <br><br>6、运动估计 <br>　运努估计使用于帧间编码方式时，通过参考帧图像产生对被压缩图像的估计。运动估计的准确程度对帧间编码的压缩效果非常重要。如果估计作的好，那么被压缩图像与估计图像相减后只留下很小的值用于传输。运动估计以宏块为单位进行，计算被压缩图像与参考图像的对应位置上的宏块间的位置偏移。这种位置偏移是以运动矢量来描述的，一个运动矢量代表水平和垂直两个方向上的位移。运动估计时，P帧和B帧图像所使用的参考帧图像是不同的。P帧图像使用前面最近解码的I帧或P帧作参考图像，称为前向预测；而B帧图像使用两帧图像作为预测参考，称为双向预测，其中一个参考帧在显示顺序上先于编码帧(前向预测)，另一帧在显示顺序上晚于编码帧(后向预测)，B帧的参考帧在任何情况下都是I帧或P帧。 <br><br>7、运动补偿 <br>　利用运动估计算出的运动矢量，将参考帧图像中的宏块移至水平和垂直方向上的相对应位置，即可生成对被压缩图像的预测。在绝大多数的自然场景中运动都是有序的。因此这种运动补偿生成的预测图像与被压缩图像的差分值是很小的。数字图像质量的主观评价 <br><br>　主观评价的条件包括：评价小组结构，观察距离，测试图像，环境照度和背景色调等。评价小组由一定人数观察人员构成，其中专业人员与非专业人员各占一定比例。观察距离为显示器对角线尺寸的3-6倍。测试图像有若干具有一定图像细节和运动的图像序列构成。主观评价反映的是许多人对图像质量统计评价的平均值。&nbsp;<br>&nbsp;
<img src ="http://www.cppblog.com/elva/aggbug/75652.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2009-03-05 17:13 <a href="http://www.cppblog.com/elva/archive/2009/03/05/75652.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MPEG2 TS流 </title><link>http://www.cppblog.com/elva/archive/2009/03/05/75650.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Thu, 05 Mar 2009 09:04:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2009/03/05/75650.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/75650.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2009/03/05/75650.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/75650.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/75650.html</trackback:ping><description><![CDATA[<table style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word" cellSpacing=0 cellPadding=0 width="100%" border=0>
    <tbody>
        <tr>
            <td align=middle>
            <table style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word" cellSpacing=0 cellPadding=0 width="100%" border=0>
                <tbody>
                    <tr>
                        <td>
                        <div id=art style="MARGIN: 15px">
                        <p>声明：以下内容转帖自<a href="http://blog.lmtw.com/b/moreframe/archives/2006/40865.html"><u><font color=#810081>http://blog.lmtw.com/b/moreframe/archives/2006/40865.html</font></u></a>，作者写的非常好，感谢作者的辛苦。<br></p>
                        <p>应该说真正了解TS，还是看了朋友推荐的《数字电视业务信息及其编码》一书之后，MPEG2 TS和数字电视是紧密不可分割的，值得总结一下其中的一些关系。</p>
                        <p>ISO/IEC－13818－1：系统部分；ISO/IEC－13818－2：视频；ISO/IEC－13818－3：音频；ISO/IEC－13818－4：一致性测试；ISO/IEC－13818－5：软件部分；ISO/IEC－13818－6：数字存储媒体命令与控制；ISO/IEC－13818－7：高级音频编码；ISO/IEC－13818－8：系统解码实时接口；</p>
                        <p>MPEG2系统任务包括：1. 规定以包传输数据的协议；2. 规定收发两端数据流同步的协议；3. 提供多个数据流的复用和解复用协议；3. 提供数据流加密的协议。以包形式存储和传送数据流是MPEG2系统之要点。</p>
                        <p>ES是直接从编码器出来的数据流，可以是编码过的视频数据流，音频数据流，或其他编码数据流的统称。ES流经过PES打包器之后，被转换成PES包。PES包由包头和payload组成，具体格式摘录如下：</p>
                        <p><img src="http://blog.lmtw.com/UploadFiles/2006-9/927993844.jpg"><br></p>
                        <p>可以看到PTS/DTS是打在PES包里面的，这两个parameters是解决视音频同步显示，防止解码器输入缓存上溢或下溢的关键。PTS表示显示单元出现在系统目标解码器(STD: system target decoder)的时间，DTS表示将存取单元全部字节从STD的ES解码缓存器移走的时刻。<span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">每个</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">I</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">、</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">P</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">、</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">B</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">帧的包头都有一个</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">PTS</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">和</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">DTS</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">，但</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">PTS</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">与</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">DTS</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">对</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">B</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">帧都是一样的，无须标出</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">B</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">帧的</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">DTS</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">。对</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">I</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">帧和</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">P</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">帧，显示前一定要存储于视频解码器的重新排序缓存器中，经过延迟（重新排序）后再显示，一定要分别标明</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">PTS</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">和</span><span style="FONT-SIZE: 11.5pt; FONT-FAMILY: ˎ̥"><font face="Times New Roman">DTS</font></span><span lang=ZH-CN style="FONT-SIZE: 11.5pt; FONT-FAMILY: 宋体">。</span></p>
                        <p>上节介绍过，ES首先需打包成PES流包，然后PES根据需要打包成PS或TS包进行存储或传输。其每路ES只包含一路信源的编码数据流，所以每路PES也只包含相对应信源的数据流。</p>
                        <p>对PS流而言，每个PES包头含有PTS和DTS，流识别码，用于区别不同性质ES。然后通过PS复用器将PES包复用成PS包。实际上是将PES包分解为更细小的PS包。在解码的时候，解复用器将PS分解成一个个PES包，拆包器然后将PES包拆成视频和音频的ES，最后输入至各自解码器进行解码。一个问题是：各个ES在解码时，如何保证视音频的同步呢？除了PTS和DTS的配合工作外，还有一个重要的参数是SCR(system clock reference)。在编码的时候，PTS，DTS和SCR都是由STC(system time clock)生成的，在解码时，STC会再生，并通过锁相环路（PLL－phase lock loop），用本地SCR相位与输入的瞬时SCR相位锁相比较，以确定解码过程是否同步，若不同步，则用这个瞬时SCR调整27MHz的本地时钟频率。最后，PTS，DTS和SCR一起配合，解决视音频同步播放的问题。PS格式摘录如下：</p>
                        <p><img src="http://blog.lmtw.com/UploadFiles/2006-9/928142321.jpg"><br></p>
                        <p>PS包的长度比较长且可变，主要用于无误码环境里，因为越长的话，同步越困难，且在丢包的情况下，重组也越困难。所以，PS适合于节目信息的编辑和本地内容应用的application。</p>
                        <div><font face=Tahoma size=2>TS流也是由一个或多个PES组合而来的，他们可以具有相同的时间基准，也可以不同。其基本的复用思想是，对具有相同时间基准<font color=#000000>的多个PES现进行节目复用</font>，然后再对相互有独立时间基准的各个PS进行传输复用，最终产生出TS。</font></div>
                        <div>&nbsp;</div>
                        <div><font face=Tahoma><font size=2>TS包由包头和包数据<span class=766400115-04102006>2部分</span>组成，其中包头还可以包括扩展的自适用区。包头长度占<span class=766400115-04102006>4bytes，自使用区和包数据共占184bytes，整个TS包长度相当于4个ATM包长。<span style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体">包的包头由如下图摘录所示的同步字节、传输误码指示符、有效载荷单元起始指示符、传输优先、包识别（</span><span style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: ˎ̥">PID-Packet Identification</span><span lang=ZH-CN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体">）、传输加扰控制、自适应区控制和连续计数器</span><span style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: ˎ̥">8</span><span lang=ZH-CN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体">个部分组成。</span></span></font></font></div>
                        <div><font face=Tahoma><font size=2><span class=766400115-04102006><span lang=ZH-CN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体"><img src="http://blog.lmtw.com/UploadFiles/2006-10/107720957.jpg"><br><span lang=ZH-CN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体">&nbsp;
                        <p class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: 18pt; TEXT-ALIGN: left" align=left><font face=Tahoma><font size=2><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">其中，可用同步字节位串的自动相关特性，检测数据流中的包限制，建立包同步；传输误码指示符，是指有不能消除误码时，采用误码校正解码器可表示</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">1bit </span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">的误码，但无法校正；有效载荷单元起始指示符，表示该数据包是否存在确定的起始信息；传输优先，是给</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包分配优先权；</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PID</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">值是由用户确定的，解码器根据</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PID</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">将</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">上从不同</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">ES</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">来的</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包区别出来，以重建原来的</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">ES</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">；传输加扰控制，可指示数据包内容是否加扰，但包头和自适应区永远不加扰；自适应区控制，用</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">2 bit</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">表示有否自适应区，即（</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">01</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">）表示有有用信息无自适应区，（</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">10</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">）表示无有用信息有自适应区，（</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">11</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">）表示有有用信息有自适应区，（</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">00</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">）无定义；连续计数器可对</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PID</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包传送顺序计数，据计数器读数，接收端可判断是否有包丢失及包传送顺序错误。显然，包头对</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包具有同步、识别、检错及加密功能。</span><span style="COLOR: black; FONT-FAMILY: ˎ̥"><o:p></o:p></span></font></font></p>
                        <p class=MsoNormal style="MARGIN: 0in 0in 0pt; LINE-HEIGHT: 18pt; TEXT-ALIGN: left" align=left><font face=Tahoma><font size=2><span style="COLOR: black; FONT-FAMILY: ˎ̥">&nbsp;&nbsp;&nbsp; TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包自适应区由自适应区长、各种标志指示符、与插入标志有关的信息和填充数据</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">4</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">部分组成。其中标志部分由间断指示符、随机存取指示符、</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">ES</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">优化指示符、</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PCR</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">标志、接点标志、传输专用数据标志、原始</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PCR</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">标志、自适应区扩展标志</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">8</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">个部分组成。重要的是标志部分的</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PCR</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">字段，可给编解码器的</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">27MHz</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">时钟提供同步资料，进行同步。其过程是，通过</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PLL</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">，用解码时本地用</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PCR</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">相位与输入的瞬时</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PCR</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">相位锁相比较，确定解码过程是否同步，若不同步，则用这个瞬时</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PCR</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">调整时钟频率。因为，数字图像采用了复杂而不同的压缩编码算法，造成每幅图像的数据各不相同，使直接从压缩编码图像数据的开始部分获取时钟信息成为不可能。为此，选择了某些（而非全部）</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包的自适应区来传送定时信息。于是，被选中的</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包的自适应区，可用于测定包信息的控制</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">bit</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">和重要的控制信息。自适应区无须伴随每个包都发送，发送多少主要由选中的</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包的传输专用时标参数决定。标志中的随机存取指示符和接点标志，在节目变动时，为随机进入</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">I</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">帧压缩的数据流提供随机进入点，也为插入当地节目提供方便。自适应区中的填充数据是由于</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">PES</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包长不可能正好转为</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包的整数倍，最后的</span><span style="COLOR: black; FONT-FAMILY: ˎ̥">TS</span><span lang=ZH-CN style="COLOR: black; FONT-FAMILY: 宋体">包保留一小部分有用容量，通过填充字节加以填补，这样可以防止缓存器下溢，保持总码率恒定不变。</span></font></font></p>
                        </span></span></span></font></font>
                        <p><font face=Tahoma size=2>前面3节总结了MPEG2 TS的基本格式，其中包括PES，PS和TS，以及相关字段的介绍。那么作为一种传输流，TS将内容进行打包/复用，让其媒体内容变成TS传输，并最终在解码端解码。简单来看，TS是一个传输层的协议栈，它可以承载各种内容的传输，比如MPEG，WMV，H264，甚至是IP，那么其中的传输规范是如何定义的呢？这个即是PSI（节目特定信息）要做的事情。</font></p>
                        <p><font face=Tahoma size=2>PSI由四张表构成：PAT，PMT，CAT和NIT，这四张表分别描述了一个TS所包括的所有ES流的传输结构。首先的一个概念是，TS是以包形式传播，在编解码端都需要以一定的包ID来标识TS流里承载的内容，比如，PAT表会存在于一个或多个TS包里，所以要用一个特别的包ID来表示，另外，不同的ES流也需要不同的包ID来标识。我们有了PAT和PMT这两种表，解码器就可以根据PID，将TS上从不同ES来的TS包区分出来进行解码。</font></p>
                        <p><font face=Tahoma><font size=2>TS的解码分两步进行，其一，是从PID为<span class=566290807-13102006>0的TS包里，解析出PAT表，然后从PAT表里找到各个节目源的PID，一般此类节目源都由若干个ES流组成，并描述在PMT表里面，然后通过节目源的PID，就可以在PMT表里检索到各个ES的PID。其二，解码器根据PMT表里的ES流的PID，将TS流上的包进行区分，并按不同的ES流进行解码。所以，TS是经过节目复用和传输复用两层完成的，即在节目复用时，加入了PMT，在传输复用时，加入了PAT。同样在节目解复用时，可以得到PMT，在传输解复用时，可以得到PAT。下图很好地概述了其思想。</span></font></font></p>
                        <p><font face=Tahoma><font size=2><span class=566290807-13102006><img src="http://blog.lmtw.com/UploadFiles/2006-10/1015748066.jpg"></span></font></font></p>
                        <p>TS是支持多路复用的，所以它可用来传输经复用后的多层节目。在复用过程中，要注意的是，解码过程中所需要面对的时间参考和同步问题，因为解复用是需要各种信息同步进行的，所以在复用过程中，就需要插入相关的时间信息：PTS，DTS，PCR。</p>
                        <p>在TS形成过程中，PTS和DTS是在ES打包成PES时，根据STC的参考，将其时钟信息注入PES包中的，而之后在PES切成TS时，再将PID和PCR信息注入到TS包中，当多路TS再进行复用的时候，各路TS的PCR将会被提取出来，再进行分析，然后再根据统一的STC参考，将新的PCR生成并注入到TS中去，最后，因为原来PAT表信息不在适用，所以新的PAT表需要再生成，并附加到新的TS流中去。经过这多层的复用之后，新的TS流即可以进入调制，传输阶段。过程可参见下图：</p>
                        <p><img src="http://blog.lmtw.com/UploadFiles/2006-10/1031369848.jpg"><br></p>
                        <p>解码过程要面对的问题是：解复用，视音频的同步，解码缓存器无上下溢。解复用即是将TS在同一信道里不同时序进行传输的节目分离出来；视音频同步由DTS, PTS和PCR三者协调完成，并且PCR是重建系统时间基准的绝对时标，而DTS和PTS是解码和重现时刻的相对时标；对解码缓存器无上下溢的问题，必须借助于系统目标解码器（STD）模型来对其进行实现，基本思想如下：</p>
                        <ol>
                            <li>TS流进入解码器后，首先由换向器，按照一定的时序关系，将各种ES流分解出来（其中也包括PSI信息流）。
                            <li>分解过后的ES流会进入各自的传输缓存器，通过之后，其PES流进入各自的主存储器，注意的是：PSI信息流会进入系统缓存器，最后也到达主存储器。
                            <li>最后，解码器根据DTS信息，从各个主存储器分别提取媒体或系统信息，进行解码，并根据PTS信息，将媒体内容进行显示处理。</li>
                        </ol>
                        <p>其过程可参见下图：</p>
                        <p><img src="http://blog.lmtw.com/UploadFiles/2006-10/1031942689.jpg"><br></p>
                        <font face=Tahoma><font size=2><span class=766400115-04102006><span lang=ZH-CN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体"><span lang=ZH-CN style="FONT-SIZE: 10.5pt; COLOR: black; FONT-FAMILY: 宋体"></span></span></span></font></font></div>
                        <div></div>
                        </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p style="MARGIN: 5px; LINE-HEIGHT: 150%"></p>
            </td>
        </tr>
        <tr>
            <td height=25>&nbsp;<font color=#000099><strong>原文地址</strong></font> <a href="http://blog.lmtw.com/b/moreframe/archives/2006/40865.html" target=_blank><u><font color=#810081>http://blog.lmtw.com/b/moreframe/archives/2006/40865.html</font></u></a> </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/elva/aggbug/75650.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2009-03-05 17:04 <a href="http://www.cppblog.com/elva/archive/2009/03/05/75650.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ProCoder 3不能正常启动的原因</title><link>http://www.cppblog.com/elva/archive/2009/02/20/74449.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Fri, 20 Feb 2009 11:57:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2009/02/20/74449.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/74449.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2009/02/20/74449.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/74449.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/74449.html</trackback:ping><description><![CDATA[<br>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt id=blog_text>
            <p>有的网友安装ProCoder 3后，可以启动，可以正常使用，有的网友安装ProCoder 3后，不能启动，无法使用。究竟为什么会出现两种不同的情况呢？经过几天对ProCoder 3多次进行安装卸载、卸载安装的试验，终于找到了产生问题的原因：与安装EDIUS4（4.5或4.51）后采用的破解方法有直接关系。</p>
            <p>EDIUS4（4.5或4.51）的破解方法有两种：第一种方法是运行Canopus.Edius.4.xcrack.exe解除30天的使用限制；第二种方法是将1.5KB的pavedius.dll（2006-8-15 16:26）复制到windows\system32中覆盖原文件解除30天的使用限制。</p>
            <p>采用第一种方法破解后， windows\system32中pavedius.dll的大小为48KB，在这种情况下安装ProCoder 3后，windows\system32中pavedius.dll的大小仍为48KB，ProCoder 3没有破解，所以不能启动，要想让ProCoder 3启动，就必须将1.5KB的pavedius.dll（2006-8-15 16:26）复制到windows\system32中覆盖原文件才行。如果你安装EDIUS4（4.5或4.51）后采用了第一种破解方法，那么你安装ProCoder 3后就会遇到麻烦，启动不起来。本人就属于这种情况。</p>
            <p>采用第二种方法破解后，windows\system32中的pavedius.dll为1.5KB，在这种情况下安装ProCoder 3后，windows\system32中pavedius.dll的大小变为2.5KB，ProCoder 3已被破解，所以安装后就可启动使用。如果你安装EDIUS4（4.5或4.51）后采用了第二种破解方法，那么你就幸运了，安装上ProCoder 3后就能使用。</p>
            <p>ProCoder 3与pavedius.dll关系密切, ProCoder 3安装后，当windows\system32中或ProCoder 3的安装目录中的pavedius.dll为1.5KB或2.5KB时，ProCoder 3可以启动，正常使用。当windows\system32或ProCoder 3安装目录中的pavedius.dll为48KB或56KB时，ProCoder 3就不能启动，无法使用。而ProCoder 2同pavedius.dll的关系与ProCoder 3却有所不同。当windows\system32中的pavedius.dll为48KB或56KB时，你就别想安装上ProCoder 2，会提示硬盘空间不足无法安装。必须将pavedius.dll删除，或将pavedius.dll替换为1.5KB或2.5KB后才能安装。ProCoder 2安装上以后，windows\system32中有无pavedius.dll以及pavedius.dll的大小都不影响它正常使用。</p>
            <p>ProCoder 3与ProCoder 2可以共存。<br>在电脑中没有安装过EDIUS、或windows\system32中没有pavedius.dll的情况下， ProCoder 3安装后肯定可以正常使用。这时 windows\system32中的pavedius.dll为2.5KB(007-3-27 0:00)，是由安装 ProCoder 3生成的。</p>
            <br>作者连接:http://hi.baidu.com/home027/blog/item/9ec62bfaf1ad90d9b58f31b0.html<br></div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cppblog.com/elva/aggbug/74449.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2009-02-20 19:57 <a href="http://www.cppblog.com/elva/archive/2009/02/20/74449.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>精解PSI-SI（一） </title><link>http://www.cppblog.com/elva/archive/2008/11/12/66733.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 12 Nov 2008 09:51:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2008/11/12/66733.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/66733.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2008/11/12/66733.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/66733.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/66733.html</trackback:ping><description><![CDATA[<div class=postText>
<p>Packet的概念</p>
<p>&nbsp;<wbr>(1)<u>TS</u><u>流是基于</u><u>Packet的位流格式,每个包是188字节或者204字节</u>(一般是188字节,204字节的格式仅仅是在188字节的Packet后部加上16字节的CRC数据,其他格式是一样的),整个TS流组成如下所示:&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>Packet&nbsp;<wbr>1&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>Packet&nbsp;<wbr>2&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>......&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>Packet&nbsp;<wbr>n</p>
<p>在实际使用中,因为TS流已经内部具有很强的错误处理能力,所以一般使用较多的是188字节一个包的格式,204字节一个包的格式据说一般在高清节目中使用较多.</p>
<p>&nbsp;<wbr>所有的Packet格式都是统一的,包括一个Packet&nbsp;<wbr>header和Packet&nbsp;<wbr>datas.其中Packet&nbsp;<wbr>header包含了同步字节(该字节固定是0x47,表示这个包的数据开始是正确的),该Packet的唯一号码(即PID)和其他一些信息.格式如下(用C格式表示)</p>
<p>typedef&nbsp;<wbr>struct</p>
<p>{</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>sync_byte:8;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>transport_error_indicator:1;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>payload_unit_start_indicator:1;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>transport_priority:1;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>PID:13;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>transport_scrambling_control:2;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>adaptation_field_control:2;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>continuity_counter:4;</p>
<p>}PACKET_HEADER;</p>
<p>以上结构刚好占用32&nbsp;<wbr>bits,即4个字节,因此一个TS流的Packet头部的4字节是header信息,分析该header信息就可以知道当前Packet的属性<u>.</u><u>剩下的</u><u>184字节有可能是Video数据,也有可能是Audio数据,也有可能是DVB&nbsp;<wbr>SI信息,</u>怎&nbsp;<wbr>么区分呢?其实很简单,就是利用header中的PID信息.上一章说了PAT是节目关联表,它的PID是0x0000.这个PID就是对应这里&nbsp;<wbr>header的PID.换句话就是说,如果我们发现一个Packet的PID等于0x0000,那么说明这个Packet是DVB的PAT表格而不是&nbsp;<wbr>Video数据或者Audio数据.</p>
<p>实&nbsp;<wbr>际上,在信号编码成TS码流的时候,不同节目的Video,Audio等数据都分配了不同的PID.例如,一个节目有两路Video,三路Audio,那&nbsp;<wbr>么分配PID的时候可能是Video&nbsp;<wbr>1==0x100,Video&nbsp;<wbr>2==0x101,Audio&nbsp;<wbr>1==0x102,Audio&nbsp;<wbr>2==0x103,&nbsp;<wbr>Audio&nbsp;<wbr>3==0x104,这样传输的TS码流中的PID就可能有以上的PID.因此,如果我们需要在程序中过滤出第一路Video和第二路&nbsp;<wbr>Audio就可以这样处理了(伪代码描述):</p>
<p>&nbsp;<wbr>void&nbsp;<wbr>Process_Packet(unsigned&nbsp;<wbr>char*buff)</p>
<p>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>int&nbsp;<wbr>PID=GETPID(buff);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>if(PID==0x100)&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>SaveToVideoBuffer(buff+4);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>else&nbsp;<wbr>if(PID==0x103)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>SaveToAudioBuffer(buff+4);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>else</p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>printf("unknown&nbsp;<wbr>PID!"n");</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>}</p>
<p>现&nbsp;<wbr>在的问题是,编码的时候分配好的PID,在解码的时候是怎么知道什么PID对应什么数据呢?这就是DVB&nbsp;<wbr>SI表格的分析与处理了,请参考第三章.这里先&nbsp;<wbr>看一个实际的TS码流的例子.这里的数据是用UltraEdit用16进制格式打开TS码流文件得到的.文件是Taiwan-551.ts.</p>
<p>这&nbsp;<wbr>里仅仅截取了3个Packet的信息,请注意图中用红色标注的部分,这就是TS流Packet的4个字节的头信息.这个TS流是采用每个包共188字节的&nbsp;<wbr>格式,因为两个头信息的间隔是188个字节(第一个0x47到第二个0x47的间隔).以后的所有的Packet都将是188字节的格式,这是&nbsp;<wbr>DVB&nbsp;<wbr>TS标准规定的固定大小.那么这三个包分别包含的是什么数据,下面我们可以自己分析一下.</p>
<p>&nbsp;<wbr>先&nbsp;<wbr>看第一个包,头信息数据是"0x47&nbsp;<wbr>0x07&nbsp;<wbr>0xe5&nbsp;<wbr>0x12",刚才已经知道了,header信息都是按位操作的(这就是为什么TS码流也可以叫&nbsp;<wbr>做位流的原因),特别要注意的是定义和传输的时候都是MSB&nbsp;<wbr>first,也就是说,先出现的位是数据的最高位.先转化成2进制格式:</p>
<p>&nbsp;<wbr>01000111&nbsp;<wbr>00000111&nbsp;<wbr>11100101&nbsp;<wbr>00010010</p>
<p>请对照上面的PACKET_HEADER结构:</p>
<p>typedef&nbsp;<wbr>struct</p>
<p>{</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>sync_byte:8;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>transport_error_indicator:1;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>payload_unit_start_indicator:1;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>transport_priority:1;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>PID:13;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>transport_scrambling_control:2;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>adaptation_field_control:2;</p>
<p>&nbsp;<wbr>unsigned&nbsp;<wbr>continuity_counter:4;</p>
<p>}PACKET_HEADER;</p>
<p>那么对照一下,我们可以发现:</p>
<p>&nbsp;<wbr>sync_byte=01000111,就是0x47,这是DVB&nbsp;<wbr>TS规定的同步字节,固定是0x47.</p>
<p>&nbsp;<wbr>transport_error_indicator=0,表示当前包没有发生传输错误.</p>
<p>&nbsp;<wbr>payload_unit_start_indicator=0,含义请参考ISO13818-1标准文档</p>
<p>&nbsp;<wbr>transport_priority=0,表示当前包是低优先级.</p>
<p>&nbsp;<wbr>PID=00111&nbsp;<wbr>11100101即0x07e5,这代表是什么呢,暂时还不知道(实际上是Video&nbsp;<wbr>PID,参考下图)</p>
<p>&nbsp;<wbr>transport_scrambling_control=00,表示节目没有加密</p>
<p>&nbsp;<wbr>adaptation_field_control=01即0x01,具体含义请参考ISO13818-1</p>
<p>&nbsp;<wbr>continuity_counte=0010即0x02,表示当前传送的相同类型的包是第3个</p>
<p>依此类推,再看一下第二个包"0x47&nbsp;<wbr>0x07&nbsp;<wbr>0xe5&nbsp;<wbr>0x13",2进制是01000111&nbsp;<wbr>00000111&nbsp;<wbr>11100101&nbsp;<wbr>00010011</p>
<p>&nbsp;<wbr>sync_byte=01000111,就是0x47,这是DVB&nbsp;<wbr>TS规定的同步字节,固定是0x47.</p>
<p>&nbsp;<wbr>transport_error_indicator=0,表示当前包没有发生传输错误.</p>
<p>&nbsp;<wbr>payload_unit_start_indicator=0,含义请参考ISO13818-1标准文档</p>
<p>&nbsp;<wbr>transport_priority=0,表示当前包是低优先级.</p>
<p>&nbsp;<wbr>PID=00111&nbsp;<wbr>11100101即0x07e5,这代表是什么呢,暂时还不知道(实际上是Video&nbsp;<wbr>PID,参考下图)</p>
<p>&nbsp;<wbr>transport_scrambling_control=00,表示节目没有加密</p>
<p>&nbsp;<wbr>adaptation_field_control=01即0x01,具体含义请参考ISO13818-1</p>
<p>&nbsp;<wbr>continuity_counte=0011即0x03,表示当前传送的相同类型的包是第4个(注意到了吧,以上两个包的PID都是0x07e5,所以这里的continuity_counte就递增一次)</p>
<p>第三个包是"0x47&nbsp;<wbr>0x07&nbsp;<wbr>0xf1&nbsp;<wbr>0x18",2进制是01000111&nbsp;<wbr>00000111&nbsp;<wbr>11110001&nbsp;<wbr>00011000.</p>
<p>&nbsp;<wbr>sync_byte=01000111,就是0x47,这是DVB&nbsp;<wbr>TS规定的同步字节,固定是0x47.</p>
<p>&nbsp;<wbr>transport_error_indicator=0,表示当前包没有发生传输错误.</p>
<p>&nbsp;<wbr>payload_unit_start_indicator=0,含义请参考ISO13818-1标准文档</p>
<p>&nbsp;<wbr>transport_priority=0,表示当前包是低优先级.</p>
<p>&nbsp;<wbr>PID=00111&nbsp;<wbr>11100101即0x07f1,这代表是什么呢,暂时还不知道(实际上是Audio&nbsp;<wbr>PID,参考下图)</p>
<p>&nbsp;<wbr>transport_scrambling_control=00,表示节目没有加密</p>
<p>&nbsp;<wbr>adaptation_field_control=01即0x01,具体含义请参考ISO13818-1</p>
<p>&nbsp;<wbr>continuity_counte=1000即0x08,表示当前传送的相同类型的包是第9个</p>
<p>请看解码程序&lt;&lt;Seekfor&nbsp;<wbr>MPEG-2&nbsp;<wbr>decoder&gt;&gt;读取该文件的结果:</p>
<p>&nbsp;<wbr></p>
<p>上图我们可以发现,Taiwan-551.ts有一个节目叫"DIMO",它的Video&nbsp;<wbr>PID是0x07e5,Audio&nbsp;<wbr>PID是0x07e6</p>
<p>还有一个节目叫"Service&nbsp;<wbr>1",没有Video&nbsp;<wbr>PID,它的Audio&nbsp;<wbr>PID是0x07f1(说明是一个广播节目而非电视节目)</p>
<p>这个数据刚好和我们刚才的分析是吻合的.</p>
<p>但&nbsp;<wbr>是我想大家还有疑问,为什么0x07e5代表Video&nbsp;<wbr>PID,0x07e6代表其中一个Audio&nbsp;<wbr>PID呢?这就是刚才提到的,这是TS流在编码的&nbsp;<wbr>时候就分配好了的.但是,在解码的时候是怎么知道0x07e5就代表的是Video而不是Audio呢?</p>
</div>
<img src ="http://www.cppblog.com/elva/aggbug/66733.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2008-11-12 17:51 <a href="http://www.cppblog.com/elva/archive/2008/11/12/66733.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>精解PSI-SI（二） </title><link>http://www.cppblog.com/elva/archive/2008/11/12/66734.html</link><dc:creator>叶子</dc:creator><author>叶子</author><pubDate>Wed, 12 Nov 2008 09:51:00 GMT</pubDate><guid>http://www.cppblog.com/elva/archive/2008/11/12/66734.html</guid><wfw:comment>http://www.cppblog.com/elva/comments/66734.html</wfw:comment><comments>http://www.cppblog.com/elva/archive/2008/11/12/66734.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/elva/comments/commentRss/66734.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/elva/services/trackbacks/66734.html</trackback:ping><description><![CDATA[<div class=postText>
<p>DVB&nbsp;<wbr>SI/PSI分析和处理</p>
<p>&nbsp;<wbr></p>
<p>SI是Specific&nbsp;<wbr>Information的简称,PSI是program&nbsp;<wbr>Specific&nbsp;<wbr>Information．该机制允许ＤＶＢ传送各种各样的讯息，比如节目名称，电视台名称，各种ＰＩＤ，私有信息，甚至单独传送数据实现数据通信等．这些功能的实现都归功于SI/PSI.</p>
<p>&nbsp;<wbr>在DVB&nbsp;<wbr>标准中，定义了一个标准的PID用来实现SI/PSI.这些PID是系统保留的，因此ＤＶＢ编码的时候并不会用这些ＰＩＤ做为Video&nbsp;<wbr>PID或者&nbsp;<wbr>Audio&nbsp;<wbr>PID或者其他ＰＩＤ．在一个简单的解复用程序中，只需要提供处理PAT,PMT表格的程序即可实现解复用，当然如果需要更友好的界面和实现&nbsp;<wbr>更复杂的功能（如ＣＡ）则必须处理其他的ＳＩ表．在这里仅仅分析PAT,PMT,SDT表格，其他SI表格的分析，请参考ISO13818-1(MPEG-2系统层标准)和EN300468(DVB&nbsp;<wbr>SI标准)文档．</p>
<p>&nbsp;<wbr>DVB定义的SI保留的PID分别是:</p>
<p>&nbsp;<wbr>&nbsp;<wbr></p>
<p>上表格的PID就是ＤＶＢ保留的ＰＩＤ，分配的其他ＰＩＤ一定不会占用这些ＰＩＤ．解复用程序需要使用到的表格只有PAT,PMT,SDT,而ＣＡ应用还需要使用CAT,EPG应用还需要使用NIT,EIT,TDT,TOT等表格.所以在需要解复用的时候，伪代码需要这样写:</p>
<p>&nbsp;<wbr>&nbsp;<wbr>void&nbsp;<wbr>Process_Packet(unsigned&nbsp;<wbr>char*buff)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>int&nbsp;<wbr>PID=GETPID(buff);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>if(PID==0x0000)&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>Process_PAT(buff+4);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>else&nbsp;<wbr>if(PID==......)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>else</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>printf("Unknown&nbsp;<wbr>PID!");</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>所&nbsp;<wbr>有的表格都开始于Packet中的184字节的数据部分，但有的时候一个表格没有184字节，这时在Packet中就可能插入一些无效信息用来填充使整个&nbsp;<wbr>Packet依然保持是188字节．也可能用头信息中的payload_unit_start_indicator标志表格有个偏移位置（当&nbsp;<wbr>payload_unit_start_indicator=0表示表格数据直接从Packet区的第四个字节开始，否则表示有一个偏移量位置开始,具体&nbsp;<wbr>请参考ISO13818-1,第4字节到偏移量间的数据是系统填充的无效数据）．</p>
<p>&nbsp;<wbr>下面针对解复用程序详细分析一下PAT,PMT和SDT三类表格的格式．</p>
<p>PAT,&nbsp;<wbr>Program&nbsp;<wbr>Association&nbsp;<wbr>Table,节目关联表</p>
<p>&nbsp;<wbr>PAT表携带以下信息:</p>
<p>(1)&nbsp;<wbr>TS流ＩＤ---&nbsp;<wbr>transport_stream_id,该ＩＤ标志唯一的流ＩＤ</p>
<p>(2)&nbsp;<wbr>节目频道号--&nbsp;<wbr>program_number,该号码标志ＴＳ流中的一个频道，该频道可以包含很多的节目(即可以包含多个Video&nbsp;<wbr>PID和Audio&nbsp;<wbr>PID)</p>
<p>(3)&nbsp;<wbr>PMT的PID---&nbsp;<wbr>program_map_PID,表示本频道使用的哪个PID做为PMT的ＰＩＤ，因为可以有很多的频道，因此ＤＶＢ规定PMT的PID可以由用户自己定义．</p>
<p>PAT表定义如下:</p>
<p>&nbsp;<wbr></p>
<p>各字段含义如下:</p>
<p>&nbsp;<wbr>table_id:8&nbsp;<wbr>bits,标志本表格的类型，应该是0x00</p>
<p>&nbsp;<wbr>section_syntax_indicator:1&nbsp;<wbr>bit,段语法标志，应该是'1'</p>
<p>&nbsp;<wbr>'0':固定的'0'，这是为了防止和ISO13818Video流格式中的控制字冲突而设置的．</p>
<p>&nbsp;<wbr>Reserved:保留的2bits,保留位一般都是'0'</p>
<p>&nbsp;<wbr>section_length:12bits的段大小，单位是Bytes.</p>
<p>&nbsp;<wbr>transport_stream_id:16bits的当前流ＩＤ，ＤＶＢ内唯一.(事实上很多都是自定义的TS&nbsp;<wbr>ID)</p>
<p>&nbsp;<wbr>version_number:5bits版本号码，标注当前节目的版本．这是个非常有用的参数，当检测到这个字段改变时，说明ＴＳ流中的节目已经变化了，程序必须重新搜索节目．</p>
<p>&nbsp;<wbr>current_next_indicator:1bit:当前还是未来使用标志符,一般情况下为'0'</p>
<p>&nbsp;<wbr>section_number:8bits当前段号码</p>
<p>&nbsp;<wbr>last_section_number:8bits最后段号码(section_number和last_section_number的功能是当PAT内容&gt;184字节时，PAT表会分成多个段(sections),解复用程序必须在全部接收完成后再进行PAT的分析)</p>
<p>&nbsp;<wbr>从for()开始，就是描述了当前流中的频道数目(N),每一个频道对应的PMT&nbsp;<wbr>PID是什么．解复用程序需要和上图类似的循环来接收所有的频道号码和对应的PMT&nbsp;<wbr>PID,并把这些信息在缓冲区中保存起来．在后部的处理中需要使用到PMT&nbsp;<wbr>PID.</p>
<p>&nbsp;<wbr>CRC_32:本段的CRC校验值，一般是会忽略的．N是一个变量，计算方法是N=(section_length-9)/4.</p>
<p>&nbsp;<wbr>从以上分析我们可以发现,PAT表主要包含频道号码和每一个频道对应的PMT的PID号码,这些信息我们在处理PAT表格的时候会保存起来,以后会使用到这些数据.例如我们可以定义这样的数据结构保存这些信息:</p>
<p>&nbsp;<wbr>typedef&nbsp;<wbr>struct</p>
<p>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>int&nbsp;<wbr>channel_number;</p>
<p>&nbsp;<wbr>&nbsp;<wbr>int&nbsp;<wbr>pmt_pid;</p>
<p>&nbsp;<wbr>}PMT_ITEM;</p>
<p>&nbsp;<wbr>PMT_ITEM&nbsp;<wbr>pmt[64];</p>
<p>PMT,&nbsp;<wbr>Program&nbsp;<wbr>Map&nbsp;<wbr>Table,节目影射表</p>
<p>&nbsp;<wbr>如果一个TS流中含有多个频道,那么就会包含多个PID不同的PMT表.检测是否PMT的伪代码如下:</p>
<p>&nbsp;<wbr>void&nbsp;<wbr>Process_Packet(unsigned&nbsp;<wbr>char*buff)</p>
<p>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>int&nbsp;<wbr>I;</p>
<p>&nbsp;<wbr>&nbsp;<wbr>int&nbsp;<wbr>PID=GETPID(buff);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>if(PID==0x0000)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>Process_PAT(buff+4);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>else&nbsp;<wbr>if(PID==.....)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>else</p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>for(i=0;i&lt;64;i++)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>if(PID==pmt[i].pmt_pid)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>Process_PMT(buff+4);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>break;</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>}&nbsp;<wbr></p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>}</p>
<p>PMT表中包含的数据如下:</p>
<p>(1)&nbsp;<wbr>当前频道中包含的所有Video数据的PID</p>
<p>(2)&nbsp;<wbr>当前频道中包含的所有Audio数据的PID</p>
<p>(3)&nbsp;<wbr>和当前频道关联在一起的其他数据的PID(如数字广播,数据通讯等使用的PID)</p>
<p>PMT定义如下:</p>
<p>&nbsp;<wbr></p>
<p>各字段含义如下:</p>
<p>&nbsp;<wbr>table_id:8bits的ID,应该是0x02</p>
<p>&nbsp;<wbr>section_syntax_indicator:1bit的段语法标志,应该是'1'</p>
<p>&nbsp;<wbr>'0':固定是'0',如果不是说明数据有错.</p>
<p>&nbsp;<wbr>reserved:2bits保留位,应该是'00'</p>
<p>&nbsp;<wbr>section_length:16bits段长度,从program_number开始,到CRC_32(包含)的字节总数.</p>
<p>&nbsp;<wbr>program_number:16bits的频道号码,表示当前的PMT关联到的频道.换句话就是说,当前描述的是program_number频道的信息.</p>
<p>&nbsp;<wbr>reserved:2bits保留位,应该是'00'</p>
<p>&nbsp;<wbr>version_number:版本号码,如果PMT内容有更新,则version_number会递增1通知解复用程序需要重新接收节目信息,否则version_number是固定不变的.</p>
<p>&nbsp;<wbr>current_next_indicator:当前未来标志符,一般是0</p>
<p>&nbsp;<wbr>section_number:当前段号码</p>
<p>&nbsp;<wbr>last_section_number:最后段号码,含义和PAT中的对应字段相同,请参考PAT部分.</p>
<p>&nbsp;<wbr>reserved:3bits保留位,一般是'000'.</p>
<p>&nbsp;<wbr>PCR_PID:13bits的PCR&nbsp;<wbr>PID,具体请参考ISO13818-1,解复用程序不使用该参数.</p>
<p>reserved:4bits保留位,一般是'0000'</p>
<p>program_info_length:节目信息长度(之后的是N个描述符结构,一般可以忽略掉,这个字段就代表描述符总的长度,单位是Bytes)</p>
<p>紧接着就是频道内部包含的节目类型和对应的PID号码了.</p>
<p>stream_type:8bits流类型,标志是Video还是Audio还是其他数据.</p>
<p>reserved:3&nbsp;<wbr>bits保留位.</p>
<p>elementary_PID:13bits对应的数据PID号码(如果stream_type是Video,那么这个PID就是Video&nbsp;<wbr>PID,如果stream_type标志是Audio,那么这个PID就是Audio&nbsp;<wbr>PID)</p>
<p>reserved:4&nbsp;<wbr>bits保留位.</p>
<p>ES_info_length:和program_info_length类似的信息长度(其后是N2个描述符号)</p>
<p>CRC_32:32bits段末尾是本段的CRC校验值,一般忽略.</p>
<p>从以上的分析可以看出,只要我们处理了PMT,那么我们就可以获取频道中所有的PID信息,例如当前频道包含多少个Video,共多少个Audio,和其他数据,还能知道每种数据对应的PID分别是什么.</p>
<p>这样如果我们要选择其中一个Video和Audio收看,那么只需要把要收看的节目的Video&nbsp;<wbr>PID和Audio&nbsp;<wbr>PID保存起来,在处理Packet的时候进行过滤即可实现.</p>
<p>比较全面实现解复用的伪代码如下:</p>
<p>int&nbsp;<wbr>Video_PID=0x07e5,Audio_PID=0x07e6;</p>
<p>void&nbsp;<wbr>Process_Packet(unsigned&nbsp;<wbr>char*buff)</p>
<p>{</p>
<p>&nbsp;<wbr>int&nbsp;<wbr>I;</p>
<p>&nbsp;<wbr>int&nbsp;<wbr>PID=GETPID(buff);</p>
<p>&nbsp;<wbr>if(PID==0x0000)</p>
<p>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>Process_PAT(buff+4);</p>
<p>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>else&nbsp;<wbr>if(PID==Video_PID)</p>
<p>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>SaveToVideoBuffer(buff+4);</p>
<p>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>else&nbsp;<wbr>if(PID==Audio_PID)</p>
<p>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>SaveToAudioBuffer(buff+4);</p>
<p>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>else</p>
<p>{</p>
<p>&nbsp;<wbr>for(&nbsp;<wbr>i=0;i&lt;64;i++)</p>
<p>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>if(PID==pmt[i].pmt_pid)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>{</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>Process_PMT(buff+4);</p>
<p>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>Break;</p>
<p>&nbsp;<wbr>&nbsp;<wbr>}</p>
<p>&nbsp;<wbr>}</p>
<p>}&nbsp;<wbr></p>
<p>&nbsp;<wbr></p>
<p>}</p>
<p>以上伪代码可以实现基本的解复用:检测所有的频道,检测所有stream的PID,选择特定的节目进行播放.只要读取每个Packet的188字节的内容,然后每次都调用Process_Packet()即可实现简单的解复用.</p>
<p>介绍到这里,我们就可以总结一下DVB搜台的原理了.(好!洗耳恭听!)</p>
<p>&nbsp;<wbr>&nbsp;<wbr>机&nbsp;<wbr>顶盒先调整高频头到一个固定的频率(如498MHZ),如果此频率有数字信号,则COFDM芯片(如MT352)会自动把TS流数据传送给MPEG-&nbsp;<wbr>2&nbsp;<wbr>decoder.&nbsp;<wbr>MPEG-2&nbsp;<wbr>decoder先进行数据的同步,也就是等待完整的Packet的到来.然后循环查找是否出现PID==&nbsp;<wbr>0x0000的Packet,如果出现了,则马上进入分析PAT的处理,获取了所有的PMT的PID.接着循环查找是否出现PMT,如果发现了,则自动进&nbsp;<wbr>入PMT分析,获取该频段所有的频道数据并保存.如果没有发现PAT或者没有发现PMT,说明该频段没有信号,进入下一个频率扫描.</p>
<p>&nbsp;<wbr>&nbsp;<wbr>从以上描述可以看出,机顶盒搜索频率是随机发生的,要使每次机顶盒都能搜索到信号,则要求TS流每隔一段时间就发送一次PAT和PMT.事实上DVB传输系统就是这么做的.因此无论何时接入终端系统,系统都能马上搜索到节目并正确解复用实现播放.不仅仅如此,其他数据也都是交替传送的.比如第一个Packet可能是PAT,第二个Packet可能是PMT,而第三个Packet可能是Video&nbsp;<wbr>1,第四个Packet可能是Video&nbsp;<wbr>2,</p>
<p>只要系统传输速度足够快(就是称之为"码率"的东东),实现实时播放是没有任何问题的.</p>
<p>&nbsp;<wbr>到这里虽然实现了解复用,但可以看出,使用的PID都是枯燥的数字,如果调台要用户自己输入数字那可是太麻烦了,而且还容易输入错误,操作非常不直观,即使做成一个菜单让用户选择也是非常的呆板.针对这个问题,DVB系统提出了一个SDT表格,该表格标志一个节目的名称,并且能和PMT中的PID联系起来,这样用户就可以通过直接选择节目名称来选择节目了.</p>
<p>SDT,&nbsp;<wbr>Service&nbsp;<wbr>description&nbsp;<wbr>section,服务描述段</p>
<p>&nbsp;<wbr>SDT可以提供的信息包括:</p>
<p>(1)&nbsp;<wbr>该节目是否在播放中</p>
<p>(2)&nbsp;<wbr>该节目是否被加密</p>
<p>(3)&nbsp;<wbr>该节目的名称</p>
<p>SDT定义如下:</p>
<p>&nbsp;<wbr></p>
<p>各字段定义如下:</p>
<p>&nbsp;<wbr>table_id:8bits的ID,可以是0x42,表示描述的是当前流的信息,也可以是0x46,表示是其他流的信息(EPG使用此参数)</p>
<p>&nbsp;<wbr>section_syntax_indicator:段语法标志,一般是'1'</p>
<p>&nbsp;<wbr>reserved_future_used:2bits保留未来使用</p>
<p>&nbsp;<wbr>reserved:1bit保留位,防止控制字冲突,一般是'0',也有可能是'1'</p>
<p>&nbsp;<wbr>section_length:12bits的段长度,单位是Bytes,从transport_stream_id开始,到CRC_32结束(包含)</p>
<p>&nbsp;<wbr>transport_stream_id:16bits当前描述的流ID</p>
<p>&nbsp;<wbr>reserved:2bits保留位</p>
<p>&nbsp;<wbr>version_number:5bits的版本号码,如果数据更新则此字段递增1</p>
<p>&nbsp;<wbr>current_next_indicator:当前未来标志,一般是'0',表示当前马上使用.</p>
<p>&nbsp;<wbr>original_netword_id:16bits的原始网络ID号</p>
<p>&nbsp;<wbr>reserved_future_use:8bits保留未来使用位</p>
<p>&nbsp;<wbr>接下来是N个节目信息的循环:</p>
<p>&nbsp;<wbr>&nbsp;<wbr>service_id:16&nbsp;<wbr>bits的服务器ID,实际上就是PMT段中的program_number.</p>
<p>&nbsp;<wbr>&nbsp;<wbr>reserved_future_used:6bits保留未来使用位</p>
<p>&nbsp;<wbr>&nbsp;<wbr>EIT_schedule_flag:1bit的EIT信息,1表示当前流实现了该节目的EIT传送</p>
<p>&nbsp;<wbr>&nbsp;<wbr>EIT_present_following_flag:1bits的EIT信息,1表示当前流实现了该节目的EIT传送</p>
<p>&nbsp;<wbr>&nbsp;<wbr>running_status:3bits的运行状态信息:1-还未播放&nbsp;<wbr>2-几分钟后马上开始,3-被暂停播出,4-正在播放,其他---保留</p>
<p>&nbsp;<wbr>&nbsp;<wbr>free_CA_mode:1bits的加密信息,'1'表示该节目被加密.</p>
<p>&nbsp;<wbr>&nbsp;<wbr>紧&nbsp;<wbr>接着的是描述符,一般是Service&nbsp;<wbr>descriptor,分析此描述符可以获取servive_id指定的节目的节目名称.具体格式请参考&nbsp;<wbr>EN300468中的Service&nbsp;<wbr>descriptor部分.分析完毕,则节目名称和节目号码已经联系起来了.机顶盒程序就可以用这些节目名称代替&nbsp;<wbr>PID让用户选择,从而实现比较友好的用户界面!</p>
<p>&nbsp;<wbr>下面参考一下&lt;&lt;Seekfor&nbsp;<wbr>MPEG2&nbsp;<wbr>decoder&gt;&gt;中的界面和显示信息.</p>
<p>&nbsp;<wbr></p>
<p>上&nbsp;<wbr>图是&lt;&lt;Seekfor&nbsp;<wbr>MPEG2&nbsp;<wbr>decoder&gt;&gt;打开三个不同的码流文件(*.ts)形成的PID信息和节目名称.用户&nbsp;<wbr>可以通过切换节目名称的下拉列表框切换节目,也可以通过"视频流"和"音频流"下拉列表框切换Video和Audio!这些数据都是通过分析PAT,&nbsp;<wbr>PMT和SDT得到的.</p>
</div>
<img src ="http://www.cppblog.com/elva/aggbug/66734.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/elva/" target="_blank">叶子</a> 2008-11-12 17:51 <a href="http://www.cppblog.com/elva/archive/2008/11/12/66734.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>