多媒体杂谈--有点乱后继整理

 1章.     RTP 

1.1.  RTP是什么

RTP全名是Real-time Transport Protocol(实时传输协议)。它是IETF提出的一个标准,对应的RFC文档为RFC3550RFC1889为其过期版本)。RFC3550不仅定义了RTP,而且定义了配套的相关协议RTCPReal-time Transport Control Protocol,即实时传输控制协议)。RTP用来为IP网上的语音、图像、传真等多种需要实时传输的多媒体数据提供端到端的实时传输服务。RTPInternet上端到端的实时传输提供时间信息和流同步,但并不保证服务质量,服务质量由RTCP来提供。

1.2.  RTP头

 

开始12个字节出现在每个RTP包中,而CSRC标识列表仅出现在混合器插入时。各段含义如下:

① 本(V)

2位,标识RTP版本。目前都是2.

② 充标识(P)

1位,如设置填充位,在包尾将包含附加填充字,它不属于有效载荷。填充的最后一个八进制包含应该忽略的八进制计数。某些加密算法需要固定大小的填充字,或为在底层协议数据单元中携带几个RTP包。当前不使用特殊的加密算法,因此该位设为 0。

③ 展(X)

1位,如设置扩展位,固定头后跟一个头扩展。目前只有手机视频会带扩展头

④CSRC计数(CC)

4位,CSRC计数包括紧接在固定头后CSRC标识符个数。

④ 记(M)

1位,标记解释由设置定义,目的在于允许重要事件在包流中标记出来。设置可定义其他标示位,或通过改变位数量来指定没有标记位。

音频时该位为0,视频时需要使用,最后一个slice需要设置为1.

 

⑥载荷类型(PT)

7位,记录后面资料使用哪种 Codec  receiver 端找出相应的 decoder 解碼出來。

常用 types:

Payload Type

Codec

0

PCM μ Law

8

PCM-A Law

9

G..722 audio codec

4

G..723 audio codec

15

G..728 audio codec

18

G..729 audio codec

34

G..763 audio codec

31

G..761 audio codec

93

nvoc audio codec(P)

98

H264 video codec(b)

126

AMR audio codec(b)

 

下表中没指定的都应该是厂商自定义。

注:

               PT      encoding    media type  clock rate

                       name                    (Hz)

               _____________________________________________

               24      unassigned  V

               25      CelB        V           90,000

               26      JPEG        V           90,000

               27      unassigned  V

               28      nv          V           90,000

               29      unassigned  V

               30      unassigned  V

               31      H261        V           90,000

               32      MPV         V           90,000

               33      MP2T        AV          90,000

               34      H263        V           90,000

               35-71   unassigned  ?

               72-76   reserved    N/A         N/A

               77-95   unassigned  ?

               96-127  dynamic     ?

               dyn     H263-1998   V           90,000

 

               Table 5: Payload types (PT) for video and combined

                        Encodings

 

               PT   encoding    media type  clock rate   channels

                    name                    (Hz)

               ___________________________________________________

               0    PCMU        A            8,000       1

               1    reserved    A

               2    reserved    A

               3    GSM         A            8,000       1

               4    G723        A            8,000       1

               5    DVI4        A            8,000       1

               6    DVI4        A           16,000       1

               7    LPC         A            8,000       1

               8    PCMA        A            8,000       1

               9    G722        A            8,000       1

               10   L16         A           44,100       2

               11   L16         A           44,100       1

               12   QCELP       A            8,000       1

               13   CN          A            8,000       1

               14   MPA         A           90,000       (see text)

               15   G728        A            8,000       1

               16   DVI4        A           11,025       1

               17   DVI4        A           22,050       1

               18   G729        A            8,000       1

               19   reserved    A

               20   unassigned  A

               21   unassigned  A

               22   unassigned  A

               23   unassigned  A

               dyn  G726-40     A            8,000       1

               dyn  G726-32     A            8,000       1

               dyn  G726-24     A            8,000       1

               dyn  G726-16     A            8,000       1

               dyn  G729D       A            8,000       1

               dyn  G729E       A            8,000       1

               dyn  GSM-EFR     A            8,000       1

               dyn  L8          A            var.        var.

               dyn  RED         A                        (see text)

               dyn  VDVI        A            var.        1

 

               Table 4: Payload types (PT) for audio encodings

 

 

⑦系列号

16位,系列号随每个RTP数据包而增加1,由接收者用来探测包损失。系列号初值是随机的,使对加密的文本攻击更加困难。

⑧时标

32位,时标反映RTP数据包中第一个八进制数的采样时刻,采样时刻必须从单调、线性增加的时钟导出,以允许同步与抖动计算。时标可以让receiver端知道在正确的时间将资料播放出来。

 

由上图可知,如果只有系列号,并不能完整按照顺序的将data播放出来,因为如果data中间有一段是没有资料的,只有系列号的话会造成错误,需搭配上让它知道在哪个时间将data正确播放出来,如此我们才能播放出正确无误的信息。

⑨SSRC

32位,SSRC段标识同步源。此标识不是随机选择的,目的在于使同一RTP包连接中没有两个同步源有相同的SSRC标识。尽管多个源选择同一个标识的概率很低,所有RTP实现都必须探测并解决冲突。如源改变源传输地址,也必须选择一个新SSRC标识以避免插入成环行源。

⑩CSRC列表

0到15项,每项32位。CSRC列表表示包内的对载荷起作用的源。标识数量由CC段给出。如超出15个作用源,也仅标识15个。CSRC标识由混合器插入,采用作用源的SSRC标识。

我们b系统一般都是0个,没有此项。

 

1.2.1 Rtp扩展头结构

RTP 提供扩展机制以允许实现个性化:某些新的与负载格式独立的功能要求的附加信息在RTP 数据包头中传输。设计此方法可以使其它没有扩展的交互忽略此头扩展。RTP扩展头格式如图2所示。                                 

        2 RTP扩展头格式

RTP 固定头中的扩展比特位置 1,则一个长度可变的头扩展部分被加到 RTP 固定头之后。头扩展包含 16 比特的长度域,指示扩展项中 32 比特字的个数,不包括 4 个字节扩展头(因此零是有效值)RTP 固定头之后只允许有一个头扩展。为允许多个互操作实现独立生成不同的头扩展,或某种特定实现有多种不同的头扩展,扩展项的前 16 比特用以识别标识符或参数。这 16 比特的格式由具体实现的上层协议定义。基本的 RTP 说明并不定义任何头扩展本身。

1.2.2 视频RTP包扩展头定义

在扩展头里面我们需要填充版本号、角度值等内容,设计如图3所示:

0

1

2

3

0

1

2

3

4

5

6

7

0

1

2

3

4

5

6

7

0

1

2

3

4

5

6

7

0

1

2

3

4

5

6

7

Defined by Profile(bc)

Length(1)

Version(0000 0000 0000 0001)

Degree

 

其中Defined by Profile16比特定义为bc,即1011 1100,取Btrun-C的缩写;

Length16比特,取值0000 0000 0000  0001

Version定义为:0000 0000 0000 0001

Degree4比特,填写角度,可以有四个取值(角度除以90):

不旋转:0

顺时针旋转90度:1

顺时针旋转180度:2

顺时针旋转270度:3

 

 

 

1.2.3 视频角度

RTP头扩展里的Degree内容意义是接收端显示视频图像之前需要对图像旋转的角度。增加此值的意义主要有:

1、 不管发送端手机如何旋转,接收端可以按照正的方向显示图像内容;

2、 屏蔽手机硬件上摄像头镜头方向的差异。

 


   Degree = 90           Degree = 180           Degree = 270            Degree = 0

 

 

1.3.  声音和图像怎么同步

根据声音流和图像流的相对时间(即RTP包的时间戳),以及它们的绝对时间(即对应的RTCP包中的RTCP),可以实现声音和图像的同步。

目前无RTCP,怎么实现同步。

 

1.4.  内容封装

live555主要用于网络流接收,ffmpeg则是对接收到的数据进行编码/解码。

1.4.1 分片slice

RFC3984 给出了3 中不同的RTP 打包方案:

1)Single NALU Packet:在一个RTP 包中只封装一个NALU,在本文中对于小于 1400字节的NALU 便采用这种打包方案。 
       (2)Aggregation Packet:在一个RTP 包中封装多个NALU,对于较小的NALU 可以采用这种打包方案,从而提高传输效率。 
       (3)Fragmentation Unit:一个NALU 封装在多个RTP包中,在本文中,对于大于1400字节的NALU 便采用这种方案进行拆包处理。

接收 RTP数据包,从RTP 包中解析出NALU 单元,然后送至解码器进行解码播放。该流媒体传输系统的框架如图3 所示。

 


 

 

1.4.1 I帧P帧

IDRInstantaneous Decoding Refresh--即时解码刷新。 

I:帧内编码帧是一种自带全部信息的独立帧,无需参考其它图像便可独立进行解码,视频序列中的第一个帧始终都是I帧。 

   IIDR帧都是使用帧内预测的。它们都是同一个东西而已,在编码和解码中为了方便,要首个I帧和其他I区别开,所以才把第一个首个I帧叫IDR,这样就方便控制编码和解码流程。 IDR帧的作用是立刻刷新,使错误不致传播,IDR帧开始,重新算一个新的序列开始编码。而I帧不具有随机访问的能力,这个功能是由IDR承担。 IDR会导致DPBDecodedPictureBuffer 参考帧列表——这是关键所在)清空,而I不会IDR图像一定是I图像,但I图像不一定是IDR图像。一个序列中可以有很多的I图像,I图像之后的图像可以引用I图像之间的图像做运动参考。一个序列中可以有很多的I图像,I图像之后的图象可以引用I图像之间的图像做运动参考。 

   对于IDR帧来说,在IDR帧之后的所有帧都不能引用任何IDR帧之前的帧的内容,与此相反,对于普通的I-帧来说,位于其之后的B-P-帧可以引用位于普通I-帧之前的I-帧。从随机存取的视频流中,播放器永远可以从一个IDR帧播放,因为在它之后没有任何帧引用之前的帧。但是,不能在一个没有IDR帧的视频中从任意点开始播放,因为后面的帧总是会引用前面的帧 

  收到 IDR 帧时,解码器另外需要做的工作就是:把所有的 PPS  SPS 参数进行更新。

  IDR帧的处理(I帧的处理相同)(1) 进行帧内预测,决定所采用的帧内预测模式。(2) 像素值减去预测值,得到残差。(3) 对残差进行变换和量化。(4) 变长编码和算术编码。(5) 重构图像并滤波,得到的图像作为其它帧的参考帧。

  多参考帧情况下,  举个例子 :有如下帧序列: IPPPP I P PPP ……。按照 3 个参考帧编码。

     因为按照 3 个参考帧编码,所以参考帧队列长度为 3 

    遇到绿色的 I 时,并不清空参考帧队列,把这个 I 帧加入参考帧队列(当然 I 编码时不用参考帧。)。再检测到红色的 P 帧时,用到的就是 PPI 三帧做参考了。

 

P:前向预测编码帧

    在针对连续动态图像编码时,将连续若干幅图像分成P,B,I三种类型,P帧由在它前面的P帧或者I帧预测而来,它比较与它前面的P帧或者I帧之间的相同信息或数据,也即考虑运动的特性进行帧间压缩。P帧法是根据本帧与相邻的前一帧(I帧或P帧)的不同点来压缩本帧数据。采取P帧和I帧联合压缩的方法可达到更高的压缩且无明显的压缩痕迹。

P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P某点预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P某点的预测值并与差值相加以得到P帧某点样值,从而可得到完整的P帧。

有的视频序列比较简单,就没有B帧,

B帧:双向预测内插编码帧

B帧的预测与重构

 B帧法是双向预测的帧间压缩算法。当把一帧压缩成B帧时,它根据相邻的前一帧、本帧以及后一帧数据的不同点来压缩本帧,也即仅记录本帧与前后帧的差值。只有采用B帧压缩才能达到2001的高压缩。

 B帧是以前面的IP帧和后面的P帧为参考帧,找出B某点的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中

 

1.4.3  H.264视频RTP负载格式  

2012-03-14 20:46:49|  分类: Live555学习笔记 |  标签: |举报 |字号大中小 订阅

1. 网络抽象层单元类型 (NALU)Network Abstract Layer Unit

NALU 头由一个字节组成, 它的语法如下:

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+

F: 1 个比特.
  forbidden_zero_bit. H.264 规范中规定了这一位必须为 0.

NRI: 2 个比特.
  nal_ref_idc. 00 ~ 11, 似乎指示这个 NALU 的重要性, 00 NALU 解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心这个属性.

Type: 5 个比特.
  nal_unit_type. 这个 NALU 单元的类型. 简述如下:

  0     没有定义
  1-23  NAL单元  单个 NAL 单元包.
  24    STAP-A   单一时间的组合包
  25    STAP-B   单一时间的组合包
  26    MTAP16   多个时间的组合包
  27    MTAP24   多个时间的组合包
  28    FU-A     分片的单元
  29    FU-B     分片的单元
  30-31 没有定义

    0:未规定
    1:非IDR图像中不采用数据划分的片段
    2:非IDR图像中A类数据划分片段
    3:非IDR图像中B类数据划分片段
    4:非IDR图像中C类数据划分片段
    5IDR图像的片段
    6:补充增强信息 (SEI)
    7:序列参数集
    8:图像参数集
    9:分割符
    10:序列结束符
    11:流结束符
    12:填充数据

NALU 包括一个片、SPSPPSSEI等等

序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)、条带(Slice)等,其中,SPSPPS属于参数集,两标准采用参数集机制是为了将一些主要的序列、图像参数(解码图像尺寸、片组数、参考帧数、量化和滤波参数标记等)与其他参数分离,通过解码器先解码出来。此外,为了增强图像的清晰度,AVS-M添加了图像头(Picture head)信息。

 

2. 打包模式

  下面是 RFC 3550 中规定的 RTP 头的结构.

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |V=2|P|X|  CC   |M|     PT      |       sequence number         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           timestamp                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           synchronization source (SSRC) identifier            |
      +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
      |            contributing source (CSRC) identifiers             |
      |                             ....                              |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  负载类型 Payload type (PT): 7 bits
  序列号 Sequence number (SN): 16 bits
  时间戳 Timestamp: 32 bits
 
  H.264 Payload 格式定义了三种不同的基本的负载(Payload)结构. 接收端可能通过 RTP Payload的第一个字节来识别它们. 这一个字节类似 NALU 头的格式, 而这个头结构的 NAL 单元类型字段则指出了代表的是哪一种结构,这个字节的结构如下, 可以看出它和 H.264 NALU 头结构是一样的.
      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+
  字段 Type: 这个 RTP payload NAL 单元的类型. 这个字段和 H.264 中类型字段的区别是, type
  的值为 24 ~ 31 表示这是一个特别格式的 NAL 单元, H.264 , 只取 1~23 是有效的值.
  
  24    STAP-A   单一时间的组合包
  25    STAP-B   单一时间的组合包
  26    MTAP16   多个时间的组合包
  27    MTAP24   多个时间的组合包
  28    FU-A     分片的单元
  29    FU-B     分片的单元
  30-31 没有定义

  可能的结构类型分别有:

  1. 单一 NAL 单元模式
     即一个 RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264
  NALU 头类型字段是一样的.

  2. 组合封包模式
    即可能是由多个 NAL 单元组成一个 RTP . 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.
  那么这里的类型值分别是 24, 25, 26 以及 27.

  3. 分片封包模式
    用于把一个 NALU 单元封装成多个 RTP . 存在两种类型 FU-A FU-B. 类型值分别是 28 29.

2.1 单一 NAL 单元模式

  对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式.
  对于一个原始的 H.264 NALU 单元常由 [Start Code] [NALU Header] [NALU Payload] 三部分组成, 其中 Start Code 用于标示这是一个NALU 单元的开始, 必须是 "00 00 00 01" "00 00 01", NALU 头仅一个字节, 其后都是 NALU 单元内容.
  打包时去除 "00 00 01" "00 00 00 01" 的开始码, 把其他数据封包的 RTP 包即可.

       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |F|NRI|  type   |                                               |
      +-+-+-+-+-+-+-+-+                                               |
      |                                                               |
      |               Bytes 2..n of a Single NAL unit                 |
      |                                                               |
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


  如有一个 H.264 NALU 是这样的:

  [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]

  这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 NALU , 42 开始的数据是 NALU 内容.

  封装成 RTP 包将如下:

  [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

  即只要去掉 4 个字节的开始码就可以了.

 

67b视频中也常用,Type=7序列参数集

Type=7图像参数集


2.2 组合封包模式

  其次, NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 RTP 包中.

 
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                          RTP Header                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |STAP-A NAL HDR |         NALU 1 Size           | NALU 1 HDR    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         NALU 1 Data                           |
      :                                                               :
      +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |               | NALU 2 Size                   | NALU 2 HDR    |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                         NALU 2 Data                           |
      :                                                               :
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


2.3 Fragmentation Units (FUs).

  而当 NALU 的长度超过 MTU , 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs).
 
       0                   1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      | FU indicator  |   FU header   |                               |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
      |                                                               |
      |                         FU payload                            |
      |                                                               |
      |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                               :...OPTIONAL RTP padding        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

      Figure 14.  RTP payload format for FU-A

   The FU indicator octet has the following format:

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+

   The FU header has the following format:

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |S|E|R|  Type   |
      +---------------+

其中S为一个NALU的开始标识,E为NALU的结束标识,R为保留位。

 

b视频分片payload:

 

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |0| 1111100=28|
      +---------------+

FU-A 

5CP帧),7CI帧)

 

FU的header:

 

      +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |S|E|R|  Type   |
      +---------------+

      |0|0|0|00101=5  |

第一包S为1,中间包S为0,最后一包E为1.

 

1.4.4  SPS和PPS

NAL nal_unit_type 为序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)不属于啥帧的概念。表示后面的数据信息为序列参数集(SPS)、图像参数集(PPS)、增强信息(SEI)。

 

http://blog.csdn.net/heanyu/article/details/6205390

 

MP4中SPS、PPS:

http://blog.csdn.net/jinlking/article/details/19124025

【参考依据】ISO/IEC 14496-15 下载

【综述】在H264中,SPSPPS存在于NALU header中,而在MP4文件中,SPSPPS存在于AVCDecoderConfigurationRecord, 首先要定位avcC.

【定义】

参数集:一组很少改变的,为大量VCL NALU 提供解码信息的数据。

   序列参数集SPS作用于一系列连续的编码图像,而图像参数集PPS作用于编码视频序列中一个或多个独立的图像。

   如果解码器没能正确接收到这两个参数集,那么其他NALU 也是无法解码的。因此它们一般在发送其它 NALU 之前发送,并且使用不同的信道或者更加可靠的传输协议(如TCP)进行传输,也可以重复传输。

②关于AVCDecoderConfigurationRecord结构定义为  

 

【实例分析】 数据如上avcC图所示,现在对数据进行详细分析

 

所以,提取的SPSPPS分别为67 42 00 1E A6 81 41 F968 CE 38 80

 

H.264编码原理

H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内。所以对于一段变化不大图像画面,我们可以先编码出一个完整的图像帧A,随后的B帧就不编码全部图像,只写入与A帧的差别,这样B帧的大小就只有完整帧的1/10或更小!B帧之后的C帧如果变化不大,我们可以继续以参考B的方式编码C帧,这样循环下去。这段图像我们称为一个序列(序列就是有相同特点的一段数据),当某个图像与之前的图像变化很大,无法参考前面的帧来生成,那我们就结束上一个序列,开始下一段序列,也就是对这个图像生成一个完整帧A1,随后的图像就参考A1生成,只写入与A1的差别内容。

H264协议里定义了三种帧,完整编码的帧叫I帧,参考之前的I帧生成的只包含差异部分编码的帧叫P帧,还有一种参考前后的帧编码的帧叫B帧。

H264采用的核心算法是帧内压缩和帧间压缩,帧内压缩是生成I帧的算法,帧间压缩是生成B帧和P帧的算法。

H264中图像以序列为单位进行组织,一个序列是一段图像编码后的数据流,以I帧开始,到下一个I帧结束。

 一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列。这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。

 一个序列就是一段内容差异不太大的图像编码后生成的一串数据流。当运动变化比较少时,一个序列可以很长,因为运动变化少就代表图像画面的内容变动很小,所以就可以编一个I帧,然后一直P帧、B帧了。当运动变化多时,可能一个序列就比较短了,比如就包含一个I帧和3、4个P帧。

I帧:帧内编码帧,I帧表示关键帧,你可以理解为这一帧画面的完整保留;解码时只需要本帧数据就可以完成(因为包含完整画面)。I帧特点如下:

1. 它是一个全帧压缩编码帧。它将全帧图像信息进行JPEG压缩编码及传输;

2. 解码时仅用I帧的数据就可重构完整图像;

3. I帧描述了图像背景和运动主体的详情;

4. I帧不需要参考其他画面而生成;

5. I帧是P帧和B帧的参考帧(其质量直接影响到同组中以后各帧的质量);

6. I帧是帧组GOP的基础帧(第一帧),在一组中只有一个I帧;

7. I帧不需要考虑运动矢量;

8. I帧所占数据的信息量比较大。

P帧:前向预测编码帧。P帧表示的是这一帧跟之前的一个关键帧(或P帧)的差别,解码时需要用之前缓存的画面叠加上本帧定义的差别,生成最终画面。(也就是差别帧,P帧没有完整画面数据,只有与前一帧的画面差别的数据)。

P帧的预测与重构:P帧是以I帧为参考帧,在I帧中找出P帧“某点”的预测值和运动矢量,取预测差值和运动矢量一起传送。在接收端根据运动矢量从I帧中找出P帧“某点”的预测值并与差值相加以得到P帧“某点”样值,从而可得到完整的P帧。P帧特点如下:

1. P帧是I帧后面相隔1~2帧的编码帧;

2. P帧采用运动补偿的方法传送它与前面的I或P帧的差值及运动矢量(预测误差);

3. 解码时必须将I帧中的预测值与预测误差求和后才能重构完整的P帧图像;

4. P帧属于前向预测的帧间编码。它只参考前面最靠近它的I帧或P帧;

