📄 video_stream.c
字号:
calc_pts = last_pts_to_dpy + (pic.header.temporal_reference - last_temporal_ref_to_dpy) * frame_interval; } } pinfos[buf_id].PTS = calc_pts; pinfos[buf_id].scr_nr = last_scr_nr; /* fprintf(stderr, "last_timestamped: %d\n", last_timestamped_temp_ref); fprintf(stderr, "last_pts: %lld\n", last_pts); fprintf(stderr, "last_pts_to_dpy: %lld\n", last_pts_to_dpy); fprintf(stderr, "pts_time %ld.%09ld\n", TIME_S (pinfos[buf_id].pts_time), TIME_SS(pinfos[buf_id].pts_time)); fprintf(stderr, "realtime_offset %ld.%09ld\n", TIME_S (ctrl_time[last_scr_nr].realtime_offset), TIME_SS(ctrl_time[last_scr_nr].realtime_offset)); */ break; case PIC_CODING_TYPE_B: /* In case we don't have a previous displayed picture * we don't now what we should set this timestamp to * unless we look at the temporal reference. * To be able to use the temporal reference we need * to have a pts in the same temporal reference 'sequence'. * (the temporal reference sequence is reset to 0 for every * GOP */ /* In case we don't use temporal reference * we don't know what the pts should be, but we calculate it * anyway and hope we end up with a time that is earlier * than the next 'real' time stamp. */ /* We use temporal reference and calculate the timestamp * from the last decoded picture which had a timestamp */ /* TODO: Check if there is a valid 'last_pts_to_dpy' to predict from.*/ calc_pts = last_pts + (pic.header.temporal_reference - last_timestamped_temp_ref) * frame_interval; /* calc_pts = last_pts_to_dpy + buf_ctrl_head->frame_interval; */ pinfos[buf_id].PTS = calc_pts; pinfos[buf_id].scr_nr = last_scr_nr; break; } } /* When it is a B-picture we are decoding we know that it is * the picture that is going to be displayed next. * We check to see if we are lagging behind the desired time * and in that case we don't decode/show this picture */ /* Calculate the time remaining until this picture shall be viewed. */ if(pic.header.picture_coding_type == PIC_CODING_TYPE_B) { clocktime_t realtime, calc_rt, err_time, pts_time; PTS_TO_CLOCKTIME(pts_time, pinfos[buf_id].PTS); clocktime_get(&realtime); if(ctrl_time[last_scr_nr].offset_valid == OFFSET_VALID) { calc_realtime_left_to_scrtime(&err_time, &realtime, &pts_time, &ctrl_time[last_scr_nr].sync_point); } else { calc_rt = realtime; timesub(&err_time, &calc_rt, &realtime); DNOTE("%s", "time offset not valid yet\n"); } /* If the picture should already have been displayed then drop it. */ /* TODO: More investigation needed. */ if((TIME_SS(err_time) < 0 || TIME_S(err_time) < 0) && forced_frame_rate) { fprintf(stderr, "!"); /* fprintf(stderr, "errpts %ld.%+010ld\n\n", TIME_S(err_time), TIME_SSerr_time)); */ /* mark the frame to be dropped */ drop_frame = 1; } } }/* else { // either this is the second field of the frame or it is an error fprintf(stderr, "*** error prev_temp_ref == cur_temp_ref\n"); } */ { // Don't use floating point math! int sar_frac_n = 1; int sar_frac_d = 1; //double sar = 1.0; uint16_t hsize, vsize; //wrong on some dvd's ? if(seq.dpy_ext.display_horizontal_size) { hsize = seq.dpy_ext.display_horizontal_size; vsize = seq.dpy_ext.display_vertical_size; /* fprintf(stderr, "*****bepa %d, %d\n", hsize, vsize); */ } else { hsize = seq.horizontal_size; vsize = seq.vertical_size; } switch(seq.header.aspect_ratio_information) { case 0x0: DPRINTF(2, "forbidden\n"); break; case 0x1: DPRINTF(2, "SAR = 1.0\n"); sar_frac_n = 1; sar_frac_d = 1; //sar = 1.0; break; case 0x2: DPRINTF(2, "DAR = 3/4\n"); sar_frac_n = 3 * hsize; sar_frac_d = 4 * vsize; //sar = 3.0/4.0*(double)hsize/(double)vsize; break; case 0x3: DPRINTF(2, "DAR = 9/16\n"); if(seq.dpy_ext.display_horizontal_size) { if(seq.dpy_ext.display_horizontal_size != seq.horizontal_size) { // DVD with wrong mpeg display_extension hsize = seq.horizontal_size; vsize = seq.vertical_size; } } sar_frac_n = 9 * hsize; sar_frac_d = 16 * vsize; //sar = 9.0/16.0*(double)hsize/(double)vsize; break; case 0x4: DPRINTF(2, "DAR = 1/2.21\n"); sar_frac_n = 100 * hsize; sar_frac_d = 221 * vsize; //sar = 1.0/2.21*(double)hsize/(double)vsize; break; default: DPRINTF(2, "reserved\n"); break; } pinfos[buf_id].picture.sar_frac_n = sar_frac_n; pinfos[buf_id].picture.sar_frac_d = sar_frac_d; //TODO add frame_center__offset compensation and // handle bigger display__size than _size if(seq.dpy_ext.display_horizontal_size > 0 && seq.dpy_ext.display_horizontal_size <= seq.horizontal_size) { pinfos[buf_id].picture.display_start_x = (seq.horizontal_size - seq.dpy_ext.display_horizontal_size) / 2; pinfos[buf_id].picture.display_width = seq.dpy_ext.display_horizontal_size; } else { pinfos[buf_id].picture.display_start_x = 0; pinfos[buf_id].picture.display_width = 0; } if(seq.dpy_ext.display_vertical_size > 0 && seq.dpy_ext.display_vertical_size <= seq.vertical_size) { pinfos[buf_id].picture.display_start_y = (seq.vertical_size - seq.dpy_ext.display_vertical_size) / 2; pinfos[buf_id].picture.display_height = seq.dpy_ext.display_vertical_size; } else { pinfos[buf_id].picture.display_start_y = 0; pinfos[buf_id].picture.display_height = 0; } } if(flush_to_scrid != -1) { // fprintf(stderr, "vs: flush picture\n"); } /* now we can decode the picture if it shouldn't be dropped */ if(!drop_frame && (flush_to_scrid == -1)) { /* Decode the slices. */ if( MPEG2 ) { do { int slice_nr; slice_nr = nextbits(32) & 0xff; mpeg2_slice(); if(slice_nr >= seq.mb_height) { break; } next_start_code(); } while((nextbits(32) >= MPEG2_VS_SLICE_START_CODE_LOWEST) && (nextbits(32) <= MPEG2_VS_SLICE_START_CODE_HIGHEST)); } else { do { err = mpeg1_slice(); if(err == -1) { drop_to_next_picture(); break; } } while((nextbits(32) >= MPEG2_VS_SLICE_START_CODE_LOWEST) && (nextbits(32) <= MPEG2_VS_SLICE_START_CODE_HIGHEST)); } } else { do { //TODO change to fast startcode finder GETBITS(8, "drop"); next_start_code(); } while((nextbits(32) >= MPEG2_VS_SLICE_START_CODE_LOWEST) && (nextbits(32) <= MPEG2_VS_SLICE_START_CODE_HIGHEST)); } // Check 'err' here? /* fprintf(stderr, "coding_type: %d, temp_ref: %d\n", pic.header.picture_coding_type, pic.header.temporal_reference); */ // Picture decoded if((prev_coded_temp_ref == pic.header.temporal_reference) || (pic.coding_ext.picture_structure == PIC_STRUCT_FRAME_PICTURE)) { if(pic.header.picture_coding_type == PIC_CODING_TYPE_B) { if(pic.header.temporal_reference == (last_temporal_ref_to_dpy+1)%1024) { last_temporal_ref_to_dpy = pic.header.temporal_reference; last_pts_to_dpy = pinfos[buf_id].PTS; last_scr_nr_to_dpy = pinfos[buf_id].scr_nr;//? if(drop_frame || (flush_to_scrid != -1)) { drop_frame = 0; pinfos[buf_id].is_reference = 0; //this is never set in a B picture? pinfos[buf_id].displayed = 1; } else { dpy_q_put(buf_id, cur_data_q); } if(bwd_ref_buf_id == -1) { WARNING("%s", " **B-frame before any reference frame!!!\n"); } if(fwd_ref_buf_id == -1) { // Test closed_gop too.... WARNING("%s", "B-frame before forward ref frame\n"); } } else { /* TODO: what should happen if the temporal reference is wrong */ WARNING("%s", "** temporal reference for B-picture incorrect\n"); temporal_reference_error = pic.header.temporal_reference - (last_temporal_ref_to_dpy + 1)%1024; last_temporal_ref_to_dpy = pic.header.temporal_reference; //last_temporal_ref_to_dpy++; last_pts_to_dpy = pinfos[buf_id].PTS; last_scr_nr_to_dpy = pinfos[buf_id].scr_nr;//? dpy_q_put(buf_id, cur_data_q); } } /* if(temporal_reference_error) { if((bwd_ref_temporal_reference != -1)) { dpy_q_put(bwd_ref_buf_id); } } */ if((bwd_ref_temporal_reference != -1) && (bwd_ref_temporal_reference == (last_temporal_ref_to_dpy+1)%1024)) { last_temporal_ref_to_dpy = bwd_ref_temporal_reference; /* bwd_ref should not be in the dpy_q more than one time */ bwd_ref_temporal_reference = -1; /* put bwd_ref in dpy_q */ last_pts_to_dpy = pinfos[bwd_ref_buf_id].PTS; last_scr_nr_to_dpy = pinfos[bwd_ref_buf_id].scr_nr; if(flush_to_scrid != -1) { pinfos[bwd_ref_buf_id].is_reference = 0; pinfos[bwd_ref_buf_id].displayed = 1; } else { dpy_q_put(bwd_ref_buf_id, cur_data_q); } } else if(bwd_ref_temporal_reference < (last_temporal_ref_to_dpy+1)%1024) { WARNING("%s", "** temporal reference in I or P picture incorrect\n"); } } prev_coded_temp_ref = pic.header.temporal_reference; DINDENT(-2); next_start_code();}/* 6.2.2.2.1 Extension data */void extension_data(const unsigned int i){ DPRINTFI(1, "extension_data(%d)", i); DINDENT(2); while(nextbits(32) == MPEG2_VS_EXTENSION_START_CODE) { GETBITS(32, "extension_start_code"); if(i == 0) { /* follows sequence_extension() */ if(nextbits(4) == MPEG2_VS_SEQUENCE_DISPLAY_EXTENSION_ID) { sequence_display_extension(); } if(nextbits(4) == MPEG2_VS_SEQUENCE_SCALABLE_EXTENSION_ID) { sequence_scalable_extension(); } } /* extension never follows a group_of_picture_header() */ if(i == 2) { /* follows picture_coding_extension() */ if(nextbits(4) == MPEG2_VS_QUANT_MATRIX_EXTENSION_ID) { quant_matrix_extension(); } if(nextbits(4) == MPEG2_VS_PICTURE_DISPLAY_EXTENSION_ID) { /* the draft says picture_pan_scan_extension_id (must be wrong?) */ picture_display_extension(); } if(nextbits(4) == MPEG2_VS_PICTURE_SPATIAL_SCALABLE_EXTENSION_ID) { picture_spatial_scalable_extension(); } if(nextbits(4) == MPEG2_VS_PICTURE_TEMPORAL_SCALABLE_EXTENSION_ID) { picture_temporal_scalable_extension(); } } } DINDENT(-2);} void reset_to_default_quantiser_matrix(void){ memcpy(seq.header.intra_inverse_quantiser_matrix, default_intra_inverse_quantiser_matrix, sizeof(seq.header.intra_inverse_quantiser_matrix)); memcpy(seq.header.non_intra_inverse_quantiser_matrix, default_non_intra_inverse_quantiser_matrix, sizeof(seq.header.non_intra_inverse_quantiser_matrix)); }void reset_to_default_intra_quantiser_matrix(void){ memcpy(seq.header.intra_inverse_quantiser_matrix, default_intra_inverse_quantiser_matrix, sizeof(seq.header.intra_inverse_quantiser_matrix));}void reset_to_default_non_intra_quantiser_matrix(void){ memcpy(seq.header.non_intra_inverse_quantiser_matrix, default_non_intra_inverse_quantiser_matrix, sizeof(seq.header.non_intra_inverse_quantiser_matrix));}/* 6.2.3.2 Quant matrix extension */void quant_matrix_extension(void){ GETBITS(4, "extension_start_code_identifier"); DPRINTFI(1, "quant_matrix_extension()\n"); DINDENT(2); if(GETBITS(1, "load_intra_quantiser_matrix")) { unsigned int n; intra_inverse_quantiser_matrix_changed = 1; /* 7.3.1 Inverse scan for matrix download */ for(n = 0; n < 64; n++) { seq.header.intra_inverse_quantiser_matrix[inverse_scan[0][n]] = GETBITS(8, "intra_quantiser_matrix[n]"); } } if(GETBITS(1, "load_non_intra_quantiser_matrix")) { unsigned int n; non_intra_inverse_quantiser_matrix_changed = 1; /* 7.3.1 Inverse scan for matrix download */ for(n = 0; n < 64; n++) { seq.header.non_intra_inverse_quantiser_matrix[inverse_scan[0][n]] = GETBITS(8, "non_intra_quantiser_matrix[n]"); } } GETBITS(1, "load_chroma_intra_quantiser_matrix (always 0 in 4:2:0)"); GETBITS(1, "load_chroma_non_intra_quantiser_matrix (always 0 in 4:2:0)"); DINDENT(-2); next_start_code();}void picture_display_extension(void){ uint8_t extension_start_code_identifier; uint16_t frame_centre_horizontal_offset; uint16_t frame_centre_vertical_offset; uint8_t number_of_frame_centre_offsets; unsigned int i; DPRINTFI(1, "picture_display_extension()\n"); DINDENT(2); if((seq.ext.progressive_sequence == 1) || ((pic.coding_ext.picture_structure == PIC_STRUCT_TOP_FIELD) || (pic.coding_ext.picture_structure == PIC_STRUCT_BOTTOM_FIELD))) { number_of_frame_centre_offsets = 1; } else { if(pic.coding_ext.repeat_first_field == 1) { number_of_frame_centre_offsets = 3; } else { number_of_frame_centre_offsets = 2; } } extension_start_code_identifier = GETBITS(4,"extension_start_code_identifier"); for(i = 0; i < number_of_frame_centre_offsets; i++) { frame_centre_horizontal_offset = GETBITS(16, "frame_centre_horizontal_offset"); marker_bit(); frame_centre_vertical_offset = GETBITS(16, "frame_centre_vertical_offset"); marker_bit(); DPRINTFI(2, "frame_centre_offset: %d, %d\n", frame_centre_horizontal_offset, frame_centre_vertical_offset); } DINDENT(-2); next_start_code();}void picture_spatial_scalable_extension(void){ fprintf(stderr, "***ni picture_spatial_scalable_extension()\n"); exit(1);}void picture_temporal_
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -