/*
* Copyright (c) 1997-2004 Alexandros Eleftheriadis, Danny Hong and
* Yuntai Kyong.
*
* This file is part of Flavor, developed at Columbia University
* (www.ee.columbia.edu/flavor).
*
* Flavor is free software; you can redistribute it and/or modify
* it under the terms of the Flavor Artistic License as described in
* the file COPYING.txt.
*
*/
/*
* Authors:
* Danny Hong <danny@ee.columbia.edu>
* Jack Caldwell
*
*/
/*
* MPEG-2 Systems (Program Stream)
*
* This example reads MPEG-2 Systems PS streams. It only parses the Systems data
* and all elementary streams are skipped.
*/
%pragma array=256
%pragma get, trace
%.c{
#include %.c}
///////////////
// PES Types //
///////////////
const unsigned int ST_PSMapTable = 0x000001BC;
const unsigned int ST_Private1 = 0x000001BD;
const unsigned int ST_Padding = 0x000001BE;
const unsigned int ST_Private2 = 0x000001BF;
const unsigned int ST_Audio1 = 0x000001C0;
const unsigned int ST_Audio2 = 0x000001DF;
const unsigned int ST_Video1 = 0x000001E0;
const unsigned int ST_Video2 = 0x000001EF;
const unsigned int ST_ECM = 0x000001F0;
const unsigned int ST_EMM = 0x000001F1;
const unsigned int ST_DSMCC = 0x000001F2;
const unsigned int ST_ISO_13522 = 0x000001F3;
const unsigned int ST_ITUT_A = 0x000001F4;
const unsigned int ST_ITUT_B = 0x000001F5;
const unsigned int ST_ITUT_C = 0x000001F6;
const unsigned int ST_ITUT_D = 0x000001F7;
const unsigned int ST_ITUT_E = 0x000001F8;
const unsigned int ST_PSDirectory = 0x000001FF;
/////////////////
// Trick codes //
/////////////////
const unsigned int fast_forward = 0b000;
const unsigned int slow_motion = 0b001;
const unsigned int freeze_frame = 0b010;
const unsigned int fast_reverse = 0b011;
const unsigned int slow_reverse = 0b100;
/*
* SystemHeader
*
*/
class SystemHeader
{
nextcode(aligned(8), 0x000001BB); // PS System Header
skipbits(32); // The next 32 bits must be the system header sc
unsigned int(16) header_length;
bit(1) marker = 0b1;
unsigned int(22) rate_bound; // UB on the program_mux_rate field
// Should check that rate_bound >= max(program_mux_rate)
bit(1) marker = 0b1;
unsigned int(6) audio_bound; // UB on the number of active audio streams
bit(1) fixed_flag; // 1 = fixed bit rate
bit(1) CSPS_flag; // 1 = constrained params
bit(1) system_audio_lock_flag; // Locked to the STC
bit(1) system_video_lock_flag; // Locked to the STC
bit(1) marker = 0b1;
unsigned int(5) video_bound; // UB on the number of video streams
bit(1) packet_rate_restriction_flag;
const bit(7) reserved = 0x7F;
while (nextbits(1) == 0b1) {
unsigned int(8) stream_id;
if (stream_id < 0xBC) {
if (stream_id != 0xB8) {
if (stream_id != 0xB9) {
%g{
print_error(); %g}
}
}
}
bit(2) bit_pattern = 0b11;
bit(1) P_STD_buffer_bound_scale;
unsigned int(13) P_STD_buffer_size_bound;
}
%.c{
void print_error() { printf("Error in SystemHeader! Wrong stream_id!"); } %.c}
%.j{
void print_error() { System.out.println("Error in SystemHeader! Wrong stream_id!"); } %.j}
}
/*
* PackHeader
*
*/
class PackHeader
{
nextcode(aligned(8), 0x000001BA);
skipbits(32);
bit(2) bit_pattern = 0b01;
bit(3) system_clock_ref_1;
bit(1) marker = 0b1;
bit(15) system_clock_ref_2;
bit(1) marker = 0b1;
bit(15) system_clock_ref_3;
bit(1) marker = 0b1;
unsigned int(9) system_clock_ref_extension;
bit(1) marker = 0b1;
unsigned int(22) program_mux_rate;
if (program_mux_rate == 0) {
%g{
print_error(); %g}
}
bit(1) marker = 0b1;
bit(1) marker = 0b1;
bit(5) reserved;
unsigned int(3) stuffing_len;
unsigned int i;
for(i=0; i < stuffing_len; i++)
bit(8) stuffing_byte = 0xFF;
if (nextbits(32) == 0x000001BB)
SystemHeader system_header;
%.c{
void print_error() { printf("Error in PackHeader! The program_mux_rate = 0!"); } %.c}
%.j{
void print_error() { System.out.println("Error in PackHeader! The program_mux_rate = 0!"); } %.j}
}
/////////////////////////
// Program Descriptors //
/////////////////////////
abstract class BaseProgramDescriptor : unsigned int(8) tag = 0
{
unsigned int(8) length;
}
class VideoDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 2
{
bit(1) multiple_frame_rate_flag;
unsigned int(4) frame_rate_code;
bit(1) MPEG1_only_flag;
bit(1) constrained_parameter_flag;
bit(1) still_picture_flag;
if (MPEG1_only_flag == 0b1) {
unsigned int(8) profile_and_level_indication;
unsigned int(2) chroma_format;
bit(1) frame_rate_extension_flag;
bit(5) reserved;
}
}
class AudioDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 3
{
bit(1) free_format_flag;
bit(1) ID;
bit(2) layer;
bit(1) variable_rate_audio_indicator;
bit(3) reserved;
}
class HierarchyDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 4
{
bit(4) reserved;
unsigned int(4) hierarchy_type;
bit(2) reserved;
unsigned int(6) hierarchy_layer_index;
bit(2) reserved;
unsigned int(6) hierarchy_embedded_layer_index;
bit(2) reserved;
unsigned int(6) hierarchy_channel;
}
class RegistrationDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 5
{
unsigned int(32) format_identifier;
unsigned int bytes_read;
for (bytes_read=4; bytes_read < length; ) {
bit(8) additional_identification_info;
bytes_read += 1;
}
}
class DataAlignmentDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 6
{
unsigned int(8) alignment_type;
}
class TargetBackgroundGridDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 7
{
unsigned int(14) horizontal_size;
unsigned int(14) vertical_size;
unsigned int(4) aspect_ratio_information;
}
class VideoWindowDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 8
{
unsigned int(14) horizontal_offset;
unsigned int(14) vertical_offset;
unsigned int(4) window_priority;
}
class ConditionalAccessDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 9
{
unsigned int(16) CA_system_ID;
bit(3) reserved;
unsigned int(13) CA_PID;
unsigned int bytes_read;
for (bytes_read=4; bytes_read < length; ) {
unsigned int(8) private_data_byte;
bytes_read += 1;
}
}
class LanguageDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 10
{
unsigned int bytes_read;
for (bytes_read=0; bytes_read < length; ) {
bit(24) ISO_639_language_code;
bit(8) audio_type;
bytes_read += 4;
}
}
class SystemClockDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 11
{
bit(1) external_clock_reference_indicator;
bit(1) reserved;
unsigned int(6) clock_accuracy_indicator;
unsigned int(3) clock_accuracy_exponent;
bit(5) reserved;
}
class MultiplexBufferUtilizationDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 12
{
bit(1) bound_valid_flag;
unsigned int(15) LTW_offset_lower_bound;
bit(1) reserved;
unsigned int(15) LTW_offset_upper_bound;
}
class CopyrightDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 13
{
unsigned int(32) copyright_identifier;
unsigned int bytes_read;
for (bytes_read=4; bytes_read < length; ) {
bit(8) additional_copyright_info;
bytes_read += 1;
}
}
class MaximumBitrateDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 14
{
bit(2) reserved;
unsigned int(22) maximum_bitrate;
}
class PrivateDataIndicatorDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 15
{
unsigned int(32) private_data_indicator;
}
class SmoothingBufferDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 16
{
bit(2) reserved;
unsigned int(22) sb_leak_rate;
bit(2) reserved;
unsigned int(22) sb_size;
}
class STDDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 17
{
bit(7) reserved;
bit(1) leak_valid_flag;
}
class IBPDescriptor extends BaseProgramDescriptor : unsigned int(8) tag = 18
{
unsigned int(1) closed_gop_flag;
unsigned int(1) identical_gop_flag;
unsigned int(14) max_gop_length;
}
////////////////////////
// Stream Descriptors //
////////////////////////
abstract class BaseStreamDescriptor : unsigned int(8) type = 0x00
{
unsigned int(8) elementary_stream_id;
unsigned int(16) elementary_stream_info_length;
unsigned int parsedBytes;
for (parsedBytes=0; parsedBytes < elementary_stream_info_length; ) {
BaseProgramDescriptor descriptor;
parsedBytes += lengthof(descriptor);
}
}
class MPEG1VideoStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x01 {}
class MPEG2VideoStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x02 {}
class MPEG1AudioStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x03 {}
class MPEG2AudioStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x04 {}
class PrivateStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x05 {}
class PrivatePESDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x06 {}
class MHEGStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x07 {}
class DSMCCStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x08 {}
class H222_1StreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x09 {}
class ATypeStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x0A {}
class BTypeStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x0B {}
class CTypeStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x0C {}
class DTypeStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x0D {}
class AuxiliaryStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x0E {}
class ReservedStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x0F .. 0x7F {}
class UserPrivateStreamDescriptor extends BaseStreamDescriptor : unsigned int(8) type = 0x80 .. 0xFF {}
/* If trick_mode '0' was not assigned to fast_forward, then we could have
* used polymorphic class inheritance.
*/
class TrickModeControl
{
unsigned int(3) trick_mode_control;
if (trick_mode_control == fast_forward || trick_mode_control == fast_reverse) {
bit(2) field_id;
bit(1) intra_slice_refresh;
bit(2) frequency_truncation;
}
else if (trick_mode_control == slow_motion)
unsigned int(5) rep_ctrl;
else if (trick_mode_control == freeze_frame) {
bit(2) field_id;
bit(3) reserved;
}
else if (trick_mode_control == slow_reverse)
unsigned int(5) rep_ctrl;
else
bit(5) reserved;
}
/////////
// PES //
/////////
/*
* PesBase
*
* Abstract base class for all PES Packet derivations
*
*/
abstract class PesBase : const unsigned int(32) st_id = 0
{
unsigned int(16) PES_packet_length;
}
/*
* PesNonData
*
* Abstract base class for all Private2, ECM, EMM, DSMCC, ITUT_E streams
*
*/
abstract class PesNonData extends PesBase : const unsigned int(32) st_id = 0
{
skipbits(8*PES_packet_length);
}
/*
* PesData
*
* Abstract base class for all PESPacket derivations whose stream id's
* Range from 0xC0 .. 0xEF
*
*/
abstract class PesData extends PesBase : const unsigned int(32) st_id = 0
{
skipbits(8*PES_packet_length);
}
// The PesPadding is similar to the PesNonData with the exception that the 8 bit padding bytes must have the value 0xFF
class PesPadding extends PesBase : const unsigned int(32) st_id = ST_Padding
{
unsigned int i;
for (i=0; i < PES_packet_length; i++) {
bit(8) padding_byte = 0xFF;
}
}
class PesAudio extends PesData : const unsigned int(32) st_id = ST_Audio1 .. ST_Audio2 {}
class PesVideo extends PesData : const unsigned int(32) st_id = ST_Video1 .. ST_Video2 {}
class PesITUT_E extends PesNonData : const unsigned int(32) st_id = ST_ITUT_E {}
class PesPrivate1 extends PesNonData : const unsigned int(32) st_id = ST_Private1 {}
class PesPrivate2 extends PesNonData : const unsigned int(32) st_id = ST_Private2 {}
class PesECM extends PesNonData : const unsigned int(32) st_id = ST_ECM {}
class PesEMM extends PesNonData : const unsigned int(32) st_id = ST_EMM {}
class PesDSMCC extends PesBase : const unsigned int(32) st_id = ST_DSMCC {}
////////////////
// PSMapTable //
////////////////
class PSMapTable extends PesBase : const unsigned int(32) st_id = ST_PSMapTable
{
if (PES_packet_length > 1018) {
%g{
print_error(); %g}
}
bit(1) current_next_indicator;
bit(2) reserved;
unsigned int(5) program_stream_map_version;
bit(7) reserved;
bit(1) marker = 0b1;
unsigned int(16) program_stream_info_length;
unsigned int parsed;
for (parsed=0; parsed < program_stream_info_length; ) {
BaseProgramDescriptor program_descriptor;
parsed += lengthof(program_descriptor);
}
unsigned int(16) elementary_stream_map_length;
unsigned int stream_map_ct;
for (stream_map_ct=0; stream_map_ct < elementary_stream_map_length; ) {
BaseStreamDescriptor stream_descriptor;
stream_map_ct += lengthof(stream_descriptor);
}
unsigned int(32) CRC_32;
%.c{
void print_error() { printf("Error in PSMapTable! The PES_packet_length is too high!"); } %.c}
%.j{
void print_error() { System.out.println("Error in PSMapTable! The PES_packet_length is too high!"); } %.j}
}
/////////////////
// PSDirectory //
/////////////////
class PSDirectory extends PesBase : const unsigned int(32) st_id = ST_PSDirectory
{
unsigned int(15) number_of_access_units;
bit(1) marker = 0b1;
unsigned int(15) previous_directory_offset_1;
bit(1) marker = 0b1;
unsigned int(15) previous_directory_offset_2;
bit(1) marker = 0b1;
unsigned int(15) previous_directory_offset_3;
bit(1) marker = 0b1;
unsigned int(15) previous_directory_offset_4;
bit(1) marker = 0b1;
unsigned int(15) previous_directory_offset_5;
bit(1) marker = 0b1;
unsigned int(15) previous_directory_offset_6;
bit(1) marker = 0b1;
unsigned int i;
for (i=0; i < number_of_access_units; i++) {
unsigned int(8) packet_stream_id;
int(1) PES_header_position_offset_sign;
unsigned int(14) PES_header_position_offset_1;
bit(1) marker = 0b1;
unsigned int(15) PES_header_position_offset_2;
bit(1) marker = 0b1;
unsigned int(15) PES_header_position_offset_3;
bit(1) marker = 0b1;
unsigned int(16) reference_offset;
bit(1) marker = 0b1;
bit(3) reserved;
unsigned int(3) PTS_1;
bit(1) marker = 0b1;
unsigned int(15) PTS_2;
bit(1) marker = 0b1;
unsigned int(15) PTS_3;
bit(1) marker = 0b1;
unsigned int(15) bytes_to_read;
bit(1) marker = 0b1;
unsigned int(8) bytes_to_read;
bit(1) marker = 0b1;
bit(1) intra_coded_indicator;
bit(2) coding_parameters_indicator;
bit(4) reserved;
}
}
//////////
// Pack //
//////////
class Pack
{
PackHeader pack_header;
while (nextbits(32) >= ST_PSMapTable && nextbits(32) <= ST_PSDirectory)
PesBase pes;
}
////////////////////
// The main class //
////////////////////
class MPEG2PS
{
do {
Pack p;
} while (nextbits(32) == 0x000001BA); // Pack start code
nextcode(aligned(8), 0x000001B9); // PS end code
skipbits(32);
}
|