All pastes #1947155 Raw Edit

Anonymous

public text v1 · immutable
#1947155 ·published 2010-09-23 07:02 UTC
rendered paste body
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 26445)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -126,6 +126,8 @@
 void render_slice_vdpau(struct AVCodecContext *s, const AVFrame *src,
                         int offset[4], int y, int type, int height);
 
+AVStream *videostream = NULL;
+
 static AVCodec *find_vdpau_decoder(AVCodec *c, enum CodecID id)
 {
     AVCodec *codec = c;
@@ -2969,6 +2971,8 @@
     AVFrame mpa_pic;
     avcodec_get_frame_defaults(&mpa_pic);
 
+    videostream = curstream;
+
     avcodeclock->lock();
     if (private_dec)
     {
@@ -3006,9 +3010,11 @@
 
     if (!gotpicture)
     {
+        gotvideo = 1;
         return true;
     }
 
+//START
     // Decode CEA-608 and CEA-708 captions
     for (uint i = 0; i < (uint)mpa_pic.atsc_cc_len;
     i += ((mpa_pic.atsc_cc_buf[i] & 0x1f) * 3) + 2)
@@ -3163,6 +3169,110 @@
     return true;
 }
 
+bool AvFormatDecoder::ProcessVideoFrame(AVStream *curstream, AVFrame *mpa_pic)
+{
+    int ret = 0, gotpicture = 0;
+    long long pts = 0;
+    AVCodecContext *context = curstream->codec;
+
+    // Decode CEA-608 and CEA-708 captions
+    for (uint i = 0; i < (uint)mpa_pic->atsc_cc_len;
+    i += ((mpa_pic->atsc_cc_buf[i] & 0x1f) * 3) + 2)
+    {
+        DecodeDTVCC(mpa_pic->atsc_cc_buf + i,
+                    mpa_pic->atsc_cc_len - i);
+    }
+
+    VideoFrame *picframe = (VideoFrame *)(mpa_pic->opaque);
+
+    if (!directrendering)
+    {
+        AVPicture tmppicture;
+
+        VideoFrame *xf = picframe;
+        picframe = GetPlayer()->GetNextVideoFrame(false);
+
+        unsigned char *buf = picframe->buf;
+        avpicture_fill(&tmppicture, buf, PIX_FMT_YUV420P, context->width,
+                       context->height);
+        tmppicture.data[0] = buf + picframe->offsets[0];
+        tmppicture.data[1] = buf + picframe->offsets[1];
+        tmppicture.data[2] = buf + picframe->offsets[2];
+        tmppicture.linesize[0] = picframe->pitches[0];
+        tmppicture.linesize[1] = picframe->pitches[1];
+        tmppicture.linesize[2] = picframe->pitches[2];
+
+        QSize dim = get_video_dim(*context);
+        sws_ctx = sws_getCachedContext(sws_ctx, context->width,
+                                       context->height, context->pix_fmt,
+                                       context->width, context->height,
+                                       PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
+                                       NULL, NULL, NULL);
+        if (!sws_ctx)
+        {
+            VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to allocate sws context");
+            return false;
+        }
+        sws_scale(sws_ctx, mpa_pic->data, mpa_pic->linesize, 0, dim.height(),
+                  tmppicture.data, tmppicture.linesize);
+
+
+        if (xf)
+        {
+            // Set the frame flags, but then discard it
+            // since we are not using it for display.
+            xf->interlaced_frame = mpa_pic->interlaced_frame;
+            xf->top_field_first = mpa_pic->top_field_first;
+            xf->frameNumber = framesPlayed;
+            GetPlayer()->DiscardVideoFrame(xf);
+        }
+    }
+    else if (!picframe)
+    {
+        VERBOSE(VB_IMPORTANT, LOC_ERR + "NULL videoframe - direct rendering not"
+                "correctly initialized.");
+        return false;
+    }
+
+    pts = (long long)(av_q2d(curstream->time_base) * mpa_pic->reordered_opaque * 1000);
+
+    long long temppts = pts;
+
+    // Validate the video pts against the last pts. If it's
+    // a little bit smaller, equal or missing, compute
+    // it from the last. Otherwise assume a wraparound.
+    if (!ringBuffer->isDVD() &&
+        temppts <= lastvpts &&
+        (temppts + 10000 > lastvpts || temppts <= 0))
+    {
+        temppts = lastvpts;
+        temppts += (long long)(1000 / fps);
+        // MPEG2/H264 frames can be repeated, update pts accordingly
+        temppts += (long long)(mpa_pic->repeat_pict * 500 / fps);
+    }
+
+    VERBOSE(VB_PLAYBACK+VB_TIMESTAMP, LOC +
+            QString("ProcessVideoFrame timecode %1 %2 %3").arg(mpa_pic->reordered_opaque).arg(temppts).arg(lastvpts));
+
+    picframe->interlaced_frame = mpa_pic->interlaced_frame;
+    picframe->top_field_first = mpa_pic->top_field_first;
+    picframe->repeat_pict = mpa_pic->repeat_pict;
+
+    picframe->frameNumber = framesPlayed;
+    GetPlayer()->ReleaseNextVideoFrame(picframe, temppts);
+    if (private_dec && mpa_pic->data[3])
+        context->release_buffer(context, mpa_pic);
+
+    decoded_video_frame = picframe;
+    gotvideo = 1;
+    framesPlayed++;
+
+    lastvpts = temppts;
+
+    return true;
+}
+
+
 /** \fn AvFormatDecoder::ProcessVBIDataPacket(const AVStream*, const AVPacket*)
  *  \brief Process ivtv proprietary embedded vertical blanking
  *         interval captions.
@@ -4075,8 +4185,21 @@
     {
         othresh =  ((ototal>>1) + (ototal>>2));
         allowedquit = ofill > othresh;
+        VERBOSE(VB_PLAYBACK,
+                LOC + QString("AudioBuffer Full ofill %1 ototal %2 othresh %3")
+                .arg(ofill).arg(ototal).arg(othresh));
     }
 
+    VERBOSE(VB_PLAYBACK, LOC + "GetFrame -- start");
+    if (private_dec && private_dec->HasBufferedFrames())
+    {
+        VERBOSE(VB_PLAYBACK, LOC + "Private Decoder has buffered frames available!");
+        AVFrame mpa_pic;   
+        avcodec_get_frame_defaults(&mpa_pic);
+        private_dec->GetBufferedFrame(videostream, &mpa_pic);
+        ProcessVideoFrame(videostream, &mpa_pic);
+    }
+//    allowedquit = false;
     while (!allowedquit)
     {
         if ((decodetype & kDecodeAudio) &&
Index: libs/libmythtv/privatedecoder_crystalhd.h
===================================================================
--- libs/libmythtv/privatedecoder_crystalhd.h	(revision 26445)
+++ libs/libmythtv/privatedecoder_crystalhd.h	(working copy)
@@ -17,6 +17,29 @@
 #include <libcrystalhd/libcrystalhd_if.h>
 #include "privatedecoder.h"
 
+class PrivateDecoderCrystalHD;
+class RetrievalThread : public QThread
+{
+    Q_OBJECT
+
+  public:
+    RetrievalThread(PrivateDecoderCrystalHD *dec)
+      : QThread(NULL), m_dec(dec) { }
+
+  protected:
+    virtual void run(void);
+
+  private:
+    PrivateDecoderCrystalHD *m_dec;
+};
+
+typedef struct PacketBuffer_
+{
+    uint8_t *buf;
+    int size;
+    int64_t pts;
+} PacketBuffer;
+
 enum BC_DEVICE_TYPE
 {
     BC_70012 = 0,
@@ -34,13 +57,17 @@
                       bool no_hardware_decode,
                       AVCodecContext *avctx);
     virtual bool Reset(void);
+    virtual bool HasBufferedFrames(void);
+    virtual int  GetBufferedFrame(AVStream *stream,
+                          AVFrame *picture);
     virtual int  GetFrame(AVStream *stream,
                           AVFrame *picture,
                           int *got_picture_ptr,
                           AVPacket *pkt);
-    void         RetrieveFrame(void);
+    void         RetrieveFrames(void);
 
   private:
+    bool StartRetrievalThread(void);
 
     bool CreateFilter(AVCodecContext *avctx);
     void FillFrame(BC_DTS_PROC_OUT *out);
@@ -53,7 +80,13 @@
     BC_DEVICE_TYPE     m_device_type;
     BC_OUTPUT_FORMAT   m_pix_fmt;
     QList<VideoFrame*> m_decoded_frames;
+    QList<PacketBuffer*> m_packet_buffers;
+    QMutex             m_decoded_frames_lock;
+    RetrievalThread   *m_retrieval_thread;
+    bool               m_pause_retrieval;
+    bool               m_kill_retrieval;
     VideoFrame        *m_frame;
+    PacketBuffer      *m_buffer;
     AVBitStreamFilterContext *m_filter;
 };
 
Index: libs/libmythtv/privatedecoder_crystalhd.cpp
===================================================================
--- libs/libmythtv/privatedecoder_crystalhd.cpp	(revision 26445)
+++ libs/libmythtv/privatedecoder_crystalhd.cpp	(working copy)
@@ -5,6 +5,16 @@
 #define ERR  QString("CrystalHD Err: ")
 #define WARN QString("CrystalHD Warn: ")
 
+void RetrievalThread::run(void)
+{
+    if (!m_dec)
+        return;
+
+    VERBOSE(VB_PLAYBACK, LOC + QString("Starting retrieval thread."));
+    m_dec->RetrieveFrames();
+    VERBOSE(VB_PLAYBACK, LOC + QString("Stopping retrieval thread."));
+}
+
 PixelFormat bcmpixfmt_to_pixfmt(BC_OUTPUT_FORMAT fmt);
 QString device_to_string(BC_DEVICE_TYPE device);
 QString bcmerr_to_string(BC_STATUS err);
@@ -31,12 +41,30 @@
 
 PrivateDecoderCrystalHD::PrivateDecoderCrystalHD()
   : m_device(NULL), m_device_type(BC_70012),
-    m_pix_fmt(OUTPUT_MODE_INVALID), m_frame(NULL), m_filter(NULL)
+    m_pix_fmt(OUTPUT_MODE_INVALID), m_decoded_frames_lock(QMutex::Recursive),
+    m_retrieval_thread(NULL), m_pause_retrieval(true), m_kill_retrieval(false),
+    m_frame(NULL), m_filter(NULL)
+
 {
 }
 
 PrivateDecoderCrystalHD::~PrivateDecoderCrystalHD()
 {
+    if (m_retrieval_thread)
+    {
+        m_pause_retrieval = true;
+        m_kill_retrieval = true;
+        int tries = 0;
+        while (!m_retrieval_thread->wait(100) && (tries++ < 50))
+            VERBOSE(VB_PLAYBACK, WARN + "Waited 100ms for retrieval to stop");
+
+        if (m_retrieval_thread->isRunning())
+            VERBOSE(VB_IMPORTANT, ERR + "Failed to stop retrieval.");
+        else
+            VERBOSE(VB_PLAYBACK, LOC + "Stopped frame retrieval.");
+        delete m_retrieval_thread;
+    }
+
     if (m_filter)
         av_bitstream_filter_close(m_filter);
 
@@ -64,7 +92,7 @@
     static bool debugged = false;
 
     uint32_t well_documented = DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW |
-                               DTS_SINGLE_THREADED_MODE | DTS_SKIP_TX_CHK_CPB |
+                               DTS_SKIP_TX_CHK_CPB |
                                DTS_PLAYBACK_DROP_RPT_MODE |
                                DTS_DFLT_RESOLUTION(vdecRESOLUTION_CUSTOM);
     INIT_ST
@@ -225,7 +253,7 @@
 
     BC_INPUT_FORMAT fmt;
     memset(&fmt, 0, sizeof(BC_INPUT_FORMAT));
-    fmt.OptFlags       = 0x80000000 | vdecFrameRateUnknown | 0x80;
+    fmt.OptFlags       = 0x80000000 | vdecFrameRateUnknown;// | 0x80;
     fmt.width          = avctx->coded_width;
     fmt.height         = avctx->coded_height;
     fmt.Progressive    = 1;
@@ -313,8 +341,22 @@
     }
 }
 
+void inline free_buffer(PacketBuffer* buffer)
+{
+    if (buffer)
+    {
+        if (buffer->buf)
+            delete [] buffer->buf;
+        delete buffer;
+    }
+}
+
 bool PrivateDecoderCrystalHD::Reset(void)
 {
+    // FIXME actually need to make sure this has stopped before continuing
+    m_pause_retrieval = true;
+
+    QMutexLocker lock(&m_decoded_frames_lock);
     free_frame(m_frame);
     m_frame = NULL;
 
@@ -322,6 +364,10 @@
         free_frame(m_decoded_frames[i]);
     m_decoded_frames.clear();
 
+    for (int i = 0; i < m_packet_buffers.size(); i++)
+        free_buffer(m_packet_buffers[i]);
+    m_packet_buffers.clear();
+
     if (!m_device)
         return true;
 
@@ -331,6 +377,42 @@
     return true;;
 }
 
+bool PrivateDecoderCrystalHD::HasBufferedFrames()
+{
+    return m_decoded_frames.size() > 0;
+}
+
+int PrivateDecoderCrystalHD::GetBufferedFrame(AVStream *stream,
+                                                  AVFrame *picture)
+{
+    AVCodecContext *avctx = stream->codec;
+    if (avctx->get_buffer(avctx, picture) < 0)
+    {
+        VERBOSE(VB_IMPORTANT, ERR +
+                QString("decoded frames available but no video buffers."));
+        return -1;
+    }
+
+    m_decoded_frames_lock.lock();
+    VideoFrame *frame = m_decoded_frames.takeLast();
+    m_decoded_frames_lock.unlock();
+
+    VERBOSE(VB_PLAYBACK, LOC +
+            QString("Output PTS timecode  (%1) external").arg(frame->timecode * av_q2d(stream->time_base)));
+    picture->reordered_opaque = (int64_t)(frame->timecode / 1000);
+    picture->interlaced_frame = frame->interlaced_frame;
+    picture->top_field_first  = frame->top_field_first;
+    picture->repeat_pict      = frame->repeat_pict;
+    copy((VideoFrame*)picture->opaque, frame);
+    if (frame->priv[0] && frame->qstride)
+    {
+        memcpy(picture->atsc_cc_buf, frame->priv[0], frame->qstride);
+        picture->atsc_cc_len = frame->qstride;
+    }
+    free_frame(frame);
+   return 0;
+}
+
 int PrivateDecoderCrystalHD::GetFrame(AVStream *stream,
                                       AVFrame *picture,
                                       int *got_picture_ptr,
@@ -344,8 +426,52 @@
     if (!avctx)
         return result;
 
-    uint8_t* buf    = pkt->data;
-    int size        = pkt->size;
+    if (!StartRetrievalThread())
+        return result;
+
+    m_buffer = new PacketBuffer();
+    m_buffer->buf  = new unsigned char[pkt->size];
+    m_buffer->size = pkt->size;
+    m_buffer->pts  = pkt->pts;
+    memcpy(m_buffer->buf, pkt->data, pkt->size);
+
+    if (!m_buffer)
+        return result;
+
+    m_packet_buffers.insert(0, m_buffer);
+    VERBOSE(VB_PLAYBACK, LOC +
+            QString("%1 packet buffers queued up").arg(m_packet_buffers.size()));
+    while (m_packet_buffers.size() > 0)
+    {
+    
+       BC_DTS_STATUS drv_status;
+       INIT_ST
+       st = DtsGetDriverStatus(m_device, &drv_status);
+       CHECK_ST
+
+    if (drv_status.cpbEmptySize < 100000) 
+    {
+        usleep(10000);
+        return 0;
+    }
+
+    PacketBuffer *buffer = m_packet_buffers.takeLast();
+
+//    while (m_packet_buffers.size() > 30 && DtsTxFreeSize(m_device) < buffer->size)
+//        usleep(10000);
+
+   
+//    if (DtsTxFreeSize(m_device) < buffer->size) 
+//    {
+//        m_packet_buffers.append(buffer);
+//        VERBOSE(VB_PLAYBACK, LOC +
+//                QString("Buffer full %1 packet buffers queued up").arg(m_packet_buffers.size()));
+//        usleep(10000);
+//        return 0;
+//    }
+
+    uint8_t* buf    = buffer->buf;
+    int size        = buffer->size;
     bool free_buf   = false;
     int outbuf_size = 0;
     uint8_t *outbuf = NULL;
@@ -374,43 +500,53 @@
 
     }
 
+    usleep(5000);
+    int64_t timecode = (int64_t)(av_q2d(stream->time_base) * buffer->pts * 1000);
     uint64_t chd_timestamp = 0; // msec units
-    if (pkt->pts != (int64_t)AV_NOPTS_VALUE)
-        chd_timestamp = (uint64_t)(av_q2d(stream->time_base) * pkt->pts * 1000);
-
+    if (buffer->pts != (int64_t)AV_NOPTS_VALUE)
+        chd_timestamp = (uint64_t)(buffer->pts * 1000);
+    VERBOSE(VB_PLAYBACK, LOC +
+            QString("Input PTS timecode (%1)").arg(timecode));
     // TODO check for busy state and available buffer size
-    INIT_ST
+    //INIT_ST
     st = DtsProcInput(m_device, buf, size, chd_timestamp, false);
     CHECK_ST
+    //CheckStatus();
 
-    // TODO why is this needed - possibly overruning CrystalHD decoder or too
-    // many buffered packets causing mythplayer problems?
-    usleep(10000);
-
     if (free_buf)
         delete buf;
 
+    free_buffer(buffer);
     if (!ok)
         VERBOSE(VB_IMPORTANT, ERR + "Failed to send packet to decoder.");
-    result = pkt->size;
+    result = buffer->size;
 
-    RetrieveFrame();
+    }
 
-    if (!m_decoded_frames.size())
+    m_decoded_frames_lock.lock();
+    int available = m_decoded_frames.size();
+    m_decoded_frames_lock.unlock();
+    if (!available)
+    {
         return result;
+    }
 
     if (avctx->get_buffer(avctx, picture) < 0)
     {
         VERBOSE(VB_IMPORTANT, ERR +
                 QString("%1 decoded frames available but no video buffers.")
-                .arg(m_decoded_frames.size()));
+                .arg(available));
         return -1;
     }
 
+    m_decoded_frames_lock.lock();
     VideoFrame *frame = m_decoded_frames.takeLast();
+    m_decoded_frames_lock.unlock();
+
+    VERBOSE(VB_PLAYBACK, LOC +
+            QString("Output PTS timecode (%1)").arg(frame->timecode * av_q2d(stream->time_base)));
     *got_picture_ptr = 1;
-    picture->reordered_opaque = (int64_t)(frame->timecode / av_q2d(stream->time_base) 
-                                                          / 1000);
+    picture->reordered_opaque = (int64_t)(frame->timecode / 1000);
     picture->interlaced_frame = frame->interlaced_frame;
     picture->top_field_first  = frame->top_field_first;
     picture->repeat_pict      = frame->repeat_pict;
@@ -424,40 +560,66 @@
     return result;
 }
 
-void PrivateDecoderCrystalHD::RetrieveFrame(void)
+void PrivateDecoderCrystalHD::RetrieveFrames(void)
 {
-    usleep(1000);
     INIT_ST
-    BC_DTS_STATUS status;
-    st = DtsGetDriverStatus(m_device, &status);
-    CHECK_ST
+    bool valid = false;
+    while (!m_kill_retrieval)
+    {
+        usleep(1000);
+        if (m_pause_retrieval)
+            continue;
 
-    if (!status.ReadyListCount)
-        return;
+        BC_DTS_STATUS status;
+        st = DtsGetDriverStatus(m_device, &status);
+        CHECK_ST
 
-    BC_DTS_PROC_OUT out;
-    memset(&out, 0, sizeof(BC_DTS_PROC_OUT));
-    st = DtsProcOutputNoCopy(m_device, 1, &out);
-    if (BC_STS_FMT_CHANGE == st)
-    {
-        VERBOSE(VB_IMPORTANT, LOC + "Decoder reported format change.");
-        CheckProcOutput(&out);
-        return;
-    }
-    CHECK_ST
+        if (!status.ReadyListCount)
+            continue;
 
-    if (!ok)
-    {
-        VERBOSE(VB_IMPORTANT, ERR + "Failed to retrieve decoded frame");
-        return;
+        BC_DTS_PROC_OUT out;
+        memset(&out, 0, sizeof(BC_DTS_PROC_OUT));
+        st = DtsProcOutputNoCopy(m_device, valid ? 2000 : 20, &out);
+
+        if (BC_STS_FMT_CHANGE == st)
+        {
+            VERBOSE(VB_IMPORTANT, LOC + "Decoder reported format change.");
+            CheckProcOutput(&out);
+            valid = true;
+            continue;
+        }
+        CHECK_ST
+
+        if (!ok)
+        {
+            VERBOSE(VB_IMPORTANT, ERR + "Failed to retrieve decoded frame");
+            continue;
+        }
+
+        //if (ok && valid && (out.PoutFlags & BC_POUT_FLAGS_PIB_VALID)&& out.PicInfo.timeStamp)
+        //if (ok && valid && (out.PoutFlags & BC_POUT_FLAGS_PIB_VALID))
+        if (ok && valid)
+            FillFrame(&out);
+        st = DtsReleaseOutputBuffs(m_device, NULL, false);
+        CHECK_ST
     }
+}
 
-    FillFrame(&out);
-    st = DtsReleaseOutputBuffs(m_device, NULL, false);
-    CHECK_ST
-    RetrieveFrame();
+bool PrivateDecoderCrystalHD::StartRetrievalThread(void)
+{
+    m_pause_retrieval = false;
+    if (m_retrieval_thread)
+        return true;
+
+    m_retrieval_thread = new RetrievalThread(this);
+    if (!m_retrieval_thread)
+        return false;
+
+    m_retrieval_thread->start();
+    return true;
 }
 
+
 void PrivateDecoderCrystalHD::FillFrame(BC_DTS_PROC_OUT *out)
 {
     bool second_field = false;
@@ -541,6 +703,7 @@
 void PrivateDecoderCrystalHD::AddFrameToQueue(void)
 {
     int i = 0;
+    m_decoded_frames_lock.lock();
 // TODO is the following code needed
 #if 0
     bool found = false;
@@ -555,7 +718,12 @@
     if (!found)
         i = m_decoded_frames.size();
 #endif
-    m_decoded_frames.insert(i, m_frame);
+    m_decoded_frames.insert(0, m_frame);
+    VERBOSE(VB_PLAYBACK, LOC + QString("Decoded frame queue size %1")
+            .arg(m_decoded_frames.size()));
+    VERBOSE(VB_PLAYBACK, LOC + QString("Inserting frame with timecode %1")
+            .arg(m_frame->timecode));
+    m_decoded_frames_lock.unlock();
     m_frame = NULL;
 }
 
Index: libs/libmythtv/privatedecoder.h
===================================================================
--- libs/libmythtv/privatedecoder.h	(revision 26445)
+++ libs/libmythtv/privatedecoder.h	(working copy)
@@ -17,6 +17,8 @@
     static PrivateDecoder* Create(const QString &decoder,
                                   bool no_hardware_decode,
                                   AVCodecContext *avctx);
+    virtual bool HasBufferedFrames(void) { return false; }
+    virtual int GetBufferedFrame(AVStream *stream, AVFrame *picture) { return 0; }
     PrivateDecoder() { }
     virtual ~PrivateDecoder() { }
     virtual QString GetName(void) = 0;
Index: libs/libmythtv/avformatdecoder.h
===================================================================
--- libs/libmythtv/avformatdecoder.h	(revision 26445)
+++ libs/libmythtv/avformatdecoder.h	(working copy)
@@ -203,6 +203,7 @@
     bool H264PreProcessPkt(AVStream *stream, AVPacket *pkt);
     bool PreProcessVideoPacket(AVStream *stream, AVPacket *pkt);
     bool ProcessVideoPacket(AVStream *stream, AVPacket *pkt);
+    bool ProcessVideoFrame(AVStream *stream, AVFrame *frame);
     bool ProcessAudioPacket(AVStream *stream, AVPacket *pkt,
                             DecodeType decodetype);
     bool ProcessSubtitlePacket(AVStream *stream, AVPacket *pkt);
Index: libs/libmyth/audiooutputalsa.cpp
===================================================================
--- libs/libmyth/audiooutputalsa.cpp	(revision 26420)
+++ libs/libmyth/audiooutputalsa.cpp	(working copy)
@@ -431,7 +431,9 @@
 
     while (frames > 0)
     {
+    VERBOSE(VB_AUDIO, QString("pcm_write_func -- start"));
         lw = pcm_write_func(pcm_handle, tmpbuf, frames);
+    VERBOSE(VB_AUDIO, QString("pcm_write_func -- end"));
 
         if (lw >= 0)
         {
Index: libs/libmyth/audiooutputbase.cpp
===================================================================
--- libs/libmyth/audiooutputbase.cpp	(revision 26420)
+++ libs/libmyth/audiooutputbase.cpp	(working copy)
@@ -21,6 +21,7 @@
 #define LOC QString("AO: ")
 #define LOC_ERR QString("AO, ERROR: ")
 
+#define AUDIOTSTESTING 1
 #define WPOS audiobuffer + org_waud
 #define RPOS audiobuffer + raud
 #define ABUF audiobuffer
@@ -1259,7 +1260,9 @@
 
             // only send zeros if card doesn't already have at least one
             // fragment of zeros -dag
+        VBAUDIOTS("WriteAudio Zeros Start");
             WriteAudio(zeros, fragment_size);
+        VBAUDIOTS("WriteAudio Zeros Done");
             continue;
         }
         else