mp4中box'stsd'中的'avcC'分析的H.264编码的头包发送

stsd 的段分析

这里写图片描述

stsd中avc1段分析

这里写图片描述

字段字节数意义
size4size
Data format4封装格式
Reserved6Six bytes that must be set to 0.
Data reference index2有说明数据的参数个数

avc1中的编码视频的宽度高度, 压缩编码32分析

这里写图片描述

size(4)type(4)version(2)Revision level(2)Vendor(4)Temporal quality(4)Spatial quality(4)width(2)Height(2)Horizontal resolution(4)Vertical resolution(4)Data size(4)Frame count(2)Compressor name(4)Depth(2)Color table ID(2)
字段字节数意义
box size4size
box type4type
version2box 版本, 0或1, 一般为0, (以下字节数均按version=0)
Revision level2must be set to 0.
Vendor4
Temporal quality4时间的压缩
Spatial quality4视频的质量
Width2
Height2
Horizontal resolution4垂直分辨率
Vertical resolution4水平分辨率
Data size4A 32-bit integer that must be set to 0
Frame count2A 16-bit integer that indicates how many frames of compressed data are stored in each sample. Usually set to 1.
Compressor name4A 32-byte Pascal string containing the name of the compressor that created the image, such as “jpeg”
Depth2表示压缩图像的像素深度的16位整数。1, 2, 4,8, 16, 24的值,32表示彩色图像的深度。只有在图像包含时才使用值32。阿尔法通道。灰度值分别为34, 36、40和表示2、4和8位灰度值。图像.
Color table ID2标识要使用的颜色表的16位整数。如果这个字段被设置为- 1,默认颜色表应用于指定深度。对于每像素16位以下的深度,这表示一个标准。指定深度的Macintosh颜色表。深度为16, 24,32没有颜色表。如果颜色表ID设置为0,则颜色表包含在示例描述本身中。颜色

这个地方特殊说明,这个地方需要32个8bit位置,0x00 *32第一个8bit来表明字符长度,后面31个8bit来表明压缩的内容,

aligned(8) abstract class SampleEntry (unsigned int(32) format) extends Box(format){
        const unsigned int(8)[6] reserved = 0;    首先6个字节的保留位  值都是0
        unsigned int(16) data_reference_index;  ///一个2个字节来描述的 数据索引
    }

    ///如果是一个空的entry,则追加一个字节的空数据
    class HintSampleEntry() extends SampleEntry (protocol) { 
        unsigned int(8) data [];
    }
    // Visual Sequences    视频entry

    class VisualSampleEntry(codingname) extends SampleEntry (codingname){ 
        unsigned int(16) pre_defined = 0;     //2个字节的保留位
        const unsigned int(16) reserved = 0;    //2个字节的保留位
        unsigned int(32)[3] pre_defined = 0;    //3*4个字节的保留位
        unsigned int(16) width;             //2个字节的宽度
        unsigned int(16) height;                //2个字节的高度
        template unsigned int(32) horizresolution = 0x00480000; // 72 dpi    //纵向dpi,4字节
        template unsigned int(32) vertresolution = 0x00480000; // 72 dpi    //横向dpi 4字节
        const unsigned int(32) reserved = 0;                                //4字节保留位
        template unsigned int(16) frame_count = 1;                      //2字节的frame_count
        string[32] compressorname;                                      //32字节的compressorname
        //这个地方特殊说明,这个地方需要32个8bit位置,0x00 *32
        第一个8bit来表明字符长度,后面318bit来表明压缩的内容,
        例子:
        0x04,                       //  strlen compressorname: 32 bytes         String[32]
                                                        //32个8 bit    第一个8bit表示长度,剩下31个8bit表示内容
            0x67, 0x31, 0x31, 0x31,  // compressorname: 32 bytes    翻译过来是g111
            0x00, 0x00, 0x00, 0x00,//
            0x00, 0x00, 0x00, 0x00,//
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00,


        template unsigned int(16) depth = 0x0018;                       //2字节的色彩深度
        int(16) pre_defined = -1;                                           //2字节的pre_defined
    }
       // Audio Sequences   音频entry

    class AudioSampleEntry(codingname) extends SampleEntry (codingname){ 
        const unsigned int(32)[2] reserved = 0;                             //2*4字节保留位
        template unsigned int(16) channelcount = 2;                         //2字节的channelcount
        template unsigned int(16) samplesize = 16;                          //2字节的 samplesize
        unsigned int(16) pre_defined = 0;                                       //2字节的pre_defined
        const unsigned int(16) reserved = 0 ;                                   //2字节保留位
        template unsigned int(32) samplerate = {timescale of media}<<16;    //4字节声音赫兹
    }

avc1中avcC字段的分析(H.264)

size(4)Type(4)AVC Decoder Configuration Record

这里写图片描述

数据有H.264分析header

00 00 00 31, 61 76 63 43, 01 42 C0 15, FF E1 00 19

67 42 C0 15, D9 01 B1 FE, 4F 01 10 00, 00 03 00 10

00 00 03 03, 20 F1 62 E4, 80 01 00 05, 68 CB 82 CB 20

mp4中分析h.264

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

长度字段说明
8 bitconfiguration Version版本号, 1
8 bitAVCProFileIndicationsps[1]
8 bitprofile_compatibilitysps[2]
8 bitAVC_LevelIndicationsps[3]
6 bitreserved
2 bitlengthSizeMinusOneNALUnitLength的长度-1
3 bitreserved111
5 bitnumOfSequencePaarameterSetssps个数, 一般为1
sequenceParameterSetNALUnitssps_size + size)的数组
8 bitnumOfPictureParameterSetspps个数, 一般为1
pictureParameterSetNALUnit(pps_size + pps)的数组

