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; }
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; }