Log in

View Full Version : Can't get x264 decoding multithreaded


paul0272
21st November 2007, 21:45
I know I'm probably asking something really basic that's been addressed many times, but please forgive me, I've looked hard for a solution and I'm still stumped.

Athlon64 X2 5200
2GB RAM
Asus Crosshair M/B
Windows XP Home SP2

I'm trying to play back 1920x1080 x264 video. Most of the time it's OK, but whenever the video gets "busy" the picture gets very choppy. Task manager reveals that only one of the CPU cores is being used. Most of the time it's using about 70-80% of one CPU but in fast or detailed scenes one CPU hits 100% while the other is doing practically nothing.

Tried VLC media player to start with. Results as above. Moved onto ffdshow-tryouts and Haali media splitter with MPC, which seems to be more efficient as it has lower CPU usage, but still only uses one CPU core and still maxes out in more demanding scenes. Bought CoreAVC Professional which does seem to use both CPUs equally, but only uses about 10-20% overall CPU and only renders about one frame a second.

Any pointers gratefully received :thanks:

nm
21st November 2007, 22:02
Both VLC and ffdshow use libavcodec's H.264 decoder, which is effectively single-threaded in case of most x264 encodings. There is a patch (http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/2007-September/035877.html) that splits CABAC decoding to a separate thread, but you'll need to do some digging to find ffdshow builds that have it. Frame-based multi-threading probably comes up at some point, but it's not there yet.

So, CoreAVC is your best bet for now, if you figure out what is wrong with your software setup (have you tried other players than MPC?).

LoRd_MuldeR
21st November 2007, 23:08
1. x264 is a piece of software, not a video format
2. the video format produced by x264 is called "H.264" (aka "AVC")
3. x264 is an encoder, it is not a decoder (hence x264 can not be used for playback!)
4. The common H.264 Decoder used in OpenSource software (VLC, MPlayer, ffdshow, etc.) is the one from ffmpeg/libavcodec
5. ffmpeg/libavcodec's H.264 decoder is not multi-threaded yet, except for sliced H.264 streams (rare)
6. x264 already is multi-threaded since ages, but only for encoding

skontel
22nd November 2007, 00:38
...
5. ffmpeg/libavcodec's H.264 decoder is not multi-threaded yet, except for sliced H.264 streams (rare)
...


I've recently obtained some fairly high bit rate 1080p H.264 content. My Core Duo 1.83 GHz would not decode it (using mplayer/libavcodec) smoothly, nor would my Core 2 Duo 2.0 GHz system. Not even my Core 2 Duo 2.33 GHz system would decode it without severely dropping frames. And while I'm not sure if the content is sliced or not, using

lavdopts=threads=4

Inside my

~/.mplayer/config

file made all systems decode the content just fine. The man page for mplayer specifically lists this as one of the libavcodec decoding options. Maybe the man page is out of date? I don't know, but I do know that this option did not produce an error (i.e. it was recognized), and it greatly improved the decoding performance.

An aside note: while I initially used threads=2, that was not sufficient to smoothly decode the content. Using threads=4 did make a difference. Methinks a single thread on a core does not fully tax the core, thus making more than one thread per core useful. I wonder if anyone did any benchmarking on this...

Hope this helps...

LoRd_MuldeR
22nd November 2007, 01:49
An aside note: while I initially used threads=2, that was not sufficient to smoothly decode the content. Using threads=4 did make a difference. Methinks a single thread on a core does not fully tax the core, thus making more than one thread per core useful. I wonder if anyone did any benchmarking on this...
That completely depends on the individual implementation! If you distribute the work among several threads, all those threads can (theoretically) run concurrently. So in theory n threads should be enough to get 100% load on a system with n processors/cores. BUT: This is only true, if all those threads always have work to do. Furthermore it would assume that none of those threads ever has to wait for another thread. This of course is unrealistic! Hence while in a perfect world n threads could get maximum load on n cores, this won't be the case with real-life software. Using even more threads than cores might improve the performance, but only if the implementation allows that! Simply adding more threads does not help at all! You also need to give some work to those additional threads - work that can be done concurrently to the existing threads!

