/*
#
# MPEG2 data structures for MPEG2Parser class
#
# $Id: mpeg2structs.h,v 1.2 2005/03/20 20:18:33 nemesis Exp $
#
# Copyright (C) 2001-2003 Kees Cook
# kees@outflux.net, http://outflux.net/
# 
# 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
# http://www.gnu.org/copyleft/gpl.html
#
*/

#ifndef _MPEG2STRUCTS_H_
#define _MPEG2STRUCTS_H_

#include <inttypes.h>

#ifndef TRUE
# define TRUE 1
#endif
#ifndef FALSE
# define FALSE 0
#endif

/*
   This problem with these damn compilers is that I can't
   specify an arbitrary bit layout structure.  It always
   grows to a different size.  If someone know how to portably
   control that problem let me know, and I can stop using bit masks
   to get at my data.  :)
*/


#define PICTURE_CODING_MASK             0x38
#define PICTURE_CODING_SHIFT            0x03
#define PICTURE_CODING_INTRA            0x01
#define PICTURE_CODING_PREDICTIVE       0x02
#define PICTURE_CODING_BIDIRECTIONAL    0x03

typedef struct
{
    uint8_t  start_code[4];
    uint8_t  bits[2];
    /*  only stuff I want to get to is picture_coding_type
    uint16_t temporal_reference:10;
    uint8_t  picture_coding_type:3;
     */
}
picture_header;

#define GOP_FLAG_MASK	0x60
#define GOP_FLAG_CLOSED	0x40
#define GOP_FLAG_BROKEN	0x20

typedef struct
{
    uint8_t start_code[4];
    uint8_t bits[4];
    /*
    uint32_t time_code:25;
    uint8_t  closed_gop:1;
    uint8_t  broken_link:1;
    uint8_t  unknown:5;
     */
}
group_of_pictures_header;

typedef struct
{
    uint8_t     start_code[4];
    uint8_t     bits[8];

    /*
    uint32_t    horizontal_size_value:12;
    uint32_t    vertical_size_value:12;
    uint32_t    aspect_ratio_information:4;
    uint32_t    frame_rate_code:4;

    uint32_t    bit_rate_code:18;
    uint32_t    marker1:1;
    uint32_t    vbv_buffer_size_value:10;
    uint32_t    constrained_parameters_flag:1;
    uint32_t    load_intra_quantiser_matrix:1;

    uint8_t     intra_quantiser_matrix[64]; // optional
    uint32_t    load_non_intra_quantiser_matrix:1;
    uint8_t     non_intra_quantiser_matrix[64]; // optional
     */
}
sequence_header;

typedef struct
{
    uint8_t     start_code[4];
    uint8_t     profile_and_level_indication;

    /*
    uint8_t     progressive_sequence:1;
    uint8_t     chroma_format:2;
    uint8_t     horizontal_size_extension:2;
    uint8_t     vertical_size_extension:2;
    uint8_t     bit_rate_extension:12;
    uint8_t     vbv_buffer_size_extension:8;
    uint8_t     low_delay:1;
    uint8_t     frame_rate_extension_n:2;
    uint8_t     frame_rate_extension_d:5;

     */
}
sequence_extension_header;


#define ES_TYPE_WEIRD   0
#define ES_TYPE_VIDEO   1
#define ES_TYPE_AUDIO   2

typedef struct
{
    uint8_t start_code[3];
    uint8_t stream_id;
    uint8_t PES_packet_length[2];
}
PES_packet_header_t;

typedef struct
{
    uint8_t bits[2];
    /*
    uint8_t         marker0:2; // 10
    uint8_t         PES_scrambling_control:2;
    uint8_t         PES_priority:1;
    uint8_t         data_alignment_indicator:1;
    uint8_t         copyright:1;
    uint8_t         original_or_copy:1;

    uint8_t         PTS_DTS_flags:2;
    uint8_t         ESCR_flag:1;
    uint8_t         ES_rate_flag:1;
    uint8_t         DSM_trick_mode_flag:1;
    uint8_t         additional_copy_info_flag:1;
    uint8_t         PES_CRC_flag:1;
    uint8_t         PES_extension_flag:1;
     */
    uint8_t PES_header_data_length;
}
PES_packet_internals_t;

typedef struct
{
    uint8_t marker_bit:1;
    uint8_t data:7;
}
PES_packet_additional_copy_info_t;

#define GET_BITS(byte,mask,shiftdown)	(((byte)&(mask))>>(shiftdown))

#define PPE_PES_private_data_flag(x)	GET_BITS(x,0x80,7)
#define PPE_pack_header_field_flag(x)	GET_BITS(x,0x40,6)
#define PPE_program_packet_sequence_counter_flag(x)	GET_BITS(x,0x20,5)
#define PPE_P_STD_buffer_flag(x)		GET_BITS(x,0x10,5)
#define PPE_PES_extension_flag_2(x)		GET_BITS(x,0x01,0)
typedef struct
{
    uint8_t bits[1];
    /*
    uint8_t         PES_private_data_flag:1;
    uint8_t         pack_header_field_flag:1;
    uint8_t         program_packet_sequence_counter_flag:1;
    uint8_t         P_STD_buffer_flag:1;
    uint8_t         reserved:3;
    uint8_t         PES_extension_flag_2:1;
     */
}
PES_packet_extension_t;

typedef struct
{
    uint8_t marker0:1;
    uint8_t program_packet_sequence_counter:7;

    uint8_t marker1:1;
    uint8_t MPEG1_MPEG2_identifier:1;
    uint8_t original_stuff_length:6;
}
PES_packet_extension_program_packet_sequence_counter_t;

