diff --git a/packages/mediacenter/kodi/patches/kodi-999.16-amlogic_timing.patch b/packages/mediacenter/kodi/patches/kodi-999.16-amlogic_timing.patch new file mode 100644 index 0000000000..3bdf39c591 --- /dev/null +++ b/packages/mediacenter/kodi/patches/kodi-999.16-amlogic_timing.patch @@ -0,0 +1,4262 @@ +From f35b302861b90fb25acad6ea3430e95a58ac394e Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Fri, 18 Nov 2016 14:39:30 +0100 +Subject: [PATCH 01/30] sync kodi clock to AML clock + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 219 +++++++++++---------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 26 ++- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 34 ++-- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 5 +- + .../VideoRenderers/HwDecRender/RendererAML.cpp | 137 ++++++++++--- + .../VideoRenderers/HwDecRender/RendererAML.h | 36 +++- + 6 files changed, 286 insertions(+), 171 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index c38c223..0ab8567 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -26,6 +26,7 @@ + #include "cores/VideoPlayer/DVDClock.h" + #include "cores/VideoPlayer/VideoRenderers/RenderFlags.h" + #include "cores/VideoPlayer/VideoRenderers/RenderManager.h" ++#include "settings/AdvancedSettings.h" + #include "guilib/GraphicContext.h" + #include "settings/DisplaySettings.h" + #include "settings/MediaSettings.h" +@@ -49,11 +50,11 @@ extern "C" { + #include + #include + #include +-#include + #include + #include + #include + #include ++#include + #include + + // amcodec include +@@ -133,6 +134,11 @@ class DllLibamCodecInterface + virtual int codec_set_cntl_mode(codec_para_t *pcodec, unsigned int mode)=0; + virtual int codec_set_cntl_avthresh(codec_para_t *pcodec, unsigned int avthresh)=0; + virtual int codec_set_cntl_syncthresh(codec_para_t *pcodec, unsigned int syncthresh)=0; ++ ++ virtual int codec_set_av_threshold(codec_para_t *pcodec, int threshold)=0; ++ virtual int codec_set_video_delay_limited_ms(codec_para_t *pcodec,int delay_ms)=0; ++ virtual int codec_get_video_delay_limited_ms(codec_para_t *pcodec,int *delay_ms)=0; ++ virtual int codec_get_video_cur_delay_ms(codec_para_t *pcodec,int *delay_ms)=0; + }; + + class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface +@@ -156,6 +162,11 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface + DEFINE_METHOD2(int, codec_set_cntl_avthresh, (codec_para_t *p1, unsigned int p2)) + DEFINE_METHOD2(int, codec_set_cntl_syncthresh,(codec_para_t *p1, unsigned int p2)) + ++ DEFINE_METHOD2(int, codec_set_av_threshold, (codec_para_t *p1, int p2)) ++ DEFINE_METHOD2(int, codec_set_video_delay_limited_ms, (codec_para_t *p1, int p2)) ++ DEFINE_METHOD2(int, codec_get_video_delay_limited_ms, (codec_para_t *p1, int *p2)) ++ DEFINE_METHOD2(int, codec_get_video_cur_delay_ms, (codec_para_t *p1, int *p2)) ++ + BEGIN_METHOD_RESOLVE() + RESOLVE_METHOD(codec_init) + RESOLVE_METHOD(codec_close) +@@ -172,6 +183,11 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface + RESOLVE_METHOD(codec_set_cntl_mode) + RESOLVE_METHOD(codec_set_cntl_avthresh) + RESOLVE_METHOD(codec_set_cntl_syncthresh) ++ ++ RESOLVE_METHOD(codec_set_av_threshold) ++ RESOLVE_METHOD(codec_set_video_delay_limited_ms) ++ RESOLVE_METHOD(codec_get_video_delay_limited_ms) ++ RESOLVE_METHOD(codec_get_video_cur_delay_ms) + END_METHOD_RESOLVE() + + public: +@@ -273,7 +289,7 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface + + #define PTS_FREQ 90000 + #define UNIT_FREQ 96000 +-#define AV_SYNC_THRESH PTS_FREQ*30 ++#define AV_SYNC_THRESH PTS_FREQ*0 + + #define TRICKMODE_NONE 0x00 + #define TRICKMODE_I 0x01 +@@ -371,6 +387,18 @@ typedef struct am_private_t + bool dumpdemux; + } am_private_t; + ++typedef struct vframe_states ++{ ++ int vf_pool_size; ++ int buf_free_num; ++ int buf_recycle_num; ++ int buf_avail_num; ++} vframe_states_t; ++ ++#define AMSTREAM_IOC_MAGIC 'S' ++#define AMSTREAM_IOC_VF_STATUS _IOR(AMSTREAM_IOC_MAGIC, 0x60, unsigned long) ++ ++ + /*************************************************************************/ + /*************************************************************************/ + void dumpfile_open(am_private_t *para) +@@ -713,7 +741,7 @@ int write_av_packet(am_private_t *para, am_packet_t *pkt) + } + pkt->newflag = 0; + } +- ++ + buf = pkt->data; + size = pkt->data_size ; + if (size == 0 && pkt->isvalid) { +@@ -1380,9 +1408,12 @@ int set_header_info(am_private_t *para) + + /*************************************************************************/ + CAMLCodec::CAMLCodec() +- : CThread("CAMLCodec") ++ : m_prefill_state(PREFILL_STATE_FILLING) ++ , m_opened(false) ++ , m_ptsIs64us(false) ++ , m_last_pts(0) ++ , m_cur_pts(0) + { +- m_opened = false; + am_private = new am_private_t; + memset(am_private, 0, sizeof(am_private_t)); + m_dll = new DllLibAmCodec; +@@ -1402,12 +1433,26 @@ CAMLCodec::CAMLCodec() + + CAMLCodec::~CAMLCodec() + { +- StopThread(); + delete am_private; + am_private = NULL; + delete m_dll, m_dll = NULL; + } + ++float CAMLCodec::OMXPtsToSeconds(int omxpts) ++{ ++ return static_cast(omxpts) / PTS_FREQ; ++} ++ ++int CAMLCodec::OMXDurationToNs(int duration) ++{ ++ return static_cast(static_cast(duration) / PTS_FREQ * 1000000 ); ++} ++ ++int CAMLCodec::GetAmlDuration() const ++{ ++ return am_private ? (am_private->video_rate * PTS_FREQ) / UNIT_FREQ : 0; ++}; ++ + bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + { + #ifdef TARGET_ANDROID +@@ -1415,7 +1460,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + #endif + + m_speed = DVD_PLAYSPEED_NORMAL; +- m_1st_pts = 0; + m_cur_pts = 0; + m_dst_rect.SetRect(0, 0, 0, 0); + m_zoom = -1; +@@ -1615,9 +1659,10 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + am_private->dumpdemux = false; + dumpfile_open(am_private); + +- //! @bug make sure we are not stuck in pause (amcodec bug) + m_dll->codec_resume(&am_private->vcodec); ++ + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); ++ m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000); + + m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); + m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); +@@ -1627,8 +1672,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + am_private->am_pkt.codec = &am_private->vcodec; + pre_header_feeding(am_private, &am_private->am_pkt); + +- Create(); +- + m_display_rect = CRect(0, 0, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iWidth, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iHeight); + + std::string strScaler; +@@ -1636,16 +1679,19 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + if (strScaler.find("enabled") == std::string::npos) // Scaler not enabled, use screen size + m_display_rect = CRect(0, 0, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iScreenWidth, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iScreenHeight); + +-/* +- // if display is set to 1080xxx, then disable deinterlacer for HD content +- // else bandwidth usage is too heavy and it will slow down video decoder. +- char display_mode[256] = {0}; +- SysfsUtils::GetString("/sys/class/display/mode", display_mode, 255); +- if (strstr(display_mode,"1080")) +- SysfsUtils::SetInt("/sys/module/di/parameters/bypass_all", 1); +- else +- SysfsUtils::SetInt("/sys/module/di/parameters/bypass_all", 0); +-*/ ++ SysfsUtils::SetInt("/sys/class/video/freerun_mode", 0); ++ ++ ++ struct utsname un; ++ if (uname(&un) == 0) ++ { ++ int linuxversion[2]; ++ sscanf(un.release,"%d.%d", &linuxversion[0], &linuxversion[1]); ++ if (linuxversion[0] > 3 || (linuxversion[0] == 3 && linuxversion[1] >= 14)) ++ m_ptsIs64us = true; ++ } ++ ++ CLog::Log(LOGNOTICE, "CAMLCodec::OpenDecoder - using V4L2 pts format: %s", m_ptsIs64us ? "64Bit":"32Bit"); + + m_opened = true; + // vcodec is open, update speed if it was +@@ -1705,7 +1751,6 @@ void CAMLCodec::SetVfmMap(const std::string &name, const std::string &map) + void CAMLCodec::CloseDecoder() + { + CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder"); +- StopThread(); + + // never leave vcodec ff/rw or paused. + if (m_speed != DVD_PLAYSPEED_NORMAL) +@@ -1754,6 +1799,8 @@ void CAMLCodec::Reset() + } + // reset the decoder + m_dll->codec_reset(&am_private->vcodec); ++ m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000); ++ + dumpfile_close(am_private); + dumpfile_open(am_private); + +@@ -1767,9 +1814,8 @@ void CAMLCodec::Reset() + SysfsUtils::SetInt("/sys/class/video/blackout_policy", blackout_policy); + + // reset some interal vars +- m_1st_pts = 0; + m_cur_pts = 0; +- m_ptsQueue.clear(); ++ m_prefill_state = PREFILL_STATE_FILLING; + SetSpeed(m_speed); + } + +@@ -1778,6 +1824,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (!m_opened) + return VC_BUFFER; + ++ float timesize(static_cast(GetTimeSize())); + if (pData) + { + am_private->am_pkt.data = pData; +@@ -1813,9 +1860,6 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE) + am_private->am_pkt.avdts -= m_start_dts; + +- //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: iSize(%d), dts(%f), pts(%f), avdts(%llx), avpts(%llx)", +- // iSize, dts, pts, am_private->am_pkt.avdts, am_private->am_pkt.avpts); +- + // some formats need header/data tweaks. + // the actual write occurs once in write_av_packet + // and is controlled by am_pkt.newflag. +@@ -1840,47 +1884,39 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + // Decoder got stuck; Reset + Reset(); + } +- +- // if we seek, then GetTimeSize is wrong as +- // reports lastpts - cur_pts and hw decoder has +- // not started outputing new pts values yet. +- // so we grab the 1st pts sent into driver and +- // use that to calc GetTimeSize. +- if (m_1st_pts == 0) +- m_1st_pts = am_private->am_pkt.lastpts; ++ if (m_prefill_state == PREFILL_STATE_FILLING && timesize >= 1.0) ++ m_prefill_state = PREFILL_STATE_FILLED; + } + +- // if we have still frames, demux size will be small +- // and we need to pre-buffer more. +- double target_timesize = 1.0; +- if (iSize < 20) +- target_timesize = 2.0; +- +- int rtn = 0; +- +- // keep hw buffered demux above 1 second +- if (GetTimeSize() < target_timesize) +- rtn |= VC_BUFFER; +- +- // wait until we get a new frame or 25ms, +- if (m_ptsQueue.size() == 0) +- m_ready_event.WaitMSec(25); +- +- if (m_ptsQueue.size() > 0) ++ int rtn(0); ++ int64_t decode_pts = 0; ++ if (m_prefill_state == PREFILL_STATE_FILLED && timesize > 0.5 && DequeueBuffer(decode_pts) == 0) + { +- CSingleLock lock(m_ptsQueueMutex); +- m_cur_pts = m_ptsQueue.front(); +- m_ptsQueue.pop_front(); + rtn |= VC_PICTURE; ++ m_last_pts = m_cur_pts; ++ m_cur_pts = decode_pts; + } +-/* +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: " +- "rtn(%d), m_cur_pictcnt(%lld), m_cur_pts(%f), lastpts(%f), GetTimeSize(%f), GetDataSize(%d)", +- rtn, m_cur_pictcnt, (float)m_cur_pts/PTS_FREQ, (float)am_private->am_pkt.lastpts/PTS_FREQ, GetTimeSize(), GetDataSize()); +-*/ ++ if ((rtn & VC_PICTURE)==0 || timesize < 1.0) ++ rtn |= VC_BUFFER; ++ ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d dts_in: %0.6f, pts_in: %0.6f, ptsOut:%0.6f, amlpts:%d timesize:%0.2f", ++ rtn, ++ static_cast(dts)/DVD_TIME_BASE, ++ static_cast(pts)/DVD_TIME_BASE, ++ static_cast(m_cur_pts)/PTS_FREQ, ++ static_cast(m_cur_pts), ++ timesize ++ ); ++ + return rtn; + } + ++int CAMLCodec::PollFrame() ++{ ++ return m_dll->codec_poll_cntl(&am_private->vcodec); ++} ++ + int CAMLCodec::DequeueBuffer(int64_t &pts) + { + v4l2_buffer vbuf = { 0 }; +@@ -1896,7 +1932,7 @@ int CAMLCodec::DequeueBuffer(int64_t &pts) + // Since kernel 3.14 Amlogic changed length and units of PTS values reported here. + // To differentiate such PTS values we check for existence of omx_pts_interval_lower + // parameter, because it was introduced since kernel 3.14. +- if (access("/sys/module/amvideo/parameters/omx_pts_interval_lower", F_OK) != -1) ++ if (m_ptsIs64us) + { + pts = vbuf.timestamp.tv_sec & 0xFFFFFFFF; + pts <<= 32; +@@ -1917,18 +1953,17 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + + pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; + pDvdVideoPicture->format = RENDER_FMT_AML; +- pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; + +- pDvdVideoPicture->dts = DVD_NOPTS_VALUE; +- if (m_speed == DVD_PLAYSPEED_NORMAL) +- pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE; ++ if (m_last_pts <= 0) ++ pDvdVideoPicture->iDuration = (double)(am_private->video_rate * DVD_TIME_BASE) / UNIT_FREQ; + else +- { +- if (m_cur_pts == 0) +- pDvdVideoPicture->pts = (double)m_1st_pts / PTS_FREQ * DVD_TIME_BASE; +- else +- pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE; +- } ++ pDvdVideoPicture->iDuration = (double)((m_cur_pts - m_last_pts) * DVD_TIME_BASE) / PTS_FREQ; ++ ++ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; ++ pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE; ++ ++ //AML video is ~ 2 frames to fast - sync audio ++ pDvdVideoPicture->pts += 2*pDvdVideoPicture->iDuration; + + return true; + } +@@ -1981,17 +2016,13 @@ double CAMLCodec::GetTimeSize() + if (!m_opened) + return 0; + +- // if m_cur_pts is zero, hw decoder was not started yet +- // so we use the pts of the 1st demux packet that was send +- // to hw decoder to calc timesize. +- if (m_cur_pts == 0) +- m_timesize = (double)(am_private->am_pkt.lastpts - m_1st_pts) / PTS_FREQ; +- else +- m_timesize = (double)(am_private->am_pkt.lastpts - GetOMXPts()) / PTS_FREQ; ++ int video_delay_ms; ++ double timesize(0); ++ if (m_dll->codec_get_video_cur_delay_ms(&am_private->vcodec, &video_delay_ms) >= 0) ++ timesize = (float)video_delay_ms / 1000.0; + + // lie to VideoPlayer, it is hardcoded to a max of 8 seconds, + // if you buffer more than 8 seconds, it goes nuts. +- double timesize = m_timesize; + if (timesize < 0.0) + timesize = 0.0; + else if (timesize > 7.0) +@@ -2000,32 +2031,6 @@ double CAMLCodec::GetTimeSize() + return timesize; + } + +-void CAMLCodec::Process() +-{ +- CLog::Log(LOGDEBUG, "CAMLCodec::Process Started"); +- +- while (!m_bStop) +- { +- if (m_dll->codec_poll_cntl(&am_private->vcodec) < 0) +- { +- CLog::Log(LOGDEBUG, "CAMLCodec::Process: codec_poll_cntl failed"); +- Sleep(10); +- } +- +- { +- CSingleLock lock(m_ptsQueueMutex); +- int64_t pts = 0; +- if (DequeueBuffer(pts) == 0) +- { +- m_ptsQueue.push_back(pts + m_start_pts); +- m_ready_event.Set(); +- } +- } +- } +- +- CLog::Log(LOGDEBUG, "CAMLCodec::Process Stopped"); +-} +- + void CAMLCodec::ShowMainVideo(const bool show) + { + static int saved_disable_video = -1; +@@ -2273,3 +2278,9 @@ void CAMLCodec::SetVideoRect(const CRect &SrcRect, const CRect &DestRect) + // that would show video playback, so show it. + ShowMainVideo(true); + } ++ ++void CAMLCodec::SetVideoRate(int videoRate) ++{ ++ if (am_private) ++ am_private->video_rate = videoRate; ++} +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 0eb5c3e..33fa0b7 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -24,8 +24,6 @@ + #include "cores/IPlayer.h" + #include "guilib/Geometry.h" + #include "rendering/RenderSystem.h" +-#include "threads/Thread.h" +-#include + + typedef struct am_private_t am_private_t; + +@@ -34,7 +32,7 @@ class DllLibAmCodec; + class PosixFile; + typedef std::shared_ptr PosixFilePtr; + +-class CAMLCodec : public CThread ++class CAMLCodec + { + public: + CAMLCodec(); +@@ -51,11 +49,13 @@ class CAMLCodec : public CThread + int GetDataSize(); + double GetTimeSize(); + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); ++ void SetVideoRate(int videoRate); + int64_t GetCurPts() const { return m_cur_pts; } + int GetOMXPts() const { return static_cast(m_cur_pts - m_start_pts); } +- +-protected: +- virtual void Process(); ++ static float OMXPtsToSeconds(int omxpts); ++ static int OMXDurationToNs(int duration); ++ int GetAmlDuration() const; ++ int PollFrame(); + + private: + void ShowMainVideo(const bool show); +@@ -73,16 +73,15 @@ class CAMLCodec : public CThread + + DllLibAmCodec *m_dll; + bool m_opened; ++ bool m_ptsIs64us; + am_private_t *am_private; + CDVDStreamInfo m_hints; + volatile int m_speed; +- volatile int64_t m_1st_pts; + volatile int64_t m_cur_pts; +- volatile double m_timesize; + volatile int64_t m_vbufsize; + int64_t m_start_dts; + int64_t m_start_pts; +- CEvent m_ready_event; ++ int64_t m_last_pts; + + CRect m_dst_rect; + CRect m_display_rect; +@@ -94,8 +93,15 @@ class CAMLCodec : public CThread + int m_contrast; + int m_brightness; + ++ enum PREFILLSTATE ++ { ++ PREFILL_STATE_FILLING, ++ PREFILL_STATE_FILLED ++ }; ++ PREFILLSTATE m_prefill_state; ++ ++ + PosixFilePtr m_amlVideoFile; + std::string m_defaultVfmMap; +- std::deque m_ptsQueue; + CCriticalSection m_ptsQueueMutex; + }; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index a27d3e3..a0f847a 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -30,6 +30,7 @@ + #include "utils/SysfsUtils.h" + #include "threads/Atomics.h" + #include "settings/Settings.h" ++#include "threads/Thread.h" + + #define __MODULE_NAME__ "DVDVideoCodecAmlogic" + +@@ -236,6 +237,7 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option + m_processInfo.SetVideoDecoderName(m_pFormatName, true); + m_processInfo.SetVideoDimensions(m_hints.width, m_hints.height); + m_processInfo.SetVideoDeintMethod("hardware"); ++ m_processInfo.SetVideoDAR(m_hints.aspect); + + CLog::Log(LOGINFO, "%s: Opened Amlogic Codec", __MODULE_NAME__); + return true; +@@ -315,7 +317,7 @@ bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) + m_Codec->GetPicture(&m_videobuffer); + *pDvdVideoPicture = m_videobuffer; + +- CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec, m_Codec->GetOMXPts()); ++ CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec, m_Codec->GetOMXPts(), m_Codec->GetAmlDuration()); + + { + CSingleLock lock(m_secure); +@@ -363,7 +365,7 @@ void CDVDVideoCodecAmlogic::SetDropState(bool bDrop) + // Freerun mode causes amvideo driver to ignore timing and process frames + // as quickly as they are coming from decoder. By enabling freerun mode we can + // skip rendering of the frames that are requested to be dropped by VideoPlayer. +- SysfsUtils::SetInt("/sys/class/video/freerun_mode", bDrop ? 1 : 0); ++ //SysfsUtils::SetInt("/sys/class/video/freerun_mode", bDrop ? 1 : 0); + } + + void CDVDVideoCodecAmlogic::SetSpeed(int iSpeed) +@@ -466,8 +468,7 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double + m_framerate = m_mpeg2_sequence->rate; + m_video_rate = (int)(0.5 + (96000.0 / m_framerate)); + +- CLog::Log(LOGDEBUG, "%s: detected mpeg2 aspect ratio(%f), framerate(%f), video_rate(%d)", +- __MODULE_NAME__, m_mpeg2_sequence->ratio, m_framerate, m_video_rate); ++ m_processInfo.SetVideoFps(m_framerate); + + // update m_hints for 1st frame fixup. + switch(m_mpeg2_sequence->rate_info) +@@ -526,7 +527,7 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double + if (cur_pts == DVD_NOPTS_VALUE) + cur_pts = m_frame_queue->dts; + +- pthread_mutex_unlock(&m_queue_mutex); ++ pthread_mutex_unlock(&m_queue_mutex); + + float duration = cur_pts - m_last_pts; + m_last_pts = cur_pts; +@@ -559,22 +560,10 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double + break; + + // 25.000 (40000.000000) +- case 40000: ++ case 39900 ... 40100: + framerate = 25000.0 / 1000.0; + break; + +- // 24.975 (40040.000000) +- case 40040: +- framerate = 25000.0 / 1001.0; +- break; +- +- /* +- // 24.000 (41666.666666) +- case 41667: +- framerate = 24000.0 / 1000.0; +- break; +- */ +- + // 23.976 (41708.33333) + case 40200 ... 43200: + // 23.976 seems to have the crappiest encodings :) +@@ -592,6 +581,12 @@ void CDVDVideoCodecAmlogic::FrameRateTracking(uint8_t *pData, int iSize, double + { + m_framerate = framerate; + m_video_rate = (int)(0.5 + (96000.0 / framerate)); ++ ++ if (m_Codec) ++ m_Codec->SetVideoRate(m_video_rate); ++ ++ m_processInfo.SetVideoFps(m_framerate); ++ + CLog::Log(LOGDEBUG, "%s: detected new framerate(%f), video_rate(%d)", + __MODULE_NAME__, m_framerate, m_video_rate); + } +@@ -607,11 +602,12 @@ void CDVDVideoCodecAmlogic::RemoveInfo(CDVDAmlogicInfo *info) + m_inflight.erase(m_inflight.find(info)); + } + +-CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts) ++CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration) + : m_refs(0) + , m_codec(codec) + , m_amlCodec(amlcodec) + , m_omxPts(omxPts) ++ , m_amlDuration(amlDuration) + { + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +index 2c44241..39f408e 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +@@ -36,7 +36,7 @@ class CDVDVideoCodecAmlogic; + class CDVDAmlogicInfo + { + public: +- CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts); ++ CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration); + + // reference counting + CDVDAmlogicInfo* Retain(); +@@ -44,6 +44,7 @@ class CDVDAmlogicInfo + + CAMLCodec *getAmlCodec() const; + int GetOmxPts() const { return m_omxPts; } ++ int GetAmlDuration() const { return m_amlDuration; } + void invalidate(); + + protected: +@@ -52,7 +53,7 @@ class CDVDAmlogicInfo + + CDVDVideoCodecAmlogic* m_codec; + CAMLCodec* m_amlCodec; +- int m_omxPts; ++ int m_omxPts, m_amlDuration; + }; + + class CDVDVideoCodecAmlogic : public CDVDVideoCodec +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index d8674c8..c45e94f 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -21,26 +21,84 @@ + #include "RendererAML.h" + + #if defined(HAS_LIBAMCODEC) +-#include "cores/IPlayer.h" +-#include "windowing/egl/EGLWrapper.h" + #include "cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h" + #include "cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h" + #include "utils/log.h" +-#include "utils/GLUtils.h" + #include "utils/SysfsUtils.h" + #include "settings/MediaSettings.h" + #include "windowing/WindowingFactory.h" + #include "cores/VideoPlayer/VideoRenderers/RenderCapture.h" ++#include "settings/AdvancedSettings.h" ++ ++static int get_pts(const char *strPath) ++{ ++ int fd = open(strPath, O_RDONLY); ++ if (fd >= 0) ++ { ++ char pts_str[64]; ++ int size = read(fd, pts_str, sizeof(pts_str)); ++ close(fd); ++ return strtol(pts_str, NULL, 16); ++ } ++ return 0; ++} ++ ++static void set_pts(const char *strPath, int pts) ++{ ++ int fd = open(strPath, O_WRONLY); ++ if (fd >= 0) ++ { ++ char pts_str[64]; ++ sprintf(pts_str, "0x%x", pts); ++ write(fd, pts_str, strlen(pts_str)); ++ close(fd); ++ } ++} + + CRendererAML::CRendererAML() ++ : m_prevPts(-1) ++ , m_bConfigured(false) ++ , m_iRenderBuffer(0) ++ , m_diff_counter(0) + { +- m_prevPts = -1; + } + + CRendererAML::~CRendererAML() + { + } + ++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) ++{ ++ m_sourceWidth = width; ++ m_sourceHeight = height; ++ m_renderOrientation = orientation; ++ ++ // Save the flags. ++ m_iFlags = flags; ++ m_format = format; ++ ++ // Calculate the input frame aspect ratio. ++ CalculateFrameAspectRatio(d_width, d_height); ++ SetViewMode(CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ViewMode); ++ ManageRenderArea(); ++ ++ m_bConfigured = true; ++ ++ for (int i = 0 ; i < m_numRenderBuffers ; ++i) ++ m_buffers[i].hwDec = 0; ++ ++ return true; ++} ++ ++CRenderInfo CRendererAML::GetRenderInfo() ++{ ++ CRenderInfo info; ++ info.formats.push_back(RENDER_FMT_BYPASS); ++ info.max_buffer_size = m_numRenderBuffers; ++ info.optimal_buffer_size = m_numRenderBuffers; ++ return info; ++} ++ + bool CRendererAML::RenderCapture(CRenderCapture* capture) + { + capture->BeginRender(); +@@ -48,16 +106,28 @@ bool CRendererAML::RenderCapture(CRenderCapture* capture) + return true; + } + ++int CRendererAML::GetImage(YV12Image *image, int source, bool readonly) ++{ ++ if (image == nullptr) ++ return -1; ++ ++ /* take next available buffer */ ++ if (source == -1) ++ source = (m_iRenderBuffer + 1) % m_numRenderBuffers; ++ ++ return source; ++} ++ + void CRendererAML::AddVideoPictureHW(DVDVideoPicture &picture, int index) + { +- YUVBUFFER &buf = m_buffers[index]; ++ BUFFER &buf = m_buffers[index]; + if (picture.amlcodec) + buf.hwDec = picture.amlcodec->Retain(); + } + + void CRendererAML::ReleaseBuffer(int idx) + { +- YUVBUFFER &buf = m_buffers[idx]; ++ BUFFER &buf = m_buffers[idx]; + if (buf.hwDec) + { + CDVDAmlogicInfo *amli = static_cast(buf.hwDec); +@@ -66,9 +136,14 @@ void CRendererAML::ReleaseBuffer(int idx) + } + } + +-int CRendererAML::GetImageHook(YV12Image *image, int source, bool readonly) ++void CRendererAML::FlipPage(int source) + { +- return source; ++ if( source >= 0 && source < m_numRenderBuffers ) ++ m_iRenderBuffer = source; ++ else ++ m_iRenderBuffer = (m_iRenderBuffer + 1) % m_numRenderBuffers; ++ ++ return; + } + + bool CRendererAML::IsGuiLayer() +@@ -104,37 +179,47 @@ EINTERLACEMETHOD CRendererAML::AutoInterlaceMethod() + return VS_INTERLACEMETHOD_NONE; + } + +-bool CRendererAML::LoadShadersHook() ++void CRendererAML::Reset() + { +- CLog::Log(LOGNOTICE, "GL: Using AML render method"); +- m_textureTarget = GL_TEXTURE_2D; +- m_renderMethod = RENDER_BYPASS; +- return false; ++ m_prevPts = 0; ++ m_diff_counter = 0; + } + +-bool CRendererAML::RenderHook(int index) +-{ +- return true;// nothing to be done for aml +-} +- +-bool CRendererAML::RenderUpdateVideoHook(bool clear, DWORD flags, DWORD alpha) ++void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + { + ManageRenderArea(); + +- CDVDAmlogicInfo *amli = static_cast(m_buffers[m_iYV12RenderBuffer].hwDec); ++ CDVDAmlogicInfo *amli = static_cast(m_buffers[m_iRenderBuffer].hwDec); ++ CAMLCodec *amlcodec = amli ? amli->getAmlCodec() : 0; ++ ++ if(amlcodec) ++ amlcodec->PollFrame(); ++ + if (amli && amli->GetOmxPts() != m_prevPts) + { + m_prevPts = amli->GetOmxPts(); +- SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", amli->GetOmxPts()); + +- CAMLCodec *amlcodec = amli->getAmlCodec(); ++ int pcrscr(get_pts("/sys/class/tsync/pts_pcrscr")); ++ m_diff_counter += static_cast((pcrscr - m_prevPts)*1.1 / amli->GetAmlDuration()); ++ ++ if (abs(m_diff_counter) > 2) ++ { ++ int videopts(get_pts("/sys/class/tsync/pts_video")); ++ set_pts("/sys/class/tsync/pts_pcrscr", m_prevPts); ++ CLog::Log(LOGDEBUG, "RenderUpdate: Adjusting: ptsclock:%d ptsscr:%d vpts:%d diff:%d", m_prevPts, pcrscr, videopts, m_diff_counter); ++ pcrscr = m_prevPts; ++ m_diff_counter = 0; ++ } ++ else if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ { ++ int videopts(get_pts("/sys/class/tsync/pts_video")); ++ CLog::Log(LOGDEBUG, "RenderUpdate: ptsclock:%d ptsscr:%d vpts:%d diff:%d", m_prevPts, pcrscr, videopts, m_diff_counter); ++ } ++ SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", pcrscr); ++ + if (amlcodec) + amlcodec->SetVideoRect(m_sourceRect, m_destRect); + } +- +- usleep(10000); +- +- return true; + } + + #endif +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +index 828f584a..bbef504 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +@@ -24,17 +24,29 @@ + + #if defined(HAS_LIBAMCODEC) + +-#include "cores/VideoPlayer/VideoRenderers/LinuxRendererGLES.h" ++#include "cores/VideoPlayer/VideoRenderers/BaseRenderer.h" + +-class CRendererAML : public CLinuxRendererGLES ++class CRendererAML : public CBaseRenderer + { + public: + CRendererAML(); + virtual ~CRendererAML(); +- ++ + virtual bool RenderCapture(CRenderCapture* capture); + virtual void AddVideoPictureHW(DVDVideoPicture &picture, int index); + virtual void ReleaseBuffer(int idx); ++ 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); ++ virtual bool IsConfigured(){ return m_bConfigured; }; ++ virtual CRenderInfo GetRenderInfo(); ++ virtual int GetImage(YV12Image *image, int source = -1, bool readonly = false); ++ virtual void ReleaseImage(int source, bool preserve = false){}; ++ virtual void FlipPage(int source); ++ virtual void PreInit(){}; ++ virtual void UnInit(){}; ++ virtual void Reset(); ++ virtual void Update(){}; ++ virtual void RenderUpdate(bool clear, unsigned int flags = 0, unsigned int alpha = 255); ++ virtual bool SupportsMultiPassRendering(){ return false; }; + + // Player functions + virtual bool IsGuiLayer(); +@@ -47,16 +59,20 @@ class CRendererAML : public CLinuxRendererGLES + + virtual EINTERLACEMETHOD AutoInterlaceMethod(); + +-protected: ++private: ++ ++ int m_iRenderBuffer; ++ static const int m_numRenderBuffers = 3; + +- // hooks for hw dec renderer +- virtual bool LoadShadersHook(); +- virtual bool RenderHook(int index); +- virtual int GetImageHook(YV12Image *image, int source = AUTOSOURCE, bool readonly = false); +- virtual bool RenderUpdateVideoHook(bool clear, DWORD flags = 0, DWORD alpha = 255); ++ struct BUFFER ++ { ++ void *hwDec; ++ int duration; ++ } m_buffers[m_numRenderBuffers]; + +-private: + int m_prevPts; ++ bool m_bConfigured; ++ int m_diff_counter; + }; + + #endif + +From 62209dbd993a5dfe1dc5ee6083c061bbc781ff7f Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Fri, 18 Nov 2016 18:59:35 +0100 +Subject: [PATCH 02/30] Increase size of render buffers (4) + +--- + xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +index bbef504..0d9f126 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +@@ -62,7 +62,7 @@ class CRendererAML : public CBaseRenderer + private: + + int m_iRenderBuffer; +- static const int m_numRenderBuffers = 3; ++ static const int m_numRenderBuffers = 4; + + struct BUFFER + { + +From d4742523c14dbed5724e80c5160334cf09cfedc7 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Fri, 18 Nov 2016 21:38:32 +0100 +Subject: [PATCH 03/30] Limit timesize to be never > 2.0 + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 0ab8567..56884af 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1896,7 +1896,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + m_last_pts = m_cur_pts; + m_cur_pts = decode_pts; + } +- if ((rtn & VC_PICTURE)==0 || timesize < 1.0) ++ if (((rtn & VC_PICTURE)==0 && timesize < 2.0) || timesize < 1.0) + rtn |= VC_BUFFER; + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + +From 514370bfd06881cc972ebd7a6f29c1948f12c91c Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Sat, 19 Nov 2016 20:47:47 +0100 +Subject: [PATCH 04/30] sleep / vfs + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 56884af..6f2cfa9 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1886,6 +1886,8 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + } + if (m_prefill_state == PREFILL_STATE_FILLING && timesize >= 1.0) + m_prefill_state = PREFILL_STATE_FILLED; ++ else if (m_prefill_state == PREFILL_STATE_FILLING) ++ Sleep(1); + } + + int rtn(0); +@@ -1899,13 +1901,24 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (((rtn & VC_PICTURE)==0 && timesize < 2.0) || timesize < 1.0) + rtn |= VC_BUFFER; + ++ vframe_states_t vfs; ++ int fd(open("/dev/amvideo", RD_ONLY); ++ if(fd) ++ { ++ ioctl(fd, AMSTREAM_IOC_VF_STATUS, &vfs); ++ close(fd); ++ } ++ else ++ memset(&vfs, 0, sizeof(vfs)); ++ + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d dts_in: %0.6f, pts_in: %0.6f, ptsOut:%0.6f, amlpts:%d timesize:%0.2f", ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d dts_in: %0.6f, pts_in: %0.6f, ptsOut:%0.6f, amlpts:%d vfs:[%d-%d-%d-%d] timesize:%0.2f", + rtn, + static_cast(dts)/DVD_TIME_BASE, + static_cast(pts)/DVD_TIME_BASE, + static_cast(m_cur_pts)/PTS_FREQ, + static_cast(m_cur_pts), ++ vfs.vf_pool_size, vfs.buf_free_num,vfs.buf_recycle_num,vfs.buf_avail_num, + timesize + ); + + +From 383c5cd6fdaddd7be841fe9898398e0812fa56c1 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Sun, 20 Nov 2016 11:29:13 +0100 +Subject: [PATCH 05/30] log vfstates / throttle prefill + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 34 +++++++++++++--------- + 1 file changed, 20 insertions(+), 14 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 6f2cfa9..920ba29 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1408,11 +1408,11 @@ int set_header_info(am_private_t *para) + + /*************************************************************************/ + CAMLCodec::CAMLCodec() +- : m_prefill_state(PREFILL_STATE_FILLING) +- , m_opened(false) ++ : m_opened(false) + , m_ptsIs64us(false) +- , m_last_pts(0) + , m_cur_pts(0) ++ , m_last_pts(0) ++ , m_prefill_state(PREFILL_STATE_FILLING) + { + am_private = new am_private_t; + memset(am_private, 0, sizeof(am_private_t)); +@@ -1887,7 +1887,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (m_prefill_state == PREFILL_STATE_FILLING && timesize >= 1.0) + m_prefill_state = PREFILL_STATE_FILLED; + else if (m_prefill_state == PREFILL_STATE_FILLING) +- Sleep(1); ++ usleep(1000); + } + + int rtn(0); +@@ -1898,20 +1898,22 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + m_last_pts = m_cur_pts; + m_cur_pts = decode_pts; + } +- if (((rtn & VC_PICTURE)==0 && timesize < 2.0) || timesize < 1.0) ++ if (((rtn & VC_PICTURE) == 0 && timesize < 2.0) || timesize < 1.0) + rtn |= VC_BUFFER; + +- vframe_states_t vfs; +- int fd(open("/dev/amvideo", RD_ONLY); +- if(fd) ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- ioctl(fd, AMSTREAM_IOC_VF_STATUS, &vfs); +- close(fd); +- } +- else +- memset(&vfs, 0, sizeof(vfs)); ++ vframe_states_t vfs; ++ int fd(open("/dev/amvideo", O_RDONLY)); ++ if(fd) ++ { ++ if (ioctl(fd, AMSTREAM_IOC_VF_STATUS, &vfs) != 0) ++ memset(&vfs, 0, sizeof(vfs)); ++ close(fd); ++ } ++ else ++ memset(&vfs, 0, sizeof(vfs)); + +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d dts_in: %0.6f, pts_in: %0.6f, ptsOut:%0.6f, amlpts:%d vfs:[%d-%d-%d-%d] timesize:%0.2f", + rtn, + static_cast(dts)/DVD_TIME_BASE, +@@ -1921,6 +1923,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + vfs.vf_pool_size, vfs.buf_free_num,vfs.buf_recycle_num,vfs.buf_avail_num, + timesize + ); ++ } + + return rtn; + } +@@ -1983,6 +1986,9 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + + void CAMLCodec::SetSpeed(int speed) + { ++ if (m_speed == speed) ++ return; ++ + CLog::Log(LOGDEBUG, "CAMLCodec::SetSpeed, speed(%d)", speed); + + // update internal vars regardless + +From e7885610feb970c3b596c158ab09d7eb53bbe4fb Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Sun, 20 Nov 2016 15:08:31 +0100 +Subject: [PATCH 06/30] throttle during playback as well, not only at prefill + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 920ba29..d038d6a 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1886,8 +1886,6 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + } + if (m_prefill_state == PREFILL_STATE_FILLING && timesize >= 1.0) + m_prefill_state = PREFILL_STATE_FILLED; +- else if (m_prefill_state == PREFILL_STATE_FILLING) +- usleep(1000); + } + + int rtn(0); +@@ -1898,6 +1896,9 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + m_last_pts = m_cur_pts; + m_cur_pts = decode_pts; + } ++ else //Timesize actualizes each 10ms, throttle decode calls to avoid reading too much ++ usleep(2500); ++ + if (((rtn & VC_PICTURE) == 0 && timesize < 2.0) || timesize < 1.0) + rtn |= VC_BUFFER; + + +From 35c24254ab9eafd9bd9f5b0025c94636e3c19889 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Thu, 24 Nov 2016 10:56:07 +0100 +Subject: [PATCH 07/30] Don't use DTS in case PTS is NO_PTS, instead don't call + checkin_pts + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 47 ++++------------------ + 1 file changed, 8 insertions(+), 39 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index d038d6a..8c51ac4c 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -632,46 +632,15 @@ void am_packet_release(am_packet_t *pkt) + + int check_in_pts(am_private_t *para, am_packet_t *pkt) + { +- int last_duration = 0; +- static int last_v_duration = 0; +- int64_t pts = 0; +- +- last_duration = last_v_duration; +- +- if (para->stream_type == AM_STREAM_ES) { +- if ((int64_t)INT64_0 != pkt->avpts) { +- pts = pkt->avpts; +- +- if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { +- CLog::Log(LOGDEBUG, "ERROR check in pts error!"); +- return PLAYER_PTS_ERROR; +- } +- +- } else if ((int64_t)INT64_0 != pkt->avdts) { +- pts = pkt->avdts * last_duration; +- +- if (para->m_dll->codec_checkin_pts(pkt->codec, pts) != 0) { +- CLog::Log(LOGDEBUG, "ERROR check in dts error!"); +- return PLAYER_PTS_ERROR; +- } +- +- last_v_duration = pkt->avduration ? pkt->avduration : 1; +- } else { +- if (!para->check_first_pts) { +- if (para->m_dll->codec_checkin_pts(pkt->codec, 0) != 0) { +- CLog::Log(LOGDEBUG, "ERROR check in 0 to video pts error!"); +- return PLAYER_PTS_ERROR; +- } +- } +- } +- if (!para->check_first_pts) { +- para->check_first_pts = 1; +- } ++ if (para->stream_type == AM_STREAM_ES && (int64_t)INT64_0 != pkt->avpts) ++ { ++ if (para->m_dll->codec_checkin_pts(pkt->codec, pkt->avpts) != 0) ++ { ++ CLog::Log(LOGDEBUG, "ERROR check in pts error!"); ++ return PLAYER_PTS_ERROR; + } +- if (pts > 0) +- pkt->lastpts = pts; +- +- return PLAYER_SUCCESS; ++ } ++ return PLAYER_SUCCESS; + } + + static int write_header(am_private_t *para, am_packet_t *pkt) + +From afb5e69423bf5a6b3b3a1e0c654fbfcd7f4c3121 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Fri, 25 Nov 2016 16:25:44 +0100 +Subject: [PATCH 08/30] allow streams without PTS (matroska) + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 64 ++++++++++------------ + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 9 +-- + 2 files changed, 33 insertions(+), 40 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 8c51ac4c..d96c96c 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -37,15 +37,6 @@ + #include "utils/SysfsUtils.h" + #include "utils/TimeUtils.h" + +-#if defined(TARGET_ANDROID) +-#include "platform/android/activity/AndroidFeatures.h" +-#include "utils/BitstreamConverter.h" +-#endif +- +-extern "C" { +-#include "libavutil/avutil.h" +-} // extern "C" +- + #include + #include + #include +@@ -295,8 +286,7 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface + #define TRICKMODE_I 0x01 + #define TRICKMODE_FFFB 0x02 + +-// same as AV_NOPTS_VALUE +-#define INT64_0 INT64_C(0x8000000000000000) ++static const int64_t INT64_0 = 0x8000000000000000ULL; + + #define EXTERNAL_PTS (1) + #define SYNC_OUTSIDE (2) +@@ -607,7 +597,7 @@ static void am_packet_init(am_packet_t *pkt) + pkt->avduration = 0; + pkt->isvalid = 0; + pkt->newflag = 0; +- pkt->lastpts = 0; ++ pkt->lastpts = INT64_0; + pkt->data = NULL; + pkt->buf = NULL; + pkt->data_size = 0; +@@ -632,13 +622,12 @@ void am_packet_release(am_packet_t *pkt) + + int check_in_pts(am_private_t *para, am_packet_t *pkt) + { +- if (para->stream_type == AM_STREAM_ES && (int64_t)INT64_0 != pkt->avpts) ++ if (para->stream_type == AM_STREAM_ES ++ && INT64_0 != pkt->avpts ++ && para->m_dll->codec_checkin_pts(pkt->codec, pkt->avpts) != 0) + { +- if (para->m_dll->codec_checkin_pts(pkt->codec, pkt->avpts) != 0) +- { +- CLog::Log(LOGDEBUG, "ERROR check in pts error!"); +- return PLAYER_PTS_ERROR; +- } ++ CLog::Log(LOGDEBUG, "ERROR check in pts error!"); ++ return PLAYER_PTS_ERROR; + } + return PLAYER_SUCCESS; + } +@@ -1379,9 +1368,9 @@ int set_header_info(am_private_t *para) + CAMLCodec::CAMLCodec() + : m_opened(false) + , m_ptsIs64us(false) +- , m_cur_pts(0) ++ , m_cur_pts(INT64_0) + , m_last_pts(0) +- , m_prefill_state(PREFILL_STATE_FILLING) ++ , m_state(0) + { + am_private = new am_private_t; + memset(am_private, 0, sizeof(am_private_t)); +@@ -1783,8 +1772,8 @@ void CAMLCodec::Reset() + SysfsUtils::SetInt("/sys/class/video/blackout_policy", blackout_policy); + + // reset some interal vars +- m_cur_pts = 0; +- m_prefill_state = PREFILL_STATE_FILLING; ++ m_cur_pts = INT64_0; ++ m_state = 0; + SetSpeed(m_speed); + } + +@@ -1806,28 +1795,30 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + // handle pts, including 31bit wrap, aml can only handle 31 + // bit pts as it uses an int in kernel. + if (m_hints.ptsinvalid || pts == DVD_NOPTS_VALUE) +- am_private->am_pkt.avpts = AV_NOPTS_VALUE; ++ am_private->am_pkt.avpts = INT64_0; + else + { + am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\ + if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff) + m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff; +- } +- if (am_private->am_pkt.avpts != (int64_t)AV_NOPTS_VALUE) + am_private->am_pkt.avpts -= m_start_pts; ++ m_state |= STATE_HASPTS; ++ } + + // handle dts, including 31bit wrap, aml can only handle 31 + // bit dts as it uses an int in kernel. + if (dts == DVD_NOPTS_VALUE) +- am_private->am_pkt.avdts = AV_NOPTS_VALUE; ++ am_private->am_pkt.avdts = INT64_0; + else + { + am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE; + if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff) + m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff; +- } +- if (am_private->am_pkt.avdts != (int64_t)AV_NOPTS_VALUE) + am_private->am_pkt.avdts -= m_start_dts; ++ // We use this to determine the fill state if no PTS is given ++ if (m_cur_pts == INT64_0) ++ m_cur_pts = am_private->am_pkt.avdts; ++ } + + // some formats need header/data tweaks. + // the actual write occurs once in write_av_packet +@@ -1853,13 +1844,13 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + // Decoder got stuck; Reset + Reset(); + } +- if (m_prefill_state == PREFILL_STATE_FILLING && timesize >= 1.0) +- m_prefill_state = PREFILL_STATE_FILLED; ++ if ((m_state & STATE_PREFILLED) == 0 && timesize >= 1.0) ++ m_state |= STATE_PREFILLED; + } + + int rtn(0); + int64_t decode_pts = 0; +- if (m_prefill_state == PREFILL_STATE_FILLED && timesize > 0.5 && DequeueBuffer(decode_pts) == 0) ++ if ((m_state & STATE_PREFILLED) != 0 && timesize > 0.5 && DequeueBuffer(decode_pts) == 0) + { + rtn |= VC_PICTURE; + m_last_pts = m_cur_pts; +@@ -2005,10 +1996,15 @@ double CAMLCodec::GetTimeSize() + if (!m_opened) + return 0; + +- int video_delay_ms; + double timesize(0); +- if (m_dll->codec_get_video_cur_delay_ms(&am_private->vcodec, &video_delay_ms) >= 0) +- timesize = (float)video_delay_ms / 1000.0; ++ if (m_state & STATE_HASPTS) ++ { ++ int video_delay_ms; ++ if (m_dll->codec_get_video_cur_delay_ms(&am_private->vcodec, &video_delay_ms) >= 0) ++ timesize = (float)video_delay_ms / 1000.0; ++ } ++ else if (m_cur_pts != INT64_0) ++ timesize = static_cast(am_private->am_pkt.avdts - m_cur_pts) / PTS_FREQ; + + // lie to VideoPlayer, it is hardcoded to a max of 8 seconds, + // if you buffer more than 8 seconds, it goes nuts. +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 33fa0b7..3a2d986 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -93,13 +93,10 @@ class CAMLCodec + int m_contrast; + int m_brightness; + +- enum PREFILLSTATE +- { +- PREFILL_STATE_FILLING, +- PREFILL_STATE_FILLED +- }; +- PREFILLSTATE m_prefill_state; ++ static const unsigned int STATE_PREFILLED = 1; ++ static const unsigned int STATE_HASPTS = 2; + ++ unsigned int m_state; + + PosixFilePtr m_amlVideoFile; + std::string m_defaultVfmMap; + +From f328dec6ca6dde3564c565a674c41bce215f9ab6 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Sun, 4 Dec 2016 17:34:15 +0100 +Subject: [PATCH 09/30] initialize cur_pts at Open / log oob timesizes + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index d96c96c..3e33480 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1418,7 +1418,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + #endif + + m_speed = DVD_PLAYSPEED_NORMAL; +- m_cur_pts = 0; ++ m_cur_pts = INT64_0; + m_dst_rect.SetRect(0, 0, 0, 0); + m_zoom = -1; + m_contrast = -1; +@@ -1427,6 +1427,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_start_dts = 0; + m_start_pts = 0; + m_hints = hints; ++ m_state = 0; + + if (!OpenAmlVideo(hints)) + { +@@ -1999,12 +2000,18 @@ double CAMLCodec::GetTimeSize() + double timesize(0); + if (m_state & STATE_HASPTS) + { +- int video_delay_ms; ++ int video_delay_ms(0); + if (m_dll->codec_get_video_cur_delay_ms(&am_private->vcodec, &video_delay_ms) >= 0) + timesize = (float)video_delay_ms / 1000.0; ++ if (timesize < 0 || timesize > 5.0) ++ CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: cur_delay_ms: %d", video_delay_ms); + } + else if (m_cur_pts != INT64_0) ++ { + timesize = static_cast(am_private->am_pkt.avdts - m_cur_pts) / PTS_FREQ; ++ if (timesize < 0 || timesize > 5.0) ++ CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: avdts: %lld cur_pts: %lld",am_private->am_pkt.avdts, m_cur_pts); ++ } + + // lie to VideoPlayer, it is hardcoded to a max of 8 seconds, + // if you buffer more than 8 seconds, it goes nuts. + +From a4aa3de63681f34a11b8c6491b2e6f49bc8b75a1 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Sun, 4 Dec 2016 21:16:17 +0100 +Subject: [PATCH 10/30] Set AV sync to 30 again + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 3e33480..c1a4359 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -280,7 +280,7 @@ class DllLibAmCodec : public DllDynamic, DllLibamCodecInterface + + #define PTS_FREQ 90000 + #define UNIT_FREQ 96000 +-#define AV_SYNC_THRESH PTS_FREQ*0 ++#define AV_SYNC_THRESH PTS_FREQ*30 + + #define TRICKMODE_NONE 0x00 + #define TRICKMODE_I 0x01 + +From 11dded59ec9ab893eb2b3e75f0aaec32450d6d95 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Sun, 4 Dec 2016 21:43:51 +0100 +Subject: [PATCH 11/30] Disable audio and sub + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index c1a4359..0d3ca38 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1386,6 +1386,8 @@ CAMLCodec::CAMLCodec() + am_private->vcodec.cntl_handle = -1; + am_private->vcodec.sub_handle = -1; + am_private->vcodec.audio_utils_handle = -1; ++ am_private->vcodec.has_audio = 0; ++ am_private->vcodec.has_sub = 0; + } + + + +From 569c477ddfc180e4692b7762f47d04330d4fb5d5 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Mon, 5 Dec 2016 17:26:54 +0100 +Subject: [PATCH 12/30] remove videodelay calculation + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 35 ++++++++-------------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 6 ++-- + 2 files changed, 14 insertions(+), 27 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 0d3ca38..b41abe7 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1426,8 +1426,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_contrast = -1; + m_brightness = -1; + m_vbufsize = 500000 * 2; +- m_start_dts = 0; +- m_start_pts = 0; ++ m_start_adj = 0; + m_hints = hints; + m_state = 0; + +@@ -1623,7 +1622,6 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_dll->codec_resume(&am_private->vcodec); + + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); +- m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000); + + m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); + m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); +@@ -1802,26 +1800,25 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + else + { + am_private->am_pkt.avpts = 0.5 + (pts * PTS_FREQ) / DVD_TIME_BASE;\ +- if (!m_start_pts && am_private->am_pkt.avpts >= 0x7fffffff) +- m_start_pts = am_private->am_pkt.avpts & ~0x0000ffff; +- am_private->am_pkt.avpts -= m_start_pts; +- m_state |= STATE_HASPTS; ++ if (!m_start_adj && am_private->am_pkt.avpts >= 0x7fffffff) ++ m_start_adj = am_private->am_pkt.avpts & ~0x0000ffff; ++ am_private->am_pkt.avpts -= m_start_adj; + } + + // handle dts, including 31bit wrap, aml can only handle 31 + // bit dts as it uses an int in kernel. + if (dts == DVD_NOPTS_VALUE) +- am_private->am_pkt.avdts = INT64_0; ++ am_private->am_pkt.avdts = am_private->am_pkt.avpts; + else + { + am_private->am_pkt.avdts = 0.5 + (dts * PTS_FREQ) / DVD_TIME_BASE; +- if (!m_start_dts && am_private->am_pkt.avdts >= 0x7fffffff) +- m_start_dts = am_private->am_pkt.avdts & ~0x0000ffff; +- am_private->am_pkt.avdts -= m_start_dts; +- // We use this to determine the fill state if no PTS is given +- if (m_cur_pts == INT64_0) +- m_cur_pts = am_private->am_pkt.avdts; ++ if (!m_start_adj && am_private->am_pkt.avdts >= 0x7fffffff) ++ m_start_adj = am_private->am_pkt.avdts & ~0x0000ffff; ++ am_private->am_pkt.avdts -= m_start_adj; + } ++ // We use this to determine the fill state if no PTS is given ++ if (m_cur_pts == INT64_0) ++ m_cur_pts = am_private->am_pkt.avdts; + + // some formats need header/data tweaks. + // the actual write occurs once in write_av_packet +@@ -2000,15 +1997,7 @@ double CAMLCodec::GetTimeSize() + return 0; + + double timesize(0); +- if (m_state & STATE_HASPTS) +- { +- int video_delay_ms(0); +- if (m_dll->codec_get_video_cur_delay_ms(&am_private->vcodec, &video_delay_ms) >= 0) +- timesize = (float)video_delay_ms / 1000.0; +- if (timesize < 0 || timesize > 5.0) +- CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: cur_delay_ms: %d", video_delay_ms); +- } +- else if (m_cur_pts != INT64_0) ++ if (m_cur_pts != INT64_0) + { + timesize = static_cast(am_private->am_pkt.avdts - m_cur_pts) / PTS_FREQ; + if (timesize < 0 || timesize > 5.0) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 3a2d986..9cdd258 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -51,7 +51,7 @@ class CAMLCodec + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); + void SetVideoRate(int videoRate); + int64_t GetCurPts() const { return m_cur_pts; } +- int GetOMXPts() const { return static_cast(m_cur_pts - m_start_pts); } ++ int GetOMXPts() const { return static_cast(m_cur_pts - m_start_adj); } + static float OMXPtsToSeconds(int omxpts); + static int OMXDurationToNs(int duration); + int GetAmlDuration() const; +@@ -79,8 +79,7 @@ class CAMLCodec + volatile int m_speed; + volatile int64_t m_cur_pts; + volatile int64_t m_vbufsize; +- int64_t m_start_dts; +- int64_t m_start_pts; ++ int64_t m_start_adj; + int64_t m_last_pts; + + CRect m_dst_rect; +@@ -94,7 +93,6 @@ class CAMLCodec + int m_brightness; + + static const unsigned int STATE_PREFILLED = 1; +- static const unsigned int STATE_HASPTS = 2; + + unsigned int m_state; + + +From aaa27fee01327a586d74ae04571b91ccd14138e1 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Tue, 6 Dec 2016 17:42:38 +0100 +Subject: [PATCH 13/30] enable seek for streams without PTS + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 9 +++++++-- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 5 +++-- + 2 files changed, 10 insertions(+), 4 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index b41abe7..405e36c 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1386,8 +1386,6 @@ CAMLCodec::CAMLCodec() + am_private->vcodec.cntl_handle = -1; + am_private->vcodec.sub_handle = -1; + am_private->vcodec.audio_utils_handle = -1; +- am_private->vcodec.has_audio = 0; +- am_private->vcodec.has_sub = 0; + } + + +@@ -1622,6 +1620,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_dll->codec_resume(&am_private->vcodec); + + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); ++ m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000); + + m_dll->codec_set_cntl_avthresh(&am_private->vcodec, AV_SYNC_THRESH); + m_dll->codec_set_cntl_syncthresh(&am_private->vcodec, 0); +@@ -1803,6 +1802,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (!m_start_adj && am_private->am_pkt.avpts >= 0x7fffffff) + m_start_adj = am_private->am_pkt.avpts & ~0x0000ffff; + am_private->am_pkt.avpts -= m_start_adj; ++ m_state |= STATE_HASPTS; + } + + // handle dts, including 31bit wrap, aml can only handle 31 +@@ -1818,7 +1818,12 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + } + // We use this to determine the fill state if no PTS is given + if (m_cur_pts == INT64_0) ++ { + m_cur_pts = am_private->am_pkt.avdts; ++ // No PTS given -> use first DTS for AML ptsserver initialization ++ if ((m_state & STATE_HASPTS) == 0) ++ am_private->am_pkt.avpts = am_private->am_pkt.avdts; ++ } + + // some formats need header/data tweaks. + // the actual write occurs once in write_av_packet +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 9cdd258..0e5334bd 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -76,8 +76,8 @@ class CAMLCodec + bool m_ptsIs64us; + am_private_t *am_private; + CDVDStreamInfo m_hints; +- volatile int m_speed; +- volatile int64_t m_cur_pts; ++ int m_speed; ++ int64_t m_cur_pts; + volatile int64_t m_vbufsize; + int64_t m_start_adj; + int64_t m_last_pts; +@@ -93,6 +93,7 @@ class CAMLCodec + int m_brightness; + + static const unsigned int STATE_PREFILLED = 1; ++ static const unsigned int STATE_HASPTS = 2; + + unsigned int m_state; + + +From 90249e2a3c6b53aa99a3ce1f4a2d301f798d896d Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Wed, 7 Dec 2016 21:16:18 +0100 +Subject: [PATCH 14/30] start with h.264 IDR frame + +--- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 32 +++++++++++++++++----- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 1 + + xbmc/utils/BitstreamConverter.cpp | 19 +++++-------- + xbmc/utils/BitstreamConverter.h | 1 + + 4 files changed, 34 insertions(+), 19 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index a0f847a..4a0598c 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -53,7 +53,8 @@ CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic(CProcessInfo &processInfo) : CDVDVi + m_bitparser(NULL), + m_bitstream(NULL), + m_opened(false), +- m_drop(false) ++ m_drop(false), ++ m_has_idr(false) + { + pthread_mutex_init(&m_queue_mutex, NULL); + } +@@ -132,8 +133,11 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option + m_hints.extradata = malloc(m_hints.extrasize); + memcpy(m_hints.extradata, m_bitstream->GetExtraData(), m_hints.extrasize); + } +- //m_bitparser = new CBitstreamParser(); +- //m_bitparser->Open(); ++ else ++ { ++ m_bitparser = new CBitstreamParser(); ++ m_bitparser->Open(); ++ } + break; + case AV_CODEC_ID_MPEG4: + case AV_CODEC_ID_MSMPEG4V2: +@@ -239,6 +243,8 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option + m_processInfo.SetVideoDeintMethod("hardware"); + m_processInfo.SetVideoDAR(m_hints.aspect); + ++ m_has_idr = false; ++ + CLog::Log(LOGINFO, "%s: Opened Amlogic Codec", __MODULE_NAME__); + return true; + } +@@ -279,13 +285,24 @@ int CDVDVideoCodecAmlogic::Decode(uint8_t *pData, int iSize, double dts, double + if (!m_bitstream->Convert(pData, iSize)) + return VC_ERROR; + ++ if (!m_bitstream->IdrFramePassed()) ++ { ++ CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for IDR frame", __MODULE_NAME__); ++ return VC_BUFFER; ++ } + pData = m_bitstream->GetConvertBuffer(); + iSize = m_bitstream->GetConvertSize(); + } +- +- if (m_bitparser) +- m_bitparser->FindIdrSlice(pData, iSize); +- ++ else if (!m_has_idr && m_bitparser) ++ { ++ if (!m_bitparser->FindIdrSlice(pData, iSize)) ++ { ++ CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for IDR frame", __MODULE_NAME__); ++ return VC_BUFFER; ++ } ++ else ++ m_has_idr = true; ++ } + FrameRateTracking( pData, iSize, dts, pts); + } + +@@ -309,6 +326,7 @@ void CDVDVideoCodecAmlogic::Reset(void) + + m_Codec->Reset(); + m_mpeg2_sequence_pts = 0; ++ m_has_idr = false; + } + + bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +index 39f408e..0a2c6bb 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +@@ -99,6 +99,7 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec + mpeg2_sequence *m_mpeg2_sequence; + double m_mpeg2_sequence_pts; + bool m_drop; ++ bool m_has_idr; + + CBitstreamParser *m_bitparser; + CBitstreamConverter *m_bitstream; +diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp +index d0a4c20..f42c50c4 100644 +--- a/xbmc/utils/BitstreamConverter.cpp ++++ b/xbmc/utils/BitstreamConverter.cpp +@@ -269,35 +269,25 @@ bool CBitstreamParser::FindIdrSlice(const uint8_t *buf, int buf_size) + buf = find_start_code(buf, buf_end, &state); + if (buf >= buf_end) + { +- //CLog::Log(LOGDEBUG, "FindIdrSlice: buf(%p), buf_end(%p)", buf, buf_end); + break; + } + +- --buf; +- int src_length = buf_end - buf; + switch (state & 0x1f) + { +- default: +- CLog::Log(LOGDEBUG, "FindIdrSlice: found nal_type(%d)", state & 0x1f); +- break; + case AVC_NAL_SLICE: +- CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_SLICE"); + break; + case AVC_NAL_IDR_SLICE: +- CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_IDR_SLICE"); + rtn = true; + break; + case AVC_NAL_SEI: +- CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_SEI"); + break; + case AVC_NAL_SPS: +- CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_SPS"); + break; + case AVC_NAL_PPS: +- CLog::Log(LOGDEBUG, "FindIdrSlice: found NAL_PPS"); ++ break; ++ default: + break; + } +- buf += src_length; + } + + return rtn; +@@ -646,6 +636,11 @@ int CBitstreamConverter::GetExtraSize() const + return m_extrasize; + } + ++bool CBitstreamConverter::IdrFramePassed() const ++{ ++ return m_sps_pps_context.first_idr == 0; ++} ++ + bool CBitstreamConverter::BitstreamConvertInitAVC(void *in_extradata, int in_extrasize) + { + // based on h264_mp4toannexb_bsf.c (ffmpeg) +diff --git a/xbmc/utils/BitstreamConverter.h b/xbmc/utils/BitstreamConverter.h +index 9045ef9..8b66f0f 100644 +--- a/xbmc/utils/BitstreamConverter.h ++++ b/xbmc/utils/BitstreamConverter.h +@@ -157,6 +157,7 @@ class CBitstreamConverter + int GetConvertSize() const; + uint8_t* GetExtraData(void) const; + int GetExtraSize() const; ++ bool IdrFramePassed() const; + + static void bits_reader_set( bits_reader_t *br, uint8_t *buf, int len ); + static uint32_t read_bits( bits_reader_t *br, int nbits ); + +From 3164250375995ae6af361f5c946540c2199fe053 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Thu, 8 Dec 2016 08:37:36 +0100 +Subject: [PATCH 15/30] IDR and SEI:recovery are keyframes -> implement + SEI:recovery_count + +--- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 7 +- + xbmc/utils/BitstreamConverter.cpp | 91 +++++++++++++++++++--- + xbmc/utils/BitstreamConverter.h | 6 +- + 3 files changed, 90 insertions(+), 14 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index 4a0598c..386aac2 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -127,6 +127,7 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option + { + m_bitstream = new CBitstreamConverter; + m_bitstream->Open(m_hints.codec, (uint8_t*)m_hints.extradata, m_hints.extrasize, true); ++ m_bitstream->ResetKeyframe(); + // make sure we do not leak the existing m_hints.extradata + free(m_hints.extradata); + m_hints.extrasize = m_bitstream->GetExtraSize(); +@@ -285,7 +286,7 @@ int CDVDVideoCodecAmlogic::Decode(uint8_t *pData, int iSize, double dts, double + if (!m_bitstream->Convert(pData, iSize)) + return VC_ERROR; + +- if (!m_bitstream->IdrFramePassed()) ++ if (!m_bitstream->HasKeyframe()) + { + CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for IDR frame", __MODULE_NAME__); + return VC_BUFFER; +@@ -295,7 +296,7 @@ int CDVDVideoCodecAmlogic::Decode(uint8_t *pData, int iSize, double dts, double + } + else if (!m_has_idr && m_bitparser) + { +- if (!m_bitparser->FindIdrSlice(pData, iSize)) ++ if (!m_bitparser->HasKeyframe(pData, iSize)) + { + CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for IDR frame", __MODULE_NAME__); + return VC_BUFFER; +@@ -327,6 +328,8 @@ void CDVDVideoCodecAmlogic::Reset(void) + m_Codec->Reset(); + m_mpeg2_sequence_pts = 0; + m_has_idr = false; ++ if (m_bitstream && m_hints.codec == AV_CODEC_ID_H264) ++ m_bitstream->ResetKeyframe(); + } + + bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) +diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp +index f42c50c4..6cb25fd 100644 +--- a/xbmc/utils/BitstreamConverter.cpp ++++ b/xbmc/utils/BitstreamConverter.cpp +@@ -72,6 +72,34 @@ enum { + HEVC_NAL_SEI_SUFFIX = 40 + }; + ++enum { ++ SEI_BUFFERING_PERIOD = 0, ++ SEI_PIC_TIMING, ++ SEI_PAN_SCAN_RECT, ++ SEI_FILLER_PAYLOAD, ++ SEI_USER_DATA_REGISTERED_ITU_T_T35, ++ SEI_USER_DATA_UNREGISTERED, ++ SEI_RECOVERY_POINT, ++ SEI_DEC_REF_PIC_MARKING_REPETITION, ++ SEI_SPARE_PIC, ++ SEI_SCENE_INFO, ++ SEI_SUB_SEQ_INFO, ++ SEI_SUB_SEQ_LAYER_CHARACTERISTICS, ++ SEI_SUB_SEQ_CHARACTERISTICS, ++ SEI_FULL_FRAME_FREEZE, ++ SEI_FULL_FRAME_FREEZE_RELEASE, ++ SEI_FULL_FRAME_SNAPSHOT, ++ SEI_PROGRESSIVE_REFINEMENT_SEGMENT_START, ++ SEI_PROGRESSIVE_REFINEMENT_SEGMENT_END, ++ SEI_MOTION_CONSTRAINED_SLICE_GROUP_SET, ++ SEI_FILM_GRAIN_CHARACTERISTICS, ++ SEI_DEBLOCKING_FILTER_DISPLAY_PREFERENCE, ++ SEI_STEREO_VIDEO_INFO, ++ SEI_POST_FILTER_HINTS, ++ SEI_TONE_MAPPING ++}; ++ ++ + //////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////// + // GStreamer h264 parser +@@ -205,6 +233,34 @@ static const uint8_t* avc_find_startcode(const uint8_t *p, const uint8_t *end) + return out; + } + ++static bool has_sei_recovery_point(const uint8_t *p, const uint8_t *end) ++{ ++ int pt(0), ps(0), offset(1); ++ ++ do ++ { ++ pt = 0; ++ do { ++ pt += p[offset]; ++ } while (p[offset++] == 0xFF); ++ ++ ps = 0; ++ do { ++ ps += p[offset]; ++ } while (p[offset++] == 0xFF); ++ ++ if (pt == SEI_RECOVERY_POINT) ++ { ++ nal_bitstream bs; ++ nal_bs_init(&bs, p + offset, ps); ++ return nal_bs_read_ue(&bs) >= 0; ++ } ++ offset += ps; ++ } while(p + offset < end && p[offset] != 0x80); ++ ++ return false; ++} ++ + //////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////// + CBitstreamParser::CBitstreamParser() +@@ -255,16 +311,16 @@ const uint8_t* CBitstreamParser::find_start_code(const uint8_t *p, + return p + 4; + } + +-bool CBitstreamParser::FindIdrSlice(const uint8_t *buf, int buf_size) ++bool CBitstreamParser::HasKeyframe(const uint8_t *buf, int buf_size) + { + if (!buf) + return false; + + bool rtn = false; + uint32_t state = -1; +- const uint8_t *buf_end = buf + buf_size; ++ const uint8_t *buf_begin, *buf_end = buf + buf_size; + +- for(;;) ++ for(;rtn == false;) + { + buf = find_start_code(buf, buf_end, &state); + if (buf >= buf_end) +@@ -280,6 +336,10 @@ bool CBitstreamParser::FindIdrSlice(const uint8_t *buf, int buf_size) + rtn = true; + break; + case AVC_NAL_SEI: ++ buf_begin = buf; ++ buf = find_start_code(buf, buf_end, &state) - 4; ++ if (has_sei_recovery_point(buf_begin, buf)) ++ rtn = true; + break; + case AVC_NAL_SPS: + break; +@@ -308,6 +368,7 @@ CBitstreamConverter::CBitstreamConverter() + m_convert_3byteTo4byteNALSize = false; + m_convert_bytestream = false; + m_sps_pps_context.sps_pps_data = NULL; ++ m_has_keyframe = true; + } + + CBitstreamConverter::~CBitstreamConverter() +@@ -387,7 +448,7 @@ bool CBitstreamConverter::Open(enum AVCodecID codec, uint8_t *in_extradata, int + // are valid, setup to convert 3 byte NAL sizes to 4 byte. + in_extradata[4] = 0xFF; + m_convert_3byteTo4byteNALSize = true; +- ++ + m_extradata = (uint8_t *)av_malloc(in_extrasize); + memcpy(m_extradata, in_extradata, in_extrasize); + m_extrasize = in_extrasize; +@@ -498,7 +559,7 @@ void CBitstreamConverter::Close(void) + bool CBitstreamConverter::Convert(uint8_t *pData, int iSize) + { + if (m_convertBuffer) +- { ++ { + av_free(m_convertBuffer); + m_convertBuffer = NULL; + } +@@ -548,7 +609,7 @@ bool CBitstreamConverter::Convert(uint8_t *pData, int iSize) + { + m_inputSize = iSize; + m_inputBuffer = pData; +- ++ + if (m_convert_bytestream) + { + if(m_convertBuffer) +@@ -636,9 +697,14 @@ int CBitstreamConverter::GetExtraSize() const + return m_extrasize; + } + +-bool CBitstreamConverter::IdrFramePassed() const ++void CBitstreamConverter::ResetKeyframe(void) ++{ ++ m_has_keyframe = false; ++} ++ ++bool CBitstreamConverter::HasKeyframe() const + { +- return m_sps_pps_context.first_idr == 0; ++ return m_has_keyframe; + } + + bool CBitstreamConverter::BitstreamConvertInitAVC(void *in_extradata, int in_extrasize) +@@ -855,7 +921,7 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t ** + int i; + uint8_t *buf = pData; + uint32_t buf_size = iSize; +- uint8_t unit_type, nal_sps, nal_pps; ++ uint8_t unit_type, nal_sps, nal_pps, nal_sei; + int32_t nal_size; + uint32_t cumul_size = 0; + const uint8_t *buf_end = buf + buf_size; +@@ -865,10 +931,12 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t ** + case AV_CODEC_ID_H264: + nal_sps = AVC_NAL_SPS; + nal_pps = AVC_NAL_PPS; ++ nal_sei = AVC_NAL_SEI; + break; + case AV_CODEC_ID_HEVC: + nal_sps = HEVC_NAL_SPS; + nal_pps = HEVC_NAL_PPS; ++ nal_sei = HEVC_NAL_SEI_PREFIX; + break; + default: + return false; +@@ -899,7 +967,10 @@ bool CBitstreamConverter::BitstreamConvert(uint8_t* pData, int iSize, uint8_t ** + if (m_sps_pps_context.first_idr && (unit_type == nal_sps || unit_type == nal_pps)) + m_sps_pps_context.idr_sps_pps_seen = 1; + +- // prepend only to the first access unit of an IDR picture, if no sps/pps already present ++ if (!m_has_keyframe && (IsIDR(unit_type) || (unit_type == nal_sei && has_sei_recovery_point(buf, buf + nal_size)))) ++ m_has_keyframe = true; ++ ++ // prepend only to the first access unit of an IDR picture, if no sps/pps already present + if (m_sps_pps_context.first_idr && IsIDR(unit_type) && !m_sps_pps_context.idr_sps_pps_seen) + { + BitstreamAllocAndCopy(poutbuf, poutbuf_size, +diff --git a/xbmc/utils/BitstreamConverter.h b/xbmc/utils/BitstreamConverter.h +index 8b66f0f..d953907 100644 +--- a/xbmc/utils/BitstreamConverter.h ++++ b/xbmc/utils/BitstreamConverter.h +@@ -137,7 +137,7 @@ class CBitstreamParser + + static bool Open(); + static void Close(); +- static bool FindIdrSlice(const uint8_t *buf, int buf_size); ++ static bool HasKeyframe(const uint8_t *buf, int buf_size); + + protected: + static const uint8_t* find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state); +@@ -157,7 +157,8 @@ class CBitstreamConverter + int GetConvertSize() const; + uint8_t* GetExtraData(void) const; + int GetExtraSize() const; +- bool IdrFramePassed() const; ++ void ResetKeyframe(void); ++ bool HasKeyframe() const; + + static void bits_reader_set( bits_reader_t *br, uint8_t *buf, int len ); + static uint32_t read_bits( bits_reader_t *br, int nbits ); +@@ -208,5 +209,6 @@ class CBitstreamConverter + bool m_convert_3byteTo4byteNALSize; + bool m_convert_bytestream; + AVCodecID m_codec; ++ bool m_has_keyframe; + }; + + +From ea31d4f1ae26060752caaa87e71f840134768b5b Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Thu, 8 Dec 2016 14:47:02 +0100 +Subject: [PATCH 16/30] Fix BitsreamParser SEI start adress + +--- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 14 +++++++------- + .../VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h | 2 +- + xbmc/utils/BitstreamConverter.cpp | 2 +- + 3 files changed, 9 insertions(+), 9 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index 386aac2..a6803e4 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -54,7 +54,7 @@ CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic(CProcessInfo &processInfo) : CDVDVi + m_bitstream(NULL), + m_opened(false), + m_drop(false), +- m_has_idr(false) ++ m_has_keyframe(false) + { + pthread_mutex_init(&m_queue_mutex, NULL); + } +@@ -244,7 +244,7 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option + m_processInfo.SetVideoDeintMethod("hardware"); + m_processInfo.SetVideoDAR(m_hints.aspect); + +- m_has_idr = false; ++ m_has_keyframe = false; + + CLog::Log(LOGINFO, "%s: Opened Amlogic Codec", __MODULE_NAME__); + return true; +@@ -288,21 +288,21 @@ int CDVDVideoCodecAmlogic::Decode(uint8_t *pData, int iSize, double dts, double + + if (!m_bitstream->HasKeyframe()) + { +- CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for IDR frame", __MODULE_NAME__); ++ CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for keyframe (bitstream)", __MODULE_NAME__); + return VC_BUFFER; + } + pData = m_bitstream->GetConvertBuffer(); + iSize = m_bitstream->GetConvertSize(); + } +- else if (!m_has_idr && m_bitparser) ++ else if (!m_has_keyframe && m_bitparser) + { + if (!m_bitparser->HasKeyframe(pData, iSize)) + { +- CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for IDR frame", __MODULE_NAME__); ++ CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for keyframe (bitparser)", __MODULE_NAME__); + return VC_BUFFER; + } + else +- m_has_idr = true; ++ m_has_keyframe = true; + } + FrameRateTracking( pData, iSize, dts, pts); + } +@@ -327,7 +327,7 @@ void CDVDVideoCodecAmlogic::Reset(void) + + m_Codec->Reset(); + m_mpeg2_sequence_pts = 0; +- m_has_idr = false; ++ m_has_keyframe = false; + if (m_bitstream && m_hints.codec == AV_CODEC_ID_H264) + m_bitstream->ResetKeyframe(); + } +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +index 0a2c6bb..a494ace 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +@@ -99,7 +99,7 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec + mpeg2_sequence *m_mpeg2_sequence; + double m_mpeg2_sequence_pts; + bool m_drop; +- bool m_has_idr; ++ bool m_has_keyframe; + + CBitstreamParser *m_bitparser; + CBitstreamConverter *m_bitstream; +diff --git a/xbmc/utils/BitstreamConverter.cpp b/xbmc/utils/BitstreamConverter.cpp +index 6cb25fd..be942a1 100644 +--- a/xbmc/utils/BitstreamConverter.cpp ++++ b/xbmc/utils/BitstreamConverter.cpp +@@ -336,7 +336,7 @@ bool CBitstreamParser::HasKeyframe(const uint8_t *buf, int buf_size) + rtn = true; + break; + case AVC_NAL_SEI: +- buf_begin = buf; ++ buf_begin = buf - 1; + buf = find_start_code(buf, buf_end, &state) - 4; + if (has_sei_recovery_point(buf_begin, buf)) + rtn = true; + +From 2400cddfebd2d0120a396aff5cc7e3259273ea35 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Tue, 13 Dec 2016 12:07:00 +0100 +Subject: [PATCH 17/30] wait for next displayed frame for sync measurement + +--- + .../VideoRenderers/HwDecRender/RendererAML.cpp | 45 ++++++++++++++-------- + .../VideoRenderers/HwDecRender/RendererAML.h | 2 +- + 2 files changed, 31 insertions(+), 16 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index c45e94f..54a2588 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -56,7 +56,7 @@ static void set_pts(const char *strPath, int pts) + } + + CRendererAML::CRendererAML() +- : m_prevPts(-1) ++ : m_prevVPts(-1) + , m_bConfigured(false) + , m_iRenderBuffer(0) + , m_diff_counter(0) +@@ -181,7 +181,7 @@ EINTERLACEMETHOD CRendererAML::AutoInterlaceMethod() + + void CRendererAML::Reset() + { +- m_prevPts = 0; ++ m_prevVPts = -1; + m_diff_counter = 0; + } + +@@ -192,33 +192,48 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + CDVDAmlogicInfo *amli = static_cast(m_buffers[m_iRenderBuffer].hwDec); + CAMLCodec *amlcodec = amli ? amli->getAmlCodec() : 0; + ++ int videopts(0); + if(amlcodec) +- amlcodec->PollFrame(); ++ { ++ unsigned int i(0); ++ do { ++ amlcodec->PollFrame(); ++ videopts = get_pts("/sys/class/tsync/pts_video"); ++ } while (i++ < 5 && videopts == m_prevVPts); ++ } ++ m_prevVPts = videopts; + +- if (amli && amli->GetOmxPts() != m_prevPts) ++ if (amli) + { +- m_prevPts = amli->GetOmxPts(); ++ int pts = amli->GetOmxPts(); + + int pcrscr(get_pts("/sys/class/tsync/pts_pcrscr")); +- m_diff_counter += static_cast((pcrscr - m_prevPts)*1.1 / amli->GetAmlDuration()); ++ int diff(static_cast((pcrscr - pts)*1.1 / amli->GetAmlDuration())); ++ m_diff_counter += diff; ++ ++ if(!diff) ++ { ++ if (m_diff_counter > 0) ++ --m_diff_counter; ++ else if (m_diff_counter < 0) ++ ++m_diff_counter; ++ } + +- if (abs(m_diff_counter) > 2) ++ if (abs(m_diff_counter) > 10) + { +- int videopts(get_pts("/sys/class/tsync/pts_video")); +- set_pts("/sys/class/tsync/pts_pcrscr", m_prevPts); +- CLog::Log(LOGDEBUG, "RenderUpdate: Adjusting: ptsclock:%d ptsscr:%d vpts:%d diff:%d", m_prevPts, pcrscr, videopts, m_diff_counter); +- pcrscr = m_prevPts; ++ set_pts("/sys/class/tsync/pts_pcrscr", pts); ++ 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); ++ pcrscr = pts; + m_diff_counter = 0; + } + else if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- int videopts(get_pts("/sys/class/tsync/pts_video")); +- CLog::Log(LOGDEBUG, "RenderUpdate: ptsclock:%d ptsscr:%d vpts:%d diff:%d", m_prevPts, pcrscr, videopts, m_diff_counter); ++ CLog::Log(LOGDEBUG, "RenderUpdate: ptsclock:%d ptsscr:%d vpts:%d diff:%d", pts, pcrscr, videopts, m_diff_counter); + } ++ + SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", pcrscr); + +- if (amlcodec) +- amlcodec->SetVideoRect(m_sourceRect, m_destRect); ++ amlcodec->SetVideoRect(m_sourceRect, m_destRect); + } + } + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +index 0d9f126..7b4203b 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +@@ -70,7 +70,7 @@ class CRendererAML : public CBaseRenderer + int duration; + } m_buffers[m_numRenderBuffers]; + +- int m_prevPts; ++ int m_prevVPts; + bool m_bConfigured; + int m_diff_counter; + }; + +From d675e0689584f84627604a07f6a5b3d62baba88a Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Tue, 13 Dec 2016 21:23:34 +0100 +Subject: [PATCH 18/30] check for amlclodec != 0 + +--- + xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index 54a2588..cb000bb 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -233,7 +233,8 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + + SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", pcrscr); + +- amlcodec->SetVideoRect(m_sourceRect, m_destRect); ++ if(amlcodec) ++ amlcodec->SetVideoRect(m_sourceRect, m_destRect); + } + } + + +From a2260af19fce474edf1378fc636feecbfc84b03d Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Tue, 13 Dec 2016 23:18:27 +0100 +Subject: [PATCH 19/30] resume aml on time we got first picture + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 8 ++++++-- + xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp | 2 +- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 405e36c..47fca3c 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1617,7 +1617,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + am_private->dumpdemux = false; + dumpfile_open(am_private); + +- m_dll->codec_resume(&am_private->vcodec); ++ m_dll->codec_pause(&am_private->vcodec); + + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000); +@@ -1752,9 +1752,10 @@ void CAMLCodec::Reset() + // restore the speed (some amcodec versions require this) + if (m_speed != DVD_PLAYSPEED_NORMAL) + { +- m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + } ++ m_dll->codec_pause(&am_private->vcodec); ++ + // reset the decoder + m_dll->codec_reset(&am_private->vcodec); + m_dll->codec_set_video_delay_limited_ms(&am_private->vcodec, 1000); +@@ -1850,7 +1851,10 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + Reset(); + } + if ((m_state & STATE_PREFILLED) == 0 && timesize >= 1.0) ++ { ++ m_dll->codec_resume(&am_private->vcodec); + m_state |= STATE_PREFILLED; ++ } + } + + int rtn(0); +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index cb000bb..e6b39f3 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -219,7 +219,7 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + ++m_diff_counter; + } + +- if (abs(m_diff_counter) > 10) ++ if (abs(m_diff_counter) > 5) + { + set_pts("/sys/class/tsync/pts_pcrscr", pts); + 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); + +From 94031c39a596e7ac14f77170565a1a2c0f969802 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Wed, 14 Dec 2016 14:22:11 +0100 +Subject: [PATCH 20/30] more log / fix start-adjusting + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 9 ++++++--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 4 ++-- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 47fca3c..4935453 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1775,6 +1775,7 @@ void CAMLCodec::Reset() + // reset some interal vars + m_cur_pts = INT64_0; + m_state = 0; ++ m_start_adj = 0; + SetSpeed(m_speed); + } + +@@ -1884,10 +1885,12 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + else + memset(&vfs, 0, sizeof(vfs)); + +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d dts_in: %0.6f, pts_in: %0.6f, ptsOut:%0.6f, amlpts:%d vfs:[%d-%d-%d-%d] timesize:%0.2f", ++ 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", + rtn, +- static_cast(dts)/DVD_TIME_BASE, +- static_cast(pts)/DVD_TIME_BASE, ++ iSize, ++ static_cast(dts)/DVD_TIME_BASE, am_private->am_pkt.avdts, ++ static_cast(pts)/DVD_TIME_BASE, am_private->am_pkt.avpts, ++ m_start_adj, + static_cast(m_cur_pts)/PTS_FREQ, + static_cast(m_cur_pts), + vfs.vf_pool_size, vfs.buf_free_num,vfs.buf_recycle_num,vfs.buf_avail_num, +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 0e5334bd..b18e6e2 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -50,8 +50,8 @@ class CAMLCodec + double GetTimeSize(); + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); + void SetVideoRate(int videoRate); +- int64_t GetCurPts() const { return m_cur_pts; } +- int GetOMXPts() const { return static_cast(m_cur_pts - m_start_adj); } ++ int64_t GetCurPts() const { return m_cur_pts + m_start_adj; } ++ int GetOMXPts() const { return static_cast(m_cur_pts); } + static float OMXPtsToSeconds(int omxpts); + static int OMXDurationToNs(int duration); + int GetAmlDuration() const; + +From 2dec8f56f8aa7614b48527739d98b6fc2d0e246d Mon Sep 17 00:00:00 2001 +From: peak3d +Date: Tue, 20 Dec 2016 13:53:03 +0100 +Subject: [PATCH 21/30] [AML] queue_buf + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 87 ++++++++++++++++------ + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 4 +- + .../VideoRenderers/HwDecRender/RendererAML.cpp | 15 ++++ + 3 files changed, 84 insertions(+), 22 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 4935453..62a7a42 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -47,6 +47,7 @@ + #include + #include + #include ++#include + + // amcodec include + extern "C" { +@@ -292,7 +293,10 @@ static const int64_t INT64_0 = 0x8000000000000000ULL; + #define SYNC_OUTSIDE (2) + + // missing tags ++#ifndef CODEC_TAG_VC_1 + #define CODEC_TAG_VC_1 (0x312D4356) ++#endif ++ + #define CODEC_TAG_RV30 (0x30335652) + #define CODEC_TAG_RV40 (0x30345652) + #define CODEC_TAG_MJPEG (0x47504a4d) +@@ -385,9 +389,10 @@ typedef struct vframe_states + int buf_avail_num; + } vframe_states_t; + ++#ifndef AMSTREAM_IOC_VF_STATUS + #define AMSTREAM_IOC_MAGIC 'S' + #define AMSTREAM_IOC_VF_STATUS _IOR(AMSTREAM_IOC_MAGIC, 0x60, unsigned long) +- ++#endif + + /*************************************************************************/ + /*************************************************************************/ +@@ -1637,7 +1642,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + if (strScaler.find("enabled") == std::string::npos) // Scaler not enabled, use screen size + m_display_rect = CRect(0, 0, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iScreenWidth, CDisplaySettings::GetInstance().GetCurrentResolutionInfo().iScreenHeight); + +- SysfsUtils::SetInt("/sys/class/video/freerun_mode", 0); ++ SysfsUtils::SetInt("/sys/class/video/freerun_mode", 1); + + + struct utsname un; +@@ -1673,8 +1678,17 @@ bool CAMLCodec::OpenAmlVideo(const CDVDStreamInfo &hints) + m_defaultVfmMap = GetVfmMap("default"); + SetVfmMap("default", "decoder ppmgr deinterlace amlvideo amvideo"); + +- SysfsUtils::SetInt("/sys/module/amlvideodri/parameters/freerun_mode", 1); ++ SysfsUtils::SetInt("/sys/module/amlvideodri/parameters/freerun_mode", 3); + ++ struct v4l2_requestbuffers rbuf = {0}; ++ rbuf.count = 1; ++ rbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ rbuf.memory = V4L2_MEMORY_USERPTR; ++ if (m_amlVideoFile->IOControl(VIDIOC_REQBUFS, &rbuf) < 0) ++ { ++ if (errno != EAGAIN) ++ CLog::Log(LOGERROR, "CAMLCodec::OpenAML - VIDIOC_REQBUFS failed: %s", strerror(errno)); ++ } + return true; + } + +@@ -1706,6 +1720,15 @@ void CAMLCodec::SetVfmMap(const std::string &name, const std::string &map) + SysfsUtils::SetString("/sys/class/vfm/map", "add " + name + " " + map); + } + ++unsigned int CAMLCodec::GetDecodedFrameCount() ++{ ++ vframe_states_t vfs; ++ if(m_amlVideoFile->IOControl(AMSTREAM_IOC_VF_STATUS, &vfs) == 0) ++ return vfs.buf_avail_num; ++ else ++ return 0; ++} ++ + void CAMLCodec::CloseDecoder() + { + CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder"); +@@ -1713,7 +1736,7 @@ void CAMLCodec::CloseDecoder() + // never leave vcodec ff/rw or paused. + if (m_speed != DVD_PLAYSPEED_NORMAL) + { +- m_dll->codec_resume(&am_private->vcodec); ++ //m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + } + m_dll->codec_close(&am_private->vcodec); +@@ -1853,7 +1876,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + } + if ((m_state & STATE_PREFILLED) == 0 && timesize >= 1.0) + { +- m_dll->codec_resume(&am_private->vcodec); ++ //m_dll->codec_resume(&am_private->vcodec); + m_state |= STATE_PREFILLED; + } + } +@@ -1875,19 +1898,12 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { + vframe_states_t vfs; +- int fd(open("/dev/amvideo", O_RDONLY)); +- if(fd) +- { +- if (ioctl(fd, AMSTREAM_IOC_VF_STATUS, &vfs) != 0) +- memset(&vfs, 0, sizeof(vfs)); +- close(fd); +- } +- else ++ if (ioctl(am_private->vcodec.handle, AMSTREAM_IOC_VF_STATUS, &vfs) != 0) + memset(&vfs, 0, sizeof(vfs)); + +- 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", ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.6f[%llX], pts_in: %0.6f[%llX], adj:%llu, ptsOut:%0.6f, amlpts:%d vfs:[0x%x-0x%x-0x%x-0x%x] timesize:%0.2f", + rtn, +- iSize, ++ static_cast(iSize), + static_cast(dts)/DVD_TIME_BASE, am_private->am_pkt.avdts, + static_cast(pts)/DVD_TIME_BASE, am_private->am_pkt.avpts, + m_start_adj, +@@ -1903,7 +1919,37 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + + int CAMLCodec::PollFrame() + { +- return m_dll->codec_poll_cntl(&am_private->vcodec); ++ struct pollfd codec_poll_fd[1]; ++ ++ if (am_private->vcodec.handle <= 0) { ++ return 0; ++ } ++ ++ codec_poll_fd[0].fd = am_private->vcodec.handle; ++ codec_poll_fd[0].events = POLLOUT; ++ ++ return poll(codec_poll_fd, 1, 100); ++} ++ ++int CAMLCodec::ReleaseFrame(unsigned long pts) ++{ ++ int ret; ++ v4l2_buffer vbuf = { 0 }; ++ vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; ++ vbuf.memory = V4L2_MEMORY_USERPTR; ++ ++ if (m_ptsIs64us) ++ { ++ uint64_t us = (static_cast(pts) * DVD_TIME_BASE) / PTS_FREQ; ++ vbuf.timestamp.tv_sec = us >> 32; ++ vbuf.timestamp.tv_usec = us & 0xFFFFFFFF; ++ } ++ else ++ vbuf.timestamp.tv_usec = pts; ++ ++ if ((ret = m_amlVideoFile->IOControl(VIDIOC_QBUF, &vbuf)) < 0) ++ CLog::Log(LOGERROR, "CAMLCodec::ReleaseFrame - VIDIOC_QBUF failed: %s", strerror(errno)); ++ return ret; + } + + int CAMLCodec::DequeueBuffer(int64_t &pts) +@@ -1951,8 +1997,7 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; + pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE; + +- //AML video is ~ 2 frames to fast - sync audio +- pDvdVideoPicture->pts += 2*pDvdVideoPicture->iDuration; ++ CLog::Log(LOGERROR, "CAMLCodec::GetPicture pts: %lld", m_cur_pts); + + return true; + } +@@ -1974,15 +2019,15 @@ void CAMLCodec::SetSpeed(int speed) + switch(speed) + { + case DVD_PLAYSPEED_PAUSE: +- m_dll->codec_pause(&am_private->vcodec); ++ //m_dll->codec_pause(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + break; + case DVD_PLAYSPEED_NORMAL: +- m_dll->codec_resume(&am_private->vcodec); ++ //m_dll->codec_resume(&am_private->vcodec); + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_NONE); + break; + default: +- m_dll->codec_resume(&am_private->vcodec); ++ //m_dll->codec_resume(&am_private->vcodec); + if ((am_private->video_format == VFORMAT_H264) || (am_private->video_format == VFORMAT_H264_4K2K)) + m_dll->codec_set_cntl_mode(&am_private->vcodec, TRICKMODE_FFFB); + else +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index b18e6e2..6348647 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -51,11 +51,12 @@ class CAMLCodec + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); + void SetVideoRate(int videoRate); + int64_t GetCurPts() const { return m_cur_pts + m_start_adj; } +- int GetOMXPts() const { return static_cast(m_cur_pts); } ++ int GetOMXPts() const { return static_cast(m_cur_pts); } + static float OMXPtsToSeconds(int omxpts); + static int OMXDurationToNs(int duration); + int GetAmlDuration() const; + int PollFrame(); ++ int ReleaseFrame(unsigned long pts); + + private: + void ShowMainVideo(const bool show); +@@ -69,6 +70,7 @@ class CAMLCodec + void CloseAmlVideo(); + std::string GetVfmMap(const std::string &name); + void SetVfmMap(const std::string &name, const std::string &map); ++ unsigned int GetDecodedFrameCount(); + int DequeueBuffer(int64_t &pts); + + DllLibAmCodec *m_dll; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index e6b39f3..d390c08 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -192,6 +192,20 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + CDVDAmlogicInfo *amli = static_cast(m_buffers[m_iRenderBuffer].hwDec); + CAMLCodec *amlcodec = amli ? amli->getAmlCodec() : 0; + ++#if 1 ++ if(amlcodec) ++ { ++ int pts = amli->GetOmxPts(); ++ if (pts != m_prevVPts) ++ { ++ CLog::Log(LOGDEBUG, "RenderUpdate: ReleaseFrame with pts:%d", pts); ++ amlcodec->ReleaseFrame(pts); ++ amlcodec->SetVideoRect(m_sourceRect, m_destRect); ++ m_prevVPts = pts; ++ } ++ amlcodec->PollFrame(); ++ } ++#else + int videopts(0); + if(amlcodec) + { +@@ -236,6 +250,7 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + if(amlcodec) + amlcodec->SetVideoRect(m_sourceRect, m_destRect); + } ++#endif + } + + #endif + +From e1557505b865a912a87e80258b5ad8ad3306cf6a Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Wed, 21 Dec 2016 23:38:53 +0100 +Subject: [PATCH 22/30] videosync impl. / cleanup + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 39 ++++------ + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 1 - + .../VideoRenderers/HwDecRender/RendererAML.cpp | 77 +------------------ + .../VideoRenderers/HwDecRender/RendererAML.h | 1 - + xbmc/video/VideoReferenceClock.cpp | 5 ++ + xbmc/video/videosync/CMakeLists.txt | 5 ++ + xbmc/video/videosync/VideoSyncAML.cpp | 86 ++++++++++++++++++++++ + xbmc/video/videosync/VideoSyncAML.h | 41 +++++++++++ + 8 files changed, 154 insertions(+), 101 deletions(-) + create mode 100644 xbmc/video/videosync/VideoSyncAML.cpp + create mode 100644 xbmc/video/videosync/VideoSyncAML.h + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 62a7a42..d081c21 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -54,6 +54,8 @@ extern "C" { + #include + } // extern "C" + ++CEvent g_aml_sync_event; ++ + class PosixFile + { + public: +@@ -1720,15 +1722,6 @@ void CAMLCodec::SetVfmMap(const std::string &name, const std::string &map) + SysfsUtils::SetString("/sys/class/vfm/map", "add " + name + " " + map); + } + +-unsigned int CAMLCodec::GetDecodedFrameCount() +-{ +- vframe_states_t vfs; +- if(m_amlVideoFile->IOControl(AMSTREAM_IOC_VF_STATUS, &vfs) == 0) +- return vfs.buf_avail_num; +- else +- return 0; +-} +- + void CAMLCodec::CloseDecoder() + { + CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder"); +@@ -1897,11 +1890,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- vframe_states_t vfs; +- if (ioctl(am_private->vcodec.handle, AMSTREAM_IOC_VF_STATUS, &vfs) != 0) +- memset(&vfs, 0, sizeof(vfs)); +- +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.6f[%llX], pts_in: %0.6f[%llX], adj:%llu, ptsOut:%0.6f, amlpts:%d vfs:[0x%x-0x%x-0x%x-0x%x] timesize:%0.2f", ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.6f[%llX], pts_in: %0.6f[%llX], adj:%llu, ptsOut:%0.6f, amlpts:%d timesize:%0.2f", + rtn, + static_cast(iSize), + static_cast(dts)/DVD_TIME_BASE, am_private->am_pkt.avdts, +@@ -1909,7 +1898,6 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + m_start_adj, + static_cast(m_cur_pts)/PTS_FREQ, + static_cast(m_cur_pts), +- vfs.vf_pool_size, vfs.buf_free_num,vfs.buf_recycle_num,vfs.buf_avail_num, + timesize + ); + } +@@ -1919,16 +1907,21 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + + int CAMLCodec::PollFrame() + { +- struct pollfd codec_poll_fd[1]; ++ struct pollfd codec_poll_fd[1]; + +- if (am_private->vcodec.handle <= 0) { +- return 0; +- } ++ if (am_private->vcodec.handle <= 0) { ++ return 0; ++ } + +- codec_poll_fd[0].fd = am_private->vcodec.handle; +- codec_poll_fd[0].events = POLLOUT; ++ codec_poll_fd[0].fd = am_private->vcodec.handle; ++ codec_poll_fd[0].events = POLLOUT; + +- return poll(codec_poll_fd, 1, 100); ++ if (poll(codec_poll_fd, 1, 100) == 0) ++ { ++ g_aml_sync_event.Set(); ++ return 0; ++ } ++ return false; + } + + int CAMLCodec::ReleaseFrame(unsigned long pts) +@@ -1997,8 +1990,6 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; + pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE; + +- CLog::Log(LOGERROR, "CAMLCodec::GetPicture pts: %lld", m_cur_pts); +- + return true; + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 6348647..1fb95b1 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -70,7 +70,6 @@ class CAMLCodec + void CloseAmlVideo(); + std::string GetVfmMap(const std::string &name); + void SetVfmMap(const std::string &name, const std::string &map); +- unsigned int GetDecodedFrameCount(); + int DequeueBuffer(int64_t &pts); + + DllLibAmCodec *m_dll; +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index d390c08..9ebcbf6 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -30,36 +30,10 @@ + #include "cores/VideoPlayer/VideoRenderers/RenderCapture.h" + #include "settings/AdvancedSettings.h" + +-static int get_pts(const char *strPath) +-{ +- int fd = open(strPath, O_RDONLY); +- if (fd >= 0) +- { +- char pts_str[64]; +- int size = read(fd, pts_str, sizeof(pts_str)); +- close(fd); +- return strtol(pts_str, NULL, 16); +- } +- return 0; +-} +- +-static void set_pts(const char *strPath, int pts) +-{ +- int fd = open(strPath, O_WRONLY); +- if (fd >= 0) +- { +- char pts_str[64]; +- sprintf(pts_str, "0x%x", pts); +- write(fd, pts_str, strlen(pts_str)); +- close(fd); +- } +-} +- + CRendererAML::CRendererAML() + : m_prevVPts(-1) + , m_bConfigured(false) + , m_iRenderBuffer(0) +- , m_diff_counter(0) + { + } + +@@ -182,7 +156,6 @@ EINTERLACEMETHOD CRendererAML::AutoInterlaceMethod() + void CRendererAML::Reset() + { + m_prevVPts = -1; +- m_diff_counter = 0; + } + + void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) +@@ -192,65 +165,19 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + CDVDAmlogicInfo *amli = static_cast(m_buffers[m_iRenderBuffer].hwDec); + CAMLCodec *amlcodec = amli ? amli->getAmlCodec() : 0; + +-#if 1 + if(amlcodec) + { + int pts = amli->GetOmxPts(); + if (pts != m_prevVPts) + { +- CLog::Log(LOGDEBUG, "RenderUpdate: ReleaseFrame with pts:%d", pts); ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "RenderUpdate: ReleaseFrame with pts:%d", pts); + amlcodec->ReleaseFrame(pts); + amlcodec->SetVideoRect(m_sourceRect, m_destRect); + m_prevVPts = pts; + } + amlcodec->PollFrame(); + } +-#else +- int videopts(0); +- if(amlcodec) +- { +- unsigned int i(0); +- do { +- amlcodec->PollFrame(); +- videopts = get_pts("/sys/class/tsync/pts_video"); +- } while (i++ < 5 && videopts == m_prevVPts); +- } +- m_prevVPts = videopts; +- +- if (amli) +- { +- int pts = amli->GetOmxPts(); +- +- int pcrscr(get_pts("/sys/class/tsync/pts_pcrscr")); +- int diff(static_cast((pcrscr - pts)*1.1 / amli->GetAmlDuration())); +- m_diff_counter += diff; +- +- if(!diff) +- { +- if (m_diff_counter > 0) +- --m_diff_counter; +- else if (m_diff_counter < 0) +- ++m_diff_counter; +- } +- +- if (abs(m_diff_counter) > 5) +- { +- set_pts("/sys/class/tsync/pts_pcrscr", pts); +- 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); +- pcrscr = pts; +- m_diff_counter = 0; +- } +- else if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- { +- CLog::Log(LOGDEBUG, "RenderUpdate: ptsclock:%d ptsscr:%d vpts:%d diff:%d", pts, pcrscr, videopts, m_diff_counter); +- } +- +- SysfsUtils::SetInt("/sys/module/amvideo/parameters/omx_pts", pcrscr); +- +- if(amlcodec) +- amlcodec->SetVideoRect(m_sourceRect, m_destRect); +- } +-#endif + } + + #endif +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +index 7b4203b..cd68401 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.h +@@ -72,7 +72,6 @@ class CRendererAML : public CBaseRenderer + + int m_prevVPts; + bool m_bConfigured; +- int m_diff_counter; + }; + + #endif +diff --git a/xbmc/video/VideoReferenceClock.cpp b/xbmc/video/VideoReferenceClock.cpp +index a8dbdaf..e8755a1 100644 +--- a/xbmc/video/VideoReferenceClock.cpp ++++ b/xbmc/video/VideoReferenceClock.cpp +@@ -49,6 +49,9 @@ + #if defined(TARGET_ANDROID) + #include "video/videosync/VideoSyncAndroid.h" + #endif ++#if defined(HAS_LIBAMCODEC) ++#include "video/videosync/VideoSyncAML.h" ++#endif + + #ifdef TARGET_POSIX + #include "linux/XTimeUtils.h" +@@ -125,6 +128,8 @@ void CVideoReferenceClock::Process() + m_pVideoSync = new CVideoSyncIMX(this); + #elif defined(TARGET_ANDROID) + m_pVideoSync = new CVideoSyncAndroid(this); ++#elif defined(HAS_LIBAMCODEC) ++ m_pVideoSync = new CVideoSyncAML(this); + #endif + + if (m_pVideoSync) +diff --git a/xbmc/video/videosync/CMakeLists.txt b/xbmc/video/videosync/CMakeLists.txt +index 421af44..75c9011 100644 +--- a/xbmc/video/videosync/CMakeLists.txt ++++ b/xbmc/video/videosync/CMakeLists.txt +@@ -35,6 +35,11 @@ if(CORE_SYSTEM_NAME STREQUAL android) + list(APPEND HEADERS VideoSyncAndroid.h) + endif() + ++if(AML_FOUND) ++ list(APPEND SOURCES VideoSyncAML.cpp) ++ list(APPEND HEADERS VideoSyncAML.h) ++endif() ++ + if(SOURCES AND HEADERS) + core_add_library(video_sync) + endif() +diff --git a/xbmc/video/videosync/VideoSyncAML.cpp b/xbmc/video/videosync/VideoSyncAML.cpp +new file mode 100644 +index 0000000..fb744e2 +--- /dev/null ++++ b/xbmc/video/videosync/VideoSyncAML.cpp +@@ -0,0 +1,86 @@ ++/* ++ * Copyright (C) 2005-2014 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#include "system.h" ++ ++#if defined(HAS_LIBAMCODEC) ++ ++#include "video/videosync/VideoSyncAML.h" ++#include "guilib/GraphicContext.h" ++#include "windowing/WindowingFactory.h" ++#include "utils/TimeUtils.h" ++#include "utils/log.h" ++#include "threads/Thread.h" ++#include ++ ++extern CEvent g_aml_sync_event; ++ ++CVideoSyncAML::CVideoSyncAML(CVideoReferenceClock *clock) ++: CVideoSync(clock) ++, m_abort(false) ++{ ++} ++ ++CVideoSyncAML::~CVideoSyncAML() ++{ ++} ++ ++bool CVideoSyncAML::Setup(PUPDATECLOCK func) ++{ ++ UpdateClock = func; ++ ++ m_abort = false; ++ ++ g_Windowing.Register(this); ++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: setting up AML"); ++ ++ return true; ++} ++ ++void CVideoSyncAML::Run(std::atomic& stop) ++{ ++ while (!stop && !m_abort) ++ { ++ g_aml_sync_event.WaitMSec(100); ++ uint64_t now = CurrentHostCounter(); ++ ++ UpdateClock(1, now, m_refClock); ++ } ++} ++ ++void CVideoSyncAML::Cleanup() ++{ ++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: cleaning up AML"); ++ g_Windowing.Unregister(this); ++} ++ ++float CVideoSyncAML::GetFps() ++{ ++ m_fps = g_graphicsContext.GetFPS(); ++ CLog::Log(LOGDEBUG, "CVideoReferenceClock: fps: %.3f", m_fps); ++ return m_fps; ++} ++ ++void CVideoSyncAML::OnResetDisplay() ++{ ++ m_abort = true; ++} ++ ++#endif +diff --git a/xbmc/video/videosync/VideoSyncAML.h b/xbmc/video/videosync/VideoSyncAML.h +new file mode 100644 +index 0000000..f48e3b4 +--- /dev/null ++++ b/xbmc/video/videosync/VideoSyncAML.h +@@ -0,0 +1,41 @@ ++#pragma once ++/* ++ * Copyright (C) 2005-2016 Team XBMC ++ * http://xbmc.org ++ * ++ * This Program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2, or (at your option) ++ * any later version. ++ * ++ * This Program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with XBMC; see the file COPYING. If not, see ++ * . ++ * ++ */ ++ ++#if defined(HAS_LIBAMCODEC) ++ ++#include "video/videosync/VideoSync.h" ++#include "guilib/DispResource.h" ++ ++class CVideoSyncAML : public CVideoSync, IDispResource ++{ ++public: ++ CVideoSyncAML(CVideoReferenceClock *clock); ++ virtual ~CVideoSyncAML(); ++ virtual bool Setup(PUPDATECLOCK func); ++ virtual void Run(std::atomic& stop); ++ virtual void Cleanup(); ++ virtual float GetFps(); ++ virtual void OnResetDisplay(); ++private: ++ volatile bool m_abort; ++}; ++ ++#endif + +From fcc5dfb9a8a7edaa66bda89424fbf68802a83198 Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Fri, 23 Dec 2016 16:17:47 +0100 +Subject: [PATCH 23/30] pts -> buffer-index + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 45 +++++++++------------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 8 ++-- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 6 ++- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 4 +- + .../VideoRenderers/HwDecRender/RendererAML.cpp | 4 +- + 5 files changed, 33 insertions(+), 34 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index d081c21..986513d 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1377,6 +1377,7 @@ CAMLCodec::CAMLCodec() + , m_ptsIs64us(false) + , m_cur_pts(INT64_0) + , m_last_pts(0) ++ , m_bufferIndex(-1) + , m_state(0) + { + am_private = new am_private_t; +@@ -1875,13 +1876,8 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + } + + int rtn(0); +- int64_t decode_pts = 0; +- if ((m_state & STATE_PREFILLED) != 0 && timesize > 0.5 && DequeueBuffer(decode_pts) == 0) +- { ++ if ((m_state & STATE_PREFILLED) != 0 && timesize > 0.5 && DequeueBuffer() == 0) + rtn |= VC_PICTURE; +- m_last_pts = m_cur_pts; +- m_cur_pts = decode_pts; +- } + else //Timesize actualizes each 10ms, throttle decode calls to avoid reading too much + usleep(2500); + +@@ -1890,7 +1886,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.6f[%llX], pts_in: %0.6f[%llX], adj:%llu, ptsOut:%0.6f, amlpts:%d timesize:%0.2f", ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.6f[%llX], pts_in: %0.6f[%llX], adj:%llu, ptsOut:%0.6f, amlpts:%d, idx:%u, timesize:%0.2f", + rtn, + static_cast(iSize), + static_cast(dts)/DVD_TIME_BASE, am_private->am_pkt.avdts, +@@ -1898,6 +1894,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + m_start_adj, + static_cast(m_cur_pts)/PTS_FREQ, + static_cast(m_cur_pts), ++ m_bufferIndex, + timesize + ); + } +@@ -1909,43 +1906,36 @@ int CAMLCodec::PollFrame() + { + struct pollfd codec_poll_fd[1]; + +- if (am_private->vcodec.handle <= 0) { ++ if (am_private->vcodec.cntl_handle <= 0) { + return 0; + } + +- codec_poll_fd[0].fd = am_private->vcodec.handle; ++ codec_poll_fd[0].fd = am_private->vcodec.cntl_handle; + codec_poll_fd[0].events = POLLOUT; + +- if (poll(codec_poll_fd, 1, 100) == 0) ++ if (poll(codec_poll_fd, 1, 100) > 0) + { + g_aml_sync_event.Set(); + return 0; + } ++ + return false; + } + +-int CAMLCodec::ReleaseFrame(unsigned long pts) ++int CAMLCodec::ReleaseFrame(const uint32_t index) + { + int ret; + v4l2_buffer vbuf = { 0 }; + vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + vbuf.memory = V4L2_MEMORY_USERPTR; +- +- if (m_ptsIs64us) +- { +- uint64_t us = (static_cast(pts) * DVD_TIME_BASE) / PTS_FREQ; +- vbuf.timestamp.tv_sec = us >> 32; +- vbuf.timestamp.tv_usec = us & 0xFFFFFFFF; +- } +- else +- vbuf.timestamp.tv_usec = pts; ++ vbuf.index = index; + + if ((ret = m_amlVideoFile->IOControl(VIDIOC_QBUF, &vbuf)) < 0) + CLog::Log(LOGERROR, "CAMLCodec::ReleaseFrame - VIDIOC_QBUF failed: %s", strerror(errno)); + return ret; + } + +-int CAMLCodec::DequeueBuffer(int64_t &pts) ++int CAMLCodec::DequeueBuffer() + { + v4l2_buffer vbuf = { 0 }; + vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +@@ -1960,17 +1950,20 @@ int CAMLCodec::DequeueBuffer(int64_t &pts) + // Since kernel 3.14 Amlogic changed length and units of PTS values reported here. + // To differentiate such PTS values we check for existence of omx_pts_interval_lower + // parameter, because it was introduced since kernel 3.14. ++ m_last_pts = m_cur_pts; ++ + if (m_ptsIs64us) + { +- pts = vbuf.timestamp.tv_sec & 0xFFFFFFFF; +- pts <<= 32; +- pts += vbuf.timestamp.tv_usec & 0xFFFFFFFF; +- pts = (pts * PTS_FREQ) / DVD_TIME_BASE; ++ m_cur_pts = vbuf.timestamp.tv_sec & 0xFFFFFFFF; ++ m_cur_pts <<= 32; ++ m_cur_pts += vbuf.timestamp.tv_usec & 0xFFFFFFFF; ++ m_cur_pts = (m_cur_pts * PTS_FREQ) / DVD_TIME_BASE; + } + else + { +- pts = vbuf.timestamp.tv_usec; ++ m_cur_pts = vbuf.timestamp.tv_usec; + } ++ m_bufferIndex = vbuf.index; + return 0; + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 1fb95b1..b2b0950 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -52,11 +52,12 @@ class CAMLCodec + void SetVideoRate(int videoRate); + int64_t GetCurPts() const { return m_cur_pts + m_start_adj; } + int GetOMXPts() const { return static_cast(m_cur_pts); } ++ uint32_t GetBufferIndex() const { return m_bufferIndex; }; + static float OMXPtsToSeconds(int omxpts); + static int OMXDurationToNs(int duration); + int GetAmlDuration() const; + int PollFrame(); +- int ReleaseFrame(unsigned long pts); ++ int ReleaseFrame(const uint32_t index); + + private: + void ShowMainVideo(const bool show); +@@ -70,7 +71,7 @@ class CAMLCodec + void CloseAmlVideo(); + std::string GetVfmMap(const std::string &name); + void SetVfmMap(const std::string &name, const std::string &map); +- int DequeueBuffer(int64_t &pts); ++ int DequeueBuffer(); + + DllLibAmCodec *m_dll; + bool m_opened; +@@ -79,9 +80,10 @@ class CAMLCodec + CDVDStreamInfo m_hints; + int m_speed; + int64_t m_cur_pts; +- volatile int64_t m_vbufsize; ++ int64_t m_vbufsize; + int64_t m_start_adj; + int64_t m_last_pts; ++ uint32_t m_bufferIndex; + + CRect m_dst_rect; + CRect m_display_rect; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index a6803e4..1f2c6c3 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -338,7 +338,8 @@ bool CDVDVideoCodecAmlogic::GetPicture(DVDVideoPicture* pDvdVideoPicture) + m_Codec->GetPicture(&m_videobuffer); + *pDvdVideoPicture = m_videobuffer; + +- CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec, m_Codec->GetOMXPts(), m_Codec->GetAmlDuration()); ++ CDVDAmlogicInfo* info = new CDVDAmlogicInfo(this, m_Codec, ++ m_Codec->GetOMXPts(), m_Codec->GetAmlDuration(), m_Codec->GetBufferIndex()); + + { + CSingleLock lock(m_secure); +@@ -623,12 +624,13 @@ void CDVDVideoCodecAmlogic::RemoveInfo(CDVDAmlogicInfo *info) + m_inflight.erase(m_inflight.find(info)); + } + +-CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration) ++CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration, uint32_t bufferIndex) + : m_refs(0) + , m_codec(codec) + , m_amlCodec(amlcodec) + , m_omxPts(omxPts) + , m_amlDuration(amlDuration) ++ , m_bufferIndex(bufferIndex) + { + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +index a494ace..c28d1c4 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +@@ -36,7 +36,7 @@ class CDVDVideoCodecAmlogic; + class CDVDAmlogicInfo + { + public: +- CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration); ++ CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcodec, int omxPts, int amlDuration, uint32_t bufferIndex); + + // reference counting + CDVDAmlogicInfo* Retain(); +@@ -45,6 +45,7 @@ class CDVDAmlogicInfo + CAMLCodec *getAmlCodec() const; + int GetOmxPts() const { return m_omxPts; } + int GetAmlDuration() const { return m_amlDuration; } ++ uint32_t GetBufferIndex() const { return m_bufferIndex; }; + void invalidate(); + + protected: +@@ -54,6 +55,7 @@ class CDVDAmlogicInfo + CDVDVideoCodecAmlogic* m_codec; + CAMLCodec* m_amlCodec; + int m_omxPts, m_amlDuration; ++ uint32_t m_bufferIndex; + }; + + class CDVDVideoCodecAmlogic : public CDVDVideoCodec +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index 9ebcbf6..5bd0a0f 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -171,8 +171,8 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + if (pts != m_prevVPts) + { + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "RenderUpdate: ReleaseFrame with pts:%d", pts); +- amlcodec->ReleaseFrame(pts); ++ CLog::Log(LOGDEBUG, "RenderUpdate: ReleaseFrame with pts:%d, idx:%u", pts, amli->GetBufferIndex()); ++ amlcodec->ReleaseFrame(amli->GetBufferIndex()); + amlcodec->SetVideoRect(m_sourceRect, m_destRect); + m_prevVPts = pts; + } + +From 29cbcbe1fa813473431d1f3322d6ecd67295dc1e Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Mon, 26 Dec 2016 15:01:08 +0100 +Subject: [PATCH 24/30] implement frame drop + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 49 ++++++++++++++-------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 11 +++-- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 1 + + .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 3 ++ + .../VideoRenderers/HwDecRender/RendererAML.cpp | 13 ++++-- + 5 files changed, 52 insertions(+), 25 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 986513d..95307ae 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -31,6 +31,7 @@ + #include "settings/DisplaySettings.h" + #include "settings/MediaSettings.h" + #include "settings/Settings.h" ++#include "threads/Atomics.h" + #include "utils/AMLUtils.h" + #include "utils/log.h" + #include "utils/StringUtils.h" +@@ -1663,6 +1664,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + // vcodec is open, update speed if it was + // changed before VideoPlayer called OpenDecoder. + SetSpeed(m_speed); ++ SetPollDevice(am_private->vcodec.cntl_handle); + + return true; + } +@@ -1683,15 +1685,6 @@ bool CAMLCodec::OpenAmlVideo(const CDVDStreamInfo &hints) + + SysfsUtils::SetInt("/sys/module/amlvideodri/parameters/freerun_mode", 3); + +- struct v4l2_requestbuffers rbuf = {0}; +- rbuf.count = 1; +- rbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- rbuf.memory = V4L2_MEMORY_USERPTR; +- if (m_amlVideoFile->IOControl(VIDIOC_REQBUFS, &rbuf) < 0) +- { +- if (errno != EAGAIN) +- CLog::Log(LOGERROR, "CAMLCodec::OpenAML - VIDIOC_REQBUFS failed: %s", strerror(errno)); +- } + return true; + } + +@@ -1727,6 +1720,8 @@ void CAMLCodec::CloseDecoder() + { + CLog::Log(LOGDEBUG, "CAMLCodec::CloseDecoder"); + ++ SetPollDevice(-1); ++ + // never leave vcodec ff/rw or paused. + if (m_speed != DVD_PLAYSPEED_NORMAL) + { +@@ -1761,6 +1756,8 @@ void CAMLCodec::Reset() + if (!m_opened) + return; + ++ SetPollDevice(-1); ++ + // set the system blackout_policy to leave the last frame showing + int blackout_policy; + SysfsUtils::GetInt("/sys/class/video/blackout_policy", blackout_policy); +@@ -1794,6 +1791,8 @@ void CAMLCodec::Reset() + m_state = 0; + m_start_adj = 0; + SetSpeed(m_speed); ++ ++ SetPollDevice(am_private->vcodec.cntl_handle); + } + + int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) +@@ -1902,34 +1901,48 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + return rtn; + } + ++long CAMLCodec::m_pollSync = 0; ++int CAMLCodec::m_pollDevice; ++ + int CAMLCodec::PollFrame() + { +- struct pollfd codec_poll_fd[1]; +- +- if (am_private->vcodec.cntl_handle <= 0) { ++ CAtomicSpinLock lock(m_pollSync); ++ if (m_pollDevice < 0) + return 0; +- } + +- codec_poll_fd[0].fd = am_private->vcodec.cntl_handle; ++ struct pollfd codec_poll_fd[1]; ++ static unsigned int pc(0); ++ ++ codec_poll_fd[0].fd = m_pollDevice; + codec_poll_fd[0].events = POLLOUT; + + if (poll(codec_poll_fd, 1, 100) > 0) + { + g_aml_sync_event.Set(); +- return 0; ++ return 1; + } ++ return 0; ++} + +- return false; ++void CAMLCodec::SetPollDevice(int dev) ++{ ++ CAtomicSpinLock lock(m_pollSync); ++ m_pollDevice = dev; + } + +-int CAMLCodec::ReleaseFrame(const uint32_t index) ++int CAMLCodec::ReleaseFrame(const uint32_t index, bool drop) + { + int ret; + v4l2_buffer vbuf = { 0 }; + vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; +- vbuf.memory = V4L2_MEMORY_USERPTR; + vbuf.index = index; + ++ if (drop) ++ vbuf.flags |= V4L2_BUF_FLAG_DONE; ++ ++ if (g_advancedSettings.CanLogComponent(LOGVIDEO)) ++ CLog::Log(LOGDEBUG, "CAMLCodec::ReleaseFrame idx:%u", index); ++ + if ((ret = m_amlVideoFile->IOControl(VIDIOC_QBUF, &vbuf)) < 0) + CLog::Log(LOGERROR, "CAMLCodec::ReleaseFrame - VIDIOC_QBUF failed: %s", strerror(errno)); + return ret; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index b2b0950..d5d5723 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -24,6 +24,7 @@ + #include "cores/IPlayer.h" + #include "guilib/Geometry.h" + #include "rendering/RenderSystem.h" ++#include + + typedef struct am_private_t am_private_t; + +@@ -56,8 +57,10 @@ class CAMLCodec + static float OMXPtsToSeconds(int omxpts); + static int OMXDurationToNs(int duration); + int GetAmlDuration() const; +- int PollFrame(); +- int ReleaseFrame(const uint32_t index); ++ int ReleaseFrame(const uint32_t index, bool bDrop = false); ++ ++ static int PollFrame(); ++ static void SetPollDevice(int device); + + private: + void ShowMainVideo(const bool show); +@@ -102,5 +105,7 @@ class CAMLCodec + + PosixFilePtr m_amlVideoFile; + std::string m_defaultVfmMap; +- CCriticalSection m_ptsQueueMutex; ++ ++ static long m_pollSync; ++ static int m_pollDevice; + }; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index 1f2c6c3..a31584e 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -631,6 +631,7 @@ CDVDAmlogicInfo::CDVDAmlogicInfo(CDVDVideoCodecAmlogic *codec, CAMLCodec *amlcod + , m_omxPts(omxPts) + , m_amlDuration(amlDuration) + , m_bufferIndex(bufferIndex) ++ , m_rendered(false) + { + } + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +index c28d1c4..bbebf57 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +@@ -47,6 +47,8 @@ class CDVDAmlogicInfo + int GetAmlDuration() const { return m_amlDuration; } + uint32_t GetBufferIndex() const { return m_bufferIndex; }; + void invalidate(); ++ void SetRendered() { m_rendered = true; }; ++ bool IsRendered() { return m_rendered; }; + + protected: + long m_refs; +@@ -56,6 +58,7 @@ class CDVDAmlogicInfo + CAMLCodec* m_amlCodec; + int m_omxPts, m_amlDuration; + uint32_t m_bufferIndex; ++ bool m_rendered; + }; + + class CDVDVideoCodecAmlogic : public CDVDVideoCodec +diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +index 5bd0a0f..292f07b 100644 +--- a/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp ++++ b/xbmc/cores/VideoPlayer/VideoRenderers/HwDecRender/RendererAML.cpp +@@ -105,7 +105,13 @@ void CRendererAML::ReleaseBuffer(int idx) + if (buf.hwDec) + { + CDVDAmlogicInfo *amli = static_cast(buf.hwDec); +- SAFE_RELEASE(amli); ++ if (amli) ++ { ++ CAMLCodec *amlcodec; ++ if (!amli->IsRendered() && (amlcodec = amli->getAmlCodec())) ++ amlcodec->ReleaseFrame(amli->GetBufferIndex(), true); ++ SAFE_RELEASE(amli); ++ } + buf.hwDec = NULL; + } + } +@@ -170,14 +176,13 @@ void CRendererAML::RenderUpdate(bool clear, DWORD flags, DWORD alpha) + int pts = amli->GetOmxPts(); + if (pts != m_prevVPts) + { +- if (g_advancedSettings.CanLogComponent(LOGVIDEO)) +- CLog::Log(LOGDEBUG, "RenderUpdate: ReleaseFrame with pts:%d, idx:%u", pts, amli->GetBufferIndex()); + amlcodec->ReleaseFrame(amli->GetBufferIndex()); + amlcodec->SetVideoRect(m_sourceRect, m_destRect); ++ amli->SetRendered(); + m_prevVPts = pts; + } +- amlcodec->PollFrame(); + } ++ CAMLCodec::PollFrame(); + } + + #endif + +From 1aa22d7a3526d21a5d9abe1ac2106828bbd86c2c Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Wed, 28 Dec 2016 23:40:19 +0100 +Subject: [PATCH 25/30] log pts/dts as double, sleep in dequeue at least 10ms + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 25 +++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 95307ae..861801f 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -49,6 +49,8 @@ + #include + #include + #include ++#include ++#include + + // amcodec include + extern "C" { +@@ -1885,11 +1887,11 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.6f[%llX], pts_in: %0.6f[%llX], adj:%llu, ptsOut:%0.6f, amlpts:%d, idx:%u, timesize:%0.2f", ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.4lf[%llX], pts_in: %0.4lf[%llX], adj:%llu, ptsOut:%0.4f, amlpts:%d, idx:%u, timesize:%0.2f", + rtn, + static_cast(iSize), +- static_cast(dts)/DVD_TIME_BASE, am_private->am_pkt.avdts, +- static_cast(pts)/DVD_TIME_BASE, am_private->am_pkt.avpts, ++ dts / DVD_TIME_BASE, am_private->am_pkt.avdts, ++ pts / DVD_TIME_BASE, am_private->am_pkt.avpts, + m_start_adj, + static_cast(m_cur_pts)/PTS_FREQ, + static_cast(m_cur_pts), +@@ -1953,10 +1955,19 @@ int CAMLCodec::DequeueBuffer() + v4l2_buffer vbuf = { 0 }; + vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + ++ //Driver change from 10 to 0ms latency, throttle here ++ std::chrono::time_point now(std::chrono::system_clock::now()); ++ + if (m_amlVideoFile->IOControl(VIDIOC_DQBUF, &vbuf) < 0) + { + if (errno != EAGAIN) + CLog::Log(LOGERROR, "CAMLCodec::DequeueBuffer - VIDIOC_DQBUF failed: %s", strerror(errno)); ++ ++ std::chrono::milliseconds elapsed(std::chrono::duration_cast(std::chrono::system_clock::now() - now).count()); ++ ++ if (elapsed < std::chrono::milliseconds(10)) ++ std::this_thread::sleep_for(std::chrono::milliseconds(10) - elapsed); ++ + return -errno; + } + +@@ -2051,12 +2062,20 @@ double CAMLCodec::GetTimeSize() + return 0; + + double timesize(0); ++#if 0 ++ int video_delay_ms; ++ if (m_dll->codec_get_video_cur_delay_ms(&am_private->vcodec, &video_delay_ms) >= 0) ++ timesize = (float)video_delay_ms / 1000.0; ++ if (timesize < 0 || timesize > 5.0) ++ CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: %0.4f",timesize); ++#else + if (m_cur_pts != INT64_0) + { + timesize = static_cast(am_private->am_pkt.avdts - m_cur_pts) / PTS_FREQ; + if (timesize < 0 || timesize > 5.0) + CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: avdts: %lld cur_pts: %lld",am_private->am_pkt.avdts, m_cur_pts); + } ++#endif + + // lie to VideoPlayer, it is hardcoded to a max of 8 seconds, + // if you buffer more than 8 seconds, it goes nuts. + +From 795416b9dea2e7ab9de696176845c237bcdcee0d Mon Sep 17 00:00:00 2001 +From: peak3d +Date: Thu, 29 Dec 2016 17:01:44 +0100 +Subject: [PATCH 26/30] pass readjusted PTS value in GetPicture() + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 861801f..db544ce 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -2005,7 +2005,7 @@ bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + pDvdVideoPicture->iDuration = (double)((m_cur_pts - m_last_pts) * DVD_TIME_BASE) / PTS_FREQ; + + pDvdVideoPicture->dts = DVD_NOPTS_VALUE; +- pDvdVideoPicture->pts = (double)m_cur_pts / PTS_FREQ * DVD_TIME_BASE; ++ pDvdVideoPicture->pts = (double)GetCurPts() / PTS_FREQ * DVD_TIME_BASE; + + return true; + } + +From bd1554621f0310c40b133e0fa3b9296b55bc75a8 Mon Sep 17 00:00:00 2001 +From: peak3d +Date: Mon, 2 Jan 2017 18:10:35 +0100 +Subject: [PATCH 27/30] Remove GetDataSize() / GetTimeSize() + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 80 +++++----------------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 4 +- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 16 ----- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.h | 2 - + 4 files changed, 20 insertions(+), 82 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index db544ce..2cfb486 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1434,7 +1434,7 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_zoom = -1; + m_contrast = -1; + m_brightness = -1; +- m_vbufsize = 500000 * 2; ++ m_max_frame_size = 0; + m_start_adj = 0; + m_hints = hints; + m_state = 0; +@@ -1792,6 +1792,7 @@ void CAMLCodec::Reset() + m_cur_pts = INT64_0; + m_state = 0; + m_start_adj = 0; ++ m_max_frame_size = 0; + SetSpeed(m_speed); + + SetPollDevice(am_private->vcodec.cntl_handle); +@@ -1800,9 +1801,18 @@ void CAMLCodec::Reset() + int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + { + if (!m_opened) +- return VC_BUFFER; ++ return VC_ERROR; ++ ++ int rtn(0); ++ ++ struct buf_status bs; ++ m_dll->codec_get_vbuf_state(&am_private->vcodec, &bs); ++ if (!m_max_frame_size || bs.data_len < m_max_frame_size) ++ rtn = VC_BUFFER; ++ ++ //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: buf status: s:%d dl:%d fl:%d rp:%u wp:%u",bs.size, bs.data_len, bs.free_len, bs.read_pointer, bs.write_pointer); ++ + +- float timesize(static_cast(GetTimeSize())); + if (pData) + { + am_private->am_pkt.data = pData; +@@ -1869,25 +1879,17 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + // Decoder got stuck; Reset + Reset(); + } +- if ((m_state & STATE_PREFILLED) == 0 && timesize >= 1.0) +- { +- //m_dll->codec_resume(&am_private->vcodec); +- m_state |= STATE_PREFILLED; +- } ++ ++ if (iSize > m_max_frame_size) ++ m_max_frame_size = iSize; + } + +- int rtn(0); +- if ((m_state & STATE_PREFILLED) != 0 && timesize > 0.5 && DequeueBuffer() == 0) ++ if (DequeueBuffer() == 0) + rtn |= VC_PICTURE; +- else //Timesize actualizes each 10ms, throttle decode calls to avoid reading too much +- usleep(2500); +- +- if (((rtn & VC_PICTURE) == 0 && timesize < 2.0) || timesize < 1.0) +- rtn |= VC_BUFFER; + + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.4lf[%llX], pts_in: %0.4lf[%llX], adj:%llu, ptsOut:%0.4f, amlpts:%d, idx:%u, timesize:%0.2f", ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.4lf[%llX], pts_in: %0.4lf[%llX], adj:%llu, ptsOut:%0.4f, amlpts:%d, idx:%u", + rtn, + static_cast(iSize), + dts / DVD_TIME_BASE, am_private->am_pkt.avdts, +@@ -1895,8 +1897,7 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + m_start_adj, + static_cast(m_cur_pts)/PTS_FREQ, + static_cast(m_cur_pts), +- m_bufferIndex, +- timesize ++ m_bufferIndex + ); + } + +@@ -2044,49 +2045,6 @@ void CAMLCodec::SetSpeed(int speed) + } + } + +-int CAMLCodec::GetDataSize() +-{ +- if (!m_opened) +- return 0; +- +- struct buf_status vbuf ={0}; +- if (m_dll->codec_get_vbuf_state(&am_private->vcodec, &vbuf) >= 0) +- m_vbufsize = vbuf.size; +- +- return vbuf.data_len; +-} +- +-double CAMLCodec::GetTimeSize() +-{ +- if (!m_opened) +- return 0; +- +- double timesize(0); +-#if 0 +- int video_delay_ms; +- if (m_dll->codec_get_video_cur_delay_ms(&am_private->vcodec, &video_delay_ms) >= 0) +- timesize = (float)video_delay_ms / 1000.0; +- if (timesize < 0 || timesize > 5.0) +- CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: %0.4f",timesize); +-#else +- if (m_cur_pts != INT64_0) +- { +- timesize = static_cast(am_private->am_pkt.avdts - m_cur_pts) / PTS_FREQ; +- if (timesize < 0 || timesize > 5.0) +- CLog::Log(LOGWARNING, "CAMLCodec::GetTimeSize limits exceed: avdts: %lld cur_pts: %lld",am_private->am_pkt.avdts, m_cur_pts); +- } +-#endif +- +- // lie to VideoPlayer, it is hardcoded to a max of 8 seconds, +- // if you buffer more than 8 seconds, it goes nuts. +- if (timesize < 0.0) +- timesize = 0.0; +- else if (timesize > 7.0) +- timesize = 7.0; +- +- return timesize; +-} +- + void CAMLCodec::ShowMainVideo(const bool show) + { + static int saved_disable_video = -1; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index d5d5723..04146a0 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -47,8 +47,6 @@ class CAMLCodec + + bool GetPicture(DVDVideoPicture* pDvdVideoPicture); + void SetSpeed(int speed); +- int GetDataSize(); +- double GetTimeSize(); + void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); + void SetVideoRate(int videoRate); + int64_t GetCurPts() const { return m_cur_pts + m_start_adj; } +@@ -83,7 +81,7 @@ class CAMLCodec + CDVDStreamInfo m_hints; + int m_speed; + int64_t m_cur_pts; +- int64_t m_vbufsize; ++ uint32_t m_max_frame_size; + int64_t m_start_adj; + int64_t m_last_pts; + uint32_t m_bufferIndex; +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index a31584e..aef4060 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -396,22 +396,6 @@ void CDVDVideoCodecAmlogic::SetSpeed(int iSpeed) + m_Codec->SetSpeed(iSpeed); + } + +-int CDVDVideoCodecAmlogic::GetDataSize(void) +-{ +- if (m_Codec) +- return m_Codec->GetDataSize(); +- +- return 0; +-} +- +-double CDVDVideoCodecAmlogic::GetTimeSize(void) +-{ +- if (m_Codec) +- return m_Codec->GetTimeSize(); +- +- return 0.0; +-} +- + void CDVDVideoCodecAmlogic::FrameQueuePop(void) + { + if (!m_frame_queue || m_queue_depth == 0) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +index bbebf57..9e57295 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.h +@@ -77,8 +77,6 @@ class CDVDVideoCodecAmlogic : public CDVDVideoCodec + virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture); + virtual void SetSpeed(int iSpeed); + virtual void SetDropState(bool bDrop); +- virtual int GetDataSize(void); +- virtual double GetTimeSize(void); + virtual const char* GetName(void) { return (const char*)m_pFormatName; } + + protected: + +From 48da105c90fd4518f2541b25ac8fcee3085f64fd Mon Sep 17 00:00:00 2001 +From: peak3d +Date: Wed, 4 Jan 2017 14:28:46 +0100 +Subject: [PATCH 28/30] increase buffer level + +--- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index 2cfb486..cedc177 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1880,8 +1880,8 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + Reset(); + } + +- if (iSize > m_max_frame_size) +- m_max_frame_size = iSize; ++ if (iSize*2 > m_max_frame_size) ++ m_max_frame_size = iSize*2; + } + + if (DequeueBuffer() == 0) + +From 52a6360260c590e3a7a08c5fa7a39816c4760f8d Mon Sep 17 00:00:00 2001 +From: peak3d +Date: Thu, 5 Jan 2017 14:58:20 +0100 +Subject: [PATCH 29/30] prefeed based on frame durations + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 54 +++++++++++++++------- + xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h | 4 ++ + 2 files changed, 41 insertions(+), 17 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index cedc177..db36553 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1382,6 +1382,7 @@ CAMLCodec::CAMLCodec() + , m_last_pts(0) + , m_bufferIndex(-1) + , m_state(0) ++ , m_frameSizeSum(0) + { + am_private = new am_private_t; + memset(am_private, 0, sizeof(am_private_t)); +@@ -1434,10 +1435,11 @@ bool CAMLCodec::OpenDecoder(CDVDStreamInfo &hints) + m_zoom = -1; + m_contrast = -1; + m_brightness = -1; +- m_max_frame_size = 0; + m_start_adj = 0; + m_hints = hints; + m_state = 0; ++ m_frameSizes.clear(); ++ m_frameSizeSum = 0; + + if (!OpenAmlVideo(hints)) + { +@@ -1792,7 +1794,9 @@ void CAMLCodec::Reset() + m_cur_pts = INT64_0; + m_state = 0; + m_start_adj = 0; +- m_max_frame_size = 0; ++ m_frameSizes.clear(); ++ m_frameSizeSum = 0; ++ + SetSpeed(m_speed); + + SetPollDevice(am_private->vcodec.cntl_handle); +@@ -1805,16 +1809,12 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + + int rtn(0); + +- struct buf_status bs; +- m_dll->codec_get_vbuf_state(&am_private->vcodec, &bs); +- if (!m_max_frame_size || bs.data_len < m_max_frame_size) +- rtn = VC_BUFFER; +- +- //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: buf status: s:%d dl:%d fl:%d rp:%u wp:%u",bs.size, bs.data_len, bs.free_len, bs.read_pointer, bs.write_pointer); +- +- ++ float timesize(GetTimeSize()); + if (pData) + { ++ m_frameSizes.push_back(iSize); ++ m_frameSizeSum += iSize; ++ + am_private->am_pkt.data = pData; + am_private->am_pkt.data_size = iSize; + +@@ -1875,21 +1875,23 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + loop++; + } + if (loop == 100) +- { + // Decoder got stuck; Reset + Reset(); +- } + +- if (iSize*2 > m_max_frame_size) +- m_max_frame_size = iSize*2; ++ if ((m_state & STATE_PREFILLED) == 0 && timesize >= 1.0) ++ m_state |= STATE_PREFILLED; + } + +- if (DequeueBuffer() == 0) ++ if ((m_state & STATE_PREFILLED) != 0 && timesize > 0.5 && DequeueBuffer() == 0) + rtn |= VC_PICTURE; + ++ if (((rtn & VC_PICTURE) == 0 && timesize < 2.0) || timesize < 1.0) ++ rtn |= VC_BUFFER; ++ ++ + if (g_advancedSettings.CanLogComponent(LOGVIDEO)) + { +- CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.4lf[%llX], pts_in: %0.4lf[%llX], adj:%llu, ptsOut:%0.4f, amlpts:%d, idx:%u", ++ CLog::Log(LOGDEBUG, "CAMLCodec::Decode: ret: %d, sz: %u, dts_in: %0.4lf[%llX], pts_in: %0.4lf[%llX], adj:%llu, ptsOut:%0.4f, amlpts:%d, idx:%u, timesize:%0.4f", + rtn, + static_cast(iSize), + dts / DVD_TIME_BASE, am_private->am_pkt.avdts, +@@ -1897,7 +1899,8 @@ int CAMLCodec::Decode(uint8_t *pData, size_t iSize, double dts, double pts) + m_start_adj, + static_cast(m_cur_pts)/PTS_FREQ, + static_cast(m_cur_pts), +- m_bufferIndex ++ m_bufferIndex, ++ timesize + ); + } + +@@ -1992,6 +1995,23 @@ int CAMLCodec::DequeueBuffer() + return 0; + } + ++float CAMLCodec::GetTimeSize() ++{ ++ struct buf_status bs; ++ m_dll->codec_get_vbuf_state(&am_private->vcodec, &bs); ++ ++ //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: buf status: s:%d dl:%d fl:%d rp:%u wp:%u",bs.size, bs.data_len, bs.free_len, bs.read_pointer, bs.write_pointer); ++ while (m_frameSizeSum > bs.data_len) ++ { ++ m_frameSizeSum -= m_frameSizes.front(); ++ m_frameSizes.pop_front(); ++ } ++ if (bs.free_len < bs.data_len) ++ return 7.0; ++ ++ return (float)(m_frameSizes.size() * am_private->video_rate) / UNIT_FREQ; ++} ++ + bool CAMLCodec::GetPicture(DVDVideoPicture *pDvdVideoPicture) + { + if (!m_opened) +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +index 04146a0..2885a88 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.h +@@ -73,6 +73,7 @@ class CAMLCodec + std::string GetVfmMap(const std::string &name); + void SetVfmMap(const std::string &name, const std::string &map); + int DequeueBuffer(); ++ float GetTimeSize(); + + DllLibAmCodec *m_dll; + bool m_opened; +@@ -104,6 +105,9 @@ class CAMLCodec + PosixFilePtr m_amlVideoFile; + std::string m_defaultVfmMap; + ++ std::deque m_frameSizes; ++ std::uint32_t m_frameSizeSum; ++ + static long m_pollSync; + static int m_pollDevice; + }; + +From 087c11d45925912921fe1d7434fb4eee50cbf0fd Mon Sep 17 00:00:00 2001 +From: Markus Pfau +Date: Mon, 9 Jan 2017 11:14:31 +0100 +Subject: [PATCH 30/30] disable h/w flv1 / vsync clock for s/w + +--- + .../cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp | 3 +-- + .../DVDCodecs/Video/DVDVideoCodecAmlogic.cpp | 18 +++++++------- + xbmc/video/videosync/VideoSyncAML.cpp | 28 ++++++++++++++++++++-- + 3 files changed, 36 insertions(+), 13 deletions(-) + +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +index db36553..38dcd23 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/AMLCodec.cpp +@@ -1917,7 +1917,6 @@ int CAMLCodec::PollFrame() + return 0; + + struct pollfd codec_poll_fd[1]; +- static unsigned int pc(0); + + codec_poll_fd[0].fd = m_pollDevice; + codec_poll_fd[0].events = POLLOUT; +@@ -2001,7 +2000,7 @@ float CAMLCodec::GetTimeSize() + m_dll->codec_get_vbuf_state(&am_private->vcodec, &bs); + + //CLog::Log(LOGDEBUG, "CAMLCodec::Decode: buf status: s:%d dl:%d fl:%d rp:%u wp:%u",bs.size, bs.data_len, bs.free_len, bs.read_pointer, bs.write_pointer); +- while (m_frameSizeSum > bs.data_len) ++ while (m_frameSizeSum > (unsigned int)bs.data_len) + { + m_frameSizeSum -= m_frameSizes.front(); + m_frameSizes.pop_front(); +diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +index aef4060..da46973 100644 +--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp ++++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecAmlogic.cpp +@@ -44,17 +44,17 @@ typedef struct frame_queue { + CDVDVideoCodecAmlogic::CDVDVideoCodecAmlogic(CProcessInfo &processInfo) : CDVDVideoCodec(processInfo), + m_Codec(NULL), + m_pFormatName("amcodec"), ++ m_opened(false), + m_last_pts(0.0), + m_frame_queue(NULL), + m_queue_depth(0), + m_framerate(0.0), + m_video_rate(0), + m_mpeg2_sequence(NULL), +- m_bitparser(NULL), +- m_bitstream(NULL), +- m_opened(false), + m_drop(false), +- m_has_keyframe(false) ++ m_has_keyframe(false), ++ m_bitparser(NULL), ++ m_bitstream(NULL) + { + pthread_mutex_init(&m_queue_mutex, NULL); + } +@@ -153,9 +153,9 @@ bool CDVDVideoCodecAmlogic::Open(CDVDStreamInfo &hints, CDVDCodecOptions &option + // amcodec can't handle h263 + return false; + break; +- case AV_CODEC_ID_FLV1: +- m_pFormatName = "am-flv1"; +- break; ++// case AV_CODEC_ID_FLV1: ++// m_pFormatName = "am-flv1"; ++// break; + case AV_CODEC_ID_RV10: + case AV_CODEC_ID_RV20: + case AV_CODEC_ID_RV30: +@@ -288,7 +288,7 @@ int CDVDVideoCodecAmlogic::Decode(uint8_t *pData, int iSize, double dts, double + + if (!m_bitstream->HasKeyframe()) + { +- CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for keyframe (bitstream)", __MODULE_NAME__); ++ CLog::Log(LOGDEBUG, "%s::Decode waiting for keyframe (bitstream)", __MODULE_NAME__); + return VC_BUFFER; + } + pData = m_bitstream->GetConvertBuffer(); +@@ -298,7 +298,7 @@ int CDVDVideoCodecAmlogic::Decode(uint8_t *pData, int iSize, double dts, double + { + if (!m_bitparser->HasKeyframe(pData, iSize)) + { +- CLog::Log(LOGDEBUG, "CDVDVideoCodecAmlogic::Decode waiting for keyframe (bitparser)", __MODULE_NAME__); ++ CLog::Log(LOGDEBUG, "%s::Decode waiting for keyframe (bitparser)", __MODULE_NAME__); + return VC_BUFFER; + } + else +diff --git a/xbmc/video/videosync/VideoSyncAML.cpp b/xbmc/video/videosync/VideoSyncAML.cpp +index fb744e2..02c613e 100644 +--- a/xbmc/video/videosync/VideoSyncAML.cpp ++++ b/xbmc/video/videosync/VideoSyncAML.cpp +@@ -30,6 +30,9 @@ + #include "threads/Thread.h" + #include + ++#include ++#include ++ + extern CEvent g_aml_sync_event; + + CVideoSyncAML::CVideoSyncAML(CVideoReferenceClock *clock) +@@ -56,12 +59,33 @@ bool CVideoSyncAML::Setup(PUPDATECLOCK func) + + void CVideoSyncAML::Run(std::atomic& stop) + { ++ // We use the wall clock for timout handling (no AML h/w, startup) ++ std::chrono::time_point now(std::chrono::system_clock::now()); ++ unsigned int waittime (3000 / m_fps); ++ uint64_t numVBlanks (0); ++ + while (!stop && !m_abort) + { +- g_aml_sync_event.WaitMSec(100); ++ int countVSyncs(1); ++ if( !g_aml_sync_event.WaitMSec(waittime)) ++ { ++ std::chrono::milliseconds elapsed(std::chrono::duration_cast(std::chrono::system_clock::now() - now).count()); ++ uint64_t curVBlanks = (m_fps * elapsed.count()) / 1000; ++ int64_t lastVBlankTime((curVBlanks * 1000) / m_fps); ++ if (elapsed.count() > lastVBlankTime) ++ { ++ lastVBlankTime = (++curVBlanks * 1000) / m_fps; ++ std::this_thread::sleep_for(std::chrono::milliseconds(lastVBlankTime - elapsed.count())); ++ } ++ countVSyncs = curVBlanks - numVBlanks; ++ numVBlanks = curVBlanks; ++ } ++ else ++ ++numVBlanks; ++ + uint64_t now = CurrentHostCounter(); + +- UpdateClock(1, now, m_refClock); ++ UpdateClock(countVSyncs, now, m_refClock); + } + } +