java封装264成flv,FLV视频封装格式详细解析

FLV的定义:

Flash Video(简称FLV),是一种流行的网络格式,是Adobe推出的。目前大部分视频网站都支持这种格式。

FLV的文件结构

FLV文件由FLV Header 和 FLV Body构成。

FLV Header 头部信息

Header 部分记录了FLV的类型、版本、流信息、Header 长度等。一般整个Header占用9个字节,大于9个字节则表示头部信息在这基础之上还存在扩展数据。Header 的头部信息排布如下所示:

07657d85617e

FLV头部信息排布

FLV Body 文件内容部分

Body 是由一个个Tag组成的,每个Tag下面有一块4个字节的空间,用来记录这个Tag 的长度。这个后置的PreviousTagSize用于逆向读取处理,表示的是前面的Tag的大小,对于FLV版本0x01来说,数值等于 11 + Tag的DataSize。其结构排布如下:

07657d85617e

FLV Body结构排布

FLV Tag

每个Tag 也是由两部分组成的:Tag Header 和 Tag Data。Tag Header 存放了当前Tag的类型,数据长度、时间戳、时间戳扩展、StreamsID等信息,然后再接着数据区Tag Data。Tag的排布如下:

07657d85617e

Tag构成排布

Tag Data

Tag Data分成 Audio,Video,Script 三种。

Audio Tag Data

音频的Tag Data又分为 AudioTagHeader 和 Data 数据区,其排布结构如下图所示:

07657d85617e

音频Tag Data排布

AudioTagHeader通常占用1个字节,AAC编码则会多出一个AACPacketType的字节,用于表示AAC的序列头还是裸数据。

其中,前4bits表示SoundFormat,其数值对应声音格式,如下:

0 - Linear PCM, platform endian

1 - ADPCM

2 - MP3

3 - LinearPCM,little endian

4 - Nellymoser 16-kHz mono

5 - Nellymoser 8-kHZ mono

6 - Nellymoser

7 - G.711 A-law logarithmic PCM

8 - G.711 U-law logarithmic PCM

9 - reserved

10 - AAC

11 - Speex

14 - MP3 8-kHz

15 - Device-specific sound

第5、6bit 表示SoundRate,数值对应采样率,对于AAC来说,总是3:

0 - 5.5kHz

1 - 11kHz

2 - 22kHz

3 - 44kHz

第7bit 表示采样大小:

0 - snd 8 bit

1 - snd 16 bit

第8bit 表示音频声道数,对于AAC来说,总是1:

0 - sndMono

1 - sndStereo

audio Data数据区,根据SoundFormat的数值来确定,如果SoundFormat = 10,则Data数据区是AAC编码部分,其他声音类型,则根据具体格式进行解析。

AAC编码

针对AAC编码,音频Data数据区的定义如下:

AACPacketType = 0 时,表示AAC序列头,也就是AudioSpecificConfig, AACPacketType = 1 时,表示AAC的裸流,也就是AAC Raw frame data。

AudioSpecificConfig

AudioSpecificConfig 只出现在第一个Audio Tag中,结构如下,

