From 46a3378f19ecfaef59629d65b365e109c54cd61a Mon Sep 17 00:00:00 2001 From: Earl Chew Date: Sun, 15 Jun 2014 07:19:28 -0700 Subject: [PATCH 1/5] [lsdvd] Clean up whitespace Remove trailing whitepace and spaces masked by tabs Signed-off-by: Earl Chew --- lsdvd-0.16/lsdvd.c | 50 ++++++++++++++++++++++----------------------- lsdvd-0.16/lsdvd.h | 1 - lsdvd-0.16/ocode.c | 1 - lsdvd-0.16/ocode.h | 1 - lsdvd-0.16/ohuman.c | 14 ++++++------- lsdvd-0.16/oxml.c | 10 ++++----- lsdvd-0.16/oxml.h | 1 - 7 files changed, 37 insertions(+), 41 deletions(-) diff --git a/lsdvd-0.16/lsdvd.c b/lsdvd-0.16/lsdvd.c index 6f4f79e..7e9aa9d 100644 --- a/lsdvd-0.16/lsdvd.c +++ b/lsdvd-0.16/lsdvd.c @@ -47,7 +47,7 @@ language[] = { { "pt", "Portugues" }, { "qu", "Quechua" }, { "rm", "Rhaeto-Romance" }, { "rn", "Kirundi" }, { "ro", "Romanian" }, { "ru", "Russian" }, { "rw", "Kinyarwanda" }, { "sa", "Sanskrit" }, { "sd", "Sindhi" }, { "sg", "Sangho" }, { "sh", "Serbo-Croatian" }, { "si", "Sinhalese" }, { "sk", "Slovak" }, { "sl", "Slovenian" }, { "sm", "Samoan" }, - { "sn", "Shona" }, { "so", "Somali" }, { "sq", "Albanian" }, { "sr", "Serbian" }, { "ss", "Siswati" }, + { "sn", "Shona" }, { "so", "Somali" }, { "sq", "Albanian" }, { "sr", "Serbian" }, { "ss", "Siswati" }, { "st", "Sesotho" }, { "su", "Sundanese" }, { "sv", "Svenska" }, { "sw", "Swahili" }, { "ta", "Tamil" }, { "te", "Telugu" }, { "tg", "Tajik" }, { "th", "Thai" }, { "ti", "Tigrinya" }, { "tk", "Turkmen" }, { "tl", "Tagalog" }, { "tn", "Setswana" }, { "to", "Tonga" }, { "tr", "Turkish" }, { "ts", "Tsonga" }, { "tt", "Tatar" }, { "tw", "Twi" }, @@ -101,7 +101,7 @@ int dvdtime2msec(dvd_time_t *dt) /* * This is used to add up sets of times in the struct. it's not elegant at all - * but a quick way to easily add up 4 times at once. tracking the times in usec's + * but a quick way to easily add up 4 times at once. tracking the times in usec's * constantly is easier, but without using math.h, it sucks to actually DO anything with it * also it ***has*** to be better to return the playback_time, not just mess with it like this */ @@ -221,7 +221,7 @@ char output_option(char *arg) return '\0'; } } - + int main(int argc, char *argv[]) { @@ -236,7 +236,7 @@ int main(int argc, char *argv[]) subp_attr_t *subp_attr; pgc_t *pgc; int i, j, k, c, titles, cell, vts_ttn, title_set_nr; - char lang_code[3]; + char lang_code[3]; char *dvd_device = "/dev/dvd"; int has_title = 0, ret = 0; int max_length = 0, max_track = 0; @@ -272,13 +272,13 @@ int main(int argc, char *argv[]) } if (argv[optind]) { dvd_device = argv[optind]; } - + ret = stat(dvd_device, &dvd_stat); if ( ret < 0 ) { fprintf(stderr, "Can't find device %s\n", dvd_device); return 1; } - + dvd = DVDOpen(dvd_device); if( !dvd ) { fprintf( stderr, "Can't open disc %s!\n", dvd_device); @@ -312,12 +312,12 @@ int main(int argc, char *argv[]) vmgi_mat = ifo_zero->vmgi_mat; struct dvd_info dvd_info; - + dvd_info.discinfo.device = dvd_device; dvd_info.discinfo.disc_title = has_title ? "unknown" : title; dvd_info.discinfo.vmg_id = vmgi_mat->vmg_identifier; dvd_info.discinfo.provider_id = vmgi_mat->provider_identifier; - + dvd_info.title_count = titles; dvd_info.titles = calloc(titles, sizeof(*dvd_info.titles)); @@ -342,7 +342,7 @@ int main(int argc, char *argv[]) dvd_info.titles[j].general.length = dvdtime2msec(&pgc->playback_time)/1000.0; converttime(&dvd_info.titles[j].general.playback_time, &pgc->playback_time); dvd_info.titles[j].general.vts_id = vtsi_mat->vts_identifier; - + if (dvdtime2msec(&pgc->playback_time) > max_length) { max_length = dvdtime2msec(&pgc->playback_time); max_track = j+1; @@ -353,12 +353,12 @@ int main(int argc, char *argv[]) dvd_info.titles[j].audiostream_count = 0; for (k=0; k < 8; k++) - if (pgc->audio_control[k] & 0x8000) + if (pgc->audio_control[k] & 0x8000) dvd_info.titles[j].audiostream_count++; dvd_info.titles[j].subtitle_count = 0; for (k=0; k < 32; k++) - if (pgc->subp_control[k] & 0x80000000) + if (pgc->subp_control[k] & 0x80000000) dvd_info.titles[j].subtitle_count++; if(opt_v) { @@ -376,7 +376,7 @@ int main(int argc, char *argv[]) // PALETTE if (opt_P) { dvd_info.titles[j].palette = malloc(16 * sizeof(int)); - for (i=0; i < 16; i++) { dvd_info.titles[j].palette[i] = pgc->palette[i]; } + for (i=0; i < 16; i++) { dvd_info.titles[j].palette[i] = pgc->palette[i]; } } else { dvd_info.titles[j].palette = NULL; } @@ -427,9 +427,9 @@ int main(int argc, char *argv[]) int ms; for (i=0; inr_of_programs; i++) - { + { ms=0; - int next = pgc->program_map[i+1]; + int next = pgc->program_map[i+1]; if (i == pgc->nr_of_programs - 1) next = pgc->nr_of_cells + 1; while (cell < next - 1) @@ -474,11 +474,11 @@ int main(int argc, char *argv[]) for (i=0, k=0; i<32; i++) { if ((pgc->subp_control[i] & 0x80000000) == 0) continue; - + subp_attr = &vtsi_mat->vts_subp_attr[i]; sprintf(lang_code, "%c%c", subp_attr->lang_code>>8, subp_attr->lang_code & 0xff); if (!isalpha(lang_code[0]) || !isalpha(lang_code[1])) { lang_code[0] = 'x'; lang_code[1] = 'x'; } - + dvd_info.titles[j].subtitles[k].langcode = strdup(lang_code); dvd_info.titles[j].subtitles[k].language = lang_name(lang_code); dvd_info.titles[j].subtitles[k].content = subp_type[subp_attr->lang_extension]; @@ -489,33 +489,33 @@ int main(int argc, char *argv[]) dvd_info.titles[j].subtitles = NULL; } - } // if vtsi_mat + } // if vtsi_mat } // if not -t } // for each title - + if (! opt_t) { dvd_info.longest_track = max_track; } if (opt_p) { ocode_print(&perl_syntax, &dvd_info); } else { switch(opt_O) { - case 'p': - ocode_print(&perl_syntax, &dvd_info); + case 'p': + ocode_print(&perl_syntax, &dvd_info); break; case 'y': - ocode_print(&python_syntax, &dvd_info); + ocode_print(&python_syntax, &dvd_info); break; case 'x': - oxml_print(&dvd_info); + oxml_print(&dvd_info); break; case 'r': - ocode_print(&ruby_syntax, &dvd_info); + ocode_print(&ruby_syntax, &dvd_info); break; case 'd': - ocode_print(&debug_syntax, &dvd_info); + ocode_print(&debug_syntax, &dvd_info); break; default : - ohuman_print(&dvd_info); + ohuman_print(&dvd_info); break; } } diff --git a/lsdvd-0.16/lsdvd.h b/lsdvd-0.16/lsdvd.h index 8ba1f22..814f884 100644 --- a/lsdvd-0.16/lsdvd.h +++ b/lsdvd-0.16/lsdvd.h @@ -1,4 +1,3 @@ - #ifndef _LSDVD_H_ #define _LSDVD_H_ diff --git a/lsdvd-0.16/ocode.c b/lsdvd-0.16/ocode.c index d993775..d15769e 100644 --- a/lsdvd-0.16/ocode.c +++ b/lsdvd-0.16/ocode.c @@ -276,4 +276,3 @@ void ocode_print(struct Syntax *syntax_, struct dvd_info *dvd_info) { } - diff --git a/lsdvd-0.16/ocode.h b/lsdvd-0.16/ocode.h index 0bcc3c7..84609a1 100644 --- a/lsdvd-0.16/ocode.h +++ b/lsdvd-0.16/ocode.h @@ -29,4 +29,3 @@ extern struct Syntax debug_syntax; void ocode_print(struct Syntax *, struct dvd_info*); #endif /* _OCODE_H_ */ - diff --git a/lsdvd-0.16/ohuman.c b/lsdvd-0.16/ohuman.c index ad91326..e76e8a9 100644 --- a/lsdvd-0.16/ohuman.c +++ b/lsdvd-0.16/ohuman.c @@ -8,10 +8,10 @@ void ohuman_print(struct dvd_info *dvd_info) { printf("Disc Title: %s\n", dvd_info->discinfo.disc_title); int i, j; - for (j=0; j < dvd_info->title_count; j++) + for (j=0; j < dvd_info->title_count; j++) { if ( opt_t == j+1 || opt_t == 0 ) { - + //GENERAL printf("Title: %02d, Length: %02d:%02d:%02d.%03d ", j+1, dvd_info->titles[j].general.playback_time.hour, @@ -24,8 +24,8 @@ void ohuman_print(struct dvd_info *dvd_info) { // dvd_info->titles[j].general.length); printf("Chapters: %02d, Cells: %02d, ", dvd_info->titles[j].chapter_count_reported, dvd_info->titles[j].cell_count); printf("Audio streams: %02d, Subpictures: %02d", dvd_info->titles[j].audiostream_count, dvd_info->titles[j].subtitle_count); - printf("\n"); - + printf("\n"); + if (dvd_info->titles[j].parameter.format != NULL ) { printf("\tVTS: %02d, TTN: %02d, ", dvd_info->titles[j].parameter.vts, dvd_info->titles[j].parameter.ttn); printf("FPS: %.2f, ", dvd_info->titles[j].parameter.fps); @@ -86,14 +86,14 @@ void ohuman_print(struct dvd_info *dvd_info) { // CELLS if (dvd_info->titles[j].cells != NULL) { - for (i=0; ititles[j].cell_count; i++) + for (i=0; ititles[j].cell_count; i++) { -// printf("\tCell: %02d, Length: %02d:%02d:%02d.%03d\n", i+1, +// printf("\tCell: %02d, Length: %02d:%02d:%02d.%03d\n", i+1, // (int)dvd_info->titles[j].cells[i].length / 3600, // (int)(dvd_info->titles[j].cells[i].length / 60 ) % 60, // (int)(dvd_info->titles[j].cells[i].length) % 60, // (int)(dvd_info->titles[j].cells[i].length*1000) % 1000); - printf("\tCell: %02d, Length: %02d:%02d:%02d.%03d\n", i+1, + printf("\tCell: %02d, Length: %02d:%02d:%02d.%03d\n", i+1, dvd_info->titles[j].cells[i].playback_time.hour, dvd_info->titles[j].cells[i].playback_time.minute, dvd_info->titles[j].cells[i].playback_time.second, diff --git a/lsdvd-0.16/oxml.c b/lsdvd-0.16/oxml.c index bdd7cd5..743a4fb 100644 --- a/lsdvd-0.16/oxml.c +++ b/lsdvd-0.16/oxml.c @@ -9,7 +9,7 @@ int XMLDEF_(char *name, const char *format, ...) { va_list argp; XMLINDENT; printf("<%s>", name); - + va_start(argp, format); vprintf(format, argp); va_end(argp); @@ -20,14 +20,14 @@ int XMLDEF_(char *name, const char *format, ...) { // int XMLBOX_(char *name) { // XMLINDENT; // printf("<%s>\n", name); -// _xlvl++; +// _xlvl++; // _xlvl_type[_xlvl] = malloc(20 * sizeof(char)); // sprintf(_xlvl_type[_xlvl], "", name); // return 0; //} //void XMLRETURN_() { -// _xlvl--; +// _xlvl--; // XMLINDENT; // printf("%s\n", _xlvl_type[_xlvl+1] ); // free(_xlvl_type[_xlvl+1]); @@ -87,7 +87,7 @@ void oxml_print(struct dvd_info *dvd_info) { XMLDEF("height", "%s", dvd_info->titles[j].parameter.height); XMLDEF("df", "%s", permitted_df_xml[dvd_info->titles[j].parameter.df_code]); } - + // PALETTE if (dvd_info->titles[j].palette != NULL ) { XMLBOX("palette"); @@ -159,7 +159,7 @@ void oxml_print(struct dvd_info *dvd_info) { XMLRETURN; } } - XMLRETURN; + XMLRETURN; } } } diff --git a/lsdvd-0.16/oxml.h b/lsdvd-0.16/oxml.h index 7dfa15d..726b397 100644 --- a/lsdvd-0.16/oxml.h +++ b/lsdvd-0.16/oxml.h @@ -1,4 +1,3 @@ - #ifndef _OXML_H_ #define _OXML_H_ From 584a71d009744906770f200f555837b3d72650f4 Mon Sep 17 00:00:00 2001 From: Earl Chew Date: Sun, 15 Jun 2014 08:10:03 -0700 Subject: [PATCH 2/5] [lsdvd] Add emacs and vi formatting directives Use formatting directives to try to keep code layout consistent. Signed-off-by: Earl Chew --- lsdvd-0.16/lsdvd.c | 1 + lsdvd-0.16/lsdvd.h | 1 + lsdvd-0.16/ocode.c | 1 + lsdvd-0.16/ocode.h | 1 + lsdvd-0.16/ohuman.c | 1 + lsdvd-0.16/oxml.c | 1 + lsdvd-0.16/oxml.h | 1 + 7 files changed, 7 insertions(+) diff --git a/lsdvd-0.16/lsdvd.c b/lsdvd-0.16/lsdvd.c index 7e9aa9d..bf01fa2 100644 --- a/lsdvd-0.16/lsdvd.c +++ b/lsdvd-0.16/lsdvd.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ /* * lsdvd.c * diff --git a/lsdvd-0.16/lsdvd.h b/lsdvd-0.16/lsdvd.h index 814f884..d9d1139 100644 --- a/lsdvd-0.16/lsdvd.h +++ b/lsdvd-0.16/lsdvd.h @@ -1,3 +1,4 @@ +/* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #ifndef _LSDVD_H_ #define _LSDVD_H_ diff --git a/lsdvd-0.16/ocode.c b/lsdvd-0.16/ocode.c index d15769e..3997f22 100644 --- a/lsdvd-0.16/ocode.c +++ b/lsdvd-0.16/ocode.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #include "ocode.h" /* diff --git a/lsdvd-0.16/ocode.h b/lsdvd-0.16/ocode.h index 84609a1..00e1328 100644 --- a/lsdvd-0.16/ocode.h +++ b/lsdvd-0.16/ocode.h @@ -1,3 +1,4 @@ +/* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #ifndef _OCODE_H_ #define _OCODE_H_ diff --git a/lsdvd-0.16/ohuman.c b/lsdvd-0.16/ohuman.c index e76e8a9..7da6667 100644 --- a/lsdvd-0.16/ohuman.c +++ b/lsdvd-0.16/ohuman.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #include #include "lsdvd.h" diff --git a/lsdvd-0.16/oxml.c b/lsdvd-0.16/oxml.c index 743a4fb..a89511f 100644 --- a/lsdvd-0.16/oxml.c +++ b/lsdvd-0.16/oxml.c @@ -1,3 +1,4 @@ +/* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #include "oxml.h" static int _xlvl = 0; diff --git a/lsdvd-0.16/oxml.h b/lsdvd-0.16/oxml.h index 726b397..10a1e5f 100644 --- a/lsdvd-0.16/oxml.h +++ b/lsdvd-0.16/oxml.h @@ -1,3 +1,4 @@ +/* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #ifndef _OXML_H_ #define _OXML_H_ From 0b5ef4b80dbb9cb219adc004ac12c0dd3decfc5a Mon Sep 17 00:00:00 2001 From: Earl Chew Date: Sun, 15 Jun 2014 08:23:35 -0700 Subject: [PATCH 3/5] [lsdvd] Print cell range for chapters, and sector range for cells In addition to showing the startcell, also show the lastcell. Signed-off-by: Earl Chew --- lsdvd-0.16/lsdvd.c | 21 +++++++++++++-------- lsdvd-0.16/lsdvd.h | 5 +++++ lsdvd-0.16/ocode.c | 5 +++++ lsdvd-0.16/ohuman.c | 13 ++++++++----- lsdvd-0.16/oxml.c | 5 +++++ 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/lsdvd-0.16/lsdvd.c b/lsdvd-0.16/lsdvd.c index bf01fa2..32c20b6 100644 --- a/lsdvd-0.16/lsdvd.c +++ b/lsdvd-0.16/lsdvd.c @@ -236,7 +236,7 @@ int main(int argc, char *argv[]) video_attr_t *video_attr; subp_attr_t *subp_attr; pgc_t *pgc; - int i, j, k, c, titles, cell, vts_ttn, title_set_nr; + int i, j, k, c, titles, vts_ttn, title_set_nr; char lang_code[3]; char *dvd_device = "/dev/dvd"; int has_title = 0, ret = 0; @@ -421,19 +421,21 @@ int main(int argc, char *argv[]) // CHAPTERS - cell = 0; if (opt_c) { + int cell = pgc->program_map[0] - 1; + int end = cell + pgc->nr_of_cells; + dvd_info.titles[j].chapter_count = pgc->nr_of_programs; dvd_info.titles[j].chapters = calloc(dvd_info.titles[j].chapter_count, sizeof(*dvd_info.titles[j].chapters)); - int ms; for (i=0; inr_of_programs; i++) { - ms=0; - int next = pgc->program_map[i+1]; - if (i == pgc->nr_of_programs - 1) next = pgc->nr_of_cells + 1; - - while (cell < next - 1) + int ms = 0; + int next = + (i == pgc->nr_of_programs - 1) + ? end + : pgc->program_map[i+1] - 1; + while (cell < next) { // Only use first cell of multi-angle cells if (pgc->cell_playback[cell].block_mode <= 1) @@ -444,6 +446,7 @@ int main(int argc, char *argv[]) cell++; } dvd_info.titles[j].chapters[i].startcell = pgc->program_map[i]; + dvd_info.titles[j].chapters[i].lastcell = cell; dvd_info.titles[j].chapters[i].length = ms * 0.001; @@ -462,6 +465,8 @@ int main(int argc, char *argv[]) dvd_info.titles[j].cells[i].block_mode = pgc->cell_playback[i].block_mode; dvd_info.titles[j].cells[i].block_type = pgc->cell_playback[i].block_type; converttime(&dvd_info.titles[j].cells[i].playback_time, &pgc->cell_playback[i].playback_time); + dvd_info.titles[j].cells[i].first_sector = pgc->cell_playback[i].first_sector; + dvd_info.titles[j].cells[i].last_sector = pgc->cell_playback[i].last_sector; } } else { dvd_info.titles[j].cells = NULL; diff --git a/lsdvd-0.16/lsdvd.h b/lsdvd-0.16/lsdvd.h index d9d1139..a596d4e 100644 --- a/lsdvd-0.16/lsdvd.h +++ b/lsdvd-0.16/lsdvd.h @@ -2,6 +2,8 @@ #ifndef _LSDVD_H_ #define _LSDVD_H_ +#include + extern int opt_a, opt_c, opt_n, opt_p, opt_q; extern int opt_s, opt_t, opt_v, opt_x, opt_d; @@ -56,11 +58,14 @@ struct dvd_info { float length; playback_time_t playback_time; int startcell; + int lastcell; } *chapters; int cell_count; struct { float length; playback_time_t playback_time; + uint32_t first_sector; + uint32_t last_sector; int block_mode; int block_type; } *cells; diff --git a/lsdvd-0.16/ocode.c b/lsdvd-0.16/ocode.c index 3997f22..248e286 100644 --- a/lsdvd-0.16/ocode.c +++ b/lsdvd-0.16/ocode.c @@ -1,6 +1,8 @@ /* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #include "ocode.h" +#include + /* Simple helper macros for generating Perl structures */ @@ -229,6 +231,7 @@ void ocode_print(struct Syntax *syntax_, struct dvd_info *dvd_info) { DEF("ix", "%d", i+1); DEF("length", "%.3f", dvd_info->titles[j].chapters[i].length); DEF("startcell", "%d", dvd_info->titles[j].chapters[i].startcell); + DEF("lastcell", "%d", dvd_info->titles[j].chapters[i].lastcell); RETURN; } RETURN; @@ -242,6 +245,8 @@ void ocode_print(struct Syntax *syntax_, struct dvd_info *dvd_info) { HASH(0); DEF("ix", "%d", i+1); DEF("length", "%.3f", dvd_info->titles[j].cells[i].length); + DEF("first_sector", "%" PRIu32, dvd_info->titles[j].cells[i].first_sector); + DEF("last_sector", "%" PRIu32, dvd_info->titles[j].cells[i].last_sector); DEF("block_mode", "%d", dvd_info->titles[j].cells[i].block_mode); DEF("block_type", "%d", dvd_info->titles[j].cells[i].block_type); RETURN; diff --git a/lsdvd-0.16/ohuman.c b/lsdvd-0.16/ohuman.c index 7da6667..a9baec9 100644 --- a/lsdvd-0.16/ohuman.c +++ b/lsdvd-0.16/ohuman.c @@ -70,18 +70,19 @@ void ohuman_print(struct dvd_info *dvd_info) { if (dvd_info->titles[j].chapters != NULL) { for (i=0; ititles[j].chapter_count; i++) { -// printf("\tChapter: %02d, Length: %02d:%02d:%02d.%03d, Start Cell: %02d\n", i+1, +// printf("\tChapter: %02d, Length: %02d:%02d:%02d.%03d, Start Cell: %02d, Last Cell: %02d\n", i+1, // (int)dvd_info->titles[j].chapters[i].length / 3600, // (int)(dvd_info->titles[j].chapters[i].length / 60 ) % 60, // (int)(dvd_info->titles[j].chapters[i].length) % 60, // (int)(dvd_info->titles[j].chapters[i].length*1000) % 1000, // dvd_info->titles[j].chapters[i].startcell); - printf("\tChapter: %02d, Length: %02d:%02d:%02d.%03d, Start Cell: %02d\n", i+1, + printf("\tChapter: %02d, Length: %02d:%02d:%02d.%03d, Start Cell: %d, Last Cell: %d\n", i+1, dvd_info->titles[j].chapters[i].playback_time.hour, dvd_info->titles[j].chapters[i].playback_time.minute, dvd_info->titles[j].chapters[i].playback_time.second, dvd_info->titles[j].chapters[i].playback_time.usec, - dvd_info->titles[j].chapters[i].startcell); + dvd_info->titles[j].chapters[i].startcell, + dvd_info->titles[j].chapters[i].lastcell); } } @@ -94,11 +95,13 @@ void ohuman_print(struct dvd_info *dvd_info) { // (int)(dvd_info->titles[j].cells[i].length / 60 ) % 60, // (int)(dvd_info->titles[j].cells[i].length) % 60, // (int)(dvd_info->titles[j].cells[i].length*1000) % 1000); - printf("\tCell: %02d, Length: %02d:%02d:%02d.%03d\n", i+1, + printf("\tCell: %02d, Length: %02d:%02d:%02d.%03d, First Sector: %d, Last Sector: %d\n", i+1, dvd_info->titles[j].cells[i].playback_time.hour, dvd_info->titles[j].cells[i].playback_time.minute, dvd_info->titles[j].cells[i].playback_time.second, - dvd_info->titles[j].cells[i].playback_time.usec); + dvd_info->titles[j].cells[i].playback_time.usec, + dvd_info->titles[j].cells[i].first_sector, + dvd_info->titles[j].cells[i].last_sector); } } diff --git a/lsdvd-0.16/oxml.c b/lsdvd-0.16/oxml.c index a89511f..136fdf9 100644 --- a/lsdvd-0.16/oxml.c +++ b/lsdvd-0.16/oxml.c @@ -1,6 +1,8 @@ /* -*- c-basic-offset:8; indent-tabs-mode:t -*- vi: set sw=8: */ #include "oxml.h" +#include + static int _xlvl = 0; char *_xlvl_type[256]; @@ -130,6 +132,7 @@ void oxml_print(struct dvd_info *dvd_info) { XMLDEF("ix", "%d", i+1); XMLDEF("length", "%.3f", dvd_info->titles[j].chapters[i].length); XMLDEF("startcell", "%d", dvd_info->titles[j].chapters[i].startcell); + XMLDEF("lastcell", "%d", dvd_info->titles[j].chapters[i].lastcell); XMLRETURN; } } @@ -141,6 +144,8 @@ void oxml_print(struct dvd_info *dvd_info) { XMLBOX("cell"); XMLDEF("ix", "%d", i+1); XMLDEF("length", "%.3f", dvd_info->titles[j].cells[i].length); + XMLDEF("first_sector", "%" PRIu32, dvd_info->titles[j].cells[i].first_sector); + XMLDEF("last_sector", "%" PRIu32, dvd_info->titles[j].cells[i].last_sector); XMLDEF("block_mode", "%d", dvd_info->titles[j].cells[i].block_mode); XMLDEF("block_type", "%d", dvd_info->titles[j].cells[i].block_type); XMLRETURN; From 9903244bfab7282d89cc90fcea116b666deeb86c Mon Sep 17 00:00:00 2001 From: Earl Chew Date: Sun, 15 Jun 2014 08:45:31 -0700 Subject: [PATCH 4/5] [lsdvd] Avoid loss of precision when computing durations Use rational arithmetic when computing and summing video durations to allow counting frame by frame. Only convert to real numbers when computing displayed quantities. Signed-off-by: Earl Chew --- lsdvd-0.16/lsdvd.c | 133 +++++++++++++++++++++++++++++++-------------- lsdvd-0.16/lsdvd.h | 2 + 2 files changed, 95 insertions(+), 40 deletions(-) diff --git a/lsdvd-0.16/lsdvd.c b/lsdvd-0.16/lsdvd.c index 32c20b6..4ccf746 100644 --- a/lsdvd-0.16/lsdvd.c +++ b/lsdvd-0.16/lsdvd.c @@ -76,8 +76,8 @@ char *sample_freq[2] = {"48000", "48000"}; char *audio_type[5] = {"Undefined", "Normal", "Impaired", "Comments1", "Comments2"}; char *subp_type[16] = {"Undefined", "Normal", "Large", "Children", "reserved", "Normal_CC", "Large_CC", "Children_CC", "reserved", "Forced", "reserved", "reserved", "reserved", "Director", "Large_Director", "Children_Director"}; -int subp_id_shift[4] = {24, 8, 8, 8}; double frames_per_s[4] = {-1.0, 25.00, -1.0, 29.97}; +int subp_id_shift[4] = {24, 8, 8, 8}; char* program_name; @@ -86,38 +86,79 @@ char* program_name; //extern void oruby_print(struct dvd_info *dvd_info); //extern void ohuman_print(struct dvd_info *dvd_info); -int dvdtime2msec(dvd_time_t *dt) -{ - double fps = frames_per_s[(dt->frame_u & 0xc0) >> 6]; - long ms; - ms = (((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f)) * 3600000; - ms += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60000; - ms += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000; +/* Ticks + * + * Compute durations using rational arithmetic to avoid loss of precision + * when summing. The result of the sum will be exact prior to converting + * the sum. + */ +#define TICK_SCALE 1001 + +typedef struct { + unsigned ticks; + unsigned scale; +} dvd_ticks_t; - if(fps > 0) - ms += (((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f)) * 1000.0 / fps; +dvd_ticks_t dvdtime2ticks(const dvd_time_t *dt) + { + unsigned scale = 0; + unsigned secs = 0; + unsigned ticks = 0; + + if (dt) { + static const unsigned tick_scale[4] = { + 0, 25 * TICK_SCALE, 0, 30 * (TICK_SCALE-1) }; + + scale = tick_scale[(dt->frame_u & 0xc0) >> 6]; + + secs += (((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f)) * 3600; + secs += (((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f)) * 60; + secs += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1; + + ticks += ((dt->frame_u & 0x30)>> 3) * 5 + (dt->frame_u & 0x0f); + ticks *= TICK_SCALE; + } - return ms; + return (dvd_ticks_t) { + .scale = scale, + .ticks = secs * scale + ticks, + }; + } + +dvd_ticks_t addticks(dvd_ticks_t lhs, dvd_ticks_t rhs) + { + if (lhs.ticks == 0) + return rhs; + if (rhs.ticks == 0) + return lhs; + return (dvd_ticks_t) { + .ticks = lhs.ticks + rhs.ticks, + .scale = lhs.scale == rhs.scale ? lhs.scale : 0, + }; } -/* - * This is used to add up sets of times in the struct. it's not elegant at all - * but a quick way to easily add up 4 times at once. tracking the times in usec's - * constantly is easier, but without using math.h, it sucks to actually DO anything with it - * also it ***has*** to be better to return the playback_time, not just mess with it like this - */ -void converttime(playback_time_t *pt, dvd_time_t *dt) +playback_time_t ticks2playbacktime(dvd_ticks_t dt) { - double fps = frames_per_s[(dt->frame_u & 0xc0) >> 6]; - - pt->usec = pt->usec + (((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f)) * 1000.0 / fps; - pt->second = pt->second + ((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f); - pt->minute = pt->minute + ((dt->minute & 0xf0) >> 3) * 5 + (dt->minute & 0x0f); - pt->hour = pt->hour + ((dt->hour & 0xf0) >> 3) * 5 + (dt->hour & 0x0f); + unsigned secs = dt.ticks / dt.scale; + unsigned frac = dt.ticks % dt.scale; + + return (playback_time_t) { + .hour = (secs / 3600), + .minute = (secs % 3600) / 60, + .second = (secs % 60), + .usec = (frac * (1000000 / dt.scale) + + frac * (1000000 % dt.scale) / dt.scale), + .ticks = (dt.ticks), + .scale = (dt.scale), + }; +} - if ( pt->usec >= 1000 ) { pt->usec -= 1000; pt->second++; } - if ( pt->second >= 60 ) { pt->second -= 60; pt->minute++; } - if ( pt->minute > 59 ) { pt->minute -= 60; pt->hour++; } +double playbacktime(playback_time_t pt) +{ + return pt.hour * 3600 + + pt.minute * 60 + + pt.second * 1 + + pt.usec / 1e6; } /* @@ -339,13 +380,16 @@ int main(int argc, char *argv[]) vmgi_mat = ifo_zero->vmgi_mat; title_set_nr = ifo_zero->tt_srpt->title[j].title_set_nr; pgc = vts_pgcit->pgci_srp[ifo[title_set_nr]->vts_ptt_srpt->title[vts_ttn - 1].ptt[0].pgcn - 1].pgc; - - dvd_info.titles[j].general.length = dvdtime2msec(&pgc->playback_time)/1000.0; - converttime(&dvd_info.titles[j].general.playback_time, &pgc->playback_time); + dvd_info.titles[j].general.length = + playbacktime( + ticks2playbacktime( + dvdtime2ticks(&pgc->playback_time))); + dvd_info.titles[j].general.playback_time = + ticks2playbacktime(dvdtime2ticks(&pgc->playback_time)); dvd_info.titles[j].general.vts_id = vtsi_mat->vts_identifier; - if (dvdtime2msec(&pgc->playback_time) > max_length) { - max_length = dvdtime2msec(&pgc->playback_time); + if (dvd_info.titles[j].general.length > max_length) { + max_length = dvd_info.titles[j].general.length; max_track = j+1; } @@ -430,7 +474,7 @@ int main(int argc, char *argv[]) for (i=0; inr_of_programs; i++) { - int ms = 0; + dvd_ticks_t ticks = dvdtime2ticks(NULL); int next = (i == pgc->nr_of_programs - 1) ? end @@ -440,16 +484,19 @@ int main(int argc, char *argv[]) // Only use first cell of multi-angle cells if (pgc->cell_playback[cell].block_mode <= 1) { - ms = ms + dvdtime2msec(&pgc->cell_playback[cell].playback_time); - converttime(&dvd_info.titles[j].chapters[i].playback_time, &pgc->cell_playback[cell].playback_time); + dvd_ticks_t dt = dvdtime2ticks( + &pgc->cell_playback[cell].playback_time); + ticks = addticks(ticks, dt); + dvd_info.titles[j].chapters[i].playback_time = + ticks2playbacktime(dt); } cell++; } dvd_info.titles[j].chapters[i].startcell = pgc->program_map[i]; dvd_info.titles[j].chapters[i].lastcell = cell; - dvd_info.titles[j].chapters[i].length = ms * 0.001; - - + dvd_info.titles[j].chapters[i].length = + playbacktime( + ticks2playbacktime(ticks)); } } @@ -461,10 +508,16 @@ int main(int argc, char *argv[]) if (opt_d) { for (i=0; inr_of_cells; i++) { - dvd_info.titles[j].cells[i].length = dvdtime2msec(&pgc->cell_playback[i].playback_time)/1000.0; + dvd_ticks_t dt = dvdtime2ticks( + &pgc->cell_playback[i].playback_time); + playback_time_t pt = ticks2playbacktime(dt); + + dvd_info.titles[j].cells[i].playback_time = pt; + dvd_info.titles[j].cells[i].length = + playbacktime(pt); + dvd_info.titles[j].cells[i].block_mode = pgc->cell_playback[i].block_mode; dvd_info.titles[j].cells[i].block_type = pgc->cell_playback[i].block_type; - converttime(&dvd_info.titles[j].cells[i].playback_time, &pgc->cell_playback[i].playback_time); dvd_info.titles[j].cells[i].first_sector = pgc->cell_playback[i].first_sector; dvd_info.titles[j].cells[i].last_sector = pgc->cell_playback[i].last_sector; } diff --git a/lsdvd-0.16/lsdvd.h b/lsdvd-0.16/lsdvd.h index a596d4e..9c873cc 100644 --- a/lsdvd-0.16/lsdvd.h +++ b/lsdvd-0.16/lsdvd.h @@ -12,6 +12,8 @@ typedef struct { int minute; int second; int usec; + int ticks; + int scale; } playback_time_t; struct dvd_info { From 50187c1f5ee5a2593cf19187e52c7f1a4c26bc1d Mon Sep 17 00:00:00 2001 From: Earl Chew Date: Sun, 15 Jun 2014 08:51:25 -0700 Subject: [PATCH 5/5] [lsdvd] Print exact durations in programmatic output Include durations as rational numbers when generating programmatic output so that computations can be exact. Signed-off-by: Earl Chew --- lsdvd-0.16/ocode.c | 9 +++++++++ lsdvd-0.16/oxml.c | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/lsdvd-0.16/ocode.c b/lsdvd-0.16/ocode.c index 248e286..50a8c8a 100644 --- a/lsdvd-0.16/ocode.c +++ b/lsdvd-0.16/ocode.c @@ -148,6 +148,12 @@ static void STOP_() { while(_lvl) RETURN; } +static void ocode_playback_time(const playback_time_t *pb) { + ARRAY("duration"); + ADEF("%d", pb->ticks); + ADEF("%d", pb->scale); + RETURN; +} void ocode_print(struct Syntax *syntax_, struct dvd_info *dvd_info) { int j, i; @@ -173,6 +179,7 @@ void ocode_print(struct Syntax *syntax_, struct dvd_info *dvd_info) { HASH(0); DEF("ix", "%d", j+1); DEF("length", "%.3f", dvd_info->titles[j].general.length); + ocode_playback_time(&dvd_info->titles[j].general.playback_time); DEF("vts_id", "'%.12s'", dvd_info->titles[j].general.vts_id); if (dvd_info->titles[j].parameter.format != NULL ) { @@ -230,6 +237,7 @@ void ocode_print(struct Syntax *syntax_, struct dvd_info *dvd_info) { HASH(0); DEF("ix", "%d", i+1); DEF("length", "%.3f", dvd_info->titles[j].chapters[i].length); + ocode_playback_time(&dvd_info->titles[j].chapters[i].playback_time); DEF("startcell", "%d", dvd_info->titles[j].chapters[i].startcell); DEF("lastcell", "%d", dvd_info->titles[j].chapters[i].lastcell); RETURN; @@ -245,6 +253,7 @@ void ocode_print(struct Syntax *syntax_, struct dvd_info *dvd_info) { HASH(0); DEF("ix", "%d", i+1); DEF("length", "%.3f", dvd_info->titles[j].cells[i].length); + ocode_playback_time(&dvd_info->titles[j].cells[i].playback_time); DEF("first_sector", "%" PRIu32, dvd_info->titles[j].cells[i].first_sector); DEF("last_sector", "%" PRIu32, dvd_info->titles[j].cells[i].last_sector); DEF("block_mode", "%d", dvd_info->titles[j].cells[i].block_mode); diff --git a/lsdvd-0.16/oxml.c b/lsdvd-0.16/oxml.c index 136fdf9..84bdc02 100644 --- a/lsdvd-0.16/oxml.c +++ b/lsdvd-0.16/oxml.c @@ -59,6 +59,10 @@ void XMLSTOP_() { while(_xlvl) XMLRETURN; } +static void oxml_playback_time(const playback_time_t *pb) { + XMLDEF("duration", "%d %d", pb->ticks, pb->scale); +} + void oxml_print(struct dvd_info *dvd_info) { int j, i; @@ -78,6 +82,7 @@ void oxml_print(struct dvd_info *dvd_info) { XMLBOX("track"); XMLDEF("ix", "%d", j+1); XMLDEF("length", "%.3f", dvd_info->titles[j].general.length); + oxml_playback_time(&dvd_info->titles[j].general.playback_time); XMLDEF("vts_id", "%.12s", dvd_info->titles[j].general.vts_id); if (dvd_info->titles[j].parameter.format != NULL ) { @@ -131,6 +136,7 @@ void oxml_print(struct dvd_info *dvd_info) { XMLBOX("chapter"); XMLDEF("ix", "%d", i+1); XMLDEF("length", "%.3f", dvd_info->titles[j].chapters[i].length); + oxml_playback_time(&dvd_info->titles[j].chapters[i].playback_time); XMLDEF("startcell", "%d", dvd_info->titles[j].chapters[i].startcell); XMLDEF("lastcell", "%d", dvd_info->titles[j].chapters[i].lastcell); XMLRETURN; @@ -144,6 +150,7 @@ void oxml_print(struct dvd_info *dvd_info) { XMLBOX("cell"); XMLDEF("ix", "%d", i+1); XMLDEF("length", "%.3f", dvd_info->titles[j].cells[i].length); + oxml_playback_time(&dvd_info->titles[j].cells[i].playback_time); XMLDEF("first_sector", "%" PRIu32, dvd_info->titles[j].cells[i].first_sector); XMLDEF("last_sector", "%" PRIu32, dvd_info->titles[j].cells[i].last_sector); XMLDEF("block_mode", "%d", dvd_info->titles[j].cells[i].block_mode);