If we look at x264's current multi-threading implementation, then it seems to require 4/3 * n threads to get full load on n cores. Also x264 seems to scale very well: Even on a systems with 8 cores it can achieve 100% load. But again: This is one specific implementation! It does not necessarily apply to other multi-threading implementations. Things are much more complex. You always have to consider how the work can (or can not) be distributed among different threads. And most important: You have to find and separate tasks, that can be done concurrently.

The current implementation of ffmpeg/libavcodec's H.264 decoder is based on Slices. Hence if the video was not encoded with slices, then that multi-threading method won't work at all! Adding more threads won't help here, since there would be nothing those threads could do concurrently! If the video was encoded with slices, then multi-threading can be used for playback: With n slices you could get full load on a maximum of n cores. But there obviously is no way to scale any further! So this method is pretty limited: Only works with slices + doesn't scale.

As far as I know, the new patch (not released yet!) works with all H.264 files (no slices needed). It works by separating the CABAC decoding from the rest of the work. Hence it will use two threads and it seems to give ~30% speed-up on a Dualcore. But: More then two threads won't help with that "new" method. So it's still not the perfect way: Works with all videos, but doesn't scale! Maybe we will see frame-based multi-threading (similar to x264's method) for the H.264 decoder some day. This could work with all H.264 videos and might scale much better than the two previous methods. But nobody can guarantee yet. Maybe they will even have to mix different methods, if that is possible at all...

burfadel
22nd November 2007, 02:29
Have you tried the Queue option in ffdshow? and playback using mpc? (make sure its a recent copy). No reason why you shouldn't be able to play 1920x1080 with that combination.

skontel
22nd November 2007, 07:47
That completely depends on the individual implementation!
[snip]


I feel that I sufficiently understand encoding/decoding, threads, how their use can scale up, and how that affects multiple cores. And I agree with your comments. I didn't mean to imply otherwise.

My only point was that I have found something that has helped me decode 1080p with the current mplayer/libavcodec. The man had asked if threads can be used to speed up decoding, and I thought I'd share what I had found. I have no reason to suspect that the content I've tested is sliced, though it could very well be. The bottom line is this: paul0272 may find that the option I mentioned helps him decode his content more smoothly. If it doesn't, he's certainly no worse off.

paul0272
22nd November 2007, 22:07
Thanks for all the info. I really had got the wrong end of the stick. The thing that was confusing me was the explicit assertion in the ffdshow documentation that "x264 is multithreaded" - I thought I must just be missing some crucial setting. Now that I understand what x264 is (and what it isn't!) I see that it's the encoding that's multithreaded.

I went back to CoreAVC and tried adjusting its settings. There was an option labelled "Aggressive Deinterlacing" which was selected by default, so I deselected it and now it seems to play everything without any problems (and with plenty of CPU to spare!).

Thanks again for all the help.

skontel
29th November 2007, 02:58
[snip]

As far as I know, the new patch (not released yet!) works with all H.264 files (no slices needed). It works by separating the CABAC decoding from the rest of the work. Hence it will use two threads and it seems to give ~30% speed-up on a Dualcore. But: More then two threads won't help with that "new" method. So it's still not the perfect way: Works with all videos, but doesn't scale! Maybe we will see frame-based multi-threading (similar to x264's method) for the H.264 decoder some day. This could work with all H.264 videos and might scale much better than the two previous methods. But nobody can guarantee yet. Maybe they will even have to mix different methods, if that is possible at all...



LoRd MuldeR, I forgot to ask: is there any chance I can get my hands on this patch? I would love to give it a test and see how it behaves. Though you did not specify in your message, I'm assuming you are talking about a patch to libavcodec. Is that indeed the case?

:thanks:

nm
29th November 2007, 09:25
I forgot to ask: is there any chance I can get my hands on this patch?
Take a look at my first post to this thread.

LoRd_MuldeR
29th November 2007, 11:37
LoRd MuldeR, I forgot to ask: is there any chance I can get my hands on this patch? I would love to give it a test and see how it behaves. Though you did not specify in your message, I'm assuming you are talking about a patch to libavcodec. Is that indeed the case?

:thanks:
Of course it's a patch to libavcodec, because all that was referring to the ffmpeg/libavcodec H.264 decoder.

Have a look at this post:
http://forum.doom9.org/showpost.php?p=1065096&postcount=2418

Patch information + Link to the patch + ffdshow with patched decoder ;)