(四)图像参数集语义

pic_parameter_set_rbsp( ) {   
    // pic_parameter_set_id 用以指定本参数集的序号,该序号在各片的片头被引用。 
   pic_parameter_set_id   
    // seq_parameter_set_id  指明本图像参数集所引用的序列参数集的序号。 
    seq_parameter_set_id   
   // entropy_coding_mode_flag  指明熵编码的选择,本句法元素为0时,表示熵编码使用 CAVLC,本句法元素为1时表示熵编码使用 CABAC  
    entropy_coding_mode_flag   
    // pic_order_present_flag        POC 的三种计算方法在片层还各需要用一些句法元素作为参数,本句法元素等于1时表示在片头会有句法元素指明这些参数;本句法元素等于0时,表示片头不会给出这些参数,这些参数使用默认值 
    pic_order_present_flag   
    // num_slice_groups_minus1  本句法元素加1后指明图像中片组的个数。H.264  中没有专门的句法元素用于指明是否使用片组模式,当本句法元素等于0(即只有一个片组),表示不使用片组模式,后面也不会跟有用于计算片组映射的句法元素。  
    num_slice_groups_minus1   
    if( num_slice_groups_minus1 > 0 ) {    
        /* slice_group_map_type  用以指明片组分割类型。  
           map_units 的定义: 
          -  当 frame_mbs_only_flag 等于1时,map_units 指的就是宏块 
          -  当 frame_mbs_only_flag 等于0时  
              -  帧场自适应模式时,map_units 指的是宏块对 
              -  场模式时,map_units 指的是宏块 
              -  帧模式时,map_units 指的是与宏块对相类似的,上下两个连续宏块的组合体。      */ 
        slice_group_map_type        
        if( slice_group_map_type    = =    0 )         
            for( iGroup = 0; iGroup <= num_slice_groups_minus1; iGroup++ )         
                // run_length_minus1[i]     用以指明当片组类型等于0时,每个片组连续的 map_units 个数 
                run_length_minus1[ iGroup ]    
        else if( slice_group_map_type    = =    2 )         
            for( iGroup = 0; iGroup < num_slice_groups_minus1; iGroup++ ) {         
                // top_left[i],bottom_right[i]   用以指明当片组类型等于2时,矩形区域的左上及右下位置。 
                top_left[ iGroup ]   
                bottom_right[ iGroup ]   
            }         
        else if(    slice_group_map_type    = =    3    | |     
                    slice_group_map_type    = =    4    | |     
                    slice_group_map_type    = =    5 ) { 
            // slice_group_change_direction_flag 与下一个句法元素一起指明确切的片组分割方法。  
           slice_group_change_direction_flag    
           // slice_group_change_rate_minus1       用以指明变量 SliceGroupChangeRAte 
            slice_group_change_rate_minus1    
        } else if( slice_group_map_type    = =    6 ) {    
           // pic_size_in_map_units_minus1   在片组类型等于6时,用以指明图像以 map_units 为单位的大小。      
            pic_size_in_map_units_minus1    
            for( i = 0; i <= pic_size_in_map_units_minus1; i++ )         
                // slice_group_id[i]           在片组类型等于6时,用以指明某个 map_units 属于哪个片组。 
                slice_group_id[ i ]    
        }         
    }         
   // num_ref_idx_l0_active_minus1  加1后指明目前参考帧队列的长度,即有多少个参考帧(包括短期和长期)。值得注意的是,当目前解码图像是场模式下,参考帧队列的长度应该是本句法元素再乘以2,因为场模式下各帧必须被分解以场对形式存在。(这里所说的场模式包括图像的场及帧场自适应下的处于场模式的宏块对)  本句法元素的值有可能在片头被重载。  
      在序列参数集中有句法元素 num_ref_frames 也是跟参考帧队列有关,它们的区别是num_ref_frames指明参考帧队列的最大值,解码 器用它的值来分配内存空 间;num_ref_idx_l0_active_minus1 指明在这个队列中当前实际的、已存在的参考帧数目,这从它的名字“active”中也可以看出来。图像时,并不是直接传送该图像的编号,而是传送该图像在参考帧队列中的序号。这个序号并不是在码流中传送的,这个句法元素是 H.264 中最重要的句法元素之一,编码器要通知解码器某个运动矢量所指向的是哪个参考而是编码器和解码器同步地、用相同的方法将参考图像放入队列,从而获得一个序号。这个队列在每解一个图像,甚至是每个片后都会动态地更新。维护参考帧队列是编解码器十分重要的工作,而本句法元素是维护参考帧队列的重要依据。参考帧队列的复杂的维护机制是 H.264 重要也是很有特色的组成部分  
    num_ref_idx_l0_active_minus1   
    num_ref_idx_l1_active_minus1
  
    // weighted_pred_flag  用以指明是否允许P和SP片的加权预测,如果允许,在片头会出现用以计算加权预测的句法元素。 
   weighted_pred_flag    
    // weighted_bipred_flag   用以指明是否允许 B 片的加权预测,本句法元素等于 0 时表示使用默认加权预测模式,等于 1 时表示使用显式加权预测模式,等于 2 时表示使用隐式加权预测模式。  
    weighted_bipred_idc    
    // pic_init_qp_minus26  加 26 后用以指明亮度分量的量化参数的初始值。在 H.264 中,量化参数分三个级别给出:图像参数集、片头、宏块。在图像参数集给出的是一个初始值。 
    pic_init_qp_minus26    /* relative to 26 */    
    pic_init_qs_minus26    /* relative to 26 */   
    // chroma_qp_index_offset   色度分量的量化参数是根据亮度分量的量化参数计算出来的,本句法元素用以指明计算时用到的参数。 
    chroma_qp_index_offset    
   // deblocking_filter_control_present_flag  编码器可以通过句法元素显式地控制去块滤波的强度,本句法元素指明是在片头是否会有句法元素传递这个控制信息。如果本句法元素等于 0,那些用于传递滤波强度的句法元素不会出现,解码器将独立地计算出滤波强度。 
    deblocking_filter_control_present_flag   
    // constrained_intra_pred_flag  在 P 和 B 片中,帧内编码的宏块的邻近宏块可能是采用的帧间编码。当本句法元素等于 1 时,表示帧内编码的宏块不能用帧间编码的宏块的像素作为自己的预测,即帧内编码的宏块只能用邻近帧内编码的宏块的像素作为自己的预测;而本句法元素等于 0 时,表示不存在这种限制。 
    constrained_intra_pred_flag   
    // redundant_pic_cnt_present_flag 指明是否会出现 redundant_pic_cnt  句法元素。 
    redundant_pic_cnt_present_flag   
    rbsp_trailing_bits
( )        
}