5. P帧可以是其后面P帧的参考帧,也可以是其前后的B帧的参考帧;

6. 由于P帧是参考帧,它可能造成解码错误的扩散;

7. 由于是差值传送,P帧的压缩比较高。

B帧:双向预测内插编码帧。B帧是双向差别帧,也就是B帧记录的是本帧与前后帧的差别(具体比较复杂,有4种情况),换言之,要解码B帧,不仅要取得之前的缓存画面,还要解码之后的画面,通过前后画面的与本帧数据的叠加取得最终的画面。B帧压缩率高,但是解码时CPU会比较累。

B帧的预测与重构:B帧以前面的I或P帧和后面的P帧为参考帧,“找出”B帧“某点”的预测值和两个运动矢量,并取预测差值和运动矢量传送。接收端根据运动矢量在两个参考帧中“找出(算出)”预测值并与差值求和,得到B帧“某点”样值,从而可得到完整的B帧。B帧特点如下:

1. B帧是由前面的I或P帧和后面的P帧来进行预测的;

2. B帧传送的是它与前面的I或P帧和后面的P帧之间的预测误差及运动矢量;

3. B帧是双向预测编码帧;

4. B帧压缩比最高,因为它只反映丙参考帧间运动主体的变化情况,预测比较准确;

5. B帧不是参考帧,不会造成解码错误的扩散。

:I、B、P各帧是根据压缩算法的需要,是人为定义的,它们都是实实在在的物理帧。一般来说,I帧的压缩率是7(跟JPG差不多),P帧是20,B帧可以达到50。可见使用B帧能节省大量空间,节省出来的空间可以用来保存多一些I帧,这样在相同码率下,可以提供更好的画质。

h264的压缩方法:

1. 分组:把几帧图像分为一组(GOP,也就是一个序列),为防止运动变化,帧数不宜取多。

2. 定义帧:将每组内各帧图像定义为三种类型,即I帧、B帧和P帧;

3. 预测帧:以I帧做为基础帧,以I帧预测P帧,再由I帧和P帧预测B帧;

4. 数据传输:最后将I帧数据与预测的差值信息进行存储和传输。

帧内(Intraframe)压缩也称为空间压缩(Spatial compression)。当压缩一帧图像时,仅考虑本帧的数据而不考虑相邻帧之间的冗余信息,这实际上与静态图像压缩类似。帧内一般采用有损压缩算法,由于帧内压缩是编码一个完整的图像,所以可以独立的解码、显示。帧内压缩一般达不到很高的压缩,跟编码jpeg差不多。

帧间(Interframe)压缩的原理是:相邻几帧的数据有很大的相关性,或者说前后两帧信息变化很小的特点。也即连续的视频其相邻帧之间具有冗余信息,根据这一特性,压缩相邻帧之间的冗余量就可以进一步提高压缩量,减小压缩比。帧间压缩也称为时间压缩(Temporal compression),它通过比较时间轴上不同帧之间的数据进行压缩。帧间压缩一般是无损的。帧差值(Frame differencing)算法是一种典型的时间压缩法,它通过比较本帧与相邻帧之间的差异,仅记录本帧与其相邻帧的差值,这样可以大大减少数据量。

无损压缩也即压缩前和解压缩后的数据完全一致。多数的无损压缩都采用RLE行程编码算法。有损压缩意味着解压缩后的数据与压缩前的数据不一致。在压缩的过程中要丢失一些人眼和人耳所不敏感的图像或音频信息,而且丢失的信息不可恢复。几乎所有高压缩的算法都采用有损压缩,这样才能达到低数据率的目标。丢失的数据率与压缩比有关,压缩比越小,丢失的数据越多,解压缩后的效果一般越差。此外,某些有损压缩算法采用多次重复压缩的方式,这样还会引起额外的数据丢失。

 

 

52 H.264码流结构示意图

起始码:如果MALU对应的Slice为一帧的开始,则用四字节表示,即0x00000001,否则用三字节表示,即0x000001。为了使NALU主体不包括起始码,在编码时每遇到两个字节(连续)的0,就插入一字节0x03,以和起始码相区别。解码时,则将相应的0x03删除掉。

 

NAL Headerforbidden-bitnal-reference-bit(优先级,2bit)nal-unit-type(类型,5bit)

NAL头信息的nal_referrence_idc(NRI)用于在重建过程中标记一个NAL单元的重要性,值为0表示这个NAL单元没有用预测,因此可以被解码器抛弃而不会有错误扩散;值高于0表示NAL单元要用于无漂移重构,且值越高,对此NAL单元丢失的影响越大。

NAL头信息的隐藏比特位,在H.264编码器中默认为0,当网络识别到单元中存在比特错误时,可将其置为1。隐藏比特位主要用于适应不同种类的网络环境(比如有线无线相结合的环境)。

    Sub mb predmb pred,运动补偿或者是帧内预测。

 

53 新一代视频压缩编码标准H.264中关于nal-unit-type定义

 

H.264编码在RTP报文中传输格式

H.264视频编码在RTP报文中的编码格式,具体可以参考rfc6184。目前终端采用FU-A格式。dserver目前I帧是FU-A,其他帧根据大小,如果只有一个nal大小,则是single NAL Unit 否则是FU-A。

 

 

NAL Unit Type Octet

 

 NRI取值越大,表示优先级越高。当NAL UNIT Type取值范围为1~12时,必须按照H.264编码规范设置HRI的取值,例如当NAL UNIT Type为6,9,10,11,12时,取值为0。当NAL UNIT Type取值为7(sequence parameter set ),8(picture parameter set)时,取值为11。当NAL UNIT Type为5,取值为11。

 

对于Fbit设置为1的NAL Unit,解码器最简单的处理方式就是丢弃该Unit。

single NAL Unit

 

对于single NAL Unit,一个 RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264的  NALU 头类型字段是一样的。

对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式。  对于一个原始的 H.264 NALU 单元常由 [Start Code] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始, 必须是 "00 00 00 01" 或 "00 00 01",NALU 头仅一个字节,其后都是 NALU 单元内容。打包时去除 "00 00 01" 或 "00 00 00 01" 的开始码,把其他数据封入 RTP 包即可。

如有一个 H.264 的 NALU 是这样的:

 [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]

这是一个序列参数集 NAL 单元。[00 00 00 01] 是四个字节的开始码,67 是 NALU 头, 42 开始的数据是 NALU 内容。

封装成 RTP 包将如下:

 [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

 即只要去掉 4 个字节的开始码就可以了。

FU-A

 



 

 

NALU 的长度超过 MTU 时,就必须对 NALU 单元进行分片封包。也称为 Fragmentation Units (FUs)FU-A模式封装的FU Payload也是不传起始码的。对于FU-A的封装,原始的 H.264的  NALU Header通过FU Indicator的高3bit和FU Header的低5bit合并得到。同一帧图像的各个分片其RTP头的时间戳相同,序列号线性递增。

 

H.264流媒体传输框架

通用的打包规则

同一帧图像编码的Slice NAL Unit或者Slice Data partition Nal Unit可以以任意顺序发送,但是,对于实时性要求高的系统,需要按照解码数序发送以减少延时。注意解码顺序指的是NAL Unit在比特流中的顺序。

Single NAL Unit Mode(只有Single NAL Unit可以使用这种模式)和Non-Interleaved Mode(FU-A可以使用这种模式),NAL Unit的发送顺序都要与NAL Unit的解码顺序一致。

通用的解包规则

解包处理和具体实现相关,以下描述可以看作是一个合理的实现例子。也可以采用其它的模式来处理,只要相同的输入与下面的描述得到相同的输出即可。相同的输出指的是得到相同得NAL Unit并且他们的顺序也相同。

报文接收方按照收到报文的先后顺序将报文保存到报文接收缓冲区,报文按照RTP的Sequence Number的顺序来解包。如果是Single NAL Unit报文,报文中包含的NAL Unit直接发送给解码器;如果是包含Single NAL Unit分片的FU-A报文,则解包得到的分片需要按照发送顺序拼接来恢复得到完整的NAL Unit,然后再发送给解码器。(如果解码器支持任意的分片顺序,则一帧图像的编码分片可以按照任意顺序发送给解码器,不用在意其发送和接收顺序)

 

 

第2.     语音 

语音信号因为是准稳态信号,在处理时常把信号分帧,每帧长度约20ms-30ms,在这一区间内把语音信号看作为稳态信号。只有稳态的信息才能进行信号处理,所以要先分帧。 “语音信号分帧进行小波变换”,就是把语音信号分帧后,对每一帧进行小波变换和处理。

2.1.  语音原理/识别

首先,我们知道声音实际上是一种波。常见的mp3、wmv等格式都是压缩格式,必须转成非压缩的纯波形文件,比如Windows PCM文件,即wav文件来处理。wav文件里存储的除了一个文件头以外,就是声音波形的一个个点了。采样率越大,每毫秒语音中包含的点的个数就越多。另外声音有单通道双通道之分,还有四通道的等等。对语音识别任务来说,单通道就足够了,多了浪费,因此一般要把声音转成单通道的来处理。下图是一个波形的示例。

 

在开始语音识别之前,通常需要把首尾端的静音切除,降低对后续步骤造成的干扰。这个静音切除的操作一般称为VAD,需要用到信号处理的一些技术。  静音切除后,就要进行分帧,也就是把声音切开成一小段一小段,每小段称为一帧。具体的分帧操作通常使用移动窗函数来实现,分帧之前还要做一些预加重等操作,这里不详述。帧与帧之间是有交叠的,就像下图这样:

 

 

 

图中,每帧的长度为25毫秒,每两帧之间有25-10=15毫秒的交叠。我们称为以帧长25ms、帧移10ms分帧。  分帧后,语音就变成了很多小段。但波形在时域上几乎没有描述能力,因此必须将波形作变换。常见的一种变换方法是提取MFCC特征,把每一帧波形变成一个12维向量。这12个点是根据人耳的生理特性提取的,可以理解为这12个点包含了这帧语音的内容信息。这个过程叫做声学特征提取。实际应用中,这一步有很多细节,比如差分、均值方差规整、高斯化、降维去冗余等,声学特征也不止有MFCC这一种,具体就不详述了。  至此,声音就成了一个12行(假设声学特征是12维)、N列的一个矩阵,称之为观察序列,这里N为总帧数。观察序列如下图所示,图中,每一帧都用一个12维的向量表示,色块的颜色深浅表示向量值的大小。

如下图所示:

 

图中,每个小竖条代表一帧,若干帧语音对应一个状态,每三个状态组合成一个音素,若干个音素组合成一个单词。也就是说,只要知道每帧语音对应哪个状态了,语音识别的结果也就出来了。  那每帧音素对应哪个状态呢?有个容易想到的办法,看某帧对应哪个状态的概率最大,那这帧就属于哪个状态。比如下面的示意图,这帧对应S3状态的概率最大,因此就让这帧属于S3状态。

 

那这些用到的概率从哪里读取呢?有个叫“声学模型”的东西,里面存了一大堆参数,通过这些参数,就可以知道帧和状态对应的概率。获取这一大堆参数的方法叫做“训练”,需要使用巨大数量的语音数据,训练的方法比较繁琐,这里不讲。  但这样做有一个问题:每一帧都会得到一个状态号,最后整个语音就会得到一堆乱七八糟的状态号,相邻两帧间的状态号基本都不相同。假设语音有1000帧,每帧对应1个状态,每3个状态组合成一个音素,那么大概会组合成300个音素,但这段语音其实根本没有这么多音素。如果真这么做,得到的状态号可能根本无法组合成音素。实际上,相邻帧的状态应该大多数都是相同的才合理,因为每帧很短。  解决这个问题的常用方法就是使用隐马尔可夫模型(Hidden Markov ModelHMM)。这东西听起来好像很高深的样子,实际上用起来很简单: 第一步,构建一个状态网络。 第二步,从状态网络中寻找与声音最匹配的路径。  这样就把结果限制在预先设定的网络中,避免了刚才说到的问题,当然也带来一个局限,比如你设定的网络里只包含了“今天晴天”和“今天下雨”两个句子的状态路径,那么不管说些什么,识别出的结果必然是这两个句子中的一句。  那如果想识别任意文本呢?把这个网络搭得足够大,包含任意文本的路径就可以了。但这个网络越大,想要达到比较好的识别准确率就越难。所以要根据实际任务的需求,合理选择网络大小和结构。  搭建状态网络,是由单词级网络展开成音素网络,再展开成状态网络。语音识别过程其实就是在状态网络中搜索一条最佳路径,语音对应这条路径的概率最大,这称之为“解码”。路径搜索的算法是一种动态规划剪枝的算法,称之为Viterbi算法,用于寻找全局最优路径。

 

这里所说的累积概率,由三部分构成,分别是:

观察概率:每帧和每个状态对应的概率

转移概率:每个状态转移到自身或转移到下个状态的概率

语言概率:根据语言统计规律得到的概率

其中,前两种概率从声学模型中获取,最后一种概率从语言模型中获取。语言模型是使用大量的文本训练出来的,可以利用某门语言本身的统计规律来帮助提升识别正确率。语言模型很重要,如果不使用语言模型,当状态网络较大时,识别出的结果基本是一团乱麻。  这样基本上语音识别过程就完成了。大家应该看懂了吧?  以上介绍的是传统的基于HMM的语音识别。事实上,HMM的内涵绝不是上面所说的“无非是个状态网络”那么简单。以上的文字只是想让大家容易理解,并不追求严谨。  如果感兴趣,想进一步了解,HTK Book是非常好的入门书,这本书实际上是剑桥大学发布的著名开源工具包HTK Speech Recognition Toolkit 的用户文档,近400页,厚厚的一本。如果有时间、有兴趣,可以照着书中的第二章在电脑上做一遍,你将搭建出一个简单但基本完整的语音识别系统,能识别简单的英语数字串。

 

2.2.  语音帧长

G.711的帧长为10ms,位速率为64kbps;

G.722的帧长为10ms,位速率为64kbps;

G.711的帧长为10ms,位速率为64kbps;

G.726-32的帧长为10ms,位速率为32kbps;

G.728的帧长为2.5ms,位速率为16kbps;

G.729的帧长为30ms,位速率为10kbps;

G.723的帧长为30ms,位速率为53kbps;

iLBC的帧长为30ms,位速率为15.2kbps13.3kbps;

 

AMR的帧结构有两种,分别称为AMR Interface Format 1AMR IF1)和AMR Interface Format 2AMR IF2)。一般在有用户面协议支持模式下用AMR IF1格式打包,在没有用户面支持的透明模式下用AMR IF2格式打包。需要说明的在AMR IF1格式下库里只对编码的净荷(语音和噪声数据)打包,至于AMR帧的报头和辅助信息由用户面协议打包。我们程序使用IF1格式。

