--- /dev/null
+#include "../libzmpeg3.h"
+
+int zvideo_t::
+get_seq_hdr()
+{
+ int i;
+ int load_intra_quantizer_matrix, load_non_intra_quantizer_matrix;
+
+//zmsg("1\n");
+ horizontal_size = vstream->get_bits(12);
+ vertical_size = vstream->get_bits(12);
+ //int aspect_ratio =
+ vstream->get_bits(4);
+ framerate_code = vstream->get_bits(4);
+ bitrate = vstream->get_bits(18);
+ vstream->get_bit_noptr(); /* marker bit (=1) */
+ //int vbv_buffer_size =
+ vstream->get_bits(10);
+ //int constrained_parameters_flag =
+ vstream->get_bit_noptr();
+ frame_rate = frame_rate_table[framerate_code];
+
+ load_intra_quantizer_matrix = vstream->get_bit_noptr();
+ if( load_intra_quantizer_matrix ) {
+ for( i=0; i<64; ++i )
+ intra_quantizer_matrix[zigzag_scan_table[i]] = vstream->get_byte_noptr();
+ }
+ else {
+ for( i=0; i<64; ++i )
+ intra_quantizer_matrix[i] = default_intra_quantizer_matrix[i];
+ }
+
+ load_non_intra_quantizer_matrix = vstream->get_bit_noptr();
+ if( load_non_intra_quantizer_matrix ) {
+ for( i=0; i<64; ++i )
+ non_intra_quantizer_matrix[zigzag_scan_table[i]] = vstream->get_byte_noptr();
+ }
+ else {
+ for( i=0; i<64; ++i )
+ non_intra_quantizer_matrix[i] = 16;
+ }
+
+/* copy luminance to chrominance matrices */
+ for( i=0; i<64; ++i ) {
+ chroma_intra_quantizer_matrix[i] = intra_quantizer_matrix[i];
+ chroma_non_intra_quantizer_matrix[i] = non_intra_quantizer_matrix[i];
+ }
+
+//zmsg("100\n");
+ return 0;
+}
+
+
+/* decode sequence extension */
+
+int zvideo_t::
+sequence_extension()
+{
+ mpeg2 = 1;
+ scalable_mode = slice_decoder_t::sc_NONE; /* unless overwritten by seq. scal. ext. */
+ //int prof_lev =
+ vstream->get_byte_noptr();
+ prog_seq = vstream->get_bit_noptr();
+ chroma_format = vstream->get_bits(2);
+ int horizontal_size_extension = vstream->get_bits(2);
+ int vertical_size_extension = vstream->get_bits(2);
+ //int bit_rate_extension =
+ vstream->get_bits(12);
+ vstream->get_bit_noptr();
+ //int vbv_buffer_size_extension =
+ vstream->get_byte_noptr();
+ //int low_delay =
+ vstream->get_bit_noptr();
+ //int frame_rate_extension_n =
+ vstream->get_bits(2);
+ //int frame_rate_extension_d =
+ vstream->get_bits(5);
+ horizontal_size = (horizontal_size_extension << 12) | (horizontal_size & 0x0fff);
+ vertical_size = (vertical_size_extension << 12) | (vertical_size & 0x0fff);
+ return 0;
+}
+
+
+/* decode sequence display extension */
+
+int zvideo_t::
+sequence_display_extension()
+{
+ // int video_format =
+ vstream->get_bits(3);
+ int colour_description = vstream->get_bit_noptr();
+
+ if( colour_description ) {
+ //int colour_primaries =
+ vstream->get_byte_noptr();
+ //int transfer_characteristics =
+ vstream->get_byte_noptr();
+ matrix_coefficients = vstream->get_byte_noptr();
+ }
+
+ //int display_horizontal_size =
+ vstream->get_bits(14);
+ vstream->get_bit_noptr();
+ //int display_vertical_size =
+ vstream->get_bits(14);
+ return 0;
+}
+
+
+/* decode quant matrix entension */
+
+int zvideo_t::
+quant_matrix_extension()
+{
+ int i;
+ int load_intra_quantiser_matrix, load_non_intra_quantiser_matrix;
+ int load_chroma_intra_quantiser_matrix;
+ int load_chroma_non_intra_quantiser_matrix;
+
+ load_intra_quantiser_matrix = vstream->get_bit_noptr();
+ if( load_intra_quantiser_matrix != 0 ) {
+ for( i=0; i<64; ++i ) {
+ chroma_intra_quantizer_matrix[zigzag_scan_table[i]]
+ = intra_quantizer_matrix[zigzag_scan_table[i]]
+ = vstream->get_byte_noptr();
+ }
+ }
+
+ load_non_intra_quantiser_matrix = vstream->get_bit_noptr();
+ if( load_non_intra_quantiser_matrix != 0 ) {
+ for( i=0; i<64; ++i ) {
+ chroma_non_intra_quantizer_matrix[zigzag_scan_table[i]]
+ = non_intra_quantizer_matrix[zigzag_scan_table[i]]
+ = vstream->get_byte_noptr();
+ }
+ }
+
+ load_chroma_intra_quantiser_matrix = vstream->get_bit_noptr();
+ if( load_chroma_intra_quantiser_matrix != 0 ) {
+ for( i=0; i<64; ++i )
+ chroma_intra_quantizer_matrix[zigzag_scan_table[i]] = vstream->get_byte_noptr();
+ }
+
+ load_chroma_non_intra_quantiser_matrix = vstream->get_bit_noptr();
+ if( load_chroma_non_intra_quantiser_matrix != 0 ) {
+ for( i=0; i<64; ++i )
+ chroma_non_intra_quantizer_matrix[zigzag_scan_table[i]] = vstream->get_byte_noptr();
+ }
+
+ return 0;
+}
+
+
+/* decode sequence scalable extension */
+
+int zvideo_t::
+sequence_scalable_extension()
+{
+ scalable_mode = vstream->get_bits(2) + 1; /* add 1 to make sc_DP != sc_NONE */
+ //int layer_id =
+ vstream->get_bits(4);
+
+ if( scalable_mode == slice_decoder_t::sc_SPAT ) {
+ llw = vstream->get_bits(14); /* lower_layer_prediction_horizontal_size */
+ vstream->get_bit_noptr();
+ llh = vstream->get_bits(14); /* lower_layer_prediction_vertical_size */
+ hm = vstream->get_bits(5);
+ hn = vstream->get_bits(5);
+ vm = vstream->get_bits(5);
+ vn = vstream->get_bits(5);
+ }
+
+ if( scalable_mode == slice_decoder_t::sc_TEMP )
+ zerr("temporal scalability not implemented\n");
+ return 0;
+}
+
+
+/* decode picture display extension */
+
+int zvideo_t::
+picture_display_extension()
+{
+// short frame_centre_horizontal_offset[3];
+// short frame_centre_vertical_offset[3];
+/* per spec */
+ int n = prog_seq ? (!repeatfirst ? 1 : (!topfirst ? 2 : 3)) :
+ pict_struct != pics_FRAME_PICTURE ? 1 : (!repeatfirst ? 2 : 3) ;
+
+ for( int i=0; i<n; ++i ) {
+ //frame_centre_horizontal_offset[i] = (short)
+ vstream->get_bits(16);
+ vstream->get_bit_noptr();
+ //frame_centre_vertical_offset[i] = (short)
+ vstream->get_bits(16);
+ vstream->get_bit_noptr();
+ }
+ return 0;
+}
+
+
+/* decode picture coding extension */
+
+int zvideo_t::
+picture_coding_extension()
+{
+ h_forw_r_size = vstream->get_bits(4) - 1;
+ v_forw_r_size = vstream->get_bits(4) - 1;
+ h_back_r_size = vstream->get_bits(4) - 1;
+ v_back_r_size = vstream->get_bits(4) - 1;
+ dc_prec = vstream->get_bits(2);
+ pict_struct = vstream->get_bits(2);
+ topfirst = vstream->get_bit_noptr();
+ frame_pred_dct = vstream->get_bit_noptr();
+ conceal_mv = vstream->get_bit_noptr();
+ qscale_type = vstream->get_bit_noptr();
+ intravlc = vstream->get_bit_noptr();
+ altscan = vstream->get_bit_noptr();
+ repeatfirst = vstream->get_bit_noptr();
+ //int chroma_420_type =
+ vstream->get_bit_noptr();
+ prog_frame = vstream->get_bit_noptr();
+ if( repeat_fields > 2 ) repeat_fields = 0;
+ repeat_fields += 2;
+ if( repeatfirst ) {
+ if( prog_seq ) repeat_fields += !topfirst ? 2 : 4;
+ else if( prog_frame ) ++repeat_fields;
+ }
+ current_field = 0;
+
+//static const char *pstruct[] = { "nil", "top", "bot", "fld" };
+//zmsgs("pstruct %s prog_seq%d prog_frame%d topfirst%d repeatfirst%d repeat_fields%d\n",
+// pstruct[pict_struct], prog_seq , prog_frame, topfirst, repeatfirst, repeat_fields);
+
+ int composite_display_flag = vstream->get_bit_noptr();
+ if( composite_display_flag ) {
+ //int v_axis =
+ vstream->get_bit_noptr();
+ field_sequence = vstream->get_bits(3);
+ //int sub_carrier =
+ vstream->get_bit_noptr();
+ //int burst_amplitude =
+ vstream->get_bits(7);
+ //int sub_carrier_phase =
+ vstream->get_byte_noptr();
+ }
+ return 0;
+}
+
+/* decode picture spatial scalable extension */
+
+int zvideo_t::
+picture_spatial_scalable_extension()
+{
+ pict_scal = 1; /* use spatial scalability in this picture */
+ lltempref = vstream->get_bits(10);
+ vstream->get_bit_noptr();
+ llx0 = vstream->get_bits(15);
+ if(llx0 >= 16384) llx0 -= 32768;
+ vstream->get_bit_noptr();
+ lly0 = vstream->get_bits(15);
+ if(lly0 >= 16384) lly0 -= 32768;
+ stwc_table_index = vstream->get_bits(2);
+ llprog_frame = vstream->get_bit_noptr();
+ llfieldsel = vstream->get_bit_noptr();
+ return 0;
+}
+
+
+/* decode picture temporal scalable extension
+ *
+ * not implemented
+ *
+ */
+
+int zvideo_t::
+picture_temporal_scalable_extension()
+{
+ zerr("temporal scalability not supported\n");
+ return 0;
+}
+
+
+/* decode extension and user data */
+
+int zvideo_t::
+ext_user_data()
+{
+ int zcode = vstream->next_start_code();
+ if( zcode < 0 ) return 1;
+ while( zcode == EXT_START_CODE || zcode == USER_START_CODE ) {
+ vstream->refill();
+ if( zcode == EXT_START_CODE ) {
+ int ext_id = vstream->get_bits(4);
+ switch(ext_id) {
+ case ext_id_SEQ:
+ sequence_extension();
+ break;
+ case ext_id_DISP:
+ sequence_display_extension();
+ break;
+ case ext_id_QUANT:
+ quant_matrix_extension();
+ break;
+ case ext_id_SEQSCAL:
+ sequence_scalable_extension();
+ break;
+ case ext_id_PANSCAN:
+ picture_display_extension();
+ break;
+ case ext_id_CODING:
+ picture_coding_extension();
+ break;
+ case ext_id_SPATSCAL:
+ picture_spatial_scalable_extension();
+ break;
+ case ext_id_TEMPSCAL:
+ picture_temporal_scalable_extension();
+ break;
+ default:
+ zerrs("reserved extension start code ID %d\n", ext_id);
+ break;
+ }
+ }
+ else if( subtitle_track >= 0 ) {
+ int32_t id = vstream->show_bits(32);
+ if( id == 0x47413934 ) { /* "GA94" - atsc user data */
+ vstream->refill();
+ int typ = vstream->get_bits(8);
+ if( typ == 3 ) /* mpeg cc */
+ get_cc()->get_atsc_data(vstream);
+ }
+ }
+ zcode = vstream->next_start_code();
+ if( zcode < 0 ) return 1;
+ }
+//zmsgs("prog_seq=%d prog_frame=%d\n", prog_seq,prog_frame);
+ return 0;
+}
+
+
+/* decode group of pictures header */
+
+int zvideo_t::
+get_gop_header()
+{
+//zmsg("1\n");
+ has_gops = 1;
+ //int drop_flag =
+ vstream->get_bit_noptr();
+ gop_timecode.hour = vstream->get_bits(5);
+ gop_timecode.minute = vstream->get_bits(6);
+ vstream->get_bit_noptr();
+ gop_timecode.second = vstream->get_bits(6);
+ gop_timecode.frame = vstream->get_bits(6);
+ //int closed_gop =
+ vstream->get_bit_noptr();
+ //int broken_link =
+ vstream->get_bit_noptr();
+//zmsg("100\n");
+//zmsgs("%d:%d:%d:%d %d %d %d\n",
+// gop_timecode.hour, gop_timecode.minute, gop_timecode.second,
+// gop_timecode.frame, drop_flag, closed_gop, broken_link);
+ return vstream->error();
+}
+
+/* decode picture header */
+
+int zvideo_t::
+get_picture_hdr()
+{
+ pict_scal = 0; /* unless overwritten by pict. spat. scal. ext. */
+ //int temp_ref =
+ vstream->get_bits(10);
+ pict_type = vstream->get_bits(3);
+ //int vbv_delay =
+ vstream->get_bits(16);
+ if( pict_type == pic_type_P || pict_type == pic_type_B ) {
+ full_forw = vstream->get_bit_noptr();
+ forw_r_size = vstream->get_bits(3) - 1;
+ }
+
+ if( pict_type == pic_type_B ) {
+ full_back = vstream->get_bit_noptr();
+ back_r_size = vstream->get_bits(3) - 1;
+ }
+
+/* get extra bit picture */
+ while( !vstream->eof() && vstream->get_bit_noptr() )
+ vstream->get_bits_noptr(8);
+ return 0;
+}
+
+
+/* move to start of header. */
+/* this updates the demuxer times */
+int zvideo_t::
+find_header()
+{
+ for( int count=0x1000; --count>=0; ) {
+ int zcode = vstream->next_start_code();
+ if( zcode < 0 ) break;
+ switch(zcode) {
+ case SEQUENCE_START_CODE:
+ case GOP_START_CODE:
+ case PICTURE_START_CODE:
+ return 0;
+ }
+ vstream->refill();
+ }
+
+ return 1;
+}
+
+
+int zvideo_t::
+get_header()
+{
+// Stop search after this many start codes
+ for( int count=0x1000; --count>=0; ) {
+/* look for startcode */
+ int zcode = vstream->next_start_code();
+ if( zcode < 0 ) break;
+ vstream->refill();
+
+ switch(zcode) {
+ case SEQUENCE_START_CODE:
+/* a sequence header should be found before returning from get_header the */
+/* first time (this is to set horizontal/vertical size properly) */
+ found_seqhdr = 1;
+ get_seq_hdr();
+ ext_user_data();
+ break;
+
+ case GOP_START_CODE:
+ get_gop_header();
+ ext_user_data();
+ break;
+
+ case PICTURE_START_CODE:
+ get_picture_hdr();
+ ext_user_data();
+ if( cc ) cc->reorder();
+ if( found_seqhdr )
+ return 0; /* Exit here */
+ break;
+ }
+ }
+
+ return 1;
+}
+
+int zslice_buffer_t::
+ext_bit_info()
+{
+ while( get_bit() ) get_bits(8);
+ return 0;
+}
+
+/* decode slice header */
+int zslice_decoder_t::
+get_slice_hdr()
+{
+ int slice_vertical_position_extension;
+ int qs;
+ slice_vertical_position_extension =
+ (video->mpeg2 && video->vertical_size>2800) ?
+ slice_buffer->get_bits(3) : 0;
+
+ if( video->scalable_mode == sc_DP )
+ pri_brk = slice_buffer->get_bits(7);
+
+ qs = slice_buffer->get_bits(5);
+ quant_scale = video->mpeg2 ?
+ (video->qscale_type ? non_linear_mquant_table[qs] : (qs << 1)) :
+ qs;
+
+//int intra_slice = 0;
+ if( slice_buffer->get_bit() ) {
+ //intra_slice =
+ slice_buffer->get_bit();
+ slice_buffer->get_bits(7);
+ slice_buffer->ext_bit_info();
+ }
+
+ return slice_vertical_position_extension;
+}
+