(五)片头句法

slice_header( ) {  
    // first_mb_in_slice  片中的第一个宏块的地址,  片通过这个句法元素来标定它自己的地址。 要注意的是在帧场自适应模式下,宏块都是成对出现,这时本句法元素表示的是第几个宏块对,对应的第一个宏块的真实地址应该是2 * first_mb_in_slice  
    first_mb_in_slice    
    /* slice_type    指明片的类型 
       slice_type          Name of slice_type 
       0                        P (P slice) 
       1                        B (B slice) 
       2                        I (I slice) 
       3                        SP (SP slice) 
       4                        SI (SI slice) 
       5                        P (P slice) 
       6                        B (B slice) 
       7                        I (I slice) 
       8                        SP (SP slice) 
       9                        SI (SI slice) */ 
    slice_type    
    // pic_parameter_set_id  图像参数集的索引号.  范围 0  到 255。  
    pic_parameter_set_id    
    // frame_num  每个参考帧都有一个依次连续的 frame_num 作为它们的标识,这指明了各图像的解码顺序。但事实上我们可以看到,frame_num 的出现没有 if 语句限定条件,这表明非参考帧的片头也会出现 frame_num。只是当该个图像是参考帧时,它所携带的这个句法元素在解码时才有意义。 
    H.264 对 frame_num的值作了如下规定:当参数集中的句法元素gaps_in_frame_num_value_allowed_flag 不为1 时,每个图像的 frame_num  值是它前一个参考帧的frame_num 值增加 1。这句话包含有两层意思: 
    1)  当 gaps_in_frame_num_value_allowed_flag  不为 1,即 frame_num  连续的情况下,每个图像的frame_num 由前一个参考帧图像对应的值加 1,着重点是“前一个参考帧”。 
           前面我们曾经提到,对于非参考帧来说,它的 frame_num  值在解码过程中是没有意义的,因为frame_num  值是参考帧特有的,它的主要作用是在该图像被其他图像引用作运动补偿的参考时提供一个标识。但 H.264 并没有在非参考帧图像中取消这一句法元素,原因是在 POC 的第二种和第三种解码方法中可以通过非参考帧的 frame_num 值计算出他们的 POC 值。 
    2)  当 gaps_in_frame_num_value_allowed_flag 等于 1,前文已经提到,这时若网络阻塞,编码器可以将编码后的若干图像丢弃,而不用另行通知解码器。在这种情况下,解码器必须有机制将缺失的frame_num 及所对应的图像填补,否则后续图像若将运动矢量指向缺失的图像将会产生解码错误。  
    frame_num    
    if( !frame_mbs_only_flag ) {  
        // field_pic_flag     这是在片层标识图像编码模式的唯一一个句法元素。所谓的编码模式是指的帧编码、场编码、帧场自适应编码。当这个句法元素取值为 1 时  属于场编码; 0 时为非场编码。         
       field_pic_flag    
        if( field_pic_flag )           
            // bottom_field_flag   等于 1 时表示当前图像是属于底场;等于 0 时表示当前图像是属于顶场。 
            bottom_field_flag    
    }          
    if( nal_unit_type    ==    5 )          
        // idr_pic_id      IDR  图像的标识。不同的 IDR 图像有不同的 idr_pic_id 值。值得注意的是,IDR 图像有不等价于 I 图像,只有在作为 IDR 图像的 I 帧才有这个句法元素,在场模式下,IDR 帧的两个场有相同的 idr_pic_id 值。idr_pic_id 的取值范围是  [0,65535],和 frame_num 类似,当它的值超出这个范围时,它会以循环的方式重新开始计数。   
        idr_pic_id   
    if( pic_order_cnt_type    ==    0 ) {     
        // pic_order_cnt_lsb    在 POC 的第一种算法中本句法元素来计算 POC 值,在 POC 的第一种算法中是显式地传递 POC 的值,而其他两种算法是通过 frame_num 来映射 POC 的值。 
        pic_order_cnt_lsb         
        if( pic_order_present_flag &&    !field_pic_flag )          
            // delta_pic_order_cnt_bottom    如果是在场模式下,场对中的两个场都各自被构造为一个图像,它们有各自的 POC 算法来分别计算两个场的 POC 值,也就是一个场对拥有一对 POC 值;而在是帧模式或是帧场自适应模式下,一个图像只能根据片头的句法元素计算出一个 POC 值。根据 H.264 的规定,在序列中有可能出现场的情况,即 frame_mbs_only_flag 不为 1 时,每个帧或帧场自适应的图像在解码完后必须分解为两个场,以供后续图像中的场作为参考图像。所以当 frame_mb_only_flag  不为 1时,帧或帧场自适应中包含的两个场也必须有各自的 POC 值。通过本句法元素,可以在已经解开的帧或帧场自适应图像的 POC 基础上新映射一个 POC 值,并把它赋给底场。当然,象句法表指出的那样,这个句法元素只用在 POC 的第一个算法中。 
            delta_pic_order_cnt_bottom    
    }          
    if( pic_order_cnt_type = = 1 && !delta_pic_order_always_zero_flag ) {       
       // delta_pic_order_cnt[0], delta_pic_order_cnt[1]:POC 的第二和第三种算法是从 frame_num 映射得来,这两个句法元素用于映射算法。delta_pic_order_cnt[0]用于帧编码方式下的底场和场编码方式的场,delta_pic_order_cnt[1] 用于帧编码方式下的顶场。     
        delta_pic_order_cnt[ 0 ]  
        if( pic_order_present_flag    &&    !field_pic_flag )          
            delta_pic_order_cnt[ 1 ]   
    }          
    if( redundant_pic_cnt_present_flag )         
        // redundant_pic_cnt    冗余片的 id 号。  
        redundant_pic_cnt   
    if( slice_type    ==    B )          
        // direct_spatial_mv_pred_flag  指出在B图像的直接预测的模式下,用时间预测还是用空间预测。1:空间预测;0:时间预测。  
        direct_spatial_mv_pred_flag   
    if( slice_type = = P | | slice_type = = SP | | slice_type = = B ) {          
        // num_ref_idx_active_override_flag    在图像参数集中我们看到已经出现句法元素num_ref_idx_l0_active_minus1 和num_ref_idx_l1_active_minus1 指定当前参考帧队列中实际可用的参考帧的数目。在片头可以重载这对句法元素,以给某特定图像更大的灵活度。这个句法元素就是指明片头是否会重载,如果该句法元素等于 1,下面会出现新的 num_ref_idx_l0_active_minus1  和num_ref_idx_l1_active_minus1 值。  
        num_ref_idx_active_override_flag  
        if( num_ref_idx_active_override_flag ) {          
            num_ref_idx_l0_active_minus1  
            if( slice_type    ==    B )          
                num_ref_idx_l1_active_minus1   
        }          
    }      
    // 参考帧队列重排序(reordering)句法 
    ref_pic_list_reordering( )           
    if( ( weighted_pred_flag    &&    ( slice_type == P    | |    slice_type == SP ) )   | | 
        ( weighted_bipred_idc    ==    1    &&    slice_type    ==    B ) ) 
        // 加权预测句法  
        pred_weight_table( )       
    if( nal_ref_idc != 0 )          
        // 参考帧队列标记(marking)句法  
       dec_ref_pic_marking( )         
    if( entropy_coding_mode_flag    &&    slice_type    !=    I    &&   slice_type    !=    SI ) 
        // cabac_init_idc  给出 cabac 初始化时表格的选择,范围 0 到 2。 
        cabac_init_idc   
    // slice_qp_delta  指出在用于当前片的所有宏块的量化参数的初始值。SliceQPY = 26+ pic_init_qp_minus26 + slice_qp_delta   范围是  0 to 51。 H.264  中量化参数是分图像参数集、片头、宏块头三层给出的,前两层各自给出一个偏移值,这个句法元素就是片层的偏移。 
    slice_qp_delta    
    if( slice_type    = =    SP    | |    slice_type    = =    SI ) {          
        if( slice_type    = =    SP )          
            // sp_for_switch_flag  指出SP 帧中的p 宏块的解码方式是否是switching 模式  
            sp_for_switch_flag  
            // slice_qs_delta  与 slice_qp_delta 的与语义相似,用在 SI 和 SP 中的  
            slice_qs_delta   
    }          
    if( deblocking_filter_control_present_flag ) {      
        // disable_deblocking_filter_idc  H.264 指定了一套算法可以在解码器端独立地计算图像中各边界的滤波强度进行滤波。除了解码器独立计算之外,编码器也可以传递句法元素来干涉滤波强度,当这个句法元素指定了在块的边界是否要用滤波,同时指明那个块的边界不用块滤波      
        disable_deblocking_filter_idc   
        if( disable_deblocking_filter_idc    !=    1 ) {    
            // slice_alpha/beta_c0_offset_div2  给出用于增强  α/beta 和  t C0 的偏移值         
            slice_alpha_c0_offset_div2   
            slice_beta_offset_div2
    
        }          
    }          
    if( num_slice_groups_minus1 > 0    && 
        slice_group_map_type >= 3    &&    slice_group_map_type <= 5) 
        // slice_group_change_cycle  当片组的类型是 3, 4,    5,由句法元素可获得片组中  映射单元的数目: 
        slice_group_change_cycle  
}

