int es_info_read(elementary_stream_info_t *es, bs_t *b) { int es_info_start = bs_pos(b); es->stream_type = bs_read_u8(b); bs_skip_u(b, 3); es->elementary_PID = bs_read_u(b, 13); bs_skip_u(b, 4); es->ES_info_length = bs_read_u(b, 12); LOG_DEBUG_ARGS ("es_info_read: es_info_start = %d, bs_pos(b) = %d, b->end = %d", es_info_start, bs_pos(b), b->end - b->start); LOG_DEBUG_ARGS ("es_info_read pre-return %d", bs_pos(b) - es_info_start); LOG_DEBUG_ARGS ("es_info_read: PID = %d, streamType = 0x%x, ES_info_length = %d. Calling read_descriptor_loop", es->elementary_PID, es->stream_type, es->ES_info_length); read_descriptor_loop(es->descriptors, b, es->ES_info_length); if (es->ES_info_length > MAX_ES_INFO_LEN) { LOG_ERROR_ARGS("ES info length is 0x%02X, larger than maximum allowed 0x%02X", es->ES_info_length, MAX_ES_INFO_LEN); reportAddErrorLogArgs("ES info length is 0x%02X, larger than maximum allowed 0x%02X", es->ES_info_length, MAX_ES_INFO_LEN); SAFE_REPORT_TS_ERR(-60); return 0; } LOG_DEBUG_ARGS ("es_info_read returning %d", bs_pos(b) - es_info_start); return bs_pos(b) - es_info_start; }
// "factory methods" int read_descriptor_loop(vqarray_t *desc_list, bs_t *b, int length) { int desc_start = bs_pos(b); while (length > bs_pos(b) - desc_start) { descriptor_t *desc = descriptor_new(); desc = descriptor_read(desc, b); vqarray_add(desc_list, desc); } return bs_pos(b) - desc_start; }
int bd_clpi_ep_map_Parse( bd_clpi_ep_map_t *p_ep_map, bs_t *s, const int i_ep_map_start ) { p_ep_map->i_pid = bs_read( s, 16 ); bs_skip( s, 10 ); p_ep_map->i_type = bs_read( s, 4 ); const int i_coarse = bs_read( s, 16 ); const int i_fine = bs_read( s, 18 ); const uint32_t i_coarse_start = bs_read( s, 32 ); p_ep_map->i_ep = i_fine; p_ep_map->p_ep = (bd_clpi_ep_t *)calloc( i_fine, sizeof(*p_ep_map->p_ep) ); // sunqueen modify if( !p_ep_map->p_ep ) return VLC_EGENERIC; bs_t cs = *s; bs_skip( &cs, 8*(i_ep_map_start + i_coarse_start) - bs_pos( s ) ); const uint32_t i_fine_start = bs_read( &cs, 32 ); for( int i = 0; i < i_coarse; i++ ) { const int i_fine_id = bs_read( &cs, 18 ); const int i_pts = bs_read( &cs, 14 ); const uint32_t i_packet = bs_read( &cs, 32 ); for( int j = i_fine_id; j < p_ep_map->i_ep; j++ ) { p_ep_map->p_ep[j].i_pts = (int64_t)(i_pts & ~1) << 19; p_ep_map->p_ep[j].i_packet = i_packet & ~( (1 << 17) - 1 ); } } bs_t fs = *s; bs_skip( &fs, 8*(i_ep_map_start + i_coarse_start + i_fine_start) - bs_pos( s ) ); for( int i = 0; i < i_fine; i++ ) { const bool b_angle_point = bs_read( &fs, 1 ); bs_skip( &fs, 3 ); /* I end position offset */ const int i_pts = bs_read( &fs, 11 ); const int i_packet = bs_read( &fs, 17 ); p_ep_map->p_ep[i].b_angle_point = b_angle_point; p_ep_map->p_ep[i].i_pts |= i_pts << 9; p_ep_map->p_ep[i].i_packet |= i_packet; } return VLC_SUCCESS; }
static int _parse_index(BITSTREAM *bs, INDX_ROOT *index) { uint32_t index_len, i; index_len = bs_read(bs, 32); /* TODO: check if goes to extension data area */ if ((bs_end(bs) - bs_pos(bs))/8 < (int64_t)index_len) { BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: invalid index_len %d !\n", index_len); return 0; } if (!_parse_playback_obj(bs, &index->first_play) || !_parse_playback_obj(bs, &index->top_menu)) { return 0; } index->num_titles = bs_read(bs, 16); if (!index->num_titles) { BD_DEBUG(DBG_CRIT, "empty index\n"); return 0; } index->titles = calloc(index->num_titles, sizeof(INDX_TITLE)); if (!index->titles) { BD_DEBUG(DBG_CRIT, "out of memory\n"); return 0; } if (bs_avail(bs)/(12*8) < index->num_titles) { BD_DEBUG(DBG_HDMV|DBG_CRIT, "index.bdmv: unexpected EOF\n"); return 0; } for (i = 0; i < index->num_titles; i++) { index->titles[i].object_type = bs_read(bs, 2); index->titles[i].access_type = bs_read(bs, 2); bs_skip(bs, 28); switch (index->titles[i].object_type) { case indx_object_type_hdmv: if (!_parse_hdmv_obj(bs, &index->titles[i].hdmv)) return 0; break; case indx_object_type_bdj: if (!_parse_bdj_obj(bs, &index->titles[i].bdj)) return 0; break; default: BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: unknown object type %d (#%d)\n", index->titles[i].object_type, i); return 0; } } return 1; }
void x264_sei_pic_timing_write( x264_t *h, bs_t *s ) { x264_sps_t *sps = h->sps; bs_t q; uint8_t tmp_buf[100]; bs_init( &q, tmp_buf, 100 ); bs_realign( &q ); if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present ) { bs_write( &q, sps->vui.hrd.i_cpb_removal_delay_length, h->fenc->i_cpb_delay - h->i_cpb_delay_pir_offset ); bs_write( &q, sps->vui.hrd.i_dpb_output_delay_length, h->fenc->i_dpb_output_delay ); } if( sps->vui.b_pic_struct_present ) { bs_write( &q, 4, h->fenc->i_pic_struct-1 ); // We use index 0 for "Auto" // These clock timestamps are not standardised so we don't set them // They could be time of origin, capture or alternative ideal display for( int i = 0; i < num_clock_ts[h->fenc->i_pic_struct]; i++ ) bs_write1( &q, 0 ); // clock_timestamp_flag } bs_align_10( &q ); bs_flush( &q ); x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_PIC_TIMING ); }
static MOBJ_OBJECTS *_mobj_parse(BD_FILE_H *fp) { BITSTREAM bs; MOBJ_OBJECTS *objects = NULL; uint16_t num_objects; uint32_t data_len; int extension_data_start, i; bs_init(&bs, fp); if (!_mobj_parse_header(&bs, &extension_data_start)) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: invalid header\n"); goto error; } if (extension_data_start) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: unknown extension data at %d\n", extension_data_start); } bs_seek_byte(&bs, 40); data_len = bs_read(&bs, 32); if ((bs_end(&bs) - bs_pos(&bs))/8 < (int64_t)data_len) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: invalid data_len %d !\n", data_len); goto error; } objects = calloc(1, sizeof(MOBJ_OBJECTS)); if (!objects) { BD_DEBUG(DBG_CRIT, "out of memory\n"); goto error; } bs_skip(&bs, 32); /* reserved */ num_objects = bs_read(&bs, 16); objects->num_objects = num_objects; objects->objects = calloc(num_objects, sizeof(MOBJ_OBJECT)); if (!objects->objects) { BD_DEBUG(DBG_CRIT, "out of memory\n"); goto error; } for (i = 0; i < objects->num_objects; i++) { if (!_mobj_parse_object(&bs, &objects->objects[i])) { BD_DEBUG(DBG_NAV | DBG_CRIT, "MovieObject.bdmv: error parsing object %d\n", i); goto error; } } return objects; error: mobj_free(&objects); return NULL; }
int es_info_read(elementary_stream_info_t *es, bs_t *b) { int es_info_start = bs_pos(b); es->stream_type = bs_read_u8(b); bs_skip_u(b, 3); es->elementary_PID = bs_read_u(b, 13); bs_skip_u(b, 4); es->ES_info_length = bs_read_u(b, 12); read_descriptor_loop(es->descriptors, b, es->ES_info_length); if (es->ES_info_length > MAX_ES_INFO_LEN) { LOG_ERROR_ARGS("ES info length is 0x%02X, larger than maximum allowed 0x%02X", es->ES_info_length, MAX_ES_INFO_LEN); SAFE_REPORT_TS_ERR(-60); return 0; } return bs_pos(b) - es_info_start; }
static MOBJ_OBJECTS *_mobj_parse(const char *file_name) { BITSTREAM bs; BD_FILE_H *fp; MOBJ_OBJECTS *objects = NULL; uint16_t num_objects; uint32_t data_len; int extension_data_start, i; fp = file_open(file_name, "rb"); if (!fp) { BD_DEBUG(DBG_NAV | DBG_CRIT, "error opening %s\n", file_name); return NULL; } bs_init(&bs, fp); if (!_mobj_parse_header(&bs, &extension_data_start)) { BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: invalid header\n", file_name); goto error; } bs_seek_byte(&bs, 40); data_len = bs_read(&bs, 32); if ((bs_end(&bs) - bs_pos(&bs))/8 < (off_t)data_len) { BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: invalid data_len %d !\n", file_name, data_len); goto error; } bs_skip(&bs, 32); /* reserved */ num_objects = bs_read(&bs, 16); objects = calloc(1, sizeof(MOBJ_OBJECTS)); objects->num_objects = num_objects; objects->objects = calloc(num_objects, sizeof(MOBJ_OBJECT)); for (i = 0; i < objects->num_objects; i++) { if (!_mobj_parse_object(&bs, &objects->objects[i])) { BD_DEBUG(DBG_NAV | DBG_CRIT, "%s: error parsing object %d\n", file_name, i); goto error; } } file_close(fp); return objects; error: mobj_free(&objects); file_close(fp); return NULL; }
int x264_rd_cost_mb( x264_t *h, int i_lambda2 ) { // backup mb_type because x264_macroblock_encode may change it to skip int i_type_bak = h->mb.i_type; int b_transform_bak = h->mb.b_transform_8x8; int i_ssd; int i_bits; x264_macroblock_encode( h ); i_ssd = h->pixf.ssd[PIXEL_16x16]( h->mb.pic.p_fenc[0], h->mb.pic.i_stride[0], h->mb.pic.p_fdec[0], h->mb.pic.i_stride[0] ) + h->pixf.ssd[PIXEL_8x8]( h->mb.pic.p_fenc[1], h->mb.pic.i_stride[1], h->mb.pic.p_fdec[1], h->mb.pic.i_stride[1] ) + h->pixf.ssd[PIXEL_8x8]( h->mb.pic.p_fenc[2], h->mb.pic.i_stride[2], h->mb.pic.p_fdec[2], h->mb.pic.i_stride[2] ); if( IS_SKIP( h->mb.i_type ) ) { i_bits = 1; } else if( h->param.b_cabac ) { x264_cabac_t cabac_tmp = h->cabac; bs_t bs_tmp = h->out.bs; cabac_tmp.s = &bs_tmp; x264_macroblock_write_cabac( h, &cabac_tmp ); i_bits = x264_cabac_pos( &cabac_tmp ) - x264_cabac_pos( &h->cabac ); } else { bs_t bs_tmp = h->out.bs; x264_macroblock_write_cavlc( h, &bs_tmp ); i_bits = bs_pos( &bs_tmp ) - bs_pos( &h->out.bs ); } h->mb.i_type = i_type_bak; h->mb.b_transform_8x8 = b_transform_bak; return i_ssd + i_bits * i_lambda2; }
int pes_read(pes_packet_t *pes, uint8_t *buf, size_t len) { if (buf == NULL || pes == NULL) return 0; bs_t b; bs_init(&b, buf, len); int header_bytes = pes_read_header(&pes->header, &b); if (header_bytes > 0) { pes->payload.len = len - header_bytes; pes->payload.bytes = (uint8_t *) realloc(pes->payload.bytes, pes->payload.len); bs_read_bytes(&b, pes->payload.bytes, pes->payload.len); } return bs_pos(&b); }
void bd_mpls_sub_path_Parse( bd_mpls_sub_path_t *p_path, bs_t *s ) { const uint32_t i_length = bs_read( s, 32 ); const int i_start = bs_pos( s ) / 8; bs_skip( s, 8 ); p_path->i_type = bs_read( s, 8 ); bs_skip( s, 15 ); p_path->b_repeat = bs_read( s, 1 ); bs_skip( s, 8 ); p_path->i_item = bs_read( s, 8 ); for( int j = 0; j < p_path->i_item; j++ ) { const int i_length = bs_read( s, 16 ); const int i_start = bs_pos( s ) / 8; /* TODO */ bs_skip( s, 8 * ( i_start + i_length ) - bs_pos( s ) ); } bs_skip( s, 8 * ( i_start + i_length ) - bs_pos( s ) ); }
int write_avcc(avcc_t* avcc, h264_stream_t* h, bs_t* b) { bs_write_u8(b, 1); // configurationVersion = 1; bs_write_u8(b, avcc->AVCProfileIndication); bs_write_u8(b, avcc->profile_compatibility); bs_write_u8(b, avcc->AVCLevelIndication); bs_write_u(b, 6, 0x3F); // reserved = '111111'b; bs_write_u(b, 2, avcc->lengthSizeMinusOne); bs_write_u(b, 3, 0x07); // reserved = '111'b; bs_write_u(b, 5, avcc->numOfSequenceParameterSets); int i; for (i = 0; i < avcc->numOfSequenceParameterSets; i++) { int max_len = 1024; // FIXME uint8_t* buf = (uint8_t*)malloc(max_len); h->nal->nal_ref_idc = 3; // NAL_REF_IDC_PRIORITY_HIGHEST; h->nal->nal_unit_type = NAL_UNIT_TYPE_SPS; h->sps = avcc->sps_table[i]; int len = write_nal_unit(h, buf, max_len); if (len < 0) { free(buf); continue; } // TODO report errors int sequenceParameterSetLength = len; bs_write_u(b, 16, sequenceParameterSetLength); bs_write_bytes(b, buf, len); free(buf); } bs_write_u(b, 8, avcc->numOfPictureParameterSets); for (i = 0; i < avcc->numOfPictureParameterSets; i++) { int max_len = 1024; // FIXME uint8_t* buf = (uint8_t*)malloc(max_len); h->nal->nal_ref_idc = 3; // NAL_REF_IDC_PRIORITY_HIGHEST; h->nal->nal_unit_type = NAL_UNIT_TYPE_PPS; h->pps = avcc->pps_table[i]; int len = write_nal_unit(h, buf, max_len); if (len < 0) { free(buf); continue; } // TODO report errors int pictureParameterSetLength = len; bs_write_u(b, 16, pictureParameterSetLength); bs_write_bytes(b, buf, len); free(buf); } if (bs_overrun(b)) { return -1; } return bs_pos(b); }
int read_avcc(avcc_t* avcc, h264_stream_t* h, bs_t* b) { avcc->configurationVersion = bs_read_u8(b); avcc->AVCProfileIndication = bs_read_u8(b); avcc->profile_compatibility = bs_read_u8(b); avcc->AVCLevelIndication = bs_read_u8(b); /* int reserved = */ bs_read_u(b, 6); // '111111'b; avcc->lengthSizeMinusOne = bs_read_u(b, 2); /* int reserved = */ bs_read_u(b, 3); // '111'b; avcc->numOfSequenceParameterSets = bs_read_u(b, 5); avcc->sps_table = (sps_t**)calloc(avcc->numOfSequenceParameterSets, sizeof(sps_t*)); int i; for (i = 0; i < avcc->numOfSequenceParameterSets; i++) { int sequenceParameterSetLength = bs_read_u(b, 16); int len = sequenceParameterSetLength; uint8_t* buf = (uint8_t*)malloc(len); len = bs_read_bytes(b, buf, len); int rc = read_nal_unit(h, buf, len); free(buf); if (h->nal->nal_unit_type != NAL_UNIT_TYPE_SPS) { continue; } // TODO report errors if (rc < 0) { continue; } avcc->sps_table[i] = h->sps; // TODO copy data? } avcc->numOfPictureParameterSets = bs_read_u(b, 8); avcc->pps_table = (pps_t**)calloc(avcc->numOfSequenceParameterSets, sizeof(pps_t*)); for (i = 0; i < avcc->numOfPictureParameterSets; i++) { int pictureParameterSetLength = bs_read_u(b, 16); int len = pictureParameterSetLength; uint8_t* buf = (uint8_t*)malloc(len); len = bs_read_bytes(b, buf, len); int rc = read_nal_unit(h, buf, len); free(buf); if (h->nal->nal_unit_type != NAL_UNIT_TYPE_PPS) { continue; } // TODO report errors if (rc < 0) { continue; } avcc->pps_table[i] = h->pps; // TODO copy data? } if (bs_overrun(b)) { return -1; } return bs_pos(b); }
void x264_sei_recovery_point_write( x264_t *h, bs_t *s, int recovery_frame_cnt ) { bs_t q; uint8_t tmp_buf[100]; bs_init( &q, tmp_buf, 100 ); bs_realign( &q ); bs_write_ue( &q, recovery_frame_cnt ); // recovery_frame_cnt bs_write1( &q, 1 ); //exact_match_flag 1 bs_write1( &q, 0 ); //broken_link_flag 0 bs_write( &q, 2, 0 ); //changing_slice_group 0 bs_align_10( &q ); bs_flush( &q ); x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_RECOVERY_POINT ); }
void x264_sei_buffering_period_write( x264_t *h, bs_t *s ) { x264_sps_t *sps = h->sps; bs_t q; uint8_t tmp_buf[100]; bs_init( &q, tmp_buf, 100 ); bs_realign( &q ); bs_write_ue( &q, sps->i_id ); if( sps->vui.b_nal_hrd_parameters_present ) { bs_write( &q, sps->vui.hrd.i_initial_cpb_removal_delay_length, h->initial_cpb_removal_delay ); bs_write( &q, sps->vui.hrd.i_initial_cpb_removal_delay_length, h->initial_cpb_removal_delay_offset ); } bs_align_10( &q ); bs_flush( &q ); x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_BUFFERING_PERIOD ); }
void x264_sei_frame_packing_write( x264_t *h, bs_t *s ) { bs_t q; uint8_t tmp_buf[100]; bs_init( &q, tmp_buf, 100 ); bs_realign( &q ); bs_write_ue( &q, 0 ); // frame_packing_arrangement_id bs_write1( &q, 0 ); // frame_packing_arrangement_cancel_flag bs_write ( &q, 7, h->param.i_frame_packing ); // frame_packing_arrangement_type bs_write1( &q, 0 ); // quincunx_sampling_flag // 0: views are unrelated, 1: left view is on the left, 2: left view is on the right bs_write ( &q, 6, 1 ); // content_interpretation_type bs_write1( &q, 0 ); // spatial_flipping_flag bs_write1( &q, 0 ); // frame0_flipped_flag bs_write1( &q, 0 ); // field_views_flag bs_write1( &q, h->param.i_frame_packing == 5 && !(h->fenc->i_frame&1) ); // current_frame_is_frame0_flag bs_write1( &q, 0 ); // frame0_self_contained_flag bs_write1( &q, 0 ); // frame1_self_contained_flag if ( /* quincunx_sampling_flag == 0 && */ h->param.i_frame_packing != 5 ) { bs_write( &q, 4, 0 ); // frame0_grid_position_x bs_write( &q, 4, 0 ); // frame0_grid_position_y bs_write( &q, 4, 0 ); // frame1_grid_position_x bs_write( &q, 4, 0 ); // frame1_grid_position_y } bs_write( &q, 8, 0 ); // frame_packing_arrangement_reserved_byte bs_write_ue( &q, 1 ); // frame_packing_arrangement_repetition_period bs_write1( &q, 0 ); // frame_packing_arrangement_extension_flag bs_align_10( &q ); bs_flush( &q ); x264_sei_write( s, tmp_buf, bs_pos( &q ) / 8, SEI_FRAME_PACKING ); }
int conditional_access_section_read(conditional_access_section_t *cas, uint8_t *buf, size_t buf_len, uint32_t payload_unit_start_indicator, psi_table_buffer_t *catBuffer) { if (cas == NULL || buf == NULL) { SAFE_REPORT_TS_ERR(-1); return 0; } bs_t *b = NULL; if (!payload_unit_start_indicator && catBuffer->buffer == NULL) { // this TS packet is not start of table, and we have no cached table data LOG_WARN ("conditional_access_section_read: payload_unit_start_indicator not set and no cached data"); return 0; } if (payload_unit_start_indicator) { uint8_t payloadStartPtr = buf[0]; buf += (payloadStartPtr + 1); buf_len -= (payloadStartPtr + 1); LOG_DEBUG_ARGS ("conditional_access_section_read: payloadStartPtr = %d", payloadStartPtr); } // check for pat spanning multiple TS packets if (catBuffer->buffer != NULL) { LOG_DEBUG_ARGS ("conditional_access_section_read: catBuffer detected: catBufferAllocSz = %d, catBufferUsedSz = %d", catBuffer->bufferAllocSz, catBuffer->bufferUsedSz); size_t numBytesToCopy = buf_len; if (buf_len > (catBuffer->bufferAllocSz - catBuffer->bufferUsedSz)) { numBytesToCopy = catBuffer->bufferAllocSz - catBuffer->bufferUsedSz; } LOG_DEBUG_ARGS ("conditional_access_section_read: copying %d bytes to catBuffer", numBytesToCopy); memcpy (catBuffer->buffer + catBuffer->bufferUsedSz, buf, numBytesToCopy); catBuffer->bufferUsedSz += numBytesToCopy; if (catBuffer->bufferUsedSz < catBuffer->bufferAllocSz) { LOG_DEBUG ("conditional_access_section_read: catBuffer not yet full -- returning"); return 0; } b = bs_new(catBuffer->buffer, catBuffer->bufferUsedSz); } else { b = bs_new(buf, buf_len); } cas->table_id = bs_read_u8(b); if (cas->table_id != conditional_access_section) { LOG_ERROR_ARGS("Table ID in CAT is 0x%02X instead of expected 0x%02X", cas->table_id, conditional_access_section); reportAddErrorLogArgs("Table ID in CAT is 0x%02X instead of expected 0x%02X", cas->table_id, conditional_access_section); SAFE_REPORT_TS_ERR(-30); resetPSITableBuffer(catBuffer); bs_free (b); return 0; } // read byte 0 cas->section_syntax_indicator = bs_read_u1(b); if (!cas->section_syntax_indicator) { LOG_ERROR("section_syntax_indicator not set in CAT"); reportAddErrorLog("section_syntax_indicator not set in CAT"); SAFE_REPORT_TS_ERR(-31); resetPSITableBuffer(catBuffer); bs_free (b); return 0; } bs_skip_u(b, 3); // TODO read the zero bit, check it to be zero cas->section_length = bs_read_u(b, 12); if (cas->section_length > 1021) // max CAT length { LOG_ERROR_ARGS("CAT section length is 0x%02X, larger than maximum allowed 0x%02X", cas->section_length, MAX_SECTION_LEN); reportAddErrorLogArgs("CAT section length is 0x%02X, larger than maximum allowed 0x%02X", cas->section_length, MAX_SECTION_LEN); SAFE_REPORT_TS_ERR(-32); resetPSITableBuffer(catBuffer); bs_free (b); return 0; } if (cas->section_length > bs_bytes_left(b)) { LOG_DEBUG ("conditional_access_section_read: Detected section spans more than one TS packet -- allocating buffer"); if (catBuffer->buffer != NULL) { // should never get here LOG_ERROR ("conditional_access_section_read: unexpected catBufffer"); reportAddErrorLog ("conditional_access_section_read: unexpected catBufffer"); resetPSITableBuffer(catBuffer); } catBuffer->bufferAllocSz = cas->section_length + 3; catBuffer->buffer = (uint8_t *)calloc (cas->section_length + 3, 1); memcpy (catBuffer->buffer, buf, buf_len); catBuffer->bufferUsedSz = buf_len; bs_free (b); return 0; } // read bytes 1-2 bs_read_u16(b); // read bytes 3,4 bs_skip_u(b, 2); cas->version_number = bs_read_u(b, 5); cas->current_next_indicator = bs_read_u1(b); if (!cas->current_next_indicator) LOG_WARN("This CAT is not yet applicable/n"); // read byte 5 cas->section_number = bs_read_u8(b); cas->last_section_number = bs_read_u8(b); if (cas->section_number != 0 || cas->last_section_number != 0) LOG_WARN("Multi-section CAT is not supported yet/n"); // read bytes 6,7 read_descriptor_loop(cas->descriptors, b, cas->section_length - 5 - 4 ); // explanation: section_length gives us the length from the end of section_length // we used 5 bytes for the mandatory section fields, and will use another 4 bytes for CRC // the remaining bytes contain descriptors, most probably only one // again, it's much shorter in C :-) cas->CRC_32 = bs_read_u32(b); // check CRC crc_t cas_crc = crc_init(); cas_crc = crc_update(cas_crc, buf, bs_pos(b) - 4); cas_crc = crc_finalize(cas_crc); if (cas_crc != cas->CRC_32) { LOG_ERROR_ARGS("CAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", cas->CRC_32, cas_crc); reportAddErrorLogArgs("CAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", cas->CRC_32, cas_crc); SAFE_REPORT_TS_ERR(-33); resetPSITableBuffer(catBuffer); bs_free (b); return 0; } bs_free(b); resetPSITableBuffer(catBuffer); return 1; }
int program_map_section_read(program_map_section_t *pms, uint8_t *buf, size_t buf_size, uint32_t payload_unit_start_indicator, psi_table_buffer_t *pmtBuffer) { LOG_DEBUG ("program_map_section_read -- entering"); if (pms == NULL || buf == NULL) { SAFE_REPORT_TS_ERR(-1); return 0; } bs_t *b = NULL; if (!payload_unit_start_indicator && pmtBuffer->buffer == NULL) { // this TS packet is not start of table, and we have no cached table data LOG_WARN ("program_map_section_read: payload_unit_start_indicator not set and no cached data"); return 0; } if (payload_unit_start_indicator) { uint8_t payloadStartPtr = buf[0]; buf += (payloadStartPtr + 1); buf_size -= (payloadStartPtr + 1); LOG_DEBUG_ARGS ("program_map_section_read: payloadStartPtr = %d", payloadStartPtr); } // check for pmt spanning multiple TS packets if (pmtBuffer->buffer != NULL) { LOG_DEBUG_ARGS ("program_map_section_read: pmtBuffer detected: pmtBufferAllocSz = %d, pmtBufferUsedSz = %d", pmtBuffer->bufferAllocSz, pmtBuffer->bufferUsedSz); size_t numBytesToCopy = buf_size; if (buf_size > (pmtBuffer->bufferAllocSz - pmtBuffer->bufferUsedSz)) { numBytesToCopy = pmtBuffer->bufferAllocSz - pmtBuffer->bufferUsedSz; } LOG_DEBUG_ARGS ("program_map_section_read: copying %d bytes to pmtBuffer", numBytesToCopy); memcpy (pmtBuffer->buffer + pmtBuffer->bufferUsedSz, buf, numBytesToCopy); pmtBuffer->bufferUsedSz += numBytesToCopy; if (pmtBuffer->bufferUsedSz < pmtBuffer->bufferAllocSz) { LOG_DEBUG ("program_map_section_read: pmtBuffer not yet full -- returning"); return 0; } b = bs_new(pmtBuffer->buffer, pmtBuffer->bufferUsedSz); } else { b = bs_new(buf, buf_size); } pms->table_id = bs_read_u8(b); if (pms->table_id != TS_program_map_section) { LOG_ERROR_ARGS("Table ID in PMT is 0x%02X instead of expected 0x%02X", pms->table_id, TS_program_map_section); reportAddErrorLogArgs("Table ID in PMT is 0x%02X instead of expected 0x%02X", pms->table_id, TS_program_map_section); SAFE_REPORT_TS_ERR(-40); resetPSITableBuffer(pmtBuffer); bs_free (b); return 0; } pms->section_syntax_indicator = bs_read_u1(b); if (!pms->section_syntax_indicator) { LOG_ERROR("section_syntax_indicator not set in PMT"); reportAddErrorLog("section_syntax_indicator not set in PMT"); SAFE_REPORT_TS_ERR(-41); resetPSITableBuffer(pmtBuffer); bs_free (b); return 0; } bs_skip_u(b, 3); pms->section_length = bs_read_u(b, 12); if (pms->section_length > MAX_SECTION_LEN) { LOG_ERROR_ARGS("PMT section length is 0x%02X, larger than maximum allowed 0x%02X", pms->section_length, MAX_SECTION_LEN); reportAddErrorLogArgs("PMT section length is 0x%02X, larger than maximum allowed 0x%02X", pms->section_length, MAX_SECTION_LEN); SAFE_REPORT_TS_ERR(-42); resetPSITableBuffer(pmtBuffer); bs_free (b); return 0; } if (pms->section_length > bs_bytes_left(b)) { LOG_DEBUG ("program_map_section_read: Detected section spans more than one TS packet -- allocating buffer"); if (pmtBuffer->buffer != NULL) { // should never get here LOG_ERROR ("program_map_section_read: unexpected pmtBufffer"); reportAddErrorLog ("program_map_section_read: unexpected pmtBufffer"); resetPSITableBuffer(pmtBuffer); } pmtBuffer->bufferAllocSz = pms->section_length + 3; pmtBuffer->buffer = (uint8_t *)calloc (pms->section_length + 3, 1); memcpy (pmtBuffer->buffer, buf, buf_size); pmtBuffer->bufferUsedSz = buf_size; bs_free (b); return 0; } int section_start = bs_pos(b); // bytes 0,1 pms->program_number = bs_read_u16(b); // byte 2; bs_skip_u(b, 2); pms->version_number = bs_read_u(b, 5); pms->current_next_indicator = bs_read_u1(b); if (!pms->current_next_indicator) LOG_WARN("This PMT is not yet applicable/n"); // bytes 3,4 pms->section_number = bs_read_u8(b); pms->last_section_number = bs_read_u8(b); if (pms->section_number != 0 || pms->last_section_number != 0) { LOG_ERROR("Multi-section PMT is not allowed/n"); reportAddErrorLog("Multi-section PMT is not allowed/n"); SAFE_REPORT_TS_ERR(-43); resetPSITableBuffer(pmtBuffer); bs_free (b); return 0; } bs_skip_u(b, 3); pms->PCR_PID = bs_read_u(b, 13); if (pms->PCR_PID < GENERAL_PURPOSE_PID_MIN || pms->PCR_PID > GENERAL_PURPOSE_PID_MAX) { LOG_ERROR_ARGS("PCR PID has invalid value 0x%02X", pms->PCR_PID); reportAddErrorLogArgs("PCR PID has invalid value 0x%02X", pms->PCR_PID); SAFE_REPORT_TS_ERR(-44); resetPSITableBuffer(pmtBuffer); bs_free (b); return 0; } // printf ("PCR PID = %d\n", pms->PCR_PID); bs_skip_u(b, 4); pms->program_info_length = bs_read_u(b, 12); if (pms->program_info_length > MAX_PROGRAM_INFO_LEN) { LOG_ERROR_ARGS("PMT program info length is 0x%02X, larger than maximum allowed 0x%02X", pms->program_info_length, MAX_PROGRAM_INFO_LEN); reportAddErrorLogArgs("PMT program info length is 0x%02X, larger than maximum allowed 0x%02X", pms->program_info_length, MAX_PROGRAM_INFO_LEN); SAFE_REPORT_TS_ERR(-45); resetPSITableBuffer(pmtBuffer); bs_free (b); return 0; } read_descriptor_loop(pms->descriptors, b, pms->program_info_length); while (!bs_eof(b) && pms->section_length - (bs_pos(b) - section_start) > 4) // account for CRC { elementary_stream_info_t *es = es_info_new(); es_info_read(es, b); vqarray_add(pms->es_info, es); } pms->CRC_32 = bs_read_u32(b); // check CRC crc_t pas_crc = crc_init(); pas_crc = crc_update(pas_crc, b->start, bs_pos(b) - 4); pas_crc = crc_finalize(pas_crc); if (pas_crc != pms->CRC_32) { LOG_ERROR_ARGS("PMT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pms->CRC_32, pas_crc); reportAddErrorLogArgs("PMT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pms->CRC_32, pas_crc); SAFE_REPORT_TS_ERR(-46); resetPSITableBuffer(pmtBuffer); bs_free (b); return 0; } else { // LOG_DEBUG("PMT CRC_32 checked successfully"); } int bytes_read = bs_pos(b); bs_free(b); resetPSITableBuffer(pmtBuffer); return bytes_read; }
//-------------------------------------------------------------------------------------------------------------------------------- // Ray ///------------------------------------------------------------------------------------------------------------------------------- bool COLLISION_WORLD::CastRay( const MATHVECTOR<float,3> & origin, const MATHVECTOR<float,3> & direction, const float length, const btCollisionObject * caster, COLLISION_CONTACT & contact, //out CARDYNAMICS* cd, int w, //out pCarDyn, nWheel bool ignoreCars, bool camTilt, bool camDist) const { btVector3 from = ToBulletVector(origin); btVector3 to = ToBulletVector(origin + direction * length); MyRayResultCallback res(from, to, caster, ignoreCars, camTilt, camDist); // data to set MATHVECTOR<float,3> pos, norm; float dist; const TRACKSURFACE * surf = TRACKSURFACE::None(); btCollisionObject * col = NULL; const BEZIER * bzr = NULL; world->rayTest(from, to, res); bool geometryHit = res.hasHit(); if (geometryHit) { pos = ToMathVector<float>(res.m_hitPointWorld); norm = ToMathVector<float>(res.m_hitNormalWorld); dist = res.m_closestHitFraction * length; col = res.m_collisionObject; const TerData& td = pApp->scn->sc->td; if (col->isStaticObject() /*&& (c->getCollisionFlags() & btCollisionObject::CF_NO_CONTACT_RESPONSE == 0)*/) { long long ptrU = (long long)col->getCollisionShape()->getUserPointer(), su = ptrU & 0xFF00, mtr = ptrU & 0xFF; //void* /// set surface, basing on shape type ----------------- if (ptrU) switch (su) { case SU_Road: // road { int id = td.layerRoad.surfId; // Road[mtr]. surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 1; cd->whRoadMtr[w] = mtr; cd->whTerMtr[w] = 0; } } break; case SU_Pipe: // pipe { int id = td.layerRoad.surfId; surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 2; cd->whRoadMtr[w] = mtr+30; cd->whTerMtr[w] = 0; } } break; case SU_Terrain: // Terrain get surface from blendmap mtr { int t = pApp->blendMapSize; float tws = td.fTerWorldSize; int mx = (pos[0] + 0.5*tws)/tws*t; mx = std::max(0,std::min(t-1, mx)); int my = (pos[1] + 0.5*tws)/tws*t; my = std::max(0,std::min(t-1, t-1-my)); int mtr = pApp->blendMtr[my*t + mx]; int id = td.layersAll[td.layers[mtr]].surfId; surf = &pApp->pGame->surfaces[id]; if (cd) // mtr 0 = not on terrain { cd->iWhOnRoad[w] = 0; cd->whRoadMtr[w] = 60; cd->whTerMtr[w] = mtr + 1; } } break; //case SU_RoadWall: //case SU_RoadColumn: //case SU_Vegetation: case SU_Border: //case SU_ObjectStatic: //case SU_ObjectDynamic: default: { int id = td.layerRoad.surfId; surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 0; cd->whRoadMtr[w] = 80; cd->whTerMtr[w] = 0; } } break; } else //if (ptrU == 0) { int id = td.layersAll[0].surfId; //0 only 1st surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 0; cd->whRoadMtr[w] = 0; cd->whTerMtr[w] = 1; } /*void * ptr = col->getUserPointer(); if (ptr != NULL) { const TRACK_OBJECT * const obj = reinterpret_cast <const TRACK_OBJECT * const> (ptr); assert(obj); surf = obj->GetSurface(); } else // track geometry { int shapeId = res.m_shapeId; //assert(shapeId >= 0 && shapeId < trackSurface.size()); if (shapeId >= trackSurface.size() || shapeId < 0) shapeId = 0; //crash hf- if (trackSurface.size() > 0) surf = 0;//trackSurface[shapeId]; }*/ } } // track bezierpatch collision if (track != NULL) { MATHVECTOR<float,3> bs_pos(origin[1], origin[2], origin[0]); //bezierspace MATHVECTOR<float,3> bs_dir(direction[1], direction[2], direction[0]); MATHVECTOR<float,3> colpos, colnorm; const BEZIER * colpatch = NULL; bool bezierHit = track->CastRay(bs_pos, bs_dir, length, colpos, colpatch, colnorm); if (bezierHit) { pos = MATHVECTOR<float,3> (colpos[2], colpos[0], colpos[1]); norm = MATHVECTOR<float,3> (colnorm[2], colnorm[0], colnorm[1]); dist = (colpos - bs_pos).Magnitude(); //surf = 0;//track->GetRoadSurface(); bzr = colpatch; col = NULL; int id = td.layerRoad.surfId; surf = &pApp->pGame->surfaces[id]; if (cd) { cd->iWhOnRoad[w] = 1; cd->whRoadMtr[w] = 0; cd->whTerMtr[w] = 0; } } } contact.Set(pos, norm, dist, surf, bzr, col); return true; } // should only happen on vehicle rollover contact.Set(origin + direction * length, -direction, length, surf, bzr, col); return false; }
int program_association_section_read(program_association_section_t *pas, uint8_t *buf, size_t buf_len, uint32_t payload_unit_start_indicator, psi_table_buffer_t *patBuffer) { vqarray_t *programs; int num_programs = 0; if (pas == NULL || buf == NULL) { SAFE_REPORT_TS_ERR(-1); return 0; } bs_t *b = NULL; if (!payload_unit_start_indicator && patBuffer->buffer == NULL) { // this TS packet is not start of table, and we have no cached table data LOG_WARN ("program_association_section_read: payload_unit_start_indicator not set and no cached data"); return 0; } if (payload_unit_start_indicator) { uint8_t payloadStartPtr = buf[0]; buf += (payloadStartPtr + 1); buf_len -= (payloadStartPtr + 1); LOG_DEBUG_ARGS ("program_association_section_read: payloadStartPtr = %d", payloadStartPtr); } // check for pat spanning multiple TS packets if (patBuffer->buffer != NULL) { LOG_DEBUG_ARGS ("program_association_section_read: patBuffer detected: patBufferAllocSz = %d, patBufferUsedSz = %d", patBuffer->bufferAllocSz, patBuffer->bufferUsedSz); size_t numBytesToCopy = buf_len; if (buf_len > (patBuffer->bufferAllocSz - patBuffer->bufferUsedSz)) { numBytesToCopy = patBuffer->bufferAllocSz - patBuffer->bufferUsedSz; } LOG_DEBUG_ARGS ("program_association_section_read: copying %d bytes to patBuffer", numBytesToCopy); memcpy (patBuffer->buffer + patBuffer->bufferUsedSz, buf, numBytesToCopy); patBuffer->bufferUsedSz += numBytesToCopy; if (patBuffer->bufferUsedSz < patBuffer->bufferAllocSz) { LOG_DEBUG ("program_association_section_read: patBuffer not yet full -- returning"); return 0; } b = bs_new(patBuffer->buffer, patBuffer->bufferUsedSz); } else { b = bs_new(buf, buf_len); } pas->table_id = bs_read_u8(b); if (pas->table_id != program_association_section) { LOG_ERROR_ARGS("Table ID in PAT is 0x%02X instead of expected 0x%02X", pas->table_id, program_association_section); reportAddErrorLogArgs("Table ID in PAT is 0x%02X instead of expected 0x%02X", pas->table_id, program_association_section); SAFE_REPORT_TS_ERR(-30); resetPSITableBuffer(patBuffer); bs_free (b); return 0; } // read byte 0 pas->section_syntax_indicator = bs_read_u1(b); if (!pas->section_syntax_indicator) { LOG_ERROR("section_syntax_indicator not set in PAT"); reportAddErrorLog("section_syntax_indicator not set in PAT"); SAFE_REPORT_TS_ERR(-31); resetPSITableBuffer(patBuffer); bs_free (b); return 0; } bs_skip_u(b, 3); // TODO read the zero bit, check it to be zero pas->section_length = bs_read_u(b, 12); if (pas->section_length > MAX_SECTION_LEN) { LOG_ERROR_ARGS("PAT section length is 0x%02X, larger than maximum allowed 0x%02X", pas->section_length, MAX_SECTION_LEN); reportAddErrorLogArgs("PAT section length is 0x%02X, larger than maximum allowed 0x%02X", pas->section_length, MAX_SECTION_LEN); SAFE_REPORT_TS_ERR(-32); resetPSITableBuffer(patBuffer); bs_free (b); return 0; } if (pas->section_length > bs_bytes_left(b)) { LOG_DEBUG ("program_association_section_read: Detected section spans more than one TS packet -- allocating buffer"); if (patBuffer->buffer != NULL) { // should never get here LOG_ERROR ("program_association_section_read: unexpected patBufffer"); reportAddErrorLog ("program_association_section_read: unexpected patBufffer"); resetPSITableBuffer(patBuffer); } patBuffer->bufferAllocSz = pas->section_length + 3; patBuffer->buffer = (uint8_t *)calloc (pas->section_length + 3, 1); memcpy (patBuffer->buffer, buf, buf_len); patBuffer->bufferUsedSz = buf_len; bs_free (b); return 0; } // read bytes 1,2 pas->transport_stream_id = bs_read_u16(b); // read bytes 3,4 bs_skip_u(b, 2); pas->version_number = bs_read_u(b, 5); pas->current_next_indicator = bs_read_u1(b); if (!pas->current_next_indicator) LOG_WARN("This PAT is not yet applicable/n"); // read byte 5 pas->section_number = bs_read_u8(b); pas->last_section_number = bs_read_u8(b); if (pas->section_number != 0 || pas->last_section_number != 0) LOG_WARN("Multi-section PAT is not supported yet/n"); // read bytes 6,7 num_programs = (pas->section_length - 5 - 4) / 4; // Programs listed in the PAT // explanation: section_length gives us the length from the end of section_length // we used 5 bytes for the mandatory section fields, and will use another 4 bytes for CRC // the remaining bytes contain program information, which is 4 bytes per iteration // It's much shorter in C :-) // Read the program loop, but ignore the NIT PID "program" programs = vqarray_new(); for (uint32_t i = 0; i < num_programs; i++) { program_info_t *prog = malloc(sizeof(program_info_t)); prog->program_number = bs_read_u16(b); if (prog->program_number == 0) { // Skip the NIT PID program (not a real program) free(prog); bs_skip_u(b, 16); continue; } bs_skip_u(b, 3); prog->program_map_PID = bs_read_u(b, 13); vqarray_add(programs, (vqarray_elem_t*)prog); } // This is our true number of programs pas->_num_programs = vqarray_length(programs); if (pas->_num_programs > 1) LOG_WARN_ARGS("%zd programs found, but only SPTS is fully supported. Patches are welcome.", pas->_num_programs); // Copy form our vqarray into the native array pas->programs = malloc(pas->_num_programs * sizeof(program_info_t)); for (uint32_t i = 0; i < pas->_num_programs; i++) { program_info_t* prog = (program_info_t*)vqarray_pop(programs); pas->programs[i] = *prog; free(prog); } vqarray_free(programs); pas->CRC_32 = bs_read_u32(b); // check CRC crc_t pas_crc = crc_init(); pas_crc = crc_update(pas_crc, buf, bs_pos(b) - 4); pas_crc = crc_finalize(pas_crc); if (pas_crc != pas->CRC_32) { LOG_ERROR_ARGS("PAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pas->CRC_32, pas_crc); reportAddErrorLogArgs("PAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pas->CRC_32, pas_crc); SAFE_REPORT_TS_ERR(-33); resetPSITableBuffer(patBuffer); bs_free (b); return 0; } else { // LOG_DEBUG("PAT CRC_32 checked successfully"); // don't enable unless you want to see this every ~100ms } bs_free(b); resetPSITableBuffer(patBuffer); return 1; }
int bd_clpi_Parse( bd_clpi_t *p_clpi, bs_t *s, int i_id ) { const int i_start = bs_pos( s ) / 8; /* */ if( bs_read( s, 32 ) != 0x48444D56 ) return VLC_EGENERIC; const uint32_t i_version = bs_read( s, 32 ); if( i_version != 0x30313030 && i_version != 0x30323030 ) return VLC_EGENERIC; /* */ const uint32_t i_sequence_start = bs_read( s, 32 ); const uint32_t i_program_start = bs_read( s, 32 ); const uint32_t i_cpi_start = bs_read( s, 32 ); bs_skip( s, 32 ); /* mark start */ bs_skip( s, 32 ); /* extension start */ /* */ p_clpi->i_id = i_id; /* Read sequence */ bs_t ss = *s; bs_skip( &ss, 8 * ( i_start + i_sequence_start ) - bs_pos( s ) ); bs_skip( &ss, 32 ); /* Length */ bs_skip( &ss, 8 ); bs_skip( &ss, 8 ); /* ATC sequence count (MUST be 1 ?) */ bs_skip( &ss, 32 ); /* ATC start (MUST be 0) */ const int i_stc = bs_read( &ss, 8 ); bs_skip( &ss, 8 ); /* STC ID offset (MUST be 0 ? */ p_clpi->p_stc = (bd_clpi_stc_t *)calloc( i_stc, sizeof(*p_clpi->p_stc) ); // sunqueen modify for( p_clpi->i_stc = 0; p_clpi->i_stc < i_stc; p_clpi->i_stc++ ) { if( !p_clpi->p_stc ) break; bd_clpi_stc_Parse( &p_clpi->p_stc[p_clpi->i_stc], &ss ); } /* Program */ bs_t ps = *s; bs_skip( &ps, 8 * ( i_start + i_program_start ) - bs_pos( s ) ); bs_skip( &ps, 32 ); /* Length */ bs_skip( &ps, 8 ); bs_skip( &ps, 8 ); /* Program count (MUST be 1 ?) */ bs_skip( &ps, 32 ); /* Program sequence start (MUST be 0) */ p_clpi->i_pmt_pid = bs_read( &ps, 16 ); const int i_stream = bs_read( &ps, 8 ); bs_skip( &ps, 8 ); /* Group count (MUST be 1 ?) */ p_clpi->p_stream = (bd_clpi_stream_t *)calloc( i_stream, sizeof(*p_clpi->p_stream) ); // sunqueen modify for( p_clpi->i_stream = 0; p_clpi->i_stream < i_stream; p_clpi->i_stream++ ) { if( !p_clpi->p_stream ) break; bd_clpi_stream_Parse( &p_clpi->p_stream[p_clpi->i_stream], &ps ); } /* Read CPI */ bs_t cs = *s; bs_skip( &cs, 8 * ( i_start + i_cpi_start ) - bs_pos( s ) ); const uint32_t i_cpi_length = bs_read( &cs, 32 ); if( i_cpi_length > 0 ) { bs_skip( &cs, 12 ); bs_skip( &cs, 4 ); /* Type (MUST be 1) */ /* EPMap */ const int i_epmap_start = bs_pos( &cs ) / 8; bs_skip( &cs, 8 ); const int i_ep_map = bs_read( &cs, 8 ); p_clpi->p_ep_map = (bd_clpi_ep_map_t *)calloc( i_ep_map, sizeof(*p_clpi->p_ep_map) ); // sunqueen modify for( p_clpi->i_ep_map = 0; p_clpi->i_ep_map < i_ep_map; p_clpi->i_ep_map++ ) { if( !p_clpi->p_ep_map ) break; if( bd_clpi_ep_map_Parse( &p_clpi->p_ep_map[p_clpi->i_ep_map], &cs, i_epmap_start ) ) break; } } else { p_clpi->i_ep_map = 0; p_clpi->p_ep_map = NULL; } return VLC_SUCCESS; }
//7.3.1 NAL unit syntax int structure(nal_unit)(h264_stream_t* h, uint8_t* buf, int size) { nal_t* nal = h->nal; int nal_size = size; int rbsp_size = size; uint8_t* rbsp_buf = (uint8_t*)calloc(1, rbsp_size); if( is_reading ) { int rc = nal_to_rbsp(buf, &nal_size, rbsp_buf, &rbsp_size); if (rc < 0) { free(rbsp_buf); // handle conversion error return -1; } } if( is_writing ) { rbsp_size = size*3/4; // NOTE this may have to be slightly smaller (3/4 smaller, worst case) in order to be guaranteed to fit } bs_t* b = bs_new(rbsp_buf, rbsp_size); value( forbidden_zero_bit, f(1, 0) ); value( nal->nal_ref_idc, u(2) ); value( nal->nal_unit_type, u(5) ); switch ( nal->nal_unit_type ) { case NAL_UNIT_TYPE_CODED_SLICE_IDR: case NAL_UNIT_TYPE_CODED_SLICE_NON_IDR: case NAL_UNIT_TYPE_CODED_SLICE_AUX: structure(slice_layer_rbsp)(h, b); break; #ifdef HAVE_SEI case NAL_UNIT_TYPE_SEI: structure(sei_rbsp)(h, b); break; #endif case NAL_UNIT_TYPE_SPS: structure(seq_parameter_set_rbsp)(h, b); break; case NAL_UNIT_TYPE_PPS: structure(pic_parameter_set_rbsp)(h, b); break; case NAL_UNIT_TYPE_AUD: structure(access_unit_delimiter_rbsp)(h, b); break; case NAL_UNIT_TYPE_END_OF_SEQUENCE: structure(end_of_seq_rbsp)(h, b); break; case NAL_UNIT_TYPE_END_OF_STREAM: structure(end_of_stream_rbsp)(h, b); break; case NAL_UNIT_TYPE_FILLER: case NAL_UNIT_TYPE_SPS_EXT: case NAL_UNIT_TYPE_UNSPECIFIED: case NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_A: case NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_B: case NAL_UNIT_TYPE_CODED_SLICE_DATA_PARTITION_C: default: return -1; } if (bs_overrun(b)) { bs_free(b); free(rbsp_buf); return -1; } if( is_writing ) { // now get the actual size used rbsp_size = bs_pos(b); int rc = rbsp_to_nal(rbsp_buf, &rbsp_size, buf, &nal_size); if (rc < 0) { bs_free(b); free(rbsp_buf); return -1; } } bs_free(b); free(rbsp_buf); return nal_size; }
void bd_mpls_play_item_Parse( bd_mpls_play_item_t *p_item, bs_t *s ) { const int i_length = bs_read( s, 16 ); const int i_start = bs_pos( s ) / 8; char psz_name[5+1]; for( int j = 0; j < 5; j++ ) psz_name[j] = bs_read( s, 8 ); psz_name[5] = '\0'; p_item->clpi.i_id = strtol( psz_name, NULL, 10 ); bs_skip( s, 32 ); bs_skip( s, 11 ); const bool b_angle = bs_read( s, 1 ); p_item->i_connection = bs_read( s, 4 ); p_item->clpi.i_stc_id = bs_read( s, 8 ); p_item->i_in_time = bs_read( s, 32 ); p_item->i_out_time = bs_read( s, 32 ); bs_skip( s, 64 ); bs_skip( s, 1 ); bs_skip( s, 7 ); p_item->i_still = bs_read( s, 8 ); p_item->i_still_time = bs_read( s, 16 ); if( p_item->i_still == BD_MPLS_PLAY_ITEM_STILL_NONE ) p_item->i_still_time = 0; else if( p_item->i_still == BD_MPLS_PLAY_ITEM_STILL_INFINITE ) p_item->i_still_time = INT_MAX; if( b_angle ) { const int i_angle = bs_read( s, 8 ); bs_skip( s, 6 ); p_item->b_angle_different_audio = bs_read( s, 1 ); p_item->b_angle_seamless = bs_read( s, 1 ); p_item->p_clpi = calloc( i_angle, sizeof(*p_item->p_clpi) ); for( p_item->i_clpi = 0; p_item->i_clpi < i_angle; p_item->i_clpi++ ) { if( !p_item->p_clpi ) break; bd_mpls_clpi_t *p_clpi = &p_item->p_clpi[p_item->i_clpi]; char psz_name[5+1]; for( int j = 0; j < 5; j++ ) psz_name[j] = bs_read( s, 8 ); psz_name[5] = '\0'; p_clpi->i_id = strtol( psz_name, NULL, 10 ); bs_skip( s, 32 ); p_clpi->i_stc_id = bs_read( s, 8 ); } } else { p_item->i_clpi = 0; p_item->p_clpi = NULL; p_item->b_angle_different_audio = false; p_item->b_angle_seamless = true; } /* STN Table */ bs_skip( s, 16 ); /* Length */ bs_skip( s, 16 ); const int i_video = bs_read( s, 8 ); const int i_audio = bs_read( s, 8 ); const int i_pg = bs_read( s, 8 ); const int i_ig = bs_read( s, 8 ); const int i_audio_2 = bs_read( s, 8 ); const int i_video_2 = bs_read( s, 8 ); const int i_pip_pg = bs_read( s, 8 ); bs_skip( s, 40 ); p_item->i_stream = 0; p_item->p_stream = calloc( i_video + i_audio + i_pg + i_ig, sizeof(*p_item->p_stream) ); for( int j = 0; j < i_video; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_PRIMARY_VIDEO ); } for( int j = 0; j < i_audio; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_PRIMARY_AUDIO ); } for( int j = 0; j < i_pg; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_PG ); } for( int j = 0; j < i_ig; j++, p_item->i_stream++ ) { if( !p_item->p_stream ) break; bd_mpls_stream_Parse( &p_item->p_stream[p_item->i_stream], s, BD_MPLS_STREAM_CLASS_IG ); } for( int j = 0; j < i_audio_2; j++ ) { /* TODO I need samples */ } for( int j = 0; j < i_video_2; j++ ) { /* TODO I need samples */ } for( int j = 0; j < i_pip_pg; j++ ) { /* TODO I need samples */ } bs_skip( s, 8 * ( i_start + i_length ) - bs_pos( s ) ); }
int program_map_section_read(program_map_section_t *pms, uint8_t *buf, size_t buf_size) { if (pms == NULL || buf == NULL) { SAFE_REPORT_TS_ERR(-1); return 0; } bs_t *b = bs_new(buf, buf_size); pms->table_id = bs_read_u8(b); if (pms->table_id != TS_program_map_section) { LOG_ERROR_ARGS("Table ID in PMT is 0x%02X instead of expected 0x%02X", pms->table_id, TS_program_map_section); SAFE_REPORT_TS_ERR(-40); return 0; } pms->section_syntax_indicator = bs_read_u1(b); if (!pms->section_syntax_indicator) { LOG_ERROR("section_syntax_indicator not set in PMT"); SAFE_REPORT_TS_ERR(-41); return 0; } bs_skip_u(b, 3); pms->section_length = bs_read_u(b, 12); if (pms->section_length > MAX_SECTION_LEN) { LOG_ERROR_ARGS("PMT section length is 0x%02X, larger than maximum allowed 0x%02X", pms->section_length, MAX_SECTION_LEN); SAFE_REPORT_TS_ERR(-42); return 0; } int section_start = bs_pos(b); // bytes 0,1 pms->program_number = bs_read_u16(b); // byte 2; bs_skip_u(b, 2); pms->version_number = bs_read_u(b, 5); pms->current_next_indicator = bs_read_u1(b); if (!pms->current_next_indicator) LOG_WARN("This PMT is not yet applicable/n"); // bytes 3,4 pms->section_number = bs_read_u8(b); pms->last_section_number = bs_read_u8(b); if (pms->section_number != 0 || pms->last_section_number != 0) { LOG_ERROR("Multi-section PMT is not allowed/n"); SAFE_REPORT_TS_ERR(-43); return 0; } bs_skip_u(b, 3); pms->PCR_PID = bs_read_u(b, 13); if (pms->PCR_PID < GENERAL_PURPOSE_PID_MIN || pms->PCR_PID > GENERAL_PURPOSE_PID_MAX) { LOG_ERROR_ARGS("PCR PID has invalid value 0x%02X", pms->PCR_PID); SAFE_REPORT_TS_ERR(-44); return 0; } bs_skip_u(b, 4); pms->program_info_length = bs_read_u(b, 12); if (pms->program_info_length > MAX_PROGRAM_INFO_LEN) { LOG_ERROR_ARGS("PMT program info length is 0x%02X, larger than maximum allowed 0x%02X", pms->program_info_length, MAX_PROGRAM_INFO_LEN); SAFE_REPORT_TS_ERR(-45); return 0; } read_descriptor_loop(pms->descriptors, b, pms->program_info_length); while (pms->section_length - (bs_pos(b) - section_start) > 4) { // account for CRC elementary_stream_info_t *es = es_info_new(); es_info_read(es, b); vqarray_add(pms->es_info, es); } pms->CRC_32 = bs_read_u32(b); // check CRC crc_t pas_crc = crc_init(); pas_crc = crc_update(pas_crc, buf, bs_pos(b) - 4); pas_crc = crc_finalize(pas_crc); if (pas_crc != pms->CRC_32) { LOG_ERROR_ARGS("PMT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pms->CRC_32, pas_crc); SAFE_REPORT_TS_ERR(-46); return 0; } else { LOG_DEBUG("PMT CRC_32 checked successfully"); } int bytes_read = bs_pos(b); bs_free(b); return bytes_read; }
int bd_mpls_Parse( bd_mpls_t *p_mpls, bs_t *s, int i_id ) { const int i_start = bs_pos( s ) / 8; /* */ if( bs_read( s, 32 ) != 0x4d504c53 ) return VLC_EGENERIC; const uint32_t i_version = bs_read( s, 32 ); if( i_version != 0x30313030 && i_version != 0x30323030 ) return VLC_EGENERIC; const uint32_t i_play_item_start = bs_read( s, 32 ); const uint32_t i_mark_start = bs_read( s, 32 ); bs_skip( s, 32 ); /* Extension start */ /* */ p_mpls->i_id = i_id; /* Read AppInfo: ignored */ /* Read Playlist */ bs_t ps = *s; bs_skip( &ps, 8 * ( i_start + i_play_item_start ) - bs_pos( s ) ); bs_skip( &ps, 32 ); /* Length */ bs_skip( &ps, 16 ); const int i_play_item = bs_read( &ps, 16 ); const int i_sub_path = bs_read( &ps, 16 ); p_mpls->p_play_item = calloc( i_play_item, sizeof(*p_mpls->p_play_item) ); for( p_mpls->i_play_item = 0; p_mpls->i_play_item < i_play_item; p_mpls->i_play_item++ ) { if( !p_mpls->p_play_item ) break; bd_mpls_play_item_t *p_item = &p_mpls->p_play_item[p_mpls->i_play_item]; bd_mpls_play_item_Parse( p_item, &ps ); } p_mpls->p_sub_path = calloc( i_sub_path, sizeof(*p_mpls->p_sub_path) ); for( p_mpls->i_sub_path = 0; p_mpls->i_sub_path < i_sub_path; p_mpls->i_sub_path++ ) { if( !p_mpls->p_sub_path ) break; bd_mpls_sub_path_t *p_sub = &p_mpls->p_sub_path[p_mpls->i_sub_path]; bd_mpls_sub_path_Parse( p_sub, &ps ); } /* Read Mark */ bs_t ms = *s; bs_skip( &ms, 8 * ( i_start + i_mark_start ) - bs_pos( s ) ); bs_skip( &ms, 32 ); const int i_mark = bs_read( &ms, 16 ); p_mpls->p_mark = calloc( i_mark, sizeof(*p_mpls->p_mark) ); for( p_mpls->i_mark = 0; p_mpls->i_mark < i_mark; p_mpls->i_mark++ ) { if( !p_mpls->p_mark ) break; bd_mpls_mark_t *p_mark = &p_mpls->p_mark[p_mpls->i_mark]; bd_mpls_mark_Parse( p_mark, &ms ); } /* Read Extension: ignored */ return VLC_SUCCESS; }
int program_association_section_read(program_association_section_t *pas, uint8_t *buf, size_t buf_len) { if (pas == NULL || buf == NULL) { SAFE_REPORT_TS_ERR(-1); return 0; } bs_t *b = bs_new(buf, buf_len); pas->table_id = bs_read_u8(b); if (pas->table_id != program_association_section) { LOG_ERROR_ARGS("Table ID in PAT is 0x%02X instead of expected 0x%02X", pas->table_id, program_association_section); SAFE_REPORT_TS_ERR(-30); return 0; } // read byte 0 pas->section_syntax_indicator = bs_read_u1(b); if (!pas->section_syntax_indicator) { LOG_ERROR("section_syntax_indicator not set in PAT"); SAFE_REPORT_TS_ERR(-31); return 0; } bs_skip_u(b, 3); // TODO read the zero bit, check it to be zero pas->section_length = bs_read_u(b, 12); if (pas->section_length > MAX_SECTION_LEN) { LOG_ERROR_ARGS("PAT section length is 0x%02X, larger than maximum allowed 0x%02X", pas->section_length, MAX_SECTION_LEN); SAFE_REPORT_TS_ERR(-32); return 0; } // read bytes 1,2 pas->transport_stream_id = bs_read_u16(b); // read bytes 3,4 bs_skip_u(b, 2); pas->version_number = bs_read_u(b, 5); pas->current_next_indicator = bs_read_u1(b); if (!pas->current_next_indicator) LOG_WARN("This PAT is not yet applicable/n"); // read byte 5 pas->section_number = bs_read_u8(b); pas->last_section_number = bs_read_u8(b); if (pas->section_number != 0 || pas->last_section_number != 0) LOG_WARN("Multi-section PAT is not supported yet/n"); // read bytes 6,7 pas->_num_programs = (pas->section_length - 5 - 4) / 4; // explanation: section_length gives us the length from the end of section_length // we used 5 bytes for the mandatory section fields, and will use another 4 bytes for CRC // the remaining bytes contain program information, which is 4 bytes per iteration // It's much shorter in C :-) if (pas->_num_programs > 1) LOG_WARN_ARGS("%zd programs found, but only SPTS is fully supported. Patches are welcome.", pas->_num_programs); pas->programs = malloc(pas->_num_programs * sizeof(program_info_t)); for (uint32_t i = 0; i < pas->_num_programs; i++) { pas->programs[i].program_number = bs_read_u16(b); bs_skip_u(b, 3); pas->programs[i].program_map_PID = bs_read_u(b, 13); } pas->CRC_32 = bs_read_u32(b); // check CRC crc_t pas_crc = crc_init(); pas_crc = crc_update(pas_crc, buf, bs_pos(b) - 4); pas_crc = crc_finalize(pas_crc); if (pas_crc != pas->CRC_32) { LOG_ERROR_ARGS("PAT CRC_32 specified as 0x%08X, but calculated as 0x%08X", pas->CRC_32, pas_crc); SAFE_REPORT_TS_ERR(-33); return 0; } else { LOG_DEBUG("PAT CRC_32 checked successfully"); } bs_free(b); return 1; }
int pes_read_header(pes_header_t *ph, bs_t *b) { int PES_packet_start = bs_pos(b); // we *really* care about bytes 0..19, as we can cheat and manipulate PTS/DTS this way if (bs_bytes_left(b) < 20) return 0; // bytes 0..2 uint32_t pes_packet_start_code = bs_read_u24(b); if (pes_packet_start_code != PES_PACKET_START_CODE_PREFIX) { int actually_read = bs_pos(b) - PES_packet_start; b->p -= actually_read; // undo the read LOG_WARN_ARGS("PES packet starts with 0x%06X instead of expected start code 0x%06X, skipping it", pes_packet_start_code, PES_PACKET_START_CODE_PREFIX); return 0; // bail out! something is fishy! } // bytes 3..5 ph->stream_id = bs_read_u8(b); ph->PES_packet_length = bs_read_u16(b); if (HAS_PES_HEADER(ph->stream_id)) { // byte 6 bs_skip_u(b, 2); ph->PES_scrambling_control = bs_read_u(b, 2); ph->PES_priority = bs_read_u1(b); ph->data_alignment_indicator = bs_read_u1(b); ph->copyright = bs_read_u1(b); ph->original_or_copy = bs_read_u1(b); // byte 7 ph->PTS_DTS_flags = bs_read_u(b, 2); ph->ESCR_flag = bs_read_u1(b); ph->ES_rate_flag = bs_read_u1(b); ph->DSM_trick_mode_flag = bs_read_u1(b); ph->additional_copy_info_flag = bs_read_u1(b); ph->PES_CRC_flag = bs_read_u1(b); ph->PES_extension_flag = bs_read_u1(b); // byte 8 ph->PES_header_data_length = bs_read_u8(b); int PES_packet_optional_start = bs_pos(b); // byte 9..14 if (ph->PTS_DTS_flags & PES_PTS_FLAG) { bs_skip_u(b, 4); ph->PTS = bs_read_90khz_timestamp(b); } // byte 15..19 if (ph->PTS_DTS_flags & PES_DTS_FLAG) { bs_skip_u(b, 4); ph->DTS = bs_read_90khz_timestamp(b); } if (ph->ESCR_flag) { bs_skip_u(b, 2); ph->ESCR_base = bs_read_90khz_timestamp(b); ph->ESCR_extension = bs_read_u(b, 9); bs_skip_u1(b); } if (ph->ES_rate_flag) { bs_skip_u1(b); ph->ES_rate = bs_read_u(b, 22); bs_skip_u1(b); } if (ph->DSM_trick_mode_flag) { ph->trick_mode_control = bs_read_u(b, 3); switch (ph->trick_mode_control) { case PES_DSM_TRICK_MODE_CTL_FAST_FORWARD: case PES_DSM_TRICK_MODE_CTL_FAST_REVERSE: ph->field_id = bs_read_u(b, 2); ph->intra_slice_refresh = bs_read_u1(b); ph->frequency_truncation = bs_read_u(b, 2); break; case PES_DSM_TRICK_MODE_CTL_SLOW_MOTION: case PES_DSM_TRICK_MODE_CTL_SLOW_REVERSE: ph->rep_cntrl = bs_read_u(b, 5); break; case PES_DSM_TRICK_MODE_CTL_FREEZE_FRAME: ph->field_id = bs_read_u(b, 2); bs_skip_u(b, 3); break; default: bs_skip_u(b, 5); break; } } if (ph->additional_copy_info_flag) { bs_skip_u1(b); ph->additional_copy_info = bs_read_u(b, 7); } if (ph->PES_CRC_flag) { ph->previous_PES_packet_CRC = bs_read_u16(b); } if (ph->PES_extension_flag) { ph->PES_private_data_flag = bs_read_u1(b); ph->pack_header_field_flag = bs_read_u1(b); ph->program_packet_sequence_counter_flag = bs_read_u1(b); ph->PSTD_buffer_flag = bs_read_u1(b); bs_skip_u(b, 3); ph->PES_extension_flag_2 = bs_read_u1(b); if (ph->PES_private_data_flag) bs_read_bytes(b, ph->PES_private_data, 16); if (ph->pack_header_field_flag) { // whoever discovers the need for pack_header() is welcome to implement it. // I haven't. ph->pack_field_length = bs_read_u8(b); bs_skip_bytes(b, ph->pack_field_length); } if (ph->program_packet_sequence_counter_flag) { bs_skip_u1(b); ph->program_packet_sequence_counter = bs_read_u(b, 7); bs_skip_u1(b); ph->MPEG1_MPEG2_identifier = bs_read_u1(b); ph->original_stuff_length = bs_read_u(b, 6); } if (ph->PSTD_buffer_flag) { bs_skip_u(b, 2); ph->PSTD_buffer_scale = bs_read_u1(b); ph->PSTD_buffer_size = bs_read_u(b, 13); } if (ph->PES_extension_flag_2) { int PES_extension_field_start = bs_pos(b); bs_skip_u1(b); ph->PES_extension_field_length = bs_read_u(b, 7); ph->stream_id_extension_flag = bs_read_u1(b); if (!ph->stream_id_extension_flag) { ph->stream_id_extension = bs_read_u(b, 7); } else { bs_skip_u(b, 6); ph->tref_extension_flag = bs_read_u1(b); if (ph->tref_extension_flag) { bs_skip_u(b, 4); ph->TREF = bs_read_90khz_timestamp(b); } } int PES_extension_bytes_left = bs_pos(b) - PES_extension_field_start; if (PES_extension_bytes_left > 0) bs_skip_bytes(b, PES_extension_bytes_left); } } int PES_optional_bytes_read = bs_pos(b) - PES_packet_optional_start; int stuffing_bytes_len = ph->PES_header_data_length - PES_optional_bytes_read; // if any if (stuffing_bytes_len > 0) bs_skip_bytes(b, stuffing_bytes_len); } return (bs_pos(b) - PES_packet_start); }
/* MPLS */ void bd_mpls_stream_Parse( bd_mpls_stream_t *p_stream, bs_t *s, int i_class ) { /* Stream entry parsing */ const int i_entry_length = bs_read( s, 8 ); const int i_entry_start = bs_pos( s ) / 8; p_stream->i_type = bs_read( s, 8 ); p_stream->i_class = i_class; if( p_stream->i_type == BD_MPLS_STREAM_TYPE_PLAY_ITEM ) { p_stream->play_item.i_pid = bs_read( s, 16 ); } else if( p_stream->i_type == BD_MPLS_STREAM_TYPE_SUB_PATH ) { p_stream->sub_path.i_sub_path_id = bs_read( s, 8 ); p_stream->sub_path.i_sub_clip_id = bs_read( s, 8 ); p_stream->sub_path.i_pid = bs_read( s, 16 ); } else if( p_stream->i_type == BD_MPLS_STREAM_TYPE_IN_MUX_SUB_PATH ) { p_stream->in_mux_sub_path.i_sub_path_id = bs_read( s, 8 ); p_stream->in_mux_sub_path.i_pid = bs_read( s, 16 ); } bs_skip( s, 8 * ( i_entry_start + i_entry_length ) - bs_pos( s ) ); /* Stream attributes parsing */ const int i_attributes_length = bs_read( s, 8 ); const int i_attributes_start = bs_pos( s ) / 8; p_stream->i_stream_type = bs_read( s, 8 ); strcpy( p_stream->psz_language, "" ); p_stream->i_charset = -1; if( p_stream->i_stream_type == 0x02 || /* MPEG-I/II */ p_stream->i_stream_type == 0x1b || /* AVC */ p_stream->i_stream_type == 0xea ) /* VC-1 */ { /* Video */ } else if( ( p_stream->i_stream_type >= 0x80 && p_stream->i_stream_type <= 0x8f ) || ( p_stream->i_stream_type >= 0xa0 && p_stream->i_stream_type <= 0xaf ) ) { /* Audio */ bs_skip( s, 4 ); bs_skip( s, 4 ); for( int i = 0; i < 3; i++ ) p_stream->psz_language[i] = bs_read( s, 8 ); p_stream->psz_language[3] = '\0'; } else if( p_stream->i_stream_type == 0x90 || /* PG stream */ p_stream->i_stream_type == 0x91 ) /* IG stream */ { for( int i = 0; i < 3; i++ ) p_stream->psz_language[i] = bs_read( s, 8 ); p_stream->psz_language[3] = '\0'; } else if( p_stream->i_stream_type == 0x92 ) /* Text stream */ { p_stream->i_charset = bs_read( s, 8 ); for( int i = 0; i < 3; i++ ) p_stream->psz_language[i] = bs_read( s, 8 ); p_stream->psz_language[3] = '\0'; } bs_skip( s, 8 * ( i_attributes_start + i_attributes_length ) - bs_pos( s ) ); }
int pes_header_write(pes_header_t *ph, bs_t *b) { // TODO: add support for PES-level stuffing int start_pos = bs_pos(b); bs_write_u24(b, PES_PACKET_START_CODE_PREFIX); bs_write_u8(b, ph->stream_id); bs_write_u16(b, ph->PES_packet_length); if (HAS_PES_HEADER(ph->stream_id)) { bs_write_u(b, 2, 0x02); bs_write_u(b, 2, ph->PES_scrambling_control); bs_write_u1(b, ph->PES_priority); bs_write_u1(b, ph->data_alignment_indicator); bs_write_u1(b, ph->copyright); bs_write_u1(b, ph->original_or_copy); bs_write_u(b, 2, ph->PTS_DTS_flags); bs_write_u1(b, ph->ESCR_flag); bs_write_u1(b, ph->ES_rate_flag); bs_write_u1(b, ph->DSM_trick_mode_flag); bs_write_u1(b, ph->additional_copy_info_flag); bs_write_u1(b, ph->PES_CRC_flag); bs_write_u1(b, ph->PES_extension_flag); bs_write_u8(b, ph->PES_header_data_length); if (ph->PTS_DTS_flags & PES_PTS_FLAG) { bs_write_u(b, 4, 0x02); bs_write_90khz_timestamp(b, ph->PTS); } if (ph->PTS_DTS_flags & PES_DTS_FLAG) { bs_write_u(b, 4, 0x01); bs_write_90khz_timestamp(b, ph->DTS); } if (ph->ESCR_flag) { bs_write_reserved(b, 2); bs_write_90khz_timestamp(b, ph->ESCR_base); bs_write_u(b, 9, ph->ESCR_extension); bs_write_marker_bit(b); } if (ph->ES_rate_flag) { bs_write_marker_bit(b); bs_write_u(b, 22, ph->ES_rate); bs_write_marker_bit(b); } if (ph->DSM_trick_mode_flag) { bs_write_u(b, 3, ph->trick_mode_control); switch (ph->trick_mode_control) { case PES_DSM_TRICK_MODE_CTL_FAST_FORWARD: case PES_DSM_TRICK_MODE_CTL_FAST_REVERSE: bs_write_u(b, 2, ph->field_id); bs_write_u1(b, ph->intra_slice_refresh); bs_write_u(b, 2, ph->frequency_truncation); break; case PES_DSM_TRICK_MODE_CTL_SLOW_MOTION: case PES_DSM_TRICK_MODE_CTL_SLOW_REVERSE: bs_write_u(b, 5, ph->rep_cntrl); break; case PES_DSM_TRICK_MODE_CTL_FREEZE_FRAME: bs_write_u(b, 2, ph->field_id); bs_write_reserved(b, 3); break; default: bs_write_reserved(b, 5); break; } } if (ph->additional_copy_info_flag) { bs_write_marker_bit(b); bs_write_u(b, 7, ph->additional_copy_info); } if (ph->PES_CRC_flag) { bs_write_u16(b, ph->previous_PES_packet_CRC); } if (ph->PES_extension_flag) { bs_write_u1(b, ph->PES_private_data_flag); bs_write_u1(b, 0); // pack_header not supported bs_write_u1(b, ph->program_packet_sequence_counter_flag); bs_write_u1(b, ph->PSTD_buffer_flag); bs_write_reserved(b, 3); bs_write_u1(b, ph->PES_extension_flag_2); if (ph->PES_private_data_flag) { bs_write_bytes(b, ph->PES_private_data, 16); } if (ph->program_packet_sequence_counter_flag) { bs_write_marker_bit(b); bs_write_u(b, 7, ph->program_packet_sequence_counter); bs_write_marker_bit(b); bs_write_u1(b, ph->MPEG1_MPEG2_identifier); bs_write_u(b, 6, ph->original_stuff_length); } if (ph->PSTD_buffer_flag) { bs_write_u(b, 2, 0x01); bs_write_u1(b, ph->PSTD_buffer_scale); bs_write_u(b, 13, ph->PSTD_buffer_size); } if (ph->PES_extension_flag_2) { bs_write_marker_bit(b); bs_write_u(b, 7, ph->PES_extension_field_length); bs_write_u1(b, ph->stream_id_extension_flag); if (!ph->stream_id_extension_flag) { bs_write_u(b, 7, ph->stream_id_extension); } else { bs_write_reserved(b, 6); bs_write_u1(b, ph->tref_extension_flag); if (ph->tref_extension_flag) { bs_write_reserved(b, 4); bs_write_90khz_timestamp(b, ph->TREF); } } } } } return (bs_pos(b) - start_pos); }