[rbp] Fix for audio out of sync part 2
authorpopcornmix <popcornmix@gmail.com>
Tue, 15 Jan 2013 20:46:07 +0000 (20:46 +0000)
committerpopcornmix <popcornmix@gmail.com>
Tue, 15 Jan 2013 20:46:07 +0000 (20:46 +0000)
xbmc/cores/omxplayer/OMXAudio.cpp
xbmc/cores/omxplayer/OMXVideo.cpp
xbmc/cores/omxplayer/OMXVideo.h

index 5399b10..1b2a1ef 100644 (file)
@@ -805,6 +805,8 @@ unsigned int COMXAudio::AddPackets(const void* data, unsigned int len, double dt
     if(m_av_clock->AudioStart())
     {
       omx_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME;
+      if(pts == DVD_NOPTS_VALUE)
+        omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
 
       m_last_pts = pts;
 
index b11aa22..0464790 100644 (file)
@@ -84,7 +84,6 @@ COMXVideo::COMXVideo()
   m_deinterlace       = false;
   m_hdmi_clock_sync   = false;
   m_first_frame       = true;
-  m_contains_valid_pts= false;
 }
 
 COMXVideo::~COMXVideo()
@@ -666,6 +665,9 @@ bool COMXVideo::Open(CDVDStreamInfo &hints, OMXClock *clock, bool deinterlace, b
     m_deinterlace, m_hdmi_clock_sync);
 
   m_first_frame   = true;
+  // start from assuming all recent frames had valid pts
+  m_history_valid_pts = ~0;
+
   return true;
 }
 
@@ -720,6 +722,14 @@ unsigned int COMXVideo::GetSize()
   return m_omx_decoder.GetInputBufferSize();
 }
 
+static unsigned count_bits(int32_t value)
+{
+  unsigned bits = 0;
+  for(;value;++bits)
+    value &= value - 1;
+  return bits;
+}
+
 int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
 {
   OMX_ERRORTYPE omx_err;
@@ -754,11 +764,11 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
 
       omx_buffer->nFlags = 0;
       omx_buffer->nOffset = 0;
-
-      // if a stream contains any pts values, then use those with UNKNOWNs. Otherwise try using dts.
-      if(pts != DVD_NOPTS_VALUE)
-        m_contains_valid_pts = true;
-      if(pts == DVD_NOPTS_VALUE && !m_contains_valid_pts)
+      // some packed bitstream AVI files set almost all pts values to DVD_NOPTS_VALUE, but have a scattering of real pts values.
+      // the valid pts values match the dts values.
+      // if a stream has had more than 4 valid pts values in the last 16, the use UNKNOWN, otherwise use dts
+      m_history_valid_pts = (m_history_valid_pts << 1) | (pts != DVD_NOPTS_VALUE);
+      if(pts == DVD_NOPTS_VALUE && count_bits(m_history_valid_pts & 0xffff) < 4)
         pts = dts;
 
       if(m_av_clock->VideoStart())
@@ -766,6 +776,8 @@ int COMXVideo::Decode(uint8_t *pData, int iSize, double dts, double pts)
         // only send dts on first frame to get nearly correct starttime
         if(pts == DVD_NOPTS_VALUE)
           pts = dts;
+        if(pts == DVD_NOPTS_VALUE)
+          omx_buffer->nFlags |= OMX_BUFFERFLAG_TIME_UNKNOWN;
         omx_buffer->nFlags = OMX_BUFFERFLAG_STARTTIME;
         CLog::Log(LOGDEBUG, "OMXVideo::Decode VDec : setStartTime %f\n", (pts == DVD_NOPTS_VALUE ? 0.0 : pts) / DVD_TIME_BASE);
         m_av_clock->VideoStart(false);
index 24cc6c8..180c2db 100644 (file)
@@ -90,7 +90,7 @@ protected:
   bool              m_deinterlace;
   bool              m_hdmi_clock_sync;
   bool              m_first_frame;
-  bool              m_contains_valid_pts;
+  uint32_t          m_history_valid_pts;
 
   bool NaluFormatStartCodes(enum CodecID codec, uint8_t *in_extradata, int in_extrasize);
 };