(六)参考帧队列重排序(reordering)句法

ref_pic_list_reordering( ) {   
    if( slice_type    !=    I    &&    slice_type    !=    SI ) {              
        // ref_pic_list_reordering_flag_l0   指明是否进行重排序操作,这个句法元素等于1 时表明紧跟着会有一系列句法元素用于参考帧队列的重排序。 
       ref_pic_list_reordering_flag_l0   
        if( ref_pic_list_reordering_flag_l0 )           
            do {           
                // reordering_of_pic_nums_idc      指明执行哪种重排序操作 
                   reordering_of_pic_nums_idc       操作 
                   0                                                  短期参考帧重排序,abs_diff_pic_num_minus1会出现在码流中,从当 
                                                                       前图像的PicNum减去  (abs_diff_pic_num_minus1  +  1)  后指明需要重 
                                                                       排序的图像。 
                   1                                                  短期参考帧重排序,abs_diff_pic_num_minus1会出现在码流中,从当 
                                                                       前图像的PicNum加上  (abs_diff_pic_num_minus1  +  1)  后指明需要重 
                                                                       排序的图像。 
                   2                                                  长期参考帧重排序,long_term_pic_num会出现在码流中,指明需要重 
                                                                       排序的图像。 
                   3                                                  结束循环,退出重排序操作。  
                reordering_of_pic_nums_idc  
                if( reordering_of_pic_nums_idc    ==    0    | | 
                    reordering_of_pic_nums_idc    ==    1 )  
                    // abs_diff_pic_num_minus1   在对短期参考帧重排序时指明重排序图像与当前的差 
                    abs_diff_pic_num_minus1   
                else if( reordering_of_pic_nums_idc    = =    2 )         
                    // long_term_pic_num     在对长期参考帧重排序时指明重排序图像   
                   long_term_pic_num  
            } while( reordering_of_pic_nums_idc    !=    3 )           
    }           
    if( slice_type    ==    B ) {           
       ref_pic_list_reordering_flag_l1   
        if( ref_pic_list_reordering_flag_l1 )           
            do {           
                reordering_of_pic_nums_idc   
                if( reordering_of_pic_nums_idc    = =    0    | | 
                    reordering_of_pic_nums_idc    = =    1 ) 
                   abs_diff_pic_num_minus1   
                else if( reordering_of_pic_nums_idc    = =    2 )           
                    long_term_pic_num    
            } while( reordering_of_pic_nums_idc    !=    3 )           
    }           
}

