H.264音视频编码【草稿】

H264中的sps pps

iOS仿微信小视频功能开发优化记录
【如何快速的开发一个完整的iOS直播app】(原理篇)
iOS动手做一个直播(原理篇)
iOS RTMP 视频直播开发笔记(3)- 了解 H.264 编码
视频方向问题处理
http://stackoverflow.com/questions/26932794/square-cropping-and-fixing-the-video-orientation-in-ios
https://github.com/rs/SDAVAssetExportSession

">"

  • "-" + "空格"xulie
  • 1 dfsf
    高亮语法为 "高亮 "
[添加超链接](http://jianshu.io)
![](网络图片连接) == 插入图片

音频录制#

背景知识###

录音功能生成的目标音频格式是PCM格式,对于PCM的定义,维基百科上是这么写到的:"Pulse-code modulation (PCM) is a method used to digitally represent sampled analog signals. It is the standard form of digital audio in computers, Compact Discs, digital telephony and other digital audio applications. In a PCM stream, the amplitude of the analog signal is sampled regularly at uniform intervals, and each sample is quantized to the nearest value within a range of digital steps.",大致意思是PCM是用来采样模拟信号的一种方法,是现在数字音频应用中数字音频的标准格式,而PCM采样的原理,是均匀间隔的将模拟信号的振幅量化成指定数据范围内最贴近的数值。
  PCM文件存储的数据是不经压缩的纯音频数据,当然只是这么说可能有些抽象,我们拉上大家熟知的MP3文件进行对比,MP3文件存储的是压缩后的音频,PCM与MP3两者之间的关系简单说就是:PCM文件经过MP3压缩算法处理后生成的文件就是MP3文件。我们简单比较一下双方存储所消耗的空间,1分钟的每采样点16位的双声道的44.1kHz采样率PCM文件大小为:16016/8244100/1024=10335.9375KB,约为10MB,而对应的128kps的MP3文件大小仅为1MB左右,既然PCM文件占用存储空间这么大,我们是不是应该放弃使用PCM格式存储录音,恰恰相反,注意第一句话:"PCM文件存储的数据是不经压缩的纯音频数据",这意味只有PCM格式的音频数据是可以用来直接进行声音处理,例如进行音量调节,声音滤镜等操作,相对的其他的音频编码格式都是必须解码后才能进行处理(PCM编码的WAV文件也得先读取文件头),当然这不代表PCM文件就好用,因为没有文件头,所以进行处理或者播放之前我们必须事先知道PCM文件的声道数,采样点字节数,采样率,编码大小端,这在大多数情况下都是不可能的,事实上就我所知没有播放器是直接支持PCM文件的播放。不过现在录音的各项系数都是我们定义的,所以我们就不用担心这个问题
源自:详解如何使用代码进行音频合成

MP3格式中的码率(BitRate)代表了MP3数据的压缩质量,现在常用的码率有128kbit/s、160kbit/s、320kbit/s等等,这个值越高声音质量也就越高。MP3编码方式常用的有两种固定码率(Constant bitrate,CBR)和可变码率(Variable bitrate,VBR)。
MP3格式中的数据通常由两部分组成,一部分为ID3用来存储歌名、演唱者、专辑、音轨数等信息,另一部分为音频数据。音频数据部分以帧(frame)为单位存储,每个音频都有自己的帧头,如图所示就是一个MP3文件帧结构图(图片同样来自互联网)。MP3中的每一个帧都有自己的帧头,其中存储了采样率等解码必须的信息,所以每一个帧都可以独立于文件存在和播放,这个特性加上高压缩比使得MP3文件成为了音频流播放的主流格式。帧头之后存储着音频数据,这些音频数据是若干个PCM数据帧经过压缩算法压缩得到的,对CBR的MP3数据来说每个帧中包含的PCM数据帧是固定的,而VBR是可变的。

AAC简介###

采样率Sample Rate指单位时间内对媒体对象的采样次数,单位Hz(这句话好像和原来不太一样,郁闷)。

帧率(Frame per second,fps),单位时间内媒体帧的个数。

这两个概念都描述了媒体的“连续”性,二者的区别在于一个Frame可能包含多个Sample。一般每个视频帧中只包含一个视频采样,而音频帧中会包含多个音频采样。如1个AAC帧中包含1024个采样。所以,帧率常用在视频方面,采样率常用于音频方面。采样率(帧率)越高,媒体越流畅,当然人的感受就越过瘾。但是,由于人的视/听器官分辨能力的局限,往往这些数值达到末各程度就可以满足人对“连续”性的需求了。比如,对采样率高于44.1kHz的声音,人很难听出区别了。对帧率高于30的视频,人很难看出帧率的区别。

比特率(bps或kbps),与前面两个概念不同,它描述了单位时间长度的媒体内容需要空间。当然该值越高,每个采样的信息量就越大,对这个采样的描述就越精确。

对于人的感受来说,当然上述数值越大越好,但是这总是会受到网络带宽和处理设备能力的限制。所以,媒体工程师会取一个折中的数值来制作媒体内容,在符合能力的范围内,提供最佳的体验。

例子:一张CD,双声道,采样率44.1kHz每个采样13bit,时长74分钟(4440秒),则CD的容量为13244100*4440约等于640MB

在AAC媒体文件中,以Sampling Frequency Index的方式记录AAC的采样率,下面的数组为对应表:AAC_Sampling_Frequency_Table[16] = {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0}

AAC媒体文件的时长难为了我不少时间,现在终于明白了如何计算。

首先要明确一点,AAC的每帧采样个数为1024,即每个AAC帧中包含1024个采样。

这样Frame_duration(s/f)=1024(Sample/f)/Sampling_Rate(Sample/s),File_duration(s)=Frame_duration(s/f)*Frame_count(f)。

例子,某个AAC媒体,采样率16000Hz,938帧,时长=(1024/16000)*938约为60秒。
AAC-Advanced Audio Coding高级音频编码,目前渐成主流的音频编码,是有损音频压缩格式。已被MPEG4标准的文件容器格式采用,估计MP3后的音频霸主就是它了。
AAC帧首部7个字节:

AAC与MPEG4封装AAC媒体帧的方式存在相当的区别,尽管记录的信息相似。
在AAC文件中,帧播放的配置信息存储于帧首部(7-8个字节,ID=0时为7,否则为8)。而在MPEG4中,由于他采用box的一对象的方式封装媒体,故其AAC音频播放信息也被封装于box中。仅使用2个字节。AAC帧首部参看过去的文章,AAC decoder config layout如下:

@struct         AudioStreamBasicDescription
@abstract       This structure encapsulates all the information for describing the basic
                format properties of a stream of audio data.(这个结构体将所有描述基本格式属性的音频数据流信息装入内部)
@discussion     This structure is sufficient to describe any constant bit rate format that  has
                channels that are the same size.(这种结构能充分描述任何恒定比特率格式,那些有声轨,大小一样) Extensions are required for variable bit rate
                data and for constant bit rate data where the channels have unequal sizes.(在那些音轨大小不相等的地方,可变比特率和恒定比特率的扩展是被需要的)
                However, where applicable, the appropriate fields will be filled out correctly
                for these kinds of formats (the extra data is provided via separate properties).(然而,在适用情况下,适当的字段将被以这些格式正确填写)
                In all fields, a value of 0 indicates that the field is either unknown, not
                applicable or otherwise is inapproprate for the format and should be ignored.
                Note that 0 is still a valid value for most formats in the mFormatFlags field.

                In audio data a frame is one sample across all channels. In non-interleaved
                audio, the per frame fields identify one channel. In interleaved audio, the per
                frame fields identify the set of n channels. In uncompressed audio, a Packet is
                one frame, (mFramesPerPacket == 1). In compressed audio, a Packet is an
                indivisible chunk of compressed data, for example an AAC packet will contain
                1024 sample frames.

@field          mSampleRate
                    The number of sample frames per second of the data in the stream.(每秒对原始数据的取样数,即采样率单位Hz)
@field          mFormatID
                    The AudioFormatID indicating the general kind of data in the stream.(表明数据类型)
@field          mFormatFlags
                    The AudioFormatFlags for the format indicated by mFormatID.(AudioFormatFlags的格式被mFormatID定义)
@field          mBytesPerPacket
                    The number of bytes in a packet of data.(一个数据包多少字节)
@field          mFramesPerPacket
                    The number of sample frames in each packet of data.(每个数据包里多少个取样帧)
@field          mBytesPerFrame
                    The number of bytes in a single sample frame of data.(一个取样帧有多少字节)
@field          mChannelsPerFrame
                    The number of channels in each frame of data.(每一帧的声道数,1为单声道)
@field          mBitsPerChannel
                    The number of bits of sample data for each channel in a frame of data.(一帧数据的一个声道采样数据的位数8为,16位或32位)
@field          mReserved
                    Pads the structure out to force an even 8 byte alignment.(猜测:不满8为补足八位)
  • 对于音频数据的所有声道来说一帧(frame)就是一次采样数据(sample)。在非交错封包模式的音频数据中,一个声道的音频数据存在在一个平面内,在交错封包模式中,以立体声为例就是声道1、声道2、声道1、声道2,循环。在未压缩的音频数据中,一个数据包(packet)就是一帧(frame)。在压缩过的音频数据中,一个数据包(packet)是不可分割的一块压缩数据,比如一个AAC(一种音频压缩格式)数据包将会包含有1024分采样帧。

struct AudioStreamBasicDescription
{
Float64 mSampleRate;
AudioFormatID mFormatID;
AudioFormatFlags mFormatFlags;
UInt32 mBytesPerPacket;
UInt32 mFramesPerPacket;
UInt32 mBytesPerFrame;
UInt32 mChannelsPerFrame;
UInt32 mBitsPerChannel;
UInt32 mReserved;
};

//视频格式对于linear PCM,仅支持interleaved格式;支持压缩格式
const AudioStreamBasicDescription *inFormat,
//视频队列的一块缓冲区填满的回调函数
AudioQueueInputCallback         inCallbackProc,
//A value or pointer to data that you specify to be passed to the callback function.
void * __nullable               inUserData,

 CFRunLoopRef __nullable         inCallbackRunLoop,
CFStringRef __nullable          inCallbackRunLoopMode,
UInt32                          inFlags,
AudioQueueRef __nullable * __nonnull outAQ)          

