Skip to content

CrystalHD improvements

Hi all,

It’s been a few weeks since I last posted, and I’ve accumulated a couple of useful CrystalHD improvements that I think are worth talking about. First off, my comprehensive interlaced detection algorithm is now merged to the main git tree, as are the changes I’m about to talk about, so there are now no outstanding changes to merge.

Downscaling

The CrystalHD hardware is capable of downscaling, so that it will shrink the decoded frames before they are copied over to system memory. While all vaguely modern graphics hardware supports scaling, it’s still useful that the CrystalHD can do it, and that’s because it allows you to scale before the copy; smaller frames take less time and CPU to copy over. Normally, this isn’t an issue, but some videos can make the hardware grumpy such that the total time needed to decode and copy over the frame is more than the time available if you want to playback in realtime. So, being able to shrink the copy time can save you from an unplayable clip. Mind you, it’s a weird hardware/firmware bug that this is even an issue – I’ve been able to playback bluray video just fine but certain encoded files at much lower bitrates can trigger this slow decode behaviour.

To take advantage of downscaling you will also need to update your Mplayer as I had to make a change there to support FFmpeg per-codec command line options. With the latest code you can do:

mplayer -lavdopts o=crystalhd_downscale_width=[width]

to specify a width (eg: Use 1280 for 720p)

Packed b-frames

I mentioned this briefly in my last update, saying that the hardware has a bug where it would output certain frames twice when decoding a DivX/XviD video in an AVI file with packed b-frames. I implemented a work-around and thought that my work was done, but it turns out that there are at least two ways of indicating packed b-frames in a file, and one of them triggers the bug while the other does not. Sounds great, you might think – except that the files which don’t trigger the bug do still look like the files which do – which caused my work-around to kick in and ruin the playback.

So, I had to find another way to distinguish them. To achieve that, I ended up staring at a binary diff of two files and saw that they were using different frame types as placeholders for the packed frames. In the files that trigger the bug, they are “drop frames” and in the normal files, they are “delay frames”. Despite their names, I don’t believe a decoder is supposed to either drop or delay anything when encountering these; rather it’s supposed to replace them with the packed frame it received earlier. In other words, there’s a convention here that a decoder has to understand and respect, and it seems the CrystalHD is not completely up to speed with things.

With that difference identified, I was able to craft an additional test that lets us distinguish the two cases and now packed b-frame support is hopefully complete.

70012

While I don’t have anything meaningful to report in this area, I did spend some more time poking at the 70012, and while the existing code will likely yield something pretty close to a sane video stream, I still see discontinuities in the output, where frames mysteriously disappear, which very quickly leads to audio de-sync in Mplayer (which doesn’t understand the concept of a frame that fails to be decoded, so doesn’t know to re-sync the audio). I tried a number of different approaches, all with the same result – missing frames from files that play perfectly on the 70015. I know it’s possible to make it work, as both the gstreamer plugin and xbmc can do it; however, they are very different architectures that use separate input and output threads, which is not possible in FFmpeg. Ultimately, I’m not sure the support can really be improved, given the constraints of the FFmpeg architecture. Such is life.

Update: Reimar rightly points out that Mplayer can understand frames that fail to decode; I failed to remember the problem properly. What’s actually going on is that you indicate a failed frame by returning nothing; however, we only find out by obtaining the next output frame and seeing that it’s not the one we expected. At this point, returning an error would mean having to store the output frame for the next decode call and accepting that the input pipeline would increase by one frame. If that happens enough times, the pipeline will fill up completely and then we’re in real trouble. So, rather, I’m wishing I could return a frame and indicate that other frames had failed to be decoded at the same time.