http://www.cnblogs.com/javawebsoa/p/3214959.html

多媒体开发之---h264 图像参数级语义的更多相关文章

  1. 多媒体开发之--- h264 图像、帧、片、NALU

    图像.帧.片.NALU 是学习 H.264的人常常感到困惑的一些概念,我在这里对自己的理解做一些阐述,欢迎大家讨论: H.264 是一次概念的革新,它打破常规,完全没有 I 帧.P帧.B 帧的概念,也 ...

  2. 多媒体开发之---h264格式slice_header

    从Slice_Header学习H.264 写在前面: $     H.264我是结合标准和毕厚杰的书一块学的.看句法语义时最是头疼,一大堆的元素,很需要耐心.标准中在介绍某个元素的语义时,经常会突然冒 ...

  3. 多媒体开发之---h264 NALU 语法结构

    补充笔记: 关于VCL:VCL层是指视频编码层,VCL NAL 单元是指那些nal_unit_type 值等于 1 到 5(包括 1 和 5)的 NAL 单元,这些单元都包含了视频数据.所有其他的 N ...

  4. 多媒体开发之---h264 取流解码分析

    1. nalu_unit_type = *((unsigned char *)pEmptyBuf->bufVirtAddr+4); nalu_unit_type = nalu_unit_type ...

  5. 多媒体开发之---h264中 的RTP PAYLOAD 格式

    H.264 视频 RTP 负载格式 1. 网络抽象层单元类型 (NALU) NALU 头由一个字节组成, 它的语法如下: +---------------+      |0|1|2|3|4|5|6|7 ...

  6. 多媒体开发之---h264 取流解码实现

    解码器在解码时,首先逐个字节读取NAL的数据,统计NAL的长度,然后再开始解码. nal_unit( NumBytesInNALunit ) {  /* NumBytesInNALunit为统计出来的 ...

  7. 多媒体开发之---h264 高度和宽度获取

    ( School of Computer Science & Technology, Soochow University,SuZhou 215006:) Abstract: H.264 is ...

  8. 多媒体开发之---H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流

    一.MP4格式基本概念 MP4格式对应标准MPEG-4标准(ISO/IEC14496) 二.MP4封装格式核心概念 1  MP4封装格式对应标准为 ISO/IEC 14496-12(信息技术 视听对象 ...

  9. 多媒体开发之分场图像和交错图像interlacing---一个破解版的迅雷云点播网站

    [-] 目录 编辑描述 编辑去交错方法 编辑去交错源自电影的影像 编辑去交错交错式影像 编辑单一场去交错intra-field deinterlacing 编辑场间去交错inter-field dei ...

随机推荐

  1. VIM使用技巧2

    假如有以下程序片段: var foo = 1 var bar = 'a' var foobar = foo + bar 如果我们想在每行行尾加上分号, (1)使用$移动光标到行尾, (2)执行a;&l ...

  2. Scrapy学习-21-信号量

    scrapy信号量 定义 Scrapy使用信号来通知事情发生.您可以在您的Scrapy项目中捕捉一些信号(使用 extension)来完成额外的工作或添加额外的功能,扩展Scrapy. 虽然信号提供了 ...

  3. sublime 中设置pylint

    http://www.360doc.com/content/14/1110/11/15077656_424004081.shtml 安装 pylinter 插件   详见 sublime 插件安装 配 ...

  4. hdu 4497(排列组合+LCM和GCD)

    GCD and LCM Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total ...

  5. 提升开发效率的一款mybatis开发神器

    文末附有完整案例的代码内容!! 以前在开发的时候,使用mybatis的时候,经常都需要先配置xml映射文件,然后每条sql操作都需要自己进行手动编写,对于一些复杂的sql这么来操作确实有必要,但是如果 ...

  6. 关于bug的沟通

    关于BUG的沟通 一个人要去做一件事情,一般来说是按照自己的意愿去做的,如果不是自己想做而是被要求这么做的话,心里一定会留下点不愉快,特别是那种有自信有自己主见的人,比如说开发人员,当测试人员发现一个 ...

  7. 某考试 T2 Tree

    2 树 2.1 题目描述 给一棵n 个节点的树,节点分别编号为0 到n - 1.你可以通过如下的操作来修改这棵树:首先先删去树上的一条边,此时树会分裂为两个连通块,然后在两个连通块之间加上一条新的边使 ...

  8. (入门SpringBoot)SpringBoot发送邮件(十一)

    SpringBoot配置邮件服务: 1.引入jar <!-- 邮件 --> <dependency>    <groupId>org.springframework ...

  9. 基于WPF系统框架设计(10)-分页控件设计

    背景 最近要求项目组成员开发一个通用的分页组件,要求是这个组件简单易用,通用性,兼容现有框架MVVM模式,可是最后给我提交的成果勉强能够用,却欠少灵活性和框架兼容性. 设计的基本思想 传入数据源,总页 ...

  10. 在dedecms后台发表文章显示外部连接栏目

    问题描述:客户的网站,有个顶级栏目,下面包含了几个子栏目,这个顶级栏目不想发布什么内容,点击后进入他的某个子栏目就可以了,这时候把这个顶级栏目设置为“外部连接”就可以了 但是设置顶级栏目为外部连接后, ...