00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "file/file.h"
00021 #include "util/bits.h"
00022 #include "util/logging.h"
00023 #include "util/macro.h"
00024 #include "index_parse.h"
00025
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <errno.h>
00029
00030 static int _parse_hdmv_obj(BITSTREAM *bs, INDX_HDMV_OBJ *hdmv)
00031 {
00032 hdmv->playback_type = bs_read(bs, 2);
00033 bs_skip(bs, 14);
00034 hdmv->id_ref = bs_read(bs, 16);
00035 bs_skip(bs, 32);
00036
00037 return 1;
00038 }
00039
00040 static int _parse_bdj_obj(BITSTREAM *bs, INDX_BDJ_OBJ *bdj)
00041 {
00042 bdj->playback_type = bs_read(bs, 2);
00043 bs_skip(bs, 14);
00044 bs_read_bytes(bs, (uint8_t*)bdj->name, 5);
00045 bdj->name[5] = 0;
00046 bs_skip(bs, 8);
00047
00048 return 1;
00049 }
00050
00051 static int _parse_playback_obj(BITSTREAM *bs, INDX_PLAY_ITEM *obj)
00052 {
00053 obj->object_type = bs_read(bs, 2);
00054 bs_skip(bs, 30);
00055
00056 if (obj->object_type == 1) {
00057 return _parse_hdmv_obj(bs, &obj->hdmv);
00058 } else {
00059 return _parse_bdj_obj(bs, &obj->bdj);
00060 }
00061 }
00062
00063 static int _parse_index(BITSTREAM *bs, INDX_ROOT *index)
00064 {
00065 uint32_t index_len, i;
00066
00067 index_len = bs_read(bs, 32);
00068
00069
00070
00071 if (!_parse_playback_obj(bs, &index->first_play) ||
00072 !_parse_playback_obj(bs, &index->top_menu)) {
00073 return 0;
00074 }
00075
00076 index->num_titles = bs_read(bs, 16);
00077
00078 index->titles = calloc(index->num_titles, sizeof(INDX_TITLE));
00079
00080 for (i = 0; i < index->num_titles; i++) {
00081
00082 index->titles[i].object_type = bs_read(bs, 2);
00083 index->titles[i].access_type = bs_read(bs, 2);
00084 bs_skip(bs, 28);
00085
00086 if (index->titles[i].object_type == 1) {
00087 _parse_hdmv_obj(bs, &index->titles[i].hdmv);
00088 } else {
00089 _parse_bdj_obj(bs, &index->titles[i].bdj);
00090 }
00091 }
00092
00093 return 1;
00094 }
00095
00096 static int _parse_app_info(BITSTREAM *bs, INDX_APP_INFO *app_info)
00097 {
00098 uint32_t len;
00099
00100 bs_seek_byte(bs, 40);
00101
00102 len = bs_read(bs, 32);
00103
00104 if (len != 34) {
00105 BD_DEBUG(DBG_NAV, "index.bdmv app_info length is %d, expected 34 !\n", len);
00106 }
00107
00108 bs_skip(bs, 1);
00109 app_info->initial_output_mode_preference = bs_read(bs, 1);
00110 app_info->content_exist_flag = bs_read(bs, 1);
00111 bs_skip(bs, 5);
00112
00113 app_info->video_format = bs_read(bs, 4);
00114 app_info->frame_rate = bs_read(bs, 4);
00115
00116 bs_read_bytes(bs, app_info->user_data, 32);
00117
00118 return 1;
00119 }
00120
00121 #define INDX_SIG1 ('I' << 24 | 'N' << 16 | 'D' << 8 | 'X')
00122 #define INDX_SIG2A ('0' << 24 | '2' << 16 | '0' << 8 | '0')
00123 #define INDX_SIG2B ('0' << 24 | '1' << 16 | '0' << 8 | '0')
00124
00125 static int _parse_header(BITSTREAM *bs, int *index_start, int *extension_data_start)
00126 {
00127 uint32_t sig1, sig2;
00128
00129 bs_seek_byte(bs, 0);
00130
00131 sig1 = bs_read(bs, 32);
00132 sig2 = bs_read(bs, 32);
00133
00134 if (sig1 != INDX_SIG1 ||
00135 (sig2 != INDX_SIG2A &&
00136 sig2 != INDX_SIG2B)) {
00137 BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv failed signature match: expected INDX0100 got %8.8s\n", bs->buf);
00138 return 0;
00139 }
00140
00141 *index_start = bs_read(bs, 32);
00142 *extension_data_start = bs_read(bs, 32);
00143
00144 return 1;
00145 }
00146
00147 INDX_ROOT *indx_parse(const char *file_name)
00148 {
00149 BITSTREAM bs;
00150 BD_FILE_H *fp;
00151 INDX_ROOT *index = calloc(1, sizeof(INDX_ROOT));
00152
00153 int indexes_start, extension_data_start;
00154
00155 fp = file_open(file_name, "rb");
00156 if (!fp) {
00157 BD_DEBUG(DBG_NAV | DBG_CRIT, "indx_parse(): error opening %s\n", file_name);
00158 X_FREE(index);
00159 return NULL;
00160 }
00161
00162 bs_init(&bs, fp);
00163
00164 if (!_parse_header(&bs, &indexes_start, &extension_data_start)) {
00165 BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: invalid header\n");
00166 goto error;
00167 }
00168
00169 if (!_parse_app_info(&bs, &index->app_info)) {
00170 BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: error parsing app info\n");
00171 goto error;
00172 }
00173
00174 bs_seek_byte(&bs, indexes_start);
00175
00176 if (!_parse_index(&bs, index)) {
00177 BD_DEBUG(DBG_NAV | DBG_CRIT, "index.bdmv: error parsing indexes\n");
00178 goto error;
00179 }
00180
00181 file_close(fp);
00182
00183 return index;
00184
00185 error:
00186 X_FREE(index);
00187 file_close(fp);
00188 return NULL;
00189 }
00190
00191 void indx_free(INDX_ROOT **p)
00192 {
00193 if (p && *p) {
00194 X_FREE((*p)->titles);
00195 X_FREE(*p);
00196 }
00197 }