I thought I might relate my adventures in the wonderful world of DLNA and UPnP.
I have a Panasonic DVR that I mostly use to time-shift various free-to-air TV programs - the very few that are worth watching. Occasionally there will be something that I feel might be worth keeping a bit longer in my video file collection.
My technique used to involve trimming out the ads and other noise and then writing the video to a re-writable DVD. This could then be ripped into my collection. This was actually a fairly convenient process - the write to DVD could be done while I slept, and when I had a few I could use Handbrake to extract the video files.
This all came to stop when the DVR's DVD drive shredded its position servo gears, and there seemed to be very little point in getting it repaired. Since it had a network connection I thought of trying to get the files from it using its DLNA interface.
So, I go buy a cat5 cable and a connector so that I don't have to get behind the hifi system but can still plug in the long cat5 cable. Once connected to the network the DVR spends ages updating its firmware - frustrating. Eventually I was able to get to its screen for setting up DLNA. It lists the MAC address of potential clients - an empty list
Next I start Googling for suitable client programs. The first was eezUPnP, but this seemed to be just for audio. Next was XBMC. This has the most awful interface I have ever attempted to use - it might be OK when used on a TV, but on a laptop -
With XBMC running it couldn't see any servers, and the DVR still couldn't see any clients. I suspected a firewall issue - but what port? More Googling gave no help, so I fired up lsof to see what XBMC was trying to use. It seemed to have some interest in several so I opened them in the firewall. Finally a glimmer of success - the DVR now listed my laptop as a potential client, which I then confirmed. XBMC could now see the DVR and even play a video. I know now that udp 1900 is the important one to open on the client.
Unfortunately, to save the video in XBMC you need a plug-in and my version of XBMC from the SL7 repos was apparently too old to get one that was compatible. So, next I uninstalled XBMC and installed VLC, and happily it was able to both play and save the video files.
At this stage I was both happy that I could get at the files, and sad that it was such a long and frustrating journey.
The next problem is that processing the files one-at-a-time using the VLC GUI was going to get tedious rather quickly - I needed some way of using ffmpeg to read the files in a batch script. Fortunately there is a program called djmount that uses libfuse to create a virtual file system of the DVR. Just the thing for doing batches.
So I download the source for djmount and successfully build it. Of course it fails to recognise my DVR
Checking the logs from running it in debug mode I see that my DVR is reporting version 2 of some standard, but djmount was only accepting version 1. Just for fun, I simply changed the string, and surprisingly it now recognised the DVR, but then failed trying to allocate some memory. At first I assumed the usual problem of corrupted memory causing malloc to fail, but eventually noticed it was being asked for a stupidly large amount of memory.
My system is 64-bit, but djmount seems to have been written for 32-bit. While it compiles, there were lots of places where 32-bit and 64-bit numbers were incorrectly used. The best example was in a function that used varargs parameters but passed one in as 32-bit, but extracted it as 64-bit. This resulted in a huge number and messed up all the following parameters. Fixing all these problems had the side effect that djmount was now able to handle files of more than 2GB which, according to some forums, is currently not possible.
The program was now able to get a directory listing from the server, but only 36 of the 586 files were shown. My server was only returning 12 at a time, not the entire list as djmount expects. It does a couple of retries and then gives up. I simply changed it to 50 retries and got the entire directory list - over and over - it was in some sort of loop. More debugging and eventually tracked it down to the cache timeout. This interval was just a bit less than the time it took to get the directory list.
Changing the timeouts from a few seconds to an hour or so (which should be reasonable for a DVR) fixed that issue.
Now it was time to copy a file. It started off OK, but after a while it reported yet another error and stopped the transfer. I traced the problem to the function that reads from the socket and parses the results. The parsing was sort of expecting that the socket read might not return a full buffer, but the parser never checks to ensure its got enough to work with. This brain dead code has Intel copyrights all over it - something that makes me quite sad. I rewrote the socket read so that it doesn't return until its got as much data as possible - hence the parser can work properly.
There is an interesting issue with files copied from the DVR - they have snippets of the video that was edited out. My assumption is that the DVR stores the files in a format that is not accurately editable (most video formats have this problem) and keeps some metadata containing the frame numbers to be skipped on replay. These frames are skipped when playing back the video, and also when preparing to write a DVD but not when playing via UPnP. This means that eventually I will need re-edit the files, but that is a task for another time.
Finally, today I created a script to get batches of files and process them with ffmpeg. It has code to handle stopping and restarting.
My last task is to clean up my debugging code and make a patch for the changes.