Package: lsdvd Version: 0.16-3+b1 Severity: normal Tags: upstream patch To convert timestamps from libdvdread, lsdvd uses the following code, from function dvdtime2msec():
double fps = frames_per_s[(dt->frame_u & 0xc0) >> 6]; 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; if(fps > 0) ms += ((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f) * 1000.0 / fps; Obviously, the hour, minute and second field are in BCD, and the frame_u field is too, except for the two most significant bits that code the frame rate. Except... the parentheses are missing in the last formula, and therefore the *1000/fps is only applied to the low nibble, not the high one. The attached patch fixes the problem. I can observe it is the right behaviour using a DVD I have on my disk. Extracting a cell from the VOB streams, I get with ffprobe: frame|pkt_pts_time=0.168178|pkt_duration_time=0.040000 ... frame|pkt_pts_time=20.008178|pkt_duration_time=0.040000 frame|pkt_pts_time=N/A|pkt_duration_time=0.040000 frame|pkt_pts_time=N/A|pkt_duration_time=0.040000 As you can see, the correct duration would be: 20.008178 + 3*0.040000 - 0.168178 = 19.960. Unpatched lsdvd prints 19.180. With the attached patch, 19.960. -- System Information: Debian Release: jessie/sid APT prefers testing APT policy: (500, 'testing'), (500, 'stable'), (50, 'unstable') Architecture: amd64 (x86_64) Foreign Architectures: i386 Kernel: Linux 3.11-2-amd64 (SMP w/8 CPU cores) Locale: LANG=C, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages lsdvd depends on: ii libc6 2.17-97 ii libdvdread4 4.2.1-2 lsdvd recommends no packages. lsdvd suggests no packages. -- no debconf information
--- lsdvd.c.orig 2014-03-01 19:41:51.102966573 +0100 +++ lsdvd.c 2014-03-01 19:41:54.095011681 +0100 @@ -92,7 +92,7 @@ ms += (((dt->second & 0xf0) >> 3) * 5 + (dt->second & 0x0f)) * 1000; if(fps > 0) - ms += ((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f) * 1000.0 / fps; + ms += (((dt->frame_u & 0x30) >> 3) * 5 + (dt->frame_u & 0x0f)) * 1000.0 / fps; return ms; }