/*
* 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>
* Chun Hao (Tony) Wang <tony.wang@ee.cooper.edu>
*
*/
/*
* MPEG-1 Video
*
* This example reads MPEG-1 Video streams.
*
*/
%pragma notrace
%import "mpeg1vsmap.fl"
const int PICTURE_START_CODE = 0x00000100;
const int USER_DATA_START_CODE = 0x000001B2;
const int SEQUENCE_HEADER_CODE = 0x000001B3;
const int EXTENSION_START_CODE = 0x000001B5;
const int SEQUENCE_END_CODE = 0x000001B7;
const int GROUP_START_CODE = 0x000001B8;
class Block(int i, int pattern_code, int intra, int picture_coding_type) {
if (pattern_code == 1) {
if (intra == 1) {
if (i < 4) {
int(TableB5a) dct_dc_size_luminance;
if (dct_dc_size_luminance != 0)
unsigned int(dct_dc_size_luminance) dct_dc_differential;
}
else {
int(TableB5b) dct_dc_size_chrominance;
if (dct_dc_size_chrominance != 0)
unsigned int(dct_dc_size_chrominance) dct_dc_differential;
}
}
else {
DCTCoeff(FirstCoeffTable) dct_coeff_first;
if (dct_coeff_first.level == 0) {
unsigned int(8) level_lsb;
dct_coeff_first.level = level_lsb;
}
else if (dct_coeff_first.level == -128) {
unsigned int(8) level_lsb;
dct_coeff_first.level = level_lsb - 256;
}
}
if (picture_coding_type != 4) {
while (nextbits(2) != 0b10) {
DCTCoeff(NextCoeffTable) dct_coeff_next;
if (dct_coeff_next.level == 0) {
unsigned int(8) level_lsb;
dct_coeff_next.level = level_lsb;
}
else if (dct_coeff_next.level == -128) {
unsigned int(8) level_lsb;
dct_coeff_next.level = level_lsb - 256;
}
}
bit(2) end_of_block = 0b10;
}
}
}
class Macroblock(int forward_f_code, int backward_f_code, int picture_coding_type) {
while (nextbits(11) == 0b0000.0001.111)
skipbits(11); // Skip stuffing bits
while (nextbits(11) == 0b0000.0001.000)
skipbits(11); // Skip escape bits
int(TableB1) macroblock_address_increment;
switch (picture_coding_type) {
case 0b001: // Intra-coded (I)
MacroblockTypes(TableB2a) macroblock_type;
break;
case 0b010: // Predictive-coded (P)
MacroblockTypes(TableB2b) macroblock_type;
break;
case 0b011: // Bidirectionally-predictive-coded (B)
MacroblockTypes(TableB2c) macroblock_type;
break;
case 0b100: // DC intra_coded (D)
MacroblockTypes(TableB2d) macroblock_type;
break;
}
if (macroblock_type.quant != 0)
bit(5) quantizer_scale;
if (macroblock_type.motion_forward != 0) {
int(TableB4) motion_horizontal_forward_code;
if ((1<<(forward_f_code-1)) != 1 && motion_horizontal_forward_code != 0)
bit(forward_f_code-1) motion_horizontal_forward_r;
int(TableB4) motion_vertical_forward_code;
if ((1<<(forward_f_code-1)) != 1 && motion_vertical_forward_code != 0)
bit(forward_f_code-1) motion_vertical_forwrad_r;
}
if (macroblock_type.motion_backward != 0) {
int(TableB4) motion_horizontal_backward_code;
if ((1<<(backward_f_code-1)) != 1 && motion_horizontal_backward_code != 0)
bit(backward_f_code-1) motion_horizontal_forward_r;
int(TableB4) motion_vertical_backward_code;
if ((1<<(backward_f_code-1)) != 1 && motion_vertical_backward_code != 0)
bit(backward_f_code-1) motion_vertical_backward_r;
}
int i;
int pattern_code[6] = (macroblock_type.intra != 0) ? 1 : 0;
if (macroblock_type.pattern != 0) {
int(TableB3) coded_block_pattern;
for (i=0; i<6; i++)
if ((coded_block_pattern & (1<<(5-i))) != 0) pattern_code[i] = 1;
}
for (i=0; i<6; i++)
Block b(i, pattern_code[i], macroblock_type.intra, picture_coding_type);
if (picture_coding_type == 4)
bit(1) end_of_macroblock = 0b1;
}
class Slice(int forward_f_code, int backward_f_code, int picture_coding_type) {
bit(32) slice_start_code = 0x00000101 .. 0x000001AF;
bit(5) quantizer_scale;
while (nextbits(1) == 0b1) {
bit(1) extra_bit_slice = 0b1;
bit(8) extra_information_slice;
}
bit(1) extra_bit_slice = 0b0;
do {
Macroblock m(forward_f_code, backward_f_code, picture_coding_type);
} while(nextbits(23) != 0);
nextcode(aligned(8), 0x000001);
}
%pragma trace
class Picture {
bit(32) picture_start_code = PICTURE_START_CODE;
bit(10) temporal_reference;
bit(3) picture_coding_type;
bit(16) vbv_delay;
if (picture_coding_type == 2 || picture_coding_type == 3) {
bit(1) full_pel_forward_vector;
bit(3) forward_f_code;
}
if (picture_coding_type == 3) {
bit(1) full_pel_backward_vector;
bit(3) backward_f_code;
}
while (nextbits(1) == 0b1) {
bit(1) extra_bit_picture = 0b1;
bit(8) extra_information_picture;
}
bit(1) extra_bit_picture = 0b0;
nextcode(aligned(8), 0x000001);
if (nextbits(32) == EXTENSION_START_CODE) {
bit(32) extension_start_code = EXTENSION_START_CODE;
// We are skipping picture_extension_data
nextcode(aligned(8), 0x000001);
}
if (nextbits(32) == USER_DATA_START_CODE) {
bit(32) extension_start_code = USER_DATA_START_CODE;
// We are skipping user_data
nextcode(aligned(8), 0x000001);
}
do {
Slice s(forward_f_code, backward_f_code, picture_coding_type);
} while(nextbits(32) >= 0x00000101 && nextbits(32) <= 0x000001AF);
}
class GroupOfPictures {
bit(32) group_start_code = GROUP_START_CODE;
bit(25) time_code;
bit(1) closed_gop;
bit(1) broken_link;
nextcode(aligned(8), 0x000001);
if (nextbits(32) == EXTENSION_START_CODE) {
bit(32) extension_start_code = EXTENSION_START_CODE;
// We are skipping group_extension_data
nextcode(aligned(8), 0x000001);
}
if (nextbits(32) == USER_DATA_START_CODE) {
bit(32) extension_start_code = USER_DATA_START_CODE;
// We are skipping user_data
nextcode(aligned(8), 0x000001);
}
while(nextbits(32) == PICTURE_START_CODE)
Picture p;
}
class SequenceHeader {
int i;
bit(32) sequence_header_code = SEQUENCE_HEADER_CODE;
bit(12) horizontal_size;
bit(12) vertical_size;
bit(4) pel_aspect_ratio;
bit(4) picture_rate;
bit(18) bit_rate;
bit(1) marker_bit = 0b1;
bit(10) vbv_buffer_size;
bit(1) constrained_parameters_flag;
bit(1) load_intra_quantizer_matrix;
if (load_intra_quantizer_matrix != 0)
bit(8) intra_quantizer_matrix[64];
bit(1) load_non_intra_quantizer_matrix;
if (load_non_intra_quantizer_matrix != 0)
bit(8) non_intra_quantizer_matrix[64];
nextcode(aligned(8), 0x000001);
if (nextbits(32) == EXTENSION_START_CODE) {
bit(32) extension_start_code = EXTENSION_START_CODE;
// We are skipping sequence_extension_data
nextcode(aligned(8), 0x000001);
}
if (nextbits(32) == USER_DATA_START_CODE) {
bit(32) user_data_start_code = USER_DATA_START_CODE;
// We are skipping user_data
nextcode(aligned(8), 0x000001);
}
}
////////////////////
// The main class //
////////////////////
class MPEG1Video {
nextcode(aligned(8), 0x000001);
do {
SequenceHeader sh;
do {
GroupOfPictures gp;
} while (nextbits(32) == GROUP_START_CODE);
} while (nextbits(32) == SEQUENCE_HEADER_CODE);
bit(32) sequence_end_code = SEQUENCE_END_CODE;
}
|