Thursday, January 12, 2012

Stuttering Video Playback Due To USB Device Reset

My kids don't usually complain when they're watching a movie on my PC, if video playback stutters. It seems that as long as playback resumes in a second or less, they don't mind the interruptions. I guess they've learned that if they do complain, chances are that they'll have to wait several long minutes, until their OCD inflicted dad "fixes" the problem.

I hate it when video playback stutters. So much so that I usually first download whatever video I want to watch and then watch it offline. Which is why I am a get-flash-videos fanboy.

But last time we were hit with such a problem, our lame ISP was not the culprit. This time, the video source was a backup ISO image of some DVD, stored on an external hard disk, connected to a Debian box (my old, headless laptop) over USB, accessed via SAMBA over a wireless connection, and played back on my WinXP laptop. The hiccups were rather noticeable, even by my lag-tolerant kids, to the point that they complained about it.

At first, it seemed that debugging this would be a daunting task - there are just so many factors involved. But I got lucky - I tried playing that same DVD image on my wife's laptop, over a wired network connection, and was hit by the same playback hiccups. This ruled out most of the suspects except for my old Debian laptop.

And yet, I had no idea what to look for now, especially because I can't just playback video on my old laptop - it's screen is busted... So I just browsed for any suspicious message in the output of dmesg - and found the following message, repeated several times:
"reset high speed USB device using ehci_hcd and address 3"

These messages seemed very relevant, and a quick search brought me to several blog posts, forum threads and bug reports.
I tried one the solutions/workarounds suggested on those links:
echo 128 > /sys/block/sdc/device/max_sectors
and it actually did the trick and made the hiccups go away.

The next challenge was to make this happen on system start-up. The Right Thing™ to do would have been to modify /etc/sysctl.conf, but there's always the chance that the relevant block device would be renamed, e.g. when another external disk drive is attached. So I ended up adding the following line line to /etc/init.d/bootmisc.sh:
echo 128 > /sys/block/$(readlink -f /dev/data | sed -e 's/1//g' -e 's/\/dev\///g')/device/max_sectors
where /dev/data is a symbolic link that points to this block device, which is generated with an appropriate UDEV rule.

No comments:

Post a Comment