#define PES_TYPE_picture_start              0x00
// slice start: 0x01 - 0xAF
// reserved: 0xB0 - 0xB1
#define PES_TYPE_user_data_start            0xB2
#define PES_TYPE_sequence_header            0xB3
#define PES_TYPE_sequence_error             0xB4
#define PES_TYPE_extension_start            0xB5
// reserved: 0xB6
#define PES_TYPE_sequence_end               0xB7
#define PES_TYPE_group_start                0xB8
#define PES_TYPE_program_end                0xB9
#define PES_TYPE_pack_start                 0xBA
#define PES_TYPE_system_header              0xBB
#define PES_TYPE_program_stream_map         0xBC    /* PES simple */
#define PES_TYPE_private_stream_1           0xBD    /* PES complex */
#define PES_TYPE_padding_stream             0xBE    /* PES simple */
#define PES_TYPE_private_stream_2           0xBF    /* PES simple */
#define PES_TYPE_ECM_stream                 0xF0    /* PES simple */
#define PES_TYPE_EMM_stream                 0xF1    /* PES simple */
#define PES_TYPE_DSMCC_stream               0xF2    /* PES simple */
#define PES_TYPE_ISO_13522                  0xF3    /* PES complex */
#define PES_TYPE_H2221A                     0xF4    /* PES complex */
#define PES_TYPE_H2221B                     0xF5    /* PES complex */
#define PES_TYPE_H2221C                     0xF6    /* PES complex */
#define PES_TYPE_H2221D                     0xF7    /* PES complex */
#define PES_TYPE_H2221E                     0xF8    /* PES simple */
#define PES_TYPE_ancillary_stream           0xF9    /* PES complex */
// reserved: 0xFA - 0xFE                        /* PES complex */
#define PES_TYPE_program_stream_directory   0xFF    /* PES simple */

#define PES_TYPE_audio                      0xC0    /* PES complex */
#define PES_TYPE_MASK_audio                 0xE0

#define PES_TYPE_video                      0xE0    /* PES complex */
#define PES_TYPE_MASK_video                 0xF0


//                            xxxxx     xxxxx
// subtitles: 0x20..0x3F   00100000..00111111
#define DVD_AUDIO_TYPE_sub              0x20
#define DVD_AUDIO_TYPE_MASK_sub         0xE0
//                            xxxxx     xxxxx
// AC3:       0x80..0x9F   10000000..10011111
#define DVD_AUDIO_TYPE_ac3              0x80
#define DVD_AUDIO_TYPE_MASK_ac3         0xE0
//                            xxxxx     xxxxx 
// PCM:       0xA0..0xBF   10100000..10111111
#define DVD_AUDIO_TYPE_pcm              0xA0
#define DVD_AUDIO_TYPE_MASK_pcm         0xE0

// frame rates from the sequence header
#define FPS_23_9    1   // 0001 -- 24000/1001
#define FPS_24      2   // 0010 -- 24
#define FPS_25      3   // 0011 -- 25
#define FPS_29_9    4   // 0100 -- 30000/1001
#define FPS_30      5   // 0101 -- 30
#define FPS_50      6   // 0110 -- 50
#define FPS_59_9    7   // 0111 -- 60000/1001
#define FPS_60      8   // 1000 -- 60

// aspect ratio values from the sequence header
#define ASPECT_1        1
#define ASPECT_3_4      2
#define ASPECT_9_16     3
#define ASPECT_1_221    4

typedef struct
{
    uint8_t start_code[4];
    uint16_t header_length;

    uint8_t bits[6];
    /*
    uint32_t        marker0:1; // 1
    uint32_t        rate_bound:22;
    uint32_t        marker1:1; // 1
    uint32_t        audio_bound:6;
    uint32_t        fixed_flag:1;
    uint32_t        CSPS_flag:1;

    uint8_t         system_audio_lock_flag:1;
    uint8_t         system_video_lock_flag:1;
    uint8_t         marker2:1; // 1
    uint8_t         video_bound:5;

    uint8_t         packet_rate_restriction_flag:1;
    uint8_t         reserved:7;
     */

}
system_header_t;

typedef struct
{
    uint8_t stream_id;
    // 1011 1000: P_STD map to all audio streams
    // 1011 1001: P_STD map to all video streams
    // otherwise, must be >= 1011 1100
    //
    uint8_t bits[2];
    /*
    uint16_t        marker0:2; // 11
    uint16_t        P_STD_buffer_bound_scale:1;
    uint16_t        P_STD_buffer_size_bound:13;
     */
}
stream_id_t;

typedef struct
{
    uint8_t start_code[4];
    /*
    uint8_t         marker0:2; // 01
    uint8_t         system_clock_reference_base_hi:3;
    uint8_t         marker1:1; // 1
    uint16_t        system_clock_reference_base_mid:15;
    uint8_t         marker2:1; // 1
    uint16_t        system_clock_reference_base_low:15;
    uint8_t         marker3:1; // 1
    uint16_t        system_clock_reference_extension:9;
    uint8_t         marker4:1; // 1
    uint32_t        program_mux_rate:22;
    uint8_t         marker5:1; // 1
    uint8_t         marker6:1; // 1
    uint8_t         reserved:5;
    uint8_t         pack_stuffing_length:3;
    */
    uint8_t bits[10];
}
pack_header_t;

#endif //  _MPEG2STRUCTS_H_

/* vi:set ai ts=4 sw=4 expandtab: */
