Pause commflagging during playback

From MythTV Official Wiki
Revision as of 02:12, 15 October 2009 by Kkuphal (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

HOWTO: Pause commercial flagging during playback

I am using 8.10 Intrepid Mythbuntu. I have a combined frontend / backend system running on a Dell P4 3.0GHz single-processor box. I use an HDHomeRun for OTA capture. I know many people have reported the problem of having jerky playback while commercial flagging is running. This is especially true when watching HD content.

I was having this problem as well. I basically have one true HD station that broadcasts in 1080i. Anytime I watch content from this station and commercial flagging jobs are running, the playback is very jerky. The only way I could find to solve the problem was to pause the commercial flagging jobs. That is a little tedious to have to pause the jobs, then remember to turn them back on again when you are finished watching videos. More than once I've come back the next day to find dozens of jobs in the queue because I forgot to restart commercial flagging.

I have this same problem watching DVD content either direct from a DVD or watching content that I have ripped (or downloaded) to the videos directory.

Well, I finally got fed up enough with the problem to do something about it. I poked around and could not find anyone who had solved this problem so I set out to do it myself.

Here is the solution I came up with. I'm sure it is possible to do this more elegantly, but this method works and that's good enough for me at the moment.

First, I must give credit where credit is due. I could not have solved this problem nearly as quickly or easily without the fine information contained in this post: http://ubuntuforums.org/showthread.php?t=992706

I took this as a basis and made my own tool, pausecommflag, that is a derivative of this work. I strongly encourage you to read the above post to get some additional background before proceeding.

Overview

Here's the basic plan. We need to pause the commercial flagging processes when we are watching video and then resume them when we quit watching video. Seems simple enough and maybe, one day, this will be an option in Myth. For the moment, let's try to solve the problem from 'outside the box'.

How can we tell when we are watching video? One simple way is to look at the CPU utilization of the frontend process (mythfrontend.real) or the MPlayer program (mplayer). If the utilization is above a certain threshold (40% in my case) then we need to pause the commercial flagging jobs.

Next problem, how do we pause the commercial flagging jobs? Well, I'm sure there is some internal way to do it because the option is offered from the system status page. However, I was too lazy to figure that out, so I used the Linux STOP signal instead. The STOP signal does not kill the process, it just puts it to sleep.

Lastly, how do we resume the commercial flagging jobs we have paused? Since we put them to sleep by sending the STOP signal, we have to resume them with the CONT signal.

That all sounds simple enough. Now let's get down to brass tacks and build some code.

The Code

For most of the following steps you will need to be root in a terminal window. Instead of typing sudo in front of everything, I went the dangerous route and did sudo -s. I know that is "against the rules" but it sure was easier for me. Use at your own risk!

Daemon

First we need a daemon that will check the CPU usage every so often. I use the following code:

#!/bin/bash
# ==============================================================
# Limit MythCommFlag from running during video playback
# ==============================================================
# adapted from http://ubuntuforums.org/showthread.php?t=992706

# Variables
CPU_LIMIT=40        # Maximum playback CPU consumption before shutting down commercial flagging
DAEMON_INTERVAL=3   # Daemon check interval (seconds)

while sleep $DAEMON_INTERVAL
do
	# need to do the +0 trick to force there to be a value even when
	# MPLAYER or MYTHFRONTEND are not running
	(( MYTHFRONTEND=$(top -bn1 | gawk 'NR>6 && $12 ~ /mythfrontend/ {print $9}') + 0 ))
	(( MPLAYER=$(top -bn1 | gawk 'NR>6 && $12 ~ /mplayer/ {print $9}') + 0 ))
	
	if [ $MYTHFRONTEND -gt $CPU_LIMIT -o $MPLAYER -gt $CPU_LIMIT ]; then
		for i in $(top -b -n1 | gawk 'NR>6 && $12 ~ /mythcommflag/ && $9>0 {print $1}')         # Violating PIDs
		do
			# echo Sleeping $i
			kill -stop $i &   # sleep active commercial flagging
		done
	else
		# wake up sleeping commercial flagging operations
		for i in $(top -b -n1 | gawk 'NR>6 && $12 ~ /mythcommflag/ && $9<1 {print $1}')         # Sleeping PIDs
		do
			# echo Waking $i
			kill -cont $i &   # wake sleeping commercial flagging
		done	
	fi
done

Save the code above into /root/pausecommflag_daemon.sh.

Make sure this script is owned by root and that it is executable. Do the following steps in a terminal window:

chown root:root /root/pausecommflag_daemon.sh
chmod 755 /root/pausecommflag_daemon.sh

Service

Now that the daemon taken care of we need a way to run it as a service. So, copy the following code into /etc/init.d/pausecommflag.

#!/bin/sh
#
# Script to start CPU limit daemon
#
set -e
. /lib/lsb/init-functions
case "$1" in
start)
nohup /root/pausecommflag_daemon.sh &
;;
stop)
ps -eo pid,args | gawk '$3=="/root/pausecommflag_daemon.sh"  {print $1}' | xargs kill   # kill daemon
killall -s CONT mythcommflag	# resume any paused commercial flagging
;;
restart)
ps -eo pid,args | gawk '$3=="/root/pausecommflag_daemon.sh"  {print $1}' | xargs kill   # kill daemon
killall -s CONT mythcommflag	# resume any paused commercial flagging
sleep 5
/root/pausecommflag_daemon.sh &
;;
status)
ps -eo pid,args | gawk '$3=="/root/pausecommflag_daemon.sh"  {print}' | wc -l | gawk '{ if ($1 == 1) print " * pausecommflag daemon is running"; else print " * pausecommflag daemon is NOT running" }'
;;
esac
exit 0

