]> git.pld-linux.org Git - packages/dvdbackup.git/blame - dvdbackup.c
- fix for libdvdread, rel 2
[packages/dvdbackup.git] / dvdbackup.c
CommitLineData
0fd9c7fb 1/*
2 * Copyright (C) 2002 Olaf Beck <olaf_sc@yahoo.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19/* dvdbackup version 0.1 */
20
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <sys/errno.h>
26#include <errno.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <fcntl.h>
30#include <unistd.h>
31#include <string.h>
32#include <limits.h>
33#include <dvdread/dvd_reader.h>
34#include <dvdread/ifo_read.h>
35#include <dvdread/ifo_print.h>
36
37
38#define MAXNAME 256
39
40/*Flag for verbose mode */
41int verbose;
42int aspect;
43
44
45/* Structs to keep title set information in */
46
47typedef struct {
48 int size_ifo;
49 int size_menu;
50 int size_bup;
51 int number_of_vob_files;
52 int size_vob[10];
53} title_set_t;
54
55typedef struct {
56 int number_of_title_sets;
57 title_set_t *title_set;
58} title_set_info_t;
59
60
61typedef struct {
62 int title;
63 int title_set;
64 int vts_title;
65 int chapters;
66 int aspect_ratio;
67 int angles;
68 int audio_tracks;
69 int audio_channels;
70 int sub_pictures;
71} titles_t;
72
73typedef struct {
74 int main_title_set;
75 int number_of_titles;
76 titles_t *titles;
77} titles_info_t;
78
79
80void bsort_max_to_min(int sector[], int title[], int size);
81
82/* Usage:
83 To gather info about the dvd:
84 dvdbackup -i /dev/dvd -I
85
86 Gerneral backup information:
87 If your backup directory is /my/dvd/backup/dir/
88 specified with the "-o" flag. Then dvdbackup
89 will create a DVD-Video structure under
90 /my/dvd/backup/dir/TITLE_NAME/VIDEO_TS.
91
92 Since the title is "uniq" you can use the same dir
93 for all your DVD backups. If it happens to have a
94 generic title dvdbackup will exit with a return value
95 of 2. And you will need to specify a title name with
96 the -n switch.
97
98 dvdbackup will always mimic the original DVD-Video
99 structure. Hence if you e.g. use the -M (mirror) you
100 will get an exact duplicate of the original. This
101 means that every file will be have the same size as
102 the original one. Like wise goes also for the -F
103 and the -T switch.
104
105 However the -t and (-t -s/-e) switch is a bit
106 different the titles sectors will be written to the
107 original file but not at the same offset as the
108 original one since they may be gaps in the cell
109 structure that we don't fill.
110
111
112 To backup the whole DVD
113
114 dvdbackup -M -i/dev/dvd -o/my/dvd/backup/dir/
115
116 This action creates a valid DVD-Video structure
117 that can be burned to a DVD-/+R(W) with help of
118 mkisofs version 1.11a27 or later
119
120
121 To backup the main feature of the DVD:
122
123 dvdbackup -F -i/dev/dvd -o/my/dvd/backup/dir/
124
125 This action creates a valid DVD-Video structure
126 of the feature title set
127
128 dvdbackup defaults to get the 16:9 version of the
129 main feature if a 4:3 is also present on the DVD.
130 To get the 4:3 version use -a 0.
131
132 dvdbackup makes it best to make a inteligent guess
133 what is the main feature of the DVD - in case it fails
134 please send a bug report.
135
136
137 To backup a title set
138
139 dvdbackup -T 2 -i/dev/dvd -o/my/dvd/backup/dir/
140
141 where "-T 2" specifies that you want to backup
142 title set 2 i.e. all VTS_02_X.XXX files.
143
144 This action creates a valid DVD-Video structure
145 of the specified title set
146
147
148 To backup a title:
149
150 dvdbackup -t 1 -i/dev/dvd -o/my/dvd/backup/dir
151
152 This action backups all cells that forms the
153 specified title. Note that there can be sector
154 gaps in between one cell and an other. dvdbackup
155 will backup all sectors that belongs to the title
156 but will skip sectors that aren't a part of the title.
157
158
159 To backup a specific chapter or chapters from a title:
160
161 dvdbackup -t 1 -s 20 -e 25 -i/dev/dvd -o/my/dvd/backup/dir
162
163 This action will backup chapter 20 to 25 in title 1, as with
164 the backup of a title there can be sector gaps between one chapter
165 (cell) and on other.dvdbackup will backup all sectors that belongs
166 to the title 1 chapter 20 to 25 but will skip sectors that aren't
167 a part of the title 1 chapter 20 to 25.
168
169 To backup a single chapter e.g. chapter 20 do -s 20 -e 20
170 To backup from chapter 20 to the end chapter use only -s 20
171 To backup to chapter 20 from the first chapter use only -e 20
172
173 You can skip the -t switch and let the program guess the title although
174 it's not recomened.
175
176 If you specify a chapter that his higher than the last chapter of the title
177 dvdbackup will turncate to the highest chapter of the title.
178
179 Return values:
180 0 on success
181 1 on usage error
182 2 on title name error
183 -1 on failur
184
185
186 Todo - i.e. what's on the agenda.
187 Make the main feature guessing algoritm better. Not that it doesn't do
188 it's job, but it's implementation it's that great. I would also like
189 to preserve more information about the main feature since that would
190 let me preform better implementations in other functions that depends
191 on the titles_info_t and title_set_info_t strcutures.
192
193 Make it possible to extract cells in a title not just chapters (very
194 easy so it will definitly be in the next version).
195
196 Make a split mirror (-S) option that divides a DVD-9 to two valid DVD-5
197 video structures. This is not a trivial hack and it's my main goal
198 the next month or so. It involves writing ifoedit and vobedit
199 libraries in order to be able to manipulate both the IFO structures
200 and the VOB files. Out of this will most probably also come tscreate
201 and vtscreate which will enable you to make a very simple DVD-Video
202 from MPEG-1/2 source.
203
204*/
205
206
207void usage(){
208 fprintf(stderr,"\nUsage: dvdbackup [options]\n");
209 fprintf(stderr,"\t-i device\twhere device is your dvd device\n");
210 fprintf(stderr,"\t-v X\t\twhere X is the amount of verbosity\n");
211 fprintf(stderr,"\t-I\t\tfor information about the DVD\n");
212 fprintf(stderr,"\t-o directory\twhere directory is your backup target\n");
213 fprintf(stderr,"\t-M\t\tbackup the whole DVD\n");
214 fprintf(stderr,"\t-F\t\tbackup the main feature of the DVD\n");
215 fprintf(stderr,"\t-T X\t\tbackup title set X\n");
216 fprintf(stderr,"\t-t X\t\tbackup title X\n");
217 fprintf(stderr,"\t-s X\t\tbackup from chapter X\n");
218 fprintf(stderr,"\t-e X\t\tbackup to chapter X\n");
219 fprintf(stderr,"\t-a 0\t\tto get aspect ratio 4:3 instead of 16:9 if both are present\n");
220 fprintf(stderr,"\t-h\t\tprint a brief usage message\n");
221 fprintf(stderr,"\t-?\t\tprint a brief usage message\n\n");
222 fprintf(stderr,"\t-i is manditory\n");
223 fprintf(stderr,"\t-o is manditory except if you use -I\n");
224 fprintf(stderr,"\t-a is option to the -F switch and has no effect on other options\n");
225 fprintf(stderr,"\t-s and -e should prefereibly be used together with -t \n\n");
226 exit(1);
227}
228
229int CheckSizeArray(const int size_array[], int reference, int target) {
230 if ( (size_array[reference]/size_array[target] == 1) &&
231 ((size_array[reference] * 2 - size_array[target])/ size_array[target] == 1) &&
232 ((size_array[reference]%size_array[target] * 3) < size_array[reference]) ) {
233 /* We have a dual DVD with two feature films - now lets see if they have the same amount of chapters*/
234 return(1);
235 } else {
236 return(0);
237 }
238}
239
240
241int CheckAudioSubChannels(int audio_audio_array[], int title_set_audio_array[],
242 int subpicture_sub_array[], int title_set_sub_array[],
243 int channels_channel_array[],int title_set_channel_array[],
244 int reference, int candidate, int title_sets) {
245
246 int temp, i, found_audio, found_sub, found_channels;
247
248 found_audio=0;
249 temp = audio_audio_array[reference];
250 for (i=0 ; i < title_sets ; i++ ) {
251 if ( audio_audio_array[i] < temp ) {
252 break;
253 }
254 if ( candidate == title_set_audio_array[i] ) {
255 found_audio=1;
256 break;
257 }
258
259 }
260
261 found_sub=0;
262 temp = subpicture_sub_array[reference];
263 for (i=0 ; i < title_sets ; i++ ) {
264 if ( subpicture_sub_array[i] < temp ) {
265 break;
266 }
267 if ( candidate == title_set_sub_array[i] ) {
268 found_sub=1;
269 break;
270 }
271
272 }
273
274
275 found_channels=0;
276 temp = channels_channel_array[reference];
277 for (i=0 ; i < title_sets ; i++ ) {
278 if ( channels_channel_array[i] < temp ) {
279 break;
280 }
281 if ( candidate == title_set_channel_array[i] ) {
282 found_channels=1;
283 break;
284 }
285
286 }
287
288
289 return(found_audio + found_sub + found_channels);
290}
291
292
293
294
295int DVDWriteCells(dvd_reader_t * dvd, int cell_start_sector[], int cell_end_sector[],
296 int length, int titles, title_set_info_t * title_set_info, titles_info_t * titles_info, char * targetdir,char * title_name){
297
298
299 /* Loop variables */
300 int i, f;
301
302
303 /* Vob control */
304 int vob;
305
306 /* Temp filename,dirname */
307 char targetname[PATH_MAX];
308
309 /* Write buffer */
310
311 unsigned char * buffer=NULL;
312
313 /* File Handler */
314 int streamout;
315
316 int size;
317 int left;
318 int leftover;
319
320 /* Buffer size in DVD sectors */
321 /* Currently set to 1MB */
322 int buff = 512;
323 int tsize;
324
325
326 /* Offsets */
327 int soffset;
328 int offset;
329
330
331 /* DVD handler */
332 dvd_file_t * dvd_file=NULL;
333
334 int title_set;
335 int number_of_vob_files;
336
337#ifdef DEBUG
338 fprintf(stderr,"DVDWriteCells: length is %d\n", length);
339
340#endif
341
342
343 title_set = titles_info->titles[titles - 1].title_set;
344 number_of_vob_files = title_set_info->title_set[title_set].number_of_vob_files;
345#ifdef DEBUG
346 fprintf(stderr,"DVDWriteCells: title set is %d\n", title_set);
347 fprintf(stderr,"DVDWriteCells: vob files are %d\n", number_of_vob_files);
348
349#endif
350
351
352
353 /* Remove all old files silently if they exists */
354
355 for ( i = 0 ; i < 10 ; i++ ) {
356 sprintf(targetname,"%s/%s/VIDEO_TS/VTS_%02i_%i.VOB",targetdir, title_name, title_set, i + 1);
357#ifdef DEBUG
358 fprintf(stderr,"DVDWriteCells: file is %s\n", targetname);
359
360#endif
361
362 unlink( targetname);
363
364 }
365
366
367
368
369 /* Loop through all sectors and find the right vob */
370 for (f = 0; f < length ; f++) {
371
372 soffset=0;
373 offset=0;
374
375
376 /* Now figure which vob we will use and write to that vob and if there is a left over write to the next vob*/
377
378 for ( i = 0; i < number_of_vob_files ; i++ ) {
379
380
381 tsize = title_set_info->title_set[title_set].size_vob[i];
382
383 if (tsize%2048 != 0) {
384 fprintf(stderr, "The Title VOB number %d of title set %d doesn't have a valid DVD size\n", i + 1, title_set);
385 return(1);
386 } else {
387 soffset = offset;
388 offset = offset + tsize/2048;
389 }
390#ifdef DEBUG
391 fprintf(stderr,"DVDWriteCells: soffset is %d\n", soffset);
392 fprintf(stderr,"DVDWriteCells: offset is %d\n", offset);
393#endif
394 /* Find out if this is the right vob */
395 if( soffset <= cell_start_sector[f] && offset > cell_start_sector[f] ) {
396#ifdef DEBUG
397 fprintf(stderr,"DVDWriteCells: got it \n");
398#endif
399 leftover=0;
400 soffset = cell_start_sector[f];
401 if ( cell_end_sector[f] > offset ) {
402 leftover = cell_end_sector[f] - offset + 1;
403 } else {
404 size = cell_end_sector[f] - cell_start_sector[f] + 1;
405 }
406#ifdef DEBUG
407 fprintf(stderr,"DVDWriteCells: size is %d\n", size);
408#endif
409 vob = i + 1;
410 break;
411 }
412
413 }
414#ifdef DEBUG
415 fprintf(stderr,"DVDWriteCells: Writing soffset is %d and leftover is %d\n", soffset, leftover);
416#endif
417
418
419
420
421 /* Create VTS_XX_X.VOB */
422 if (title_set == 0) {
423 fprintf(stderr,"Don't try to copy chapters from the VMG domain there aren't any\n");
424 return(1);
425 } else {
426 sprintf(targetname,"%s/%s/VIDEO_TS/VTS_%02i_%i.VOB",targetdir, title_name, title_set, vob);
427 }
428
429#ifdef DEBUG
430 fprintf(stderr,"DVDWriteCells: 1\n");
431#endif
432
433
434 if ((buffer = (unsigned char *)malloc(buff * 2048 * sizeof(unsigned char))) == NULL) {
435 fprintf(stderr, "Out of memory coping %s\n", targetname);
436 return(1);
437 }
438
439#ifdef DEBUG
440 fprintf(stderr,"DVDWriteCells: 2\n");
441#endif
442
443
444 if ((streamout = open(targetname, O_WRONLY | O_CREAT | O_APPEND, 0644)) == -1) {
445 fprintf(stderr, "Error creating %s\n", targetname);
446 perror("");
447 return(1);
448 }
449
450#ifdef DEBUG
451 fprintf(stderr,"DVDWriteCells: 3\n");
452#endif
453
454
455 if ((dvd_file = DVDOpenFile(dvd, title_set, DVD_READ_TITLE_VOBS))== 0) {
456 fprintf(stderr, "Faild opending TITLE VOB\n");
457 free(buffer);
458 close(streamout);
459 return(1);
460 }
461
462 left = size;
463
464#ifdef DEBUG
465 fprintf(stderr,"DVDWriteCells: left is %d\n", left);
466#endif
467
468 while( left > 0 ) {
469
470 if (buff > left) {
471 buff = left;
472 }
473 if ( DVDReadBlocks(dvd_file,soffset,buff, buffer) != buff) {
474 fprintf(stderr, "Error reading MENU VOB\n");
475 free(buffer);
476 DVDCloseFile(dvd_file);
477 close(streamout);
478 return(1);
479 }
480
481
482 if (write(streamout,buffer,buff * 2048) != buff * 2048) {
483 fprintf(stderr, "Error writing TITLE VOB\n");
484 free(buffer);
485 close(streamout);
486 return(1);
487 }
488
489 soffset = soffset + buff;
490 left = left - buff;
491
492 }
493
494 DVDCloseFile(dvd_file);
495 free(buffer);
496 close(streamout);
497
498
499 if ( leftover != 0 ) {
500
501 vob = vob + 1;
502
503 if (title_set == 0) {
504 fprintf(stderr,"Don't try to copy chapters from the VMG domain there aren't any\n");
505 return(1);
506 } else {
507 sprintf(targetname,"%s/%s/VIDEO_TS/VTS_%02i_%i.VOB",targetdir, title_name, title_set, vob);
508 }
509
510
511 if ((buffer = (unsigned char *)malloc(buff * 2048 * sizeof(unsigned char))) == NULL) {
512 fprintf(stderr, "Out of memory coping %s\n", targetname);
513 close(streamout);
514 return(1);
515 }
516
517
518 if ((streamout = open(targetname, O_WRONLY | O_CREAT | O_APPEND, 0644)) == -1) {
519 fprintf(stderr, "Error creating %s\n", targetname);
520 perror("");
521 return(1);
522 }
523
524
525 if ((dvd_file = DVDOpenFile(dvd, title_set, DVD_READ_TITLE_VOBS))== 0) {
526 fprintf(stderr, "Faild opending TITLE VOB\n");
527 free(buffer);
528 close(streamout);
529 return(1);
530 }
531
532 left = leftover;
533
534 while( left > 0 ) {
535
536 if (buff > left) {
537 buff = left;
538 }
539 if ( DVDReadBlocks(dvd_file,offset,buff, buffer) != buff) {
540 fprintf(stderr, "Error reading MENU VOB\n");
541 free(buffer);
542 DVDCloseFile(dvd_file);
543 close(streamout);
544 return(1);
545 }
546
547
548 if (write(streamout,buffer,buff * 2048) != buff * 2048) {
549 fprintf(stderr, "Error writing TITLE VOB\n");
550 free(buffer);
551 close(streamout);
552 return(1);
553 }
554
555 offset = offset + buff;
556 left = left - buff;
557
558 }
559
560 DVDCloseFile(dvd_file);
561 free(buffer);
562 close(streamout);
563 }
564
565 }
566 return(0);
567}
568
569
570
571void FreeSortArrays( int chapter_chapter_array[], int title_set_chapter_array[],
572 int angle_angle_array[], int title_set_angle_array[],
573 int subpicture_sub_array[], int title_set_sub_array[],
574 int audio_audio_array[], int title_set_audio_array[],
575 int size_size_array[], int title_set_size_array[],
576 int channels_channel_array[], int title_set_channel_array[]) {
577
578
579 free(chapter_chapter_array);
580 free(title_set_chapter_array);
581
582 free(angle_angle_array);
583 free(title_set_angle_array);
584
585 free(subpicture_sub_array);
586 free(title_set_sub_array);
587
588 free(audio_audio_array);
589 free(title_set_audio_array);
590
591 free(size_size_array);
592 free(title_set_size_array);
593
594 free(channels_channel_array);
595 free(title_set_channel_array);
596}
597
598
599titles_info_t * DVDGetInfo(dvd_reader_t * _dvd) {
600
601 /* title interation */
602 int counter, i, f;
603
604 /* Our guess */
605 int candidate;
606 int multi = 0;
607 int dual = 0;
608
609
610 int titles;
611 int title_sets;
612
613 /* Arrays for chapter, angle, subpicture, audio, size, aspect, channels - file_set relationship */
614
615 /* Size == number_of_titles */
616 int * chapter_chapter_array;
617 int * title_set_chapter_array;
618
619 int * angle_angle_array;
620 int * title_set_angle_array;
621
622 /* Size == number_of_title_sets */
623
624 int * subpicture_sub_array;
625 int * title_set_sub_array;
626
627 int * audio_audio_array;
628 int * title_set_audio_array;
629
630 int * size_size_array;
631 int * title_set_size_array;
632
633 int * channels_channel_array;
634 int * title_set_channel_array;
635
636 /* Temp helpers */
637 int channels;
638 int temp;
639 int found;
640 int chapters_1;
641 int chapters_2;
642 int found_chapter;
643 int number_of_multi;
644
645
646 /*DVD handlers*/
647 ifo_handle_t * vmg_ifo=NULL;
648 dvd_file_t * vts_title_file=NULL;
649
650 titles_info_t * titles_info=NULL;
651
652 /* Open main info file */
653 vmg_ifo = ifoOpen( _dvd, 0 );
654 if( !vmg_ifo ) {
655 fprintf( stderr, "Can't open VMG info.\n" );
656 return (0);
657 }
658
659 titles = vmg_ifo->tt_srpt->nr_of_srpts;
660 title_sets = vmg_ifo->vmgi_mat->vmg_nr_of_title_sets;
661
662 if ((vmg_ifo->tt_srpt == 0) || (vmg_ifo->vts_atrt == 0)) {
663 ifoClose(vmg_ifo);
664 return(0);
665 }
666
667
668 /* Todo fix malloc check */
669 titles_info = ( titles_info_t *)malloc(sizeof(titles_info_t));
670 titles_info->titles = (titles_t *)malloc((titles)* sizeof(titles_t));
671
672 titles_info->number_of_titles = titles;
673
674
675 chapter_chapter_array = malloc(titles * sizeof(int));
676 title_set_chapter_array = malloc(titles * sizeof(int));
677
678 /*currently not used in the guessing */
679 angle_angle_array = malloc(titles * sizeof(int));
680 title_set_angle_array = malloc(titles * sizeof(int));
681
682
683 subpicture_sub_array = malloc(title_sets * sizeof(int));
684 title_set_sub_array = malloc(title_sets * sizeof(int));
685
686 audio_audio_array = malloc(title_sets * sizeof(int));
687 title_set_audio_array = malloc(title_sets * sizeof(int));
688
689 size_size_array = malloc(title_sets * sizeof(int));
690 title_set_size_array = malloc(title_sets * sizeof(int));
691
692 channels_channel_array = malloc(title_sets * sizeof(int));
693 title_set_channel_array = malloc(title_sets * sizeof(int));
694
695
696 /* Interate over the titles nr_of_srpts */
697
698
699 for (counter=0; counter < titles; counter++ ) {
700 /* For titles_info */
701 titles_info->titles[counter].title = counter + 1;
702 titles_info->titles[counter].title_set = vmg_ifo->tt_srpt->title[counter].title_set_nr;
703 titles_info->titles[counter].vts_title = vmg_ifo->tt_srpt->title[counter].vts_ttn;
704 titles_info->titles[counter].chapters = vmg_ifo->tt_srpt->title[counter].nr_of_ptts;
705 titles_info->titles[counter].angles = vmg_ifo->tt_srpt->title[counter].nr_of_angles;
706
707 /* For main title*/
708 chapter_chapter_array[counter] = vmg_ifo->tt_srpt->title[counter].nr_of_ptts;
709 title_set_chapter_array[counter] = vmg_ifo->tt_srpt->title[counter].title_set_nr;
710 angle_angle_array[counter] = vmg_ifo->tt_srpt->title[counter].nr_of_angles;
711 title_set_angle_array[counter] = vmg_ifo->tt_srpt->title[counter].title_set_nr;
712 }
713
714 /* Interate over vmg_nr_of_title_sets */
715
716 for (counter=0; counter < title_sets ; counter++ ) {
717
718 /* Picture*/
719 subpicture_sub_array[counter] = vmg_ifo->vts_atrt->vts[counter].nr_of_vtstt_subp_streams;
720 title_set_sub_array[counter] = counter + 1;
721
722
723 /* Audio */
724 audio_audio_array[counter] = vmg_ifo->vts_atrt->vts[counter].nr_of_vtstt_audio_streams;
725 title_set_audio_array[counter] = counter + 1;
726
727 channels=0;
728 for (i=0; i < audio_audio_array[counter]; i++) {
729 if ( channels < vmg_ifo->vts_atrt->vts[counter].vtstt_audio_attr[i].channels + 1) {
730 channels = vmg_ifo->vts_atrt->vts[counter].vtstt_audio_attr[i].channels + 1;
731 }
732
733 }
734 channels_channel_array[counter] = channels;
735 title_set_channel_array[counter] = counter + 1;
736
737 /* For tiles_info */
738 for (f=0; f < titles_info->number_of_titles ; f++ ) {
739 if ( titles_info->titles[f].title_set == counter + 1 ) {
740 titles_info->titles[f].aspect_ratio = vmg_ifo->vts_atrt->vts[counter].vtstt_vobs_video_attr.display_aspect_ratio;
741 titles_info->titles[f].sub_pictures = vmg_ifo->vts_atrt->vts[counter].nr_of_vtstt_subp_streams;
742 titles_info->titles[f].audio_tracks = vmg_ifo->vts_atrt->vts[counter].nr_of_vtstt_audio_streams;
743 titles_info->titles[f].audio_channels = channels;
744 }
745 }
746
747 }
748
749
750 /* Close the VMG ifo file we got all the info we need */
751 ifoClose(vmg_ifo);
752
753
754 for (counter=0; counter < title_sets; counter++ ) {
755
756 vts_title_file = DVDOpenFile(_dvd, counter + 1, DVD_READ_TITLE_VOBS);
757
758 if (vts_title_file != 0) {
759 size_size_array[counter] = DVDFileSize(vts_title_file);
760 DVDCloseFile(vts_title_file);
761 } else {
762 size_size_array[counter] = 0;
763 }
764
765 title_set_size_array[counter] = counter + 1;
766
767
768 }
769
770
771 /* Sort all arrays max to min */
772
773 bsort_max_to_min(chapter_chapter_array, title_set_chapter_array, titles);
774 bsort_max_to_min(angle_angle_array, title_set_angle_array, titles);
775 bsort_max_to_min(subpicture_sub_array, title_set_sub_array, title_sets);
776 bsort_max_to_min(audio_audio_array, title_set_audio_array, title_sets);
777 bsort_max_to_min(size_size_array, title_set_size_array, title_sets);
778 bsort_max_to_min(channels_channel_array, title_set_channel_array, title_sets);
779
780
781 /* Check if the second biggest one actually can be a feature title */
782 /* Here we will take do biggest/second and if that is bigger than one it's not a feauture title */
783 /* Now this is simply not enough since we have to check that the diff between the two of them is small enough
784 to consider the second one a feature title we are doing two checks (biggest + biggest - second) /second == 1
785 and biggest%second * 3 < biggest */
786
787 if ( CheckSizeArray(size_size_array, 0, 1) == 1 ) {
788 /* We have a dual DVD with two feature films - now lets see if they have the same amount of chapters*/
789
790 chapters_1 = 0;
791 for (i=0 ; i < titles ; i++ ) {
792 if (titles_info->titles[i].title_set == title_set_size_array[0] ) {
793 if ( chapters_1 < titles_info->titles[i].chapters){
794 chapters_1 = titles_info->titles[i].chapters;
795 }
796 }
797 }
798
799 chapters_2 = 0;
800 for (i=0 ; i < titles ; i++ ) {
801 if (titles_info->titles[i].title_set == title_set_size_array[1] ) {
802 if ( chapters_2 < titles_info->titles[i].chapters){
803 chapters_2 = titles_info->titles[i].chapters;
804 }
805 }
806 }
807
808 if ( vmg_ifo->vts_atrt->vts[title_set_size_array[0] - 1].vtstt_vobs_video_attr.display_aspect_ratio ==
809 vmg_ifo->vts_atrt->vts[title_set_size_array[1] - 1].vtstt_vobs_video_attr.display_aspect_ratio) {
810 /* In this case it's most likely so that we have a dual film but with different context
811 They are with in the same size range and have the same aspect ratio
812 I would guess that such a case is e.g. a DVD containing several episodes of a TV serie*/
813 candidate = title_set_size_array[0];
814 multi = 1;
815 } else if ( chapters_1 == chapters_2 && vmg_ifo->vts_atrt->vts[title_set_size_array[0] - 1].vtstt_vobs_video_attr.display_aspect_ratio !=
816 vmg_ifo->vts_atrt->vts[title_set_size_array[1] - 1].vtstt_vobs_video_attr.display_aspect_ratio){
817 /* In this case we have (guess only) the same context - they have the same number of chapters but different aspect ratio and are in the same size range*/
818 if ( vmg_ifo->vts_atrt->vts[title_set_size_array[0] - 1].vtstt_vobs_video_attr.display_aspect_ratio == aspect) {
819 candidate = title_set_size_array[0];
820 } else if ( vmg_ifo->vts_atrt->vts[title_set_size_array[1] - 1].vtstt_vobs_video_attr.display_aspect_ratio == aspect) {
821 candidate = title_set_size_array[1];
822 } else {
823 /* Okay we didn't have the prefered aspect ratio - just make the biggest one a candidate */
824 /* please send report if this happens*/
825 fprintf(stderr, "You have encountered a very special DVD, please send a bug report along with all IFO files from this title\n");
826 candidate = title_set_size_array[0];
827 }
828 dual = 1;
829 }
830 } else {
831 candidate = title_set_size_array[0];
832 }
833
834
835 /* Lets start checking audio,sub pictures and channels my guess is namly that a special suburb will put titles with a lot of
836 chapters just to make our backup hard */
837
838
839 found = CheckAudioSubChannels(audio_audio_array, title_set_audio_array,
840 subpicture_sub_array, title_set_sub_array,
841 channels_channel_array, title_set_channel_array,
842 0 , candidate, title_sets);
843
844
845 /* Now lets see if we can find our candidate among the top most chapters */
846 found_chapter=6;
847 temp = chapter_chapter_array[0];
848 for (i=0 ; (i < titles) && (i < 4) ; i++ ) {
849 if ( candidate == title_set_chapter_array[i] ) {
850 found_chapter=i+1;
851 break;
852 }
853 }
854
855
856 if (((found == 3) && (found_chapter == 1) && (dual == 0) && (multi == 0)) || ((found == 3) && (found_chapter < 3 ) && (dual == 1))) {
857
858 FreeSortArrays( chapter_chapter_array, title_set_chapter_array,
859 angle_angle_array, title_set_angle_array,
860 subpicture_sub_array, title_set_sub_array,
861 audio_audio_array, title_set_audio_array,
862 size_size_array, title_set_size_array,
863 channels_channel_array, title_set_channel_array);
864 titles_info->main_title_set = candidate;
865 return(titles_info);
866
867 }
868
869 if (multi == 1) {
870 for (i=0 ; i < title_sets ; ++i) {
871 if (CheckSizeArray(size_size_array, 0, i + 1) == 0) {
872 break;
873 }
874 }
875 number_of_multi = i;
876 for (i = 0; i < number_of_multi; i++ ) {
877 if (title_set_chapter_array[0] == i + 1) {
878 candidate = title_set_chapter_array[0];
879 }
880 }
881
882 found = CheckAudioSubChannels(audio_audio_array, title_set_audio_array,
883 subpicture_sub_array, title_set_sub_array,
884 channels_channel_array, title_set_channel_array,
885 0 , candidate, title_sets);
886
887 if (found == 3) {
888 FreeSortArrays( chapter_chapter_array, title_set_chapter_array,
889 angle_angle_array, title_set_angle_array,
890 subpicture_sub_array, title_set_sub_array,
891 audio_audio_array, title_set_audio_array,
892 size_size_array, title_set_size_array,
893 channels_channel_array, title_set_channel_array);
894 titles_info->main_title_set = candidate;
895 return(titles_info);
896 }
897 }
898
899 /* We have now come to that state that we more or less have given up :( giving you a good guess of the main feature film*/
900 /*No matter what we will more or less only return the biggest VOB*/
901 /* Lets see if we can find our biggest one - then we return that one */
902 candidate = title_set_size_array[0];
903
904 found = CheckAudioSubChannels(audio_audio_array, title_set_audio_array,
905 subpicture_sub_array, title_set_sub_array,
906 channels_channel_array, title_set_channel_array,
907 0 , candidate, title_sets);
908
909 /* Now lets see if we can find our candidate among the top most chapters */
910
911 found_chapter=5;
912 temp = chapter_chapter_array[0];
913 for (i=0 ; (i < titles) && (i < 4) ; i++ ) {
914 if ( candidate == title_set_chapter_array[i] ) {
915 found_chapter=i+1;
916 break;
917 }
918
919 }
920
921 /* Here we take chapters in to consideration*/
922 if (found == 3) {
923 FreeSortArrays( chapter_chapter_array, title_set_chapter_array,
924 angle_angle_array, title_set_angle_array,
925 subpicture_sub_array, title_set_sub_array,
926 audio_audio_array, title_set_audio_array,
927 size_size_array, title_set_size_array,
928 channels_channel_array, title_set_channel_array);
929 titles_info->main_title_set = candidate;
930 return(titles_info);
931 }
932
933 /* Here we do but we lower the treshold for audio, sub and channels */
934
935 if ((found > 1 ) && (found_chapter <= 4)) {
936 FreeSortArrays( chapter_chapter_array, title_set_chapter_array,
937 angle_angle_array, title_set_angle_array,
938 subpicture_sub_array, title_set_sub_array,
939 audio_audio_array, title_set_audio_array,
940 size_size_array, title_set_size_array,
941 channels_channel_array, title_set_channel_array);
942 titles_info->main_title_set = candidate;
943 return(titles_info);
944
945 /* return it */
946 } else {
947 /* Here we give up and just return the biggest one :(*/
948 /* Just return the biggest badest one*/
949 FreeSortArrays( chapter_chapter_array, title_set_chapter_array,
950 angle_angle_array, title_set_angle_array,
951 subpicture_sub_array, title_set_sub_array,
952 audio_audio_array, title_set_audio_array,
953 size_size_array, title_set_size_array,
954 channels_channel_array, title_set_channel_array);
955 titles_info->main_title_set = candidate;
956 return(titles_info);
957 }
958
959
960 /* Some radom thoughts about DVD guessing */
961 /* We will now gather as much data about the DVD-Video as we can and
962 then make a educated guess which one is the main feature film of it*/
963
964
965 /* Make a tripple array with chapters, angles and title sets
966 - sort out dual title sets with a low number of chapters. Tradtionaly
967 the title set with most chapters is the main film. Number of angles is
968 keept as a reference point of low value*/
969
970 /* Make a dual array with number of audio streams, sub picture streams
971 and title sets. Tradtionaly the main film has many audio streams
972 since it's supposed be synconised e.g. a English film syncronised/dubbed
973 in German. We are also keeping track of sub titles since it's also indication
974 of the main film*/
975
976 /* Which title set is the biggest one - dual array with title sets and size
977 The biggest one is usally the main film*/
978
979 /* Which title set is belonging to title 1 and how many chapters has it. Once
980 again tradtionaly title one is belonging to the main film*/
981
982 /* Yes a lot of rant - but it helps me think - some sketch on paper or in the mind
983 I sketch in the comments - beside it will help you understand the code*/
984
985 /* Okay lets see if the biggest one has most chapters, it also has more subtitles
986 and audio tracks than the second one and it's title one.
987 Done it must be the main film
988
989 Hmm the biggest one doesn't have the most chapters?
990
991 See if the second one has the same amount of chapters and is the biggest one
992 If so we probably have a 4:3 and 16:9 versions of film on the same disk
993
994 Now we fetch the 16:9 by default unless the forced to do 4:3
995 First check which one is which.
996 If the 16:9 is the biggest one and has the same or more subtile, audio streams
997 then we are happy unless we are in force 4:3 mode :(
998 The same goes in reverse if we are in force 4:3 mode
999
1000
1001 Hmm, in force 4:3 mode - now we check how much smaller than the biggest one it is
1002 (or the reverse if we are in 16:9 mode)
1003
1004 Generally a reverse division should render in 1 and with a small modulo - like wise
1005 a normal modulo should give us a high modulo
1006
1007 If we get more than one it's of cource a fake however if we get just one we still need to check
1008 if we subtract the smaller one from the bigger one we should end up with a small number - hence we
1009 need to multiply it more than 4 times to get it bigger than the biggest one. Now we know that the
1010 two biggest once are really big and possibly carry the same film in differnet formats.
1011
1012 We will now return the prefered one either 16:9 or 4:3 but we will first check that the one
1013 we return at lest has two or more audio tracks. We don't want it if the other one has a lot
1014 more sound (we may end up with a film that only has 2ch Dolby Digital so we want to check for
1015 6ch DTS or Dolby Digital. If the prefered one doesn't have those features but the other once has
1016 we will return the other one.
1017 */
1018
1019}
1020
1021
1022
1023
1024int DVDCopyTileVobX(dvd_reader_t * dvd, title_set_info_t * title_set_info, int title_set, int vob, char * targetdir,char * title_name) {
1025
1026 /* Loop variable */
1027 int i;
1028
1029 /* Temp filename,dirname */
1030 char targetname[PATH_MAX];
1031 struct stat fileinfo;
1032
1033 /* Write buffer */
1034
1035 unsigned char * buffer=NULL;
1036 unsigned char buffy; /* :-) */
1037
1038 /* File Handler */
1039 int streamout;
1040
1041 int size;
1042 int left;
1043
1044 /* Buffer size in DVD sectors */
1045 /* Currently set to 1MB */
1046 int buff = 512;
1047 int offset = 0;
1048 int tsize;
1049
1050 /* DVD handler */
1051 dvd_file_t * dvd_file=NULL;
1052
1053 if (title_set_info->number_of_title_sets + 1 < title_set) {
1054 fprintf(stderr,"Faild num title test\n");
1055 return(1);
1056 }
1057
1058 if (title_set_info->title_set[title_set].number_of_vob_files < vob ) {
1059 fprintf(stderr,"Faild vob test\n");
1060 return(1);
1061 }
1062
1063 if (title_set_info->title_set[title_set].size_vob[0] == 0 ) {
1064 fprintf(stderr,"Faild vob 1 size test\n");
1065 return(0);
1066 } else if (title_set_info->title_set[title_set].size_vob[vob - 1] == 0 ) {
1067 fprintf(stderr,"Faild vob %d test\n", vob);
1068 return(0);
1069 } else {
1070 size = title_set_info->title_set[title_set].size_vob[vob - 1]/2048;
1071 if (title_set_info->title_set[title_set].size_vob[vob - 1]%2048 != 0) {
1072 fprintf(stderr, "The Title VOB number %d of title set %d doesn't have a valid DVD size\n", vob, title_set);
1073 return(1);
1074 }
1075 }
1076#ifdef DEBUG
1077 fprintf(stderr,"After we check the vob it self %d\n", vob);
1078#endif
1079
1080 /* Create VTS_XX_X.VOB */
1081 if (title_set == 0) {
1082 fprintf(stderr,"Don't try to copy a Title VOB from the VMG domain there aren't any\n");
1083 return(1);
1084 } else {
1085 sprintf(targetname,"%s/%s/VIDEO_TS/VTS_%02i_%i.VOB",targetdir, title_name, title_set, vob);
1086 }
1087
1088
1089
1090 /* Now figure out the offset we will start at also check that the previus files are of valid DVD size */
1091 for ( i = 0; i < vob - 1; i++ ) {
1092 tsize = title_set_info->title_set[title_set].size_vob[i];
1093 if (tsize%2048 != 0) {
1094 fprintf(stderr, "The Title VOB number %d of title set %d doesn't have a valid DVD size\n", i + 1, title_set);
1095 return(1);
1096 } else {
1097 offset = offset + tsize/2048;
1098 }
1099 }
1100#ifdef DEBUG
1101 fprintf(stderr,"The offset for vob %d is %d\n", vob, offset);
1102#endif
1103
1104
1105 if (stat(targetname, &fileinfo) == 0) {
1106 fprintf(stderr, "The Title file %s exists will try to over write it.\n", targetname);
1107 if (! S_ISREG(fileinfo.st_mode)) {
1108 fprintf(stderr,"The Title %s file is not valid, it may be a directory\n", targetname);
1109 return(1);
1110 } else {
1111 if ((streamout = open(targetname, O_WRONLY | O_TRUNC, 0644)) == -1) {
1112 fprintf(stderr, "Error opening %s\n", targetname);
1113 perror("");
1114 return(1);
1115 }
1116 }
1117 } else {
1118 if ((streamout = open(targetname, O_WRONLY | O_CREAT, 0644)) == -1) {
1119 fprintf(stderr, "Error creating %s\n", targetname);
1120 perror("");
1121 return(1);
1122 }
1123 }
1124
1125 left = size;
1126
1127 if ((buffer = (unsigned char *)malloc(buff * 2048 * sizeof(buffy))) == NULL) {
1128 fprintf(stderr, "Out of memory coping %s\n", targetname);
1129 close(streamout);
1130 return(1);
1131 }
1132
1133
1134 if ((dvd_file = DVDOpenFile(dvd, title_set, DVD_READ_TITLE_VOBS))== 0) {
1135 fprintf(stderr, "Faild opending TITLE VOB\n");
1136 free(buffer);
1137 close(streamout);
1138 return(1);
1139 }
1140
1141 while( left > 0 ) {
1142
1143 if (buff > left) {
1144 buff = left;
1145 }
1146 if ( DVDReadBlocks(dvd_file,offset,buff, buffer) != buff) {
1147 fprintf(stderr, "Error reading MENU VOB\n");
1148 free(buffer);
1149 DVDCloseFile(dvd_file);
1150 close(streamout);
1151 return(1);
1152 }
1153
1154
1155 if (write(streamout,buffer,buff * 2048) != buff * 2048) {
1156 fprintf(stderr, "Error writing TITLE VOB\n");
1157 free(buffer);
1158 close(streamout);
1159 return(1);
1160 }
1161
1162 offset = offset + buff;
1163 left = left - buff;
1164
1165 }
1166
1167 DVDCloseFile(dvd_file);
1168 free(buffer);
1169 close(streamout);
1170 return(0);
1171
1172}
1173
1174
1175
1176
1177int DVDCopyMenu(dvd_reader_t * dvd, title_set_info_t * title_set_info, int title_set, char * targetdir,char * title_name) {
1178
1179 /* Temp filename,dirname */
1180 char targetname[PATH_MAX];
1181 struct stat fileinfo;
1182
1183 /* Write buffer */
1184
1185 unsigned char * buffer=NULL;
1186 unsigned char buffy; /* :-) */
1187
1188 /* File Handler */
1189 int streamout;
1190
1191 int size;
1192 int left;
1193
1194 /* Buffer size in DVD sectors */
1195 /* Currently set to 1MB */
1196 int buff = 512;
1197 int offset = 0;
1198
1199
1200 /* DVD handler */
1201 dvd_file_t * dvd_file=NULL;
1202
1203 if (title_set_info->number_of_title_sets + 1 < title_set) {
1204 return(1);
1205 }
1206
1207 if (title_set_info->title_set[title_set].size_menu == 0 ) {
1208 return(0);
1209 } else {
1210 size = title_set_info->title_set[title_set].size_menu/2048;
1211 if (title_set_info->title_set[title_set].size_menu%2048 != 0) {
1212 fprintf(stderr, "The Menu VOB of title set %d doesn't have a valid DVD size\n", title_set);
1213 return(1);
1214 }
1215 }
1216
1217 /* Create VIDEO_TS.VOB or VTS_XX_0.VOB */
1218 if (title_set == 0) {
1219 sprintf(targetname,"%s/%s/VIDEO_TS/VIDEO_TS.VOB",targetdir, title_name);
1220 } else {
1221 sprintf(targetname,"%s/%s/VIDEO_TS/VTS_%02i_0.VOB",targetdir, title_name, title_set);
1222 }
1223
1224
1225 if (stat(targetname, &fileinfo) == 0) {
1226 fprintf(stderr, "The Menu file %s exists will try to over write it.\n", targetname);
1227 if (! S_ISREG(fileinfo.st_mode)) {
1228 fprintf(stderr,"The Menu %s file is not valid, it may be a directory\n", targetname);
1229 return(1);
1230 } else {
1231 if ((streamout = open(targetname, O_WRONLY | O_TRUNC, 0644)) == -1) {
1232 fprintf(stderr, "Error opening %s\n", targetname);
1233 perror("");
1234 return(1);
1235 }
1236 }
1237 } else {
1238 if ((streamout = open(targetname, O_WRONLY | O_CREAT, 0644)) == -1) {
1239 fprintf(stderr, "Error creating %s\n", targetname);
1240 perror("");
1241 return(1);
1242 }
1243 }
1244
1245 left = size;
1246
1247 if ((buffer = (unsigned char *)malloc(buff * 2048 * sizeof(buffy))) == NULL) {
1248 fprintf(stderr, "Out of memory coping %s\n", targetname);
1249 close(streamout);
1250 return(1);
1251 }
1252
1253
1254 if ((dvd_file = DVDOpenFile(dvd, title_set, DVD_READ_MENU_VOBS))== 0) {
1255 fprintf(stderr, "Faild opending MENU VOB\n");
1256 free(buffer);
1257 close(streamout);
1258 return(1);
1259 }
1260
1261 while( left > 0 ) {
1262
1263 if (buff > left) {
1264 buff = left;
1265 }
1266 if ( DVDReadBlocks(dvd_file,offset,buff, buffer) != buff) {
1267 fprintf(stderr, "Error reading MENU VOB\n");
1268 free(buffer);
1269 DVDCloseFile(dvd_file);
1270 close(streamout);
1271 return(1);
1272 }
1273
1274
1275 if (write(streamout,buffer,buff * 2048) != buff * 2048) {
1276 fprintf(stderr, "Error writing MENU VOB\n");
1277 free(buffer);
1278 close(streamout);
1279 return(1);
1280 }
1281
1282 offset = offset + buff;
1283 left = left - buff;
1284
1285 }
1286
1287 DVDCloseFile(dvd_file);
1288 free(buffer);
1289 close(streamout);
1290 return(0);
1291
1292}
1293
1294
1295int DVDCopyIfoBup (dvd_reader_t * dvd, title_set_info_t * title_set_info, int title_set, char * targetdir,char * title_name) {
1296
1297 /* Temp filename,dirname */
1298 char targetname[PATH_MAX];
1299 struct stat fileinfo;
1300
1301 /* Write buffer */
1302
1303 unsigned char * buffer=NULL;
1304 unsigned char buffy; /* :-) */
1305
1306 /* File Handler */
1307 int streamout;
1308
1309 int size;
1310
1311 /* DVD handler */
1312 dvd_file_t * dvd_file=NULL;
1313
1314
1315 if (title_set_info->number_of_title_sets + 1 < title_set) {
1316 return(1);
1317 }
1318
1319 if (title_set_info->title_set[title_set].size_ifo == 0 ) {
1320 return(0);
1321 } else {
1322 size = title_set_info->title_set[title_set].size_ifo;
1323 if (title_set_info->title_set[title_set].size_ifo%2048 != 0) {
1324 fprintf(stderr, "The IFO of title set %d doesn't have a valid DVD size\n", title_set);
1325 return(1);
1326 }
1327 }
1328
1329 /* Create VIDEO_TS.IFO or VTS_XX_0.IFO */
1330
1331 if (title_set == 0) {
1332 sprintf(targetname,"%s/%s/VIDEO_TS/VIDEO_TS.IFO",targetdir, title_name);
1333 } else {
1334 sprintf(targetname,"%s/%s/VIDEO_TS/VTS_%02i_0.IFO",targetdir, title_name, title_set);
1335 }
1336
1337 if (stat(targetname, &fileinfo) == 0) {
1338 fprintf(stderr, "The IFO file %s exists will try to over write it.\n", targetname);
1339 if (! S_ISREG(fileinfo.st_mode)) {
1340 fprintf(stderr,"The IFO %s file is not valid, it may be a directory\n", targetname);
1341 return(1);
1342 } else {
1343 if ((streamout = open(targetname, O_WRONLY | O_TRUNC, 0644)) == -1) {
1344 fprintf(stderr, "Error opening %s\n", targetname);
1345 perror("");
1346 return(1);
1347 }
1348 }
1349 } else {
1350 if ((streamout = open(targetname, O_WRONLY | O_CREAT, 0644)) == -1) {
1351 fprintf(stderr, "Error creating %s\n", targetname);
1352 perror("");
1353 return(1);
1354 }
1355 }
1356
1357 /* Copy VIDEO_TS.IFO, since it's a small file try to copy it in one shot */
1358
1359
1360 if ((buffer = (unsigned char *)malloc(size * sizeof(buffy))) == NULL) {
1361 fprintf(stderr, "Out of memory coping %s\n", targetname);
1362 close(streamout);
1363 return(1);
1364 }
1365
1366
1367 if ((dvd_file = DVDOpenFile(dvd, title_set, DVD_READ_INFO_FILE))== 0) {
1368 fprintf(stderr, "Faild opending IFO for tile set %d\n", title_set);
1369 free(buffer);
1370 close(streamout);
1371 return(1);
1372 }
1373
1374 if ( DVDReadBytes(dvd_file,buffer,size) != size) {
1375 fprintf(stderr, "Error reading IFO for title set %d\n", title_set);
1376 free(buffer);
1377 DVDCloseFile(dvd_file);
1378 close(streamout);
1379 return(1);
1380 }
1381
1382 DVDCloseFile(dvd_file);
1383
1384 if (write(streamout,buffer,size) != size) {
1385 fprintf(stderr, "Error writing %s\n",targetname);
1386 free(buffer);
1387 close(streamout);
1388 return(1);
1389 }
1390
1391 free(buffer);
1392 close(streamout);
1393
1394
1395 /* Create VIDEO_TS.BUP or VTS_XX_0.BUP */
1396
1397 if (title_set == 0) {
1398 sprintf(targetname,"%s/%s/VIDEO_TS/VIDEO_TS.BUP",targetdir, title_name);
1399 } else {
1400 sprintf(targetname,"%s/%s/VIDEO_TS/VTS_%02i_0.BUP",targetdir, title_name, title_set);
1401 }
1402
1403
1404 if (title_set_info->title_set[title_set].size_bup == 0 ) {
1405 return(0);
1406 } else {
1407 size = title_set_info->title_set[title_set].size_bup;
1408 if (title_set_info->title_set[title_set].size_bup%2048 != 0) {
1409 fprintf(stderr, "The BUP of title set %d doesn't have a valid DVD size\n", title_set);
1410 return(1);
1411 }
1412 }
1413
1414
1415 if (stat(targetname, &fileinfo) == 0) {
1416 fprintf(stderr, "The BUP file %s exists will try to over write it.\n", targetname);
1417 if (! S_ISREG(fileinfo.st_mode)) {
1418 fprintf(stderr,"The BUP %s file is not valid, it may be a directory\n", targetname);
1419 return(1);
1420 } else {
1421 if ((streamout = open(targetname, O_WRONLY | O_TRUNC, 0644)) == -1) {
1422 fprintf(stderr, "Error opening %s\n", targetname);
1423 perror("");
1424 return(1);
1425 }
1426 }
1427 } else {
1428 if ((streamout = open(targetname, O_WRONLY | O_CREAT, 0644)) == -1) {
1429 fprintf(stderr, "Error creating %s\n", targetname);
1430 perror("");
1431 return(1);
1432 }
1433 }
1434
1435
1436
1437 /* Copy VIDEO_TS.BUP or VTS_XX_0.BUP, since it's a small file try to copy it in one shot */
1438
1439 if ((buffer = (unsigned char *)malloc(size * sizeof(buffy))) == NULL) {
1440 fprintf(stderr, "Out of memory coping %s\n", targetname);
1441 close(streamout);
1442 return(1);
1443 }
1444
1445
1446 if ((dvd_file = DVDOpenFile(dvd, title_set, DVD_READ_INFO_BACKUP_FILE))== 0) {
1447 fprintf(stderr, "Faild opending BUP for title set %d\n", title_set);
1448 free(buffer);
1449 close(streamout);
1450 return(1);
1451 }
1452
1453 if ( DVDReadBytes(dvd_file,buffer,size) != size) {
1454 fprintf(stderr, "Error reading BUP for title set %d\n", title_set);
1455 free(buffer);
1456 DVDCloseFile(dvd_file);
1457 close(streamout);
1458 return(1);
1459 }
1460
1461 DVDCloseFile(dvd_file);
1462
1463 if (write(streamout,buffer,size) != size) {
1464 fprintf(stderr, "Error writing %s\n", targetname);
1465 free(buffer);
1466 close(streamout);
1467 return(1);
1468 }
1469
1470 free(buffer);
1471 close(streamout);
1472
1473 return(0);
1474}
1475
1476
1477int DVDMirrorVMG(dvd_reader_t * dvd, title_set_info_t * title_set_info,char * targetdir,char * title_name){
1478
1479 if ( DVDCopyIfoBup(dvd, title_set_info, 0, targetdir, title_name) != 0 ) {
1480 return(1);
1481 }
1482
1483 if ( DVDCopyMenu(dvd, title_set_info, 0, targetdir, title_name) != 0 ) {
1484 return(1);
1485 }
1486 return(0);
1487}
1488
1489int DVDMirrorTitleX(dvd_reader_t * dvd, title_set_info_t * title_set_info, int title_set, char * targetdir,char * title_name) {
1490
1491 /* Loop through the vobs */
1492 int i;
1493
1494
1495
1496 if ( DVDCopyIfoBup(dvd, title_set_info, title_set, targetdir, title_name) != 0 ) {
1497 return(1);
1498 }
1499
1500 if ( DVDCopyMenu(dvd, title_set_info, title_set, targetdir, title_name) != 0 ) {
1501 return(1);
1502 }
1503
1504 for (i = 0; i < title_set_info->title_set[title_set].number_of_vob_files ; i++) {
1505#ifdef DEBUG
1506 fprintf(stderr,"In the VOB copy loop for %d\n", i);
1507#endif
1508 if ( DVDCopyTileVobX(dvd, title_set_info, title_set, i + 1, targetdir, title_name) != 0 ) {
1509 return(1);
1510 }
1511 }
1512
1513
1514 return(0);
1515}
1516
1517int DVDGetTitleName(const char *device, char *title)
1518{
1519 /* Variables for filehandel and title string interaction */
1520
1521 int filehandle, i, last;
1522
1523 /* Open DVD device */
1524
1525 if ( !(filehandle = open(device, O_RDONLY)) ) {
1526 fprintf(stderr, "Can't open secified device %s - check your DVD device\n", device);
1527 return(1);
1528 }
1529
1530 /* Seek to title of first track, which is at (track_no * 32768) + 40 */
1531
1532 if ( 32808 != lseek(filehandle, 32808, SEEK_SET) ) {
1533 close(filehandle);
1534 fprintf(stderr, "Can't seek DVD device %s - check your DVD device\n", device);
1535 return(1);
1536 }
1537
1538 /* Read the DVD-Video title */
1539
1540 if ( 32 != read(filehandle, title, 32)) {
1541 close(filehandle);
1542 fprintf(stderr, "Can't read title from DVD device %s\n", device);
1543 return(1);
1544 }
1545
1546 /* Terminate the title string */
1547
1548 title[32] = '\0';
1549
1550
1551 /* Remove trailing white space */
1552
1553 last = 32;
1554 for ( i = 0; i < 32; i++ ) {
1555 if ( title[i] != ' ' ) { last = i; }
1556 }
1557
1558 title[last + 1] = '\0';
1559
1560 return(0);
1561}
1562
1563
1564
1565void bsort_min_to_max(int sector[], int title[], int size){
1566
1567 int temp_title, temp_sector, i, j;
1568
1569 for ( i=0; i < size ; i++ ) {
1570 for ( j=0; j < size ; j++ ) {
1571 if (sector[i] < sector[j]) {
1572 temp_sector = sector[i];
1573 temp_title = title[i];
1574 sector[i] = sector[j];
1575 title[i] = title[j];
1576 sector[j] = temp_sector;
1577 title[j] = temp_title;
1578 }
1579 }
1580 }
1581}
1582
1583void bsort_max_to_min(int sector[], int title[], int size){
1584
1585 int temp_title, temp_sector, i, j;
1586
1587 for ( i=0; i < size ; i++ ) {
1588 for ( j=0; j < size ; j++ ) {
1589 if (sector[i] > sector[j]) {
1590 temp_sector = sector[i];
1591 temp_title = title[i];
1592 sector[i] = sector[j];
1593 title[i] = title[j];
1594 sector[j] = temp_sector;
1595 title[j] = temp_title;
1596 }
1597 }
1598 }
1599}
1600
1601
1602
1603void uniq(int sector[], int title[], int title_sets_array[], int sector_sets_array[], int titles){
1604 int i, j;
1605
1606
1607 for ( i=0, j=0; j < titles;) {
1608 if (sector[j] != sector[j+1]) {
1609 title_sets_array[i] = title[j];
1610 sector_sets_array[i] = sector[j];
1611 i++ ;
1612 j++ ;
1613 } else {
1614 do {
1615 if (j < titles) {
1616 j++ ;
1617 }
1618 } while ( sector[j] == sector[j+1] );
1619
1620 }
1621 }
1622
1623}
1624
1625void align_end_sector(int cell_start_sector[],int cell_end_sector[], int size) {
1626
1627 int i;
1628
1629 for (i = 0; i < size - 1 ; i++) {
1630 if ( cell_end_sector[i] >= cell_start_sector[i + 1] ) {
1631 cell_end_sector[i] = cell_start_sector[i + 1] - 1;
1632 }
1633 }
1634}
1635
1636
1637
1638
1639void DVDFreeTitleSetInfo(title_set_info_t * title_set_info) {
1640 free(title_set_info->title_set);
1641 free(title_set_info);
1642}
1643
1644void DVDFreeTitlesInfo(titles_info_t * titles_info) {
1645 free(titles_info->titles);
1646 free(titles_info);
1647}
1648
1649
1650
1651title_set_info_t *DVDGetFileSet(dvd_reader_t * _dvd) {
1652
1653 /* title interation */
1654 int title_sets, counter, i;
1655
1656
1657 /* DVD Video files */
1658 char filename[MAXNAME];
1659 int size;
1660
1661 /*DVD ifo handler*/
1662 ifo_handle_t * vmg_ifo=NULL;
1663
1664 /* The Title Set Info struct*/
1665 title_set_info_t * title_set_info;
1666
1667 /* Open main info file */
1668 vmg_ifo = ifoOpen( _dvd, 0 );
1669 if( !vmg_ifo ) {
1670 fprintf( stderr, "Can't open VMG info.\n" );
1671 return (0);
1672 }
1673
1674
1675 title_sets = vmg_ifo->vmgi_mat->vmg_nr_of_title_sets;
1676
1677 /* Close the VMG ifo file we got all the info we need */
1678 ifoClose(vmg_ifo);
1679
1680 /* Todo fix malloc check */
1681 title_set_info = (title_set_info_t *)malloc(sizeof(title_set_info_t));
1682 title_set_info->title_set = (title_set_t *)malloc((title_sets + 1)* sizeof(title_set_t));
1683
1684 title_set_info->number_of_title_sets = title_sets;
1685
1686
1687 /* Find VIDEO_TS.IFO is present - must be present since we did a ifo open 0*/
1688
1689 sprintf(filename,"/VIDEO_TS/VIDEO_TS.IFO");
1690
1691 if ( UDFFindFile(_dvd, filename, &size) != 0 ) {
1692 title_set_info->title_set[0].size_ifo = size;
1693 } else {
1694 DVDFreeTitleSetInfo(title_set_info);
1695 return(0);
1696 }
1697
1698
1699
1700 /* Find VIDEO_TS.VOB if present*/
1701
1702 sprintf(filename,"/VIDEO_TS/VIDEO_TS.VOB");
1703
1704 if ( UDFFindFile(_dvd, filename, &size) != 0 ) {
1705 title_set_info->title_set[0].size_menu = size;
1706 } else {
1707 title_set_info->title_set[0].size_menu = 0 ;
1708 }
1709
1710 /* Find VIDEO_TS.BUP if present */
1711
1712 sprintf(filename,"/VIDEO_TS/VIDEO_TS.BUP");
1713
1714 if ( UDFFindFile(_dvd, filename, &size) != 0 ) {
1715 title_set_info->title_set[0].size_bup = size;
1716 } else {
1717 DVDFreeTitleSetInfo(title_set_info);
1718 return(0);
1719 }
1720
1721 if (title_set_info->title_set[0].size_ifo != title_set_info->title_set[0].size_bup) {
1722 fprintf(stderr,"BUP and IFO size not the same be warened!\n");
1723 }
1724
1725
1726 /* Take care of the titles which we don't have in VMG */
1727
1728 title_set_info->title_set[0].number_of_vob_files = 0;
1729 title_set_info->title_set[0].size_vob[0] = 0;
1730
1731
1732 if ( verbose > 0 ){
1733 fprintf(stderr,"\n\n\nFile sizes for Title set 0 VIDEO_TS.XXX\n");
1734 fprintf(stderr,"IFO = %d, MENU_VOB = %d, BUP = %d\n",title_set_info->title_set[0].size_ifo, title_set_info->title_set[0].size_menu, title_set_info->title_set[0].size_bup );
1735
1736 }
1737
1738
1739 if ( title_sets >= 1 ) {
1740 for (counter=0; counter < title_sets; counter++ ){
1741
1742 if ( verbose > 1 ){
1743 fprintf(stderr,"At top of loop\n");
1744 }
1745
1746
1747 sprintf(filename,"/VIDEO_TS/VTS_%02i_0.IFO",counter + 1);
1748
1749 if ( UDFFindFile(_dvd, filename, &size) != 0 ) {
1750 title_set_info->title_set[counter + 1].size_ifo = size;
1751 } else {
1752 DVDFreeTitleSetInfo(title_set_info);
1753 return(0);
1754 }
1755
1756 if ( verbose > 1 ){
1757 fprintf(stderr,"After opening files\n");
1758 }
1759
1760
1761 /* Find VTS_XX_0.VOB if present*/
1762
1763 sprintf(filename,"/VIDEO_TS/VTS_%02i_0.VOB", counter + 1);
1764
1765 if ( UDFFindFile(_dvd, filename, &size) != 0 ) {
1766 title_set_info->title_set[counter + 1].size_menu = size;
1767 } else {
1768 title_set_info->title_set[counter + 1].size_menu = 0 ;
1769 }
1770
1771
1772 if ( verbose > 1 ){
1773 fprintf(stderr,"After Menu VOB check\n");
1774 }
1775
1776
1777 /* Find all VTS_XX_[1 to 9].VOB files if they are present*/
1778
1779 for( i = 0; i < 9; ++i ) {
1780 sprintf(filename,"/VIDEO_TS/VTS_%02i_%i.VOB", counter + 1, i + 1 );
1781 if(UDFFindFile(_dvd, filename, &size) == 0 ) {
1782 break;
1783 }
1784 title_set_info->title_set[counter + 1].size_vob[i] = size;
1785 }
1786 title_set_info->title_set[counter + 1].number_of_vob_files = i;
1787
1788 if ( verbose > 1 ){
1789 fprintf(stderr,"After Menu Title VOB check\n");
1790 }
1791
1792
1793 sprintf(filename,"/VIDEO_TS/VTS_%02i_0.BUP", counter + 1);
1794
1795 if ( UDFFindFile(_dvd, filename, &size) != 0 ) {
1796 title_set_info->title_set[counter +1].size_bup = size;
1797 } else {
1798 DVDFreeTitleSetInfo(title_set_info);
1799 return(0);
1800 }
1801
1802 if (title_set_info->title_set[counter +1].size_ifo != title_set_info->title_set[counter + 1].size_bup) {
1803 fprintf(stderr,"BUP and IFO size for fileset %d is not the same be warened!\n", counter + 1);
1804 }
1805
1806
1807
1808 if ( verbose > 1 ){
1809 fprintf(stderr,"After Menu Title BUP check\n");
1810 }
1811
1812
1813 if ( verbose > 0 ) {
1814 fprintf(stderr,"\n\n\nFile sizes for Title set %d i.e.VTS_%02d_X.XXX\n", counter + 1, counter + 1);
1815 fprintf(stderr,"IFO: %d, MENU: %d\n", title_set_info->title_set[counter +1].size_ifo, title_set_info->title_set[counter +1].size_menu);
1816 for (i = 0; i < title_set_info->title_set[counter + 1].number_of_vob_files ; i++) {
1817 fprintf(stderr, "VOB %d is %d\n", i + 1, title_set_info->title_set[counter + 1].size_vob[i]);
1818 }
1819 fprintf(stderr,"BUP: %d\n",title_set_info->title_set[counter +1].size_bup);
1820 }
1821
1822 if ( verbose > 1 ){
1823 fprintf(stderr,"Bottom of loop \n");
1824 }
1825 }
1826
1827 }
1828
1829 /* Return the info */
1830 return(title_set_info);
1831
1832
1833}
1834
1835int DVDMirror(dvd_reader_t * _dvd, char * targetdir,char * title_name) {
1836
1837 int i;
1838 title_set_info_t * title_set_info=NULL;
1839
1840 title_set_info = DVDGetFileSet(_dvd);
1841 if (!title_set_info) {
1842 DVDClose(_dvd);
1843 return(1);
1844 }
1845
1846 if ( DVDMirrorVMG(_dvd, title_set_info, targetdir, title_name) != 0 ) {
1847 fprintf(stderr,"Mirror of VMG faild\n");
1848 DVDFreeTitleSetInfo(title_set_info);
1849 return(1);
1850 }
1851
1852 for ( i=0; i < title_set_info->number_of_title_sets; i++) {
1853 if ( DVDMirrorTitleX(_dvd, title_set_info, i + 1, targetdir, title_name) != 0 ) {
1854 fprintf(stderr,"Mirror of Title set %d faild\n", i + 1);
1855 DVDFreeTitleSetInfo(title_set_info);
1856 return(1);
1857 }
1858 }
1859 return(0);
1860}
1861
1862int DVDMirrorTitleSet(dvd_reader_t * _dvd, char * targetdir,char * title_name, int title_set) {
1863
1864 title_set_info_t * title_set_info=NULL;
1865
1866
1867#ifdef DEBUG
1868 fprintf(stderr,"In DVDMirrorTitleSet\n");
1869#endif
1870
1871 title_set_info = DVDGetFileSet(_dvd);
1872
1873 if (!title_set_info) {
1874 DVDClose(_dvd);
1875 return(1);
1876 }
1877
1878 if ( title_set > title_set_info->number_of_title_sets ) {
1879 fprintf(stderr, "Can't copy title_set %d there is only %d title_sets present on this DVD\n", title_set, title_set_info->number_of_title_sets);
1880 DVDFreeTitleSetInfo(title_set_info);
1881 return(1);
1882 }
1883
1884 if ( title_set == 0 ) {
1885 if ( DVDMirrorVMG(_dvd, title_set_info, targetdir, title_name) != 0 ) {
1886 fprintf(stderr,"Mirror of Title set 0 (VMG) faild\n");
1887 DVDFreeTitleSetInfo(title_set_info);
1888 return(1);
1889 }
1890 } else {
1891 if ( DVDMirrorTitleX(_dvd, title_set_info, title_set, targetdir, title_name) != 0 ) {
1892 fprintf(stderr,"Mirror of Title set %d faild\n", title_set);
1893 DVDFreeTitleSetInfo(title_set_info);
1894 return(1);
1895 }
1896 }
1897 DVDFreeTitleSetInfo(title_set_info);
1898 return(0);
1899}
1900
1901int DVDMirrorMainFeature(dvd_reader_t * _dvd, char * targetdir,char * title_name) {
1902
1903 title_set_info_t * title_set_info=NULL;
1904 titles_info_t * titles_info=NULL;
1905
1906
1907 titles_info = DVDGetInfo(_dvd);
1908 if (!titles_info) {
1909 fprintf(stderr, "Guess work of main feature film faild\n");
1910 return(1);
1911 }
1912
1913 title_set_info = DVDGetFileSet(_dvd);
1914 if (!title_set_info) {
1915 DVDFreeTitlesInfo(titles_info);
1916 return(1);
1917 }
1918
1919 if ( DVDMirrorTitleX(_dvd, title_set_info, titles_info->main_title_set, targetdir, title_name) != 0 ) {
1920 fprintf(stderr,"Mirror of main featur file which is title set %d faild\n", titles_info->main_title_set);
1921 DVDFreeTitleSetInfo(title_set_info);
1922 return(1);
1923 }
1924
1925 DVDFreeTitlesInfo(titles_info);
1926 DVDFreeTitleSetInfo(title_set_info);
1927 return(0);
1928}
1929
1930
1931int DVDMirrorChapters(dvd_reader_t * _dvd, char * targetdir,char * title_name, int start_chapter,int end_chapter, int titles) {
1932
1933
1934 int result;
1935 int chapters = 0;
1936 int feature;
1937 int i, s;
1938 int spg, epg;
1939 int pgc;
1940 int start_cell, end_cell;
1941 int vts_title;
1942
1943 title_set_info_t * title_set_info=NULL;
1944 titles_info_t * titles_info=NULL;
1945 ifo_handle_t * vts_ifo_info=NULL;
1946 int * cell_start_sector=NULL;
1947 int * cell_end_sector=NULL;
1948
1949 /* To do free memory*/
1950
1951 titles_info = DVDGetInfo(_dvd);
1952 if (!titles_info) {
1953 fprintf(stderr, "Faild to obtain titles information\n");
1954 return(1);
1955 }
1956
1957 title_set_info = DVDGetFileSet(_dvd);
1958 if (!title_set_info) {
1959 DVDFreeTitlesInfo(titles_info);
1960 return(1);
1961 }
1962
1963 if(titles == 0) {
1964 fprintf(stderr, "No title specified for chapter extraction, will try to figure out main feature title\n");
1965 feature = titles_info->main_title_set;
1966 for (i=0; i < titles_info->number_of_titles ; i++ ) {
1967 if ( titles_info->titles[i].title_set == titles_info->main_title_set ) {
1968 if(chapters < titles_info->titles[i].chapters) {
1969 chapters = titles_info->titles[i].chapters;
1970 titles = i + 1;
1971 }
1972 }
1973 }
1974 }
1975
1976 vts_ifo_info = ifoOpen(_dvd, titles_info->titles[titles - 1].title_set);
1977 if(!vts_ifo_info) {
1978 fprintf(stderr, "Coundn't open tile_set %d IFO file\n", titles_info->titles[titles - 1].title_set);
1979 DVDFreeTitlesInfo(titles_info);
1980 DVDFreeTitleSetInfo(title_set_info);
1981 return(1);
1982 }
1983
1984 vts_title = titles_info->titles[titles - 1].vts_title;
1985
1986 if (end_chapter > titles_info->titles[titles - 1].chapters) {
1987 end_chapter = titles_info->titles[titles - 1].chapters;
1988 fprintf(stderr, "Turncated the end_chapter only %d chapters in %d title\n", end_chapter,titles);
1989 }
1990
1991 if (start_chapter > titles_info->titles[titles - 1].chapters) {
1992 start_chapter = titles_info->titles[titles - 1].chapters;
1993 fprintf(stderr, "Turncated the end_chapter only %d chapters in %d title\n", end_chapter,titles);
1994 }
1995
1996
1997
1998 /* We assume the same PGC for the whole title - this is not true and need to be fixed later on */
1999
2000 pgc = vts_ifo_info->vts_ptt_srpt->title[vts_title - 1].ptt[start_chapter - 1].pgcn;
2001
2002
2003 /* Lookup PG for start chapter */
2004
2005 spg = vts_ifo_info->vts_ptt_srpt->title[vts_title - 1].ptt[start_chapter - 1].pgn;
2006
2007 /* Look up start cell for this pgc/pg */
2008
2009 start_cell = vts_ifo_info->vts_pgcit->pgci_srp[pgc - 1].pgc->program_map[spg - 1];
2010
2011
2012 /* Lookup end cell*/
2013
2014
2015 if ( end_chapter < titles_info->titles[titles - 1].chapters ) {
2016 epg = vts_ifo_info->vts_ptt_srpt->title[vts_title - 1].ptt[end_chapter].pgn;
2017#ifdef DEBUG
2018 fprintf(stderr,"DVDMirrorChapter: epg %d\n", epg);
2019#endif
2020
2021 end_cell = vts_ifo_info->vts_pgcit->pgci_srp[pgc - 1].pgc->program_map[epg -1] - 1;
2022#ifdef DEBUG
2023 fprintf(stderr,"DVDMirrorChapter: end cell adjusted %d\n", end_cell);
2024#endif
2025
2026 } else {
2027
2028 end_cell = vts_ifo_info->vts_pgcit->pgci_srp[pgc - 1].pgc->nr_of_cells;
2029#ifdef DEBUG
2030 fprintf(stderr,"DVDMirrorChapter: end cell adjusted 2 %d\n",end_cell);
2031#endif
2032
2033 }
2034
2035#ifdef DEBUG
2036 fprintf(stderr,"DVDMirrorChapter: star cell %d\n", start_cell);
2037#endif
2038
2039
2040 /* Put all the cells start and end sector in a dual array */
2041
2042 cell_start_sector = (int *)malloc( (end_cell - start_cell + 1) * sizeof(int));
2043 if(!cell_start_sector) {
2044 fprintf(stderr,"Memory allocation error 1\n");
2045 DVDFreeTitlesInfo(titles_info);
2046 DVDFreeTitleSetInfo(title_set_info);
2047 ifoClose(vts_ifo_info);
2048 return(1);
2049 }
2050 cell_end_sector = (int *)malloc( (end_cell - start_cell + 1) * sizeof(int));
2051 if(!cell_end_sector) {
2052 fprintf(stderr,"Memory allocation error\n");
2053 DVDFreeTitlesInfo(titles_info);
2054 DVDFreeTitleSetInfo(title_set_info);
2055 ifoClose(vts_ifo_info);
2056 free(cell_start_sector);
2057 return(1);
2058 }
2059#ifdef DEBUG
2060 fprintf(stderr,"DVDMirrorChapter: start cell is %d\n", start_cell);
2061 fprintf(stderr,"DVDMirrorChapter: end cell is %d\n", end_cell);
2062 fprintf(stderr,"DVDMirrorChapter: pgc is %d\n", pgc);
2063#endif
2064
2065 for (i=0, s=start_cell; s < end_cell +1 ; i++, s++) {
2066
2067 cell_start_sector[i] = vts_ifo_info->vts_pgcit->pgci_srp[pgc - 1].pgc->cell_playback[s - 1].first_sector;
2068 cell_end_sector[i] = vts_ifo_info->vts_pgcit->pgci_srp[pgc - 1].pgc->cell_playback[s - 1].last_sector;
2069#ifdef DEBUG
2070 fprintf(stderr,"DVDMirrorChapter: S is %d\n", s);
2071 fprintf(stderr,"DVDMirrorChapter: start sector %d\n", vts_ifo_info->vts_pgcit->pgci_srp[pgc - 1].pgc->cell_playback[s - 1].first_sector);
2072 fprintf(stderr,"DVDMirrorChapter: end sector %d\n", vts_ifo_info->vts_pgcit->pgci_srp[pgc - 1].pgc->cell_playback[s - 1].last_sector);
2073#endif
2074 }
2075
2076 bsort_min_to_max(cell_start_sector, cell_end_sector, end_cell - start_cell + 1);
2077
2078 align_end_sector(cell_start_sector, cell_end_sector,end_cell - start_cell + 1);
2079
2080#ifdef DEBUG
2081 for (i=0 ; i < end_cell - start_cell + 1; i++) {
2082 fprintf(stderr,"DVDMirrorChapter: Start sector is %d end sector is %d\n", cell_start_sector[i], cell_end_sector[i]);
2083 }
2084#endif
2085
2086 result = DVDWriteCells(_dvd, cell_start_sector, cell_end_sector , end_cell - start_cell + 1, titles, title_set_info, titles_info, targetdir, title_name);
2087
2088 DVDFreeTitlesInfo(titles_info);
2089 DVDFreeTitleSetInfo(title_set_info);
2090 ifoClose(vts_ifo_info);
2091 free(cell_start_sector);
2092 free(cell_end_sector);
2093
2094 if( result != 0) {
2095 return(1);
2096 } else {
2097 return(0);
2098 }
2099}
2100
2101
2102
2103
2104
2105
2106int DVDMirrorTitles(dvd_reader_t * _dvd, char * targetdir,char * title_name, int titles) {
2107
2108 int end_chapter;
2109
2110 titles_info_t * titles_info=NULL;
2111
2112#ifdef DEBUG
2113 fprintf(stderr,"In DVDMirrorTitles\n");
2114#endif
2115
2116
2117
2118 titles_info = DVDGetInfo(_dvd);
2119 if (!titles_info) {
2120 fprintf(stderr, "Faild to obtain titles information\n");
2121 return(1);
2122 }
2123
2124
2125 end_chapter = titles_info->titles[titles - 1].chapters;
2126#ifdef DEBUG
2127 fprintf(stderr,"DVDMirrorTitles: end_chapter %d\n", end_chapter);
2128#endif
2129
2130 if (DVDMirrorChapters( _dvd, targetdir, title_name, 1, end_chapter, titles) != 0 ) {
2131 DVDFreeTitlesInfo(titles_info);
2132 return(1);
2133 }
2134
2135 DVDFreeTitlesInfo(titles_info);
2136
2137 return(0);
2138}
2139
2140int DVDDisplayInfo(dvd_reader_t * _dvd, char * dvd) {
2141
2142
2143 int i, f;
2144 int chapters;
2145 int channels;
2146 char title_name[33]="";
2147 title_set_info_t * title_set_info=NULL;
2148 titles_info_t * titles_info=NULL;
2149
2150
2151 titles_info = DVDGetInfo(_dvd);
2152 if (!titles_info) {
2153 fprintf(stderr, "Guess work of main feature film faild\n");
2154 return(1);
2155 }
2156
2157 title_set_info = DVDGetFileSet(_dvd);
2158 if (!title_set_info) {
2159 DVDFreeTitlesInfo(titles_info);
2160 return(1);
2161 }
2162
2163 DVDGetTitleName(dvd,title_name);
2164
2165
2166 fprintf(stdout,"\n\n\nDVD-Video information of the DVD with tile %s\n\n", title_name);
2167
2168 /* Print file structure */
2169
2170 fprintf(stdout,"File Structure DVD\n");
2171 fprintf(stdout,"VIDEO_TS/\n");
2172 fprintf(stdout,"\tVIDEO_TS.IFO\t%i\n", title_set_info->title_set[0].size_ifo);
2173
2174 if (title_set_info->title_set[0].size_menu != 0 ) {
2175 fprintf(stdout,"\tVIDEO_TS.VOB\t%i\n", title_set_info->title_set[0].size_menu);
2176 }
2177
2178 fprintf(stdout,"\tVIDEO_TS.BUP\t%i\n", title_set_info->title_set[0].size_bup);
2179
2180 for( i = 0 ; i < title_set_info->number_of_title_sets ; i++) {
2181 fprintf(stdout,"\tVTS_%02i_0.IFO\t%i\n", i + 1, title_set_info->title_set[i + 1].size_ifo);
2182 if (title_set_info->title_set[i + 1].size_menu != 0 ) {
2183 fprintf(stdout,"\tVTS_%02i_0.VOB\t%i\n", i + 1, title_set_info->title_set[i + 1].size_menu);
2184 }
2185 if (title_set_info->title_set[i + 1].number_of_vob_files != 0) {
2186 for( f = 0; f < title_set_info->title_set[i + 1].number_of_vob_files ; f++ ) {
2187 fprintf(stdout,"\tVTS_%02i_%i.VOB\t%i\n", i + 1, f + 1, title_set_info->title_set[i + 1].size_vob[f]);
2188 }
2189 }
2190 fprintf(stdout,"\tVTS_%02i_0.BUP\t%i\n", i + 1, title_set_info->title_set[i + 1].size_bup);
2191 }
2192
2193 fprintf(stdout,"\n\nMain feature:\n");
2194 fprintf(stdout,"\tTitle set containing the main feature is %d\n", titles_info->main_title_set);
2195 for (i=0; i < titles_info->number_of_titles ; i++ ) {
2196 if (titles_info->titles[i].title_set == titles_info->main_title_set) {
2197 if(titles_info->titles[i].aspect_ratio == 3) {
2198 fprintf(stdout,"\tThe aspect ratio of the main feature is 16:9\n");
2199 } else if (titles_info->titles[i].aspect_ratio == 0) {
2200 fprintf(stdout,"\tThe aspect ratio of the main feature is 4:3\n");
2201 } else {
2202 fprintf(stdout,"\tThe aspect ratio of the main feature is unknown\n");
2203 }
2204 fprintf(stdout,"\tThe main feature has %d angle(s)\n", titles_info->titles[i].angles);
2205 fprintf(stdout,"\tThe main feature has %d audio_track(s)\n", titles_info->titles[i].angles);
2206 fprintf(stdout,"\tThe main feature has %d subpicture channel(s)\n",titles_info->titles[i].sub_pictures);
2207 chapters=0;
2208 channels=0;
2209
2210 for (f=0; f < titles_info->number_of_titles ; f++ ) {
2211 if ( titles_info->titles[i].title_set == titles_info->main_title_set ) {
2212 if(chapters < titles_info->titles[f].chapters) {
2213 chapters = titles_info->titles[f].chapters;
2214 }
2215 if(channels < titles_info->titles[f].audio_channels) {
2216 channels = titles_info->titles[f].audio_channels;
2217 }
2218 }
2219 }
2220 fprintf(stdout,"\tThe main feature has a maximum of %d chapter(s) in on of it's titles\n", chapters);
2221 fprintf(stdout,"\tThe main feature has a maximum of %d audio channel(s) in on of it's titles\n", channels);
2222 break;
2223 }
2224
2225 }
2226
2227 fprintf(stdout,"\n\nTitle Sets:");
2228 for (f=0; f < title_set_info->number_of_title_sets ; f++ ) {
2229 fprintf(stdout,"\n\n\tTitle set %d\n", f + 1);
2230 for (i=0; i < titles_info->number_of_titles ; i++ ) {
2231 if (titles_info->titles[i].title_set == f + 1) {
2232 if(titles_info->titles[i].aspect_ratio == 3) {
2233 fprintf(stdout,"\t\tThe aspect ratio of title set %d is 16:9\n", f + 1);
2234 } else if (titles_info->titles[i].aspect_ratio == 0) {
2235 fprintf(stdout,"\t\tThe aspect ratio of title set %d is 4:3\n", f + 1);
2236 } else {
2237 fprintf(stdout,"\t\tThe aspect ratio of title set %d is unknown\n", f + 1);
2238 }
2239 fprintf(stdout,"\t\tTitle set %d has %d angle(s)\n", f + 1, titles_info->titles[i].angles);
2240 fprintf(stdout,"\t\tTitle set %d has %d audio_track(s)\n", f + 1, titles_info->titles[i].angles);
2241 fprintf(stdout,"\t\tTitle set %d has %d subpicture channel(s)\n", f + 1, titles_info->titles[i].sub_pictures);
2242 break;
2243 }
2244 }
2245 fprintf(stdout,"\n\t\tTitles included in title set %d is/are\n", f + 1);
2246 for (i=0; i < titles_info->number_of_titles ; i++ ) {
2247 if (titles_info->titles[i].title_set == f + 1) {
2248 fprintf(stdout,"\t\t\tTitle %d:\n", i + 1);
2249 fprintf(stdout,"\t\t\t\tTitle %d has %d chapter(s)\n", i + 1, titles_info->titles[i].chapters);
2250 fprintf(stdout,"\t\t\t\tTitle %d has %d audio channle(s)\n", i + 1, titles_info->titles[i].audio_channels);
2251 }
2252 }
2253 }
2254 DVDFreeTitlesInfo(titles_info);
2255 DVDFreeTitleSetInfo(title_set_info);
2256
2257 return(0);
2258}
2259
2260int main(int argc, char *argv[]){
2261
2262 /* Args */
2263 int flags;
2264
2265 /* Switches */
2266 int title_set = 0;
2267 int titles;
2268 int start_chapter;
2269 int end_chapter;
2270
2271 int do_mirror = 0;
2272 int do_title_set = 0;
2273 int do_chapter = 0;
2274 int do_titles = 0;
2275 int do_feature = 0;
2276 int do_info = 0;
2277
2278
2279
2280 int return_code;
2281
2282 /* DVD Video device */
2283 char * dvd=NULL;
2284
2285 /* Temp switch helpers */
2286 char * verbose_temp=NULL;
2287 char * aspect_temp=NULL;
2288 char * start_chapter_temp=NULL;
2289 char * end_chapter_temp=NULL;
2290 char * titles_temp=NULL;
2291 char * title_set_temp=NULL;
2292
2293
2294 /* Title of the DVD */
2295 char title_name[33]="";
2296 char * provided_title_name=NULL;
2297
2298 /* Targer dir */
2299 char * targetdir=NULL;
2300
2301 /* Temp filename,dirname */
2302 char targetname[PATH_MAX];
2303 struct stat fileinfo;
2304
2305
2306 /* The DVD main structure */
2307 dvd_reader_t * _dvd=NULL;
2308
2309
2310
2311 /*Todo do isdigit check */
2312
2313 while ((flags = getopt(argc, argv, "MFI?hi:v:a:o:n:s:e:t:T:")) != -1) {
2314 switch (flags) {
2315 case 'i':
2316 if(optarg[0]=='-') usage();
2317 dvd = optarg;
2318 break;
2319 case 'v':
2320 if(optarg[0]=='-') usage();
2321 verbose_temp = optarg;
2322 break;
2323 case 'o':
2324 if(optarg[0]=='-') usage();
2325 targetdir = optarg;
2326 break;
2327 case 'n':
2328 if(optarg[0]=='-') usage();
2329 provided_title_name = optarg;
2330 break;
2331 case 'a':
2332 if(optarg[0]=='-') usage();
2333 aspect_temp = optarg;
2334 break;
2335 case 's':
2336 if(optarg[0]=='-') usage();
2337 start_chapter_temp = optarg;
2338 break;
2339 case 'e':
2340 if(optarg[0]=='-') usage();
2341 end_chapter_temp = optarg;
2342 break;
2343 case 't':
2344 if(optarg[0]=='-') usage();
2345 titles_temp = optarg;
2346 break;
2347 case 'T':
2348 if(optarg[0]=='-') usage();
2349 title_set_temp = optarg;
2350 break;
2351 case 'M':
2352 do_mirror = 1;
2353 break;
2354 case 'F':
2355 do_feature = 1;
2356 break;
2357 case 'I':
2358 do_info = 1;
2359 break;
2360
2361 case '?':
2362 usage();
2363 break;
2364 case 'h':
2365 usage();
2366 break;
2367 default:
2368 usage();
2369 }
2370 }
2371
2372 if (dvd == NULL) {
2373 usage();
2374 exit(1);
2375 }
2376
2377 if (targetdir == NULL && do_info == 0) {
2378 usage();
2379 exit(1);
2380 }
2381
2382 if(verbose_temp == NULL) {
2383 verbose = 0;
2384 } else {
2385 verbose = atoi(verbose_temp);
2386 }
2387
2388 if (aspect_temp == NULL) {
2389 /* Deafult to 16:9 aspect ratio */
2390 aspect = 3;
2391 } else {
2392 aspect = atoi(aspect_temp);
2393 }
2394
2395 if((aspect != 0) && (aspect != 3) && (do_info == 0)){
2396 usage();
2397 exit(1);
2398 }
2399
2400 if ( titles_temp != NULL) {
2401 titles = atoi(titles_temp);
2402 if ( titles < 1 ) {
2403 usage();
2404 exit(1);
2405 }
2406 }
2407
2408 if ( start_chapter_temp !=NULL) {
2409 start_chapter = atoi(start_chapter_temp);
2410 if ( start_chapter < 1 || start_chapter > 99 ) {
2411 usage();
2412 exit(1);
2413 }
2414 }
2415
2416 if (end_chapter_temp != NULL) {
2417 end_chapter = atoi(end_chapter_temp);
2418 if ( end_chapter < 1 || end_chapter > 99 ) {
2419 usage();
2420 exit(1);
2421 }
2422 }
2423
2424 if ( end_chapter_temp != NULL || start_chapter_temp != NULL) {
2425 if( end_chapter_temp == NULL) {
2426 end_chapter = 99;
2427 } else if ( start_chapter_temp == NULL) {
2428 start_chapter = 1;
2429 }
2430 if ( end_chapter < start_chapter ) {
2431 usage();
2432 exit(1);
2433 }
2434 }
2435
2436 if ( titles_temp != NULL && ((end_chapter_temp != NULL) || (start_chapter_temp != NULL))) {
2437 do_chapter = 1;
2438 } else if ((titles_temp != NULL) && ((end_chapter_temp == NULL) && (start_chapter_temp == NULL))) {
2439 do_titles=1;
2440 }
2441 if (do_chapter && (titles_temp == NULL)) {
2442 titles = 0;
2443 }
2444
2445 if ( title_set_temp != NULL ) {
2446 title_set = atoi(title_set_temp);
2447 if ( title_set > 99 || title_set < 0 ) {
2448 usage();
2449 exit(1);
2450 }
2451 do_title_set = 1;
2452 }
2453
2454 if (do_info + do_titles + do_chapter + do_feature + do_title_set + do_mirror > 1 ) {
2455 usage();
2456 exit(1);
2457 } else if ( do_info + do_titles + do_chapter + do_feature + do_title_set + do_mirror == 0) {
2458 usage();
2459 exit(1);
2460 }
2461#ifdef DEBUG
2462 fprintf(stderr,"After args\n");
2463#endif
2464
2465
2466 _dvd = DVDOpen(dvd);
2467 if(!_dvd) exit(-1);
2468
2469
2470 if (do_info) {
2471 DVDDisplayInfo(_dvd, dvd);
2472 DVDClose(_dvd);
2473 exit(0);
2474 }
2475
2476
2477 if(provided_title_name == NULL) {
2478 if (DVDGetTitleName(dvd,title_name) != 0) {
2479 fprintf(stderr,"You must provide a title name when you read your DVD-Video structure direct from the HD\n");
2480 DVDClose(_dvd);
2481 exit(1);
2482 }
2483 if (strstr(title_name, "DVD_VIDEO") != NULL) {
2484 fprintf(stderr,"The DVD-Video title on the disk is DVD_VIDEO which is to generic please provide a title with the -n switch\n");
2485 DVDClose(_dvd);
2486 exit(2);
2487 }
2488
2489 } else {
2490 if (strlen(provided_title_name) > 32) {
2491 fprintf(stderr,"The title name specified is longer than 32 charachters, truncating the title name\n");
2492 strncpy(title_name,provided_title_name, 32);
2493 title_name[32]='\0';
2494 } else {
2495 strcpy(title_name,provided_title_name);
2496 }
2497 }
2498
2499
2500
2501 sprintf(targetname,"%s",targetdir);
2502
2503 if (stat(targetname, &fileinfo) == 0) {
2504 if (! S_ISDIR(fileinfo.st_mode)) {
2505 fprintf(stderr,"The target directory is not valid, it may be a ordinary file\n");
2506 }
2507 } else {
2508 if (mkdir(targetname, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
2509 fprintf(stderr,"Faild creating target directory\n");
2510 perror("");
2511 DVDClose(_dvd);
2512 exit(-1);
2513 }
2514 }
2515
2516
2517 sprintf(targetname,"%s/%s",targetdir, title_name);
2518
2519 if (stat(targetname, &fileinfo) == 0) {
2520 if (! S_ISDIR(fileinfo.st_mode)) {
2521 fprintf(stderr,"The title directory is not valid, it may be a ordinary file\n");
2522 }
2523 } else {
2524 if (mkdir(targetname, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
2525 fprintf(stderr,"Faild creating title directory\n");
2526 perror("");
2527 DVDClose(_dvd);
2528 exit(-1);
2529 }
2530 }
2531
2532 sprintf(targetname,"%s/%s/VIDEO_TS",targetdir, title_name);
2533
2534 if (stat(targetname, &fileinfo) == 0) {
2535 if (! S_ISDIR(fileinfo.st_mode)) {
2536 fprintf(stderr,"The VIDEO_TS directory is not valid, it may be a ordinary file\n");
2537 }
2538 } else {
2539 if (mkdir(targetname, S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
2540 fprintf(stderr,"Faild creating VIDEO_TS directory\n");
2541 perror("");
2542 DVDClose(_dvd);
2543 exit(-1);
2544 }
2545 }
2546
2547
2548#ifdef DEBUG
2549 fprintf(stderr,"After dirs\n");
2550#endif
2551
2552
2553 if(do_mirror) {
2554 if ( DVDMirror(_dvd, targetdir, title_name) != 0 ) {
2555 fprintf(stderr, "Mirror of DVD faild\n");
2556 return_code = -1;
2557 } else {
2558 return_code = 0;
2559 }
2560 }
2561#ifdef DEBUG
2562 fprintf(stderr,"After Mirror\n");
2563#endif
2564
2565
2566 if (do_title_set) {
2567 if (DVDMirrorTitleSet(_dvd, targetdir, title_name, title_set) != 0) {
2568 fprintf(stderr, "Mirror of title set %d faild\n", title_set);
2569 return_code = -1;
2570 } else {
2571 return_code = 0;
2572 }
2573
2574 }
2575#ifdef DEBUG
2576 fprintf(stderr,"After Title Set\n");
2577#endif
2578
2579
2580
2581 if(do_feature) {
2582 if ( DVDMirrorMainFeature(_dvd, targetdir, title_name) != 0 ) {
2583 fprintf(stderr, "Mirror of main feature film of DVD faild\n");
2584 return_code = -1;
2585 } else {
2586 return_code = 0;
2587 }
2588 }
2589
2590 if(do_titles) {
2591 if (DVDMirrorTitles(_dvd, targetdir, title_name, titles) != 0) {
2592 fprintf(stderr, "Mirror of title %d faild\n", titles);
2593 return_code = -1;
2594 } else {
2595 return_code = 0;
2596 }
2597 }
2598
2599
2600 if(do_chapter) {
2601 if (DVDMirrorChapters(_dvd, targetdir, title_name, start_chapter, end_chapter, titles) != 0) {
2602 fprintf(stderr, "Mirror of chapters %d to %d in title %d faild\n", start_chapter, end_chapter, titles);
2603 return_code = -1;
2604 } else {
2605 return_code = 0;
2606 }
2607 }
2608
2609
2610 DVDClose(_dvd);
2611 exit(return_code);
2612}
2613
2614
2615
This page took 0.442129 seconds and 4 git commands to generate.