mpeg3ifo.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:20k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. #include <mpeg4ip.h>
  2. #ifdef HAVE_BYTESWAP_H
  3. #include <byteswap.h>
  4. #endif
  5. #include <mpeg4ip_byteswap.h>
  6. #include <dirent.h>
  7. #include <fcntl.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <sys/types.h>
  11. #include <unistd.h>
  12. #include "ifo.h"
  13. #include "mpeg3private.h"
  14. #include "mpeg3protos.h"
  15. typedef struct
  16. {
  17. int64_t start_byte;
  18. int64_t end_byte;
  19. // Used in final table
  20. int program;
  21. // Used in cell play info
  22. int cell_type;
  23. // Used in cell addresses
  24. int vob_id;
  25. int cell_id;
  26. } mpeg3ifo_cell_t;
  27. typedef struct
  28. {
  29. mpeg3ifo_cell_t *cells;
  30. long total_cells;
  31. long cells_allocated;
  32. } mpeg3ifo_celltable_t;
  33. #define CADDR_HDR_LEN 8
  34. typedef struct {
  35. u_short num : 16; // Number of Video Objects
  36. u_short unknown : 16; // don't know
  37. u_int len : 32; // length of table
  38. } cell_addr_hdr_t;
  39. typedef struct {
  40. u_int foo : 16; // ???
  41. u_int num : 16; // number of subchannels
  42. } audio_hdr_t;
  43. #define AUDIO_HDR_LEN 4
  44. typedef struct {
  45. u_short id : 16; // Language
  46. u_short : 16; // don't know
  47. u_int start : 32; // Start of unit
  48. } pgci_sub_t;
  49. #define PGCI_SUB_LEN 8
  50. #define PGCI_COLOR_LEN 4
  51. static u_int get4bytes(u_char *buf)
  52. {
  53. return B2N_32(*((u_int32_t *)buf));
  54. }
  55. static u_int get2bytes(u_char *buf)
  56. {
  57. return B2N_16(*((u_int16_t *)buf));
  58. }
  59. static int ifo_read(int fd, long pos, long count, unsigned char *data)
  60. {
  61. if((pos = lseek(fd, pos, SEEK_SET)) < 0)
  62. {
  63.      perror("ifo_read");
  64.      return -1;
  65.     }
  66. return read(fd, data, count); 
  67. }
  68. #define OFF_PTT get4bytes (ifo->data[ID_MAT] + 0xC8)
  69. #define OFF_TITLE_PGCI get4bytes (ifo->data[ID_MAT] + 0xCC)
  70. #define OFF_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xD0)
  71. #define OFF_TMT get4bytes (ifo->data[ID_MAT] + 0xD4)
  72. #define OFF_MENU_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xD8)
  73. #define OFF_MENU_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xDC)
  74. #define OFF_TITLE_CELL_ADDR get4bytes (ifo->data[ID_MAT] + 0xE0)
  75. #define OFF_TITLE_VOBU_ADDR_MAP get4bytes (ifo->data[ID_MAT] + 0xE4)
  76. #define OFF_VMG_TSP get4bytes (ifo->data[ID_MAT] + 0xC4)
  77. #define OFF_VMG_MENU_PGCI get4bytes (ifo->data[ID_MAT] + 0xC8)
  78. #define OFF_VMG_TMT get4bytes (ifo->data[ID_MAT] + 0xD0)
  79. static int ifo_vts(ifo_t *ifo)
  80. {
  81.     if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VTS", 12)) 
  82. return 0;
  83. return -1;
  84. }
  85. static int ifo_vmg(ifo_t *ifo)
  86. {
  87.     if(!strncmp((char*)ifo->data[ID_MAT], "DVDVIDEO-VMG", 12))
  88. return 0;
  89. return -1;
  90. }
  91. static int ifo_table(ifo_t *ifo, unsigned long offset, unsigned long tbl_id)
  92. {
  93. unsigned char *data;
  94. unsigned long len = 0;
  95. int i;
  96. u_int32_t *ptr;
  97. if(!offset) return -1;
  98. data = (u_char *)calloc(1, DVD_VIDEO_LB_LEN);
  99. if(ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, DVD_VIDEO_LB_LEN, data) <= 0) 
  100. {
  101. perror("ifo_table");
  102. return -1;
  103. }
  104. switch(tbl_id)
  105. {
  106. case ID_TITLE_VOBU_ADDR_MAP:
  107. case ID_MENU_VOBU_ADDR_MAP:
  108. len = get4bytes(data) + 1;
  109. break;
  110. default: 
  111. {
  112. ifo_hdr_t *hdr = (ifo_hdr_t *)data;
  113. len = B2N_32(hdr->len) + 1;
  114. }
  115. }
  116. if(len > DVD_VIDEO_LB_LEN) 
  117. {
  118. data = (u_char *)realloc((void *)data, len);
  119. bzero(data, len);
  120. ifo_read(ifo->fd, ifo->pos + offset * DVD_VIDEO_LB_LEN, len, data);
  121. }
  122. ifo->data[tbl_id] = data;
  123. ptr = (u_int32_t*)data;
  124. len /= 4;
  125. if(tbl_id == ID_TMT) 
  126. for (i = 0; i < len; i++)
  127. ptr[i] = B2N_32(ptr[i]);
  128. return 0;
  129. }
  130. static ifo_t* ifo_open(int fd, long pos)
  131. {
  132. ifo_t *ifo;
  133. ifo = (ifo_t *)calloc(sizeof(ifo_t), 1);
  134. ifo->data[ID_MAT] = (unsigned char *)calloc(DVD_VIDEO_LB_LEN, 1);
  135. ifo->pos = pos; 
  136. ifo->fd = fd;
  137. if(ifo_read(fd, pos, DVD_VIDEO_LB_LEN, ifo->data[ID_MAT]) < 0) 
  138. {
  139. perror("ifo_open");
  140. free(ifo->data[ID_MAT]);
  141. free(ifo);
  142. return NULL;
  143. }
  144. ifo->num_menu_vobs = get4bytes(ifo->data[ID_MAT] + 0xC0);
  145. ifo->vob_start = get4bytes(ifo->data[ID_MAT] + 0xC4);
  146. #ifdef DEBUG
  147. printf ("num of vobs: %x vob_start %xn", ifo->num_menu_vobs, ifo->vob_start);
  148. #endif
  149. if(!ifo_vts(ifo)) 
  150. {
  151. ifo_table(ifo, OFF_PTT, ID_PTT);
  152.      ifo_table(ifo, OFF_TITLE_PGCI, ID_TITLE_PGCI);
  153. ifo_table(ifo, OFF_MENU_PGCI, ID_MENU_PGCI);
  154. ifo_table(ifo, OFF_TMT, ID_TMT);
  155. ifo_table(ifo, OFF_MENU_CELL_ADDR, ID_MENU_CELL_ADDR);
  156. ifo_table(ifo, OFF_MENU_VOBU_ADDR_MAP, ID_MENU_VOBU_ADDR_MAP);
  157.      ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
  158. ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
  159. else 
  160. if(!ifo_vmg(ifo)) 
  161. {
  162. ifo_table(ifo, OFF_VMG_TSP, ID_TSP);
  163. ifo_table(ifo, OFF_VMG_MENU_PGCI, ID_MENU_PGCI);
  164. ifo_table(ifo, OFF_VMG_TMT, ID_TMT);
  165. ifo_table(ifo, OFF_TITLE_CELL_ADDR, ID_TITLE_CELL_ADDR);
  166. ifo_table(ifo, OFF_TITLE_VOBU_ADDR_MAP, ID_TITLE_VOBU_ADDR_MAP);
  167. }
  168. return ifo;
  169. }
  170. static int ifo_close(ifo_t *ifo)
  171. {
  172. if(ifo->data[ID_MAT]) free(ifo->data[ID_MAT]);
  173. if(ifo->data[ID_PTT]) free(ifo->data[ID_PTT]);
  174. if(ifo->data[ID_TITLE_PGCI]) free(ifo->data[ID_TITLE_PGCI]);
  175. if(ifo->data[ID_MENU_PGCI]) free(ifo->data[ID_MENU_PGCI]);
  176. if(ifo->data[ID_TMT]) free(ifo->data[ID_TMT]);
  177. if(ifo->data[ID_MENU_CELL_ADDR]) free(ifo->data[ID_MENU_CELL_ADDR]);
  178. if(ifo->data[ID_MENU_VOBU_ADDR_MAP]) free(ifo->data[ID_MENU_VOBU_ADDR_MAP]);
  179. if(ifo->data[ID_TITLE_CELL_ADDR]) free(ifo->data[ID_TITLE_CELL_ADDR]);
  180. if(ifo->data[ID_TITLE_VOBU_ADDR_MAP]) free(ifo->data[ID_TITLE_VOBU_ADDR_MAP]);
  181. free(ifo);
  182. return 0;
  183. }
  184. static int ifo_audio(char *_hdr, char **ptr)
  185. {
  186. audio_hdr_t *hdr = (audio_hdr_t *)_hdr;
  187. if(!_hdr) return -1;
  188. *ptr = _hdr + AUDIO_HDR_LEN;
  189. return B2N_16(hdr->num);
  190. }
  191. static int pgci(ifo_hdr_t *hdr, int title, char **ptr)
  192. {
  193. pgci_sub_t *pgci_sub;
  194. uint32_t temp;
  195. *ptr = (char *) hdr;
  196. if(!*ptr) return -1;
  197. if(title > hdr->num) return -1;
  198. *ptr += IFO_HDR_LEN;
  199. pgci_sub = (pgci_sub_t *)*ptr + title;
  200. temp = pgci_sub->start;
  201. temp = B2N_32(temp);
  202. *ptr = (char *)hdr + temp;
  203. return 0;
  204. }
  205. static int program_map(char *pgc, char **ptr)
  206. {
  207. int num;
  208. *ptr = pgc;
  209. if (!pgc)
  210. return -1;
  211. *ptr += 2;
  212. num = **ptr;
  213. *ptr += 10;
  214. *ptr += 8 * 2; // AUDIO
  215. *ptr += 32 * 4; // SUBPICTURE
  216. *ptr += 8;
  217. *ptr += 16 * PGCI_COLOR_LEN; // CLUT
  218. *ptr += 2;
  219. *ptr = get2bytes((unsigned char*)*ptr) + pgc;
  220. return num;
  221. }
  222. static u_int get_cellplayinfo(u_char *pgc, u_char **ptr)
  223. {
  224. u_int num;
  225. *ptr = pgc;
  226. if (!pgc)
  227. return -1;
  228. *ptr += 3;
  229. num = **ptr;
  230. *ptr += 9;
  231. *ptr += 8 * 2; // AUDIO
  232. *ptr += 32 * 4; // SUBPICTURE
  233. *ptr += 8;
  234. *ptr += 16 * PGCI_COLOR_LEN; // CLUT
  235. *ptr += 4;
  236. *ptr =  get2bytes(*ptr) + pgc;
  237. return num;
  238. }
  239. static void get_ifo_playlist(mpeg3_t *file, mpeg3_demuxer_t *demuxer)
  240. {
  241. DIR *dirstream;
  242. char directory[MPEG3_STRLEN];
  243. char filename[MPEG3_STRLEN];
  244. char complete_path[MPEG3_STRLEN];
  245. char title_path[MPEG3_STRLEN];
  246. char vob_prefix[MPEG3_STRLEN];
  247. struct dirent *new_filename;
  248. char *ptr;
  249. int64_t total_bytes = 0;
  250. int done = 0, i;
  251. // Get titles matching ifo file
  252. mpeg3io_complete_path(complete_path, file->fs->path);
  253. mpeg3io_get_directory(directory, complete_path);
  254. mpeg3io_get_filename(filename, complete_path);
  255. strncpy(vob_prefix, filename, 6);
  256. dirstream = opendir(directory);
  257. while(new_filename = readdir(dirstream))
  258. {
  259. if(!strncasecmp(new_filename->d_name, vob_prefix, 6))
  260. {
  261. ptr = strrchr(new_filename->d_name, '.');
  262. if(ptr && !strncasecmp(ptr, ".vob", 4))
  263. {
  264. // Got a title
  265. if(atol(&new_filename->d_name[7]) > 0)
  266. {
  267. mpeg3_title_t *title;
  268. mpeg3io_joinpath(title_path, directory, new_filename->d_name);
  269. title = demuxer->titles[demuxer->total_titles++] = mpeg3_new_title(file, title_path);
  270. title->total_bytes = mpeg3io_path_total_bytes(title_path);
  271. total_bytes += title->total_bytes;
  272. //printf("%sn", title_path);
  273. }
  274. }
  275. }
  276. }
  277. // Alphabetize titles.  Only problematic for guys who rip entire DVD's
  278. // to their hard drives while retaining the file structure.
  279. while(!done)
  280. {
  281. done = 1;
  282. for(i = 0; i < demuxer->total_titles - 1; i++)
  283. {
  284. if(strcmp(demuxer->titles[i]->fs->path, demuxer->titles[i + 1]->fs->path) > 0)
  285. {
  286. mpeg3_title_t *temp = demuxer->titles[i];
  287. demuxer->titles[i] = demuxer->titles[i + 1];
  288. demuxer->titles[i + 1] = temp;
  289. done = 0;
  290. }
  291. }
  292. }
  293. }
  294. // IFO parsing
  295. static void get_ifo_header(mpeg3_demuxer_t *demuxer, ifo_t *ifo)
  296. {
  297. int i;
  298. // Video header
  299. demuxer->vstream_table[0] = 1;
  300. // Audio header
  301. if(!ifo_vts(ifo))
  302. {
  303. ifo_audio_t *audio;
  304. int result = 0;
  305. // Doesn't detect number of tracks.
  306. int atracks = ifo_audio((char*)ifo->data[ID_MAT] + IFO_OFFSET_AUDIO, (char**)&audio);
  307. int atracks_empirical = 0;
  308. // Construct audio stream id's
  309. #define TEST_START 0x600000
  310. #define TEST_LEN   0x100000
  311. mpeg3demux_open_title(demuxer, 0);
  312. mpeg3demux_seek_byte(demuxer, TEST_START);
  313. while(!result && 
  314. !mpeg3demux_eof(demuxer) && 
  315. mpeg3demux_tell(demuxer) < TEST_START + TEST_LEN)
  316. {
  317. result = mpeg3_read_next_packet(demuxer);
  318. }
  319. mpeg3demux_seek_byte(demuxer, 0);
  320. for(i = 0; i < MPEG3_MAX_STREAMS; i++)
  321. {
  322. //printf("%x %dn", i, demuxer->astream_table[i]);
  323. if(demuxer->astream_table[i]) atracks_empirical++;
  324. }
  325. // Doesn't detect PCM audio or total number of tracks
  326. /*
  327.  *  if(atracks && !atracks_empirical)
  328.  *  for(i = 0; i < atracks; i++)
  329.  *  {
  330.  *  int audio_mode = AUDIO_AC3;
  331.  *  switch(audio->coding_mode)
  332.  *  {
  333.  *  case 0: audio_mode = AUDIO_AC3;  break;
  334.  *  case 1: audio_mode = AUDIO_MPEG; break;
  335.  *  case 2: audio_mode = AUDIO_MPEG; break;
  336.  *  case 3: audio_mode = AUDIO_PCM;  break;
  337.  *  }
  338.  *  if(!demuxer->astream_table[i + 0x80]) demuxer->astream_table[i + 0x80] = audio_mode;
  339.  *  }
  340.  */
  341. }
  342. else
  343. if(!ifo_vmg(ifo))
  344. {
  345. }
  346. }
  347. static mpeg3ifo_cell_t* append_cell(mpeg3ifo_celltable_t *table)
  348. {
  349. if(!table->cells || table->total_cells >= table->cells_allocated)
  350. {
  351. long new_allocation;
  352. mpeg3ifo_cell_t *new_cells;
  353. new_allocation = table->cells_allocated ? table->cells_allocated * 2 : 64;
  354. new_cells = calloc(1, sizeof(mpeg3ifo_cell_t) * new_allocation);
  355. if(table->cells)
  356. {
  357. memcpy(new_cells, table->cells, sizeof(mpeg3ifo_cell_t) * table->total_cells);
  358. free(table->cells);
  359. }
  360. table->cells = new_cells;
  361. table->cells_allocated = new_allocation;
  362. }
  363. return &table->cells[table->total_cells++];
  364. }
  365. static void delete_celltable(mpeg3ifo_celltable_t *table)
  366. {
  367. if(table->cells) free(table->cells);
  368. free(table);
  369. }
  370. static void cellplayinfo(ifo_t *ifo, mpeg3ifo_celltable_t *cells)
  371. {
  372. int i, j;
  373. char *cell_hdr, *cell_hdr_start, *cell_info;
  374. ifo_hdr_t *hdr = (ifo_hdr_t*)ifo->data[ID_TITLE_PGCI];
  375. int program_chains = B2N_16(hdr->num);
  376. long total_cells;
  377. //printf("cellplayinfon");
  378. for(j = 0; j < program_chains; j++)
  379. {
  380. // Cell header
  381. pgci(hdr, j, &cell_hdr);
  382. cell_hdr_start = cell_hdr;
  383. // Unknown
  384. cell_hdr += 2;
  385. // Num programs
  386. cell_hdr += 2;
  387. // Chain Time
  388. cell_hdr += 4;
  389. // Unknown
  390. cell_hdr += 4;
  391. // Subaudio streams
  392. for(i = 0; i < 8; i++) cell_hdr += 2;
  393. // Subpictures
  394. for(i = 0; i < 32; i++) cell_hdr += 4;
  395. // Unknown
  396. for(i = 0; i < 8; i++) cell_hdr++;
  397. // Skip CLUT
  398. // Skip PGC commands
  399. // Program map
  400. if(program_map(cell_hdr_start, &cell_hdr))
  401. ;
  402. // Cell Positions
  403. if(total_cells = get_cellplayinfo((unsigned char*)cell_hdr_start, (unsigned char**)&cell_hdr))
  404. {
  405. //printf("cellplayinfo %d %dn", j, total_cells);
  406. cell_info = cell_hdr;
  407. for(i = 0; i < total_cells; i++)
  408. {
  409. ifo_pgci_cell_addr_t *cell_addr = (ifo_pgci_cell_addr_t *)cell_info;
  410. long start_byte = B2N_32(cell_addr->vobu_start);
  411. long end_byte = B2N_32(cell_addr->vobu_last_end);
  412. int cell_type = cell_addr->chain_info;
  413. if(!cells->total_cells && start_byte > 0)
  414. start_byte = 0;
  415. if(!cells->total_cells ||
  416. end_byte >= cells->cells[cells->total_cells - 1].end_byte)
  417. {
  418. mpeg3ifo_cell_t *cell = append_cell(cells);
  419. cell->start_byte = start_byte;
  420. cell->end_byte = end_byte;
  421. cell->cell_type = cell_type;
  422. //printf("cellplayinfo start: %llx end: %llx type: %xn", 
  423. // (int64_t)cell->start_byte * 0x800, (int64_t)cell->end_byte * 0x800, cell->cell_type);
  424. }
  425. cell_info += PGCI_CELL_ADDR_LEN;
  426. }
  427. }
  428. }
  429. }
  430. static void celladdresses(ifo_t *ifo, mpeg3ifo_celltable_t *cell_addresses)
  431. {
  432. int i;
  433. char *ptr = (char*)ifo->data[ID_TITLE_CELL_ADDR];
  434. int total_addresses;
  435. cell_addr_hdr_t *cell_addr_hdr = (cell_addr_hdr_t*)ptr;
  436. ifo_cell_addr_t *cell_addr = (ifo_cell_addr_t*)(ptr + CADDR_HDR_LEN);
  437. int done = 0;
  438. //printf("celladdressesn");
  439. if(total_addresses = B2N_32(cell_addr_hdr->len) / sizeof(ifo_cell_addr_t))
  440. {
  441. for(i = 0; i < total_addresses; i++)
  442. {
  443. mpeg3ifo_cell_t *cell;
  444. cell = append_cell(cell_addresses);
  445. cell->start_byte = (int64_t)B2N_32(cell_addr->start);
  446. cell->end_byte = (int64_t)B2N_32(cell_addr->end);
  447. cell->vob_id = B2N_16(cell_addr->vob_id);
  448. cell->cell_id = cell_addr->cell_id;
  449. /*
  450.  * printf("celladdresses vob id: %x cell id: %x start: %ld end: %ldn", 
  451.  *  B2N_16(cell_addr->vob_id), cell_addr->cell_id, (long)cell->start_byte, (long)cell->end_byte);
  452.  */
  453. cell_addr++;
  454. }
  455. }
  456. // Sort addresses by address instead of vob id
  457. done = 0;
  458. while(!done)
  459. {
  460. done = 1;
  461. for(i = 0; i < total_addresses - 1; i++)
  462. {
  463. mpeg3ifo_cell_t *cell1, *cell2;
  464. cell1 = &cell_addresses->cells[i];
  465. cell2 = &cell_addresses->cells[i + 1];
  466. if(cell1->start_byte > cell2->start_byte)
  467. {
  468. mpeg3ifo_cell_t temp = *cell1;
  469. *cell1 = *cell2;
  470. *cell2 = temp;
  471. done = 0;
  472. break;
  473. }
  474. }
  475. }
  476. for(i = 0; i < total_addresses; i++)
  477. {
  478. mpeg3ifo_cell_t *cell = &cell_addresses->cells[i];
  479. //printf("celladdresses vob id: %x cell id: %x start: %ld end: %ldn", 
  480. // cell->vob_id, cell->cell_id, (long)cell->start_byte, (long)cell->end_byte);
  481. }
  482. }
  483. static void finaltable(mpeg3ifo_celltable_t *final_cells, 
  484. mpeg3ifo_celltable_t *cells, 
  485. mpeg3ifo_celltable_t *cell_addresses)
  486. {
  487. int input_cell = 0, current_address = 0;
  488. int output_cell = 0;
  489. int done;
  490. int i, j;
  491. int current_vobid;
  492. // Start and end bytes of programs
  493. long program_start_byte[256], program_end_byte[256];
  494. final_cells->total_cells = 0;
  495. final_cells->cells_allocated = cell_addresses->total_cells;
  496. final_cells->cells = calloc(1, sizeof(mpeg3ifo_cell_t) * final_cells->cells_allocated);
  497. // Assign programs to cells
  498. current_vobid = -1;
  499. for(i = cell_addresses->total_cells - 1; i >= 0; i--)
  500. {
  501. mpeg3ifo_cell_t *input = &cell_addresses->cells[i];
  502. mpeg3ifo_cell_t *output = &final_cells->cells[i];
  503. if(current_vobid < 0) current_vobid = input->vob_id;
  504. *output = *input;
  505. // Reduce current vobid
  506. if(input->vob_id < current_vobid)
  507. current_vobid = input->vob_id;
  508. else
  509. // Get the current program number
  510. if(input->vob_id > current_vobid)
  511. {
  512. int current_program = input->vob_id - current_vobid;
  513. output->program = current_program;
  514. // Get the last interleave by brute force
  515. for(j = i; 
  516. j < cell_addresses->total_cells && cell_addresses->cells[i].cell_id == cell_addresses->cells[j].cell_id; 
  517. j++)
  518. {
  519. int new_program = final_cells->cells[j].vob_id - current_vobid;
  520. if(new_program <= current_program)
  521. final_cells->cells[j].program = new_program;
  522. }
  523. }
  524. final_cells->total_cells++;
  525. }
  526. // Expand byte position and remove duplicates
  527. for(i = 0; i < final_cells->total_cells; i++)
  528. {
  529. if(i < final_cells->total_cells - 1 &&
  530. final_cells->cells[i].start_byte == final_cells->cells[i + 1].start_byte)
  531. {
  532. for(j = i; j < final_cells->total_cells - 1; j++)
  533. final_cells->cells[j] = final_cells->cells[j + 1];
  534. final_cells->total_cells--;
  535. }
  536. final_cells->cells[i].start_byte *= (int64_t)2048;
  537. final_cells->cells[i].end_byte *= (int64_t)2048;
  538. }
  539. return;
  540. // Debug
  541. printf("finaltablen");
  542. for(i = 0; i < final_cells->total_cells; i++)
  543. {
  544. printf(" vob id: %x cell id: %x start: %llx end: %llx program: %xn", 
  545. 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);
  546. }
  547. }
  548. /* Read the title information from a ifo */
  549. static int read_ifo(mpeg3_t *file, 
  550. mpeg3_demuxer_t *demuxer, 
  551. int read_timecodes)
  552. {
  553. int64_t last_ifo_byte = 0, first_ifo_byte = 0;
  554. mpeg3ifo_celltable_t *cells, *cell_addresses, *final_cells;
  555. int current_title = 0, current_cell = 0;
  556. int i;
  557. ifo_t *ifo;
  558.     int fd = mpeg3io_get_fd(file->fs);
  559. int64_t title_start_byte = 0;
  560. int result;
  561. //printf("read_ifo 1n");
  562. if(!(ifo = ifo_open(fd, 0))) 
  563. {
  564. fprintf(stderr, "read_ifo: Error decoding ifo.n");
  565. return 1;
  566. }
  567. //printf("read_ifo 1n");
  568. // file->packet_size = 2048;
  569. demuxer->read_all = 1;
  570. cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
  571. cell_addresses = calloc(1, sizeof(mpeg3ifo_celltable_t));
  572. final_cells = calloc(1, sizeof(mpeg3ifo_celltable_t));
  573. //printf("read_ifo 1n");
  574. get_ifo_playlist(file, demuxer);
  575. get_ifo_header(demuxer, ifo);
  576. cellplayinfo(ifo, cells);
  577. celladdresses(ifo, cell_addresses);
  578. finaltable(final_cells, 
  579. cells, 
  580. cell_addresses);
  581. //printf("read_ifo 2n");
  582. // Assign cells to titles
  583. while(final_cells && current_cell < final_cells->total_cells)
  584. {
  585. mpeg3_title_t *title;
  586. mpeg3ifo_cell_t *cell;
  587. int64_t cell_start, cell_end;
  588. int64_t length = 1;
  589. title = demuxer->titles[current_title];
  590. cell = &final_cells->cells[current_cell];
  591. cell_start = cell->start_byte;
  592. cell_end = cell->end_byte;
  593. //printf("read_ifo 1 %d %llx %llx %dn", current_cell, (int64_t)cell->start_byte, (int64_t)cell->end_byte, cell->program);
  594. while(cell_start < cell_end && length)
  595. {
  596. length = cell_end - cell_start;
  597. if(cell_start + length - title_start_byte > title->total_bytes)
  598. length = title->total_bytes - cell_start + title_start_byte;
  599. //printf("read_ifo 3 %llx - %llx + %llx = %llxn", title->total_bytes, cell_start, title_start_byte, length);
  600. // Should never fail.  If it does it means the length of the cells and the
  601. // length of the titles don't match.  The title lengths must match or else
  602. // the cells won't line up.
  603. if(length)
  604. {
  605. mpeg3_new_timecode(title, 
  606. (long)(cell_start - title_start_byte), 
  607. 0,
  608. (long)(cell_start - title_start_byte + length),
  609. 0,
  610. cell->program);
  611. cell_start += length;
  612. }
  613. else
  614. {
  615. fprintf(stderr, "read_ifo: cell length and title length don't match.n");
  616. }
  617. // Advance title
  618. if(cell_start - title_start_byte >= title->total_bytes && 
  619. current_title < demuxer->total_titles - 1)
  620. {
  621. title_start_byte += title->total_bytes;
  622. title = demuxer->titles[++current_title];
  623. }
  624. }
  625. current_cell++;
  626. }
  627. //printf("read_ifo 4n");
  628. // Look up time values for the timecodes
  629. // Should only be used for building a TOC
  630. if(read_timecodes)
  631. {
  632. for(current_title = 0; current_title < demuxer->total_titles; current_title++)
  633. {
  634. mpeg3_title_t *title = demuxer->titles[current_title];
  635. mpeg3demux_open_title(demuxer, current_title);
  636. for(i = 0; i < title->timecode_table_size; i++)
  637. {
  638. mpeg3demux_timecode_t *timecode = &title->timecode_table[i];
  639. mpeg3io_seek(title->fs, timecode->start_byte);
  640. mpeg3_read_next_packet(demuxer);
  641. timecode->start_time = demuxer->time;
  642. mpeg3io_seek(title->fs, timecode->end_byte);
  643. if(timecode->end_byte >= title->total_bytes)
  644. mpeg3_read_prev_packet(demuxer);
  645. else
  646. mpeg3_read_next_packet(demuxer);
  647. timecode->end_time = demuxer->time;
  648. }
  649. }
  650. mpeg3demux_open_title(demuxer, 0);
  651. }
  652. //for(i = 0; i < demuxer->total_titles; i++) mpeg3_dump_title(demuxer->titles[i]);
  653. delete_celltable(cells);
  654. delete_celltable(cell_addresses);
  655. delete_celltable(final_cells);
  656. ifo_close(ifo);
  657. //printf("read_ifo 5n");
  658. mpeg3demux_assign_programs(demuxer);
  659. //printf("read_ifo 6n");
  660. return 0;
  661. }
  662. int mpeg3_read_ifo(mpeg3_t *file, int read_timecodes)
  663. {
  664. file->is_program_stream = 1;
  665. read_ifo(file, file->demuxer, read_timecodes);
  666. return 0;
  667. }