DVD access libraries and their status

I’ve noted when I posted suggestions for GSoC that we’ve been working on improving the DVD-related libraries that are currently used by most of the open-source DVD players out there: libdvdread and libdvdnav — together with these, me and the Other Diego have been dusting off libdvdcss as well, which takes care of, well, cracking the CSS protection on DVDs so that you can watch your legally owned DVDs on Linux and other operating systems without going crazy.

Yes I did take the picture just to remind you all that I do pay for content so if you find me taking about libdvdcss is not because I’m a piracy apologist because I’m cheap — whenever I do resolve to piracy it’s because it’s nigh impossible to get the content legally, like for what concerns J-Drama.

Anyway, the work we’ve been pouring into these libraries will hopefully soon come into fruition; on my part it’s mostly a build system cleanup task: while the first fork, on mplayer, was trying to replace autotools with a generic, FFmpeg-inspired build system, the results have been abysmal enough that we decided to get back to autotools (I mean, with me on board, are you surprised?) so now they have a modern, non-recursive, autotools based build system. Diego and J-B have been cleaning up the code itself from the conditionals for Windows, and and Rafaël has now started cleaning up libdvdnav’s code by itself.

One of the interesting part of all this is that the symbol table exposed by the libraries does not really match what is exposed by the headers themselves. You can easily find this by using exuberant-ctags – part of dev-util/ctags – to produce the list of exported symbols from a set of header files:

% exuberant-ctags --c-kinds=px -f - /usr/include/dvdread/*.h
DVDClose        /usr/include/dvdread/dvd_reader.h       /^void DVDClose( dvd_reader_t * );$/;"  p
DVDCloseFile    /usr/include/dvdread/dvd_reader.h       /^void DVDCloseFile( dvd_file_t * );$/;"        p
DVDDiscID       /usr/include/dvdread/dvd_reader.h       /^int DVDDiscID( dvd_reader_t *, unsigned char * );$/;" p
DVDFileSeek     /usr/include/dvdread/dvd_reader.h       /^int32_t DVDFileSeek( dvd_file_t *, int32_t );$/;"     p
DVDFileSeekForce        /usr/include/dvdread/dvd_reader.h       /^int DVDFileSeekForce( dvd_file_t *, int offset, int force_size);$/;"  p
DVDFileSize     /usr/include/dvdread/dvd_reader.h       /^ssize_t DVDFileSize( dvd_file_t * );$/;"      p
DVDFileStat     /usr/include/dvdread/dvd_reader.h       /^int DVDFileStat(dvd_reader_t *, int, dvd_read_domain_t, dvd_stat_t *);$/;"    p
DVDISOVolumeInfo        /usr/include/dvdread/dvd_reader.h       /^int DVDISOVolumeInfo( dvd_reader_t *, char *, unsigned int,$/;"       p
DVDOpen /usr/include/dvdread/dvd_reader.h       /^dvd_reader_t *DVDOpen( const char * );$/;"    p
DVDOpenFile     /usr/include/dvdread/dvd_reader.h       /^dvd_file_t *DVDOpenFile( dvd_reader_t *, int, dvd_read_domain_t );$/;"        p
DVDReadBlocks   /usr/include/dvdread/dvd_reader.h       /^ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * );$/;"      p
DVDReadBytes    /usr/include/dvdread/dvd_reader.h       /^ssize_t DVDReadBytes( dvd_file_t *, void *, size_t );$/;"     p
DVDUDFCacheLevel        /usr/include/dvdread/dvd_reader.h       /^int DVDUDFCacheLevel( dvd_reader_t *, int );$/;"      p
DVDUDFVolumeInfo        /usr/include/dvdread/dvd_reader.h       /^int DVDUDFVolumeInfo( dvd_reader_t *, char *, unsigned int,$/;"       p
FreeUDFCache    /usr/include/dvdread/dvd_udf.h  /^void FreeUDFCache(void *cache);$/;"   p
[...]

You can then compare this list with the content of the library by using nm:

% nm -D --defined-only /usr/lib/libdvdread.so
0000000000004480 T DVDClose
0000000000004920 T DVDCloseFile
0000000000005180 T DVDDiscID
0000000000004e60 T DVDFileSeek
0000000000004ec0 T DVDFileSeekForce
0000000000005120 T DVDFileSize
00000000000049c0 T DVDFileStat
000000000021e878 B dvdinput_close
000000000021e888 B dvdinput_error
000000000021e898 B dvdinput_open
000000000021e890 B dvdinput_read
000000000021e880 B dvdinput_seek
000000000000f960 T dvdinput_setup
000000000021e870 B dvdinput_title
0000000000005340 T DVDISOVolumeInfo
0000000000003fa0 T DVDOpen
0000000000004520 T DVDOpenFile
0000000000004d80 T DVDReadBlocks
0000000000004fa0 T DVDReadBytes
[...]

But without going into further details I can tell you that there are two functions that should be exported that are not, and the dvdinput_ series that shouldn’t have been exposed are. So there are a few things to fix there for sure.

As I said before, my personal preference would be to merge libdvdread and libdvdnav again (they were split a long time ago as some people didn’t need/want the menu support) — if it wasn’t for obvious legal issues I would merge libdvdcss as well, but that’s a different story. I just need to find the motivation to go look in the reverse dependencies of these two libraries, and see if the interface exposed between the two is ever used, it might be possible to reduce their surface as well.

Yes this would be a relatively big change for relatively small gain, on the other hand, it might be worth to get this as a new side-by-side installable library that can be used preferentially, falling back to the old ones if not present. And given the staleness of the code, I wouldn’t really mind having to go through testing from scratch at this point.

Anyway, at least the build system of the three libraries will soon look similar enough that they seem to be part of the same project, instead of each going its own way — among other things the ebuilds for the three should look almost entirely identical, in my opinion, so that should be a good start.

If you want to contribute, given that the only mailing list we have on videolan is for libdvdcss, you can push your branches to Gitorious thanks to the VideoLAN mirror and from there just contact somebody in on Freenode to get it reviewed/merged.

Update (2017-04-22): as you may know, Gitorious was acquired by GitLab in 2015 and turned down the service. So no more VideoLAN mirror or anything actually.

Exit mobile version