I'd like to add transcoding support to minidlna and just wanted to make sure no one else was working on this already. Currently I have a proof-of-concept working for audio only, in which the server decompresses all audio files using libavcodec and streams them to the device as LPCM. Clearly this could use some optimisation, but it works pretty well.
I would be interested to hear from anyone else who has been looking into this.
That is very good news, congragulations. I want to ask something, most of the Samsung B650 TV users suffer from DTS codec type in bluray rips. What you have done downmixes the sound to 2-channels. So, in order to keep surround sound, is it possible to detect DTS sound (I guess, this part is already done), and convert it to AC3 5.1 or AAC 5.1 sound formats?
I haven't had time to work on it yet, but it's something I've been very interested in adding. Would you happen to have any code to share at this point?
Sure. I'll tidy it up a bit and post a patch over the weekend. The current implementation transcodes all audio files to L16 - there is no video or seek support yet. The file size is correctly reported based on the duration, samplerate and number of channels detected by the file scanner, and it works fine with MP3, FLAC and Vorbis on a Samsung B650 and mostly on a PS3 (on some tracks it plays a few seconds of the beginning again at the end - this is likely to do with the way the file size is calculated).
Do you know if there is any way to determine the codec capabilities of the connected device (preferably other than a UserAgent based lookup table)? Ideally I would only invoke the transcoder when the player can't support the file that is being played.
That sounds great, thanks!
UPnP/DLNA renders are supposed to return a list of all the media profiles they support when you invoke the GetProtocolInfo action from the ConnectionManager service. There is a list of devices at http://www.upnp-database.info, but most of the renders don't have this field filled in for some reason.
There's also an old package called Intel Tools for UPnP Technology, which comes with a utility called Device Spy. If you run it on your network, you should be able to query your media players to see what they return.
Patch as promised at http://www.mikestirling.co.uk/files/audio_transcode_20100607.patch.gz. Hopefully this should apply against the current CVS HEAD. Remember this is just a proof of concept - there are some things I would prefer to improve upon, such as only transcoding when required.
The multi-channel DTS->AC3 transcode that Gurcan requested above would be nice to have but would depend on FFMPEG having the required codec support (I haven't checked). It would also be complicated by the fact that we wouldn't know the transcoded length in advance.
Hopefully I'll have some more time to work on this over the next couple of weeks, day-job commitments permitting!
Nice work! Should be a good start. Would you be able to get patch using diff -up instead?
Figuring out the actual file size shouldn't be too much of an issue. You should be able to use chunked encoding and not send the file size to the client.
As requested. Hope this is okay.
Hi, I tried you patch against CVS head, but I get the following error:
upnphttp.c: In function ‘SendResp_audiotranscode’:
upnphttp.c:2010: error: too few arguments to function ‘send_data’
upnphttp.c:2057: warning: pointer targets in initialization differ in signedness
upnphttp.c:2067: error: too few arguments to function ‘send_data’
The following command failed:
gcc -Wall -g -O3 -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/ffmpeg -I/usr/include/libavutil -I/usr/include/libavcodec -I/usr/include/libavformat -I/usr/include/ffmpeg/libavutil -I/usr/include/ffmpeg/libavcodec -I/usr/include/ffmpeg/libavformat -o upnphttp.o -c upnphttp.c
make: *** Error 1
Hi, yes looks like send_data has changed in the last couple of days. I'm hoping to get time to do some more on this later in the week. In the meantime if you add an extra argument of 0 at the end of the two broken send_data calls it should work as it did before, or roll back upnphttp.c to CVS rev 1.57.
Thanks, I added 0 at the end of the send_data function calls and it compiled fine. My problem now is that I built it on a debian 5 machine, but the NVX is debian 4 (etch) so is missing a bunch of libraries. I installed the missing libs on the NVX, which got me to the point of being able to run minidlna, but now my Denon just says "server disconnected" when I try to play a track (I'm trying to transcode alac). If I run minidnla with debugging, the last thing I see is:
upnphttp.c:1879: info: Audio sample rate = 44100 Hz, 2 channels, decoded size = 38478660 bytes
upnphttp.c:1891: info: Serving DetailID: 27
So at least it's finding the decoder now, but I'm not sure what is failing next since there are no error messages.
Unfortunately the NVX runs etch which is so old that there are no repositories any more. I'm downloading the CD's to set up an etch machine, but I'm not sure if this will help.
You could statically link the binary so that you don't need to worry about runtime dependencies. This might help. Regarding the "server disconnected" message - I didn't look at the send_data changes in much detail and I never had time to test the proposed fix so it's possible that there is still something wrong here. I'll take a proper look at it this evening (I'm in UK). You could also try building it for the PC and running Wireshark while you access it to see if this yields any clues.
You probably don't need to build a whole new etch machine either, if you don't want to static link. Just set up a chroot environment, like this:
apt-get install debootstrap dchroot
debootstrap -arch i386 etch ./etch-env http://mirrors.kernel.org/debian
The recent changes were just to pass along flags to the send function, so we don't have to send a partial frame just for the HTTP header.
Would love to see this working - I have a bunch of ALAC files which I can't listen to currently using MiniDLNA / ReadyDLNA on a ReadyNAS Duo. I tried to go the TwonkyMedia Server route and add transcoding using either the alac command which is built into the ReadyNAS - in /usr/bin (and used by SqueezeServer for transcoding) or a new version of faad which the Squeezeserver guys developed - both transcode ALAC to LPCM at about 5 to 6 x realtime (faad also handles AAC) but I just could not get Twonky to transcode them and gave up. Now would love to see this just work (like pretty much everything else does) in Ready/Mini DLNA. Let me know if I can help with beta testing or debugging.
Unfortunately it doesn't look like etch is available any more:
# debootstrap -arch i386 etch ./etch-env http://mirrors.kernel.org/debian
I: Retrieving Release
E: Failed getting release file http://mirrors.kernel.org/debian/dists/etch/Release
The good news is that it works from my lenny machine (actually a VM running on Mac OS X). Now I just need to get it working for the NVX!
Even better news is that I managed to statically compile minidnla and can now transcode ALAC from my NVX!
Like the previous poster, I've been trying TwonkyMedia, MediaTomb, faad, ffmpeg, you name it for about the last 6 months, but I could never get them to work.
Great work guys!
I managed to get this to compile as well on my Duo. It appears to be working to some extent: on my Samsung B650 TV with ALAC files I hear white noise so not sure the TV can handle the PCM stream over DLNA. With MP3 or AAC, there is a long pause and then the TV gives an error - I've even had the TV crash once. Looking in the log file I see either:
upnphttp.c:1056: error: send(res_buf): Broken pipe
upnphttp.c:1056: error: send(res_buf): Connection reset by peer
Had to compile FFMPEG first (on the DUO) which took forever. Also had to compile LIBID3TAG from source as there was a version mismatch between the executable package and the development headers available through apt-get.
Oh and a feature request: Would be great if audio transcoding could be a client by client option (or even a file-type by file-type option - my Samsung plays AAC just fine - really only need this for ALAC). I also use plugplayer on an iPhone and it plays ALAC quite happily so no need for transcoding there. Thanks.
It's interesting that it doesn't work with the Samsung because I've tested with that model (from the PC) and it worked fine. If you are able to try a build running on a PC on a recent Linux distribution then it would be useful to see if that behaves any differently. A quick search didn't show up whether the Duo CPU is big or little endian, but at least the older SPARCs were big-endian, so this may be the root of the problem.
Transcoding selectively was always the plan, along with adding support for seeking. A lack of free time is preventing me from working on this at the moment, but I do intend to get back onto it soon.
I'm also seeing the broken pipe problem. I'm transcoding from an NVX to a Denon S302. On the Denon, the track stops playing and I see the following in the error log:
upnphttp.c:1056: error: send(res_buf): Broken pipe
After a few minutes, the Denon starts playing the track again, so there seems to be some kind of error recovery.
Let me know if there's anything I can do to help debug the problem.
I managed to confirm that the DUO uses a SPARC V8 which I believe is big-endian. Any suggestions as to what changes might be needed to the code to make this work? As far as I can see, the SPARC has the horsepower to transcode ALAC comfortably, and AAC / MP3 at a stretch so would be very nice to get this working.
Well if libavcodec decodes to the architecture's native endianness then the byte-swap in upnphttp.c at lines 2055-2065 is not required on a big-endian machine. Try commenting that block out. Search for "Re-order buffer for big-endian" if the line numbers don't match.
Commented it out.. recompiled… same issue - white noise (with what sounds like very staticky music trying to come through). Could it be anything to do with sampling rates? I know that the music is all 44.1khz (I can see that when I run MinDLNA in debug mode) but it is being streamed as 48khz (as confirmed by my audio receiver attached to the TV). Does avcodec automatically upsample to the higher sampling rate?
No, the transcoded stream should be the same sample rate as the original file, so it is likely that the TV is upsampling (which is not a problem). Any sampling rate error would be apparent as a pitch and speed change anyway - the music would still be audible. Badly distorted audio is usually either wrong byte order or a signed/unsigned mismatch.
Unfortunately I have no SPARC hardware to test this on, but I do have access to a PowerPC development board which is big-endian, so I will give it a try on that later on.
OK - I am an idiot. I was still running the old executable with the endian conversion lines still in there. When I ran the correct file, ALAC streams perfectly to the TV. With MP3 and AAC, I'm wondering whether the DUO has the horsepower to transcode these - with AAC, I eventually get bursts of music after a long wait.. with MP3 I never get anything and eventually the TV errors out with "Network Disconnected" - I'm assuming some sort of timeout when no data is streamed to the TV. But this is great - if I can now make transcoding selective, I will be a very happy camper. Thanks.