AudioSpecificConfig() {

audioObjectType; 5bits

samplingFrequencyIndex; 4bits

if ( samplingFrequencyIndex == 0xf ) {

samplingFrequency; 24bits

}

channelConfiguration; 4bits

sbrPresentFlag = -1;

if ( audioObjectType == 5 ) {

extensionAudioObjectType = audioObjectType;

sbrPresentFlag = 1;

extensionSamplingFrequencyIndex; 4bits

if ( extensionSamplingFrequencyIndex == 0xf ) {

extensionSamplingFrequency; 24bits

}

audioObjectType; 5bits

} else {

extensionAudioObjectType = 0;

}

if ( audioObjectType == 1 || audioObjectType == 2 ||

audioObjectType == 3 || audioObjectType == 4 ||

audioObjectType == 6 || audioObjectType == 7 ) {

GASpecificConfig();

}

if ( audioObjectType == 8 ) {

CelpSpecificConfig();

}

if ( audioObjectType == 9 ) {

HvxcSpecificConfig();

}

if ( audioObjectType == 12 ) {

TTSSpecificConfig();

}

if ( audioObjectType == 13 || audioObjectType == 14 ||

audioObjectType == 15 || audioObjectType == 16 ) {

StructureAudioSpecificConfig();

}

if ( audioObjectType == 17 || audioObjectType == 19 ||

audioObjectType == 20 || audioObjectType == 21 ||

audioObjectType == 22 || audioObjectType == 23 ) {

GASpecificConfig();

}

if ( audioObjectType == 24 ) {

ErrorResilientCelpSpecificConfig();

}

if ( audioObjectType == 25 ) {

ErrorResilientHvxcSpecificConfig();

}

if ( audioObjectType == 26 || audioObjectType == 27 ) {

ParametricSpecificConfig();

}

if ( audioObjectType == 17 || audioObjectType == 19 ||

audioObjectType == 20 || audioObjectType == 21 ||

audioObjectType == 22 || audioObjectType == 23 ||

audioObjectType == 24 || audioObjectType == 25 ||

audioObjectType == 26 || audioObjectType == 27 ) {

epConfig; 2bits

if ( epConfig == 2 || epConfig == 3 ) {

ErrorProtectionSpecificConfig();

}

if ( epConfig == 3 ) {

directMapping; 1bit

if ( ! directMapping ) {

/* tbd */

}

}

}

if ( audioObjectType == 28 ) {

SSCSpecificConfig();

}

if ( extensionAudioObjectType != 5 && bits_to_decode() >= 16 ) {

syncExtensionType; 11bits

if ( syncExtensionType == 0x2b7 ) {

extensionAudioObjectType; 5bits

if ( extensionAudioObjectType == 5 ) {

sbrPresentFlag; 1bit

if ( sbrPresentFlag == 1 ) {

extensionSamplingFrequencyIndex; 4bits

if ( extensionSamplingFrequencyIndex == 0xf ) {

extensionSamplingFrequency; 24bits

}

}

}

}

}

}

AudioSpecificConfig 简化格式如下:

audioObjectType 5bits 编码结构类型,AAC-LC为2

samplingFreguencyIndex 4bits 音频采样率索引值

channelConfiguration 4bits 音频声道数

GASpecificConfig

frameLengthFlag 1bits 标志位,用于表明IMDCT窗口长度,为0

dependsOnCoreCoder 1bits 标志位,用于表明是否依赖corecoder,为0

extensionFlag 1bits 扩展标志位,选择了AAC-LC,这里必须为0

其中,samplingFreguencyIndex 对应关系如下:

0 - 96000

1 - 88200

2 - 64000

3 - 48000

4 - 44100

5 - 32000

6 - 24000

7 - 22050

8 - 16000

9 - 12000

10 - 11025

11 - 8000

12 - 7350

13 - Reserved

14 - Reserved

15 - frequency is written explictly

AAC Raw frame data

AAC裸流AAC Raw frame data,即AAC音频原始数据,不包括AAC头数据ADTS。

AAC头部数据 ADTS

ADTS包括采样频率、帧长度等信息,共7个字节,分为两部分:

adts_fixed_header 、adts_variable_header

adts_fixed_header 排布如下:

adts_fixed_header() {

syncword 12bits always 0xFFF

ID 1bit 0--MPEG-4 1--MPEG-2

layer 2bits always '00'

protection_absent 1bit

profile 2bits 0--Main profile 1--Low Complexity profile(LC)

2--Scalable Sampling Rate profile(SSR) 3--reserved

sampling_frequency_index 4bits 音频采样率索引值

private_bit 1bit

channel_configuration 3bits 音频声道数

original_copy 1bit

home 1bit

}

channel_configuration 对应关系如下:

0 bit : Defined in AOT Specific Config

1 bit : 1 channel:front-center

2 bit : 2 channels:front-left,front-right

3 bit : 3 channels:front-center,front-left,front-right

4 bit : 4 channels:front-center,front-left,front-right,back-center

5 bit : 5 channels:front-center,front-left,front-right,back-left,back-right

6 bit : 6 channels:front-center,front-left,front-right,back-left,back-right,LFE-channel

7 bit : 8 channels:front-center,front-left,front-right,side-left,side-right,back-left,back-right,LFE-channel

8-15 bit:Reserved

adts_variable_header排布如下:

adts_variable_header() {

copyright_identification_bit 1bit

copyright_identification_start 1bit

aac_frame_length 13bits ADTS头 + AAC原始流

adts_buffer_fullness 11bits 0x7FF表示码率可变的码流

number_of_raw_data_blocks_in_frame 2bits

}

MP3编码

如果是MP3 编码部分,audio 数据区直接为 MP3 头 + MP3 原始数据。

MP3 头部格式如下:

MP3FrameHeader

{

sync 11bits 同步信息always 0xFFF

version 2bits 版本 00--MPEG 2.5 01--未定义 10--MPEG 2 11--MPEG 1

layer 2bits 层 00--未定义 01--Layer 3 10--Layer 2 11--Layer 1

error_protection 1bit CRC校验0--校验 1--不校验

bitrate_index 4bits 位率

sampling_frequency 2bits 采样率索引值

padding 1bit 帧长调节

private 1bit 保留字

mode 2bits 声道模式

mode_extension 2bits 扩充模式

copyright 1bit 版权

original 1bit 原版标志

emphasis 2bits 强调模式

}

sampling_frequency对应关系如下:

version 00--MPEG 2.5 01--未定义 10--MPEG 2 11--MPEG 1

MPEG 1: 00--44.1kHz 01--48kHz 10--32kHz 11--未定义

MPEG 2: 00--22.05kHz 01--24kHz 10--16kHz 11--未定义

MPEG 2.5: 00--11.025kHz 01--12kHz 10--8kHz 11--未定义

mode对应关系如下:

00--立体声Stereo 01--Joint Stereo 10--双声道 11--单声道

Video Tag Data

如果Tag 包中的TagType = 9时,这个Tag就表示video数据。则StreamID之后紧跟着 VideoTagHeader 和 Video Data 数据区。

Video Tag 有一个字节的VideoTagHeader 和 Video数据区部分组成

VideoTagHeader

VideoTagHeader 通常由一个字节构成,前4bit表示类型,后4bit表示编码器Id。

07657d85617e

VideoTagHeader

Video数据区

Video数据区部分格式不确定。对于H264/AVC编码部分,Video数据区排布如下:

07657d85617e

Video数据区排布

其中,AVCsequenceheader只有出现在第一个Video Tag,只有一个。为了能够从FLV中获取NALU,必须知道前面的NALU长度所占的字节数,通常是1、2、4个字节,这个内容则必须从AVCDecoderConfigurationRecord中获取,这个遵从标准ISO/IEC 14496-15的5.2.4小节。AVCDecoderConfigurationRecord 的结构如下:

aligned(8) class AVCDecoderConfigurationRecord {

unsigned int(8) configurationVersion = 1; //版本号

unsigned int(8) AVCProfileIndication; //sps[1],即0x67后面那个字节

unsigned int(8) profile_compatibility; //sps[2]

unsigned int(8) AVCLevelIndication; //sps[3]

bit(6) reserved = '111111'b;

unsigned int(2) lengthSizeMinusOne; //NALUnitLength的长度减1,一般为3

bit(3) reserved = '111'b;

unsigned int(5) numOfSequenceParameterSets; //sps个数,一般为1

for ( i=0; i

unsigned int(16) sequenceParameterSetLength; //sps的长度

bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;

}

unsigned int(8) numOfPictureParameterSets; //pps个数,一般为1

for ( i=0; i

unsigned int(16) pictureParameterSetLength; //pps长度

bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;

}

}

其中,lengthSizeMinusOne + 1 = NALU长度字段所占字节数

Script Tag

当TagType = 0x12时, 这个Tag就是Script tag。Script Tag一般只有一个,是FLV文件的第一个Tag,用于存放FLV文件信息,比如时长、分辨率、音频采样率等。所有的数据都是以数据类型 + (数据长度) + 数据格式出现,数据类型占1个字节,数据长度看数据类型是否存在,后面才是数据。数据排布如下:

07657d85617e

ScriptTag排布

其中SCRIPTDATAOBJECTEND和SCRIPTDATAVARIABLEEND为0x000009,用于标记结尾

SCRIPTDATASTRING结构为:

StringLength 2bytes

StringData String

SCRIPTDATALONGSTRING结构为:

StringLength 4bytes

StringData String

ECMA array type结构为:

ECMAArrayLength 4bytes

StringLength 2bytes

StringData String

DataType 1byte

Data 不定长

SCRIPTDATAVARIABLEEND

Object type结构为:

StringLength 2bytes

StringData String

DataType 1byte

DataVale 不定长

SCRIPTDATAOBJECTEND

Strict array type结构为:

ArrayNum 4bytes

DataType byte

DataValue 不定长

类型在FLV的官方文档中有详细的介绍。

onMeteData

onMeteData 是FLV文件中的第一个Tag,是ScriptData中对我们来说十分重要的信息,结构如下:

07657d85617e

onMeteData结构

audiocodecid

音频编码类型id,跟AudioTagHeader中的SoundFormat是对应的。

videocodecid

视频编码类型id,跟VideoTagHeader 的 CodecID是对应的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将 H264 转换为 FLV 格式可以使用以下方法: 1. 首先,你需要使用 H264 的编码器,将视频编码为 H264 格式。 2. 然后,你需要将编码后的 H264 数据封装FLV 格式。这可以使用 FLV 封装器来完。 3. 最后,你需要将封装后的 FLV 数据写入到文件或网络,以便播放或传输。 下面是一个简单的 Java 示例代码,将 H264 数据转换为 FLV: ``` import java.io.*; public class H264ToFlv { public static void main(String[] args) throws Exception { // 读取 H264 数据 FileInputStream h264File = new FileInputStream("input.h264"); byte[] h264Data = new byte[h264File.available()]; h264File.read(h264Data); h264File.close(); // 创建 FLV 封装器 FileOutputStream flvFile = new FileOutputStream("output.flv"); FlvWriter flvWriter = new FlvWriter(flvFile); // 将 H264 数据封装FLV FlvTag videoTag = new FlvTag(FlvTag.VIDEO_TAG); videoTag.setData(h264Data); flvWriter.writeTag(videoTag); // 关闭 FLV 封装flvWriter.close(); flvFile.close(); } } class FlvWriter { private OutputStream out; public FlvWriter(OutputStream out) { this.out = out; } public void writeTag(FlvTag tag) throws IOException { // 写入 Tag Header out.write(tag.getType()); out.write(tag.getDataSize() >> 16); out.write(tag.getDataSize() >> 8); out.write(tag.getDataSize()); out.write(tag.getTimestamp() >> 16); out.write(tag.getTimestamp() >> 8); out.write(tag.getTimestamp()); out.write(tag.getTimestampExtended()); out.write(0); // 写入 Tag Data out.write(tag.getData()); // 写入 Tag Footer out.write(tag.getDataSize() >> 16); out.write(tag.getDataSize() >> 8); out.write(tag.getDataSize()); out.write(tag.getStreamId() >> 16); out.write(tag.getStreamId() >> 8); out.write(tag.getStreamId()); } public void close() throws IOException { out.close(); } } class FlvTag { public static final int AUDIO_TAG = 8; public static final int VIDEO_TAG = 9; public static final int SCRIPT_DATA_TAG = 18; private int type; private int dataSize; private int timestamp; private byte timestampExtended; private int streamId; private byte[] data; public FlvTag(int type) { this.type = type; this.timestamp = 0; this.timestampExtended = 0; this.streamId = 0; } public int getType() { return type; } public int getDataSize() { return dataSize; } public void setDataSize(int dataSize) { this.dataSize = dataSize; } public int getTimestamp() { return timestamp; } public void setTimestamp(int timestamp) { this.timestamp = timestamp; } public byte getTimestampExtended() { return timestampExtended; } public void setTimestampExtended(byte timestampExtended) { this.timestampExtended = timestampExtended; } public int getStreamId() { return streamId; } public void setStreamId(int streamId) { this.streamId = streamId; } public byte[] getData() { return data; } public void setData(byte[] data) { this.data = data; this.dataSize = data.length; } } ``` 在上面的示例代码,我们使用 `FlvWriter` 类来将 H264 数据封装FLV 格式,并写入到文件。`FlvWriter` 类的 `writeTag()` 方法用于写入 FLV 格式Tag 数据。`FlvTag` 类表示一个 FLV 格式Tag,包含 Tag Header 和 Tag Data。其Tag Header 包含了 Tag 的类型、数据大小、时间戳等信息,而 Tag Data 则包含了具体的音视频数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值