Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 13799)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -24,6 +24,7 @@
 #include "cc708decoder.h"
 #include "interactivetv.h"
 #include "DVDRingBuffer.h"
+#include "audiooutputbase.h"
 
 #ifdef USING_XVMC
 #include "videoout_xv.h"
@@ -2681,6 +2682,7 @@
     }
 }
 
+// documented in decoderbase.h
 bool AvFormatDecoder::GetFrame(int onlyvideo)
 {
     AVPacket *pkt = NULL;
@@ -2704,13 +2706,71 @@
 
     bool skipaudio = (lastvpts == 0);
 
+    bool has_video = true;
+    if (ic->cur_pmt_sect)
+    {
+        const PESPacket pes = PESPacket::ViewData(ic->cur_pmt_sect);
+        const PSIPTable psip(pes);
+        const ProgramMapTable pmt(psip);
+
+        has_video = false;
+        for (uint i = 0; i < pmt.StreamCount(); i++)
+        {
+            // MythTV remaps OpenCable Video to normal video during recording
+            // so "dvb" is the safest choice for system info type, since this
+            // will ignore other uses of the same stream id in DVB countries.
+            has_video |= pmt.IsVideo(i, "dvb");
+        }
+    }
+
+    //cerr<<"GetFrame("<<onlyvideo<<") has_video: "<<has_video;
+
+    if (!has_video && (onlyvideo >= 0))
+    {
+        VideoFrame *frame = GetNVP()->GetNextVideoFrame(true);
+        if (frame)
+        {
+            clear(frame, GUID_YV12_PLANAR);
+            unsigned int ysize  = frame->width * frame->height;
+            for (uint i = 0; i < ysize; i++)
+            {
+                *(frame->buf + frame->offsets[0] + i) =
+                    (framesPlayed+i) & 0xff;
+            }
+
+            frame->interlaced_frame = 0; // not interlaced
+            frame->top_field_first  = 1; // top field first
+            frame->repeat_pict      = 0; // not a repeated picture
+            frame->frameNumber = framesPlayed;
+
+            GetNVP()->ReleaseNextVideoFrame(frame, lastvpts);
+
+            if (GetNVP()->getVideoOutput())
+            {
+                GetNVP()->getVideoOutput()->DeLimboFrame(frame);
+                if (!GetNVP()->getVideoOutput()->EnoughPrebufferedFrames())
+                    allowedquit = true;
+            }
+
+            decoded_video_frame = frame;
+            gotvideo = 1;
+            framesPlayed++;
+        }
+        onlyvideo = -1;
+        skipaudio = false;
+    }
+
+    uint deadmancounter = 0;
+
     while (!allowedquit)
     {
-        if ((onlyvideo == 0) &&
+        //cerr<<".";
+        if ((onlyvideo == 0) && has_video &&
             ((currentTrack[kTrackTypeAudio] < 0) ||
              (selectedTrack[kTrackTypeAudio].av_stream_index < 0)))
         {
             // disable audio request if there are no audio streams anymore
+            cerr<<"disabling audio";
             onlyvideo = 1;
         }
 
@@ -2780,8 +2840,9 @@
                 //cout << "behind: " << lastapts << " " << lastvpts << endl;
                 storevideoframes = true;
             }
-            else
+            else if (onlyvideo >= 0)
             {
+                //cerr<<"got video -- set allowedquit"<<endl;
                 allowedquit = true;
                 continue;
             }
@@ -3013,6 +3074,8 @@
             {
                 case CODEC_TYPE_AUDIO:
                 {
+                    deadmancounter++;
+
                     bool reselectAudioTrack = false;
 
                     // detect switches between stereo and dual languages
@@ -3056,7 +3119,7 @@
                         lastapts = (long long)(av_q2d(curstream->time_base) *
                                                pkt->pts * 1000);
 
-                    if (onlyvideo != 0 || (pkt->stream_index != audIdx))
+                    if ((onlyvideo > 0) || (pkt->stream_index != audIdx))
                     {
                         ptr += len;
                         len = 0;
@@ -3142,6 +3205,26 @@
                     GetNVP()->AddAudioData((char *)audioSamples, data_size,
                                            temppts);
 
+                    AudioOutputBase *audio = dynamic_cast<AudioOutputBase*>
+                        (GetNVP()->getAudioOutput());
+
+                    if ((onlyvideo < 0) &&
+                        (!audio ||
+                         ((audio->getBufferedOnSoundcard() == 0) ||
+                          (audio->getSpaceOnSoundcard() <
+                           audio->getBufferedOnSoundcard()))))
+                    {
+                        allowedquit = (onlyvideo < 0);
+                        //if (onlyvideo < 0)
+                        //    cerr<<"audio -- set allowedquit"<<endl;
+                    }
+
+                    if ((onlyvideo < 0) && deadmancounter > 10)
+                    {
+                        cerr<<"BUG: dead man counter triggered"<<endl;
+                        allowedquit = true;
+                    }
+
                     if (ringBuffer->InDVDMenuOrStillFrame())
                         allowedquit = true;
 
@@ -3395,6 +3478,7 @@
     if (pkt)
         delete pkt;
 
+    //cerr<<endl;
     return true;
 }
 
Index: libs/libmythtv/decoderbase.h
===================================================================
--- libs/libmythtv/decoderbase.h	(revision 13799)
+++ libs/libmythtv/decoderbase.h	(working copy)
@@ -70,6 +70,9 @@
     virtual void SetDisablePassThrough(bool disable) { (void)disable; }
 
     virtual void setWatchingRecording(bool mode);
+    /// Decode a frame of video/audio. If onlyvideo is +1,
+    /// decodes the video portion, if it is -1 only decodes
+    /// the audio portion, if it is 0 it decodes audio and video
     virtual bool GetFrame(int onlyvideo) = 0;
     NuppelVideoPlayer *GetNVP() { return m_parent; }
     
Index: libs/libmythtv/libmythtv.pro
===================================================================
--- libs/libmythtv/libmythtv.pro	(revision 13799)
+++ libs/libmythtv/libmythtv.pro	(working copy)
@@ -14,6 +14,7 @@
 INCLUDEPATH += ../libmythlivemedia/groupsock/include
 INCLUDEPATH += ../libmythlivemedia/liveMedia/include
 INCLUDEPATH += ../libmythlivemedia/UsageEnvironment/include
+INCLUDEPATH += ../libmythsoundtouch
 
 DEPENDPATH  += ../libmyth ../libavcodec ../libavformat ../libavutil
 DEPENDPATH  += ../libmythmpeg2 ../libmythdvdnav
Index: libs/libmythtv/hdhrrecorder.cpp
===================================================================
--- libs/libmythtv/hdhrrecorder.cpp	(revision 13799)
+++ libs/libmythtv/hdhrrecorder.cpp	(working copy)
@@ -273,6 +273,13 @@
         if (tspacket.HasPayload())
         {
             const unsigned int lpid = tspacket.PID();
+
+            if ((GetStreamData()->VideoPIDSingleProgram() == 0xffffffff) &&
+                _wait_for_keyframe_option)
+            {
+                _wait_for_keyframe_option = false;
+            }
+
             // Pass or reject frames based on PID, and parse info from them
             if (lpid == GetStreamData()->VideoPIDSingleProgram())
             {
Index: libs/libmythtv/mpeg/mpegstreamdata.cpp
===================================================================
--- libs/libmythtv/mpeg/mpegstreamdata.cpp	(revision 13799)
+++ libs/libmythtv/mpeg/mpegstreamdata.cpp	(working copy)
@@ -15,6 +15,8 @@
 #include "atscstreamdata.h"
 #include "atsctables.h"
 
+#define DEBUG_MPEG_RADIO // uncomment to strip video streams from TS stream
+
 void init_sections(sections_t &sect, uint last_section)
 {
     static const unsigned char init_bits[8] =
@@ -554,7 +556,12 @@
             audioPIDs.push_back(pid);
         }
 
+#ifdef DEBUG_MPEG_RADIO
         if (is_video)
+            continue;
+#endif // DEBUG_MPEG_RADIO
+
+        if (is_video)
         {
             video_cnt++;
             videoPIDs.push_back(pid);
Index: libs/libmythtv/avformatdecoder.h
===================================================================
--- libs/libmythtv/avformatdecoder.h	(revision 13799)
+++ libs/libmythtv/avformatdecoder.h	(working copy)
@@ -94,8 +94,6 @@
                  char testbuf[kDecoderProbeBufferSize],
                  int testbufsize = kDecoderProbeBufferSize);
 
-    /// Decode a frame of video/audio. If onlyvideo is set, 
-    /// just decode the video portion.
     bool GetFrame(int onlyvideo);
 
     bool isLastFrameKey(void) { return false; }
Index: libs/libmyth/audiooutputbase.h
===================================================================
--- libs/libmyth/audiooutputbase.h	(revision 13799)
+++ libs/libmyth/audiooutputbase.h	(working copy)
@@ -77,6 +77,7 @@
     virtual bool OpenDevice(void) = 0;
     virtual void CloseDevice(void) = 0;
     virtual void WriteAudio(unsigned char *aubuf, int size) = 0;
+  public:
     virtual int getSpaceOnSoundcard(void) = 0;
     virtual int getBufferedOnSoundcard(void) = 0;
     virtual int GetVolumeChannel(int channel) = 0; // Returns 0-100
