RTMP发送H264及AAC的音视频

RTMP推送的音视频流的封装形式和FLV格式相似,由此可知,向FMS推送H264和AAC直播流,需要首先发送"AVC sequence header"和"AAC sequence header",这两项数据包含的是重要的编码信息,没有它们,解码器将无法解码。

  AVC sequence header就是AVCDecoderConfigurationRecord结构,该结构在标准文档“ISO-14496-15 AVC file format”中有详细说明。

    RTMP发送H264及AAC的音视频_第1张图片

  AAC sequence header存放的是AudioSpecificConfig结构,该结构则在“ISO-14496-3 Audio”中描述。AudioSpecificConfig结构的描述非常复杂,这里我做一下简化,事先设定要将要编码的音频格式,其中,选择"AAC-LC"为音频编码,音频采样率为44100,于是AudioSpecificConfig简化为下表:

    RTMP发送H264及AAC的音视频_第2张图片

  这样,AVC sequence header和AAC sequence header的内容可以基本确定了,更详细的信息,大家可以去翻阅相关文档。

在发送这两个header需要在前面分别加上 VideoTags、AudioTags  这连个tags都是1个字节(8bits)的数据

其中AudioTags每bit表示的意义如下图:


RTMP发送H264及AAC的音视频_第3张图片

其中SoundData 的组成如下:

RTMP发送H264及AAC的音视频_第4张图片

当数据的第一个字节为0时,后面跟AAC sequence header;

当数据的第一个字节为1时,后面跟AAC 数据;

其中VideoTags每bit表示的意义如下图:

RTMP发送H264及AAC的音视频_第5张图片

发送的为avc数据,所以,CodecID(后4bit)的值为7

所以videodata的数据打包方式为 ,具体的信息见下图:


具体代码实现:

//添加Flv的VideoTags
char* RtmpLiveEncoder::AddVideoTags(char* buf,bool isKeyframe)
{
//前面4字节表示FrameType,后面4字节表示CodecID
unsigned char flag = 0;
if (isKeyframe)
flag = 0x17;
else
flag = 0x27;


buf = UI08ToBytes(buf, flag);
buf = UI08ToBytes(buf, 1);    // avc packet type (0, nalu)  包的类型,同步包为0
buf = UI24ToBytes(buf, 0);    // composition time  0为打开,1为关闭


return buf;
}
//添加Flv的AudioTags
char* RtmpLiveEncoder::AddAudioTags(char* buf)
{
//
unsigned char flag = 0;
flag = (10 << 4) |  // soundformat "10 == AAC"
(3 << 2) |      // soundrate   "3  == 44-kHZ"
(1 << 1) |      // soundsize   "1  == 16bit"
1;              // soundtype   "1  == Stereo"


buf = UI08ToBytes(buf, flag); 
buf = UI08ToBytes(buf, 1);    // aac packet type (1, raw)  包的类型,同步包为0


return buf;
}

这两个函数返回的buf后面接需要发送的数据



注 :

             Audio AAC stream : AudioMetadata + (AF 01 + AAC frame) + (AF 01 + AAC frame) + ...

             Video AVC Stream : VideoMetadata  + (TAG + AVC frame) + (TAG + AVC frame) + ...

 

AudioMetadata : AAC header + ADTS header

 1: AAC header (例如 :AF 00 13 90 )

          第一个音频包那就是AAC header. 

如:af 00 13 90。包长4个字节,解释如下,

1)

  a :第一个字节AF,A就是10代表的意思是AAC。

           第一个字节中的后四位F代表如下 :

                       前2个bit的含义 抽样频率,这里是二进制11,代表44kHZ

                       第3个bit,代表 音频用16位的

                       第4个bit代表声道

                

        b : 第2个字节  AACPacketType,这个字段来表示AACAUDIODATA的类型:0 = AAC sequence header,1 = AAC raw。第一个音频包用0,后面的都用1

        c : 第3,4个字节内容AudioSpecificConfig

2 : ADTS headeer
///////// ADTS_FIXED_HEADER
     1 ~ 12 : 0xFFF syncword
     13 : ID
     14 ~ 15 : layer, always "00"
     16 : protection_absent
     17 ~ 18 : profile. main = 1, LC = 2, SSR = 3, LTP = 4, HE/SBR = 5;
     19 ~ 22 : sampleRate index over next 4 bits                                                                               
     23 : private bit
     24 ~ 26 : channels over last 2 bits channels continued over next 2 bits + 4 bits at zero                                  
     27 : original_copy
     28 : home          
//////// ADTS_VARIABLE_HEADER 
     29 : copyright_identification_bit
     30 : copyright_identification_start    
     31 ~ 43  : 13 bits for frame size
     44 ~ 54 : buffer fullness (0x7FF for VBR) over 5 last bits 
     55 ~ 56  : number_of_raw_data_blocks_in_frame.   

VideoMetadata :  Flags + SPS + PPS
    
    body[i++] = 0x17; // 1:keyframe  7:AVC
    body[i++] = 0x00; // AVC sequence header                                                                                                                              
    body[i++] = 0x00;         
    body[i++] = 0x00;
    body[i++] = 0x00; // fill in 0;
                                                                                                                                     
    // AVCDecoderConfigurationRecord.
    body[i++] = 0x01; // configurationVersion
    body[i++] = lpMetaData->Sps[1]; // AVCProfileIndication
    body[i++] = lpMetaData->Sps[2]; // profile_compatibility
    body[i++] = lpMetaData->Sps[3]; // AVCLevelIndication
    body[i++] = 0xff; // lengthSizeMinusOne                                                                                                                               

    // sps nums
    body[i++] = 0xE1; //&0x1f 
    // sps data length
    body[i++] = lpMetaData->nSpsLen>>8;
    body[i++] = lpMetaData->nSpsLen&0xff;
    // sps data
    memcpy(&body[i], lpMetaData->Sps, lpMetaData->nSpsLen);
    i += lpMetaData->nSpsLen;

    // pps nums
    body[i++] = 0x01; //&0x1f
    // pps data length
    body[i++] = lpMetaData->nPpsLen>>8;
    body[i++] = lpMetaData->nPpsLen&0xff;
    // sps data
    memcpy(&body[i], lpMetaData->Pps, lpMetaData->nPpsLen);
    i += lpMetaData->nPpsLen;

TAG :
    int i = 0;
    if(0 == bIsKeyFrame) 
        body[i++] = 0x17;// 1:Iframe  7:AVC                                                                                                                               
    else
        body[i++] = 0x27;// 2:Pframe  7:AVC                                                                                                                               

    body[i++] = 0x01;// AVC NALU   
    body[i++] = 0x00;
    body[i++] = 0x00;
    body[i++] = 0x00;

    // NALU size
    body[i++] = size>>24;
    body[i++] = size>>16;
    body[i++] = size>>8;
    body[i++] = size&0xff;;


C代码下载 : http://download.csdn.net/detail/dssxk/9202893

你可能感兴趣的:(RTMP发送H264及AAC的音视频)