Advertisement
Guest User

AML-Clock timing adjust

a guest
Dec 28th, 2016
574
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 47.24 KB | None | 0 0
  1. diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp
  2. index c38c223..b91ed02 100644
  3. --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp
  4. +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp
  5. @@ -26,6 +26,7 @@
  6.  #include "cores/VideoPlayer/DVDClock.h"
  7.  #include "cores/VideoPlayer/VideoRenderers/RenderFlags.h"
  8.  #include "cores/VideoPlayer/VideoRenderers/RenderManager.h"
  9. +#include "settings/AdvancedSettings.h"
  10.  #include "guilib/GraphicContext.h"
  11.  #include "settings/DisplaySettings.h"
  12.  #include "settings/MediaSettings.h"
  13. @@ -41,19 +42,15 @@
  14.  #include "utils/BitstreamConverter.h"
  15.  #endif
  16.  
  17. -extern "C" {
  18. -#include "libavutil/avutil.h"
  19. -}  // extern "C"
  20. -
  21.  #include <unistd.h>
  22.  #include <queue>
  23.  #include <vector>
  24.  #include <signal.h>
  25. -#include <semaphore.h>
  26.  #include <fcntl.h>
  27.  #include <stdio.h>
  28.  #include <stdlib.h>
  29.  #include <sys/ioctl.h>
  30. +#include <sys/utsname.h>
  31.  #include <linux/videodev2.h>
  32.  
  33.  // amcodec include
  34. @@ -133,6 +130,11 @@ public:
  35.    virtual int codec_set_cntl_mode(codec_para_t *pcodec, unsigned int mode)=0;
  36.    virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int avthresh)=0;
  37.    virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0;
  38. +
  39. +  virtual int codec_set_av_threshold(codec_para_t *pcodec, int threshold)=0;
  40. +  virtual int codec_set_video_delay_limited_ms(codec_para_t *pcodec,int delay_ms)=0;
  41. +  virtual int codec_get_video_delay_limited_ms(codec_para_t *pcodec,int *delay_ms)=0;
  42. +  virtual int codec_get_video_cur_delay_ms(codec_para_t *pcodec,int *delay_ms)=0;
  43.  };
  44.  
  45.  class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface
  46. @@ -156,6 +158,11 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface
  47.    DEFINE_METHOD2(int, codec_set_cntl_avthresh,  (codec_para_t *p1, unsigned int p2))
  48.    DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2))
  49.  
  50. +  DEFINE_METHOD2(int, codec_set_av_threshold,   (codec_para_t *p1, int p2))
  51. +  DEFINE_METHOD2(int, codec_set_video_delay_limited_ms, (codec_para_t *p1, int p2))
  52. +  DEFINE_METHOD2(int, codec_get_video_delay_limited_ms, (codec_para_t *p1, int *p2))
  53. +  DEFINE_METHOD2(int, codec_get_video_cur_delay_ms, (codec_para_t *p1, int *p2))
  54. +
  55.    BEGIN_METHOD_RESOLVE()
  56.      RESOLVE_METHOD(codec_init)
  57.      RESOLVE_METHOD(codec_close)
  58. @@ -172,6 +179,11 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface
  59.      RESOLVE_METHOD(codec_set_cntl_mode)
  60.      RESOLVE_METHOD(codec_set_cntl_avthresh)
  61.      RESOLVE_METHOD(codec_set_cntl_syncthresh)
  62. +
  63. +    RESOLVE_METHOD(codec_set_av_threshold)
  64. +    RESOLVE_METHOD(codec_set_video_delay_limited_ms)
  65. +    RESOLVE_METHOD(codec_get_video_delay_limited_ms)
  66. +    RESOLVE_METHOD(codec_get_video_cur_delay_ms)
  67.    END_METHOD_RESOLVE()
  68.  
  69.  public:
  70. @@ -279,8 +291,7 @@ public:
  71.  #define TRICKMODE_I     0x01
  72.  #define TRICKMODE_FFFB  0x02
  73.  
  74. -// same as AV_NOPTS_VALUE
  75. -#define INT64_0         INT64_C(0x8000000000000000)
  76. +static const int64_t INT64_0 = 0x8000000000000000ULL;
  77.  
  78.  #define EXTERNAL_PTS    (1)
  79.  #define SYNC_OUTSIDE    (2)
  80. @@ -371,6 +382,18 @@ typedef struct am_private_t
  81.    bool              dumpdemux;
  82.  } am_private_t;
  83.  
  84. +typedef struct vframe_states
  85. +{
  86. +  int vf_pool_size;
  87. +  int buf_free_num;
  88. +  int buf_recycle_num;
  89. +  int buf_avail_num;
  90. +} vframe_states_t;
  91. +
  92. +#define AMSTREAM_IOC_MAGIC  'S'
  93. +#define AMSTREAM_IOC_VF_STATUS  _IOR(AMSTREAM_IOC_MAGIC, 0x60, unsigned long)
  94. +
  95. +
  96.  /*************************************************************************/
  97.  /*************************************************************************/
  98.  void dumpfile_open(am_private_t *para)
  99. @@ -579,7 +602,7 @@ static void am_packet_init(am_packet_t *pkt)
  100.    pkt->avduration = 0;
  101.    pkt->isvalid    = 0;
  102.    pkt->newflag    = 0;
  103. -  pkt->lastpts    = 0;
  104. +  pkt->lastpts    = INT64_0;
  105.    pkt->data       = NULL;
  106.    pkt->buf        = NULL;
  107.    pkt->data_size  = 0;
  108. @@ -604,46 +627,14 @@ void am_packet_release(am_packet_t *pkt)
  109.  
  110.  int check_in_pts(am_private_t *para, am_packet_t *pkt)
  111.  {
  112. -    int last_duration = 0;
  113. -    static int last_v_duration = 0;
  114. -    int64_t pts = 0;
  115. -
  116. -    last_duration = last_v_duration;
  117. -
  118. -    if (para->stream_type == AM_STREAM_ES) {
  119. -        if ((int64_t)INT64_0 != pkt->avpts) {
  120. -            pts = pkt->avpts;
  121. -
  122. -            if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
  123. -                CLog::Log(LOGDEBUG, "ERROR check in pts error!");
  124. -                return PLAYER_PTS_ERROR;
  125. -            }
  126. -
  127. -        } else if ((int64_t)INT64_0 != pkt->avdts) {
  128. -            pts = pkt->avdts * last_duration;
  129. -
  130. -            if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) {
  131. -                CLog::Log(LOGDEBUG, "ERROR check in dts error!");
  132. -                return PLAYER_PTS_ERROR;
  133. -            }
  134. -
  135. -            last_v_duration = pkt->avduration ? pkt->avduration : 1;
  136. -        } else {
  137. -            if (!para->check_first_pts) {
  138. -                if (para->m_dll->codec_checkin_pts(pkt->codec, 0) != 0) {
  139. -                    CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!");
  140. -                    return PLAYER_PTS_ERROR;
  141. -                }
  142. -            }
  143. -        }
  144. -        if (!para->check_first_pts) {
  145. -            para->check_first_pts = 1;
  146. -        }
  147. -    }
  148. -    if (pts > 0)
  149. -      pkt->lastpts = pts;
  150. -
  151. -    return PLAYER_SUCCESS;
  152. +  if (para->stream_type == AM_STREAM_ES
  153. +    && INT64_0 != pkt->avpts
  154. +    && para->m_dll->codec_checkin_pts(pkt->codec, pkt->avpts) != 0)
  155. +  {
  156. +    CLog::Log(LOGDEBUG, "ERROR check in pts error!");
  157. +    return PLAYER_PTS_ERROR;
  158. +  }
  159. +  return PLAYER_SUCCESS;
  160.  }
  161.  
  162.  static int write_header(am_private_t *para, am_packet_t *pkt)
  163. @@ -713,7 +704,7 @@ int write_av_packet(am_private_t *para, am_packet_t *pkt)
  164.          }
  165.          pkt->newflag = 0;
  166.      }
  167. -  
  168. +
  169.      buf = pkt->data;
  170.      size = pkt->data_size ;
  171.      if (size == 0 && pkt->isvalid) {
  172. @@ -1380,9 +1371,12 @@ int set_header_info(am_private_t *para)
  173.  
  174.  /*************************************************************************/
  175.  CAMLCodec::CAMLCodec()
  176. -  : CThread("CAMLCodec")
  177. +  : m_opened(false)
  178. +  , m_ptsIs64us(false)
  179. +  , m_cur_pts(INT64_0)
  180. +  , m_last_pts(0)
  181. +  , m_state(0)
  182.  {
  183. -  m_opened = false;
  184.    am_private = new am_private_t;
  185.    memset(am_private, 0, sizeof(am_private_t));
  186.    m_dll = new DllLibAmCodec;
  187. @@ -1402,12 +1396,26 @@ CAMLCodec::CAMLCodec()
  188.  
  189.  CAMLCodec::~CAMLCodec()
  190.  {
  191. -  StopThread();
  192.    delete am_private;
  193.    am_private = NULL;
  194.    delete m_dll, m_dll = NULL;
  195.  }
  196.  
  197. +float CAMLCodec::OMXPtsToSeconds(int omxpts)
  198. +{
  199. +  return static_cast<float>(omxpts) / PTS_FREQ;
  200. +}
  201. +
  202. +int CAMLCodec::OMXDurationToNs(int duration)
  203. +{
  204. +  return static_cast<int>(static_cast<float>(duration) / PTS_FREQ * 1000000 );
  205. +}
  206. +
  207. +int CAMLCodec::GetAmlDuration() const
  208. +{
  209. +  return am_private ? (am_private->video_rate * PTS_FREQ) / UNIT_FREQ : 0;
  210. +};
  211. +
  212.  bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
  213.  {
  214.  #ifdef TARGET_ANDROID
  215. @@ -1415,16 +1423,15 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
  216.  #endif
  217.  
  218.    m_speed = DVD_PLAYSPEED_NORMAL;
  219. -  m_1st_pts = 0;
  220. -  m_cur_pts = 0;
  221. +  m_cur_pts = INT64_0;
  222.    m_dst_rect.SetRect(0, 0, 0, 0);
  223.    m_zoom = -1;
  224.    m_contrast = -1;
  225.    m_brightness = -1;
  226.    m_vbufsize = 500000 * 2;
  227. -  m_start_dts = 0;
  228. -  m_start_pts = 0;
  229. +  m_start_adj = 0;
  230.    m_hints = hints;
  231. +  m_state = 0;
  232.  
  233.    if (!OpenAmlVideo(hints))
  234.    {
  235. @@ -1615,9 +1622,10 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
  236.    am_private->dumpdemux = false;
  237.    dumpfile_open(am_private);
  238.  
  239. -  //! @bug make sure we are not stuck in pause (amcodec bug)
  240. -  m_dll->codec_resume(&am_private->vcodec);
  241. +  m_dll->codec_pause(&am_private->vcodec);
  242. +
  243.    m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
  244. +  m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000);
  245.  
  246.    m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH);
  247.    m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0);
  248. @@ -1627,8 +1635,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
  249.    am_private->am_pkt.codec = &am_private->vcodec;
  250.    pre_header_feeding(am_private, &am_private->am_pkt);
  251.  
  252. -  Create();
  253. -
  254.    m_display_rect = CRect(0, 0, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iWidth, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iHeight);
  255.  
  256.    std::string strScaler;
  257. @@ -1636,16 +1642,19 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints)
  258.    if (strScaler.find("enabled") == std::string::npos)     // Scaler not enabled, use screen size
  259.      m_display_rect = CRect(0, 0, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iScreenWidth, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iScreenHeight);
  260.  
  261. -/*
  262. -  // if display is set to 1080xxx, then disable deinterlacer for HD content
  263. -  // else bandwidth usage is too heavy and it will slow down video decoder.
  264. -  char display_mode[256] = {0};
  265. -  SysfsUtils::GetString("/sys/class/display/mode", display_mode, 255);
  266. -  if (strstr(display_mode,"1080"))
  267. -    SysfsUtils::SetInt("/sys/module/di/parameters/bypass_all", 1);
  268. -  else
  269. -    SysfsUtils::SetInt("/sys/module/di/parameters/bypass_all", 0);
  270. -*/
  271. +  SysfsUtils::SetInt("/sys/class/video/freerun_mode", 0);
  272. +
  273. +
  274. +  struct utsname un;
  275. +  if (uname(&un) == 0)
  276. +  {
  277. +    int linuxversion[2];
  278. +    sscanf(un.release,"%d.%d", &linuxversion[0], &linuxversion[1]);
  279. +    if (linuxversion[0] > 3 || (linuxversion[0] == 3 && linuxversion[1] >= 14))
  280. +      m_ptsIs64us = true;
  281. +  }
  282. +
  283. +  CLog::Log(LOGNOTICE, "CAMLCodec::OpenDecoder - using V4L2 pts format: %s", m_ptsIs64us ? "64Bit":"32Bit");
  284.  
  285.    m_opened = true;
  286.    // vcodec is open, update speed if it was
  287. @@ -1705,7 +1714,6 @@ void CAMLCodec::SetVfmMap(const std::string &name, const std::string &map)
  288.  void CAMLCodec::CloseDecoder()
  289.  {
  290.    CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder");
  291. -  StopThread();
  292.  
  293.    // never leave vcodec ff/rw or paused.
  294.    if (m_speed != DVD_PLAYSPEED_NORMAL)
  295. @@ -1749,11 +1757,14 @@ void CAMLCodec::Reset()
  296.    // restore the speed (some amcodec versions require this)
  297.    if (m_speed != DVD_PLAYSPEED_NORMAL)
  298.    {
  299. -    m_dll->codec_resume(&am_private->vcodec);
  300.      m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE);
  301.    }
  302. +  m_dll->codec_pause(&am_private->vcodec);
  303. +
  304.    // reset the decoder
  305.    m_dll->codec_reset(&am_private->vcodec);
  306. +  m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000);
  307. +
  308.    dumpfile_close(am_private);
  309.    dumpfile_open(am_private);
  310.  
  311. @@ -1767,9 +1778,9 @@ void CAMLCodec::Reset()
  312.    SysfsUtils::SetInt("/sys/class/video/blackout_policy", blackout_policy);
  313.  
  314.    // reset some interal vars
  315. -  m_1st_pts = 0;
  316. -  m_cur_pts = 0;
  317. -  m_ptsQueue.clear();
  318. +  m_cur_pts = INT64_0;
  319. +  m_state = 0;
  320. +  m_start_adj = 0;
  321.    SetSpeed(m_speed);
  322.  }
  323.  
  324. @@ -1778,6 +1789,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts)
  325.    if (!m_opened)
  326.      return VC_BUFFER;
  327.  
  328. +  float timesize(static_cast<float>(GetTimeSize()));
  329.    if (pData)
  330.    {
  331.      am_private->am_pkt.data = pData;
  332. @@ -1790,31 +1802,35 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts)
  333.      // handle pts, including 31bit wrap, aml can only handle 31
  334.      // bit pts as it uses an int in kernel.
  335.      if (m_hints.ptsinvalid || pts == DVD_NOPTS_VALUE)
  336. -      am_private->am_pkt.avpts = AV_NOPTS_VALUE;
  337. +      am_private->am_pkt.avpts = INT64_0;
  338.      else
  339.      {
  340.        am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\
  341. -      if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff)
  342. -        m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff;
  343. +      if (!m_start_adj && am_private->am_pkt.avpts >= 0x7fffffff)
  344. +        m_start_adj = am_private->am_pkt.avpts & ~0x0000ffff;
  345. +      am_private->am_pkt.avpts -= m_start_adj;
  346. +      m_state |= STATE_HASPTS;
  347.      }
  348. -    if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE)
  349. -      am_private->am_pkt.avpts -= m_start_pts;
  350.  
  351.      // handle dts, including 31bit wrap, aml can only handle 31
  352.      // bit dts as it uses an int in kernel.
  353.      if (dts == DVD_NOPTS_VALUE)
  354. -      am_private->am_pkt.avdts = AV_NOPTS_VALUE;
  355. +      am_private->am_pkt.avdts = am_private->am_pkt.avpts;
  356.      else
  357.      {
  358.        am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE;
  359. -      if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff)
  360. -        m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff;
  361. +      if (!m_start_adj && am_private->am_pkt.avdts >= 0x7fffffff)
  362. +        m_start_adj = am_private->am_pkt.avdts & ~0x0000ffff;
  363. +      am_private->am_pkt.avdts -= m_start_adj;
  364. +    }
  365. +    // We use this to determine the fill state if no PTS is given
  366. +    if (m_cur_pts == INT64_0)
  367. +    {
  368. +      m_cur_pts = am_private->am_pkt.avdts;
  369. +      // No PTS given -> use first DTS for AML ptsserver initialization
  370. +      if ((m_state & STATE_HASPTS) == 0)
  371. +         am_private->am_pkt.avpts = am_private->am_pkt.avdts;
  372.      }
  373. -    if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE)
  374. -      am_private->am_pkt.avdts -= m_start_dts;
  375. -
  376. -    //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: iSize(%d), dts(%f), pts(%f), avdts(%llx), avpts(%llx)",
  377. -    //  iSize, dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts);
  378.  
  379.      // some formats need header/data tweaks.
  380.      // the actual write occurs once in write_av_packet
  381. @@ -1840,47 +1856,61 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts)
  382.        // Decoder got stuck; Reset
  383.        Reset();
  384.      }
  385. -
  386. -    // if we seek, then GetTimeSize is wrong as
  387. -    // reports lastpts - cur_pts and hw decoder has
  388. -    // not started outputing new pts values yet.
  389. -    // so we grab the 1st pts sent into driver and
  390. -    // use that to calc GetTimeSize.
  391. -    if (m_1st_pts == 0)
  392. -      m_1st_pts = am_private->am_pkt.lastpts;
  393. +    if ((m_state & STATE_PREFILLED) == 0 && timesize >= 1.0)
  394. +    {
  395. +      m_dll->codec_resume(&am_private->vcodec);
  396. +      m_state |= STATE_PREFILLED;
  397. +    }
  398.    }
  399.  
  400. -  // if we have still frames, demux size will be small
  401. -  // and we need to pre-buffer more.
  402. -  double target_timesize = 1.0;
  403. -  if (iSize < 20)
  404. -    target_timesize = 2.0;
  405. -
  406. -  int rtn = 0;
  407. -
  408. -  // keep hw buffered demux above 1 second
  409. -  if (GetTimeSize() < target_timesize)
  410. -    rtn |= VC_BUFFER;
  411. +  int rtn(0);
  412. +  int64_t decode_pts = 0;
  413. +  if ((m_state & STATE_PREFILLED) != 0 && timesize > 0.5 &&  DequeueBuffer(decode_pts) == 0)
  414. +  {
  415. +    rtn |= VC_PICTURE;
  416. +    m_last_pts = m_cur_pts;
  417. +    m_cur_pts = decode_pts;
  418. +  }
  419. +  else //Timesize actualizes each 10ms, throttle decode calls to avoid reading too much
  420. +    usleep(2500);
  421.  
  422. -  // wait until we get a new frame or 25ms,
  423. -  if (m_ptsQueue.size() == 0)
  424. -    m_ready_event.WaitMSec(25);
  425. +  if (((rtn & VC_PICTURE) == 0 && timesize < 2.0) || timesize < 1.0)
  426. +   rtn |= VC_BUFFER;
  427.  
  428. -  if (m_ptsQueue.size() > 0)
  429. +  if (g_advancedSettings.CanLogComponent(LOGVIDEO))
  430.    {
  431. -    CSingleLock lock(m_ptsQueueMutex);
  432. -    m_cur_pts = m_ptsQueue.front();
  433. -    m_ptsQueue.pop_front();
  434. -    rtn |= VC_PICTURE;
  435. +    vframe_states_t vfs;
  436. +    int fd(open("/dev/amvideo", O_RDONLY));
  437. +    if(fd)
  438. +    {
  439. +      if (ioctl(fd, AMSTREAM_IOC_VF_STATUS, &vfs) != 0)
  440. +        memset(&vfs, 0, sizeof(vfs));
  441. +      close(fd);
  442. +    }
  443. +    else
  444. +      memset(&vfs, 0, sizeof(vfs));
  445. +
  446. +    CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %llu, dts_in: %0.6f[%llX], pts_in: %0.6f[%llX], adj:%llu, ptsOut:%0.6f, amlpts:%d vfs:[%d-%d-%d-%d] timesize:%0.2f",
  447. +      rtn,
  448. +      iSize,
  449. +      static_cast<float>(dts)/DVD_TIME_BASE, am_private->am_pkt.avdts,
  450. +      static_cast<float>(pts)/DVD_TIME_BASE, am_private->am_pkt.avpts,
  451. +      m_start_adj,
  452. +      static_cast<float>(m_cur_pts)/PTS_FREQ,
  453. +      static_cast<int>(m_cur_pts),
  454. +      vfs.vf_pool_size, vfs.buf_free_num,vfs.buf_recycle_num,vfs.buf_avail_num,
  455. +      timesize
  456. +    );
  457.    }
  458. -/*
  459. -  CLog::Log(LOGDEBUG, "CAMLCodec::Decode: "
  460. -    "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)",
  461. -    rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize());
  462. -*/
  463. +
  464.    return rtn;
  465.  }
  466.  
  467. +int CAMLCodec::PollFrame()
  468. +{
  469. +   return m_dll->codec_poll_cntl(&am_private->vcodec);
  470. +}
  471. +
  472.  int CAMLCodec::DequeueBuffer(int64_t &pts)
  473.  {
  474.    v4l2_buffer vbuf = { 0 };
  475. @@ -1896,7 +1926,7 @@ int CAMLCodec::DequeueBuffer(int64_t &pts)
  476.    // Since kernel 3.14 Amlogic changed length and units of PTS values reported here.
  477.    // To differentiate such PTS values we check for existence of omx_pts_interval_lower
  478.    // parameter, because it was introduced since kernel 3.14.
  479. -  if (access("/sys/module/amvideo/parameters/omx_pts_interval_lower", F_OK) != -1)
  480. +  if (m_ptsIs64us)
  481.    {
  482.      pts = vbuf.timestamp.tv_sec & 0xFFFFFFFF;
  483.      pts <<= 32;
  484. @@ -1917,24 +1947,26 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture)
  485.  
  486.    pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
  487.    pDvdVideoPicture->format = RENDER_FMT_AML;
  488. -  pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ;
  489.  
  490. -  pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
  491. -  if (m_speed == DVD_PLAYSPEED_NORMAL)
  492. -    pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE;
  493. +  if (m_last_pts <= 0)
  494. +    pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ;
  495.    else
  496. -  {
  497. -    if (m_cur_pts == 0)
  498. -      pDvdVideoPicture->pts = (double)m_1st_pts / PTS_FREQ * DVD_TIME_BASE;
  499. -    else
  500. -      pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE;
  501. -  }
  502. +    pDvdVideoPicture->iDuration = (double)((m_cur_pts - m_last_pts) * DVD_TIME_BASE) / PTS_FREQ;
  503. +
  504. +  pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
  505. +  pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE;
  506. +
  507. +  //AML video is ~ 2 frames to fast - sync audio
  508. +  pDvdVideoPicture->pts += 2*pDvdVideoPicture->iDuration;
  509.  
  510.    return true;
  511.  }
  512.  
  513.  void CAMLCodec::SetSpeed(int speed)
  514.  {
  515. +  if (m_speed == speed)
  516. +    return;
  517. +
  518.    CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed);
  519.  
  520.    // update internal vars regardless
  521. @@ -1981,17 +2013,16 @@ double CAMLCodec::GetTimeSize()
  522.    if (!m_opened)
  523.      return 0;
  524.  
  525. -  // if m_cur_pts is zero, hw decoder was not started yet
  526. -  // so we use the pts of the 1st demux packet that was send
  527. -  // to hw decoder to calc timesize.
  528. -  if (m_cur_pts == 0)
  529. -    m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ;
  530. -  else
  531. -    m_timesize = (double)(am_private->am_pkt.lastpts - GetOMXPts()) / PTS_FREQ;
  532. +  double timesize(0);
  533. +  if (m_cur_pts != INT64_0)
  534. +  {
  535. +    timesize = static_cast<double>(am_private->am_pkt.avdts - m_cur_pts) / PTS_FREQ;
  536. +    if (timesize < 0 || timesize > 5.0)
  537. +     CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: avdts: %lld  cur_pts: %lld",am_private->am_pkt.avdts, m_cur_pts);
  538. +  }
  539.  
  540.    // lie to VideoPlayer, it is hardcoded to a max of 8 seconds,
  541.    // if you buffer more than 8 seconds, it goes nuts.
  542. -  double timesize = m_timesize;
  543.    if (timesize < 0.0)
  544.      timesize = 0.0;
  545.    else if (timesize > 7.0)
  546. @@ -2000,32 +2031,6 @@ double CAMLCodec::GetTimeSize()
  547.    return timesize;
  548.  }
  549.  
  550. -void CAMLCodec::Process()
  551. -{
  552. -  CLog::Log(LOGDEBUG, "CAMLCodec::Process Started");
  553. -
  554. -  while (!m_bStop)
  555. -  {
  556. -    if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0)
  557. -    {
  558. -      CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed");
  559. -      Sleep(10);
  560. -    }
  561. -
  562. -    {
  563. -      CSingleLock lock(m_ptsQueueMutex);
  564. -      int64_t pts = 0;
  565. -      if (DequeueBuffer(pts) == 0)
  566. -      {
  567. -        m_ptsQueue.push_back(pts + m_start_pts);
  568. -        m_ready_event.Set();
  569. -      }
  570. -    }
  571. -  }
  572. -
  573. -  CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped");
  574. -}
  575. -
  576.  void CAMLCodec::ShowMainVideo(const bool show)
  577.  {
  578.    static int saved_disable_video = -1;
  579. @@ -2273,3 +2278,9 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect)
  580.    // that would show video playback, so show it.
  581.    ShowMainVideo(true);
  582.  }
  583. +
  584. +void CAMLCodec::SetVideoRate(int videoRate)
  585. +{
  586. +  if (am_private)
  587. +    am_private->video_rate = videoRate;
  588. +}
  589. diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h
  590. index 0eb5c3e..b18e6e2 100644
  591. --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h
  592. +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h
  593. @@ -24,8 +24,6 @@
  594.  #include "cores/IPlayer.h"
  595.  #include "guilib/Geometry.h"
  596.  #include "rendering/RenderSystem.h"
  597. -#include "threads/Thread.h"
  598. -#include <deque>
  599.  
  600.  typedef struct am_private_t am_private_t;
  601.  
  602. @@ -34,7 +32,7 @@ class DllLibAmCodec;
  603.  class PosixFile;
  604.  typedef std::shared_ptr<PosixFile> PosixFilePtr;
  605.  
  606. -class CAMLCodec : public CThread
  607. +class CAMLCodec
  608.  {
  609.  public:
  610.    CAMLCodec();
  611. @@ -51,11 +49,13 @@ public:
  612.    int           GetDataSize();
  613.    double        GetTimeSize();
  614.    void          SetVideoRect(const CRect &SrcRect, const CRect &DestRect);
  615. -  int64_t       GetCurPts() const { return m_cur_pts; }
  616. -  int          GetOMXPts() const { return static_cast<int>(m_cur_pts - m_start_pts); }
  617. -
  618. -protected:
  619. -  virtual void  Process();
  620. +  void          SetVideoRate(int videoRate);
  621. +  int64_t       GetCurPts() const { return m_cur_pts + m_start_adj; }
  622. +  int          GetOMXPts() const { return static_cast<int>(m_cur_pts); }
  623. +  static float  OMXPtsToSeconds(int omxpts);
  624. +  static int    OMXDurationToNs(int duration);
  625. +  int           GetAmlDuration() const;
  626. +  int           PollFrame();
  627.  
  628.  private:
  629.    void          ShowMainVideo(const bool show);
  630. @@ -73,16 +73,14 @@ private:
  631.  
  632.    DllLibAmCodec   *m_dll;
  633.    bool             m_opened;
  634. +  bool             m_ptsIs64us;
  635.    am_private_t    *am_private;
  636.    CDVDStreamInfo   m_hints;
  637. -  volatile int     m_speed;
  638. -  volatile int64_t m_1st_pts;
  639. -  volatile int64_t m_cur_pts;
  640. -  volatile double  m_timesize;
  641. +  int              m_speed;
  642. +  int64_t          m_cur_pts;
  643.    volatile int64_t m_vbufsize;
  644. -  int64_t          m_start_dts;
  645. -  int64_t          m_start_pts;
  646. -  CEvent           m_ready_event;
  647. +  int64_t          m_start_adj;
  648. +  int64_t          m_last_pts;
  649.  
  650.    CRect            m_dst_rect;
  651.    CRect            m_display_rect;
  652. @@ -94,8 +92,12 @@ private:
  653.    int              m_contrast;
  654.    int              m_brightness;
  655.  
  656. +  static const unsigned int STATE_PREFILLED  = 1;
  657. +  static const unsigned int STATE_HASPTS     = 2;
  658. +
  659. +  unsigned int m_state;
  660. +
  661.    PosixFilePtr     m_amlVideoFile;
  662.    std::string      m_defaultVfmMap;
  663. -  std::deque<int64_t>  m_ptsQueue;
  664.    CCriticalSection m_ptsQueueMutex;
  665.  };
  666. diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp
  667. index a27d3e3..a6803e4 100644
  668. --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp
  669. +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp
  670. @@ -30,6 +30,7 @@
  671.  #include "utils/SysfsUtils.h"
  672.  #include "threads/Atomics.h"
  673.  #include "settings/Settings.h"
  674. +#include "threads/Thread.h"
  675.  
  676.  #define __MODULE_NAME__ "DVDVideoCodecAmlogic"
  677.  
  678. @@ -52,7 +53,8 @@ CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic(CProcessInfo &processInfo) : CDVDVi
  679.    m_bitparser(NULL),
  680.    m_bitstream(NULL),
  681.    m_opened(false),
  682. -  m_drop(false)
  683. +  m_drop(false),
  684. +  m_has_keyframe(false)
  685.  {
  686.    pthread_mutex_init(&m_queue_mutex, NULL);
  687.  }
  688. @@ -125,14 +127,18 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option
  689.        {
  690.          m_bitstream = new CBitstreamConverter;
  691.          m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true);
  692. +        m_bitstream->ResetKeyframe();
  693.          // make sure we do not leak the existing m_hints.extradata
  694.          free(m_hints.extradata);
  695.          m_hints.extrasize = m_bitstream->GetExtraSize();
  696.          m_hints.extradata = malloc(m_hints.extrasize);
  697.          memcpy(m_hints.extradata, m_bitstream->GetExtraData(), m_hints.extrasize);
  698.        }
  699. -      //m_bitparser = new CBitstreamParser();
  700. -      //m_bitparser->Open();
  701. +      else
  702. +      {
  703. +        m_bitparser = new CBitstreamParser();
  704. +        m_bitparser->Open();
  705. +      }
  706.        break;
  707.      case AV_CODEC_ID_MPEG4:
  708.      case AV_CODEC_ID_MSMPEG4V2:
  709. @@ -236,6 +242,9 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option
  710.    m_processInfo.SetVideoDecoderName(m_pFormatName, true);
  711.    m_processInfo.SetVideoDimensions(m_hints.width, m_hints.height);
  712.    m_processInfo.SetVideoDeintMethod("hardware");
  713. +  m_processInfo.SetVideoDAR(m_hints.aspect);
  714. +
  715. +  m_has_keyframe = false;
  716.  
  717.    CLog::Log(LOGINFO, "%s: Opened Amlogic Codec", __MODULE_NAME__);
  718.    return true;
  719. @@ -277,13 +286,24 @@ int CDVDVideoCodecAmlogic::Decode(uint8_t *pData, int iSize, double dts, double
  720.        if (!m_bitstream->Convert(pData, iSize))
  721.          return VC_ERROR;
  722.  
  723. +      if (!m_bitstream->HasKeyframe())
  724. +      {
  725. +        CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for keyframe (bitstream)", __MODULE_NAME__);
  726. +        return VC_BUFFER;
  727. +      }
  728.        pData = m_bitstream->GetConvertBuffer();
  729.        iSize = m_bitstream->GetConvertSize();
  730.      }
  731. -
  732. -    if (m_bitparser)
  733. -      m_bitparser->FindIdrSlice(pData, iSize);
  734. -
  735. +    else if (!m_has_keyframe && m_bitparser)
  736. +    {
  737. +      if (!m_bitparser->HasKeyframe(pData, iSize))
  738. +      {
  739. +        CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for keyframe (bitparser)", __MODULE_NAME__);
  740. +        return VC_BUFFER;
  741. +      }
  742. +      else
  743. +        m_has_keyframe = true;
  744. +    }
  745.      FrameRateTracking( pData, iSize, dts, pts);
  746.    }
  747.  
  748. @@ -307,6 +327,9 @@ void CDVDVideoCodecAmlogic::Reset(void)
  749.  
  750.    m_Codec->Reset();
  751.    m_mpeg2_sequence_pts = 0;
  752. +  m_has_keyframe = false;
  753. +  if (m_bitstream && m_hints.codec == AV_CODEC_ID_H264)
  754. +    m_bitstream->ResetKeyframe();
  755.  }
  756.  
  757.  bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  758. @@ -315,7 +338,7 @@ bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture)
  759.      m_Codec->GetPicture(&m_videobuffer);
  760.    *pDvdVideoPicture = m_videobuffer;
  761.  
  762. -  CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec, m_Codec->GetOMXPts());
  763. +  CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec, m_Codec->GetOMXPts(), m_Codec->GetAmlDuration());
  764.  
  765.    {
  766.      CSingleLock lock(m_secure);
  767. @@ -363,7 +386,7 @@ void CDVDVideoCodecAmlogic::SetDropState(bool bDrop)
  768.    // Freerun mode causes amvideo driver to ignore timing and process frames
  769.    // as quickly as they are coming from decoder. By enabling freerun mode we can
  770.    // skip rendering of the frames that are requested to be dropped by VideoPlayer.
  771. -  SysfsUtils::SetInt("/sys/class/video/freerun_mode", bDrop ? 1 : 0);
  772. +  //SysfsUtils::SetInt("/sys/class/video/freerun_mode", bDrop ? 1 : 0);
  773.  }
  774.  
  775.  void CDVDVideoCodecAmlogic::SetSpeed(int iSpeed)
  776. @@ -466,8 +489,7 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double
  777.        m_framerate = m_mpeg2_sequence->rate;
  778.        m_video_rate = (int)(0.5 + (96000.0 / m_framerate));
  779.  
  780. -      CLog::Log(LOGDEBUG, "%s: detected mpeg2 aspect ratio(%f), framerate(%f), video_rate(%d)",
  781. -        __MODULE_NAME__, m_mpeg2_sequence->ratio, m_framerate, m_video_rate);
  782. +      m_processInfo.SetVideoFps(m_framerate);
  783.  
  784.        // update m_hints for 1st frame fixup.
  785.        switch(m_mpeg2_sequence->rate_info)
  786. @@ -526,7 +548,7 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double
  787.      if (cur_pts == DVD_NOPTS_VALUE)
  788.        cur_pts = m_frame_queue->dts;
  789.  
  790. -    pthread_mutex_unlock(&m_queue_mutex); 
  791. +    pthread_mutex_unlock(&m_queue_mutex);
  792.  
  793.      float duration = cur_pts - m_last_pts;
  794.      m_last_pts = cur_pts;
  795. @@ -559,22 +581,10 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double
  796.            break;
  797.  
  798.          // 25.000 (40000.000000)
  799. -        case 40000:
  800. +        case 39900 ... 40100:
  801.            framerate = 25000.0 / 1000.0;
  802.            break;
  803.  
  804. -        // 24.975 (40040.000000)
  805. -        case 40040:
  806. -          framerate = 25000.0 / 1001.0;
  807. -          break;
  808. -
  809. -        /*
  810. -        // 24.000 (41666.666666)
  811. -        case 41667:
  812. -          framerate = 24000.0 / 1000.0;
  813. -          break;
  814. -        */
  815. -
  816.          // 23.976 (41708.33333)
  817.          case 40200 ... 43200:
  818.            // 23.976 seems to have the crappiest encodings :)
  819. @@ -592,6 +602,12 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double
  820.        {
  821.          m_framerate = framerate;
  822.          m_video_rate = (int)(0.5 + (96000.0 / framerate));
  823. +
  824. +        if (m_Codec)
  825. +          m_Codec->SetVideoRate(m_video_rate);
  826. +
  827. +        m_processInfo.SetVideoFps(m_framerate);
  828. +
  829.          CLog::Log(LOGDEBUG, "%s: detected new framerate(%f), video_rate(%d)",
  830.            __MODULE_NAME__, m_framerate, m_video_rate);
  831.        }
  832. @@ -607,11 +623,12 @@ void CDVDVideoCodecAmlogic::RemoveInfo(CDVDAmlogicInfo *info)
  833.    m_inflight.erase(m_inflight.find(info));
  834.  }
  835.  
  836. -CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts)
  837. +CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration)
  838.    : m_refs(0)
  839.    , m_codec(codec)
  840.    , m_amlCodec(amlcodec)
  841.    , m_omxPts(omxPts)
  842. +  , m_amlDuration(amlDuration)
  843.  {
  844.  }
  845.  
  846. diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h
  847. index 2c44241..a494ace 100644
  848. --- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h
  849. +++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h
  850. @@ -36,7 +36,7 @@ class CDVDVideoCodecAmlogic;
  851.  class CDVDAmlogicInfo
  852.  {
  853.  public:
  854. -  CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts);
  855. +  CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration);
  856.  
  857.    // reference counting
  858.    CDVDAmlogicInfo* Retain();
  859. @@ -44,6 +44,7 @@ public:
  860.  
  861.    CAMLCodec *getAmlCodec() const;
  862.    int GetOmxPts() const { return m_omxPts; }
  863. +  int GetAmlDuration() const { return m_amlDuration; }
  864.    void invalidate();
  865.  
  866.  protected:
  867. @@ -52,7 +53,7 @@ protected:
  868.  
  869.    CDVDVideoCodecAmlogic* m_codec;
  870.    CAMLCodec* m_amlCodec;
  871. -  int m_omxPts;
  872. +  int m_omxPts, m_amlDuration;
  873.  };
  874.  
  875.  class CDVDVideoCodecAmlogic : public CDVDVideoCodec
  876. @@ -98,6 +99,7 @@ protected:
  877.    mpeg2_sequence *m_mpeg2_sequence;
  878.    double          m_mpeg2_sequence_pts;
  879.    bool            m_drop;
  880. +  bool            m_has_keyframe;
  881.  
  882.    CBitstreamParser *m_bitparser;
  883.    CBitstreamConverter *m_bitstream;
  884. diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp
  885. index d8674c8..e6b39f3 100644
  886. --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp
  887. +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp
  888. @@ -21,26 +21,84 @@
  889.  #include "RendererAML.h"
  890.  
  891.  #if defined(HAS_LIBAMCODEC)
  892. -#include "cores/IPlayer.h"
  893. -#include "windowing/egl/EGLWrapper.h"
  894.  #include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h"
  895.  #include "cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h"
  896.  #include "utils/log.h"
  897. -#include "utils/GLUtils.h"
  898.  #include "utils/SysfsUtils.h"
  899.  #include "settings/MediaSettings.h"
  900.  #include "windowing/WindowingFactory.h"
  901.  #include "cores/VideoPlayer/VideoRenderers/RenderCapture.h"
  902. +#include "settings/AdvancedSettings.h"
  903. +
  904. +static int get_pts(const char *strPath)
  905. +{
  906. +  int fd = open(strPath, O_RDONLY);
  907. +  if (fd >= 0)
  908. +  {
  909. +    char pts_str[64];
  910. +    int size = read(fd, pts_str, sizeof(pts_str));
  911. +    close(fd);
  912. +    return strtol(pts_str, NULL, 16);
  913. +  }
  914. +  return 0;
  915. +}
  916. +
  917. +static void set_pts(const char *strPath, int pts)
  918. +{
  919. +  int fd = open(strPath, O_WRONLY);
  920. +  if (fd >= 0)
  921. +  {
  922. +    char pts_str[64];
  923. +    sprintf(pts_str, "0x%x", pts);
  924. +    write(fd, pts_str, strlen(pts_str));
  925. +    close(fd);
  926. +  }
  927. +}
  928.  
  929.  CRendererAML::CRendererAML()
  930. + : m_prevVPts(-1)
  931. + , m_bConfigured(false)
  932. + , m_iRenderBuffer(0)
  933. + , m_diff_counter(0)
  934.  {
  935. -  m_prevPts = -1;
  936.  }
  937.  
  938.  CRendererAML::~CRendererAML()
  939.  {
  940.  }
  941.  
  942. +bool CRendererAML::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_formatl, unsigned int orientation)
  943. +{
  944. +  m_sourceWidth = width;
  945. +  m_sourceHeight = height;
  946. +  m_renderOrientation = orientation;
  947. +
  948. +  // Save the flags.
  949. +  m_iFlags = flags;
  950. +  m_format = format;
  951. +
  952. +  // Calculate the input frame aspect ratio.
  953. +  CalculateFrameAspectRatio(d_width, d_height);
  954. +  SetViewMode(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode);
  955. +  ManageRenderArea();
  956. +
  957. +  m_bConfigured = true;
  958. +
  959. +  for (int i = 0 ; i < m_numRenderBuffers ; ++i)
  960. +    m_buffers[i].hwDec = 0;
  961. +
  962. +  return true;
  963. +}
  964. +
  965. +CRenderInfo CRendererAML::GetRenderInfo()
  966. +{
  967. +  CRenderInfo info;
  968. +  info.formats.push_back(RENDER_FMT_BYPASS);
  969. +  info.max_buffer_size = m_numRenderBuffers;
  970. +  info.optimal_buffer_size = m_numRenderBuffers;
  971. +  return info;
  972. +}
  973. +
  974.  bool CRendererAML::RenderCapture(CRenderCapture* capture)
  975.  {
  976.    capture->BeginRender();
  977. @@ -48,16 +106,28 @@ bool CRendererAML::RenderCapture(CRenderCapture* capture)
  978.    return true;
  979.  }
  980.  
  981. +int CRendererAML::GetImage(YV12Image *image, int source, bool readonly)
  982. +{
  983. +  if (image == nullptr)
  984. +    return -1;
  985. +
  986. +  /* take next available buffer */
  987. +  if (source == -1)
  988. +   source = (m_iRenderBuffer + 1) % m_numRenderBuffers;
  989. +
  990. +  return source;
  991. +}
  992. +
  993.  void CRendererAML::AddVideoPictureHW(DVDVideoPicture &picture, int index)
  994.  {
  995. -  YUVBUFFER &buf = m_buffers[index];
  996. +  BUFFER &buf = m_buffers[index];
  997.    if (picture.amlcodec)
  998.      buf.hwDec = picture.amlcodec->Retain();
  999.  }
  1000.  
  1001.  void CRendererAML::ReleaseBuffer(int idx)
  1002.  {
  1003. -  YUVBUFFER &buf = m_buffers[idx];
  1004. +  BUFFER &buf = m_buffers[idx];
  1005.    if (buf.hwDec)
  1006.    {
  1007.      CDVDAmlogicInfo *amli = static_cast<CDVDAmlogicInfo *>(buf.hwDec);
  1008. @@ -66,9 +136,14 @@ void CRendererAML::ReleaseBuffer(int idx)
  1009.    }
  1010.  }
  1011.  
  1012. -int CRendererAML::GetImageHook(YV12Image *image, int source, bool readonly)
  1013. +void CRendererAML::FlipPage(int source)
  1014.  {
  1015. -  return source;
  1016. +  if( source >= 0 && source < m_numRenderBuffers )
  1017. +    m_iRenderBuffer = source;
  1018. +  else
  1019. +    m_iRenderBuffer = (m_iRenderBuffer + 1) % m_numRenderBuffers;
  1020. +
  1021. +  return;
  1022.  }
  1023.  
  1024.  bool CRendererAML::IsGuiLayer()
  1025. @@ -104,37 +179,63 @@ EINTERLACEMETHOD CRendererAML::AutoInterlaceMethod()
  1026.    return VS_INTERLACEMETHOD_NONE;
  1027.  }
  1028.  
  1029. -bool CRendererAML::LoadShadersHook()
  1030. +void CRendererAML::Reset()
  1031.  {
  1032. -  CLog::Log(LOGNOTICE, "GL: Using AML render method");
  1033. -  m_textureTarget = GL_TEXTURE_2D;
  1034. -  m_renderMethod = RENDER_BYPASS;
  1035. -  return false;
  1036. +  m_prevVPts = -1;
  1037. +  m_diff_counter = 0;
  1038.  }
  1039.  
  1040. -bool CRendererAML::RenderHook(int index)
  1041. -{
  1042. -  return true;// nothing to be done for aml
  1043. -}
  1044. -
  1045. -bool CRendererAML::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha)
  1046. +void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
  1047.  {
  1048.    ManageRenderArea();
  1049.  
  1050. -  CDVDAmlogicInfo *amli = static_cast<CDVDAmlogicInfo *>(m_buffers[m_iYV12RenderBuffer].hwDec);
  1051. -  if (amli && amli->GetOmxPts() != m_prevPts)
  1052. +  CDVDAmlogicInfo *amli = static_cast<CDVDAmlogicInfo *>(m_buffers[m_iRenderBuffer].hwDec);
  1053. +  CAMLCodec *amlcodec = amli ? amli->getAmlCodec() : 0;
  1054. +
  1055. +  int videopts(0);
  1056. +  if(amlcodec)
  1057.    {
  1058. -    m_prevPts = amli->GetOmxPts();
  1059. -    SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", amli->GetOmxPts());
  1060. +    unsigned int i(0);
  1061. +    do {
  1062. +      amlcodec->PollFrame();
  1063. +      videopts = get_pts("/sys/class/tsync/pts_video");
  1064. +    } while (i++ < 5 && videopts == m_prevVPts);
  1065. +  }
  1066. +  m_prevVPts = videopts;
  1067.  
  1068. -    CAMLCodec *amlcodec = amli->getAmlCodec();
  1069. -    if (amlcodec)
  1070. +  if (amli)
  1071. +  {
  1072. +    int pts = amli->GetOmxPts();
  1073. +
  1074. +    int pcrscr(get_pts("/sys/class/tsync/pts_pcrscr"));
  1075. +    int diff(static_cast<int>((pcrscr - pts)*1.1 / amli->GetAmlDuration()));
  1076. +    m_diff_counter += diff;
  1077. +
  1078. +    if(!diff)
  1079. +    {
  1080. +      if (m_diff_counter > 0)
  1081. +        --m_diff_counter;
  1082. +      else if (m_diff_counter < 0)
  1083. +        ++m_diff_counter;
  1084. +    }
  1085. +
  1086. +    if (abs(m_diff_counter) > 5)
  1087. +    {
  1088. +      set_pts("/sys/class/tsync/pts_pcrscr", pts);
  1089. +      CLog::Log(LOGDEBUG, "RenderUpdate: Adjusting: ptsclock:%d ptsscr:%d vpts:%d dur:%d diff:%d diffsum:%d", pts, pcrscr, videopts,amli->GetAmlDuration(), diff, m_diff_counter);
  1090. +      pcrscr = pts;
  1091. +      m_diff_counter = 0;
  1092. +    }
  1093. +    else if (g_advancedSettings.CanLogComponent(LOGVIDEO))
  1094. +    {
  1095. +      CLog::Log(LOGDEBUG, "RenderUpdate: ptsclock:%d ptsscr:%d vpts:%d diff:%d", pts, pcrscr, videopts, m_diff_counter);
  1096. +    }
  1097. +
  1098. +    SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", pcrscr);
  1099. +
  1100. +    if(amlcodec)
  1101.        amlcodec->SetVideoRect(m_sourceRect, m_destRect);
  1102.    }
  1103. -
  1104. -  usleep(10000);
  1105. -
  1106. -  return true;
  1107.  }
  1108.  
  1109.  #endif
  1110. diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h
  1111. index 828f584..7b4203b 100644
  1112. --- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h
  1113. +++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h
  1114. @@ -24,17 +24,29 @@
  1115.  
  1116.  #if defined(HAS_LIBAMCODEC)
  1117.  
  1118. -#include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h"
  1119. +#include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h"
  1120.  
  1121. -class CRendererAML : public CLinuxRendererGLES
  1122. +class CRendererAML : public CBaseRenderer
  1123.  {
  1124.  public:
  1125.    CRendererAML();
  1126.    virtual ~CRendererAML();
  1127. -  
  1128. +
  1129.    virtual bool RenderCapture(CRenderCapture* capture);
  1130.    virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index);
  1131.    virtual void ReleaseBuffer(int idx);
  1132. +  virtual bool Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_formatl, unsigned int orientation);
  1133. +  virtual bool IsConfigured(){ return m_bConfigured; };
  1134. +  virtual CRenderInfo GetRenderInfo();
  1135. +  virtual int GetImage(YV12Image *image, int source = -1, bool readonly = false);
  1136. +  virtual void ReleaseImage(int source, bool preserve = false){};
  1137. +  virtual void FlipPage(int source);
  1138. +  virtual void PreInit(){};
  1139. +  virtual void UnInit(){};
  1140. +  virtual void Reset();
  1141. +  virtual void Update(){};
  1142. +  virtual void RenderUpdate(bool clear, unsigned int flags = 0, unsigned int alpha = 255);
  1143. +  virtual bool SupportsMultiPassRendering(){ return false; };
  1144.  
  1145.    // Player functions
  1146.    virtual bool IsGuiLayer();
  1147. @@ -47,16 +59,20 @@ public:
  1148.  
  1149.    virtual EINTERLACEMETHOD AutoInterlaceMethod();
  1150.  
  1151. -protected:
  1152. +private:
  1153. +
  1154. +  int m_iRenderBuffer;
  1155. +  static const int m_numRenderBuffers = 4;
  1156.  
  1157. -  // hooks for hw dec renderer
  1158. -  virtual bool LoadShadersHook();
  1159. -  virtual bool RenderHook(int index);  
  1160. -  virtual int  GetImageHook(YV12Image *image, int source = AUTOSOURCE, bool readonly = false);
  1161. -  virtual bool RenderUpdateVideoHook(bool clear, DWORD flags = 0, DWORD alpha = 255);
  1162. +  struct BUFFER
  1163. +  {
  1164. +    void *hwDec;
  1165. +    int duration;
  1166. +  } m_buffers[m_numRenderBuffers];
  1167.  
  1168. -private:
  1169. -  int m_prevPts;
  1170. +  int m_prevVPts;
  1171. +  bool m_bConfigured;
  1172. +  int m_diff_counter;
  1173.  };
  1174.  
  1175.  #endif
  1176. diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp
  1177. index d0a4c20..be942a1 100644
  1178. --- a/xbmc/utils/BitstreamConverter.cpp
  1179. +++ b/xbmc/utils/BitstreamConverter.cpp
  1180. @@ -72,6 +72,34 @@ enum {
  1181.      HEVC_NAL_SEI_SUFFIX = 40
  1182.  };
  1183.  
  1184. +enum {
  1185. +  SEI_BUFFERING_PERIOD = 0,
  1186. +  SEI_PIC_TIMING,
  1187. +  SEI_PAN_SCAN_RECT,
  1188. +  SEI_FILLER_PAYLOAD,
  1189. +  SEI_USER_DATA_REGISTERED_ITU_T_T35,
  1190. +  SEI_USER_DATA_UNREGISTERED,
  1191. +  SEI_RECOVERY_POINT,
  1192. +  SEI_DEC_REF_PIC_MARKING_REPETITION,
  1193. +  SEI_SPARE_PIC,
  1194. +  SEI_SCENE_INFO,
  1195. +  SEI_SUB_SEQ_INFO,
  1196. +  SEI_SUB_SEQ_LAYER_CHARACTERISTICS,
  1197. +  SEI_SUB_SEQ_CHARACTERISTICS,
  1198. +  SEI_FULL_FRAME_FREEZE,
  1199. +  SEI_FULL_FRAME_FREEZE_RELEASE,
  1200. +  SEI_FULL_FRAME_SNAPSHOT,
  1201. +  SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START,
  1202. +  SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END,
  1203. +  SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET,
  1204. +  SEI_FILM_GRAIN_CHARACTERISTICS,
  1205. +  SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE,
  1206. +  SEI_STEREO_VIDEO_INFO,
  1207. +  SEI_POST_FILTER_HINTS,
  1208. +  SEI_TONE_MAPPING
  1209. +};
  1210. +
  1211. +
  1212.  ////////////////////////////////////////////////////////////////////////////////////////////
  1213.  /////////////////////////////////////////////////////////////////////////////////////////////
  1214.  // GStreamer h264 parser
  1215. @@ -205,6 +233,34 @@ static const uint8_t* avc_find_startcode(const uint8_t *p, const uint8_t *end)
  1216.    return out;
  1217.  }
  1218.  
  1219. +static bool has_sei_recovery_point(const uint8_t *p, const uint8_t *end)
  1220. +{
  1221. +  int pt(0), ps(0), offset(1);
  1222. +
  1223. +  do
  1224. +  {
  1225. +    pt = 0;
  1226. +    do {
  1227. +      pt += p[offset];
  1228. +    } while (p[offset++] == 0xFF);
  1229. +
  1230. +    ps = 0;
  1231. +    do {
  1232. +      ps += p[offset];
  1233. +    } while (p[offset++] == 0xFF);
  1234. +
  1235. +    if (pt == SEI_RECOVERY_POINT)
  1236. +    {
  1237. +      nal_bitstream bs;
  1238. +      nal_bs_init(&bs, p + offset, ps);
  1239. +      return nal_bs_read_ue(&bs) >= 0;
  1240. +    }
  1241. +    offset += ps;
  1242. +  } while(p + offset < end && p[offset] != 0x80);
  1243. +
  1244. +  return false;
  1245. +}
  1246. +
  1247.  ////////////////////////////////////////////////////////////////////////////////////////////
  1248.  /////////////////////////////////////////////////////////////////////////////////////////////
  1249.  CBitstreamParser::CBitstreamParser()
  1250. @@ -255,49 +311,43 @@ const uint8_t* CBitstreamParser::find_start_code(const uint8_t *p,
  1251.    return p + 4;
  1252.  }
  1253.  
  1254. -bool CBitstreamParser::FindIdrSlice(const uint8_t *buf, int buf_size)
  1255. +bool CBitstreamParser::HasKeyframe(const uint8_t *buf, int buf_size)
  1256.  {
  1257.    if (!buf)
  1258.      return false;
  1259.  
  1260.    bool rtn = false;
  1261.    uint32_t state = -1;
  1262. -  const uint8_t *buf_end = buf + buf_size;
  1263. +  const uint8_t *buf_begin, *buf_end = buf + buf_size;
  1264.  
  1265. -  for(;;)
  1266. +  for(;rtn == false;)
  1267.    {
  1268.      buf = find_start_code(buf, buf_end, &state);
  1269.      if (buf >= buf_end)
  1270.      {
  1271. -      //CLog::Log(LOGDEBUG, "FindIdrSlice: buf(%p), buf_end(%p)", buf, buf_end);
  1272.        break;
  1273.      }
  1274.  
  1275. -    --buf;
  1276. -    int src_length = buf_end - buf;
  1277.      switch (state & 0x1f)
  1278.      {
  1279. -      default:
  1280. -        CLog::Log(LOGDEBUG, "FindIdrSlice: found nal_type(%d)", state & 0x1f);
  1281. -        break;
  1282.        case AVC_NAL_SLICE:
  1283. -        CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_SLICE");
  1284.          break;
  1285.        case AVC_NAL_IDR_SLICE:
  1286. -        CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_IDR_SLICE");
  1287.          rtn = true;
  1288.          break;
  1289.        case AVC_NAL_SEI:
  1290. -        CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_SEI");
  1291. +        buf_begin = buf - 1;
  1292. +        buf = find_start_code(buf, buf_end, &state) - 4;
  1293. +        if (has_sei_recovery_point(buf_begin, buf))
  1294. +          rtn = true;
  1295.          break;
  1296.        case AVC_NAL_SPS:
  1297. -        CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_SPS");
  1298.          break;
  1299.        case AVC_NAL_PPS:
  1300. -        CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_PPS");
  1301. +        break;
  1302. +      default:
  1303.          break;
  1304.      }
  1305. -    buf += src_length;
  1306.    }
  1307.  
  1308.    return rtn;
  1309. @@ -318,6 +368,7 @@ CBitstreamConverter::CBitstreamConverter()
  1310.    m_convert_3byteTo4byteNALSize = false;
  1311.    m_convert_bytestream = false;
  1312.    m_sps_pps_context.sps_pps_data = NULL;
  1313. +  m_has_keyframe = true;
  1314.  }
  1315.  
  1316.  CBitstreamConverter::~CBitstreamConverter()
  1317. @@ -397,7 +448,7 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int
  1318.              // are valid, setup to convert 3 byte NAL sizes to 4 byte.
  1319.              in_extradata[4] = 0xFF;
  1320.              m_convert_3byteTo4byteNALSize = true;
  1321. -          
  1322. +
  1323.              m_extradata = (uint8_t *)av_malloc(in_extrasize);
  1324.              memcpy(m_extradata, in_extradata, in_extrasize);
  1325.              m_extrasize = in_extrasize;
  1326. @@ -508,7 +559,7 @@ void CBitstreamConverter::Close(void)
  1327.  bool CBitstreamConverter::Convert(uint8_t *pData, int iSize)
  1328.  {
  1329.    if (m_convertBuffer)
  1330. -  {  
  1331. +  {
  1332.      av_free(m_convertBuffer);
  1333.      m_convertBuffer = NULL;
  1334.    }
  1335. @@ -558,7 +609,7 @@ bool CBitstreamConverter::Convert(uint8_t *pData, int iSize)
  1336.        {
  1337.          m_inputSize = iSize;
  1338.          m_inputBuffer = pData;
  1339. -  
  1340. +
  1341.          if (m_convert_bytestream)
  1342.          {
  1343.            if(m_convertBuffer)
  1344. @@ -646,6 +697,16 @@ int CBitstreamConverter::GetExtraSize() const
  1345.      return m_extrasize;
  1346.  }
  1347.  
  1348. +void CBitstreamConverter::ResetKeyframe(void)
  1349. +{
  1350. +  m_has_keyframe = false;
  1351. +}
  1352. +
  1353. +bool CBitstreamConverter::HasKeyframe() const
  1354. +{
  1355. +  return m_has_keyframe;
  1356. +}
  1357. +
  1358.  bool CBitstreamConverter::BitstreamConvertInitAVC(void *in_extradata, int in_extrasize)
  1359.  {
  1360.    // based on h264_mp4toannexb_bsf.c (ffmpeg)
  1361. @@ -860,7 +921,7 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **
  1362.    int i;
  1363.    uint8_t *buf = pData;
  1364.    uint32_t buf_size = iSize;
  1365. -  uint8_t  unit_type, nal_sps, nal_pps;
  1366. +  uint8_t  unit_type, nal_sps, nal_pps, nal_sei;
  1367.    int32_t  nal_size;
  1368.    uint32_t cumul_size = 0;
  1369.    const uint8_t *buf_end = buf + buf_size;
  1370. @@ -870,10 +931,12 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **
  1371.      case AV_CODEC_ID_H264:
  1372.        nal_sps = AVC_NAL_SPS;
  1373.        nal_pps = AVC_NAL_PPS;
  1374. +      nal_sei = AVC_NAL_SEI;
  1375.        break;
  1376.      case AV_CODEC_ID_HEVC:
  1377.        nal_sps = HEVC_NAL_SPS;
  1378.        nal_pps = HEVC_NAL_PPS;
  1379. +      nal_sei = HEVC_NAL_SEI_PREFIX;
  1380.        break;
  1381.      default:
  1382.        return false;
  1383. @@ -904,7 +967,10 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t **
  1384.      if (m_sps_pps_context.first_idr && (unit_type == nal_sps || unit_type == nal_pps))
  1385.        m_sps_pps_context.idr_sps_pps_seen = 1;
  1386.  
  1387. -      // prepend only to the first access unit of an IDR picture, if no sps/pps already present
  1388. +    if (!m_has_keyframe && (IsIDR(unit_type) || (unit_type == nal_sei && has_sei_recovery_point(buf, buf + nal_size))))
  1389. +      m_has_keyframe = true;
  1390. +
  1391. +    // prepend only to the first access unit of an IDR picture, if no sps/pps already present
  1392.      if (m_sps_pps_context.first_idr && IsIDR(unit_type) && !m_sps_pps_context.idr_sps_pps_seen)
  1393.      {
  1394.        BitstreamAllocAndCopy(poutbuf, poutbuf_size,
  1395. diff --git a/xbmc/utils/BitstreamConverter.h b/xbmc/utils/BitstreamConverter.h
  1396. index 9045ef9..d953907 100644
  1397. --- a/xbmc/utils/BitstreamConverter.h
  1398. +++ b/xbmc/utils/BitstreamConverter.h
  1399. @@ -137,7 +137,7 @@ public:
  1400.  
  1401.    static bool Open();
  1402.    static void Close();
  1403. -  static bool FindIdrSlice(const uint8_t *buf, int buf_size);
  1404. +  static bool HasKeyframe(const uint8_t *buf, int buf_size);
  1405.  
  1406.  protected:
  1407.    static const uint8_t* find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state);
  1408. @@ -157,6 +157,8 @@ public:
  1409.    int               GetConvertSize() const;
  1410.    uint8_t*          GetExtraData(void) const;
  1411.    int               GetExtraSize() const;
  1412. +  void              ResetKeyframe(void);
  1413. +  bool              HasKeyframe() const;
  1414.  
  1415.    static void       bits_reader_set( bits_reader_t *br, uint8_t *buf, int len );
  1416.    static uint32_t   read_bits( bits_reader_t *br, int nbits );
  1417. @@ -207,5 +209,6 @@ protected:
  1418.    bool              m_convert_3byteTo4byteNALSize;
  1419.    bool              m_convert_bytestream;
  1420.    AVCodecID         m_codec;
  1421. +  bool              m_has_keyframe;
  1422.  };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement