static int _mobj_parse_object(BITSTREAM *bs, MOBJ_OBJECT *obj) { int i; obj->resume_intention_flag = bs_read(bs, 1); obj->menu_call_mask = bs_read(bs, 1); obj->title_search_mask = bs_read(bs, 1); bs_skip(bs, 13); /* padding */ obj->num_cmds = bs_read(bs, 16); obj->cmds = calloc(obj->num_cmds, sizeof(MOBJ_CMD)); if (!obj->cmds) { BD_DEBUG(DBG_CRIT, "out of memory\n"); return 0; } for (i = 0; i < obj->num_cmds; i++) { uint8_t buf[12]; bs_read_bytes(bs, buf, 12); mobj_parse_cmd(buf, &obj->cmds[i]); } return 1; }
static int _parse_app_info(BITSTREAM *bs, INDX_APP_INFO *app_info) { uint32_t len; if (bs_seek_byte(bs, 40) < 0) { return 0; } len = bs_read(bs, 32); if (len != 34) { BD_DEBUG(DBG_NAV, "index.bdmv app_info length is %d, expected 34 !\n", len); } bs_skip(bs, 1); app_info->initial_output_mode_preference = bs_read(bs, 1); app_info->content_exist_flag = bs_read(bs, 1); bs_skip(bs, 5); app_info->video_format = bs_read(bs, 4); app_info->frame_rate = bs_read(bs, 4); bs_read_bytes(bs, app_info->user_data, 32); return 1; }
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); }
static BDID_DATA *_bdid_parse(BD_FILE_H *fp) { BITSTREAM bs; BDID_DATA *bdid = NULL; uint32_t data_start, extension_data_start; uint8_t tmp[16]; if (bs_init(&bs, fp) < 0) { BD_DEBUG(DBG_NAV, "id.bdmv: read error\n"); return NULL; } if (!_parse_header(&bs, &data_start, &extension_data_start)) { BD_DEBUG(DBG_NAV | DBG_CRIT, "id.bdmv: invalid header\n"); return NULL; } if (bs_seek_byte(&bs, 40) < 0) { BD_DEBUG(DBG_NAV, "id.bdmv: read error\n"); return NULL; } bdid = calloc(1, sizeof(BDID_DATA)); if (!bdid) { BD_DEBUG(DBG_CRIT, "out of memory\n"); return NULL; } bs_read_bytes(&bs, tmp, 4); str_print_hex(bdid->org_id, tmp, 4); bs_read_bytes(&bs, tmp, 16); str_print_hex(bdid->disc_id, tmp, 16); if (extension_data_start) { BD_DEBUG(DBG_NAV | DBG_CRIT, "id.bdmv: ignoring unknown extension data\n"); } return bdid; }
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); }
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); }