/* * Copyright 2005 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. */ /** * @description * This file contains functions that allow one to parse MPEG-2 compliant video. * The code is based on the MPEG-2 specification (ISO/IEC 13818-2). The MPEG-2 decoding * is a work in progress, although it works within a limited test range. Throughout the * source code, citations are made in cases where an understanding of the code would be * helped by looking at an outside source. The format I have chosen is * (cite NUM#, LOOKUP_INFO). NUM=1 refers to ISO/IEC: 13818-2, and NUM=2 refers to the reference * MPEG implementation written in C, available at [www.mpeg.org]. * * @author Matthew Drake * @file Parser.str.pre * @version 1.0 */ /** * Performs variable length decoding on an MPEG-2 compliant bit stream in accordance * with the IEEE MPEG-2 specification. * @param UpdatePortal_quantiser_data_ac The portal that recieves AC quantiser coefficient table data * @param UpdatePortal_quantiser_data_dc The portal that recieves DC quantiser coefficient table data * @param UpdatePortal_macroblock_intra The portal that receives intra macroblock information * @param UpdatePortal_picture_type The portal that receives picture type information * @param UpdatePortal_mvd The portal that needs to be notified about motion vector resets * @param UpdatePortal_picture_type2 The portal that receives picture type information * @input An MPEG-2 variable length encoded bitstream * @output A series of variable length decoded macroblocks with associated motion vectors * and messages interleaved on parser phase boundaries with updates to the state of * the decoded data. */ bit->int filter MPEGStreamParser(portal UpdatePortal_quantiser_data_ac, portal UpdatePortal_quantiser_data_dc, portal UpdatePortal_macroblock_intra, portal UpdatePortal_picture_type, portal UpdatePortal_mvd, portal UpdatePortal_picture_type2, portal UpdatePortal_picture_type3, int width, int height, int the_chroma_format) { // FEATURETODO // When helper functions can express their I/O rates as a function // of their parameters, get rid of this definition and uncomment // the definition in the filter work function, and change the // phase PushMacroblock() to use the parameter. int b_per_m = blocks_per_macroblock[the_chroma_format]; int[12][64] QFS; // Should be b_per_m, but b_per_m gets assigned later for some reason. int picture_coding_type; int macroblock_intra; int macroblock_motion_forward; int macroblock_motion_backward; int[2][2][2] motion_code; int[2][2][2] motion_residual; int next_cfg_node; int extension_start_code_identifier; int chroma_format; int block_count; int mb_width; int vertical_size; boolean sequence_end_code_not_found; boolean picture_or_group_start_code_found; int[2][2] f_code; int frame_pred_frame_dct; int picture_structure; int concealment_motion_vectors; int intra_vlc_format; boolean slice_start_code_follows; int previous_macroblock_address; int quantiser_scale_code; int[3] dc_dct_pred; // (cite 1, P.64-65) boolean macroblock_next; int macroblock_address_increment; int num_skipped_macroblocks; int i; int j; int k; init { next_cfg_node = 0; } void PushMacroblock() push (b_per_m*64+19) { for (int i = 0; i < blocks_per_macroblock[the_chroma_format]; i++) { for (int j = 0; j < 64; j++) { push(QFS[i][j]); } } for (int r = 0; r < 2; r++) for (int s = 0; s < 2; s++) for (int t = 0; t < 2; t++) { push(motion_code[r][s][t]); } for (int r = 0; r < 2; r++) for (int s = 0; s < 2; s++) for (int t = 0; t < 2; t++) { push(motion_residual[r][s][t]); } push(macroblock_intra); push(macroblock_motion_forward); push(macroblock_motion_backward); } work pop * push (b_per_m*64+19) { // Actually unknown pop/push rate int tempval = 0; boolean pushedMacroblock = false; while (pushedMacroblock == false) { if (next_cfg_node == 0) { println("Parsing M2V File..."); // video_sequence() (cite 1, P. 25) { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } // sequence_header() (cite 1, P. 26) tempval = 0; for (int pops_i = 0; pops_i < (32-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval != 0x000001B3) println("Error - Expected Video Sequence Start Code, Found " + tempval); // Reading Sequence Header int horizontal_size_value; int vertical_size_value; int aspect_ratio_information; int frame_rate_code; int bit_rate_value; int vbv_buffer_size_value; int constrained_parameters_flag; int load_intra_quantiser_matrix; int load_non_intra_quantiser_matrix; float frame_rate_value; int[64] intra_quantiser_matrix; int[64] non_intra_quantiser_matrix; // (cite 1, P.55) horizontal_size_value = 0; for (int pops_i = 0; pops_i < (12-1); pops_i++) { horizontal_size_value += pop(); horizontal_size_value <<= 1; } horizontal_size_value += pop(); vertical_size_value = 0; for (int pops_i = 0; pops_i < (12-1); pops_i++) { vertical_size_value += pop(); vertical_size_value <<= 1; } vertical_size_value += pop(); aspect_ratio_information = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { aspect_ratio_information += pop(); aspect_ratio_information <<= 1; } aspect_ratio_information += pop(); // (cite 1, P.41 Table 6-3) if (aspect_ratio_information == 0) println("Error - Forbidden Aspect Ratio"); else if (aspect_ratio_information == 1) { // aspect_ratio_information == 1 -> aspect ratio is 1:1, this case is handled } else { println("Error - Program Limitation: Don't Know How to Handle Other Aspect Ratios"); println(" correct mpeg2enc parameter: 1 /* aspect_ratio_information 1=square pel, 2=4:3, 3=16:9, 4=2.11:1 */"); } frame_rate_code = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { frame_rate_code += pop(); frame_rate_code <<= 1; } frame_rate_code += pop(); // (cite 1, P.41-42 Table 6-4) frame_rate_value = 0; if (frame_rate_code == 0) println("Error - Forbidden Frame Rate Code"); else if (frame_rate_code == 4) { // frame_rate_code 4 frame_rate_value = 30000.0/1001.0; } else { println("Error - Program Limitation: Don't Know How to Handle Other Frame Rate Codes"); println(" correct mpeg2enc parameter: 4 /* frame_rate_code 1=23.976, 2=24, 3=25, 4=29.97, 5=30 frames/sec. */"); } bit_rate_value = 0; for (int pops_i = 0; pops_i < (18-1); pops_i++) { bit_rate_value += pop(); bit_rate_value <<= 1; } bit_rate_value += pop(); { int marker_bit; marker_bit = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { marker_bit += pop(); marker_bit <<= 1; } marker_bit += pop(); if (marker_bit != 1) print("Error - Expected Marker Bit To Be Set"); } vbv_buffer_size_value = 0; for (int pops_i = 0; pops_i < (10-1); pops_i++) { vbv_buffer_size_value += pop(); vbv_buffer_size_value <<= 1; } vbv_buffer_size_value += pop(); constrained_parameters_flag = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { constrained_parameters_flag += pop(); constrained_parameters_flag <<= 1; } constrained_parameters_flag += pop(); // (cite 1, P. 43) if (constrained_parameters_flag != 0) { println("Error - Expected Constrained Parameters Flag To Be 0"); println(" correct mpeg2enc parameter: 0 /* constrained_parameters_flag */"); } // Default Values for the quantiser_matrices // Assumes no alternate_scan TODO load_intra_quantiser_matrix = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { load_intra_quantiser_matrix += pop(); load_intra_quantiser_matrix <<= 1; } load_intra_quantiser_matrix += pop(); if (load_intra_quantiser_matrix == 1) { // println(" Loading Intra Quantiser Matrix from File"); int[64] tempOrder; for (int i = 0; i < 64; i++) { tempOrder[i] = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { tempOrder[i] += pop(); tempOrder[i] <<= 1; } tempOrder[i] += pop(); } for (int i = 0; i < 64; i++) { // Assumes no alternate_scan TODO intra_quantiser_matrix[i] = tempOrder[ZigZagUnorder[i]]; } } else { // println(" Using Default Intra Quantiser Matrix"); for (int i = 0; i < 64; i++) { intra_quantiser_matrix[i] = default_intra_quantiser_matrix[i]; } } load_non_intra_quantiser_matrix = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { load_non_intra_quantiser_matrix += pop(); load_non_intra_quantiser_matrix <<= 1; } load_non_intra_quantiser_matrix += pop(); if (load_non_intra_quantiser_matrix == 1) { // println(" Loading Non Intra Quantiser Matrix from File"); int[64] tempOrder; for (int i = 0; i < 64; i++) { tempOrder[i] = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { tempOrder[i] += pop(); tempOrder[i] <<= 1; } tempOrder[i] += pop(); } for (int i = 0; i < 64; i++) { // Assumes no alternate_scan non_intra_quantiser_matrix[i] = tempOrder[ZigZagUnorder[i]]; } } else { // println(" Using Default Non Intra Quantiser Matrix"); for (int i = 0; i < 64; i++) { non_intra_quantiser_matrix[i] = default_non_intra_quantiser_matrix[i]; } } UpdatePortal_quantiser_data_ac.setQuantiserMatrices(intra_quantiser_matrix, non_intra_quantiser_matrix) [0:0]; { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } // sequence_extension() (cite 1, P. 28) tempval = 0; for (int pops_i = 0; pops_i < (32-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval != 0x000001B5) { println("Error - Expected Extension Start Code, File is MPEG-1, not MPEG-2 "); println(" correct mpeg2enc parameter: 0 /* ISO/IEC 11172-2 stream */"); } extension_start_code_identifier = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { extension_start_code_identifier += pop(); extension_start_code_identifier <<= 1; } extension_start_code_identifier += pop(); if (extension_start_code_identifier != 0x1) println("Error - Expected Sequence Extension Identifier " + extension_start_code_identifier); int profile_and_level_indication; profile_and_level_indication = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { profile_and_level_indication += pop(); profile_and_level_indication <<= 1; } profile_and_level_indication += pop(); // We don't really care about the profile_and_level indicator - this matters if this implementation // were fully MPEG2 compliant to some profile/level, but it isn't. int progressive_sequence; progressive_sequence = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { progressive_sequence += pop(); progressive_sequence <<= 1; } progressive_sequence += pop(); if (progressive_sequence == 1) { // progressive_sequence 1: allows only progressive frames } else { // progressive_sequence 0: allows interlaced and progressive frames println("Error - Program Limitation: Don't handle interlaced frames"); println(" correct mpeg2enc parameter: 1 /* progressive_sequence */"); } chroma_format = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { chroma_format += pop(); chroma_format <<= 1; } chroma_format += pop(); block_count = blocks_per_macroblock[the_chroma_format]; // (cite 1, P. 62) if (chroma_format != the_chroma_format) { println("Error - Program specified with chroma " + the_chroma_format); println(" File has chroma " + chroma_format); } int horizontal_size_extension; int vertical_size_extension; int bit_rate_extension; int vbv_buffer_size_extension; int low_delay; int bit_rate; int vbv_buffer_size; float frame_rate; int mb_height; int horizontal_size; horizontal_size_extension = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { horizontal_size_extension += pop(); horizontal_size_extension <<= 1; } horizontal_size_extension += pop(); horizontal_size = horizontal_size_value + (horizontal_size_extension << 12); mb_width = (horizontal_size + 15) / 16; vertical_size_extension = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { vertical_size_extension += pop(); vertical_size_extension <<= 1; } vertical_size_extension += pop(); vertical_size = vertical_size_value + (vertical_size_extension << 12); mb_height = (vertical_size + 15) / 16; bit_rate_extension = 0; for (int pops_i = 0; pops_i < (12-1); pops_i++) { bit_rate_extension += pop(); bit_rate_extension <<= 1; } bit_rate_extension += pop(); // (cite 1, P.42) bit_rate = 400 * (bit_rate_value + (bit_rate_extension << 18)); { int marker_bit; marker_bit = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { marker_bit += pop(); marker_bit <<= 1; } marker_bit += pop(); if (marker_bit != 1) print("Error - Expected Marker Bit To Be Set"); } vbv_buffer_size_extension = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { vbv_buffer_size_extension += pop(); vbv_buffer_size_extension <<= 1; } vbv_buffer_size_extension += pop(); vbv_buffer_size = vbv_buffer_size_value + (vbv_buffer_size_extension << 10); low_delay = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { low_delay += pop(); low_delay <<= 1; } low_delay += pop(); if (low_delay == 1) { // low_delay 1 indicates that sequence contains no B-pictures println("Error - Program Limitation: Can't Handle This Case Yet"); println(" correct mpeg2enc parameter: 0 /* low_delay */"); } else { // low_delay 0 indicates that sequence is allowed to contain B-pictures } int frame_rate_extension_n; int frame_rate_extension_d; frame_rate_extension_n = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { frame_rate_extension_n += pop(); frame_rate_extension_n <<= 1; } frame_rate_extension_n += pop(); frame_rate_extension_d = 0; for (int pops_i = 0; pops_i < (5-1); pops_i++) { frame_rate_extension_d += pop(); frame_rate_extension_d <<= 1; } frame_rate_extension_d += pop(); // (cite 1, P. P.41) frame_rate = frame_rate_value * ((float) (frame_rate_extension_n + 1)) / ((float) (frame_rate_extension_d + 1)); { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } sequence_end_code_not_found = true; next_cfg_node = 1; } else if (next_cfg_node == 1) { // assert: sequence_end_code_not_found == true // extension_and_user_data(0) (cite 1, P.26) tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); while (tempval == 0x000001B5 || tempval == 0x000001B2) { tempval = 0; for (int pops_i = 0; pops_i < (32-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval == 0x000001B5) { // extension_data(0) (cite 1, P.27) tempval = 0; for (int peeks_i = 0; peeks_i < (4-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(4-1); if (tempval == 2) { // extension_start_code_identifier int video_format; int color_description; int color_primaries; int transfer_characteristics; int matrix_coefficients; int display_horizontal_size; int display_vertical_size; tempval = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); video_format = 0; for (int pops_i = 0; pops_i < (3-1); pops_i++) { video_format += pop(); video_format <<= 1; } video_format += pop(); color_description = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { color_description += pop(); color_description <<= 1; } color_description += pop(); if (color_description == 1) { color_primaries = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { color_primaries += pop(); color_primaries <<= 1; } color_primaries += pop(); transfer_characteristics = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { transfer_characteristics += pop(); transfer_characteristics <<= 1; } transfer_characteristics += pop(); matrix_coefficients = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { matrix_coefficients += pop(); matrix_coefficients <<= 1; } matrix_coefficients += pop(); } display_horizontal_size = 0; for (int pops_i = 0; pops_i < (14-1); pops_i++) { display_horizontal_size += pop(); display_horizontal_size <<= 1; } display_horizontal_size += pop(); { int marker_bit; marker_bit = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { marker_bit += pop(); marker_bit <<= 1; } marker_bit += pop(); if (marker_bit != 1) print("Error - Expected Marker Bit To Be Set"); } display_vertical_size = 0; for (int pops_i = 0; pops_i < (14-1); pops_i++) { display_vertical_size += pop(); display_vertical_size <<= 1; } display_vertical_size += pop(); // TODO - we don't do anything with this extra data we get out. Eventually we should. { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } } else { println("Error - Program Limitation: Not Yet Support for Sequence Scalable Extension()"); } } else { // user_data() (cite 1, P.27) if (tempval != 0x000001B2) { println("Error - Program Limitation: Not Yet Support for User_Data()"); } tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(24-1); while (tempval != 0x000001) { int user_data; user_data = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { user_data += pop(); user_data <<= 1; } user_data += pop(); // TODO we should probably do something with this data tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(24-1); } { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } } tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); } picture_or_group_start_code_found = true; next_cfg_node = 3; } else if (next_cfg_node == 3) { // assert: picture_or_group_start_code_found == true tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); if (tempval == 0x000001B8) { // group_of_pictures_header() (cite 1, P.29) tempval = 0; for (int pops_i = 0; pops_i < (32-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); // -- Time Code - Not Used in Decoding Process -- // (cite 1, P.49) int drop_frame_flag; int time_code_hours; int time_code_minutes; int time_code_seconds; int time_code_pictures; int closed_gop; int broken_link; drop_frame_flag = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { drop_frame_flag += pop(); drop_frame_flag <<= 1; } drop_frame_flag += pop(); time_code_hours = 0; for (int pops_i = 0; pops_i < (5-1); pops_i++) { time_code_hours += pop(); time_code_hours <<= 1; } time_code_hours += pop(); time_code_minutes = 0; for (int pops_i = 0; pops_i < (6-1); pops_i++) { time_code_minutes += pop(); time_code_minutes <<= 1; } time_code_minutes += pop(); { int marker_bit; marker_bit = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { marker_bit += pop(); marker_bit <<= 1; } marker_bit += pop(); if (marker_bit != 1) print("Error - Expected Marker Bit To Be Set"); } time_code_seconds = 0; for (int pops_i = 0; pops_i < (6-1); pops_i++) { time_code_seconds += pop(); time_code_seconds <<= 1; } time_code_seconds += pop(); time_code_pictures = 0; for (int pops_i = 0; pops_i < (6-1); pops_i++) { time_code_pictures += pop(); time_code_pictures <<= 1; } time_code_pictures += pop(); // -- End of Time Code closed_gop = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { closed_gop += pop(); closed_gop <<= 1; } closed_gop += pop(); broken_link = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { broken_link += pop(); broken_link <<= 1; } broken_link += pop(); if (broken_link == 1) println("Error - Program Limitation: broken_link = 1"); { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } // extension_and_user_data(1) (cite 1, P.26) tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); if (tempval == 0x000001B5 || tempval == 0x000001B2) println("Error - Program Limitation: Not Yet Support for extension_and_user_data(1)"); } // picture_header() (cite 1, P.30) tempval = 0; for (int pops_i = 0; pops_i < (32-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval != 0x00000100) { println("Error - Picture Start Code Expected, " + tempval); } // (cite 1, P.50) for interpretation of the following fields int temporal_reference; temporal_reference = 0; for (int pops_i = 0; pops_i < (10-1); pops_i++) { temporal_reference += pop(); temporal_reference <<= 1; } temporal_reference += pop(); picture_coding_type = 0; for (int pops_i = 0; pops_i < (3-1); pops_i++) { picture_coding_type += pop(); picture_coding_type <<= 1; } picture_coding_type += pop(); if (picture_coding_type == 1) { // picture_coding_type = I-picture } else if (picture_coding_type == 2) { // picture_coding_type = P-picture } else if (picture_coding_type == 3) { // picture_coding_type = B-picture } else { println(" Error: Forbidden picture_coding_type " + picture_coding_type); } UpdatePortal_picture_type.setPictureType(picture_coding_type) [0:0]; UpdatePortal_picture_type2.setPictureType(picture_coding_type) [0:0]; UpdatePortal_picture_type3.setPictureType(picture_coding_type) [0:0]; int vbv_delay; vbv_delay = 0; for (int pops_i = 0; pops_i < (16-1); pops_i++) { vbv_delay += pop(); vbv_delay <<= 1; } vbv_delay += pop(); int full_pel_forward_vector; int forward_f_code; int full_pel_backward_vector; int backward_f_code; // TODO unknown interpretation for vbv_delay, (cite 1, P.50) // The following is not used by the MPEG-2 specification (cite 1, P.51) // Supposed to have certain values, but not guaranteed for most files. if (picture_coding_type == 2 || picture_coding_type == 3) { full_pel_forward_vector = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { full_pel_forward_vector += pop(); full_pel_forward_vector <<= 1; } full_pel_forward_vector += pop(); forward_f_code = 0; for (int pops_i = 0; pops_i < (3-1); pops_i++) { forward_f_code += pop(); forward_f_code <<= 1; } forward_f_code += pop(); } if (picture_coding_type == 3) { full_pel_backward_vector = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { full_pel_backward_vector += pop(); full_pel_backward_vector <<= 1; } full_pel_backward_vector += pop(); backward_f_code = 0; for (int pops_i = 0; pops_i < (3-1); pops_i++) { backward_f_code += pop(); backward_f_code <<= 1; } backward_f_code += pop(); } tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval == 1) println("Error: File conforms to some superset of the MPEG-2 specification"); { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } // picture_coding_extension() (cite 1, P.30) tempval = 0; for (int pops_i = 0; pops_i < (32-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval != 0x000001B5) println("Error - Expecting extension start code " + tempval); extension_start_code_identifier = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { extension_start_code_identifier += pop(); extension_start_code_identifier <<= 1; } extension_start_code_identifier += pop(); if (extension_start_code_identifier != 0x8) println("Error - Expecting picture coding extension ID " + extension_start_code_identifier); f_code[0][0] = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { f_code[0][0] += pop(); f_code[0][0] <<= 1; } f_code[0][0] += pop(); f_code[0][1] = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { f_code[0][1] += pop(); f_code[0][1] <<= 1; } f_code[0][1] += pop(); f_code[1][0] = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { f_code[1][0] += pop(); f_code[1][0] <<= 1; } f_code[1][0] += pop(); f_code[1][1] = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { f_code[1][1] += pop(); f_code[1][1] <<= 1; } f_code[1][1] += pop(); UpdatePortal_mvd.setFCode(f_code) [0:0]; // (cite 1, P.51) for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { if (f_code[i][j] == 0 || (f_code[i][j] >= 10 && f_code[i][j] <= 14)) println("Error - Invalid f_code"); if (picture_coding_type == 1 && f_code[i][j] != 0xF) println("Error - Program Limitation: I-frame has motion prediction"); if (picture_coding_type == 2 && f_code[1][j] != 0xF) println("Error - Program Limitation: P-frame has backward motion prediction"); } } int intra_dc_precision; int top_field_first; int q_scale_type; int alternate_scan; int repeat_first_field; int chroma_420_type; int progressive_frame; int composite_display_flag; int actual_intra_dc_precision; intra_dc_precision = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { intra_dc_precision += pop(); intra_dc_precision <<= 1; } intra_dc_precision += pop(); UpdatePortal_quantiser_data_dc.setIntraDCPrecision(intra_dc_precision); actual_intra_dc_precision = intra_dc_precision + 8; picture_structure = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { picture_structure += pop(); picture_structure <<= 1; } picture_structure += pop(); if (picture_structure != 3) println("Error - Program Limitation: Interlaced or bad picture structure"); top_field_first = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { top_field_first += pop(); top_field_first <<= 1; } top_field_first += pop(); // Interpreted Later frame_pred_frame_dct = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { frame_pred_frame_dct += pop(); frame_pred_frame_dct <<= 1; } frame_pred_frame_dct += pop(); if (frame_pred_frame_dct != 1) println("Error - Program Limitation or Bad Syntax: frame_pred_frame_dct must be 1"); concealment_motion_vectors = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { concealment_motion_vectors += pop(); concealment_motion_vectors <<= 1; } concealment_motion_vectors += pop(); q_scale_type = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { q_scale_type += pop(); q_scale_type <<= 1; } q_scale_type += pop(); UpdatePortal_quantiser_data_ac.setQScaleType(q_scale_type) [0:0]; intra_vlc_format = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { intra_vlc_format += pop(); intra_vlc_format <<= 1; } intra_vlc_format += pop(); alternate_scan = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { alternate_scan += pop(); alternate_scan <<= 1; } alternate_scan += pop(); if (alternate_scan == 1) println("Error - Program Limitation - Doesn't handle alternate_scan right now"); repeat_first_field = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { repeat_first_field += pop(); repeat_first_field <<= 1; } repeat_first_field += pop(); // TODO Assumes progressive_sequence = 1 if (repeat_first_field == 0) { // repeat_first_field = 0, one frame output } else { if (top_field_first == 0) println(" repeat_first_field = 1, top_field_first = 0, two frames output"); else println(" repeat_first_field = 1, top_field_first = 1, three frames output"); } chroma_420_type = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { chroma_420_type += pop(); chroma_420_type <<= 1; } chroma_420_type += pop(); // We don't really care about this, although it should be 1 for 4:2:0 chroma. // (cite 1, P.53) progressive_frame = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { progressive_frame += pop(); progressive_frame <<= 1; } progressive_frame += pop(); // Again, I don't think we care too much about this value, since we assume only a // base stream exists. composite_display_flag = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { composite_display_flag += pop(); composite_display_flag <<= 1; } composite_display_flag += pop(); if (composite_display_flag == 1) { println("Error - Program Limitation: Assumes no composite display information"); } else { // composite_display_flag - not present } { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } // extension_and_user_data(2) tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); if (tempval == 0x000001B5 || tempval == 0x000001B2) println("Error - Program Limitation: Not Yet Support for extension_and_user_data(2)"); // picture_data() (cite 1, P.34) slice_start_code_follows = true; previous_macroblock_address = -1; next_cfg_node = 5; } else if (next_cfg_node == 5) { // assert: slice_start_code_follows == true // slice() (cite 1, P.34) // Reset motion vector predictors, (cite 1, P.77-80) UpdatePortal_mvd.resetPredictors() [0:0]; tempval = 0; for (int pops_i = 0; pops_i < (24-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval != 0x000001) println("Error - Expecting slice_start_code " + tempval); int slice_vertical_position; slice_vertical_position = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { slice_vertical_position += pop(); slice_vertical_position <<= 1; } slice_vertical_position += pop(); if (slice_vertical_position < 0x01 || slice_vertical_position > 0xAF) println("Error - Invalid slice_vertical_position" + slice_vertical_position); if (vertical_size > 2800) println("Error - Program Limitation: Doesn't handle vertical_sizes > 2800"); int mb_row; mb_row = slice_vertical_position - 1; previous_macroblock_address = (mb_row * mb_width) - 1; quantiser_scale_code = 0; for (int pops_i = 0; pops_i < (5-1); pops_i++) { quantiser_scale_code += pop(); quantiser_scale_code <<= 1; } quantiser_scale_code += pop(); UpdatePortal_quantiser_data_ac.setQuantiserScaleCode(quantiser_scale_code) [0:0]; tempval = 0; for (int peeks_i = 0; peeks_i < (1-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(1-1); if (tempval == 1) println("Error - Program Limitation: Doesn't handle intra_slice_flag"); tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval == 1) println("Error - Extra_bit_slice must be 0"); // I'm not sure about this - see P. 64 and getpic.c Line 1180 // they disagree TODO dc_dct_pred[0] = 0; // (int) pow(2,actual_intra_dc_precision - 1); dc_dct_pred[1] = 0; // (int) pow(2,actual_intra_dc_precision - 1); dc_dct_pred[2] = 0; // (int) pow(2,actual_intra_dc_precision - 1); macroblock_next = true; next_cfg_node = 7; } else if (next_cfg_node == 7) { // assert: macroblock_next == true // macroblock() (cite 1, P.35) int macroblock_escape; macroblock_escape = 0; tempval = 0; for (int peeks_i = 0; peeks_i < (11-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(11-1); while (tempval == 8) { tempval = 0; for (int pops_i = 0; pops_i < (11-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); macroblock_escape += 33; tempval = 0; for (int peeks_i = 0; peeks_i < (11-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(11-1); } { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { tempval = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_macroblock_address_inc_len) { if (tempval == const_macroblock_address_inc[tablepos].code && guesslength == const_macroblock_address_inc[tablepos].len) { found = true; tempval = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); } else { tablepos++; } } guesslength++; } tempval = const_macroblock_address_inc[tablepos].value; } macroblock_address_increment = tempval + macroblock_escape; if (macroblock_address_increment > 1) next_cfg_node = 8; else next_cfg_node = 12; } else if (next_cfg_node == 8) { num_skipped_macroblocks = macroblock_address_increment - 1; for (int i = 0; i < blocks_per_macroblock[the_chroma_format]; i++) { for (int j = 0; j < 64; j++) { QFS[i][j] = 0; } } for (int r = 0; r < 2; r++) for (int s = 0; s < 2; s++) for (int t = 0; t < 2; t++) { motion_code[r][s][t] = 0; } for (int r = 0; r < 2; r++) for (int s = 0; s < 2; s++) for (int t = 0; t < 2; t++) { motion_residual[r][s][t] = 0; } if (picture_coding_type == 2) { // [cite 1, P. 80] // UpdatePortal_mvd.resetPredictors() [0:0]; } macroblock_intra = 0; macroblock_motion_forward = 0; macroblock_motion_backward = 0; k = 0; next_cfg_node = 9; } else if (next_cfg_node == 9) { // assert: k < num_skipped_macroblocks PushMacroblock(); pushedMacroblock = true; k++; if (k < num_skipped_macroblocks) next_cfg_node = 9; else next_cfg_node = 12; } else if (next_cfg_node == 12) { int macroblock_address; macroblock_address = previous_macroblock_address + macroblock_address_increment; previous_macroblock_address = macroblock_address; int mb_column; mb_column = macroblock_address % mb_width; // TODO - Don't actually check to make sure that macroblocks are skipped which aren't // allowed to be skipped - this should be done, the rules are on (cite 1, P.60) // macroblock_modes, (cite 1, P.36) // TODO - If a sequence_scalable_extension present in bitstream, then may possibly // need to use tables B5,6,7,8 as well. if (picture_coding_type == 1) { // I-picture { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { tempval = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_macroblock_type_Ipictures_len) { if (tempval == const_macroblock_type_Ipictures[tablepos].code && guesslength == const_macroblock_type_Ipictures[tablepos].len) { found = true; tempval = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); } else { tablepos++; } } guesslength++; } tempval = const_macroblock_type_Ipictures[tablepos].value; } } else if (picture_coding_type == 2) { // P-picture { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { tempval = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_macroblock_type_Ppictures_len) { if (tempval == const_macroblock_type_Ppictures[tablepos].code && guesslength == const_macroblock_type_Ppictures[tablepos].len) { found = true; tempval = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); } else { tablepos++; } } guesslength++; } tempval = const_macroblock_type_Ppictures[tablepos].value; } } else if (picture_coding_type == 3) { // B-picture { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { tempval = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_macroblock_type_Bpictures_len) { if (tempval == const_macroblock_type_Bpictures[tablepos].code && guesslength == const_macroblock_type_Bpictures[tablepos].len) { found = true; tempval = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); } else { tablepos++; } } guesslength++; } tempval = const_macroblock_type_Bpictures[tablepos].value; } } int spatial_temporal_weight_code_flag; int macroblock_quant; int macroblock_pattern; spatial_temporal_weight_code_flag = tempval & 0x01; tempval >>= 1; macroblock_intra = tempval & 0x01; UpdatePortal_macroblock_intra.setMacroblockIntra(macroblock_intra) [0:0]; tempval >>= 1; macroblock_pattern = tempval & 0x01; tempval >>= 1; macroblock_motion_backward = tempval & 0x01; tempval >>= 1; macroblock_motion_forward = tempval & 0x01; tempval >>= 1; macroblock_quant = tempval & 0x01; if (spatial_temporal_weight_code_flag == 1) println("Error - Program Limitation - Expects spatial_temporal_weight_code_flag to be 0"); // (cite 1, P.60, Table 6-17) int prediction_type; prediction_type = 0; // 0 = reserved, 1 = field-based, 2=frame-based, 3=dual-prime int motion_vector_count; motion_vector_count = 0; int mv_format; mv_format = 0; // 0 = field, 1 = frame int dmv; dmv = 0; if (frame_pred_frame_dct == 1) { // See comments on P.60 regarding what happens if frame_motion_type // is omitted. prediction_type = 2; motion_vector_count = 1; mv_format = 1; dmv = 0; } if (macroblock_motion_forward == 1 || macroblock_motion_backward == 1) { if (picture_structure == 3) { if (frame_pred_frame_dct == 0) { // (cite 1, P.60, Table 6-17) tempval = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval == 0) { println("Error - Invalid frame_motion_type code"); } else if (tempval == 1) { if (spatial_temporal_weight_code_flag < 2) { println("Error - Don't handle this case of frame_motion_type"); } else { println("Error - Don't handle this case of frame_motion_type"); } } else if (tempval == 2) { prediction_type = 2; motion_vector_count = 1; mv_format = 1; dmv = 0; } else if (tempval == 3) { prediction_type = 3; motion_vector_count = 1; mv_format = 0; dmv = 1; } if (prediction_type == 0) println("Error - Invalid prediction_type"); else if (prediction_type == 1) println(" prediction_type field-based"); else if (prediction_type == 2) println(" prediction_type frame-based"); else if (prediction_type == 3) println(" prediction_type dual-prime"); println(" motion_vector_count " + motion_vector_count); if (mv_format == 0) println(" mv_format field"); else println(" mv_format frame"); println(" dmv " + dmv); } } else { println("Error - Program Limitation: Doesn't handle this case"); } } if ((picture_structure == 3) && (frame_pred_frame_dct == 0) && ((macroblock_intra == 1) || (macroblock_pattern == 1))) println("Error - Program Limitation, Doesn't Handle This Particular Case"); if (macroblock_quant == 1) { quantiser_scale_code = 0; for (int pops_i = 0; pops_i < (5-1); pops_i++) { quantiser_scale_code += pop(); quantiser_scale_code <<= 1; } quantiser_scale_code += pop(); UpdatePortal_quantiser_data_ac.setQuantiserScaleCode(quantiser_scale_code) [0:0]; } /* int[2][2][2] motion_code; int[2][2][2] motion_residual; FEATURETODO */ for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) { motion_code[i][j][k] = 0; motion_residual[i][j][k] = 0; } // Motion Vector Predictor Reset, (cite 1, P.80) if ((macroblock_intra == 1 && concealment_motion_vectors == 0) || (macroblock_intra == 0 && macroblock_motion_forward == 0 && picture_coding_type == 2)) { UpdatePortal_mvd.resetPredictors() [0:0]; } if (macroblock_motion_forward == 1 || (macroblock_intra == 1 && concealment_motion_vectors == 1)) { // motion_vectors(0); (cite 1, P.36, 61) if (motion_vector_count == 1) { if ((mv_format == 0) && (dmv != 1)) { println("Error - Program Limitation: Don't handle this case with mv_format and dmv."); println("mv_format " + mv_format + " dmv " + dmv); } // motion_vector(0,0); // (cite 1, P.61) for (int t = 0; t < 2; t++) { { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { motion_code[0][0][t] = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { motion_code[0][0][t] += peek(peeks_i); motion_code[0][0][t] <<= 1; } motion_code[0][0][t] += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_motion_code_len) { if (motion_code[0][0][t] == const_motion_code[tablepos].code && guesslength == const_motion_code[tablepos].len) { found = true; motion_code[0][0][t] = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { motion_code[0][0][t] += pop(); motion_code[0][0][t] <<= 1; } motion_code[0][0][t] += pop(); } else { tablepos++; } } guesslength++; } motion_code[0][0][t] = const_motion_code[tablepos].value; } if ((f_code[0][t] != 1) && (motion_code[0][0][t] != 0)) { int r_size = f_code[0][t]-1; motion_residual[0][0][t] = 0; for (int pops_i = 0; pops_i < (r_size-1); pops_i++) { motion_residual[0][0][t] += pop(); motion_residual[0][0][t] <<= 1; } motion_residual[0][0][t] += pop(); } if (dmv == 1) { println("Error - Program Limitation: Don't handle case of dmv = 1"); } } } else { println("Error - Program Limitation: Don't handle field motion vectors"); } } if (macroblock_motion_backward == 1) { // motion_vectors(1); (cite 1, P.36, 61) if (motion_vector_count == 1) { if ((mv_format == 0) && (dmv != 1)) { println("Error - Program Limitation: Don't handle this case with mv_format and dmv."); println("mv_format " + mv_format + " dmv " + dmv); } // motion_vector(0,1); // (cite 1, P.61) for (int t = 0; t < 2; t++) { { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { motion_code[0][1][t] = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { motion_code[0][1][t] += peek(peeks_i); motion_code[0][1][t] <<= 1; } motion_code[0][1][t] += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_motion_code_len) { if (motion_code[0][1][t] == const_motion_code[tablepos].code && guesslength == const_motion_code[tablepos].len) { found = true; motion_code[0][1][t] = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { motion_code[0][1][t] += pop(); motion_code[0][1][t] <<= 1; } motion_code[0][1][t] += pop(); } else { tablepos++; } } guesslength++; } motion_code[0][1][t] = const_motion_code[tablepos].value; } if ((f_code[1][t] != 1) && (motion_code[0][1][t] != 0)) { int r_size = f_code[1][t]-1; motion_residual[0][1][t] = 0; for (int pops_i = 0; pops_i < (r_size-1); pops_i++) { motion_residual[0][1][t] += pop(); motion_residual[0][1][t] <<= 1; } motion_residual[0][1][t] += pop(); } if (dmv == 1) { println("Error - Program Limitation: Don't handle the case of dmv = 1"); } } } } if (macroblock_intra == 1 && concealment_motion_vectors == 1) { { int marker_bit; marker_bit = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { marker_bit += pop(); marker_bit <<= 1; } marker_bit += pop(); if (marker_bit != 1) print("Error - Expected Marker Bit To Be Set"); } } // The meaning of pattern_code is defined somewhat poorly // on (cite 1, P.62) in the code block int[12] pattern_code; for (int i = 0; i < 12; i++) { if (macroblock_intra == 1) { pattern_code[i] = 1; } else { pattern_code[i] = 0; } } if (macroblock_pattern == 1) { // coded_block_pattern() (cite 1, P.37, 62) int cbp; { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { cbp = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { cbp += peek(peeks_i); cbp <<= 1; } cbp += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_coded_block_patterns_len) { if (cbp == const_coded_block_patterns[tablepos].code && guesslength == const_coded_block_patterns[tablepos].len) { found = true; cbp = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { cbp += pop(); cbp <<= 1; } cbp += pop(); } else { tablepos++; } } guesslength++; } cbp = const_coded_block_patterns[tablepos].value; } for (int i = 0; i < 6; i++) { if ((cbp & (1 << (5-i))) > 0) pattern_code[i] = 1; } if (chroma_format == 1 && cbp == 0) { println("Error - cbp not allowed to be zero in 4:2:0 format"); } if (chroma_format == 2) { int coded_block_pattern_1; coded_block_pattern_1 = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { coded_block_pattern_1 += pop(); coded_block_pattern_1 <<= 1; } coded_block_pattern_1 += pop(); for (int i = 6; i < 8; i++) { if ((coded_block_pattern_1 & (1<< (7-i))) > 0) pattern_code[i] = 1; } } if (chroma_format == 3) { println("Error - Program Limitation: Doesn't handle 4:4:4 format"); } } for (int i = 0; i < block_count; i++) { int QFS_current; QFS_current = 0; for (int j = 0; j < 64; j++) { QFS[i][j] = 0; } // block(i) (cite 1, P.38) // if macroblocks are skipped, predictor is reset if (pattern_code[i] == 1) { if (macroblock_intra == 1) { int dct_diff; int half_range; if (i < 4) { int dc_dct_size_luminance; int dc_dct_differential_luminance; int dc_dct_luminance; { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { dc_dct_size_luminance = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { dc_dct_size_luminance += peek(peeks_i); dc_dct_size_luminance <<= 1; } dc_dct_size_luminance += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_dct_dc_size_luminance_len) { if (dc_dct_size_luminance == const_dct_dc_size_luminance[tablepos].code && guesslength == const_dct_dc_size_luminance[tablepos].len) { found = true; dc_dct_size_luminance = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { dc_dct_size_luminance += pop(); dc_dct_size_luminance <<= 1; } dc_dct_size_luminance += pop(); } else { tablepos++; } } guesslength++; } dc_dct_size_luminance = const_dct_dc_size_luminance[tablepos].value; } // This next section from (cite 1, P.65) if (dc_dct_size_luminance == 0) { dct_diff = 0; } else { dc_dct_differential_luminance = 0; for (int pops_i = 0; pops_i < (dc_dct_size_luminance-1); pops_i++) { dc_dct_differential_luminance += pop(); dc_dct_differential_luminance <<= 1; } dc_dct_differential_luminance += pop(); half_range = (int) pow(2,dc_dct_size_luminance-1); if (dc_dct_differential_luminance >= half_range) { dct_diff = dc_dct_differential_luminance; } else { dct_diff = (dc_dct_differential_luminance + 1) - (2*half_range); } } dc_dct_luminance = dc_dct_pred[0] + dct_diff; dc_dct_pred[0] = dc_dct_luminance; QFS[i][0] = dc_dct_luminance; QFS_current = 1; } else { int dc_dct_size_chrominance; int dc_dct_differential_chrominance; int dc_dct_chrominance; // Other ones { boolean found = false; int guesslength = 1; int tablepos = 0; while (!found) { dc_dct_size_chrominance = 0; for (int peeks_i = 0; peeks_i < (guesslength-1); peeks_i++) { dc_dct_size_chrominance += peek(peeks_i); dc_dct_size_chrominance <<= 1; } dc_dct_size_chrominance += peek(guesslength-1); tablepos = 0; while (!found && tablepos < const_dct_dc_size_chrominance_len) { if (dc_dct_size_chrominance == const_dct_dc_size_chrominance[tablepos].code && guesslength == const_dct_dc_size_chrominance[tablepos].len) { found = true; dc_dct_size_chrominance = 0; for (int pops_i = 0; pops_i < (guesslength-1); pops_i++) { dc_dct_size_chrominance += pop(); dc_dct_size_chrominance <<= 1; } dc_dct_size_chrominance += pop(); } else { tablepos++; } } guesslength++; } dc_dct_size_chrominance = const_dct_dc_size_chrominance[tablepos].value; } if (dc_dct_size_chrominance == 0) { dct_diff = 0; } else { dc_dct_differential_chrominance = 0; for (int pops_i = 0; pops_i < (dc_dct_size_chrominance-1); pops_i++) { dc_dct_differential_chrominance += pop(); dc_dct_differential_chrominance <<= 1; } dc_dct_differential_chrominance += pop(); half_range = (int) pow(2,dc_dct_size_chrominance-1); if (dc_dct_differential_chrominance >= half_range) { dct_diff = dc_dct_differential_chrominance; } else { dct_diff = (dc_dct_differential_chrominance + 1) - (2*half_range); } } // Blocks 4, 6, 8, and 10 go into [1] // Blocks 5, 7, 9, 11 go into [2] int temp_index; temp_index = (i % 2) + 1; dc_dct_chrominance = dc_dct_pred[temp_index] + dct_diff; dc_dct_pred[temp_index] = dc_dct_chrominance; QFS[i][0] = dc_dct_chrominance; QFS_current = 1; } } else { // I don't think we really need to do anything here... if we let this just // fall through it should get handled in the next section, right? // Reset predictors, (cite 1, P. 64) dc_dct_pred[0] = 0; dc_dct_pred[1] = 0; dc_dct_pred[2] = 0; } if (intra_vlc_format == 1 && macroblock_intra == 1) println("Error - Program Limitation: Need to use B15 to decode DCT coefficients instead of B14"); while (QFS_current < 64) { if (macroblock_intra == 0 && QFS_current == 0) { // This section here from end of Table B.14 and 7.2.2.2 (cite 1, P.66) tempval = 0; for (int peeks_i = 0; peeks_i < (1-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(1-1); if (tempval == 1) { tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval == 0) QFS[i][0] = 1; else QFS[i][0] = -1; QFS_current += 1; } } tempval = 0; for (int peeks_i = 0; peeks_i < (2-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(2-1); if (tempval == 2) { tempval = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); QFS_current = 64; } else { int signed_level; int run; int level; int sign; signed_level = 0; run = 0; tempval = 0; for (int peeks_i = 0; peeks_i < (6-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(6-1); if (tempval == 1) { // Escape Code tempval = 0; for (int pops_i = 0; pops_i < (6-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); level = 0; sign = 0; run = 0; for (int pops_i = 0; pops_i < (6-1); pops_i++) { run += pop(); run <<= 1; } run += pop(); sign = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { sign += pop(); sign <<= 1; } sign += pop(); level = 0; for (int pops_i = 0; pops_i < (11-1); pops_i++) { level += pop(); level <<= 1; } level += pop(); if (sign == 0) { signed_level = level; } else { signed_level = level - 2048; } } else { // Regular Code level = 0; sign = 0; // The old. inefficient way: v ariable_length_code_dct(run,level,const_dct_coefficients_table_zero); // begin variable length code tempval = 0; for (int peeks_i = 0; peeks_i < (16-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(16-1); // if (tempval >= 49152 && tempval <= 65535) { // 2 if (tempval >= 49152) { tempval = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len2[0].run; level = const_dct_coefficients_table_zero_len2[0].level; // } else if (tempval >= 24576 && tempval <= 32767) { // 3 } else if (tempval >= 24576) { tempval = 0; for (int pops_i = 0; pops_i < (3-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len3[0].run; level = const_dct_coefficients_table_zero_len3[0].level; // } else if (tempval >= 16384 && tempval <= 24575) { // 4 } else if (tempval >= 16384) { tempval = 0; for (int pops_i = 0; pops_i < (4-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len4[tempval-4].run; level = const_dct_coefficients_table_zero_len4[tempval-4].level; // } else if (tempval >= 10240 && tempval <= 16383) { // 5 } else if (tempval >= 10240) { tempval = 0; for (int pops_i = 0; pops_i < (5-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len5[tempval-5].run; level = const_dct_coefficients_table_zero_len5[tempval-5].level; // } else if (tempval >= 8192 && tempval <= 10239) { // 8 } else if ( tempval >= 8192) { tempval = 0; for (int pops_i = 0; pops_i < (8-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len8[tempval-32].run; level = const_dct_coefficients_table_zero_len8[tempval-32].level; // } else if (tempval >= 4096 && tempval <= 8191) { // 6 } else if (tempval >= 4096) { tempval = 0; for (int pops_i = 0; pops_i < (6-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len6[tempval-4].run; level = const_dct_coefficients_table_zero_len6[tempval-4].level; // } else if (tempval >= 2048 && tempval <= 4095) { // 7 } else if (tempval >= 2048) { tempval = 0; for (int pops_i = 0; pops_i < (7-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len7[tempval-4].run; level = const_dct_coefficients_table_zero_len7[tempval-4].level; // } else if (tempval >= 512 && tempval <= 1023) { // 10 } else if (tempval >= 512) { tempval = 0; for (int pops_i = 0; pops_i < (10-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len10[tempval-8].run; level = const_dct_coefficients_table_zero_len10[tempval-8].level; // } else if (tempval >= 256 && tempval <= 511) { // 12 } else if (tempval >= 256) { tempval = 0; for (int pops_i = 0; pops_i < (12-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len12[tempval-16].run; level = const_dct_coefficients_table_zero_len12[tempval-16].level; // } else if (tempval >= 128 && tempval <= 255) { // 13 } else if (tempval >= 128) { tempval = 0; for (int pops_i = 0; pops_i < (13-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len13[tempval-16].run; level = const_dct_coefficients_table_zero_len13[tempval-16].level; // } else if (tempval >= 64 && tempval <= 127) { // 14 } else if (tempval >= 64) { tempval = 0; for (int pops_i = 0; pops_i < (14-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len14[tempval-16].run; level = const_dct_coefficients_table_zero_len14[tempval-16].level; // } else if (tempval >= 32 && tempval <= 63) { // 15 } else if (tempval >= 32) { tempval = 0; for (int pops_i = 0; pops_i < (15-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len15[tempval-16].run; level = const_dct_coefficients_table_zero_len15[tempval-16].level; // } else if (tempval >= 16 && tempval <= 31) { // 16 } else if (tempval >= 16) { tempval = 0; for (int pops_i = 0; pops_i < (16-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); run = const_dct_coefficients_table_zero_len16[tempval-16].run; level = const_dct_coefficients_table_zero_len16[tempval-16].level; } else { print("Error - Unknown Huffman Symbol"); } // end variable length code sign = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { sign += pop(); sign <<= 1; } sign += pop(); if (sign == 0) { signed_level = level; } else { signed_level = -level; } } QFS_current += run; if (QFS_current == 63) { tempval = 0; for (int pops_i = 0; pops_i < (2-1); pops_i++) { tempval += pop(); tempval <<= 1; } tempval += pop(); if (tempval != 2) { println("Error - Reached End of Block, Expecting End of Block Code"); } } QFS[i][QFS_current] = signed_level; QFS_current++; } if (QFS_current > 64) println("Error - QFS_current > 64 " + QFS_current); } } else { // Skipped block // This indicates a skipped block, but not a skipped macroblock. for (int index = 0; index < 64; index++) { QFS[i][index] = 0; } } } PushMacroblock(); pushedMacroblock = true; tempval = 0; for (int peeks_i = 0; peeks_i < (23-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(23-1); if (tempval == 0) { macroblock_next = false; next_cfg_node = 13; } else { macroblock_next = true; next_cfg_node = 7; } } else if (next_cfg_node == 13) { { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); if (tempval > 0x000001AF || tempval < 0x00000101) { slice_start_code_follows = false; next_cfg_node = 15; } else { slice_start_code_follows = true; next_cfg_node = 5; } } else if (next_cfg_node == 15) { { int nsc_tempval; nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); while (nsc_tempval != 1) { nsc_tempval = 0; for (int pops_i = 0; pops_i < (1-1); pops_i++) { nsc_tempval += pop(); nsc_tempval <<= 1; } nsc_tempval += pop(); // print("....looking for next_start_code...."); nsc_tempval = 0; for (int peeks_i = 0; peeks_i < (24-1); peeks_i++) { nsc_tempval += peek(peeks_i); nsc_tempval <<= 1; } nsc_tempval += peek(24-1); } } tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); if (tempval == 0x00000100 || tempval == 0x000001B8) { picture_or_group_start_code_found = true; next_cfg_node = 3; } else { picture_or_group_start_code_found = false; next_cfg_node = 17; } } else if (next_cfg_node == 17) { tempval = 0; for (int peeks_i = 0; peeks_i < (32-1); peeks_i++) { tempval += peek(peeks_i); tempval <<= 1; } tempval += peek(32-1); if (tempval != 0x000001B7) { println("Error - Program Limitation: Don't handle repeated sequence headers and sequence extensions"); } if (tempval != 0x000001B7) { sequence_end_code_not_found = true; next_cfg_node = 1; } else { sequence_end_code_not_found = false; next_cfg_node = 18; } } else if (next_cfg_node == 18) { println("Done Parsing M2V File..."); println("Generating fake last frame to push out last real frame of video."); UpdatePortal_picture_type.setPictureType(1) [0:0]; UpdatePortal_picture_type2.setPictureType(1) [0:0]; UpdatePortal_picture_type3.setPictureType(1) [0:0]; UpdatePortal_macroblock_intra.setMacroblockIntra(1); for (int i = 0; i < blocks_per_macroblock[the_chroma_format]; i++) { for (int j = 0; j < 64; j++) { QFS[i][j] = 0; } } for (int r = 0; r < 2; r++) for (int s = 0; s < 2; s++) for (int t = 0; t < 2; t++) { motion_code[r][s][t] = 0; } for (int r = 0; r < 2; r++) for (int s = 0; s < 2; s++) for (int t = 0; t < 2; t++) { motion_residual[r][s][t] = 0; } macroblock_intra = 1; macroblock_motion_forward = 0; macroblock_motion_backward = 0; int i = 0; next_cfg_node = 21; } else if (next_cfg_node == 21) { // assert: i < width/16 int j = 0; next_cfg_node = 22; } else if (next_cfg_node == 22) { // assert: j < height/16 PushMacroblock(); pushedMacroblock = true; j++; if (j < height/16) next_cfg_node = 22; else next_cfg_node = 27; } else if (next_cfg_node == 27) { i++; if (i < width/16) next_cfg_node = 21; else next_cfg_node = 29; } else if (next_cfg_node == 29) { println("Done generating fake frame"); next_cfg_node = 30; } else if (next_cfg_node == 30) { // println("Error - Trying to parse M2V file for a second time..."); pushedMacroblock = true; } } } }