00001 #include <byteswap.h>
00002 #include <dirent.h>
00003 #include <fcntl.h>
00004 #include <stdlib.h>
00005 #include <string.h>
00006 #include <sys/types.h>
00007 #include <unistd.h>
00008
00009 #include "ifo.h"
00010 #include "mpeg3private.h"
00011 #include "mpeg3protos.h"
00012
00013 typedef struct
00014 {
00015
00016 int64_t start_byte;
00017 int64_t end_byte;
00018
00019 int program;
00020
00021 int cell_type;
00022
00023 int vob_id;
00024 int cell_id;
00025 } mpeg3ifo_cell_t;
00026
00027 typedef struct
00028 {
00029 mpeg3ifo_cell_t *cells;
00030 long total_cells;
00031 long cells_allocated;
00032 } mpeg3ifo_celltable_t;
00033
00034
00035 #define CADDR_HDR_LEN 8
00036
00037 typedef struct {
00038 u_short num : 16;
00039 u_short unknown : 16;
00040 u_int len : 32;
00041 } cell_addr_hdr_t;
00042
00043 typedef struct {
00044 u_int foo : 16;
00045 u_int num : 16;
00046 } audio_hdr_t;
00047
00048 #define AUDIO_HDR_LEN 4
00049
00050 typedef struct {
00051 u_short id : 16;
00052 u_short : 16;
00053 u_int start : 32;
00054 } pgci_sub_t;
00055
00056 #define PGCI_SUB_LEN 8
00057
00058 #define PGCI_COLOR_LEN 4
00059
00060
00061 static u_int get4bytes(u_char *buf)
00062 {
00063 return bswap_32 (*((u_int32_t *)buf));
00064 }
00065
00066 static u_int get2bytes(u_char *buf)
00067 {
00068 return bswap_16 (*((u_int16_t *)buf));
00069 }
00070
00071 static int ifo_read(int fd, long pos, long count, unsigned char *data)
00072 {
00073 if((pos = lseek(fd, pos, SEEK_SET)) < 0)
00074 {
00075 perror("ifo_read");
00076 return -1;
00077 }
00078
00079 return read(fd, data, count);
00080 }
00081
00082 #define OFF_PTT get4bytes (ifo->data[ID_MAT] + 0xC8)
00083 #define OFF_TITLE_PGCI get4bytes (ifo->data[ID_MAT] + 0xCC)
00084 #define OFF_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xD0)
00085 #define OFF_TMT get4bytes (ifo->data[ID_MAT] + 0xD4)
00086 #define OFF_MENU_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xD8)
00087 #define OFF_MENU_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xDC)
00088 #define OFF_TITLE_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xE0)
00089 #define OFF_TITLE_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xE4)
00090
00091 #define OFF_VMG_TSP get4bytes (ifo->data[ID_MAT] + 0xC4)
00092 #define OFF_VMG_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xC8)
00093 #define OFF_VMG_TMT get4bytes (ifo->data[ID_MAT] + 0xD0)
00094
00095
00096 static int ifo_vts(ifo_t *ifo)
00097 {
00098 if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VTS", 12))
00099 return 0;
00100
00101 return -1;
00102 }
00103
00104
00105 static int ifo_vmg(ifo_t *ifo)
00106 {
00107 if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VMG", 12))
00108 return 0;
00109
00110 return -1;
00111 }
00112
00113 static int ifo_table(ifo_t *ifo, int64_t offset, unsigned long tbl_id)
00114 {
00115 unsigned char *data;
00116 int64_t len = 0;
00117 int i;
00118 u_int32_t *ptr;
00119
00120 if(!offset) return -1;
00121
00122 data = (u_char *)calloc(1, DVD_VIDEO_LB_LEN);
00123
00124 if(ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, DVD_VIDEO_LB_LEN, data) <= 0)
00125 {
00126 perror("ifo_table");
00127 return -1;
00128 }
00129
00130 switch(tbl_id)
00131 {
00132 case ID_TITLE_VOBU_ADDR_MAP:
00133 case ID_MENU_VOBU_ADDR_MAP:
00134 len = get4bytes(data) + 1;
00135 break;
00136
00137 default:
00138 {
00139 ifo_hdr_t *hdr = (ifo_hdr_t *)data;
00140 len = bswap_32(hdr->len) + 1;
00141 }
00142 }
00143
00144 if(len > DVD_VIDEO_LB_LEN)
00145 {
00146 data = (u_char *)realloc((void *)data, len);
00147 bzero(data, len);
00148 ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, len, data);
00149 }
00150
00151 ifo->data[tbl_id] = data;
00152 ptr = (u_int32_t*)data;
00153 len /= 4;
00154
00155 if(tbl_id == ID_TMT)
00156 for (i = 0; i < len; i++)
00157 ptr[i] = bswap_32(ptr[i]);
00158
00159 return 0;
00160 }
00161
00162 static ifo_t* ifo_open(int fd, long pos)
00163 {
00164 ifo_t *ifo;
00165
00166 ifo = (ifo_t *)calloc(sizeof(ifo_t), 1);
00167
00168 ifo->data[ID_MAT] = (unsigned char *)calloc(DVD_VIDEO_LB_LEN, 1);
00169
00170 ifo->pos = pos;
00171 ifo->fd = fd;
00172
00173 if(ifo_read(fd, pos, DVD_VIDEO_LB_LEN, ifo->data[ID_MAT]) < 0)
00174 {
00175 perror("ifo_open");
00176 free(ifo->data[ID_MAT]);
00177 free(ifo);
00178 return NULL;
00179 }
00180
00181 ifo->num_menu_vobs = get4bytes(ifo->data[ID_MAT] + 0xC0);
00182 ifo->vob_start = get4bytes(ifo->data[ID_MAT] + 0xC4);
00183
00184 #ifdef DEBUG
00185 printf ("num of vobs: %x vob_start %x\n", ifo->num_menu_vobs, ifo->vob_start);
00186 #endif
00187
00188 if(!ifo_vts(ifo))
00189 {
00190 ifo_table(ifo, OFF_PTT, ID_PTT);
00191 ifo_table(ifo, OFF_TITLE_PGCI, ID_TITLE_PGCI);
00192 ifo_table(ifo, OFF_MENU_PGCI, ID_MENU_PGCI);
00193 ifo_table(ifo, OFF_TMT, ID_TMT);
00194 ifo_table(ifo, OFF_MENU_CELL_ADDR, ID_MENU_CELL_ADDR);
00195 ifo_table(ifo, OFF_MENU_VOBU_ADDR_MAP, ID_MENU_VOBU_ADDR_MAP);
00196 ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
00197 ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
00198 }
00199 else
00200 if(!ifo_vmg(ifo))
00201 {
00202 ifo_table(ifo, OFF_VMG_TSP, ID_TSP);
00203 ifo_table(ifo, OFF_VMG_MENU_PGCI, ID_MENU_PGCI);
00204 ifo_table(ifo, OFF_VMG_TMT, ID_TMT);
00205 ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
00206 ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
00207 }
00208
00209 return ifo;
00210 }
00211
00212
00213 static int ifo_close(ifo_t *ifo)
00214 {
00215 if(ifo->data[ID_MAT]) free(ifo->data[ID_MAT]);
00216 if(ifo->data[ID_PTT]) free(ifo->data[ID_PTT]);
00217 if(ifo->data[ID_TITLE_PGCI]) free(ifo->data[ID_TITLE_PGCI]);
00218 if(ifo->data[ID_MENU_PGCI]) free(ifo->data[ID_MENU_PGCI]);
00219 if(ifo->data[ID_TMT]) free(ifo->data[ID_TMT]);
00220 if(ifo->data[ID_MENU_CELL_ADDR]) free(ifo->data[ID_MENU_CELL_ADDR]);
00221 if(ifo->data[ID_MENU_VOBU_ADDR_MAP]) free(ifo->data[ID_MENU_VOBU_ADDR_MAP]);
00222 if(ifo->data[ID_TITLE_CELL_ADDR]) free(ifo->data[ID_TITLE_CELL_ADDR]);
00223 if(ifo->data[ID_TITLE_VOBU_ADDR_MAP]) free(ifo->data[ID_TITLE_VOBU_ADDR_MAP]);
00224
00225 free(ifo);
00226
00227 return 0;
00228 }
00229
00230 static int ifo_audio(char *_hdr, char **ptr)
00231 {
00232 audio_hdr_t *hdr = (audio_hdr_t *)_hdr;
00233
00234 if(!_hdr) return -1;
00235
00236 *ptr = _hdr + AUDIO_HDR_LEN;
00237
00238 return bswap_16(hdr->num);
00239 }
00240
00241
00242 static int pgci(ifo_hdr_t *hdr, int title, char **ptr)
00243 {
00244 pgci_sub_t *pgci_sub;
00245
00246 *ptr = (char *) hdr;
00247
00248 if(!*ptr) return -1;
00249
00250 if(title > hdr->num) return -1;
00251
00252 *ptr += IFO_HDR_LEN;
00253
00254 pgci_sub = (pgci_sub_t *)*ptr + title;
00255
00256 *ptr = (char *)hdr + bswap_32(pgci_sub->start);
00257
00258 return 0;
00259 }
00260
00261 static int program_map(mpeg3_t *file, char *pgc, unsigned char **ptr)
00262 {
00263 int num;
00264 int i;
00265 *ptr = pgc;
00266
00267 if (!pgc)
00268 return -1;
00269
00270 *ptr += 2;
00271 num = **ptr;
00272
00273 *ptr += 10;
00274 *ptr += 8 * 2;
00275 *ptr += 32 * 4;
00276 *ptr += 8;
00277
00278
00279
00280 if(!file->have_palette)
00281 {
00282 for(i = 0; i < 16; i++)
00283 {
00284 int r = (int)*(*ptr)++;
00285 int g = (int)*(*ptr)++;
00286 int b = (int)*(*ptr)++;
00287 (*ptr)++;
00288
00289 int y = (int)(0.29900 * r + 0.58700 * g + 0.11400 * b);
00290 int u = (int)(-0.16874 * r + -0.33126 * g + 0.50000 * b + 0x80);
00291 int v = (int)(0.50000 * r + -0.41869 * g + -0.08131 * b + 0x80);
00292 CLAMP(y, 0, 0xff);
00293 CLAMP(u, 0, 0xff);
00294 CLAMP(v, 0, 0xff);
00295
00296 file->palette[i * 4] = y;
00297 file->palette[i * 4 + 1] = u;
00298 file->palette[i * 4 + 2] = v;
00299
00300 }
00301
00302 file->have_palette = 1;
00303
00304
00305 }
00306 else
00307 {
00308 (*ptr) += 16 * 4;
00309 }
00310
00311 *ptr += 2;
00312
00313 *ptr = get2bytes((unsigned char*)*ptr) + pgc;
00314
00315 return num;
00316 }
00317
00318
00319 static u_int get_cellplayinfo(u_char *pgc, u_char **ptr)
00320 {
00321 u_int num;
00322 *ptr = pgc;
00323
00324 if (!pgc)
00325 return -1;
00326
00327 *ptr += 3;
00328 num = **ptr;
00329
00330 *ptr += 9;
00331 *ptr += 8 * 2;
00332 *ptr += 32 * 4;
00333 *ptr += 8;
00334 *ptr += 16 * PGCI_COLOR_LEN;
00335 *ptr += 4;
00336
00337 *ptr = get2bytes(*ptr) + pgc;
00338
00339 return num;
00340 }
00341
00342 static void get_ifo_playlist(mpeg3_t *file, mpeg3_demuxer_t *demuxer)
00343 {
00344 DIR *dirstream;
00345 char directory[MPEG3_STRLEN];
00346 char filename[MPEG3_STRLEN];
00347 char complete_path[MPEG3_STRLEN];
00348 char title_path[MPEG3_STRLEN];
00349 char vob_prefix[MPEG3_STRLEN];
00350 struct dirent *new_filename;
00351 char *ptr;
00352 int64_t total_bytes = 0;
00353 int done = 0, i;
00354
00355
00356 mpeg3io_complete_path(complete_path, file->fs->path);
00357 mpeg3io_get_directory(directory, complete_path);
00358 mpeg3io_get_filename(filename, complete_path);
00359 strncpy(vob_prefix, filename, 6);
00360
00361 dirstream = opendir(directory);
00362 while(new_filename = readdir(dirstream))
00363 {
00364 if(!strncasecmp(new_filename->d_name, vob_prefix, 6))
00365 {
00366 ptr = strrchr(new_filename->d_name, '.');
00367 if(ptr && !strncasecmp(ptr, ".vob", 4))
00368 {
00369
00370 if(atol(&new_filename->d_name[7]) > 0)
00371 {
00372 mpeg3_title_t *title;
00373
00374 mpeg3io_joinpath(title_path, directory, new_filename->d_name);
00375 title = demuxer->titles[demuxer->total_titles++] =
00376 mpeg3_new_title(file, title_path);
00377 title->total_bytes = mpeg3io_path_total_bytes(title_path);
00378 title->start_byte = total_bytes;
00379 title->end_byte = total_bytes + title->total_bytes;
00380 total_bytes += title->total_bytes;
00381
00382 mpeg3_new_cell(title,
00383 0,
00384 title->end_byte,
00385 0,
00386 title->end_byte,
00387 0);
00388
00389
00390 }
00391 }
00392 }
00393 }
00394 closedir(dirstream);
00395
00396
00397
00398
00399 while(!done)
00400 {
00401 done = 1;
00402 for(i = 0; i < demuxer->total_titles - 1; i++)
00403 {
00404 if(strcmp(demuxer->titles[i]->fs->path, demuxer->titles[i + 1]->fs->path) > 0)
00405 {
00406 mpeg3_title_t *temp = demuxer->titles[i];
00407 demuxer->titles[i] = demuxer->titles[i + 1];
00408 demuxer->titles[i + 1] = temp;
00409 done = 0;
00410 }
00411 }
00412 }
00413
00414
00415 }
00416
00417
00418
00419
00420
00421 static void get_ifo_header(mpeg3_demuxer_t *demuxer, ifo_t *ifo)
00422 {
00423 int i;
00424
00425 demuxer->vstream_table[0] = 1;
00426
00427
00428 if(!ifo_vts(ifo))
00429 {
00430 ifo_audio_t *audio;
00431 int result = 0;
00432
00433 int atracks = ifo_audio((char*)ifo->data[ID_MAT] + IFO_OFFSET_AUDIO, (char**)&audio);
00434 int atracks_empirical = 0;
00435
00436
00437 #define TEST_START 0x1000000
00438 #define TEST_LEN 0x1000000
00439 mpeg3demux_open_title(demuxer, 0);
00440 mpeg3demux_seek_byte(demuxer, TEST_START);
00441 while(!result &&
00442 !mpeg3demux_eof(demuxer) &&
00443 mpeg3demux_tell_byte(demuxer) < TEST_START + TEST_LEN)
00444 {
00445 result = mpeg3_read_next_packet(demuxer);
00446 }
00447 mpeg3demux_seek_byte(demuxer, 0);
00448
00449 for(i = 0; i < MPEG3_MAX_STREAMS; i++)
00450 {
00451 if(demuxer->astream_table[i]) atracks_empirical++;
00452 }
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 }
00471 else
00472 if(!ifo_vmg(ifo))
00473 {
00474 }
00475 }
00476
00477 static mpeg3ifo_cell_t* append_cell(mpeg3ifo_celltable_t *table)
00478 {
00479 if(!table->cells || table->total_cells >= table->cells_allocated)
00480 {
00481 long new_allocation;
00482 mpeg3ifo_cell_t *new_cells;
00483
00484 new_allocation = table->cells_allocated ? table->cells_allocated * 2 : 64;
00485 new_cells = calloc(1, sizeof(mpeg3ifo_cell_t) * new_allocation);
00486 if(table->cells)
00487 {
00488 memcpy(new_cells, table->cells, sizeof(mpeg3ifo_cell_t) * table->total_cells);
00489 free(table->cells);
00490 }
00491 table->cells = new_cells;
00492 table->cells_allocated = new_allocation;
00493 }
00494
00495 return &table->cells[table->total_cells++];
00496 }
00497
00498 static void delete_celltable(mpeg3ifo_celltable_t *table)
00499 {
00500 if(table->cells) free(table->cells);
00501 free(table);
00502 }
00503
00504 static void cellplayinfo(mpeg3_t *file, ifo_t *ifo, mpeg3ifo_celltable_t *cells)
00505 {
00506 int i, j;
00507 char *cell_hdr, *cell_hdr_start, *cell_info;
00508 ifo_hdr_t *hdr = (ifo_hdr_t*)ifo->data[ID_TITLE_PGCI];
00509 int program_chains = bswap_16(hdr->num);
00510 long total_cells;
00511
00512
00513 for(j = 0; j < program_chains; j++)
00514 {
00515
00516
00517 pgci(hdr, j, &cell_hdr);
00518
00519 cell_hdr_start = cell_hdr;
00520
00521 cell_hdr += 2;
00522
00523 cell_hdr += 2;
00524
00525 cell_hdr += 4;
00526
00527 cell_hdr += 4;
00528
00529 for(i = 0; i < 8; i++) cell_hdr += 2;
00530
00531 for(i = 0; i < 32; i++) cell_hdr += 4;
00532
00533 for(i = 0; i < 8; i++) cell_hdr++;
00534
00535
00536
00537 if(program_map(file, cell_hdr_start, &cell_hdr))
00538 ;
00539
00540
00541 if(total_cells = get_cellplayinfo((unsigned char*)cell_hdr_start, (unsigned char**)&cell_hdr))
00542 {
00543
00544 cell_info = cell_hdr;
00545 for(i = 0; i < total_cells; i++)
00546 {
00547 ifo_pgci_cell_addr_t *cell_addr = (ifo_pgci_cell_addr_t *)cell_info;
00548 int64_t start_byte = bswap_32(cell_addr->vobu_start);
00549 int64_t end_byte = bswap_32(cell_addr->vobu_last_end);
00550 int cell_type = cell_addr->chain_info;
00551
00552 if(!cells->total_cells && start_byte > 0)
00553 start_byte = 0;
00554
00555 if(!cells->total_cells ||
00556 end_byte >= cells->cells[cells->total_cells - 1].end_byte)
00557 {
00558 mpeg3ifo_cell_t *cell = append_cell(cells);
00559
00560 cell->start_byte = start_byte;
00561 cell->end_byte = end_byte;
00562 cell->cell_type = cell_type;
00563
00564
00565 }
00566 cell_info += PGCI_CELL_ADDR_LEN;
00567 }
00568 }
00569 }
00570 }
00571
00572 static void celladdresses(ifo_t *ifo, mpeg3ifo_celltable_t *cell_addresses)
00573 {
00574 int i;
00575 char *ptr = (char*)ifo->data[ID_TITLE_CELL_ADDR];
00576 int total_addresses;
00577 cell_addr_hdr_t *cell_addr_hdr = (cell_addr_hdr_t*)ptr;
00578 ifo_cell_addr_t *cell_addr = (ifo_cell_addr_t*)(ptr + CADDR_HDR_LEN);
00579 int done = 0;
00580
00581
00582 if(total_addresses = bswap_32(cell_addr_hdr->len) / sizeof(ifo_cell_addr_t))
00583 {
00584 for(i = 0; i < total_addresses; i++)
00585 {
00586 mpeg3ifo_cell_t *cell;
00587 cell = append_cell(cell_addresses);
00588 cell->start_byte = (int64_t)bswap_32(cell_addr->start);
00589 cell->end_byte = (int64_t)bswap_32(cell_addr->end);
00590 cell->vob_id = bswap_16(cell_addr->vob_id);
00591 cell->cell_id = cell_addr->cell_id;
00592 cell_addr++;
00593 }
00594 }
00595
00596
00597 done = 0;
00598 while(!done)
00599 {
00600 done = 1;
00601 for(i = 0; i < total_addresses - 1; i++)
00602 {
00603 mpeg3ifo_cell_t *cell1, *cell2;
00604 cell1 = &cell_addresses->cells[i];
00605 cell2 = &cell_addresses->cells[i + 1];
00606
00607 if(cell1->start_byte > cell2->start_byte)
00608 {
00609 mpeg3ifo_cell_t temp = *cell1;
00610 *cell1 = *cell2;
00611 *cell2 = temp;
00612 done = 0;
00613 break;
00614 }
00615 }
00616 }
00617
00618 for(i = 0; i < total_addresses; i++)
00619 {
00620 mpeg3ifo_cell_t *cell = &cell_addresses->cells[i];
00621 }
00622 }
00623
00624 static void finaltable(mpeg3ifo_celltable_t *final_cells,
00625 mpeg3ifo_celltable_t *cells,
00626 mpeg3ifo_celltable_t *cell_addresses)
00627 {
00628 int input_cell = 0, current_address = 0;
00629 int output_cell = 0;
00630 int done;
00631 int i, j;
00632 int current_vobid;
00633
00634 int64_t program_start_byte[256], program_end_byte[256];
00635
00636 final_cells->total_cells = 0;
00637 final_cells->cells_allocated = cell_addresses->total_cells;
00638 final_cells->cells = calloc(1, sizeof(mpeg3ifo_cell_t) * final_cells->cells_allocated);
00639
00640
00641 current_vobid = -1;
00642 for(i = cell_addresses->total_cells - 1; i >= 0; i--)
00643 {
00644 mpeg3ifo_cell_t *input = &cell_addresses->cells[i];
00645 mpeg3ifo_cell_t *output = &final_cells->cells[i];
00646 if(current_vobid < 0) current_vobid = input->vob_id;
00647
00648 *output = *input;
00649
00650 if(input->vob_id < current_vobid)
00651 current_vobid = input->vob_id;
00652 else
00653
00654 if(input->vob_id > current_vobid)
00655 {
00656 int current_program = input->vob_id - current_vobid;
00657 output->program = current_program;
00658
00659
00660 for(j = i;
00661 j < cell_addresses->total_cells && cell_addresses->cells[i].cell_id == cell_addresses->cells[j].cell_id;
00662 j++)
00663 {
00664 int new_program = final_cells->cells[j].vob_id - current_vobid;
00665 if(new_program <= current_program)
00666 final_cells->cells[j].program = new_program;
00667 }
00668 }
00669
00670 final_cells->total_cells++;
00671 }
00672
00673
00674 for(i = 0; i < final_cells->total_cells; i++)
00675 {
00676 if(i < final_cells->total_cells - 1 &&
00677 final_cells->cells[i].start_byte == final_cells->cells[i + 1].start_byte)
00678 {
00679 for(j = i; j < final_cells->total_cells - 1; j++)
00680 final_cells->cells[j] = final_cells->cells[j + 1];
00681
00682 final_cells->total_cells--;
00683 }
00684
00685 final_cells->cells[i].start_byte *= (int64_t)2048;
00686 final_cells->cells[i].end_byte *= (int64_t)2048;
00687
00688 final_cells->cells[i].end_byte += 2048;
00689 }
00690
00691 return;
00692
00693 printf("finaltable\n");
00694 for(i = 0; i < final_cells->total_cells; i++)
00695 {
00696 printf(" vob id: %x cell id: %x start: %llx end: %llx program: %x\n",
00697 final_cells->cells[i].vob_id, final_cells->cells[i].cell_id, (int64_t)final_cells->cells[i].start_byte, (int64_t)final_cells->cells[i].end_byte, final_cells->cells[i].program);
00698 }
00699 }
00700
00701
00702
00703
00704
00705 int mpeg3_read_ifo(mpeg3_t *file,
00706 int read_cells)
00707 {
00708 int64_t last_ifo_byte = 0, first_ifo_byte = 0;
00709 mpeg3ifo_celltable_t *cells, *cell_addresses, *final_cells;
00710 mpeg3_demuxer_t *demuxer = file->demuxer;
00711 int current_title = 0, current_cell = 0;
00712 int i, j;
00713 ifo_t *ifo;
00714 int fd = mpeg3io_get_fd(file->fs);
00715 int64_t title_start_byte = 0;
00716 int result;
00717
00718 if(!(ifo = ifo_open(fd, 0)))
00719 {
00720 fprintf(stderr, "read_ifo: Error decoding ifo.\n");
00721 return 1;
00722 }
00723
00724 demuxer->read_all = 1;
00725 cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
00726 cell_addresses = calloc(1, sizeof(mpeg3ifo_celltable_t));
00727 final_cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
00728
00729 get_ifo_playlist(file, demuxer);
00730 get_ifo_header(demuxer, ifo);
00731 cellplayinfo(file, ifo, cells);
00732 celladdresses(ifo, cell_addresses);
00733 finaltable(final_cells,
00734 cells,
00735 cell_addresses);
00736
00737
00738 int total_programs = 0;
00739 if(final_cells)
00740 {
00741 for(i = 0; i < final_cells->total_cells; i++)
00742 {
00743 mpeg3ifo_cell_t *cell = &final_cells->cells[i];
00744 if(cell->program > total_programs - 1)
00745 total_programs = cell->program + 1;
00746 }
00747 }
00748 int64_t *program_bytes = calloc(total_programs, sizeof(int64_t));
00749
00750
00751
00752 for(i = 0; i < demuxer->total_titles; i++)
00753 {
00754 mpeg3_title_t *title = demuxer->titles[i];
00755 if(title->cell_table)
00756 {
00757 for(j = 0; j < title->cell_table_size; j++)
00758 {
00759 free(title->cell_table);
00760 title->cell_table = 0;
00761 }
00762 }
00763 }
00764
00765
00766
00767 while(final_cells && current_cell < final_cells->total_cells)
00768 {
00769 mpeg3_title_t *title;
00770 mpeg3ifo_cell_t *cell;
00771 int64_t cell_start, cell_end;
00772 int64_t length = 1;
00773
00774 title = demuxer->titles[current_title];
00775 cell = &final_cells->cells[current_cell];
00776 cell_start = cell->start_byte;
00777 cell_end = cell->end_byte;
00778
00779
00780 while(cell_start < cell_end && length > 0)
00781 {
00782 length = cell_end - cell_start;
00783
00784
00785 if(cell_start + length - title_start_byte > title->total_bytes)
00786 length = title->total_bytes - cell_start + title_start_byte;
00787
00788
00789
00790
00791
00792
00793 if(length > 0)
00794 {
00795 int64_t program_start = program_bytes[cell->program];
00796 int64_t program_end = program_start + length;
00797 int64_t title_start = cell_start - title_start_byte;
00798 int64_t title_end = title_start + length;
00799 mpeg3_new_cell(title,
00800 program_start,
00801 program_end,
00802 title_start,
00803 title_end,
00804 cell->program);
00805 cell_start += length;
00806 program_bytes[cell->program] += length;
00807 }
00808 else
00809 {
00810 fprintf(stderr,
00811 "read_ifo: cell length and title length don't match! title=%d cell=%d cell_start=%llx cell_end=%llx.\n",
00812 current_title,
00813 current_cell,
00814 cell_start - title_start_byte,
00815 cell_end - title_start_byte);
00816
00817
00818
00819 if(current_title < demuxer->total_titles - 1) current_cell--;
00820 }
00821
00822
00823 if(cell_start - title_start_byte >= title->total_bytes &&
00824 current_title < demuxer->total_titles - 1)
00825 {
00826 title_start_byte += title->total_bytes;
00827 title = demuxer->titles[++current_title];
00828 }
00829 }
00830 current_cell++;
00831 }
00832
00833 free(program_bytes);
00834 delete_celltable(cells);
00835 delete_celltable(cell_addresses);
00836 delete_celltable(final_cells);
00837 ifo_close(ifo);
00838 return 0;
00839 }
00840