定义一个回调函数的指针,当录制音频的队列填满一个视频缓冲区时会被调用

typedef void (*AudioQueueInputCallback)(
                                    void * __nullable               inUserData,
                                    AudioQueueRef                   inAQ,
                                    AudioQueueBufferRef             inBuffer,
                                    const AudioTimeStamp *          inStartTime,
                                    UInt32                          inNumberPacketDescriptions,
                                    const AudioStreamPacketDescription * __nullable inPacketDescs);
inUserData:
inStartTime:指向音频时间戳结构体的一个指针,之歌时间戳对应着缓冲区第一个样本
inNumberPacketDescriptions:提供给回调函数的数据内包含的packet数
inPacketDescs:packet descriptions

片、场、帧、片的概念###

H264结构中,一个视频图像编码后的数据叫做一帧,一帧由一个片(slice)或多个片组成,一个片由一个或多个宏块(MB)组成,一个宏块由16×16的yuv数据组成。宏块作为H264编码的基本单位。

1帧 = n个片
1片 = n个宏块
1宏块 = 16x16yuv数据

场和帧:视频的一场或一帧可用来产生一个编码图像。在电视中,为减少大面积闪烁现象,把一帧分成两个隔行的场。

宏块:一个编码图像通常划分成若干宏块组成,一个宏块由一个16×16亮度像素和附加的一个8×8 Cb和一个8×8 Cr彩色像素块组成。

片:每个图象中,若干宏块被排列成片的形式。片分为I片、B片、P片和其他一些片。

  • I片只包含I宏块,P片可包含P和I宏块,而B片可包含B和I宏块。
  • I宏块利用从当前片中已解码的像素作为参考进行帧内预测。
  • P宏块利用前面已编码图象作为参考图象进行帧内预测。
  • B宏块则利用双向的参考图象(前一帧和后一帧)进行帧内预测。

详情参考:iOS RTMP 视频直播开发笔记(3)- 了解 H.264 编码

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,198评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,663评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,985评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,673评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,994评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,399评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,717评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,407评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,112评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,371评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,891评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,255评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,881评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,010评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,764评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,412评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,299评论 2 260

推荐阅读更多精彩内容