You need to make sure this is owned by root and executable as well. Do the same steps as before in a terminal window:

chown root:root /etc/init.d/pausecommflag
chmod 755 /etc/init.d/pausecommflag).

Installation

Now install your new daemon as a service (again, in a terminal window):

cd /etc/init.d
update-rc.d pausecommflag defaults

At this point you can reboot if you want. The service should start automatically. However, you can just start it manually now and all should be well.

cd /etc/init.d
service pausecommflag start

Testing

You can check that everything is working correctly by running top in a terminal (I connect in from another machine via SSH) and seeing that the commercial flagging jobs (mythcommflag) are running (obviously you have to be flagging something currently). Then start watching a video and within a few seconds (3 seconds by default) you should see the commercial flagging jobs disappear from the list (actually they move to near the bottom of the list with no CPU cycles allocated to them). They should reappear at the top of the list within a few seconds after you stop watching video.

Note that being on the Watch Recordings screen (the one with the two-pane list, programs and categories on the left, individual episodes on the right) will still pause commercial flagging. The 'preview' video in the bottom right corner uses enough cycles to cause commercial flagging to pause (at least on my system). Consequently, if you leave Myth on this screen, your commercial flagging jobs will pile up and not get done. If you don't like this behavior, you need to change the CPU_LIMIT value to something above the usage while on the Watch Recordings screen but well below the value when actually watching a video full screen.

You can do the same test with MPlayer by watching some video content other than recorded programs. Either go to Media Library | Watch Videos or just watch a DVD. You should see the commercial flagging jobs disappear from the top of the list when you start the video and then reappear when you stop watching.

Configuration

Depending on your processor and other factors you may need to adjust the two variables at the top of the daemon script (/root/pausecommflag_daemon.sh). The CPU_LIMIT determines what percentage of the CPU the front end process must use before it kills the commercial flagging. If the front end is above this percentage, commercial flagging is turned off (paused), if it is below this percentage, commercial flagging is resumed.

The DAEMON_INTERVAL determines how often the system checks to see if it needs to pause or resume commercial flagging. You can increase this delay if you want it to check less often. I would not suggest making it much shorter than the default of 3 seconds for performance reasons.

Conclusion

I hope you find this tool useful. I am certainly open to suggestions for improvement. If someone wants to figure out how and/or build a tool to pause and resume commercial flagging using the existing Myth messaging system, that would probably be better.