-
Notifications
You must be signed in to change notification settings - Fork 5
/
dvd_chapter.c
133 lines (87 loc) · 4.22 KB
/
dvd_chapter.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "dvd_vmg_ifo.h"
#include "dvd_track.h"
#include "dvd_chapter.h"
/** It's a *safe guess* that if the program_map is NULL or there is no starting cell,
* that the starting cell is actually the same as the chapter number. See DVD id 79,
* track #12 for an example where this matches (NULL values)
*
* TODO some closer examination to check that cells and chapters match up properly
* is probably in order. Some scenarios to look for would be where there are more
* chapters than cells, and the lengths of chapters don't exceed cells either. Doing
* so would be a good fit for dvd_debug program.
*/
uint8_t dvd_chapter_first_cell(ifo_handle_t *vmg_ifo, ifo_handle_t *vts_ifo, uint16_t track_number, uint8_t chapter_number) {
if(vts_ifo->vts_pgcit == NULL || vts_ifo->vts_ptt_srpt == NULL || vts_ifo->vts_ptt_srpt->title == NULL)
return chapter_number;
uint8_t ttn = dvd_track_ttn(vmg_ifo, track_number);
pgcit_t *vts_pgcit = vts_ifo->vts_pgcit;
pgc_t *pgc = vts_pgcit->pgci_srp[vts_ifo->vts_ptt_srpt->title[ttn - 1].ptt[0].pgcn - 1].pgc;
if(pgc == NULL || pgc->program_map == NULL)
return chapter_number;
uint8_t first_cell = pgc->program_map[chapter_number - 1];
if(first_cell > 0)
return first_cell;
else
return chapter_number;
}
/**
* We know how many cells are on the track, and I'm somewhat guessing where the
* first cell is on a chapter, so I'm not totally confident that this is always
* correct -- but I'm saying that with the basis that there could be some
* oddly mastered DVDs out there or some tricky navigation instructions. In
* short, I'm overly cautious, and this will probably work just fine.
*/
uint8_t dvd_chapter_last_cell(ifo_handle_t *vmg_ifo, ifo_handle_t *vts_ifo, uint16_t track_number, uint8_t chapter_number) {
if(vts_ifo->vts_pgcit == NULL || vts_ifo->vts_ptt_srpt == NULL || vts_ifo->vts_ptt_srpt->title == NULL)
return chapter_number;
uint8_t ttn = dvd_track_ttn(vmg_ifo, track_number);
pgcit_t *vts_pgcit = vts_ifo->vts_pgcit;
pgc_t *pgc = vts_pgcit->pgci_srp[vts_ifo->vts_ptt_srpt->title[ttn - 1].ptt[0].pgcn - 1].pgc;
if(pgc == NULL || pgc->program_map == NULL)
return chapter_number;
uint8_t track_chapters = dvd_track_chapters(vmg_ifo, vts_ifo, track_number);
if(chapter_number == track_chapters)
return pgc->nr_of_cells;
uint8_t first_cell = dvd_chapter_first_cell(vmg_ifo, vts_ifo, track_number, chapter_number);
uint8_t last_cell = first_cell;
if(chapter_number < track_chapters) {
uint8_t next_chapter_first_cell = dvd_chapter_first_cell(vmg_ifo, vts_ifo, track_number, chapter_number + 1);
last_cell = next_chapter_first_cell - 1;
}
return last_cell;
}
uint8_t dvd_chapter_cells(ifo_handle_t *vmg_ifo, ifo_handle_t *vts_ifo, uint16_t track_number, uint8_t chapter_number) {
uint8_t first_cell = dvd_chapter_first_cell(vmg_ifo, vts_ifo, track_number, chapter_number);
uint8_t last_cell = dvd_chapter_first_cell(vmg_ifo, vts_ifo, track_number, chapter_number);
return last_cell - first_cell + 1;
}
uint64_t dvd_chapter_blocks(ifo_handle_t *vmg_ifo, ifo_handle_t *vts_ifo, uint16_t track_number, uint8_t chapter_number) {
uint8_t first_cell = dvd_chapter_first_cell(vmg_ifo, vts_ifo, track_number, chapter_number);
uint8_t last_cell = dvd_chapter_last_cell(vmg_ifo, vts_ifo, track_number, chapter_number);
uint8_t cell;
uint64_t cell_blocks = 0;
uint64_t chapter_blocks = 0;
for(cell = first_cell; cell < last_cell + 1; cell++) {
cell_blocks = dvd_cell_blocks(vmg_ifo, vts_ifo, track_number, cell);
chapter_blocks += cell_blocks;
}
return chapter_blocks;
}
uint64_t dvd_chapter_filesize(ifo_handle_t *vmg_ifo, ifo_handle_t *vts_ifo, uint16_t track_number, uint8_t chapter_number) {
uint64_t blocks;
blocks = dvd_chapter_blocks(vmg_ifo, vts_ifo, track_number, chapter_number);
uint64_t filesize = 0;
filesize = blocks * DVD_VIDEO_LB_LEN;
return filesize;
}
double dvd_chapter_filesize_mbs(ifo_handle_t *vmg_ifo, ifo_handle_t *vts_ifo, uint16_t track_number, uint8_t chapter_number) {
uint64_t blocks;
blocks = dvd_chapter_blocks(vmg_ifo, vts_ifo, track_number, chapter_number);
if(blocks == 0)
return 0;
double filesize_mbs = 0;
filesize_mbs = (blocks * DVD_VIDEO_LB_LEN) / 1048576.0;
if(filesize_mbs < 1.0)
filesize_mbs = 1.0;
return filesize_mbs;
}