📄 video_stream.c
字号:
} if(picture_header() == -1) { next_start_code(); continue; // Error, we need our picture header. } DINDENT(1); if(picture_coding_extension() == -1) { next_start_code(); continue; // Error, we need the coding extension data (or ?) } extension_and_user_data(2); picture_data(); DINDENT(-1); } while((nextbits(32) == MPEG2_VS_PICTURE_START_CODE) || (nextbits(32) == MPEG2_VS_GROUP_START_CODE)); DINDENT(-1); if(nextbits(32) != MPEG2_VS_SEQUENCE_END_CODE) { if(nextbits(32) != MPEG2_VS_SEQUENCE_HEADER_CODE) { DPRINTF(0, "*** not a sequence header or end code\n"); break; } sequence_header(); sequence_extension(); } } while(nextbits(32) != MPEG2_VS_SEQUENCE_END_CODE); DINDENT(-1); } else { /* ERROR: This is an ISO/IEC 11172-2 Stream */ /* No extension code following the sequence header implies MPEG-1 */ MPEG2 = 0; // init values for MPEG-1 pic.coding_ext.picture_structure = PIC_STRUCT_FRAME_PICTURE; pic.coding_ext.frame_pred_frame_dct = 1; pic.coding_ext.intra_vlc_format = 0; pic.coding_ext.concealment_motion_vectors = 0; //mb.modes.frame_motion_type = 0x2; // This implies the ones below.. mb.prediction_type = PRED_TYPE_FRAME_BASED; mb.motion_vector_count = 1; mb.mv_format = MV_FORMAT_FRAME; mb.dmv = 0; seq.ext.chroma_format = 0x1; /* Display init */ if(!shm_ready) { cur_data_q = new_data_q(&data_q_head, seq.mb_width * 16, seq.mb_height * 16, nr_of_buffers); shm_ready = 1; } next_start_code(); extension_and_user_data(1); do { if(nextbits(32) == MPEG2_VS_GROUP_START_CODE) { group_of_pictures_header(); extension_and_user_data(1); } if(picture_header() == -1) { next_start_code(); continue; // Error, we need out picture header } extension_and_user_data(1); picture_data(); } while(nextbits(32) == MPEG2_VS_PICTURE_START_CODE || (nextbits(32) == MPEG2_VS_GROUP_START_CODE)); } DINDENT(-1); /* If we are exiting there should be a sequence end code following. */ if(nextbits(32) == MPEG2_VS_SEQUENCE_END_CODE) { GETBITS(32, "Sequence End Code"); DPRINTF(1, "Found Sequence End\n"); } else { DPRINTF(0, "*** Didn't find Sequence End\n"); }} /* 6.2.2.1 Sequence header */void sequence_header(void){ uint32_t sequence_header_code; long int frame_interval_pts = 0; DPRINTFI(1, "sequence_header()\n"); DINDENT(2); sequence_header_code = GETBITS(32, "sequence header code"); if(sequence_header_code != MPEG2_VS_SEQUENCE_HEADER_CODE) { WARNING("wrong start_code sequence_header_code: %08x\n", sequence_header_code); } seq.header.horizontal_size_value = GETBITS(12, "horizontal_size_value"); seq.header.vertical_size_value = GETBITS(12, "vertical_size_value"); seq.header.aspect_ratio_information = GETBITS(4, "aspect_ratio_information"); seq.header.frame_rate_code = GETBITS(4, "frame_rate_code"); seq.header.bit_rate_value = GETBITS(18, "bit_rate_value"); marker_bit(); seq.header.vbv_buffer_size_value = GETBITS(10, "vbv_buffer_size_value"); seq.header.constrained_parameters_flag = GETBITS(1, "constrained_parameters_flag"); /* When a sequence header is decoded all matrices shall either be reset to their default values or downloaded from the bit stream. */ if(GETBITS(1, "load_intra_quantiser_matrix")) { 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]"); } } else { if(intra_inverse_quantiser_matrix_changed) { reset_to_default_intra_quantiser_matrix(); intra_inverse_quantiser_matrix_changed = 0; } } if(GETBITS(1, "load_non_intra_quantiser_matrix")) { 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]"); } } else { if(non_intra_inverse_quantiser_matrix_changed) { reset_to_default_non_intra_quantiser_matrix(); non_intra_inverse_quantiser_matrix_changed = 0; } } DPRINTFI(2, "horizontal_size_value: %u\n", seq.header.horizontal_size_value); DPRINTFI(2, "vertical_size_value: %u\n", seq.header.vertical_size_value); DPRINTFI(2, "aspect_ratio_information:(0x%01x) ", seq.header.aspect_ratio_information);#ifdef DEBUG switch(seq.header.aspect_ratio_information) { case 0x0: DPRINTF(2, "forbidden\n"); break; case 0x1: DPRINTF(2, "SAR = 1.0\n"); break; case 0x2: DPRINTF(2, "DAR = 3/4\n"); break; case 0x3: DPRINTF(2, "DAR = 9/16\n"); break; case 0x4: DPRINTF(2, "DAR = 1/2.21\n"); break; default: DPRINTF(2, "reserved\n"); break; }#endif DPRINTFI(2, "frame_rate_code:(0x%01x) ", seq.header.frame_rate_code); switch(seq.header.frame_rate_code) { case 0x0: DPRINTF(2, "forbidden\n"); break; case 0x1: DPRINTF(2, "24000/1001 (23.976)\n"); frame_interval_pts = 3754; break; case 0x2: DPRINTF(2, "24\n"); frame_interval_pts = 3750; break; case 0x3: DPRINTF(2, "25\n"); frame_interval_pts = 3600; break; case 0x4: DPRINTF(2, "30000/1001 (29.97)\n"); /* TODO hack for 24fps progressive */ if(last_gop_had_repeat_field_progressive_frame) { /* it's probably coded as 24 fps progressive */ frame_interval_pts = 3754; } else { frame_interval_pts = 3003; } break; case 0x5: DPRINTF(2, "30\n"); frame_interval_pts = 3000; break; case 0x6: DPRINTF(2, "50\n"); frame_interval_pts = 1800; break; case 0x7: DPRINTF(2, "60000/1001 (59.94)\n"); frame_interval_pts = 1502; break; case 0x8: DPRINTF(2, "60\n"); frame_interval_pts = 1500; break; default: DPRINTF(2, "Reserved\n"); WARNING("%s", "reserved framerate found in sequence header\n"); break; } if(forced_frame_rate == -1) { /* No forced frame rate */ //buf_ctrl_head->frame_interval = frame_interval_pts; frame_interval = frame_interval_pts; } else { if(forced_frame_rate == 0) { //buf_ctrl_head->frame_interval = 1; frame_interval = 1; } else { //buf_ctrl_head->frame_interval = PTS_BASE/forced_frame_rate; frame_interval = PTS_BASE/forced_frame_rate; } } DPRINTFI(2, "bit_rate_value: (0x%03x) %d bits/second\n", seq.header.bit_rate_value, seq.header.bit_rate_value*400); DPRINTFI(2, "vbv_buffer_size_value: (0x%02x) min %d bits\n", seq.header.vbv_buffer_size_value, 16*1024*seq.header.vbv_buffer_size_value); DPRINTFI(2, "constrained_parameters_flag: %01x\n", seq.header.constrained_parameters_flag); seq.horizontal_size = seq.header.horizontal_size_value; seq.vertical_size = seq.header.vertical_size_value; seq.mb_width = (seq.horizontal_size+15)/16; seq.mb_height = (seq.vertical_size+15)/16; DINDENT(-2);}#define INC_8b_ALIGNMENT(a) ((a+7)/8*8)int detach_data_q(int q_shmid, data_q_t **data_q_list){ MsgEvent_t ev; data_q_t **data_q_p; data_q_t *data_q_tmp; q_head_t *q_head; data_buf_head_t *data_head; int data_shmid; // fprintf(stderr, "DEBUG[vs]: detach_data_q q_shmid: %d\n", q_shmid); for(data_q_p=data_q_list; *data_q_p != NULL && (*data_q_p)->q_head->qid != q_shmid; data_q_p = &(*data_q_p)->next) { } if(*data_q_p == NULL) { ERROR("%s", "detach_data_q q_shmid not found\n"); return -1; } q_head = (*data_q_p)->q_head; data_head = (*data_q_p)->data_head; data_shmid = (*data_q_p)->data_head->shmid; if(shmdt((char *)data_head) == -1) { perror("ERROR[vs]: detach_data_q data_head"); } if(shmdt((char *)q_head) == -1) { perror("ERROR[vs]: detach_data_q q_head"); } //TODO ugly hack free((*data_q_p)->image_bufs); data_q_tmp = *data_q_p; *data_q_p = (*data_q_p)->next; free(data_q_tmp); ev.type = MsgEventQDestroyQ; ev.detachq.q_shmid = q_shmid; if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) { ERROR("%s", "couldn't send destroyq\n"); } ev.type = MsgEventQDestroyBuf; ev.destroybuf.shmid = data_shmid; if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) { ERROR("%s", "couldn't send destroybuf\n"); } return 0;}data_q_t *new_data_q(data_q_t **data_q_list, int padded_width, int padded_height, int nr_of_bufs){ data_q_t **data_q_p; for(data_q_p = data_q_list; *data_q_p != NULL; data_q_p =&(*data_q_p)->next); *data_q_p = malloc(sizeof(data_q_t)); if(get_output_buffer(*data_q_p, padded_width, padded_height, nr_of_bufs) == -1) { free(*data_q_p); *data_q_p = NULL; } return *data_q_p;}int get_output_buffer(data_q_t *data_q, int padded_width, int padded_height, int nr_of_bufs){ int picture_size; int picture_bufs_size; int picture_ctrl_size; int buf_size; MsgEvent_t ev; int num_pels = padded_width * padded_height; int pagesize = sysconf(_SC_PAGESIZE); int y_size = INC_8b_ALIGNMENT(num_pels); int uv_size = INC_8b_ALIGNMENT(num_pels/4); int yuv_size = y_size + 2 * uv_size; int data_shmid; int q_shmid; int picture_data_offset; int n; char *data_shmaddr; char *q_shmaddr; q_head_t *q_head = NULL; q_elem_t *q_elems = NULL; data_buf_head_t *data_head = NULL; picture_data_elem_t *data_elems = NULL; yuv_image_t *image_bufs = NULL; DNOTE("%s", "get ouput buffer\n"); picture_size = ((yuv_size + (pagesize-1))/pagesize*pagesize); /* Mlib reads ?8? bytes beyond the last pel (in the v-picture), if that pel just before a page boundary then *boom*!! */ // TODO this is an ugly hack for not mixing in ref.frames#ifdef HAVE_XV picture_bufs_size = (nr_of_bufs+1) * picture_size + pagesize;//Hack picture_ctrl_size = sizeof(data_buf_head_t) + sizeof(picture_data_elem_t)*(nr_of_bufs+1);#else picture_bufs_size = nr_of_bufs * picture_size + pagesize;//Hack picture_ctrl_size = sizeof(data_buf_head_t) + sizeof(picture_data_elem_t)*nr_of_bufs;#endif picture_ctrl_size = INC_8b_ALIGNMENT(picture_ctrl_size); buf_size = picture_ctrl_size + picture_bufs_size; // Get shared memory buffer ev.type = MsgEventQReqBuf; ev.reqbuf.size = buf_size; if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) { ERROR("%s", "couldn't send buffer request\n"); } while(1) { if(MsgNextEvent(msgq, &ev) != -1) { if(ev.type == MsgEventQGntBuf) { DPRINTF(1, "video_decoder: got buffer id %d, size %d\n", ev.gntbuf.shmid, ev.gntbuf.size); data_shmid = ev.gntbuf.shmid; break; } else { handle_events(msgq, &ev); } } } if(data_shmid >= 0) { if((data_shmaddr = shmat(data_shmid, NULL, SHM_SHARE_MMU)) == (void *)-1) { perror("**video_decode: attach_buffer(), shmat()"); return -1; } data_head = (data_buf_head_t *)data_shmaddr; data_head->shmid = data_shmid; data_head->info.type = DataBufferType_Video; data_head->info.video.format = 0; data_head->info.video.width = padded_width; data_head->info.video.height = padded_height; data_head->info.video.stride = padded_width; data_head->nr_of_dataelems = nr_of_bufs; data_head->write_nr = 0; image_bufs = malloc(nr_of_bufs*sizeof(yuv_image_t)); data_elems =(picture_data_elem_t *)(data_shmaddr + sizeof(data_buf_head_t)); picture_data_offset = picture_ctrl_size; // TODO this is an ugly hack for not mixing in ref.frames#ifdef HAVE_XV for(n = 0; n < (data_head->nr_of_dataelems+1); n++) {#else for(n = 0; n < data_head->nr_of_dataelems; n++) {#endif data_elems[n].displayed = 1; data_elems[n].is_reference = 0; data_elems[n].picture.y_offset = picture_data_offset; image_bufs[n].y = data_shmaddr + picture_data_offset; data_elems[n].picture.v_offset = picture_data_offset + y_size; image_bufs[n].v = data_shmaddr + picture_data_offset + y_size; data_elems[n].picture.u_offset = picture_data_offset + y_size + uv_size; image_bufs[n].u = data_shmaddr + picture_data_offset+y_size+uv_size; data_elems[n].picture.horizontal_size = seq.horizontal_size; data_elems[n].picture.vertical_size = seq.vertical_size; data_elems[n].picture.start_x = 0; data_elems[n].picture.start_y = 0; data_elems[n].picture.padded_width = padded_width; data_elems[n].picture.padded_height = padded_height; picture_data_offset += picture_size; } fwd_ref_image = &image_bufs[0]; bwd_ref_image = &image_bufs[1]; /* send create decoder request msg*/ ev.type = MsgEventQReqPicBuf; ev.reqpicbuf.nr_of_elems = nr_of_bufs; ev.reqpicbuf.data_buf_shmid = data_shmid; if(MsgSendEvent(msgq, CLIENT_RESOURCE_MANAGER, &ev, 0) == -1) { ERROR("%s", "couldn't send picbuf request\n"); } /* wait for answer */ while(1) { if(MsgNextEvent(msgq, &ev) != -1) { if(ev.type == MsgEventQGntPicBuf) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -