/* packet-h264.c
 * Routines for H.264 dissection
 * Copyright 2007 - 2009, Anders Broman <anders.broman[at]ericsson.com>
 *
 * $Id$
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * References:
 * http://www.ietf.org/rfc/rfc3984.txt?number=3984
 * http://www.itu.int/rec/T-REC-H.264/en
 */

#include "config.h"

#include <string.h>

#include <glib.h>

#include <epan/packet.h>
#include <epan/asn1.h>
#include <epan/strutil.h>
#include <epan/expert.h>
#include <epan/prefs.h>
#include <epan/wmem/wmem.h>

/* Initialize the protocol and registered fields */
static int proto_h264                                      = -1;
static int hf_h264_type                                    = -1;
static int hf_h264_nal_f_bit                               = -1;
static int hf_h264_nal_nri                                 = -1;
static int hf_h264_start_bit                               = -1;
static int hf_h264_forbidden_bit                           = -1;
static int hf_h264_end_bit                                 = -1;
static int hf_h264_profile                                 = -1;
static int hf_h264_profile_idc                             = -1;
static int hf_h264_rbsp_stop_bit                           = -1;
static int hf_h264_rbsp_trailing_bits                      = -1;
static int hf_h264_constraint_set0_flag                    = -1;
static int hf_h264_constraint_set1_flag                    = -1;
static int hf_h264_constraint_set2_flag                    = -1;
static int hf_h264_constraint_set3_flag                    = -1;
static int hf_h264_reserved_zero_4bits                     = -1;
static int hf_h264_level_idc                               = -1;
static int hf_h264_nal_unit                                = -1;
static int hf_h264_forbidden_zero_bit                      = -1;
static int hf_h264_nal_ref_idc                             = -1;
static int hf_h264_nal_unit_type                           = -1;
static int hf_h264_seq_parameter_set_id                    = -1;
static int hf_h264_chroma_format_idc                       = -1;
static int hf_h264_residual_colour_transform_flag          = -1;
static int hf_h264_bit_depth_luma_minus8                   = -1;
static int hf_h264_bit_depth_chroma_minus8                 = -1;
static int hf_h264_qpprime_y_zero_transform_bypass_flag    = -1;
static int hf_h264_seq_scaling_matrix_present_flag         = -1;
static int hf_h264_log2_max_frame_num_minus4               = -1;
static int hf_h264_pic_order_cnt_type                      = -1;
static int hf_h264_log2_max_pic_order_cnt_lsb_minus4       = -1;
static int hf_h264_delta_pic_order_always_zero_flag        = -1;
static int hf_h264_offset_for_non_ref_pic                  = -1;
static int hf_h264_offset_for_top_to_bottom_field          = -1;
static int hf_h264_num_ref_frames_in_pic_order_cnt_cycle   = -1;
static int hf_h264_offset_for_ref_frame                    = -1;
static int hf_h264_num_ref_frames                          = -1;
static int hf_h264_gaps_in_frame_num_value_allowed_flag    = -1;
static int hf_h264_pic_width_in_mbs_minus1                 = -1;
static int hf_h264_pic_height_in_map_units_minus1          = -1;
static int hf_h264_frame_mbs_only_flag                     = -1;
static int hf_h264_mb_adaptive_frame_field_flag            = -1;
static int hf_h264_direct_8x8_inference_flag               = -1;
static int hf_h264_frame_cropping_flag                     = -1;
static int hf_h264_frame_crop_left_offset                  = -1;
static int hf_h264_frame_crop_right_offset                 = -1;
static int hf_h264_frame_crop_top_offset                   = -1;
static int hf_h264_frame_crop_bottom_offset                = -1;
static int hf_h264_vui_parameters_present_flag             = -1;
static int hf_h264_pic_parameter_set_id                    = -1;
static int hf_h264_entropy_coding_mode_flag                = -1;
static int hf_h264_pic_order_present_flag                  = -1;
static int hf_h264_num_slice_groups_minus1                 = -1;
static int hf_h264_slice_group_map_type                    = -1;
static int hf_h264_num_ref_idx_l0_active_minus1            = -1;
static int hf_h264_num_ref_idx_l1_active_minus1            = -1;
static int hf_h264_weighted_pred_flag                      = -1;
static int hf_h264_weighted_bipred_idc                     = -1;
static int hf_h264_pic_init_qp_minus26                     = -1;
static int hf_h264_pic_init_qs_minus26                     = -1;
static int hf_h264_chroma_qp_index_offset                  = -1;
static int hf_h264_deblocking_filter_control_present_flag  = -1;
static int hf_h264_constrained_intra_pred_flag             = -1;
static int hf_h264_redundant_pic_cnt_present_flag          = -1;
static int hf_h264_transform_8x8_mode_flag                 = -1;
static int hf_h264_pic_scaling_matrix_present_flag         = -1;
static int hf_h264_second_chroma_qp_index_offset           = -1;
static int hf_h264_par_profile                             = -1;
static int hf_h264_par_profile_b                           = -1;
static int hf_h264_par_profile_m                           = -1;
static int hf_h264_par_profile_e                           = -1;
static int hf_h264_par_profile_h                           = -1;
static int hf_h264_par_profile_h10                         = -1;
static int hf_h264_par_profile_h4_2_2                      = -1;
static int hf_h264_par_profile_h4_4_4                      = -1;
/* static int hf_h264_par_add_mode_sup                        = -1; */
static int hf_h264_par_AdditionalModesSupported            = -1;
static int hf_h264_par_add_mode_sup_rcdo                   = -1;
static int hf_h264_par_ProfileIOP                          = -1;
static int hf_h264_par_constraint_set0_flag                = -1;
static int hf_h264_par_constraint_set1_flag                = -1;
static int hf_h264_par_constraint_set2_flag                = -1;

/* VUI parameters */
static int hf_h264_aspect_ratio_info_present_flag          = -1;
static int hf_h264_aspect_ratio_idc                        = -1;
static int hf_h264_sar_width                               = -1;
static int hf_h264_sar_height                              = -1;
static int hf_h264_overscan_info_present_flag              = -1;
static int hf_h264_overscan_appropriate_flag               = -1;
static int hf_h264_video_signal_type_present_flag          = -1;
static int hf_h264_video_format                            = -1;
static int hf_h264_video_full_range_flag                   = -1;
static int hf_h264_colour_description_present_flag         = -1;
static int hf_h264_colour_primaries                        = -1;
static int hf_h264_transfer_characteristics                = -1;
static int hf_h264_matrix_coefficients                     = -1;
static int hf_h264_chroma_loc_info_present_flag            = -1;
static int hf_h264_chroma_sample_loc_type_top_field        = -1;
static int hf_h264_chroma_sample_loc_type_bottom_field     = -1;
static int hf_h264_timing_info_present_flag                = -1;
static int hf_h264_num_units_in_tick                       = -1;
static int hf_h264_time_scale                              = -1;
static int hf_h264_fixed_frame_rate_flag                   = -1;
static int hf_h264_nal_hrd_parameters_present_flag         = -1;
static int hf_h264_vcl_hrd_parameters_present_flag         = -1;
static int hf_h264_low_delay_hrd_flag                      = -1;
static int hf_h264_pic_struct_present_flag                 = -1;
static int hf_h264_bitstream_restriction_flag              = -1;
static int hf_h264_motion_vectors_over_pic_boundaries_flag = -1;
static int hf_h264_max_bytes_per_pic_denom                 = -1;
static int hf_h264_max_bits_per_mb_denom                   = -1;
static int hf_h264_log2_max_mv_length_horizontal           = -1;
static int hf_h264_log2_max_mv_length_vertical             = -1;
static int hf_h264_num_reorder_frames                      = -1;
static int hf_h264_max_dec_frame_buffering                 = -1;
static int hf_h264_cpb_cnt_minus1                          = -1;
static int hf_h264_bit_rate_scale                          = -1;
static int hf_h264_cpb_size_scale                          = -1;
static int hf_h264_bit_rate_value_minus1                   = -1;
static int hf_h264_cpb_size_value_minus1                   = -1;
static int hf_h264_cbr_flag                                = -1;
static int hf_h264_initial_cpb_removal_delay_length_minus1 = -1;
static int hf_h264_cpb_removal_delay_length_minus1         = -1;
static int hf_h264_dpb_output_delay_length_minus11         = -1;
static int hf_h264_time_offset_length                      = -1;

static int hf_h264_first_mb_in_slice                       = -1;
static int hf_h264_slice_type                              = -1;
static int hf_h264_slice_id                                = -1;
static int hf_h264_payloadsize                             = -1;
static int hf_h264_payloadtype                             = -1;
/* static int hf_h264_frame_num                               = -1; */

/* Initialize the subtree pointers */
static int ett_h264                                        = -1;
static int ett_h264_profile                                = -1;
static int ett_h264_nal                                    = -1;
static int ett_h264_fua                                    = -1;
static int ett_h264_stream                                 = -1;
static int ett_h264_nal_unit                               = -1;
static int ett_h264_par_profile                            = -1;
static int ett_h264_par_AdditionalModesSupported           = -1;
static int ett_h264_par_ProfileIOP                         = -1;

static expert_field ei_h264_undecoded = EI_INIT;

/* The dynamic payload type range which will be dissected as H.264 */

#define RTP_PT_DEFAULT_RANGE "0"
static range_t *temp_dynamic_payload_type_range = NULL;

static dissector_handle_t h264_handle;

/* syntax tables in subclause 7.3 is equal to
 * ue(v), me(v), se(v), or te(v).
 */
typedef enum {
    H264_UE_V = 0,
    H264_ME_V = 1,
    H264_SE_V = 2,
    H264_TE_V = 3
} h264_golomb_descriptors;


static const true_false_string h264_f_bit_vals = {
  "Bit errors or other syntax violations",
  "No bit errors or other syntax violations"
};

static const true_false_string h264_start_bit_vals = {
  "the first packet of FU-A picture",
  "Not the first packet of FU-A picture"
};

static const true_false_string h264_end_bit_vals = {
  "the last packet of FU-A picture",
  "Not the last packet of FU-A picture"
};

#if 0
static const true_false_string h264_forbidden_bit_vals = {
  "Forbidden Bit of FU-A",
  "Not Forbidden Bit of FU-A"
};
#endif

#define H264_SEQ_PAR_SET        7
#define H264_PIC_PAR_SET        8

static const value_string h264_type_values[] = {
    {  0,   "Undefined" },
    {  1,   "NAL unit - Coded slice of a non-IDR picture" },    /* Single NAL unit packet per H.264 */
    {  2,   "NAL unit - Coded slice data partition A" },
    {  3,   "NAL unit - Coded slice data partition B" },
    {  4,   "NAL unit - Coded slice data partition C" },
    {  5,   "NAL unit - Coded slice of an IDR picture" },
    {  6,   "NAL unit - Supplemental enhancement information (SEI)" },
    { H264_SEQ_PAR_SET, "NAL unit - Sequence parameter set" },              /* 7 */
    { H264_PIC_PAR_SET, "NAL unit - Picture parameter set" },               /* 8 */
    {  9,   "NAL unit - Access unit delimiter" },
    { 10,   "NAL unit - End of sequence" },
    { 11,   "NAL unit - End of stream" },
    { 12,   "NAL unit - Filler data" },
    { 13,   "NAL unit - Sequence parameter set extension" },
    { 14,   "NAL unit - Reserved" },
    { 15,   "NAL unit - Reserved" },
    { 16,   "NAL unit - Reserved" },
    { 17,   "NAL unit - Reserved" },
    { 18,   "NAL unit - Reserved" },
    { 19,   "NAL unit - Coded slice of an auxiliary coded picture without partitioning" },
    { 20,   "NAL unit - Reserved" },
    { 21,   "NAL unit - Reserved" },
    { 22,   "NAL unit - Reserved" },
    { 23,   "NAL unit - Reserved" },
    { 24,   "STAP-A" },     /* Single-time aggregation packet */
    { 25,   "STAP-B" },     /* Single-time aggregation packet */
    { 26,   "MTAP16" },     /* Multi-time aggregation packet */
    { 27,   "MTAP24" },     /* Multi-time aggregation packet */
    { 28,   "FU-A" },       /* Fragmentation unit */
    { 29,   "FU-B" },       /* Fragmentation unit */
    { 30,   "undefined" },
    { 31,   "undefined" },
    { 0,    NULL }
};

/* A.2 Profiles */
static const value_string h264_profile_idc_values[] = {
    {  66,  "Baseline profile" },
    {  77,  "Main profile" },
    {  88,  "Extended profile" },
    { 100,  "High profile" },
    { 110,  "High 10 profile" },
    { 122,  "High 4:2:2 profile" },
    { 144,  "High 4:4:4 profile" },
    { 0,    NULL }
};

/* Table A-1 - Level limits */
static const value_string h264_level_bitrate_values[] = {
    { 10,   "64 kb/s" },
    { 11,   "192 kb/s" },
    { 12,   "384 kb/s" },
    { 13,   "768 kb/s" },
    { 20,   "2 Mb/s" },
    { 21,   "4 Mb/s" },
    { 22,   "4 Mb/s" },
    { 30,   "10 Mb/s" },
    { 31,   "14 Mb/s" },
    { 32,   "20 Mb/s" },
    { 40,   "20 Mb/s" },
    { 41,   "50 Mb/s" },
    { 42,   "50 Mb/s" },
    { 50,   "135 Mb/s" },
    { 51,   "240 Mb/s" },
    { 0,    NULL }
};

static const value_string h264_nal_unit_type_vals[] = {
    {  0,   "Unspecified" },
    {  1,   "Coded slice of a non-IDR picture" },
    {  2,   "Coded slice data partition A" },
    {  3,   "Coded slice data partition B" },
    {  4,   "Coded slice data partition C" },
    {  5,   "Coded slice of an IDR picture" },
    {  6,   "Supplemental enhancement information (SEI)" },
    {  7,   "Sequence parameter set" },
    {  8,   "Picture parameter set" },
    {  9,   "Access unit delimiter" },
    { 10,   "End of sequence" },
    { 11,   "End of stream" },
    { 12,   "Filler data" },
    { 13,   "Sequence parameter set extension" },
    { 14,   "Reserved" },
    { 15,   "Reserved" },
    { 16,   "Reserved" },
    { 17,   "Reserved" },
    { 18,   "Reserved" },
    { 19,   "Coded slice of an auxiliary coded picture without partitioning" },
    { 20,   "Reserved" },
    { 21,   "Reserved" },
    { 22,   "Reserved" },
    { 23,   "Reserved" },
    { 24,   "Unspecified" },
    { 25,   "Unspecified" },
    { 26,   "Unspecified" },
    { 27,   "Unspecified" },
    { 28,   "FU-A" },
    { 29,   "Unspecified" },
    { 30,   "Unspecified" },
    { 31,   "Unspecified" },
    { 0,    NULL }
};

static const value_string h264_slice_group_map_type_vals[] = {
    { 0,    "Interleaved slice groups" },
    { 1,    "Dispersed slice group mapping" },
    { 2,    "One or more foreground slice groups and a leftover slice group" },
    { 3,    "Changing slice groups" },
    { 4,    "Changing slice groups" },
    { 5,    "Changing slice groups" },
    { 6,    "Explicit assignment of a slice group to each slice group map unit" },
    { 0,    NULL }
};

/* Table 7-6 Name association to slice_type */
static const value_string h264_slice_type_vals[] = {
    { 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)" },
    { 0,    NULL }
};

/* byte_aligned( ) is specified as follows.
 * - If the current position in the bitstream is on a byte boundary, i.e.,
 *   the next bit in the bitstream is the first bit in a byte,
 *   the return value of byte_aligned( ) is equal to TRUE.
 * - Otherwise, the return value of byte_aligned( ) is equal to FALSE.
 */
static gboolean
h264_byte_aligned(int bit_offset)
{
    if (bit_offset&0x3)
        return FALSE;

    return TRUE;
}

/* Expect a tvb and a bit offset into the tvb
 * returns the value and bit_offset
 */
#define cVALS(x) (const value_string*)(x)

guint32
dissect_h264_exp_golomb_code(proto_tree *tree, int hf_index, tvbuff_t *tvb, gint *start_bit_offset, h264_golomb_descriptors descriptor)
/*(tvbuff_t *tvb, gint *start_bit_offset) */
{
    gint     leading_zero_bits, bit_offset, start_offset;
    guint32  codenum, mask, value, tmp;
    gint32   se_value = 0;
    gint     b;
    char    *str;
    int      bit;
    int      i;
    header_field_info *hf_field = NULL;

    start_offset = *start_bit_offset>>3;

    if (hf_index > -1)
        hf_field = proto_registrar_get_nth(hf_index);

    bit_offset = *start_bit_offset;

    /* prepare the string */
    str = (char *)wmem_alloc(wmem_packet_scope(), 256);
    str[0] = '\0';
    for (bit=0; bit<((int)(bit_offset&0x07)); bit++) {
        if (bit && (!(bit%4))) {
            g_strlcat(str, " ", 256);
        }
        g_strlcat(str,".", 256);
    }


    leading_zero_bits = -1;
    for (b = 0; !b; leading_zero_bits++) {
        if (bit && (!(bit%4))) {
            g_strlcat(str, " ", 256);
        }
        if (bit && (!(bit%8))) {
            g_strlcat(str, " ", 256);
        }
        b = tvb_get_bits8(tvb, bit_offset, 1);
        if (b != 0) {
            g_strlcat(str, "1", 256);
        } else {
            g_strlcat(str, "0", 256);
        }
        bit++;
        bit_offset++;
    }

    if (leading_zero_bits == 0) {
        codenum = 0;
        *start_bit_offset = bit_offset;
        for (; bit%8; bit++) {
            if (bit && (!(bit%4))) {
                g_strlcat(str, " ", 256);
            }
        g_strlcat(str,".", 256);
        }
        if (hf_field) {
            g_strlcat(str," = ", 256);
            g_strlcat(str, hf_field->name, 256);
            switch (descriptor) {
            case H264_SE_V:
                /* if the syntax element is coded as se(v),
                 * the value of the syntax element is derived by invoking the
                 * mapping process for signed Exp-Golomb codes as specified in
                 * subclause 9.1.1 with codeNum as the input.
                 */
                if (hf_field->type == FT_INT32) {
                    if (hf_field->strings) {
                        proto_tree_add_int_format(tree, hf_index, tvb, start_offset, 1, codenum,
                              "%s: %s (%d)",
                              str,
                              val_to_str_const(codenum, cVALS(hf_field->strings), "Unknown "),
                              codenum);
                    } else {
                        switch (hf_field->display) {
                            case BASE_DEC:
                                proto_tree_add_int_format(tree, hf_index, tvb, start_offset, 1, codenum,
                                     "%s: %d",
                                      str,
                                      codenum);
                                break;
                            default:
                                DISSECTOR_ASSERT_NOT_REACHED();
                                break;
                        }
                    }
                }
                return codenum;
            default:
                break;
            }
            if (hf_field->type == FT_UINT32) {
                if (hf_field->strings) {
                    proto_tree_add_uint_format(tree, hf_index, tvb, start_offset, 1, codenum,
                          "%s: %s (%u)",
                          str,
                          val_to_str_const(codenum, cVALS(hf_field->strings), "Unknown "),
                          codenum);
                } else {
                    switch (hf_field->display) {
                        case BASE_DEC:
                            proto_tree_add_uint_format(tree, hf_index, tvb, start_offset, 1, codenum,
                                 "%s: %u",
                                  str,
                                  codenum);
                            break;
                        case BASE_HEX:
                            proto_tree_add_uint_format(tree, hf_index, tvb, start_offset, 1, codenum,
                                 "%s: 0x%x",
                                  str,
                                  codenum);
                            break;
                        default:
                            DISSECTOR_ASSERT_NOT_REACHED();
                            break;
                    }
                }
            } else {
                /* Only allow guint32 */
                DISSECTOR_ASSERT_NOT_REACHED();
            }
        }
        return codenum;
    }

    /*
    Syntax elements coded as ue(v), me(v), or se(v) are Exp-Golomb-coded. Syntax elements coded as te(v) are truncated
    Exp-Golomb-coded. The parsing process for these syntax elements begins with reading the bits starting at the current
    location in the bitstream up to and including the first non-zero bit, and counting the number of leading bits that are
    equal to 0. This process is specified as follows:
    leadingZeroBits = -1;
    for (b = 0; !b; leadingZeroBits++)
    b = read_bits( 1 )
    The variable codeNum is then assigned as follows:
    codeNum = 2leadingZeroBits - 1 + read_bits( leadingZeroBits )
    where the value returned from read_bits( leadingZeroBits ) is interpreted as a binary representation of an unsigned
    integer with most significant bit written first.
    */
    codenum = 1;
    codenum = codenum << leading_zero_bits;
    mask = codenum>>1;
    if (leading_zero_bits > 32)
        DISSECTOR_ASSERT_NOT_REACHED();
    else if (leading_zero_bits > 16)
        value = tvb_get_bits32(tvb, bit_offset, leading_zero_bits, ENC_BIG_ENDIAN);
    else if (leading_zero_bits > 8)
        value = tvb_get_bits16(tvb, bit_offset, leading_zero_bits, ENC_BIG_ENDIAN);
    else
        value = tvb_get_bits8(tvb, bit_offset, leading_zero_bits);
    codenum = (codenum-1) + value;
    bit_offset = bit_offset + leading_zero_bits;

    /* read the bits for the int */
    for (i=0; i<leading_zero_bits; i++) {
        if (bit && (!(bit%4))) {
            g_strlcat(str, " ", 256);
        }
        if (bit && (!(bit%8))) {
            g_strlcat(str, " ", 256);
        }
        bit++;
        tmp = value & mask;
        if (tmp != 0) {
            g_strlcat(str, "1", 256);
        } else {
            g_strlcat(str, "0", 256);
        }
        mask = mask>>1;
    }
    for ( ; bit%8; bit++) {
        if (bit && (!(bit%4))) {
            g_strlcat(str, " ", 256);
        }
        g_strlcat(str,".", 256);
    }

    switch (descriptor) {
    case H264_SE_V:
        /* if the syntax element is coded as se(v),
         * the value of the syntax element is derived by invoking the
         * mapping process for signed Exp-Golomb codes as specified in
         * subclause 9.1.1 with codeNum as the input.
         *      k+1
         * (-1)    Ceil( k/2 )
         */
        se_value = (codenum + 1) >> 1;
        if (!(se_value & 1)) {
            se_value =  - se_value;
        }
        break;
    default:
        break;
    }

    if (hf_field) {
        g_strlcat(str," = ", 256);
        g_strlcat(str, hf_field->name, 256);
        switch (descriptor) {
        case H264_SE_V:
            g_strlcat(str,"(se(v))", 256);
            /* if the syntax element is coded as se(v),
             * the value of the syntax element is derived by invoking the
             * mapping process for signed Exp-Golomb codes as specified in
             * subclause 9.1.1 with codeNum as the input.
             */
            break;
        default:
        break;
        }
        if ((hf_field->type == FT_UINT32) && (descriptor == H264_UE_V)) {
            if (hf_field->strings) {
                proto_tree_add_uint_format(tree, hf_index, tvb, start_offset, 1, codenum,
                          "%s: %s (%u)",
                          str,
                          val_to_str_const(codenum, cVALS(hf_field->strings), "Unknown "),
                          codenum);
            } else {
                switch (hf_field->display) {
                    case BASE_DEC:
                        proto_tree_add_uint_format(tree, hf_index, tvb, start_offset, 1, codenum,
                             "%s: %u",
                              str,
                              codenum);
                        break;
                    case BASE_HEX:
                        proto_tree_add_uint_format(tree, hf_index, tvb, start_offset, 1, codenum,
                             "%s: 0x%x",
                              str,
                              codenum);
                        break;
                    default:
                        DISSECTOR_ASSERT_NOT_REACHED();
                        break;
                }
            }
        } else if ((hf_field->type == FT_INT32) && (descriptor == H264_SE_V)) {
            if (hf_field->strings) {
                proto_tree_add_int_format(tree, hf_index, tvb, start_offset, 1, codenum,
                          "%s: %s (%d)",
                          str,
                          val_to_str_const(codenum, cVALS(hf_field->strings), "Unknown "),
                          se_value);
            } else {
                switch (hf_field->display) {
                    case BASE_DEC:
                        proto_tree_add_int_format(tree, hf_index, tvb, start_offset, 1, codenum,
                             "%s: %d",
                              str,
                              se_value);
                        break;
                    default:
                        DISSECTOR_ASSERT_NOT_REACHED();
                        break;
                }
            }
            *start_bit_offset = bit_offset;
            return se_value;

        } else {
            /* Only allow guint32 */
            DISSECTOR_ASSERT_NOT_REACHED();
        }
    }

    *start_bit_offset = bit_offset;
    return codenum;
}

/* This function is adapted to parsing NAL units from SDP data where the
 * base64 coding may add extra padding
 */

static gboolean
more_rbsp_data(proto_tree *tree _U_, tvbuff_t *tvb, packet_info *pinfo _U_, gint bit_offset)
{
    int    offset;
    int    remaining_length;
    int    last_one_bit;
    guint8 b = 0;

    /* XXX might not be the best way of doing things but:
     * Serch from the end of the tvb for the first '1' bit
     * assuming that it's the RTBSP stop bit
     */

    /* Set offset to the byte we are treating */
    offset = bit_offset>>3;
    remaining_length = tvb_length_remaining(tvb, offset);
    /* If there is more then 2 bytes left there *should* be more data */
    if (remaining_length>2) {
        return TRUE;
    }
    /* Start from last bit */
    last_one_bit = (tvb_length(tvb) << 3);

    for (b = 0; !b; ) {
        last_one_bit--;
        b = tvb_get_bits8(tvb, last_one_bit, 1);
    }

    if (last_one_bit == bit_offset) {
        return FALSE;
    }

    return TRUE;
}