{ 7 } Comments

  1. Maic Striepe | 1st May 2011 at 12:15 | Permalink

    Great news, seems I’ll have to update my mplayer again :-)

    Thank you.

  2. Reimar Döffinger | 2nd May 2011 at 02:28 | Permalink

    > audio de-sync in Mplayer (which doesn’t understand the concept of a frame that fails to be decoded, so doesn’t know to re-sync the audio)

    Actually it does, and actually it should be the default behaviour. Otherwise there would have been no need for the mpi_no_picture hack in vd_ffmpeg.c
    There might of course be one or more bugs..

  3. Philip Langdale | 2nd May 2011 at 05:55 | Permalink

    You are correct, and I’ve updated the post to explain what I really mean.

  4. Brian Hall | 2nd May 2011 at 14:46 | Permalink

    After doing a fresh clone, I get this error, maybe a ./configure problem? I gave it no options, just let it use the defaults:

    cc -MD -MP -Wundef -Wstrict-prototypes -Wmissing-prototypes -Wdisabled-optimization -Wno-pointer-sign -Wdeclaration-after-statement -std=gnu99 -O3 -march=atom -mtune=atom -mssse3 -mfpmath=sse -pipe -fexcess-precision=fast -floop-parallelize-all -flto -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -Ilibdvdread4 -I. -Iffmpeg -O3 -march=atom -mtune=atom -mssse3 -mfpmath=sse -fomit-frame-pointer -pipe -D_REENTRANT -I/usr/include/ -D_REENTRANT -I/usr/include/freetype2 -DFF_API_MAX_STREAMS=0 -c -o command.o command.c
    In file included from command.c:24:0:
    config.h:106:23: warning: missing terminating ” character [enabled by default]
    config.h:107:1: warning: missing terminating ” character [enabled by default]
    config.h:107:1: error: missing terminating ” character
    In file included from stream/stream.h:22:0,
    from command.c:27:
    ./config.h:106:23: warning: missing terminating ” character [enabled by default]
    ./config.h:107:1: warning: missing terminating ” character [enabled by default]
    In file included from ./mp_msg.h:143:0,
    from stream/stream.h:24,
    from command.c:27:
    ./config.h:106:23: warning: missing terminating ” character [enabled by default]
    ./config.h:107:1: warning: missing terminating ” character [enabled by default]
    make: *** [command.o] Error 1

    It looks like an extra newline is in config.h after EXTERN_PREFEX, but if I remove it, I get:

    cc -MD -MP -Wundef -Wstrict-prototypes -Wmissing-prototypes -Wdisabled-optimization -Wno-pointer-sign -Wdeclaration-after-statement -std=gnu99 -O3 -march=atom -mtune=atom -mssse3 -mfpmath=sse -pipe -fexcess-precision=fast -floop-parallelize-all -flto -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE -Ilibdvdread4 -I. -Iffmpeg -O3 -march=atom -mtune=atom -mssse3 -mfpmath=sse -fomit-frame-pointer -pipe -D_REENTRANT -I/usr/include/ -D_REENTRANT -I/usr/include/freetype2 -DFF_API_MAX_STREAMS=0 -c -o libmpcodecs/vf_fspp.o libmpcodecs/vf_fspp.c
    libmpcodecs/vf_fspp.c: Assembler messages:
    libmpcodecs/vf_fspp.c:905: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_707106781′ after expression
    libmpcodecs/vf_fspp.c:910: Error: junk `C 0000000000000001 0000000000000001MM_2′ after expression
    libmpcodecs/vf_fspp.c:936: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_414213562_A’ after expression
    libmpcodecs/vf_fspp.c:952: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_382683433′ after expression
    libmpcodecs/vf_fspp.c:954: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_541196100′ after expression
    libmpcodecs/vf_fspp.c:956: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_306562965′ after expression
    libmpcodecs/vf_fspp.c:958: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_707106781′ after expression
    libmpcodecs/vf_fspp.c:1002: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_847759065′ after expression
    libmpcodecs/vf_fspp.c:1006: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_566454497′ after expression
    libmpcodecs/vf_fspp.c:1010: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_198912367′ after expression
    libmpcodecs/vf_fspp.c:1051: Error: junk `C 0000000000000001 0000000000000001MM_FIX_2_613125930′ after expression
    libmpcodecs/vf_fspp.c:1053: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_847759065′ after expression
    libmpcodecs/vf_fspp.c:1055: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_082392200′ after expression
    libmpcodecs/vf_fspp.c:1061: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_414213562′ after expression
    libmpcodecs/vf_fspp.c:1127: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_707106781′ after expression
    libmpcodecs/vf_fspp.c:1132: Error: junk `C 0000000000000001 0000000000000001MM_2′ after expression
    libmpcodecs/vf_fspp.c:1158: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_414213562_A’ after expression
    libmpcodecs/vf_fspp.c:1174: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_382683433′ after expression
    libmpcodecs/vf_fspp.c:1176: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_541196100′ after expression
    libmpcodecs/vf_fspp.c:1178: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_306562965′ after expression
    libmpcodecs/vf_fspp.c:1180: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_707106781′ after expression
    libmpcodecs/vf_fspp.c:1224: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_847759065′ after expression
    libmpcodecs/vf_fspp.c:1228: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_566454497′ after expression
    libmpcodecs/vf_fspp.c:1232: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_198912367′ after expression
    libmpcodecs/vf_fspp.c:1275: Error: junk `C 0000000000000001 0000000000000001MM_FIX_2_613125930′ after expression
    libmpcodecs/vf_fspp.c:1277: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_847759065′ after expression
    libmpcodecs/vf_fspp.c:1279: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_082392200′ after expression
    libmpcodecs/vf_fspp.c:1285: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_414213562′ after expression
    libmpcodecs/vf_fspp.c:1694: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_414213562_A’ after expression
    libmpcodecs/vf_fspp.c:1734: Error: junk `C 0000000000000001 0000000000000001MM_FIX_2_613125930′ after expression
    libmpcodecs/vf_fspp.c:1736: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_847759065′ after expression
    libmpcodecs/vf_fspp.c:1738: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_082392200′ after expression
    libmpcodecs/vf_fspp.c:1742: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_414213562′ after expression
    libmpcodecs/vf_fspp.c:1758: Error: junk `C 0000000000000001 0000000000000001MM_DESCALE_RND’ after expression
    libmpcodecs/vf_fspp.c:1986: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_707106781′ after expression
    libmpcodecs/vf_fspp.c:2014: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_707106781′ after expression
    libmpcodecs/vf_fspp.c:2018: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_541196100′ after expression
    libmpcodecs/vf_fspp.c:2020: Error: junk `C 0000000000000001 0000000000000001MM_FIX_0_382683433′ after expression
    libmpcodecs/vf_fspp.c:2022: Error: junk `C 0000000000000001 0000000000000001MM_FIX_1_306562965′ after expression
    make: *** [libmpcodecs/vf_fspp.o] Error 1
    #

  5. E.F | 21st July 2011 at 13:06 | Permalink

    I know this may not the proper place to ask for – but is there any bugzilla etc. for the crystalhd kernel driver? Googling around I wasn’t able to find any, nor I was able to post at Jarod Wilsons blog…

    I was not able to build the kernel module on my recent 2.6.39 kernel. This was not an issue with 2.6.38.

  6. Philip Langdale | 21st July 2011 at 17:42 | Permalink

    It doesn’t appear to be a serious error:

    https://bbs.archlinux.org/viewtopic.php?id=121682

  7. E.F | 22nd July 2011 at 03:26 | Permalink

    Many thanks for the hint! Replacing “-Werror” with “-Wno-error=implicit-function-declaration” in the Makefile solves the problem for me.

{ 2 } Trackbacks

  1. [...] wideo w MPlayer i FFmpeg przy użyciu adapterów Broadcom Crystal HD. Okazuje się, że programista dodał kolejne usprawnienia. Pojawiło się wsparcie dla dekodowania przez skalowanie ramek wideo, wsparcie dla pakowanych [...]

  2. [...] wideo w MPlayer i FFmpeg przy użyciu adapterów Broadcom Crystal HD. Okazuje się, że programista dodał kolejne usprawnienia. Pojawiło się wsparcie dla dekodowania przez skalowanie ramek wideo, wsparcie dla pakowanych [...]