All pastes #1947020 Raw Edit

Unnamed

public text v1 · immutable
#1947020 ·published 2010-09-23 01:53 UTC
rendered paste body
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
--- libs/libmythtv/avformatdecoder.cpp	(revision 26445)
+++ libs/libmythtv/avformatdecoder.cpp	(working copy)
@@ -4075,8 +4075,12 @@
     {
         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));
     }
 
+//    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,
@@ -38,9 +61,10 @@
                           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 +77,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;
 
@@ -344,8 +390,47 @@
     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);
+    //PacketBuffer *buffer = m_packet_buffers.takeLast();
+    //if (DtsTxFreeSize(m_device) > buffer->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 < 300000) 
+    {
+        usleep(10000);
+        continue;
+    }
+
+
+    PacketBuffer *buffer = m_packet_buffers.takeLast();
+   
+//    if (DtsTxFreeSize(m_device) < buffer->size) 
+//    {
+//        m_packet_buffers.insert(0, buffer);
+//        usleep(10000);
+//        continue;
+//    }
+
+    uint8_t* buf    = buffer->buf;
+    int size        = buffer->size;
     bool free_buf   = false;
     int outbuf_size = 0;
     uint8_t *outbuf = NULL;
@@ -374,43 +459,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 +519,65 @@
     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))
+            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 +661,7 @@
 void PrivateDecoderCrystalHD::AddFrameToQueue(void)
 {
     int i = 0;
+    m_decoded_frames_lock.lock();
 // TODO is the following code needed
 #if 0
     bool found = false;
@@ -556,6 +677,9 @@
         i = m_decoded_frames.size();
 #endif
     m_decoded_frames.insert(i, m_frame);
+    VERBOSE(VB_PLAYBACK, LOC + QString("Decoded frame queue size %1")
+            .arg(m_decoded_frames.size()));
+    m_decoded_frames_lock.unlock();
     m_frame = NULL;
 }