static int
dissect_h264_rbsp_trailing_bits(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint bit_offset)
{
    gint remaining_bits=0;

    proto_tree_add_bits_item(tree, hf_h264_rbsp_stop_bit, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if ((bit_offset&0x7) != 0) {
        remaining_bits = 8 - (bit_offset&0x7);
        proto_tree_add_bits_item(tree, hf_h264_rbsp_trailing_bits, tvb, bit_offset, remaining_bits, ENC_BIG_ENDIAN);
    }

    return bit_offset+remaining_bits;
}

/*
 * 7.3.3 Slice header syntax
 * slice_header( )
 * XXX Just parse a few bytes
 */
static int
dissect_h264_slice_header(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint bit_offset)
{
    /* first_mb_in_slice 2 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_first_mb_in_slice, tvb, &bit_offset, H264_UE_V);

    /* slice_type 2 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_slice_type, tvb, &bit_offset, H264_UE_V);

    /* pic_parameter_set_id 2 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_pic_parameter_set_id, tvb, &bit_offset, H264_UE_V);

    /* frame_num 2 u(v) */
    /*
     * represented by log2_max_frame_num_minus4 + 4 bits in
     * the bitstream
     * proto_tree_add_bits_item(tree, hf_h264_frame_num, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
     */

    return bit_offset;
}

/* 7.3.2.1.1 Scaling list syntax
 *
 * scaling_list( scalingList, sizeOfScalingList, useDefaultScalingMatrixFlag )
 */
/*
static int
dissect_h264_scaling_list(proto_tree *tree, tvbuff_t *tvb, gint bit_offset, int hf_index_scalinglist,
                          guint8 sizeOfScalingList, int hf_index_usedefaultscalingmatrixflag)
{

    guint8 lastScale = 8;
    guint8 nextScale = 8:
    guint8 delta_scale;

    for (j = 0; j < sizeOfScalingList; j++) {
      if (nextScale != 0) {
          / delta_scale 0 | 1 se(v) /
          delta_scale = dissect_h264_exp_golomb_code(tree, hf_h264_delta_scale, tvb, &bit_offset);
          nextScale = ( lastScale + delta_scale + 256 ) % 256;
          useDefaultScalingMatrixFlag = ( j == 0 && nextScale == 0 );
    }
    scalingList[ j ] = ( nextScale == 0 ) ? lastScale : nextScale
    lastScale = scalingList[ j ]
    }
}
*/
/* E.1.2 HRD parameters syntax */
static int
dissect_h264_hrd_parameters(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint bit_offset)
{
    guint8 cpb_cnt_minus1;
    int    SchedSelIdx;


    /* cpb_cnt_minus1 0 ue(v) */
    cpb_cnt_minus1 = dissect_h264_exp_golomb_code(tree, hf_h264_cpb_cnt_minus1, tvb, &bit_offset, H264_UE_V);

    /* bit_rate_scale 0 u(4) */
    proto_tree_add_bits_item(tree, hf_h264_bit_rate_scale, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
    bit_offset = bit_offset + 4;

    /* cpb_size_scale 0 u(4) */
    proto_tree_add_bits_item(tree, hf_h264_cpb_size_scale, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
    bit_offset = bit_offset + 4;
    /* for (SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++) { */
    for (SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++) {

        /* bit_rate_value_minus1[ SchedSelIdx ] 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_bit_rate_value_minus1, tvb, &bit_offset, H264_UE_V);

        /* cpb_size_value_minus1[ SchedSelIdx ] 0 ue(v)*/
        dissect_h264_exp_golomb_code(tree, hf_h264_cpb_size_value_minus1, tvb, &bit_offset, H264_UE_V);

        /* cbr_flag[ SchedSelIdx ] 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_cbr_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;
    }
    /* initial_cpb_removal_delay_length_minus1 0 u(5) */
    proto_tree_add_bits_item(tree, hf_h264_initial_cpb_removal_delay_length_minus1, tvb, bit_offset, 5, ENC_BIG_ENDIAN);
    bit_offset = bit_offset + 5;

    /* cpb_removal_delay_length_minus1 0 u(5) */
    proto_tree_add_bits_item(tree, hf_h264_cpb_removal_delay_length_minus1, tvb, bit_offset, 5, ENC_BIG_ENDIAN);
    bit_offset = bit_offset + 5;

    /* dpb_output_delay_length_minus1 0 u(5) */
    proto_tree_add_bits_item(tree, hf_h264_dpb_output_delay_length_minus11, tvb, bit_offset, 5, ENC_BIG_ENDIAN);
    bit_offset = bit_offset + 5;

    /* time_offset_length 0 u(5) */
    proto_tree_add_bits_item(tree, hf_h264_time_offset_length, tvb, bit_offset, 5, ENC_BIG_ENDIAN);
    bit_offset = bit_offset + 5;

    return bit_offset;
}

#define EXTENDED_SAR 255

/* E.1.1 VUI parameters syntax */

/* Table E-2 - Meaning of video_format */
static const value_string h264_video_format_vals[] = {
    { 22,   "reserved_sei_message)" },
    {  0,   "Component" },
    {  1,   "PAL" },
    {  2,   "NTSC" },
    {  3,   "SECAM" },
    {  4,   "MAC" },
    {  5,   "Unspecified video format" },
    {  6,   "Reserved" },
    {  7,   "Reserved" },
    { 0,    NULL }
};

static int
dissect_h264_vui_parameters(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint bit_offset)
{

    guint8 aspect_ratio_info_present_flag, aspect_ratio_idc, overscan_info_present_flag;
    guint8 video_signal_type_present_flag, colour_description_present_flag, chroma_loc_info_present_flag;
    guint8 timing_info_present_flag, nal_hrd_parameters_present_flag, vcl_hrd_parameters_present_flag;
    guint8 bitstream_restriction_flag;

    /* vui_parameters( ) {
     * aspect_ratio_info_present_flag 0 u(1)
     */
    aspect_ratio_info_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_aspect_ratio_info_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (aspect_ratio_info_present_flag) {
        /* aspect_ratio_idc 0 u(8) */
        aspect_ratio_idc = tvb_get_bits8(tvb, bit_offset, 8);
        proto_tree_add_bits_item(tree, hf_h264_aspect_ratio_idc, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
        bit_offset = bit_offset + 8;

        if (aspect_ratio_idc == EXTENDED_SAR) {
            /* sar_width 0 u(16) */
            proto_tree_add_bits_item(tree, hf_h264_sar_width, tvb, bit_offset, 16, ENC_BIG_ENDIAN);
            bit_offset = bit_offset + 16;

            /* sar_height 0 u(16) */
            proto_tree_add_bits_item(tree, hf_h264_sar_height, tvb, bit_offset, 16, ENC_BIG_ENDIAN);
            bit_offset = bit_offset + 16;
        }
    }
    /* overscan_info_present_flag 0 u(1) */
    overscan_info_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_overscan_info_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (overscan_info_present_flag) {
        /* overscan_appropriate_flag 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_overscan_appropriate_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;
    }

    /* video_signal_type_present_flag 0 u(1) */
    video_signal_type_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_video_signal_type_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (video_signal_type_present_flag) {
        /* video_format 0 u(3) > */
        proto_tree_add_bits_item(tree, hf_h264_video_format, tvb, bit_offset, 3, ENC_BIG_ENDIAN);
        bit_offset = bit_offset + 3;

        /* video_full_range_flag 0 u(1)*/
        proto_tree_add_bits_item(tree, hf_h264_video_full_range_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        /* colour_description_present_flag 0 u(1) */
        colour_description_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
        proto_tree_add_bits_item(tree, hf_h264_colour_description_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        if (colour_description_present_flag) {
            /* colour_primaries 0 u(8) */
            proto_tree_add_bits_item(tree, hf_h264_colour_primaries, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
            bit_offset = bit_offset + 8;

            /* transfer_characteristics 0 u(8) */
            proto_tree_add_bits_item(tree, hf_h264_transfer_characteristics, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
            bit_offset = bit_offset + 8;

            /* matrix_coefficients 0 u(8)*/
            proto_tree_add_bits_item(tree, hf_h264_matrix_coefficients, tvb, bit_offset, 8, ENC_BIG_ENDIAN);
            bit_offset = bit_offset + 8;
        }
    }

    /* chroma_loc_info_present_flag 0 u(1) */
    chroma_loc_info_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_chroma_loc_info_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (chroma_loc_info_present_flag) {
        /* chroma_sample_loc_type_top_field 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_chroma_sample_loc_type_top_field, tvb, &bit_offset, H264_UE_V);

        /* chroma_sample_loc_type_bottom_field 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_chroma_sample_loc_type_bottom_field, tvb, &bit_offset, H264_UE_V);
    }

    /* timing_info_present_flag 0 u(1) */
    timing_info_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_timing_info_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (timing_info_present_flag) {
        /* num_units_in_tick 0 u(32) */
        proto_tree_add_bits_item(tree, hf_h264_num_units_in_tick, tvb, bit_offset, 32, ENC_BIG_ENDIAN);
        bit_offset = bit_offset + 32;

        /* time_scale 0 u(32) */
        proto_tree_add_bits_item(tree, hf_h264_time_scale, tvb, bit_offset, 32, ENC_BIG_ENDIAN);
        bit_offset = bit_offset + 32;

        /* fixed_frame_rate_flag 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_fixed_frame_rate_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;
    }
    /* nal_hrd_parameters_present_flag 0 u(1) */
    nal_hrd_parameters_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_nal_hrd_parameters_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (nal_hrd_parameters_present_flag) {
        /* hrd_parameters( ) */
        bit_offset = dissect_h264_hrd_parameters(tree, tvb, pinfo, bit_offset);
    }

    /* vcl_hrd_parameters_present_flag 0 u(1) */
    vcl_hrd_parameters_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_vcl_hrd_parameters_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (vcl_hrd_parameters_present_flag) {
        /* hrd_parameters( ) */
        bit_offset = dissect_h264_hrd_parameters(tree, tvb, pinfo, bit_offset);
    }
    if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag) {
        /* low_delay_hrd_flag 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_low_delay_hrd_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;
    }
    /* pic_struct_present_flag 0 u(1) */
    proto_tree_add_bits_item(tree, hf_h264_pic_struct_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /* bitstream_restriction_flag 0 u(1) */
    bitstream_restriction_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_bitstream_restriction_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (bitstream_restriction_flag) {
        /* motion_vectors_over_pic_boundaries_flag 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_motion_vectors_over_pic_boundaries_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        /* max_bytes_per_pic_denom 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_max_bytes_per_pic_denom, tvb, &bit_offset, H264_UE_V);

        /* max_bits_per_mb_denom 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_max_bits_per_mb_denom, tvb, &bit_offset, H264_UE_V);

        /* log2_max_mv_length_horizontal 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_log2_max_mv_length_horizontal, tvb, &bit_offset, H264_UE_V);

        /* log2_max_mv_length_vertical 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_log2_max_mv_length_vertical, tvb, &bit_offset, H264_UE_V);

        /* num_reorder_frames 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_num_reorder_frames, tvb, &bit_offset, H264_UE_V);

        /* max_dec_frame_buffering 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_max_dec_frame_buffering, tvb, &bit_offset, H264_UE_V);
    }

    return bit_offset;
}

/* Used To dissect SDP parameter (H.264)profile */
void
dissect_h264_profile(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
{
    proto_item *item, *level_item;
    proto_tree *h264_profile_tree;
    gint        offset = 0;
    guint8      constraint_set3_flag;
    guint32     level_idc;

    item = proto_tree_add_item(tree, hf_h264_profile, tvb, offset, -1, ENC_NA);
    h264_profile_tree = proto_item_add_subtree(item, ett_h264_profile);

    proto_tree_add_item(h264_profile_tree, hf_h264_profile_idc, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    constraint_set3_flag = (tvb_get_guint8(tvb, offset)&0x10)>>4;
    proto_tree_add_item(h264_profile_tree, hf_h264_constraint_set0_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(h264_profile_tree, hf_h264_constraint_set1_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(h264_profile_tree, hf_h264_constraint_set2_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(h264_profile_tree, hf_h264_constraint_set3_flag, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(h264_profile_tree, hf_h264_reserved_zero_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    /* A level to which the bitstream conforms shall be indicated by the syntax element level_idc as follows.
     *  - If level_idc is equal to 11 and constraint_set3_flag is equal to 1, the indicated level is level 1b.
     *  - Otherwise (level_idc is not equal to 11 or constraint_set3_flag is not equal to 1), level_idc shall
     *    be set equal to a value of ten times the level number specified in Table A-1 and constraint_set3_flag
     *    shall be set equal to 0.
     */

    level_idc = tvb_get_guint8(tvb, offset);
    level_item = proto_tree_add_item(h264_profile_tree, hf_h264_level_idc, tvb, offset, 1, ENC_BIG_ENDIAN);
    if ((level_idc == 11) && (constraint_set3_flag == 1)) {
        proto_item_append_text(level_item," [Level 1b (128kb/s)]");
    } else {
        proto_item_append_text(level_item," [Level %.1f %s]", ((double)level_idc/10), val_to_str_const(level_idc, h264_level_bitrate_values, "Unknown "));
    }
}

/*
 * 7.3.1 NAL unit syntax
 * Un escape the NAL tvb
 *
 *
 * nal_unit( NumBytesInNALunit ) { C Descriptor
 *   forbidden_zero_bit All f(1)
 *   nal_ref_idc All u(2)
 *   nal_unit_type All u(5)
 *   NumBytesInRBSP = 0
 *   for (i = 1; i < NumBytesInNALunit; i++) {
 *     if (i + 2 < NumBytesInNALunit && next_bits( 24 ) = = 0x000003 ) {
 *       rbsp_byte[ NumBytesInRBSP++ ] All b(8)
 *       rbsp_byte[ NumBytesInRBSP++ ] All b(8)
 *       i += 2
 *       emulation_prevention_three_byte / * equal to 0x03 * / All f(8)
 *     } else
 *       rbsp_byte[ NumBytesInRBSP++ ] All b(8)
 *     }
 *   }
 */

static tvbuff_t *
dissect_h265_unescap_nal_unit(tvbuff_t *tvb, packet_info *pinfo, int offset)
{
    tvbuff_t *tvb_rbsp;
    int       length         = tvb_length_remaining(tvb, offset);
    int       NumBytesInRBSP = 0;
    int       i;
    gchar    *buff;

    buff = (gchar *)wmem_alloc(pinfo->pool, length);
    for (i = 0; i < length; i++) {
        if ((i + 2 < length) && (tvb_get_ntoh24(tvb, offset) == 0x000003)) {
            buff[NumBytesInRBSP++] = tvb_get_guint8(tvb, offset);
            buff[NumBytesInRBSP++] = tvb_get_guint8(tvb, offset+1);
            i += 2;
            offset+=3;
        } else {
            buff[ NumBytesInRBSP++] = tvb_get_guint8(tvb, offset);
            offset++;
        }
    }

    tvb_rbsp = tvb_new_child_real_data(tvb, buff, NumBytesInRBSP, NumBytesInRBSP);
    add_new_data_source(pinfo, tvb_rbsp, "Unescaped RSP Data");

    return tvb_rbsp;
}

/*
 * 7.3.2.8 Slice layer without partitioning RBSP syntax
 * slice_layer_without_partitioning_rbsp( )
 */

static void
dissect_h264_slice_layer_without_partitioning_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset)
{
    gint bit_offset;

    bit_offset = offset <<3;

    /* slice_header( ) 2 */
    bit_offset = dissect_h264_slice_header(tree, tvb, pinfo, bit_offset);
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, bit_offset>>3, -1);
    return;
    /* slice_data( ) * all categories of slice_data( ) syntax * 2 | 3 | 4 */
    /* rbsp_slice_trailing_bits( ) */
}

/*
 * 7.3.2.9.1 Slice data partition A RBSP syntax
 * slice_data_partition_a_layer_rbsp( )
 */
static void
dissect_h264_slice_data_partition_a_layer_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    gint bit_offset;

    bit_offset = offset <<3;

    /* slice_header( ) 2 */
    bit_offset = dissect_h264_slice_header(tree, tvb, pinfo, bit_offset);

    /* slice_id All ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_slice_id, tvb, &bit_offset, H264_UE_V);
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, bit_offset>>3, -1);
    return;
    /* slice_data( ) * only category 2 parts of slice_data( ) syntax * 2*/
    /* rbsp_slice_trailing_bits( )*/
}

/*
 * 7.3.2.9.2 Slice data partition B RBSP syntax
 * slice_data_partition_b_layer_rbsp(
 */
static void
dissect_h264_slice_data_partition_b_layer_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    gint bit_offset;

    bit_offset = offset <<3;

    /* slice_id All ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_slice_id, tvb, &bit_offset, H264_UE_V);
    /* if (redundant_pic_cnt_present_flag) */
    /* redundant_pic_cnt All ue(v) */
    /* slice_data( ) * only category 3 parts of slice_data( ) syntax * 3 */
    /* rbsp_slice_trailing_bits( ) 3 */
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, bit_offset>>3, -1);

}

/*
 * 7.3.2.9.3 Slice data partition C RBSP syntax
 * slice_data_partition_c_layer_rbsp( )
 */
static void
dissect_h264_slice_data_partition_c_layer_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    gint bit_offset;

    bit_offset = offset <<3;

    /* slice_id All ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_slice_id, tvb, &bit_offset, H264_UE_V);
    /* if (redundant_pic_cnt_present_flag) */
    /* redundant_pic_cnt All ue(v) */
    /* slice_data( ) * only category 4 parts of slice_data( ) syntax * 4 */
    /* rbsp_slice_trailing_bits( ) 4 */
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, bit_offset>>3, -1);
}

/* D.1.6 User data unregistered SEI message syntax */

static int
h264_user_data_unregistered(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint bit_offset, guint32 payloadSize)
{
    /* user_data_unregistered( payloadSize ) { C Descriptor */
    /* uuid_iso_iec_11578 5 u(128)
     * uuid_iso_iec_11578 shall have a value specified as a UUID
     * according to the procedures of ISO/IEC 11578:1996 Annex A.
     */
    proto_tree_add_text(tree, tvb, bit_offset>>3, 16, "uuid_iso_iec_1157");
    bit_offset+=128;
    /*  for (i = 16; i < payloadSize; i++)
     *  user_data_payload_byte 5 b(8)
     */
    proto_tree_add_text(tree, tvb, bit_offset>>3, payloadSize-16, "user_data_payload");
    bit_offset+=(payloadSize-16)<<3;

    return bit_offset;
}

/* D.1 SEI payload syntax */
static const value_string h264_sei_payload_vals[] = {
    {  0,   "buffering_period" },
    {  1,   "pic_timing" },
    {  2,   "pan_scan_rect" },
    {  3,   "filler_payload" },
    {  4,   "user_data_registered_itu_t_t35" },
    {  5,   "user_data_unregistered" },
    {  6,   "recovery_point" },
    {  7,   "dec_ref_pic_marking_repetition" },
    {  8,   "spare_pic" },
    {  9,   "scene_inf)" },
    { 10,   "sub_seq_info)" },
    { 11,   "sub_seq_layer_characteristics" },
    { 12,   "sub_seq_characteristics" },
    { 13,   "full_frame_freeze_release" },
    { 14,   "full_frame_freeze_release" },
    { 15,   "full_frame_snapshot" },
    { 16,   "progressive_refinement_segment_start" },
    { 17,   "progressive_refinement_segment_end" },
    { 18,   "motion_constrained_slice_group_set" },
    { 19,   "film_grain_characteristics)" },
    { 20,   "deblocking_filter_display_preference)" },
    { 21,   "stereo_video_info)" },
    { 22,   "reserved_sei_message)" },
    { 0,    NULL }
};

static int
h264_sei_payload(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint bit_offset, guint32 payloadType, guint32 payloadSize)
{
    /* sei_payload( payloadType, payloadSize ) { C Descriptor */
    if (payloadType == 0) {
        /* buffering_period( payloadSize ) 5 */
        bit_offset = bit_offset +(payloadSize<<3);
#if 0
    } else if (payloadType == 1) {
        /* pic_timing( payloadSize ) 5 */
    } else if (payloadType == 2) {
        /* pan_scan_rect( payloadSize ) 5 */
    } else if (payloadType == 3) {
        /* filler_payload( payloadSize ) 5 */
    } else if (payloadType == 4) {
        /* user_data_registered_itu_t_t35( payloadSize ) 5 */
#endif
    } else if (payloadType == 5) {
        /* user_data_unregistered( payloadSize ) 5 */
        bit_offset = h264_user_data_unregistered( tree, tvb, pinfo, bit_offset, payloadSize);
    } else if (payloadType == 6) {
        /* recovery_point( payloadSize ) 5 */
        bit_offset = bit_offset +(payloadSize<<3);
    } else if (payloadType == 7) {
        /* dec_ref_pic_marking_repetition( payloadSize ) 5 */
        bit_offset = bit_offset +(payloadSize<<3);
    }
#if 0
else if (payloadType == 8)
spare_pic( payloadSize ) 5
else if (payloadType == 9)
scene_info( payloadSize ) 5
else if (payloadType == 10)
sub_seq_info( payloadSize ) 5
else if (payloadType == 11)
sub_seq_layer_characteristics( payloadSize ) 5
else if (payloadType == 12)
sub_seq_characteristics( payloadSize ) 5
else if (payloadType == 13)
full_frame_freeze( payloadSize ) 5
else if (payloadType == 14)
full_frame_freeze_release( payloadSize ) 5
else if (payloadType == 15)
full_frame_snapshot( payloadSize ) 5
else if (payloadType == 16)
progressive_refinement_segment_start( payloadSize ) 5
else if (payloadType == 17)
progressive_refinement_segment_end( payloadSize ) 5
else if (payloadType == 18)
motion_constrained_slice_group_set( payloadSize ) 5
else if (payloadType == 19)
film_grain_characteristics( payloadSize ) 5
else if (payloadType == 20)
deblocking_filter_display_preference( payloadSize ) 5
else if (payloadType == 21)
stereo_video_info( payloadSize ) 5
else
reserved_sei_message( payloadSize ) 5
    return bit_offset;
#endif
    if (!h264_byte_aligned(bit_offset)) {
        /* bit_equal_to_one / * equal to 1 * / 5 f(1) */
        /* TODO:Display the filler and, error if not 1 ?? */
        bit_offset++;
        while (!h264_byte_aligned(bit_offset)) {
            /* bit_equal_to_zero / * equal to 0 * / 5 f(1) */
            /* TODO:Display the filler and, error if not 0 ?? */
            bit_offset++;
        }
    }
    return bit_offset;
}

/*
 * 7.3.2.3.1 Supplemental enhancement information message syntax
 */
static gint
dissect_h264_sei_message(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint bit_offset)
{
    /* sei_message( ) { C Descriptor */
    guint32 payloadType = 0, payloadSize;
    gint    start_bit_offset, length;

    start_bit_offset = bit_offset;

    /* while (next_bits( 8 ) == 0xFF) { */
    while (tvb_get_bits8(tvb, bit_offset, 8) == 0xFF) {
        /* ff_byte / * equal to 0xFF * / 5 f(8) */
        payloadType += 255;
        bit_offset+=8;
    }
    /* last_payload_type_byte 5 u(8) */
    payloadType += tvb_get_bits8(tvb, bit_offset, 8);
    bit_offset+=8;
    length = (bit_offset - start_bit_offset)>>3;

    proto_tree_add_uint(tree, hf_h264_payloadtype, tvb, start_bit_offset>>3, length, payloadType);

    payloadSize = 0;
    start_bit_offset = bit_offset;
    /* while (next_bits( 8 ) == 0xFF) { */
    while (tvb_get_bits8(tvb, bit_offset, 8) == 0xFF) {
        /* ff_byte / * equal to 0xFF * / 5 f(8) */
        payloadSize += 255;
        bit_offset+=8;
    }
    /* last_payload_size_byte 5 u(8) */
    /* payloadSize += last_payload_size_byte */
    payloadSize += tvb_get_bits8(tvb, bit_offset, 8);
    bit_offset+=8;
    length = (bit_offset - start_bit_offset)>>3;
    proto_tree_add_uint(tree, hf_h264_payloadsize, tvb, start_bit_offset>>3, length, payloadSize);

    /*sei_payload( payloadType, payloadSize ) 5 */
    bit_offset = h264_sei_payload( tree, tvb, pinfo, bit_offset, payloadType, payloadSize);
    return bit_offset;
}

/*
 * 7.3.2.3 Supplemental enhancement information RBSP syntax
 * sei_rbsp( )
 */
static int
dissect_h264_sei_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    gint bit_offset;

    bit_offset = offset <<3;
    /* do */
    /* sei_message( ) 5*/
    bit_offset = dissect_h264_sei_message( tree, tvb, pinfo, bit_offset);

    /* while (more_rbsp_data( ))
     * If there is more data in an RBSP before rbsp_trailing_bits( ),
     * the return value of more_rbsp_data( ) is equal to TRUE.
     */
    /* rbsp_trailing_bits( ) 5 */
    bit_offset = dissect_h264_rbsp_trailing_bits(tree, tvb, pinfo, bit_offset);

    return bit_offset;
}

/* Ref 7.3.2.1 Sequence parameter set RBSP syntax */
static int
dissect_h264_seq_parameter_set_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset)
{
    proto_item *level_item;
    gint        bit_offset;
    guint8      constraint_set3_flag;
    guint32     level_idc;

    gint        i;
    guint8      profile_idc, chroma_format_idc, frame_mbs_only_flag, frame_cropping_flag;
    guint8      pic_order_cnt_type, vui_parameters_present_flag, num_ref_frames_in_pic_order_cnt_cycle;
    guint8      seq_scaling_matrix_present_flag; /* seq_scaling_list_present_flag */

    /* profile_idc 0 u(8) */
    profile_idc = tvb_get_guint8(tvb, offset);
    proto_tree_add_item(tree, hf_h264_profile_idc, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    constraint_set3_flag = (tvb_get_guint8(tvb, offset)&0x10)>>4;
    /* constraint_set0_flag 0 u(1) */
    proto_tree_add_item(tree, hf_h264_constraint_set0_flag, tvb, offset, 1, ENC_BIG_ENDIAN);

    /* constraint_set1_flag 0 u(1) */
    proto_tree_add_item(tree, hf_h264_constraint_set1_flag, tvb, offset, 1, ENC_BIG_ENDIAN);

    /* constraint_set2_flag 0 u(1) */
    proto_tree_add_item(tree, hf_h264_constraint_set2_flag, tvb, offset, 1, ENC_BIG_ENDIAN);

    /* constraint_set3_flag 0 u(1) */
    proto_tree_add_item(tree, hf_h264_constraint_set3_flag, tvb, offset, 1, ENC_BIG_ENDIAN);

    /* reserved_zero_4bits  equal to 0  0 u(4)*/
    proto_tree_add_item(tree, hf_h264_reserved_zero_4bits, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    /* level_idc 0 u(8) */
    level_idc = tvb_get_guint8(tvb, offset);
    level_item = proto_tree_add_item(tree, hf_h264_level_idc, tvb, offset, 1, ENC_BIG_ENDIAN);
    if ((level_idc == 11) && (constraint_set3_flag == 1)) {
        proto_item_append_text(level_item,"[Level 1b]");
    } else {
        proto_item_append_text(level_item," [Level %.1f %s]", ((double)level_idc/10), val_to_str_const(level_idc, h264_level_bitrate_values, "Unknown "));
    }
    offset++;
    /* seq_parameter_set_id 0 ue(v)
     * ue(v): unsigned integer Exp-Golomb-coded syntax element with the left bit first.
     * The parsing process for this descriptor is specified in subclause 9.1.
     */
    bit_offset = offset<<3;
    dissect_h264_exp_golomb_code(tree, hf_h264_seq_parameter_set_id, tvb, &bit_offset, H264_UE_V);


    if ((profile_idc == 100) || (profile_idc == 110) ||
        (profile_idc == 122) || (profile_idc == 144)) {

        /* chroma_format_idc 0 ue(v) */
        chroma_format_idc = dissect_h264_exp_golomb_code(tree, hf_h264_chroma_format_idc, tvb, &bit_offset, H264_UE_V);
        if (chroma_format_idc == 3) {
            /* residual_colour_transform_flag 0 u(1) */
            proto_tree_add_bits_item(tree, hf_h264_residual_colour_transform_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
            bit_offset++;
        }

        /* bit_depth_luma_minus8 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_bit_depth_luma_minus8, tvb, &bit_offset, H264_UE_V);

        /* bit_depth_chroma_minus8 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_bit_depth_chroma_minus8, tvb, &bit_offset, H264_UE_V);

        /* qpprime_y_zero_transform_bypass_flag 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_qpprime_y_zero_transform_bypass_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        /* seq_scaling_matrix_present_flag 0 u(1) */
        seq_scaling_matrix_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
        proto_tree_add_bits_item(tree, hf_h264_seq_scaling_matrix_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        if (seq_scaling_matrix_present_flag) {
            /*
            for (i = 0; i < 8; i++) {
                / seq_scaling_list_present_flag[ i ] 0 u(1) /
                seq_scaling_list_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
                bit_offset++;
                if (seq_scaling_list_present_flag) {
                    if (i < 6)
                        scaling_list( ScalingList4x4[ i ], 16, UseDefaultScalingMatrix4x4Flag[ i ])0
                        dissect_h264_scaling_list()
                    else
                        scaling_list( ScalingList8x8[ i - 6 ], 64, UseDefaultScalingMatrix8x8Flag[ i - 6 ] )0
                }
            }
            */
            proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, offset, -1);
            return -1;
        }

    }

    /* log2_max_frame_num_minus4 0 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_log2_max_frame_num_minus4, tvb, &bit_offset, H264_UE_V);

    /* pic_order_cnt_type 0 ue(v) */
    pic_order_cnt_type = dissect_h264_exp_golomb_code(tree, hf_h264_pic_order_cnt_type, tvb, &bit_offset, H264_UE_V);

    if (pic_order_cnt_type == 0) {
        /* log2_max_pic_order_cnt_lsb_minus4 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_log2_max_pic_order_cnt_lsb_minus4, tvb, &bit_offset, H264_UE_V);
    } else if (pic_order_cnt_type == 1) {
        /* delta_pic_order_always_zero_flag 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_delta_pic_order_always_zero_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        /* offset_for_non_ref_pic 0 se(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_offset_for_non_ref_pic, tvb, &bit_offset, H264_SE_V);

        /* offset_for_top_to_bottom_field 0 se(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_offset_for_top_to_bottom_field, tvb, &bit_offset, H264_SE_V);

        /* num_ref_frames_in_pic_order_cnt_cycle 0 ue(v) */
        num_ref_frames_in_pic_order_cnt_cycle = dissect_h264_exp_golomb_code(tree, hf_h264_num_ref_frames_in_pic_order_cnt_cycle, tvb, &bit_offset, H264_UE_V);
        for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
            /*offset_for_ref_frame[ i ] 0 se(v)*/
            dissect_h264_exp_golomb_code(tree, hf_h264_offset_for_ref_frame, tvb, &bit_offset, H264_SE_V);
        }
    }
    /* num_ref_frames 0 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_num_ref_frames, tvb, &bit_offset, H264_UE_V);

    /*  gaps_in_frame_num_value_allowed_flag 0 u(1) */
    proto_tree_add_bits_item(tree, hf_h264_gaps_in_frame_num_value_allowed_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /*  pic_width_in_mbs_minus1 0 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_pic_width_in_mbs_minus1, tvb, &bit_offset, H264_UE_V);

    /* pic_height_in_map_units_minus1 0 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_pic_height_in_map_units_minus1, tvb, &bit_offset, H264_UE_V);

    /* frame_mbs_only_flag 0 u(1) */
    frame_mbs_only_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_frame_mbs_only_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;
    if (!frame_mbs_only_flag) {
        /* mb_adaptive_frame_field_flag 0 u(1) */
        proto_tree_add_bits_item(tree, hf_h264_mb_adaptive_frame_field_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;
    }

    /* direct_8x8_inference_flag 0 u(1) */
    proto_tree_add_bits_item(tree, hf_h264_direct_8x8_inference_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /* frame_cropping_flag 0 u(1) */
    frame_cropping_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_frame_cropping_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (frame_cropping_flag) {
        /* frame_crop_left_offset 0 ue(v) */
        dissect_h264_exp_golomb_code(tree, hf_h264_frame_crop_left_offset, tvb, &bit_offset, H264_UE_V);
        dissect_h264_exp_golomb_code(tree, hf_h264_frame_crop_right_offset, tvb, &bit_offset, H264_UE_V);
        dissect_h264_exp_golomb_code(tree, hf_h264_frame_crop_top_offset, tvb, &bit_offset, H264_UE_V);
        dissect_h264_exp_golomb_code(tree, hf_h264_frame_crop_bottom_offset, tvb, &bit_offset, H264_UE_V);

    }

    /*  vui_parameters_present_flag 0 u(1) */
    vui_parameters_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
    proto_tree_add_bits_item(tree, hf_h264_vui_parameters_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;
    if (vui_parameters_present_flag) {
        bit_offset = dissect_h264_vui_parameters(tree, tvb, pinfo, bit_offset);
    }

    /*  rbsp_trailing_bits( ) 0 */
    bit_offset = dissect_h264_rbsp_trailing_bits(tree, tvb, pinfo, bit_offset);

    offset = bit_offset>>3;

    return offset;
}

/* 7.3.2.2 Picture parameter set RBSP syntax */

static void
dissect_h264_pic_parameter_set_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, gint offset)
{
    gint    bit_offset;
    guint32 num_slice_groups_minus1, pic_scaling_matrix_present_flag;

    bit_offset = offset<<3;

    /* pic_parameter_set_id 1 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_pic_parameter_set_id, tvb, &bit_offset, H264_UE_V);

    /* seq_parameter_set_id 1 ue(v) */
    dissect_h264_exp_golomb_code(tree, hf_h264_seq_parameter_set_id, tvb, &bit_offset, H264_UE_V);

    /* entropy_coding_mode_flag 1 u(1) */
    proto_tree_add_bits_item(tree, hf_h264_entropy_coding_mode_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /* pic_order_present_flag 1 u(1)*/
    proto_tree_add_bits_item(tree, hf_h264_pic_order_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /* num_slice_groups_minus1 1 ue(v)*/
    num_slice_groups_minus1 = dissect_h264_exp_golomb_code(tree, hf_h264_num_slice_groups_minus1, tvb, &bit_offset, H264_UE_V);
    if (num_slice_groups_minus1 > 0) {
        /* slice_group_map_type 1 ue(v)*/
        dissect_h264_exp_golomb_code(tree, hf_h264_slice_group_map_type, tvb, &bit_offset, H264_UE_V);
    /*  slice_group_map_type = dissect_h264_exp_golomb_code(tree, hf_h264_slice_group_map_type, tvb, &bit_offset, H264_UE_V);*/
    /* if (slice_group_map_type == 0)*/
    /* for (iGroup = 0; iGroup <= num_slice_groups_minus1; iGroup++)*/
    /* run_length_minus1[ iGroup ] 1 ue(v)*/
    /* else if (slice_group_map_type == 2)*/
    /* for (iGroup = 0; iGroup < num_slice_groups_minus1; iGroup++) {*/
    /* top_left[ iGroup ] 1 ue(v)*/
    /* bottom_right[ iGroup ] 1 ue(v)*/
    /* }*/
    /* else if (slice_group_map_type == 3 ||*/
    /* slice_group_map_type == 4 ||*/
    /* slice_group_map_type == 5 ) {*/
    /* slice_group_change_direction_flag 1 u(1)*/
    /* slice_group_change_rate_minus1 1 ue(v)*/
    /* } else if (slice_group_map_type == 6) {*/
    /* pic_size_in_map_units_minus1 1 ue(v)*/
    /* for (i = 0; i <= pic_size_in_map_units_minus1; i++)*/
    /* slice_group_id[ i ] 1 u(v)*/
    /* }*/
    /* }*/
        proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, bit_offset>>3, -1);
        return;
    }
    /* num_ref_idx_l0_active_minus1 1 ue(v)*/
    dissect_h264_exp_golomb_code(tree, hf_h264_num_ref_idx_l0_active_minus1, tvb, &bit_offset, H264_UE_V);

    /* num_ref_idx_l1_active_minus1 1 ue(v)*/
    dissect_h264_exp_golomb_code(tree, hf_h264_num_ref_idx_l1_active_minus1, tvb, &bit_offset, H264_UE_V);

    /* weighted_pred_flag 1 u(1)*/
    proto_tree_add_bits_item(tree, hf_h264_weighted_pred_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /* weighted_bipred_idc 1 u(2)*/
    proto_tree_add_bits_item(tree, hf_h264_weighted_bipred_idc, tvb, bit_offset, 2, ENC_BIG_ENDIAN);
    bit_offset= bit_offset+2;

    /* pic_init_qp_minus26  * relative to 26 * 1 se(v)*/
    dissect_h264_exp_golomb_code(tree, hf_h264_pic_init_qp_minus26, tvb, &bit_offset, H264_SE_V);

    /* pic_init_qs_minus26  * relative to 26 *  1 se(v)*/
    dissect_h264_exp_golomb_code(tree, hf_h264_pic_init_qs_minus26, tvb, &bit_offset, H264_SE_V);

    /* chroma_qp_index_offset 1 se(v)*/
    dissect_h264_exp_golomb_code(tree, hf_h264_chroma_qp_index_offset, tvb, &bit_offset, H264_SE_V);

    /* deblocking_filter_control_present_flag 1 u(1)*/
    proto_tree_add_bits_item(tree, hf_h264_deblocking_filter_control_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /* constrained_intra_pred_flag 1 u(1)*/
    proto_tree_add_bits_item(tree, hf_h264_constrained_intra_pred_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    /* redundant_pic_cnt_present_flag 1 u(1)*/
    proto_tree_add_bits_item(tree, hf_h264_redundant_pic_cnt_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
    bit_offset++;

    if (more_rbsp_data(tree, tvb, pinfo, bit_offset)) {
        /* transform_8x8_mode_flag 1 u(1)*/
        proto_tree_add_bits_item(tree, hf_h264_transform_8x8_mode_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        /* pic_scaling_matrix_present_flag 1 u(1)*/
        pic_scaling_matrix_present_flag = tvb_get_bits8(tvb, bit_offset, 1);
        proto_tree_add_bits_item(tree, hf_h264_pic_scaling_matrix_present_flag, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
        bit_offset++;

        if (pic_scaling_matrix_present_flag) {
            proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, bit_offset>>3, -1);
            return;
            /* for (i = 0; i < 6 + 2* transform_8x8_mode_flag; i++) {*/
                /* pic_scaling_list_present_flag[ i ] 1 u(1)*/
                /* if (pic_scaling_list_present_flag[ i ])*/
                /* if (i < 6)*/
                    /* scaling_list( ScalingList4x4[ i ], 16, UseDefaultScalingMatrix4x4Flag[ i ] )*/
                /* else*/
                    /* scaling_list( ScalingList8x8[ i - 6 ], 64, UseDefaultScalingMatrix8x8Flag[ i - 6 ] )*/
            /* }*/
            }

        /* second_chroma_qp_index_offset 1 se(v)*/
        dissect_h264_exp_golomb_code(tree, hf_h264_second_chroma_qp_index_offset, tvb, &bit_offset, H264_SE_V);
    }
    bit_offset = dissect_h264_rbsp_trailing_bits(tree, tvb, pinfo, bit_offset);
}

/*
 * 7.3.2.4 Access unit delimiter RBSP syntax
 * access_unit_delimiter_rbsp( )
 */
static void
dissect_h264_access_unit_delimiter_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    /* primary_pic_type 6 u(3) */
    /* rbsp_trailing_bits( ) 6 */
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, offset, -1);
}

/*
 * 7.3.2.5 End of sequence RBSP syntax
 * end_of_seq_rbsp( ) {}
 */
static void
dissect_h264_end_of_seq_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, offset, -1);
}

/*
 * 7.3.2.6 End of stream RBSP syntax
 * end_of_stream_rbsp( ) {}
 */
static void
dissect_h264_end_of_stream_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, offset, -1);
}

/*
 * 7.3.2.7 Filler data RBSP syntax
 * filler_data_rbsp( )
 */
static void
dissect_h264_filler_data_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    /* while (next_bits( 8 ) == 0xFF) */
    /* ff_byte * equal to 0xFF * 9 f(8) */
    /* rbsp_trailing_bits( ) 9 */
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, offset, -1);
}

/*
 * 7.3.2.1.2 Sequence parameter set extension RBSP syntax
 * seq_parameter_set_extension_rbsp( )
 */
static void
dissect_h264_seq_parameter_set_extension_rbsp(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo _U_, gint offset)
{
    /* seq_parameter_set_id 10 ue(v) */
    /* aux_format_idc 10 ue(v) */
    /* if (aux_format_idc != 0 ) { */
    /* bit_depth_aux_minus8 10 ue(v) */
    /* alpha_incr_flag 10 u(1) */
    /* alpha_opaque_value 10 u(v) */
    /* alpha_transparent_value 10 u(v) */
    /* } */
    /* additional_extension_flag 10 u(1) */
    /* rbsp_trailing_bits() 10 */
    proto_tree_add_expert(tree, pinfo, &ei_h264_undecoded, tvb, offset, -1);
}


/*
 * Dissect NAL unit as recived in sprop-parameter-sets of SDP
 * or "DecoderConfiguration parameter in H.245
 */
void
dissect_h264_nal_unit(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree)
{
    proto_item *item;
    proto_tree *h264_nal_tree;
    gint        offset = 0;
    guint8      nal_unit_type;
    guint32     dword;

    item          = proto_tree_add_item(tree, hf_h264_nal_unit, tvb, offset, -1, ENC_NA);
    h264_nal_tree = proto_item_add_subtree(item, ett_h264_nal_unit);

startover:
    /* In decoder configuration start code may be pressent
     * B.1.1 Byte stream NAL unit syntax
     */
    dword = tvb_get_bits32(tvb, offset<<3, 32, ENC_BIG_ENDIAN);
    if (dword == 1) {
        /* zero_byte + start_code_prefix_one_3bytes */
        offset+=4;
    } else if ((dword >> 8) == 1) {
        /* start_code_prefix_one_3bytes */
        offset+= 3;
    }
    /* Ref: 7.3.1 NAL unit syntax */
    nal_unit_type = tvb_get_guint8(tvb, offset) & 0x1f;

    /* forbidden_zero_bit All f(1) */
    proto_tree_add_item(h264_nal_tree, hf_h264_forbidden_zero_bit, tvb, offset, 1, ENC_BIG_ENDIAN);
    /* nal_ref_idc All u(2) */
    proto_tree_add_item(h264_nal_tree, hf_h264_nal_ref_idc, tvb, offset, 1, ENC_BIG_ENDIAN);
    /* nal_unit_type All u(5) */
    proto_tree_add_item(h264_nal_tree, hf_h264_nal_unit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset++;

    switch (nal_unit_type) {
    case 1: /* Coded slice of a non-IDR picture */
        dissect_h264_slice_layer_without_partitioning_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 2: /* Coded slice data partition A */
        dissect_h264_slice_data_partition_a_layer_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 3: /* Coded slice data partition B */
        dissect_h264_slice_data_partition_b_layer_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 4: /* Coded slice data partition C */
        dissect_h264_slice_data_partition_c_layer_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 5: /* Coded slice of an IDR picture */
        dissect_h264_slice_layer_without_partitioning_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 6: /* Supplemental enhancement information (SEI) */
        dissect_h264_sei_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case H264_SEQ_PAR_SET:  /* 7 Sequence parameter set*/
        offset = dissect_h264_seq_parameter_set_rbsp(h264_nal_tree, tvb, pinfo, offset);
        /* A bit ugly */
        if (tvb_length_remaining(tvb, offset) > 0) {
            /* In this case length = offset as we start from zero */
            proto_item_set_len(item, offset/*Length */);
            item = proto_tree_add_item(tree, hf_h264_nal_unit, tvb, offset, -1, ENC_NA);
            h264_nal_tree = proto_item_add_subtree(item, ett_h264_nal_unit);
            goto startover;
        }
        break;
    case H264_PIC_PAR_SET:  /* 8 Picture parameter set */
        dissect_h264_pic_parameter_set_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 9: /* Access unit delimiter */
        dissect_h264_access_unit_delimiter_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 10:    /* End of sequence */
        dissect_h264_end_of_seq_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 11:    /* End of stream */
        dissect_h264_end_of_stream_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 12:    /* Filler data */
        dissect_h264_filler_data_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 13:    /* Sequence parameter set extension */
        dissect_h264_seq_parameter_set_extension_rbsp(h264_nal_tree, tvb, pinfo, offset);
        break;
    case 14:    /* Reserved */
    case 15:    /* Reserved */
    case 16:    /* Reserved */
    case 17:    /* Reserved */
    case 18:    /* Reserved */
        proto_tree_add_text(h264_nal_tree, tvb, offset, -1, "Reserved NAL unit type");
        break;
    case 19:    /* Coded slice of an auxiliary coded picture without partitioning */
        dissect_h264_slice_layer_without_partitioning_rbsp(tree, tvb, pinfo, offset);
        break;
    case 28:
        dissect_h264_slice_layer_without_partitioning_rbsp(tree, tvb, pinfo, offset);
        break;
    case 0: /* Unspecified */
    default:
        /* 24..31 Unspecified */
        proto_tree_add_text(h264_nal_tree, tvb, offset, -1, "Unspecified NAL unit type");
        break;
    }
}

/* Code to actually dissect the packets */
static void
dissect_h264(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    int         offset = 0;
    proto_item *item, *ti, *stream_item, *fua_item;
    proto_tree *h264_tree, *h264_nal_tree, *stream_tree, *fua_tree;
    guint8      type;
    tvbuff_t   *rbsp_tvb;


/* Make entries in Protocol column and Info column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "H264");

    type = tvb_get_guint8(tvb, offset)&0x1f;

    col_append_fstr(pinfo->cinfo, COL_INFO, " %s",
                    val_to_str(type, h264_type_values, "Unknown Type (%u)"));

    if (tree) {
        item = proto_tree_add_item(tree, proto_h264, tvb, 0, -1, ENC_NA);
        h264_tree = proto_item_add_subtree(item, ett_h264);

        /* if the type is 28, it would be draw another title */
        if (type == 28)
            ti = proto_tree_add_text(h264_tree, tvb, offset, 1, "FU identifier");
        else
            ti = proto_tree_add_text(h264_tree, tvb, offset, 1, "NAL unit header or first byte of the payload");
        h264_nal_tree = proto_item_add_subtree(ti, ett_h264_nal);

        /* +---------------+
         * |0|1|2|3|4|5|6|7|
         * +-+-+-+-+-+-+-+-+
         * |F|NRI|  Type   |
         * +---------------+
         */

        /* F: 1 bit
         * forbidden_zero_bit.  A value of 0 indicates that the NAL unit type
         * octet and payload should not contain bit errors or other syntax
         * violations.  A value of 1 indicates that the NAL unit type octet
         * and payload may contain bit errors or other syntax violations.
         */
        proto_tree_add_item(h264_nal_tree, hf_h264_nal_f_bit, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(h264_nal_tree, hf_h264_nal_nri,   tvb, offset, 1, ENC_BIG_ENDIAN);

        proto_tree_add_item(h264_nal_tree, hf_h264_type, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset++;
        if (type == 28) {
            fua_item = proto_tree_add_text(h264_tree, tvb, offset, 1, "FU Header");
            fua_tree = proto_item_add_subtree(fua_item, ett_h264_fua);
            proto_tree_add_item(fua_tree, hf_h264_start_bit,     tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(fua_tree, hf_h264_end_bit,       tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(fua_tree, hf_h264_forbidden_bit, tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(fua_tree, hf_h264_nal_unit_type, tvb, offset, 1, ENC_BIG_ENDIAN);
            if ((tvb_get_guint8(tvb, offset)&0x80) == 0x80) {
                type = tvb_get_guint8(tvb, offset)&0x1f;
                offset++;
            }
            else
                return;
        }

        /* Unescape NAL unit */
        rbsp_tvb = dissect_h265_unescap_nal_unit(tvb, pinfo, offset);

        stream_item = proto_tree_add_text(h264_tree, tvb, offset, -1, "H264 bitstream");
        stream_tree = proto_item_add_subtree(stream_item, ett_h264_stream);
        switch (type) {
        case 1:             /* 1 Coded slice of a non-IDR picture */
            dissect_h264_slice_layer_without_partitioning_rbsp(stream_tree, rbsp_tvb, pinfo, 0);
            break;
        case 3: /* Coded slice data partition B */
            dissect_h264_slice_data_partition_b_layer_rbsp(h264_nal_tree, rbsp_tvb, pinfo, 0);
            break;
        case 4: /* Coded slice data partition C */
            dissect_h264_slice_data_partition_c_layer_rbsp(h264_nal_tree, rbsp_tvb, pinfo, 0);
            break;
        case 5: /* Coded slice of an IDR picture */
            dissect_h264_slice_layer_without_partitioning_rbsp(stream_tree, rbsp_tvb, pinfo, 0);
            break;
        case 6: /* Supplemental enhancement information (SEI) */
            dissect_h264_sei_rbsp(stream_tree, tvb, pinfo, offset);
            break;
        case H264_SEQ_PAR_SET:  /* 7 Sequence parameter set*/
            dissect_h264_seq_parameter_set_rbsp(stream_tree, rbsp_tvb, pinfo, 0);
            break;
        case H264_PIC_PAR_SET:  /* 8 Picture parameter set */
            dissect_h264_pic_parameter_set_rbsp(stream_tree, rbsp_tvb, pinfo, 0);
            break;
        case 19:    /* Coded slice of an auxiliary coded picture without partitioning */
            dissect_h264_slice_layer_without_partitioning_rbsp(stream_tree, rbsp_tvb, pinfo, 0);
            break;
        default:
            break;
        }
    } /* if (tree) */
}


/* Capability */

static const int *profile_fields[] = {
    &hf_h264_par_profile_b,
    &hf_h264_par_profile_m,
    &hf_h264_par_profile_e,
    &hf_h264_par_profile_h,
    &hf_h264_par_profile_h10,
    &hf_h264_par_profile_h4_2_2,
    &hf_h264_par_profile_h4_4_4,
    NULL
};

static int
dissect_h264_par_profile(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
    int offset = 0;

    proto_tree_add_bitmask(tree, tvb, offset,
                           hf_h264_par_profile, ett_h264_par_profile,
                           profile_fields, ENC_BIG_ENDIAN);
    offset += 1;
    return offset;
}

static const int *AdditionalModesSupported_fields[] = {
    &hf_h264_par_add_mode_sup_rcdo,
    NULL
};

static int
dissect_h264_par_AdditionalModesSupported(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
    int offset = 0;

    proto_tree_add_bitmask(tree, tvb, offset,
                           hf_h264_par_AdditionalModesSupported, ett_h264_par_AdditionalModesSupported,
                           AdditionalModesSupported_fields, ENC_BIG_ENDIAN);
    offset += 1;
    return offset;
}


static const int *ProfileIOP_fields[] = {
    &hf_h264_par_constraint_set0_flag,
    &hf_h264_par_constraint_set1_flag,
    &hf_h264_par_constraint_set2_flag,
    NULL
};


static int
dissect_h264_ProfileIOP(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, void *data _U_)
{
    int offset = 0;

    proto_tree_add_bitmask(tree, tvb, offset,
                           hf_h264_par_ProfileIOP, ett_h264_par_ProfileIOP,
                           ProfileIOP_fields, ENC_BIG_ENDIAN);
    offset += 1;
    return offset;
}

static const value_string h264_par_level_values[] = {
    {  15,    "1" },
    {  19,    "1b" },
    {  22,    "1.1" },
    {  29,    "1.2" },
    {  36,    "1.3" },
    {  43,    "2" },
    {  50,    "2.1" },
    {  57,    "2.2" },
    {  64,    "3" },
    {  71,    "3.1" },
    {  78,    "3.2" },
    {  85,    "4" },
    {  92,    "4.1" },
    {  99,    "4.2" },
    { 106,    "5" },
    { 113 ,   "5.1" },
    { 0,  NULL }
};

static int
dissect_h264_par_level(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree _U_, void *data _U_)
{
    int          offset = 0;
    guint16      lvl;
    const gchar *p;
    asn1_ctx_t  *actx = get_asn1_ctx(data);

    DISSECTOR_ASSERT(actx);

    lvl = tvb_get_ntohs(tvb, offset);
    p = try_val_to_str(lvl, VALS(h264_par_level_values));
    if (p) {
        proto_item_append_text(actx->created_item, " - Level %s", p);
    }
    offset += 2;
    return offset;
}

static int
dissect_h264_par_DecoderConfigurationInformation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    asn1_ctx_t *actx = get_asn1_ctx(data);

    DISSECTOR_ASSERT(actx);

    dissect_h264_nal_unit(tvb, pinfo, tree);

    return tvb_length(tvb);
}

typedef struct _h264_capability_t {
    const gchar *id;
    const gchar *name;
    new_dissector_t content_pdu;
} h264_capability_t;

static h264_capability_t h264_capability_tab[] = {
    /* ITU-T H.241 (05/2006), 8.3 H.264 capabilities */
    { "GenericCapability/0.0.8.241.0.0.1", "ITU-T Rec. H.241 H.264 Video Capabilities", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/41", "Profile", dissect_h264_par_profile },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/42", "Level", dissect_h264_par_level },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/3" , "CustomMaxMBPS", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/4" , "CustomMaxFS", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/5" , "CustomMaxDPB", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/6" , "CustomMaxBRandCPB", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/7" , "MaxStaticMBPS", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/8" , "max-rcmd-nal-unit-size", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/9" , "max-nal-unit-size", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/10", "SampleAspectRatiosSupported", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/11", "AdditionalModesSupported", dissect_h264_par_AdditionalModesSupported },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/12", "AdditionalDisplayCapabilities", NULL },
    /* TS 26.111  H.264 */
    { "GenericCapability/0.0.8.241.0.0.1/nonCollapsing/43" , "DecoderConfigurationInformation", dissect_h264_par_DecoderConfigurationInformation },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/44" , "AcceptRedundantSlices", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/45" , "NalAlignedMode", NULL },
    { "GenericCapability/0.0.8.241.0.0.1/collapsing/46" , "ProfileIOP", dissect_h264_ProfileIOP },
    { NULL, NULL, NULL },
};

static h264_capability_t *find_cap(const gchar *id) {
    h264_capability_t *ftr = NULL;
    h264_capability_t *f;

    for (f=h264_capability_tab; f->id; f++) {
        if (!strcmp(id, f->id)) { ftr = f; break; }
    }
    return ftr;
}

static int
dissect_h264_name(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree, void* data _U_)
{
    asn1_ctx_t *actx = get_asn1_ctx(data);

    DISSECTOR_ASSERT(actx);
    if (tree) {
        h264_capability_t *ftr;
        ftr = find_cap(pinfo->match_string);
        if (ftr) {
            proto_item_append_text(actx->created_item, " - %s", ftr->name);
            proto_item_append_text(proto_item_get_parent(proto_tree_get_parent(tree)), ": %s", ftr->name);
        } else {
            proto_item_append_text(actx->created_item, " - unknown(%s)", pinfo->match_string);
        }
    }

    return tvb_length(tvb);
}


static void range_delete_h264_rtp_pt_callback(guint32 rtp_pt) {
    if (rtp_pt >= 96 && rtp_pt <= 127)
        dissector_delete_uint("rtp.pt", rtp_pt, h264_handle);
}

static void range_add_h264_rtp_pt_callback(guint32 rtp_pt) {
    if (rtp_pt >= 96 && rtp_pt <= 127)
        dissector_add_uint("rtp.pt", rtp_pt, h264_handle);
}

void proto_reg_handoff_h264(void);

void
proto_register_h264(void)
{
    module_t *h264_module;
    expert_module_t* expert_h264;

/* Setup list of header fields  See Section 1.6.1 for details*/
    static hf_register_info hf[] = {
        { &hf_h264_nal_f_bit,
            { "F bit",           "h264.f",
            FT_BOOLEAN, 8, TFS(&h264_f_bit_vals), 0x80,
            NULL, HFILL }
        },
        { &hf_h264_nal_nri,
            { "Nal_ref_idc (NRI)",           "h264.nal_nri",
            FT_UINT8, BASE_DEC, NULL, 0x60,
            NULL, HFILL }
        },
        { &hf_h264_type,
            { "Type",           "h264.nal_unit_hdr",
            FT_UINT8, BASE_DEC, VALS(h264_type_values), 0x1f,
            NULL, HFILL }
        },
        { &hf_h264_start_bit,
            { "Start bit", "h264.start.bit",
            FT_BOOLEAN, 8, TFS(&h264_start_bit_vals), 0x80,
            NULL, HFILL }
        },
        { &hf_h264_end_bit,
            { "End bit", "h264.end.bit",
            FT_BOOLEAN, 8, TFS(&h264_end_bit_vals), 0x40,
            NULL, HFILL }
        },
        { &hf_h264_forbidden_bit,
            { "Forbidden bit", "h264.forbidden.bit",
            FT_UINT8, BASE_DEC, NULL, 0x20,
            NULL, HFILL }
        },
        { &hf_h264_profile,
            { "Profile",           "h264.profile",
            FT_BYTES, BASE_NONE, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_profile_idc,
            { "Profile_idc",           "h264.profile_idc",
            FT_UINT8, BASE_DEC, VALS(h264_profile_idc_values), 0xff,
            NULL, HFILL }
        },
        { &hf_h264_rbsp_stop_bit,
            { "rbsp_stop_bit",           "h264.rbsp_stop_bit",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_rbsp_trailing_bits,
            { "rbsp_trailing_bits",           "h264.rbsp_trailing_bits",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_constraint_set0_flag,
            { "Constraint_set0_flag",           "h264.constraint_set0_flag",
            FT_UINT8, BASE_DEC, NULL, 0x80,
            NULL, HFILL }
        },
        { &hf_h264_constraint_set1_flag,
            { "Constraint_set1_flag",           "h264.constraint_set1_flag",
            FT_UINT8, BASE_DEC, NULL, 0x40,
            NULL, HFILL }
        },
        { &hf_h264_constraint_set2_flag,
            { "Constraint_set2_flag",           "h264.constraint_set2_flag",
            FT_UINT8, BASE_DEC, NULL, 0x20,
            NULL, HFILL }
        },
        { &hf_h264_constraint_set3_flag,
            { "Constraint_set3_flag",           "h264.constraint_set3_flag",
            FT_UINT8, BASE_DEC, NULL, 0x10,
            NULL, HFILL }
        },
        { &hf_h264_reserved_zero_4bits,
            { "Reserved_zero_4bits",           "h264.reserved_zero_4bits",
            FT_UINT8, BASE_DEC, NULL, 0x0f,
            NULL, HFILL }
        },
        { &hf_h264_level_idc,
            { "Level_id",           "h264.level_id",
            FT_UINT8, BASE_DEC, NULL, 0xff,
            NULL, HFILL }
        },
        { &hf_h264_nal_unit,
            { "NAL unit",           "h264.nal_unit",
            FT_BYTES, BASE_NONE, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_forbidden_zero_bit,
            { "Forbidden_zero_bit",           "h264.forbidden_zero_bit",
            FT_UINT8, BASE_DEC, NULL, 0x80,
            NULL, HFILL }
        },
        { &hf_h264_nal_ref_idc,
            { "Nal_ref_idc",           "h264.nal_ref_idc",
            FT_UINT8, BASE_DEC, NULL, 0x60,
            NULL, HFILL }
        },
        {&hf_h264_nal_unit_type,
            { "Nal_unit_type",           "h264.nal_unit_type",
            FT_UINT8, BASE_DEC, VALS(h264_nal_unit_type_vals), 0x1f,
            NULL, HFILL }
        },
        { &hf_h264_seq_parameter_set_id,
            { "seq_parameter_set_id",           "h264.seq_parameter_set_id",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_chroma_format_idc,
            { "chroma_format_id",           "h264.chroma_format_id",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_residual_colour_transform_flag,
            { "residual_colour_transform_flag",           "h264.residual_colour_transform_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_bit_depth_luma_minus8,
            { "bit_depth_luma_minus8",           "h264.bit_depth_luma_minus8",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_bit_depth_chroma_minus8,
            { "bit_depth_chroma_minus8",           "h264.bit_depth_chroma_minus8",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_qpprime_y_zero_transform_bypass_flag,
            { "qpprime_y_zero_transform_bypass_flag",           "h264.qpprime_y_zero_transform_bypass_flag",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_seq_scaling_matrix_present_flag,
            { "seq_scaling_matrix_present_flag",           "h264.seq_scaling_matrix_present_flag",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_log2_max_frame_num_minus4,
            { "log2_max_frame_num_minus4",           "h264.log2_max_frame_num_minus4",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_order_cnt_type,
            { "pic_order_cnt_type",           "h264.pic_order_cnt_type",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_log2_max_pic_order_cnt_lsb_minus4,
            { "log2_max_pic_order_cnt_lsb_minus4",           "h264.log2_max_pic_order_cnt_lsb_minus4",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_delta_pic_order_always_zero_flag,
            { "delta_pic_order_always_zero_flag",           "h264.delta_pic_order_always_zero_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_offset_for_non_ref_pic,
            { "offset_for_non_ref_pic",           "h264.offset_for_non_ref_pic",
            FT_INT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_offset_for_top_to_bottom_field,
            { "offset_for_top_to_bottom_field",           "h264.offset_for_top_to_bottom_field",
            FT_INT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_num_ref_frames_in_pic_order_cnt_cycle,
            { "num_ref_frames_in_pic_order_cnt_cycle",           "h264.num_ref_frames_in_pic_order_cnt_cycle",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_offset_for_ref_frame,
            { "offset_for_ref_frame",           "h264.offset_for_ref_frame",
            FT_INT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_num_ref_frames,
            { "num_ref_frames",           "h264.num_ref_frames",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_gaps_in_frame_num_value_allowed_flag,
            { "gaps_in_frame_num_value_allowed_flag",           "h264.gaps_in_frame_num_value_allowed_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_width_in_mbs_minus1,
            { "pic_width_in_mbs_minus1",           "h264.pic_width_in_mbs_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_height_in_map_units_minus1,
            { "pic_height_in_map_units_minus1",           "h264.pic_height_in_map_units_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_frame_mbs_only_flag,
            { "frame_mbs_only_flag",           "h264.frame_mbs_only_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_mb_adaptive_frame_field_flag,
            { "mb_adaptive_frame_field_flag",           "h264.mb_adaptive_frame_field_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_direct_8x8_inference_flag,
            { "direct_8x8_inference_flag",           "h264.direct_8x8_inference_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_frame_cropping_flag,
            { "frame_cropping_flag",           "h264.frame_cropping_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_frame_crop_left_offset,
            { "frame_crop_left_offset",           "h264.frame_crop_left_offset",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_frame_crop_right_offset,
            { "frame_crop_left_offset",           "h264.frame_crop_right_offset",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_frame_crop_top_offset,
            { "frame_crop_top_offset",           "h264.frame_crop_top_offset",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_frame_crop_bottom_offset,
            { "frame_crop_bottom_offset",           "h264.frame_crop_bottom_offset",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_vui_parameters_present_flag,
            { "vui_parameters_present_flag",           "h264.vui_parameters_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_parameter_set_id,
            { "pic_parameter_set_id",           "h264.pic_parameter_set_id",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_entropy_coding_mode_flag,
            { "entropy_coding_mode_flag",           "h264.entropy_coding_mode_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_order_present_flag,
            { "pic_order_present_flag",           "h264.pic_order_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_num_slice_groups_minus1,
            { "num_slice_groups_minus1",           "h264.num_slice_groups_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_slice_group_map_type,
            { "slice_group_map_type",           "h264.slice_group_map_type",
            FT_UINT32, BASE_DEC, VALS(h264_slice_group_map_type_vals), 0x0,
            NULL, HFILL }
        },
        { &hf_h264_num_ref_idx_l0_active_minus1,
            { "num_ref_idx_l0_active_minus1",           "h264.num_ref_idx_l0_active_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_num_ref_idx_l1_active_minus1,
            { "num_ref_idx_l1_active_minus1",           "h264.num_ref_idx_l1_active_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_weighted_pred_flag,
            { "weighted_pred_flag",           "h264.weighted_pred_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_weighted_bipred_idc,
            { "weighted_bipred_idc",           "h264.weighted_bipred_idc",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_init_qp_minus26,
            { "pic_init_qp_minus26",           "h264.pic_init_qp_minus26",
            FT_INT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_init_qs_minus26,
            { "pic_init_qs_minus26",           "h264.pic_init_qs_minus26",
            FT_INT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_chroma_qp_index_offset,
            { "chroma_qp_index_offset",           "h264.chroma_qp_index_offset",
            FT_INT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_deblocking_filter_control_present_flag,
            { "deblocking_filter_control_present_flag",           "h264.deblocking_filter_control_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_constrained_intra_pred_flag,
            { "constrained_intra_pred_flag",           "h264.constrained_intra_pred_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_redundant_pic_cnt_present_flag,
            { "redundant_pic_cnt_present_flag",           "h264.redundant_pic_cnt_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_transform_8x8_mode_flag,
            { "transform_8x8_mode_flag",           "h264.transform_8x8_mode_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_scaling_matrix_present_flag,
            { "pic_scaling_matrix_present_flag",           "h264.pic_scaling_matrix_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_second_chroma_qp_index_offset,
            { "second_chroma_qp_index_offset",           "h264.second_chroma_qp_index_offset",
            FT_INT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },

        { &hf_h264_aspect_ratio_info_present_flag,
            { "aspect_ratio_info_present_flag",           "h264.aspect_ratio_info_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_aspect_ratio_idc,
            { "aspect_ratio_idc",           "h264.aspect_ratio_idc",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_sar_width,
            { "sar_width",           "h264.sar_width",
            FT_UINT16, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_sar_height,
            { "sar_height",           "h264.sar_height",
            FT_UINT16, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_overscan_info_present_flag,
            { "overscan_info_present_flag",           "h264.overscan_info_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_overscan_appropriate_flag,
            { "overscan_appropriate_flag",           "h264.overscan_appropriate_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_video_signal_type_present_flag,
            { "video_signal_type_present_flag",           "h264.video_signal_type_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_video_format,
            { "video_format",           "h264.video_format",
            FT_UINT8, BASE_DEC, VALS(h264_video_format_vals), 0x0,
            NULL, HFILL }
        },
        { &hf_h264_video_full_range_flag,
            { "video_full_range_flag",           "h264.video_full_range_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_colour_description_present_flag,
            { "colour_description_present_flag",           "h264.colour_description_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_colour_primaries,
            { "colour_primaries",           "h264.colour_primaries",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_transfer_characteristics,
            { "transfer_characteristics",           "h264.transfer_characteristics",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_matrix_coefficients,
            { "matrix_coefficients",           "h264.matrix_coefficients",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_chroma_loc_info_present_flag,
            { "chroma_loc_info_present_flag",           "h264.chroma_loc_info_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_chroma_sample_loc_type_top_field,
            { "chroma_sample_loc_type_top_field",           "h264.chroma_sample_loc_type_top_field",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_chroma_sample_loc_type_bottom_field,
            { "chroma_sample_loc_type_bottom_field",           "h264.chroma_sample_loc_type_bottom_field",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_timing_info_present_flag,
            { "timing_info_present_flag",           "h264.timing_info_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_num_units_in_tick,
            { "num_units_in_tick",           "h264.num_units_in_tick",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_time_scale,
            { "time_scale",           "h264.time_scale",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_fixed_frame_rate_flag,
            { "fixed_frame_rate_flag",           "h264.fixed_frame_rate_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_nal_hrd_parameters_present_flag,
            { "nal_hrd_parameters_present_flag",           "h264.nal_hrd_parameters_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_vcl_hrd_parameters_present_flag,
            { "vcl_hrd_parameters_present_flag",           "h264.vcl_hrd_parameters_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_low_delay_hrd_flag,
            { "low_delay_hrd_flag",           "h264.low_delay_hrd_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_pic_struct_present_flag,
            { "pic_struct_present_flag",           "h264.pic_struct_present_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_bitstream_restriction_flag,
            { "bitstream_restriction_flag",           "h264.bitstream_restriction_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_motion_vectors_over_pic_boundaries_flag,
            { "motion_vectors_over_pic_boundaries_flag",           "h264.motion_vectors_over_pic_boundaries_flag",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_max_bytes_per_pic_denom,
            { "max_bytes_per_pic_denom",           "h264.max_bytes_per_pic_denom",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_max_bits_per_mb_denom,
            { "max_bits_per_mb_denom",           "h264.max_bits_per_mb_denom",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_log2_max_mv_length_horizontal,
            { "max_mv_length_horizontal",           "h264.max_mv_length_horizontal",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_log2_max_mv_length_vertical,
            { "log2_max_mv_length_vertical",           "h264.log2_max_mv_length_vertical",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_num_reorder_frames,
            { "num_reorder_frames",           "h264.num_reorder_frames",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_max_dec_frame_buffering,
            { "max_dec_frame_buffering",           "h264.max_dec_frame_buffering",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_cpb_cnt_minus1,
            { "cpb_cnt_minus1",           "h264.cpb_cnt_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_bit_rate_scale,
            { "bit_rate_scale",           "h264.bit_rate_scale",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_cpb_size_scale,
            { "cpb_size_scale",           "h264.cpb_size_scale",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_bit_rate_value_minus1,
            { "bit_rate_value_minus1",           "h264.bit_rate_value_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_cpb_size_value_minus1,
            { "cpb_size_value_minus1",           "h264.cpb_size_value_minus1",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_cbr_flag,
            { "cbr_flag",           "h264.cbr_flag",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_initial_cpb_removal_delay_length_minus1,
            { "initial_cpb_removal_delay_length_minus1",           "h264.initial_cpb_removal_delay_length_minus1",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_cpb_removal_delay_length_minus1,
            { "cpb_removal_delay_length_minus1",           "h264.cpb_removal_delay_length_minus1",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_dpb_output_delay_length_minus11,
            { "dpb_output_delay_length_minus11",           "h264.dpb_output_delay_length_minus11",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_time_offset_length,
            { "time_offset_length",           "h264.time_offset_length",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_first_mb_in_slice,
            { "first_mb_in_slice",           "h264.first_mb_in_slice",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_slice_type,
            { "slice_type",           "h264.slice_type",
            FT_UINT32, BASE_DEC, VALS(h264_slice_type_vals), 0x0,
            NULL, HFILL }
        },
        { &hf_h264_slice_id,
            { "slice_id",           "h264.slice_id",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_payloadsize,
            { "PayloadSize",           "h264.payloadsize",
            FT_UINT32, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
        { &hf_h264_payloadtype,
            { "payloadType",           "h264.payloadtype",
            FT_UINT32, BASE_DEC, VALS(h264_sei_payload_vals), 0x0,
            NULL, HFILL }
        },
#if 0
        { &hf_h264_frame_num,
            { "frame_num",           "h264.frame_num",
            FT_UINT8, BASE_DEC, NULL, 0x0,
            NULL, HFILL }
        },
#endif
        { &hf_h264_par_profile,
                { "Profile", "h264.profile",
                FT_UINT8, BASE_HEX, NULL, 0x00,
            NULL, HFILL}},
        { &hf_h264_par_profile_b,
                { "Baseline Profile", "h264.profile.base",
            FT_BOOLEAN, 8, NULL, 0x40,
            NULL, HFILL}},
        { &hf_h264_par_profile_m,
                { "Main Profile", "h264.profile.main",
            FT_BOOLEAN, 8, NULL, 0x20,
            NULL, HFILL}},
        { &hf_h264_par_profile_e,
                { "Extended Profile.", "h264.profile.ext",
            FT_BOOLEAN, 8, NULL, 0x10,
            NULL, HFILL}},
        { &hf_h264_par_profile_h,
                { "High Profile", "h264.profile.high",
            FT_BOOLEAN, 8, NULL, 0x08,
            NULL, HFILL}},
        { &hf_h264_par_profile_h10,
                { "High 10 Profile", "h264.profile.high10",
            FT_BOOLEAN, 8, NULL, 0x04,
            NULL, HFILL}},
        { &hf_h264_par_profile_h4_2_2,
                { "High 4:2:2 Profile", "h264.profile.high4_2_2",
            FT_BOOLEAN, 8, NULL, 0x02,
            NULL, HFILL}},
        { &hf_h264_par_profile_h4_4_4,
                { "High 4:4:4 Profile", "h264.profile.high4_4_4",
            FT_BOOLEAN, 8, NULL, 0x01,
            NULL, HFILL}},
        { &hf_h264_par_AdditionalModesSupported,
                { "AdditionalModesSupported", "h264.AdditionalModesSupported",
            FT_UINT8, BASE_HEX, NULL, 0x00,
            NULL, HFILL}},
#if 0
        { &hf_h264_par_add_mode_sup,
                { "Additional Modes Supported", "h264.add_mode_sup",
            FT_UINT8, BASE_HEX, NULL, 0x00,
            NULL, HFILL}},
#endif
        { &hf_h264_par_add_mode_sup_rcdo,
                { "Reduced Complexity Decoding Operation (RCDO) support", "h264.add_mode_sup.rcdo",
            FT_BOOLEAN, 8, NULL, 0x40,
            NULL, HFILL}},
        { &hf_h264_par_ProfileIOP,
                { "ProfileIOP", "h264.ProfileIOP",
            FT_UINT8, BASE_HEX, NULL, 0x00,
            NULL, HFILL}},
        { &hf_h264_par_constraint_set0_flag,
                { "constraint_set0_flag", "h264.par.constraint_set0_flag",
            FT_BOOLEAN, 8, NULL, 0x80,
            NULL, HFILL}},
        { &hf_h264_par_constraint_set1_flag,
                { "constraint_set1_flag", "h264.par.constraint_set1_flag",
            FT_BOOLEAN, 8, NULL, 0x40,
            NULL, HFILL}},
        { &hf_h264_par_constraint_set2_flag,
                { "constraint_set2_flag", "h264.par.constraint_set2_flag",
            FT_BOOLEAN, 8, NULL, 0x20,
            NULL, HFILL}},
    };

/* Setup protocol subtree array */
    static gint *ett[] = {
        &ett_h264,
        &ett_h264_profile,
        &ett_h264_nal,
        &ett_h264_fua,
        &ett_h264_stream,
        &ett_h264_nal_unit,
        &ett_h264_par_profile,
        &ett_h264_par_AdditionalModesSupported,
        &ett_h264_par_ProfileIOP,
    };

    static ei_register_info ei[] = {
        { &ei_h264_undecoded, { "h264.undecoded", PI_UNDECODED, PI_WARN, "[Not decoded yet]", EXPFILL }},
    };

/* Register the protocol name and description */
    proto_h264 = proto_register_protocol("H.264","H264", "h264");

/* Required function calls to register the header fields and subtrees used */
    proto_register_field_array(proto_h264, hf, array_length(hf));
    proto_register_subtree_array(ett, array_length(ett));
    expert_h264 = expert_register_protocol(proto_h264);
    expert_register_field_array(expert_h264, ei, array_length(ei));
    /* Register a configuration option for port */


    h264_module = prefs_register_protocol(proto_h264, proto_reg_handoff_h264);


    prefs_register_range_preference(h264_module, "dynamic.payload.type",
                            "H264 dynamic payload types",
                            "Dynamic payload types which will be interpreted as H264"
                            "; Values must be in the range 96 - 127",
                            &temp_dynamic_payload_type_range, 127);

    register_dissector("h264", dissect_h264, proto_h264);
}


/* Register the protocol with Wireshark */
void
proto_reg_handoff_h264(void)
{
    static range_t  *dynamic_payload_type_range = NULL;
    static gboolean  h264_prefs_initialized     = FALSE;

    if (!h264_prefs_initialized) {
        dissector_handle_t h264_name_handle;
        h264_capability_t *ftr;

        h264_handle = find_dissector("h264");
        dissector_add_string("rtp_dyn_payload_type","H264", h264_handle);

        h264_name_handle = new_create_dissector_handle(dissect_h264_name, proto_h264);
        for (ftr=h264_capability_tab; ftr->id; ftr++) {
            if (ftr->name)
                dissector_add_string("h245.gef.name", ftr->id, h264_name_handle);
            if (ftr->content_pdu)
                dissector_add_string("h245.gef.content", ftr->id, new_create_dissector_handle(ftr->content_pdu, proto_h264));
        }
        h264_prefs_initialized = TRUE;
    } else {
        range_foreach(dynamic_payload_type_range, range_delete_h264_rtp_pt_callback);
        g_free(dynamic_payload_type_range);
    }

    dynamic_payload_type_range = range_copy(temp_dynamic_payload_type_range);
    range_foreach(dynamic_payload_type_range, range_add_h264_rtp_pt_callback);
}