根据 AVCDecoderConfigurationRecord 结构的定义:

  1. 00 00 00 31: box size : ‘avcC’ 大小 49个字节
  2. 61 76 63 43: box type : ‘avcC’ 类型
  3. 01 : box 版本:
  4. 42 C0 15 : box ProFile sps[1]
  5. FF : 非常重要,是 H.264 视频中 NALU 的长度,计算方法是 1 + (lengthSizeMinusOne & 3),实际计算结果一直是4
  6. E1 : SPS 的个数,计算方法是 numOfSequenceParameterSets & 0x1F,实际计算结果一直为1
  7. 00 19 : SPS的长度 ->25个字节
  8. 67 42 C0 15, D9 01 B1 FE, 4F 01 10 00, 00 03 00 10, 00 00 03 03, 20 F1 62 E4, 80 –> SPS
  9. 01 : PPS的个数
  10. 00 05 : PPS的长度
  11. 68 CB 82 CB 20 : PPS数据

发送NALU包


    void add_264_sequence_header(unsigned char *pps, unsigned char *sps,
                                 int pps_len, int sps_len) {
        int body_size = 13 + sps_len + 3 + pps_len;
        RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket));
        RTMPPacket_Alloc(packet, body_size);
        RTMPPacket_Reset(packet);
        char *body = packet->m_body;
        int i = 0;
        body[i++] = 0x17;
        body[i++] = 0x00;
        //composition time 0x000000
        body[i++] = 0x00;
        body[i++] = 0x00;
        body[i++] = 0x00;

        /*AVCDecoderConfigurationRecord*/
        body[i++] = 0x01;
        body[i++] = sps[1];
        body[i++] = sps[2];
        body[i++] = sps[3];
        body[i++] = 0xFF;

        /*sps*/
        body[i++] = 0xE1;
        body[i++] = (sps_len >> 8) & 0xff;
        body[i++] = sps_len & 0xff;
        memcpy(&body[i], sps, sps_len);
        i += sps_len;

        /*pps*/
        body[i++] = 0x01;
        body[i++] = (pps_len >> 8) & 0xff;
        body[i++] = (pps_len) & 0xff;
        memcpy(&body[i], pps, pps_len);
        i += pps_len;

        packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
        packet->m_nBodySize = body_size;
        packet->m_nChannel = 0x04;
        packet->m_nTimeStamp = 0;
        packet->m_hasAbsTimestamp = 0;
        packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
        add_rtmp_packet(packet);
    }

    void add_264_body(unsigned char *buf, int len) {
        /*去掉帧界定符 *00 00 00 01*/
        if (buf[2] == 0x00) { //
            buf += 4;
            len -= 4;
        } else if (buf[2] == 0x01) { //00 00 01
            buf += 3;
            len -= 3;
        }
        int body_size = len + 9;
        RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket));
        RTMPPacket_Alloc(packet, len + 9);
        char *body = packet->m_body;
        int type = buf[0] & 0x1f;
        /*key frame*/
        body[0] = 0x27;
        if (type == NAL_SLICE_IDR) {
            body[0] = 0x17;
        }
        body[1] = 0x01; /*nal unit*/
        body[2] = 0x00;
        body[3] = 0x00;
        body[4] = 0x00;

        body[5] = (len >> 24) & 0xff;
        body[6] = (len >> 16) & 0xff;
        body[7] = (len >> 8) & 0xff;
        body[8] = (len) & 0xff;

        /*copy data*/
        memcpy(&body[9], buf, len);

        packet->m_hasAbsTimestamp = 0;
        packet->m_nBodySize = body_size;
        packet->m_packetType = RTMP_PACKET_TYPE_VIDEO;
        packet->m_nChannel = 0x04;
        packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
    //  packet->m_nTimeStamp = -1;
        packet->m_nTimeStamp = RTMP_GetTime() - start_time;
        add_rtmp_packet(packet);
    }

    void add_aac_body(unsigned char *buf, int len) {
        //outputformat = 1 ADTS头 7个,写入文件
        //  outputformat = 0  直接为原始数据 不需要去掉头7个
    //      buf += 7;
    //      len -= 7;
        int body_size = len + 2;
        RTMPPacket *packet = (RTMPPacket *) malloc(sizeof(RTMPPacket));
        RTMPPacket_Alloc(packet, body_size);
        char *body = packet->m_body;
        /*AF 01 + AAC RAW data*/
        body[0] = 0xAF;
        body[1] = 0x01;
        memcpy(&body[2], buf, len);
        packet->m_packetType = RTMP_PACKET_TYPE_AUDIO;
        packet->m_nBodySize = body_size;
        packet->m_nChannel = 0x04;
        packet->m_hasAbsTimestamp = 0;
        packet->m_headerType = RTMP_PACKET_SIZE_MEDIUM;
    //  packet->m_nTimeStamp = -1;
        packet->m_nTimeStamp = RTMP_GetTime() - start_time;
        add_rtmp_packet(packet);
    }

音频数据分析

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

长度字段说明
5 bitaudio ObjectType编码结构类型, AAC-LC为2
4 bitsamplingFrequencyIndex音频采样率索引值, 44100对应值4
4 bitchannelConfiguration音频输出声道, 2
GASpecific该结构包含以下三项
1 bitframeLengthFlag标志位, 用于表明IMDCT窗口长度, 0
1 bitdependsOnCoreCoder标志位, 表明是否依赖于corecoder, 0
1 bitextensionFlag选择了AAC-LC, 这里必须为0

这里写图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值