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; }
static INDX_ROOT *_indx_parse(BD_FILE_H *fp) { BITSTREAM bs; INDX_ROOT *index = calloc(1, sizeof(INDX_ROOT)); int indexes_start, extension_data_start; if (!index) { BD_DEBUG(DBG_CRIT, "out of memory\n"); return NULL; } bs_init(&bs, fp); if (!_parse_header(&bs, &indexes_start, &extension_data_start) || !_parse_app_info(&bs, &index->app_info)) { indx_free(&index); return NULL; } bs_seek_byte(&bs, indexes_start); if (!_parse_index(&bs, index)) { indx_free(&index); return NULL; } if (extension_data_start) { BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: unknown extension data at %d\n", extension_data_start); } return index; }
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; }
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; }
static int _mobj_parse_header(BITSTREAM *bs, int *extension_data_start) { uint32_t sig1, sig2; bs_seek_byte(bs, 0); sig1 = bs_read(bs, 32); sig2 = bs_read(bs, 32); if (sig1 != MOBJ_SIG1 || (sig2 != MOBJ_SIG2A && sig2 != MOBJ_SIG2B)) { BD_DEBUG(DBG_NAV, "MovieObject.bdmv failed signature match: expected MOBJ0100 got %8.8s\n", bs->buf); return 0; } *extension_data_start = bs_read(bs, 32); return 1; }
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; }
static int _parse_header(BITSTREAM *bs, int *index_start, int *extension_data_start) { uint32_t sig1, sig2; bs_seek_byte(bs, 0); sig1 = bs_read(bs, 32); sig2 = bs_read(bs, 32); if (sig1 != INDX_SIG1 || (sig2 != INDX_SIG2A && sig2 != INDX_SIG2B)) { BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv failed signature match: expected INDX0100 got %8.8s\n", bs->buf); return 0; } *index_start = bs_read(bs, 32); *extension_data_start = bs_read(bs, 32); return 1; }