AMR

Adaptive MutiRate codec

自适应多速率话音编码

 

          AMR的帧类型和帧结构的不同,编码输出的长度是不同的。

 

编码输出的帧类型

 

帧结构1编码输出的长度(单位字节)

帧结构2编码输出的长度(单位字节)

   12.2k语音帧b使用)

          31

31

10.2k语音帧

          26

          26

7.95k语音帧

          20

          21

7.40k语音帧

          19

          19

6.7k语音帧

          17

          18

5.90k语音帧

          15

          16

5.15k语音帧

          13

          14

4.75k语音帧

          12

          13

SID静音帧

          5

          6

空帧

          0

          1

 

 

1 nvoc 13帧, 60ms 1包大小为  3*9+ 12 + 28 = 69 字节  9是一帧的净荷, 12RTP头, 28IP+UDP

 

1秒钟就是  1000/60  * 69 = 1104字节, 也就是1104 bps

 

如果rtpgtpu头有扩展,那就不是这个值了。

 

 

2 AMR12帧, 40ms 1包大小为 1+ 32*2 + 40 + 40 = 145 字节

 

1秒钟就是 1000/40 * 145 = 3625字节, 也就是3625 bps

 

如果AMR一包是1帧, 8帧, 那又不是这个值了。

 

2.3.  AMR

具体可以参考rfc4867

RTP头:

Timsstamp:是指本报文中第一个采样相对于本RTP会话的第一个采样的数目,例如AMR采样频率为8K,20ms一帧的语音报文其中采样数目为160,则每传送一帧的语音报文,timestamp就增加160。

Marker bit (M):如果传送的第一个frame-block包含了一个语音突发的第一个语音帧,则需要将该标志设置为1,否则置0。

 

目前的AMR语音都是单通道语音,没有使用错误检测,Interleaving技术。

Bandwith-Efficient Mode:只有整个AMR载荷是字节对齐的,各个单独的部分是不字节对齐的,以便可以添加比较少的填充位。填充位都是位于least significant bit,并且和RTP报文头中标识的填充位没有关系。填充的bit位取值为0。

Octet-Aligned Mode:AMR头、AMR Table of Contents,AMR语音帧都是各自字节对齐的,使得程序实现比较简单。

 

 

51 Payload structure

Bandwith-Efficient Mode Payload header只包含一个属性:CMRCodec Mode Request,是报文发送方对报文接收方的编码器的编码模式要求,取值范围0-71515表示对编码无要求,如果收到的语音报文CMR取值非法,接收方需要忽略此取值。ddrrs不主动发送语音报文给UE,所以不用处理此参数。

Octet-Aligned Mode Payload header结构如下:其中CMR含义同Bandwith-Efficient ModeR为填充位。后面的ILLILPInterleaving打包时携带,调度器发给ddrrss的报文中不使用此属性。

 

 

一个语音帧对应一个table of content,结构如下:

 

F:1表示此帧后面还有其它帧,0表示此帧是本报文中最后一帧。

FT

 

FT取值为15表示本包未打包该语音帧的数据。

 

Q:0表示该帧严重损坏,接收方需要根据FTRX_TYPE设置为SPEECH_BAD或者SID_BAD。质量正常的帧设置为1

 

Octet-Aligned Modetable of contents后面可选携带table of frame CRCsFT15的语音帧不会携带CRC。一个CRC为一个字节。

 

以一个先后包含了一个位率为4.75Kbps的语音帧,紧接着是一个没有打包语音数据的帧,最后是一个位率为12.2Kbps的语音帧的AMR报文为例,描述两种模式下AMR语音报文的打包格式:

Bandwith-Efficient Mode

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

CMR=15

1

FT=0

1

1

FT=15

1

0

FT=7

1

d0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

d94

e0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

e243

p

p

p

p

p

p

p

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

d0到d94为位率为4.75Kbps的语音帧数据,e0到e243为位率为12.2Kbps的语音帧,后面为了将整个语音报文补齐为字节对齐,填充了7bit的0值。

 

Octet-Aligned Mode

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

CMR=15

R

R

R

R

1

FT=0

1

P

P

1

FT=15

1

P

P

0

FT=7

1

P

P

d0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

d94

P

e0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

e243

P

P

P

P

 

 

 

 

 

 

 

 

 

1.        AMR:

又称为AMR-NB,相对于下面的WB而言,

语音带宽范围:3003400Hz

8KHz抽样

 

2.       AMR-WB:

AMR WideBand

语音带宽范围: 507000Hz

16KHz抽样

 

AMR-WB”全称为“Adaptive Multi-rate - Wideband”,即“自适应多速率宽带编码”,采样频率为16kHz,是一种同时被国际标准化组织ITU-T3GPP采用的宽带语音编码标准,也称 为G722.2标准。

足够的传输带宽保证AMR-WB可采用从6.6kb/s23.85kb/s共九种编码,语音质量超越PSTN固定电话。

 

l  音频数据帧大小的计算:

amr 一帧对应20ms,那么一秒有50帧的音频数据。由于比特率不同,每帧的数据大小也不同。

如果比特率是12.2kbs,那么每秒采样的音频数据位数为:

12200 / 50 = 244bit = 30.5byte,取整为31字节。

取整要四舍五入。

再加上一个字节的帧头,这样数据帧的大小为32字节。

 

AMR文件格式如下所示:

Header(文件头)

Speech frame 1(语音帧1

Speech fram n(语音帧n

它包含一个文件头,然后就是一帧一帧的AMR数据了。

 

2.4 AMR文件

AMR文件头6字节 直接偏移

例子里面给出的帧比特率为4.75(帧头04 帧长度是13字节


规格

比特率(kbps

音频帧大小(字节)

帧头(字节)

FT

 

0

AMR 4.75

  4.75

13

04  00000100

0000

1

AMR 5.15

  5.15

14

0C  00001100

0001

2

AMR 5.9

   5.90

16

14 00010100

0010

3

AMR 6.7

   6.70

18

1C  00011100

0011

4

AMR 7.4

   7.40

20

24 00100100

0100

5

AMR 7.95

   7.95

21

2C  00101100

0101

6

AMR 10.2

  10.20

27

34 00110100

0110

7

AMR 12.2

  12.20

32

3C  00111100

0111


 

2.5.  语音转换

2G

Nvoc  PCM mp3

4G

AMR  PCM mp3

 

1lame 
lame-3.99.5.tar.gz 
Urlhttp://sourceforge.net/project/showfiles.php?group_id=290&package_id=309 
安装方法如下:

1     tar -zxvf lame-3.99.5.tar.gz  

2     cd lame-3.99.5  

3     ./configure --enable-shared 

4     make  

5     make install  

 

 

其中PCMmp3用的lame库,在这里可以下源代码:

http://sourceforge.net/projects/lame/files/lame/3.99/

源代码在版本机上编译后得到mp3lame动态库,链接时使用即可。

编码中使用lame的头文件加动态库。

 

程序运行时需要lame动态库。Lame是一个开源代码库。

 

从网上下载了lame-3.99.5.tar.gz源代码包 根据指导 tar -zvxf lame-3.99.5.tar.gz cd lame-3.99.5 ./configure --enable-share make make install 确实可以在/usr/local 目录下生成libmp3lame.so  但是我想通过目录/usr/local/3.4.1/linux-gcc编译器来生成与改编译器对应的libmp3lame.so动态库 但是lame-3.99.5.tar.gz里的makefile没看懂,求指导 由于不能带附件,这里发一个lame-3.99.5.tar.gz下载的连接 http://downloads.sourceforge.net/lame/lame-3.99.5.tar.gz

 configure  CC  CPP 环境变量中指定你自己特定的编译器,就可以实现指定的编译。  不过你本来的意思应当是需要把lame的库链接到特定的C库吧?这个会复杂一点,所以有特殊需要的库都尽量用静态编译。  编译完成后用 ldd 命令检验一下你的链接的库是正确的。

MP3 Encoding

* 编码MP3文件必须按如下顺序使用LAME API

1.      [Optional] 如果对lame版本感兴趣,使用get_lame_version()获得。

2.      [Optional] 设置lame的输出函数errorf(),debugf(),msgf()

3.      [Required] lame_global_flags* lame_init()初始化编码器。编码器的初始设置会输出[J-Stereo, 44.1khz, 128kbps, CBR ,quality 5]规格的MP3文件。使用一些的set/get方法调整参数,控制蔬菜MP3文件的质量和大小。

4.      [Required] lame_init_params()根据编码器的现有设置初始化编码器内部的设置。函数的返回值表明执行的结果。

5.      [Required] 使用lame_encode_buffer()将输入的PCM数据编码成MP3数据。

6.      [Required] 使用lame_encode_flush()mp3buffer中的MP3数据输出。

7.      [Required] 使用lame_mp3_tags_fid()VBR/INFO tags封装到一个MP3 Frame中,写到文件开头。如果输出流没有办法回溯,那么必须在第3步设置lame_set_bWriteVbrTag(gfp,0)

这一步调用lame_mp3_tags_fid(lame_global_flags *,FILE* fid)fid参数=NULL。这样的话那个开头的信息帧(MP3 FRAME)的所有字节都是0

8.      [Required] 释放所有内部参数使用的空间。lame_close()

 

第3.     视频 

语音信号因为是准稳态信号,在处理时常把信号分帧,每帧长度约20ms-30ms,在这一区间内把语音信号看作为稳态信号。只有稳态的信息才能进行信号处理,所以要先分帧。 “语音信号分帧进行小波变换”,就是把语音信号分帧后,对每一帧进行小波变换和处理。

3.1.  视频原理

视频帧,相当于一个静止的画面,也就类似一张图片。当一张张图片连续快速播放,就形成一个动的视频。胶片电影就是如此,它每秒播放24张,也叫帧速率为24。通常情况下,我国用的是P制式,是25帧。  美国等国家用的是N制式,是30帧。  还有用电影制式的,是24帧!  只要视频的帧速率大于24帧,则人眼是感觉不出来的。

频帧率(Frame rate)是用于测量显示帧数的量度。所谓的测量单位为每秒显示帧数(Frames per Second,简:FPS)或“赫兹”(Hz)。此词多用于影视制作和电子游戏。

由于人类眼睛的特殊生理结构,如果所看画面之帧率高于16的时候,就会认为是连贯的,此现象称之为视觉停留。这也就是为什么电影胶片是一格一格拍摄出来,然后快速播放的。

 

表45 音视频各编码格式对应的SDP参数

编码类型

载荷类型

(payload_type)

timestamp frequency(kHz)

G729

18

8

CELP

100

8

AMR

126

8

H.264

98

90

MPEG-4

97

90

SVAC

99

90

PCMA

8

8

PCMU

0

8

VP8

110

90

H.263

111

90

NVOC

101

8

 

表46 各视频编码格式对应的分辨率

视频编码格式

分辨率

含义

QCIF

176×144

四分之一公共中间格式

QVGA

320×240

 

CIF

352×288

CIF为常用视频标准化格式简称(Common Intermediate Format)。在H.323协议簇中,规定了视频采集设备的标准采集分辨率。CIF = 352×288像素(水平像素×垂直像素),QCIF全称Quarter common intermediate format

VGA

640×480

VGA(Video Graphics Array)IBM1987年随PS/2机一起推出的一种视频传输标准

4CIF

704×576

 

D1

720×576

数字电视标准

720p

1280×720

1080p720p的意思是指清晰度。1080其实是1920×1080720则代表1280×720。但别以为720就一定比1080分辨率低,实际上,720P这个P是指逐行扫描1080i这个i是指隔行扫描,同样是一个扫描频率,逐行要比隔行画面更稳定、更不闪烁、效果更好!实际上,1080i折算后,效果只相当于540P,当然不如720P效果好了

1080p

1920×1080

 

Q

 

720P1080P

对于高清节目,实际上720P1080i1080P的概念已经没有实际意义了,以720代表1280*7201080代表1920*1080就可以了,因为即使是1080i的图像,平板电视也可处理成1080P的。对于平板电视,720P1080i1080P更没有意义,平板电视全部可以认为是逐行的,清晰度高低由分辨率决定的,按照高清国标要求至少要达到1280*720,当然是1920*1080的物理分辨率最佳了,但是这和720P1080i1080P已经没有什么关系。唯一还需要720P1080i1080P概念的,就是高清摄像机,但是对于电视观众而言,我们只要看节目就好了,至于用什么格式摄像机拍摄的节目,并不影响观看效果。

720P1080i中的iinterlace,代表隔行扫描;PProgressive,代表逐行扫描。要讲清楚这两个名词,还要从模拟的CRT电视说起,传统的CRT电视,工作的原理是通过电子束在屏幕上一行行地扫描后发光来显示图象的。电视信号在传输过程中,由于受带宽的限制,只能传递隔行信号,以节省带宽。以NTSC电视机为例,在工作的时候,把一幅525行图像分成两场来扫,第一场称奇数场,只扫描奇数行(依次扫描135…行),而第二场(偶数场)只扫描偶数行(依次扫描246…行),通过两场扫描完成原来一帧图像扫描的行数,由于人眼具有视觉暂留效应,因此看在眼中时仍是一幅完整的图象,这就是隔行扫描。NTSC制节目共525行扫描线,每秒60场图像,表示为60i525i,如果是逐行扫描的,就称作60P525PPAL制节目为625行,每秒50场图像,表示为50i625i,逐行则称为50P625P。记住,这是针对CRT电视机的。

1080P1920*1080约为200像素, 720P1280*720约为100像素。

3.1.  视频采集

视频采集视频源模拟信号通处理转变数字信号(01)并些数字信息存储电脑硬盘程种模拟/数字转变通视频采集卡采集芯片进行   电脑通视频采集卡接收自视频输入端模拟视频信号该信号进行采集、量化数字信号压缩编码数字视频 视频采集卡 数模A/D转换流程数视频卡都具备硬件压缩功能采集视频信号首先卡视频信号进行压缩再通PCI接口压缩视频数据传送主机般PC视频采集卡采用帧内压缩算数字化视频存储AVI文件高档些视频采集卡能直接采集数字视频数据实压缩MPEG-1格式文件   由于模拟视频输入端提供间断信息源视频采集卡要采集模拟视频序列每帧图像并采集帧图像前些数据传入PC系统实现实采集关键每帧所需处理间每帧视频图像处理间超相邻两帧间相隔间则要现数据丢失即丢帧现象采集卡都获取视频序列先进行压缩处理再存入硬盘说视频序列获取压缩起完免除再进行压缩处理便同档采集卡具同质量采集压缩性能   由视频采集芯片模拟信号转换数字信号传至板卡自带临存储器再由卡自带视频压缩芯片执行压缩算庞视频信号压缩变些压缩直接或通PCI桥芯片进入PCI存储硬盘。

 

3.1.  视频播放

调用mediaplay控件

http://www.cnblogs.com/over140/archive/2009/03/23/1419643.html

 

3.4.  视频转换

主流是FFmpeg(大部分播放器),少数使用 libavffmpeg政变而来),也有直接代码的(不知正确性如何?)

 

3.5.  ffmpeg的Linux安装

一、安装yasm

http://yasm.tortall.net/Download.html 下载yasm
tar -zxvf yasm.tar.gz
./configure
make
make install

 

注:目前使用yasm-1.3.0

 

 

注:目前使用faac-1.28

faachttps://sourceforge.net/projects/faac/?source=typ_redirect

# wget http://downloads.sourceforge.net/faac/faac-1.26.tar.gz
# tar xvfz faac-1.26.tar.gz
# cd faac
# ./bootstrap
# ./configure
# make
# make install

首先编译faac

 

1. configure

 

2. make

 

make error:

mpeg4ip.h:126: error: new declaration ‘char* strcasestr(const char*, const char*)’

123行开始修改此文件mpeg4ip.h,到129行结束。

 修改前:

#ifdef __cplusplus

 extern "C" {

 #endif

char *strcasestr(const char *haystack, const char *needle);

 #ifdef __cplusplus

 }

 #endif

 

修改后:

#ifdef __cplusplus

 extern "C++" {

 #endif

const char *strcasestr(const char *haystack, const char *needle);

 #ifdef __cplusplus

 }

 #endif

 

 

3. make install

 

注:目前使用x264-20150819-git-e86f3a1

编译x264

 

1. 编译yasm

2. 编译x264

   2.1 ./configure --enable-shared --enable-static --enable-yasm

   2.2 make

   2.3 make install

   

   

 

 

注:目前使用ffmpeg-2.0.2

编译ffmpeg

 

1   ./configure --enable-shared --enable-yasm  --enable-pthreads --enable-libfaac --enable-libx264 --enable-gpl --enable-nonfree

2   make  

3   make install

 

 

 

 

 

 

ffmpeg编出的库都拷贝到用户lib目录,编译用户程序会报错UTLconfig.h文件。

程序编译错误:

方法一:

fix方法是直接在common.h的最前面加上:

 

#ifdef __cplusplus

#define __STDC_CONSTANT_MACROS

#ifdef _STDINT_H

#undef _STDINT_H

#endif

# include <stdint.h>

#endif


#ifndef   UINT64_C

#define   UINT64_C(value)__CONCAT(value,ULL)

#endif

 

 

 

 

最新版本,目前最新版本无法使用目前视频代码,只能暂记录在此:

http://ffmpeg.org/download.html

下载的是:ffmpeg-2.8.4.tar.bz2

tar –jxvf   ffmpeg-2.8.4.tar.bz2

 

Libx264

http://www.videolan.org/developers/x264.html

Or grab a daily tarball.得到代码快照。

tar jxvf last_x264.tar.bz2

 

其中configure时报错:

http://yasm.tortall.net/Download.html

 

程序编译错误:

方法一:

fix方法是直接在common.h的最前面加上:

 

#ifdef __cplusplus

#define __STDC_CONSTANT_MACROS

#ifdef _STDINT_H

#undef _STDINT_H

#endif

# include <stdint.h>

#endif


#ifndef   UINT64_C

#define   UINT64_C(value)__CONCAT(value,ULL)

#endif


如果还出现找不到库的情况:

 

error while loading shared libraries: libavdevice.so.55: cannot open shared object file: No such file or directory

首先确认在安装路径下这些库存在,如果存在,则编辑 /etc/ld.so.conf文件,把安装路径加上,比如我的安装路径是/usr/local/lib,修改后整个文件就是

include /etc/ld.so.conf.d/*.conf
/usr/local/lib

 

 

方法二:

ffmpeg遇到inttypes.hUINT64_C问题

 

http://blog.csdn.net/cll131421/article/details/7763657
我用这个解决了
错误二: error C3861: “UINT64_C”: 找不到标识符
解决方法:在common.h中添加如下代码:
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif

 

 

 

3.6  未经实践的ffmpeg安装网络文章

 

http://ffmpeg.org/download.html

Linux
安装环境CentOS
下载tar.bz2安装包
tar -xvf XX.tar.bz2

yasm/nasm not found or too old. Use –disable-yasm for a crippled build.

If you think configure made a mistake, make sure you are using the latest
version from Git. If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file “config.log” produced by configure as this will help
solve the problem.

http://yasm.tortall.net/Download.html 下载yasm
tar -zxvf yasm.tar.gz
./configure
make
make install

再来
ffmpeg下面
./configure

安装完毕,发现无法将amr转成MP3
./ffmpeg -i x.amr x.mp3

./configure –enable-libmp3lame
少这个libmp3lame

# wget http://downloads.sourceforge.net/lame/lame-3.97.tar.gz
# tar xzf lame-3.97.tar.gz
# cd lame-3.97
# ./configure
# make
# make install

ERROR: libmp3lame >= 3.98.3 not found

http://downloads.sourceforge.net/lame/去这里找最新的版本,下载一个。

我下到的是lame-3.99.5.tar.gz
# ./configure
# make
# make install

./ffmpeg -i x.amr x.mp3

ffmpeg: error while loading shared libraries: libmp3lame.so.0: cannot open shared object file: No such file or directory

发生这个我们这样弄

编辑/etc/ld.so.conf文件加入如下内容
/usr/local/lib
保存退出后执行ldconfig命令

大功告成。

你缺少的库,可能都在下面了

FFmpeg软件只是个解码编码软件,如果支持多种格式必须先安装好对应的库,下面就说下我装的库:
1. 安装faad2

# wget http://downloads.sourceforge.net/faac/faad2-2.6.1.tar.gz
# tar xvfz faad2-2.6.1.tar.gz
# cd faad2
# ./bootstrap
# ./configure
# make
# make install
2. 安装liba52

# wget http://liba52.sourceforge.net/files/a52dec-0.7.4.tar.gz
# tar xvfz a52dec-0.7.4.tar.gz
# cd a52dec-0.7.4
# ./configure
# make
# make install
3. 安装libdirac

# wget http://downloads.sourceforge.net/dirac/dirac-0.10.0.tar.gz
# tar xvfz dirac-0.10.0.tar.gz
# cd dirac-0.10.0
# ./configure
# make
# make install
4. 安装faac2

# wget http://downloads.sourceforge.net/faac/faac-1.26.tar.gz
# tar xvfz faac-1.26.tar.gz
# cd faac
# ./bootstrap
# ./configure
# make
# make install
5. 安装libamrnb

# wget http://ftp.penguin.cz/pub/users/utx/amr/amrnb-7.0.0.2.tar.bz2
# tar xvfj amrnb-7.0.0.2.tar.bz2
# cd amrnb-7.0.0.2
# ./configure
# make
# make install
6. 安装libamrwb

# wget http://ftp.penguin.cz/pub/users/utx/amr/amrwb-7.0.0.3.tar.bz2
# tar xvfj amrwb-7.0.0.3.tar.bz2
# cd amrwb-7.0.0.3
# ./configure
# make
# make install
7. 安装libmp3lame

# wget http://downloads.sourceforge.net/lame/lame-3.97.tar.gz
# tar xzf lame-3.97.tar.gz
# cd lame-3.97
# ./configure
# make
# make install
8. 安装libx264
此软件包需要用git来获取,所以要先安装git:

# wget http://kernel.org/pub/software/scm/git/git-1.6.2.tar.gz (地址要确认)
# tar zxvf git-1.6.2.tar.gz
# cd git-1.6.2
# ./configure
# make
# make install
然后安装libx264

# /usr/local/bin/git clone git://git.videolan.org/x264.git x264
# cd x264
# ./configure –enable-pthread –enable-shared –disable-asm
# make
# make install
8. 安装libnut,该软件需要用svn获取源代码,svn可以直接用yum install svn来装。先下载:

# svn co svn://svn.mplayerhq.hu/nut/src/trunk libnut
下载后代码保存在新建立的libnut目录下,对于64位Linux需要修改配置文件:

# cd libnut
# vi config.mak
在最后一个CFLAGS下一行增加:

CFLAGS += -fPIC
然后编译安装:

# make
# make install
9. 安装libogg

# wget http://downloads.xiph.org/releases/ogg/libogg-1.1.3.tar.gz
# tar xvf libogg-1.1.3.tar.gz
# cd libogg-1.1.3
# ./configure
# make
# make install
10. 安装libtheora (svn获取)

# svn co http://svn.xiph.org/trunk/theora theora
# cd theora
# ./autogen.sh
# ./configure
# make
# make install
11. 安装libvorbis

# wget http://downloads.xiph.org/releases/vorbis/libvorbis-1.2.0.tar.gz
# tar xvfz libvorbis-1.2.0.tar.gz
# cd libvorbis-1.2.0
# ./configure
# make
# make install
12. 安装libxvid

# wget http://downloads.xvid.org/downloads/xvidcore-1.2.1.tar.gz
# tar xvf xvidcore-1.2.1.tar.gz
# cd xvidcore-1.2.1/build/generic
# ./bootstrap.sh
# ./configure –disable-assembly
# make
# make install

上面的媒体支持库安装完后,可以设置下环境准备编译FFmpeg了!
13. 修改环境变量

# vi /etc/ld.so.conf
在文件末增加一行:

/usr/local/lib
然后生效之:

# ldconfig
14. 安装FFmpeg
可以通过svn获取,不过文件比较大,所以特别慢:

# svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
# cd ffmpeg
也可以自己下载:

# http://www.ffmpeg.org/releases/ffmpeg-0.5.tar.bz2
# bzip2 -d ffmpeg-0.5.tar.bz2
# tar -xf ffmpeg-0.5.tar
# cd ffmpeg-0.5
编译(64位系统需要设置PKG_CONFIG_PATH参数):

# export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig CFLAGS=”-fPIC -m64″
# ./configure –enable-shared \
–enable-gpl \
–enable-nonfree \
–enable-postproc \
–enable-avfilter \
–enable-avfilter-lavf \
–enable-pthreads \
–enable-libamr-nb \
–enable-libamr-wb \
–enable-libdirac \
–enable-libfaac \
–enable-libfaad \
–enable-libfaadbin \
–enable-libmp3lame \
–enable-libnut \
–enable-libtheora \
–enable-libvorbis \
–enable-libx264 \
–enable-libxvid \
–enable-decoder=libx264 \
–enable-encoder=libx264
# make
# make install

14. 可能出现的错误:

/usr/include/linux/videodev.h:56: error: syntax error before “ulong”
/usr/include/linux/videodev.h:72: error: syntax error before ‘}’ token
libavdevice/v4l.c: In function `grab_read_header’:
libavdevice/v4l.c:75: error: storage size of ‘tuner’ isn’t known
libavdevice/v4l.c:133: error: invalid application of `sizeof’ to incomplete type `video_tuner’
libavdevice/v4l.c:140: error: invalid application of `sizeof’ to incomplete type `video_tuner’
libavdevice/v4l.c:75: warning: unused variable `tuner’
这可能是源代码videodev.h不是针对次版本Linux写的,标准C没有ulong类型,所以要改成unsigned long

15. 运行ffmpeg -formats,可能出的错误:

ffmpeg: error while loading shared libraries: libavfilter.so.0: cannot open shared object file: No such file or directory
这事没有设置环境路径造成了,增加一个ffmpeg.conf配置文件:

# cd /etc/ld.so.conf.d
# vi ffmpeg.conf
在文件内写上:

/usr/local/lib
然后确认生效:

# ldconfig
16. 其他:

 

 

3.6  ffmpeg的VS2010使用方法

http://www.tuicool.com/articles/aiueai

 

http://ffmpeg.org/platform.html#Microsoft-Visual-C_002b_002b-or-Intel-C_002b_002b-Compiler-for-Windows

 

看起来靠谱的

http://blog.csdn.net/download_73/article/details/46563665

1,更新pacman

[root@BlackGhost zhangy]# pacman -S pacman

2,换一下下载源,这种方法不好,你不知道那个网站更新快,哪个网新更新慢。这种方法比较傻

nano /etc/pacman.conf

[core],[extra],[community]里面的源注释掉加上新源就可以了。

3,手动将要下的数据包下到本地,然后在安装

pacman -Sw 源地址/libldap-2.4.23-1-i686.pkg.tar.xz  -P /var/cache/pacman/pkg/

pacman -U /var/cache/pacman/pkg/libldap-2.4.23-1-i686.pkg.tar.xz

pacman -U 时,遇到以下问题

warning: directory permissions differ on var/
filesystem: 777  package: 755

解决上面的问题是

chmod 755 /var

这种方法比较通用性

 

 

3.7  ffmpeg的VS2013使用方法

方法介绍:http://ffmpeg.org/platform.html#Microsoft-Visual-C_002b_002b-or-Intel-C_002b_002b-Compiler-for-Windows

 

安装Vs2013,需要1小时左右。

 

安装MSYS2

有报错:

gpgkeys: HTTP fetch error

6: Couldn't resolve host 'pool.sks-keyservers.net'

 

pacman  -Sl

安装一个包,但公司内网总是报错,无法访问网站

$ pacman -S  mingw-w64-i686-gcc

 

 

 

http://blog.chinaunix.net/uid-20718335-id-2980793.html

 

2 下载 yasm(汇编编译器)
    ffmpeg编译的时候里面的汇编代码需要yasm.exe
    去官网:http://yasm.tortall.net/Download.html 下载
    Latest Release栏,直接下载:Win32 .exe (for general use on 32-bit Windows) 
    文件名类似为:yasm-1.2.0-win32.exe

为了减少配置环境变量的麻烦,本处直接把 yasm-1.1.0-win32.exe 文件名修改成:yasm.exe,并放到系统目录下:C:\WINDOWS\system32

 

执行下载文件:mingw-get-inst-20111118.exe
    在第3步选择“Download latest repository catalogues
    选择安装路径:C:\MinGW(我直接采用默认路径,未做修改)
    在“Select Components”步骤中选择:
        C Compiler (默认且一定选择)
        C++ Compiler
        MSYS Basic System(选择此项将会安装msysmsys则不需要另外安装)
        MinGW Developer ToolKit
    等待安装完成!(需要等待一定的时间,因为安装过程需要下载文件,可想而知,网速越快,安装越快)
    安装完成后,在C:\MinGW目录下可以看到 msys 文件夹,msys也已经安装。

 

再选installation菜单中update进行安装。

 

3 系统整合
    使用UltraEdit修改C:\MinGW\msys\1.0\etc目下的fstab文件,如果不存在fstab,请复制一份fstab.sample,然后改名为:fstab,再修改其内容为:C:/MinGW /mingw,也即为MinGW的安装路径。

 

5 编译 mp3lame(可选项)

http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz/download

下载lame-3.99.5.tar.gz


    lame-3.99.2.tar.gz 接压到:D:\ffmpeg\ 目录下,双击“C:\MinGW\msys\1.0\msys.bat”,启动“MinGW32”,切换到lame目录:D:\ffmpeg\lame-3.99.2
    $ cd /d
    $ cd ffmpeg
    $ cd lame-3.99.2
    再执行以下命令:
    $./configure --disable-shared (首选)
: $./configure --disable-static --enable-shared
    $ make
    $ make install
    编译结果在:C:\MinGW\msys\1.0\local 目录下

 

6 编译 ffmpeg

 

 $ cd /d

$ cd ffmpeg

 $ ./configure

$ make

 $ make install

等待完成,在C:\MinGW\msys\1.0\local中将会生成 binincludelib等文件夹,其中包含了ffmpeg.exeffplay.exeffprobe.exedlllib和头文件等。

其中:

 $ ./configure --enable-shared --disable-static --enable-ffplay
    --enable-nonfree --enable-memalign-hack
    --enable-libmp3lame
    --enable-gpl--enable-libx264   
    --enable-libxvid
    --enable-faad --enable-libfaac
    --enable-libvo-aacenc
    --enable-version3 --enable-libopencore-amrnb   
    --enable-libopencore-amrwb --enable-libvo-amrwbenc
    --extra-cflags=-Id:/ffmpeg/ffmpeg-0.8.6/include
    --extra-ldflags=-Ld:/ffmpeg/ffmpeg-0.8.6/lib

 

执行make时报错,如下:
CC libavformat/applehttp.o In file include from libavformat/applehttp.o\c:34:0: c:\mingw\include\unistd.h:79:1: error:epected ','or ';'before'int'
int __mingw_sleep<unsigned long, unsigned long>;
make*** [libavformat/applehttp.o] Error 1

解决方法:

C:\\MinGW\\include\\unistd.h修改该文件中的“_cdecl”为“__cdecl”,然后再继续make

而标准C里面也就只有少数的一些函数是用__cdecl来调用的,像printf scanf

1_cdecl c调用约定, 按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。 _cdeclCC++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。VC将函数编译后会在函数名前面加上下划线前缀。是MFC缺省调用约定。

2__cdeclC/C++MFC程序默认使用的调用约定。采用__cdecl约定时,函数参数按照从右到左的顺序入栈,并且由调用函数者把参数弹出栈以清理堆栈。因此,实现可变参数的函数只能使用该调用约定。由于每一个使用__cdecl约定的函数都要包含清理堆栈的代码,所以产生的可执行文件大小会比较大。__cdecl可以写成_cdecl 

windows平台上C++开发会遇到。
其它的还有__stdcall __fastcall什么的,大概56个。
主要决定两方面的事情:
  符号的修饰
  参数的压栈顺序,调用方被调用方谁清栈

 

自己工程报错解决方法:

问题1. LIBCMT.lib(realloc.obj) : error LNK2005: __recalloc 已经在 msvcrtd.lib(MSVCR80D.dll) 中定义

解决1链接器->输入->忽略特定库: libcmt.lib

 

 

问题2 error LNK2019: 无法解析的外部符号 __imp__accept@

在添加头文件处,添加引用:

解决2#pragma comment(lib,"ws2_32.lib")

 

 

3.7  ffmpeg的SDK方法

http://ffmpeg.zeranoe.com/builds/

方法介绍:http://www.cnblogs.com/js2854/archive/2013/05/16/ffmpeg-sdk.html

学习ffmpeg的过程很多基础知识不清楚,比如ffmpeg sdk从哪里下载,现在记录一下

 

ffmpeg sdk由两部分组成:1.include(ffmpeg开发所需头文件)lib(静态库)  2.dll动态库

 

这两个部分都可以从http://ffmpeg.zeranoe.com/builds/下载

截至目前为止,提供如下图所示最新版本下载

 

第一部分includelib包含在FFmpegDev包中 Download FFmpeg git-56ba331 32-bit Dev

第二部分动态库可以在FFmpeg Shared包中找到 Download FFmpeg git-56ba331 32-bit Shared

开发阶段只需要工程中包含includelib,运行阶段需要对应dll(注意两部分版本要一致)

 

如果开发中需要使用SDL(Simple DirectMedia Layer),可以到http://www.libsdl.org下载SDLSDK(Development Libraries)

SDL的使用方法,与ffmpeg sdk相同,所需要的includelibdll全部包含在Development LibrariesSDL(Simple DirectMedia Layer)一个跨平台的multimedia library ,包含了对video,audio,keyboard,mouse的支持。
它的接口比较简洁,你甚至不需要知道Win32 API,就可以写出游戏来。它封装了跟
平台相关的部分。它使我想起了TC下面的graphics BGI

官方地址:   http://www.libsdl.org/

Development Libraries下载:

Linux: 
SDL-devel-1.2.15-1.i386.rpmhttp://www.libsdl.org/release/SDL-devel-1.2.15-1.i386.rpmSDL-devel-1.2.15-1.x86_64.rpmhttp://www.libsdl.org/release/SDL-devel-1.2.15-1.x86_64.rpm

Win32: 
SDL-devel-1.2.15-VC.zip (Visual C++)http://www.libsdl.org/release/SDL-devel-1.2.15-VC.zip
SDL-devel-1.2.15-mingw32.tar.gz (Mingw32)http://www.libsdl.org/release/SDL-devel-1.2.15-mingw32.tar.gz

 

第4.    实现

判断帧类型

1NAL全称Network Abstract Layer, 即网络抽象层。
         H.264/AVC视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL)和网络抽象层面(NAL)。其中,前者负责有效表示视频数据的内容,而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。因此我们平时的每帧数据就是一个NAL单元(SPSPPS除外)。在实际的H264数据帧中,往往帧前面带有00 00 00 01 00 00 01分隔符,一般来说编码器编出的首帧数据为PPSSPS,接着为I……

如下图:


2、如何判断帧类型(是图像参考帧还是IP帧等)?

     NALU类型是我们判断帧类型的利器,从官方文档中得出如下图:


我们还是接着看最上面图的码流对应的数据来层层分析,以00 00 00 01分割之后的下一个字节就是NALU类型,将其转为二进制数据后,解读顺序为从左往右算,如下:
1)第1位禁止位,值为1表示语法出错
2)第2~3位为参考级别
3)第4~8为是nal单元类型

例如上面00000001后有67,68以及65

其中0x67的二进制码为:
0110 0111
4-800111,转为十进制7,参考第二幅图:7对应序列参数集SPS

其中0x68的二进制码为:
0110 1000
4-801000,转为十进制8,参考第二幅图:8对应图像参数集PPS

其中0x65的二进制码为:
0110 0101
4-800101,转为十进制5,参考第二幅图:5对应IDR图像中的片(I)

 

所以判断是否为I帧的算法为: (NALU类型  & 0001  1111= 5      NALU类型  & 31 = 5

比如0x65 & 31 = 5

 

 

 

 

第5.    MP4

MP4封装格式对应标准为 ISO/IEC 14496-12(信息技术 视听对象编码的第12部分: ISO 基本媒体文件格式/Information technology Coding of audio-visual objects Part 12: ISO base media file format

 附-- 标准免费下载: Freely Available Standards   http://standards.iso.org/ittf/PubliclyAvailableStandards/index.html

 

5.1.  视频原理

视频帧,相当于一个静止的画面,也就类似一张图片。当一张张图片连续快速播放,就形成一个动的视频。胶片电影就是如此,它每秒播放24张,也叫帧速率为24。通常情况下,我国用的是P制式,是25帧。  美国等国家用的是N制式,是30帧。  还有用电影制式的,是24帧!  只要视频

 

 

 

6章.     Ffmpeg原理

1.简介:
    ffmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。
使用ffmpeg能够完成如下功能:parse,demux,decode,filter(preprocessing),encode,mux,streamplayer.

2.下载和编译:

    下载地址:  http://ffmpeg.org/download.html

    编译:
       1)windows平台static library/shared library, 编译工具:mingw-gcc或者在linux平台下交叉编译(推荐)
       2)linux平台static library/shared library, 编译工具:gcc

    模块:
        libavcodec    - 编码解码器
        libavdevice   - 输入输出设备的支持
        libavfilter   - 视音频滤镜支持
        libavformat   - 视音频等格式的解析
        libavutil     - 工具库
        libpostproc   - 后期效果处理
        libswscale    - 图像颜色、尺寸转换
    
3.SDK介绍和开发(基于ffmpeg 0.8 sdk)
    ffmpeg每部分功能都采用plugin的方式,使用统一的接口调用,这样就能够非常方便的使用和扩展。
    plugin分为几种:muxer,demuxer,protocol,hwaccel,encoder,decoder,parser,bitstream,filter,...
    因此在使用SDK的时候第一步就是注册plugin
    
    avcodec_register_all()  : 注册 hwaccel,encoder,decoder,parser,bitstream
    av_register_all()       : 注册 muxer,demuxer,protocol
    avfilter_register_all() : 注册 滤镜filter

 

 

第7.基本概念

FFMPEGFast Forward MPEG(动态图像专家组)MovingPictureExpertsGroup的简称

 

采样频率:

采样频率,也称为采样速度或者采样率,定义了每秒从连续信号中提取并组成离散信号的采样个数,它用赫兹Hz)来表示。采样频率的倒数是采样周期或者叫作采样时间,它是采样之间的时间间隔。

8,000 Hz - 电话所用采样率, 对于人的说话已经足够AMR采样频率为8K20ms一帧的语音报文其中采样数目为160,则每传送一帧的语音报文,timestamp就增加160

 

 

第8.     参考资料

[1]     大师级:http://www.360doc.com/content/15/0401/20/21412_459894416.shtml

[2]      http://www.faqs.org/rfcs/,上面有全面的英文RFC文档

[3]      http://www.cnpaf.net/,有不少协议分析文档,也有中文RFC文档,但质量不是特别高。

 

 

Ffmepg命令:

http://www.cnblogs.com/wainiwann/p/4128154.html

 

总体介绍:

http://blog.csdn.net/leixiaohua1020/article/details/15811977

最简单的基于FFMPEG的视频编码器(YUV编码为H.264

http://blog.csdn.net/leixiaohua1020/article/details/25430425

 

FFmpeg的官方网址是 http://ffmpeg.mplayerhq.hu/ 

中文Wiki http://www.ffmpeg.com.cn/  ,资料很多。

 

 

 

 

 

 

第9.ffmpeg编程

av_sample_get_buffer_size

使用av_sample_get_buffer_size来计算音频占用的字节数。

音频所占用字节数 = 通道数 * 采用频率(Hz) * 采用位数(byte)

http://blog.csdn.net/oldmtn/article/details/48048687

 

avpicture_fill

1 int avpicture_fill(AVPicture *picture, uint8_t *ptr,

                   int pix_fmt, int width, int height);

这个函数的使用本质上是为已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间,这个结构体中有一个指针数组data[4],挂在这个数组里。一般我们这么使用:

1) pFrameRGB=avcodec_alloc_frame();

2) numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);

    buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));

3) avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx-        >height);

以上就是为pFrameRGB挂上buffer。这个buffer是用于存缓冲数据的。

好,现在让我们来看一下tutorials里常出现的pFrame为什么不用fill空间。主要是下面这句:

avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);

这里根据我的瞎猜,很可能是pFrame已经挂上了packet.data,所以就不用fill了。

 

avcodec_open2

 

Specified sample format s16 is invalid or not supported

AVCodecConext对象的strict_std_compliance成员,设置为FF_COMPLIANCE_EXPERIMENTAL就行。

 audioCodec->sample_fmt = audioCodec->codec->sample_fmts[0];

 

 

第10.概念

10.1.  PTS

http://www.aichengxu.com/view/2469326

我将帧率设置为15,而且是CIF分辨率,局域网传输,不应该有丢帧啊!?我XX查了一整天,各种办法,最后我发现是海思SDK送出来PTS有问题:
pts=pstStream->pstPack[i].u64PTS*90/1000; //ms*90
干脆换成我自己计算PTS:
gVideoPath[ch].VencOutQue[wp].u64PTS=gVideoPath[ch].seq*gVencIn[ch].pts_tick;
这样就不丢帧了,延时也正常了。
但刚开始时,仍然要丢几帧。
不过仔细听起来,这种做法,声音总是一顿一顿的,不连续。
没有办法,还是得用SDK提供出来timestamp。而且,越播延迟越大,但第一路流1080P就不会,这TMD究竟是什么原因啊?
我在海思底层MPP上面配置了三个通道(1080P/720P/QVGA):
VpssGrp = 0; VpssChn = 3;
VencGrp = 0; VencChn = 0; //for HD recording
s32Ret = _COMM_VENC_Start(VencGrp, VencChn, pVideo+0);
s32Ret = SAMPLE_COMM_VENC_BindVpss(VencGrp, VpssGrp, VpssChn);
VpssGrp = 0; VpssChn = 4;
VencGrp = 1; VencChn = 1; //for preview
s32Ret = _COMM_VENC_Start(VencGrp, VencChn, pVideo+1);
s32Ret = SAMPLE_COMM_VENC_BindVpss(VencChn, VpssGrp, VpssChn);
VpssGrp = 0; VpssChn = 5;
VencGrp = 2; VencChn = 2; //for CIF clip recording
s32Ret = _COMM_VENC_Start(VencGrp, VencChn, (pVideo+2));
现在的现象就是1080P这个通道是正常的,延迟在2s左右,丢帧也少。720P/QVGA就不行了,延时达到6秒以上,丢帧严重。
下面只有两个办法:
1、 换成wis-streamer。
2、 录像为mp4文件播放,看是否有问题。
我把VpssChn改了一下,不再关联3/4/5,而是关联0,这样的话,延时的问题基本上算是解决了。但是,丢帧的原因始终没有找到。
我去掉audio后,Video就不再丢帧了,看来,这是音视频不同步引发的血案啊!
Hi3518平台流媒体服务器的音视频同步问题
PTS:Presentation Time Stamp
DTS:Decoding TimeStamp
PCR:Program ClockReference
STC:System TimeClock

我也正在研究这一块.说解码才得到的都是不对的.其实是从LIVE555那里得到的.afterGettingFrame里面有一个参数是presentationTime.通过RTSP得到的流的PTS都是由它计算出来的.不过它的单位是us.还是90000.这个要值得注意.ffmpeg解码后只是校准了PTS.PTS真正的源头是RTSP的发送方.只有发送方才有能力告诉你数据采集的PTS从而帮助你进行同步.
RTP规范里,RTP包的TIMESTAMP字段应该指示图像的显示时间,而且时间单位是tick.像视频的话单位就是90K,那一段25fps的视频每增长一帧,时间戳就应该增加3600.但是同样是通过RTSP播实时流,ffplay和vlc对于时间戳的处理是不一样的.如果在ffplay里.它直接把rtp包里的timestamp当作是解码前的pts传入avcodec_decode_video2().ffmpeg进行重排序(如果没有B帧,一般是原样复制到解码后的AVFrame里),然后将它乘以1/90K还原成us的单位,然后直接用来usleep();而vlc的rtsp传输模块用的是live555,live555在我看来多此一举了,它对上层屏蔽了RTP包里的TIMESTAMP.而是直接帮你还原好了.单位就是us.也就是说,afterGettingFrame()函数的pts单位是us.可以直接拿来用usleep了。
// 1s = 90000 time scale , 一帧就应该是 90000/video_frame_rate 个timescale
static uint32_t video_frame_rate = 30;
static uint32_t video_pts_increment = 90000 / video_frame_rate; //用一秒钟除以帧率,得到每一帧应该耗时是多少,单位是 timescale单位
static uint64_t video_pts = 0;
pts初始值可以是任意的,我一般定为0,后面每一帧加上增量就可以了。
音频pts的计算方法同上,只不过不是通过帧率,而是通过采样率。
uint32_t audio_pts_increment = (90000 * audio_samples_per_frame) / audio_sample_rate;
audio_samples_per_frame这个值对aac和mp3是不同的,aac固定为1024,mp3固定为1152。
>> 
用了你的计算方法,音视频可以用VLC同时播放,但是音频过一段时间后就变慢了。
而且越来延时越大,最后音频就没有了。请问知道是什么原因吗?而且这是变帧率,根本不应该这样来计算。
A:RFC3984 规定采用 90000 Hz 的时钟,因此如果编码帧频是 30,那么时间戳间隔就该是 90000 / 30 = 3000。audio_timebase =av_q2d(fmtctx->streams[audio_index]->time_base);
video_timebase = av_q2d(fmtctx->streams[video_index]->time_base);
last_video_pts = pts * video_timebase;
last_audio_pts = pts * audio_timebase;

timebase就是单位

audio为基准同步video(算法是如何?),因为audio是固定帧率的,而video是变帧率。只要设置好了 ao 的参数,如sample rate,
channels, sample size等, audio驱动就能以正确的速度播放,所以只要程序里write不出大问题的话,这种同步是非常有效的。
固定帧率
1. 视频时间戳
pts = inc++*(1000/fps); 其中inc是一个静态的,初始值为0,每次打完时间戳inc加1.
ffmpeg,中的代码
pkt.pts=m_nVideoTimeStamp++ * (m_VCtx->time_base.num * 1000 /m_VCtx->time_base.den);
2. 音频时间戳
pts = inc++ *(frame_size * 1000 / sample_rate)
ffmpeg中的代码为
pkt.pts=m_nAudioTimeStamp++ * (m_ACtx->frame_size * 1000 / m_ACtx->sample_rate);
采样频率是指将模拟声音波形进行数字化时,每秒钟抽取声波幅度样本的次数。
。正常人听觉的频率范围大约在20Hz~20kHz之间,根据奈奎斯特采样理论,为了保证声音不失真,采样频率应该在40kHz左右。常用的音频采样频率有8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz等,如果采用更高的采样频率,还可以达到DVD的音质
对采样率为44.1kHz的AAC音频进行解码时,一帧的解码时间须控制在23.22毫秒内。
背景知识:
(一个AAC原始帧包含一段时间内1024个采样及相关数据)
分析:
1 AAC
音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率(单位为s)
一帧 1024个 sample。采样率 Samplerate 44100KHz,每秒44100个sample, 所以 根据公式 音频帧的播放时间=一个AAC帧对应的采样样本的个数/采样频率
当前AAC一帧的播放时间是= 1024*1000000/44100=22.32ms(单位为ms)
2 MP3
mp3 每帧均为1152个字节, 则:
frame_duration = 1152 * 1000000 /sample_rate
例如:sample_rate= 44100HZ时, 计算出的时长为26.122ms,这就是经常听到的mp3每帧播放时间固定为26ms的由来。
可变帧率
有很多的采集卡,摄像头,在做采集的时候,明明设置的25FPS,但实际采集数据回调过来,发现并不是40毫秒的间隔,而是50,60,甚至100不等的时间间隔。
这就给编码后打时间戳带来很大的困难。
libav里,我们的默认编码参数都是:
ptAvEncoder->ptAvStreamVideo->codec->time_base.den = s32Fps;
ptAvEncoder->ptAvStreamVideo->codec->time_base.num = 1;
这样在编码后的时间戳以1递增,只适合于固定帧率。
我们来改一下:
ptAvEncoder->ptAvStreamVideo->codec->time_base.den = s32Fps * 1000;
ptAvEncoder->ptAvStreamVideo->codec->time_base.num = 1* 1000;
这样就把时间戳的scale变成了毫秒,就可以以毫秒为单位进行计算了,如下:
tAvPacket.pts = ((s64)u32TimeStamp * (s64)s32Fps);(李永奇:还需除以2左右,实测视频时长比声音时间长1倍左右)
u32TimeStamp是从开始记录的时间差值,以毫秒为单位;s32Fps是帧率。
对于音频,mp4文件默认是采样率为tick的,时间戳计算为:
tAvPacket.pts = (AvEncoderAudioInSizeGet(hHandle) * ( (s64)(u32TimeStamp)) / (AvEncoderAudioInSizeGet(hHandle) * 1000 / ptAvEncoder->ptAvStreamAudio->codec->sample_rate);

AvEncoderAudioInSizeGet(hHandle) 每次编码器需要的PCM数据长度。
u32TimeStamp是从开始记录的时间差值,以毫秒为单位。
ptAvEncoder->ptAvStreamAudio->codec->sample_rate PCM采样率,代表一秒的数据量。
因为乘以了1000,所以也化成了毫秒单位。
一般有三种办法
1.以音频为主进行同步
2.以视频为主进行同步
3.以一个外部参考时钟为同步

你可以参考下ffmpeg下的ffplay来做,还有
http://www.dranger.com/ffmpeg/tutorial05.html 
http://www.dranger.com/ffmpeg/tutorial04.html 

具体如何实现还是要靠自己研究清楚代码后来解决的.

同步的方法:
1、 audio pts直接用video的pts,这样的话,播放继续,Video受audio拖累而丢包严重。
2、 video pts直接用audio pts,结果Video播放不动,audio可以继续。
3、 audio pts直接填0,也就是不要,这样播放是最为流畅的,但video偶尔有丢帧,不知道是否受audio的拖累。

 

10.2 视频格式

 

尺寸 (阔 x 高)

简称 (代号)

全写

尺寸比例

128 x 96

subQCIF

 

4:3

176 X 144

QCIF

 

11:9

320 x 200

CGA

Color-Graphics-Adapter

8:5

320 x 240

Quarter-VGA

 

4:3

352 x 288

CIF

 

11:9

640 x 350

EGA

Extended-Graphics-Adapter

64:35

640 x 480

VGA

Video-Graphics-Array

4:3

800 x 600

SVGA

Super-Video-Graphics-Array

4:3

1024 x 768

XGA

eXtended-VGA

4:3

1280 x 768

XGA-W

 

15:9

1280 x 960

QVGA

Quad-VGA

4:3

1280 x 1024

SXGA

Super-eXtended-VGA

5:4

1400 x 1050

SXGA+

Super-eXtended-VGA-plu

4:3

1600 x 1024

SXGA-W

 

25:16

1600 x 1200

UGA

Ultra-VGA

4:3

1920 x 1080

HDTV

High-Definition-TV

16:9

1900 x 1200

UXGA

Ultra-eXtended-VGA

19:12

1920 x 1200

UXGA-W

 

8:5

2048 x 1536

QXGA

Quad-eXtended-VGA

4:3

2560 x 2048

QSXGA

Quad-Super-eXtended-VGA

5:4

3200 x 2400

QUXGA

Quad-Ultra-eXtended-VGA

4:3

3840 x 2400

QUXGA-W

 

8:5

 

  • 0
    点赞
  • 0
    评论
  • 2
    收藏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值