Skip to content

Commit 50f228b

Browse files
committed
First trivial timestamp (pts) support
1 parent 53ebff0 commit 50f228b

File tree

2 files changed

+230
-29
lines changed

2 files changed

+230
-29
lines changed

xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecIMX.cpp

Lines changed: 191 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
#include "utils/log.h"
3131
#include "DVDClock.h"
32-
32+
//#include "mfw_gst_ts.h"
3333

3434
//#define NO_V4L_RENDERING
3535

@@ -39,6 +39,106 @@
3939
#define _4CC(c1,c2,c3,c4) (((uint32_t)(c4)<<24)|((uint32_t)(c3)<<16)|((uint32_t)(c2)<<8)|(uint32_t)(c1))
4040
#define Align(ptr,align) (((unsigned int)ptr + (align) - 1)/(align)*(align))
4141

42+
43+
CDTSManager::CDTSManager()
44+
{
45+
m_current = 0;
46+
Flush();
47+
}
48+
49+
CDTSManager::~CDTSManager()
50+
{
51+
}
52+
53+
void CDTSManager::Flush()
54+
{
55+
int i;
56+
for (i = 0; i < maxEntries; i++)
57+
{
58+
m_entries[i].used = false;
59+
}
60+
}
61+
62+
int CDTSManager::FindFree()
63+
{
64+
int i;
65+
unsigned int oldest = 0;
66+
int oldestID = -1;
67+
68+
for (i = 0; i < maxEntries; i++)
69+
{
70+
if (!m_entries[i].used)
71+
return i;
72+
if ((m_current - m_entries[i].id) > oldest)
73+
{
74+
oldest = (m_current - m_entries[i].id);
75+
oldestID = i;
76+
}
77+
}
78+
CLog::Log(LOGNOTICE, "%s - flushing pts %f which is thes oldest\n", __FUNCTION__, m_entries[i].pts);
79+
return oldestID;
80+
}
81+
82+
void CDTSManager::Register(double pts, int size)
83+
{
84+
int i;
85+
i = FindFree();
86+
m_entries[i].id = m_current;
87+
m_entries[i].size = size;
88+
m_entries[i].pts = pts;
89+
m_entries[i].key = NULL;
90+
m_entries[i].used = true;
91+
// CLog::Log(LOGNOTICE, "%s - Register pts %f size %d at %d\n", __FUNCTION__,pts, size, i);
92+
m_current++;
93+
}
94+
95+
bool CDTSManager::Associate(int size, void *key)
96+
{
97+
int i;
98+
unsigned int oldest = 0;
99+
int oldestID = -1;
100+
101+
/* If there are several candidates, the oldest is used */
102+
for (i = 0; i < maxEntries; i++)
103+
{
104+
if ((m_entries[i].used) && (m_entries[i].key == NULL))
105+
{
106+
if (((size - 60) <= m_entries[i].size) && (m_entries[i].size <= (size + 60)))
107+
{
108+
if ((m_current - m_entries[i].id) > oldest)
109+
{
110+
oldest = m_current - m_entries[i].id;
111+
oldestID = i;
112+
}
113+
}
114+
}
115+
}
116+
117+
// CLog::Log(LOGNOTICE, "%s - size %d key %x idx %d\n", __FUNCTION__,size, key, oldestID);
118+
if (oldestID == -1)
119+
return false;
120+
121+
m_entries[oldestID].key = key;
122+
return true;
123+
}
124+
125+
double CDTSManager::Get(void *key)
126+
{
127+
int i;
128+
double pts;
129+
// CLog::Log(LOGNOTICE, "%s - searching key %x \n", __FUNCTION__, key);
130+
for (i = 0; i < maxEntries; i++)
131+
{
132+
if ((m_entries[i].used) && (m_entries[i].key == key))
133+
{
134+
pts = m_entries[i].pts;
135+
m_entries[i].used = false;
136+
return pts;
137+
}
138+
}
139+
return DVD_NOPTS_VALUE;
140+
}
141+
42142
/* video device on which the video will be rendered (/dev/video17 => /dev/fb1) */
43143
const char *CDVDVideoCodecIMX::m_v4lDeviceName = "/dev/video17";
44144
/* Experiments show that we need at least one more (+1) V4L buffer than the min value returned by the VPU */
@@ -257,7 +357,7 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void)
257357
/* Alloc frame buffers from V4L2 for efficient rendering through V4L streaming */
258358
struct v4l2_requestbuffers bufReq;
259359
struct v4l2_format fmt;
260-
struct v4l2_control ctrl;
360+
// struct v4l2_control ctrl;
261361
int ret, i;
262362
int width, height;
263363
int ySize, cSize;
@@ -411,7 +511,7 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void)
411511

412512
bool CDVDVideoCodecIMX::VpuPushFrame(VpuFrameBuffer *frameBuffer)
413513
{
414-
int i, ret, type;
514+
int i;
415515

416516
/* Find Frame */
417517
for (i=0; i<m_vpuFrameBufferNum; i++)
@@ -438,6 +538,9 @@ bool CDVDVideoCodecIMX::VpuPushFrame(VpuFrameBuffer *frameBuffer)
438538

439539
void CDVDVideoCodecIMX::RenderFrame(void)
440540
{
541+
/* Warning : called from renderer thread
542+
* Especially do not call any VPU funcrions as they are not thread safe
543+
*/
441544
struct v4l2_buffer* buffer;
442545
int ret, type;
443546

@@ -447,7 +550,9 @@ void CDVDVideoCodecIMX::RenderFrame(void)
447550
__FUNCTION__);
448551
return;
449552
}
450-
553+
/* std::queue is not threadsafe -
554+
* FIXME add lock (contention should not happen but still..)
555+
*/
451556
buffer = m_outputFrames.front();
452557
m_outputFrames.pop();
453558
buffer->timestamp.tv_sec = 0;
@@ -548,6 +653,8 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX()
548653
m_vpuFrameBufferNum = 0;
549654
m_extraMem.nSize = 0;
550655
m_streamon = false;
656+
m_ts = CDTSManager();
657+
m_tsSyncRequired = true;
551658
}
552659

553660
CDVDVideoCodecIMX::~CDVDVideoCodecIMX()
@@ -564,6 +671,7 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
564671
}
565672

566673
m_nframes = 0;
674+
m_displayedFrames = 0;
567675
m_hints = hints;
568676
CLog::Log(LOGNOTICE, "Let's decode with iMX VPU\n");
569677

@@ -653,6 +761,9 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
653761
}
654762

655763
InitFB();
764+
765+
//m_tsm = createTSManager (1024);
766+
// setTSManagerFrameRate(m_tsm, m_hints.fpsrate, m_hints.fpsscale);
656767
return VpuOpen();
657768
}
658769

@@ -732,13 +843,19 @@ void CDVDVideoCodecIMX::Dispose(void)
732843
CLog::Log(LOGERROR, "%s - VPU unload failed with error code %d.\n", __FUNCTION__, ret);
733844
}
734845

846+
/* if (m_tsm != NULL)
847+
{
848+
destroyTSManager(m_tsm);
849+
m_tsm = NULL;
850+
}*/
851+
735852
RestoreFB();
736853
return;
737854
}
738855

739856
int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
740857
{
741-
// VpuDecFrameLengthInfo frameLengthInfo;
858+
VpuDecFrameLengthInfo frameLengthInfo;
742859
VpuBufferNode inData;
743860
VpuDecRetCode ret;
744861
VpuDecOutFrameInfo frameInfo;
@@ -747,14 +864,34 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
747864
int demuxer_bytes = iSize;
748865
uint8_t *demuxer_content = pData;
749866
bool bitstream_convered = false;
867+
868+
750869

751870
if (!m_vpuHandle)
752871
return VC_ERROR;
753872

873+
// CLog::Log(LOGNOTICE, "%s - %x - %d - %f %f \n", __FUNCTION__, pData, iSize, dts, pts);
874+
754875
while (VpuDeQueueFrame());
755876

756877
if (pData && iSize)
757878
{
879+
//CLog::Log(LOGDEBUG, "%s - demux size : %d dts : %f - pts : %f\n", __FUNCTION__, iSize, dts, pts);
880+
if (pts != DVD_NOPTS_VALUE)
881+
{
882+
if (m_tsSyncRequired)
883+
{
884+
//Flush();
885+
//resyncTSManager (m_tsm, llrint(pts), MODE_AI /*MODE_FIFO*/);
886+
m_tsSyncRequired = false;
887+
}
888+
//TSManagerReceive2(m_tsm, llrint(pts), iSize);
889+
m_ts.Register(pts, iSize);
890+
} else
891+
{
892+
m_tsSyncRequired = true;
893+
}
894+
758895
if (m_convert_bitstream)
759896
{
760897
// convert demuxer packet from bitstream to bytestream (AnnexB)
@@ -827,14 +964,15 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
827964
}//VPU_DEC_INIT_OK
828965

829966
if (decRet & VPU_DEC_ONE_FRM_CONSUMED)
830-
{/*
967+
{
831968
ret = VPU_DecGetConsumedFrameInfo(m_vpuHandle, &frameLengthInfo);
832969
if (ret != VPU_DEC_RET_SUCCESS)
833970
{
834971
CLog::Log(LOGERROR, "%s - VPU error retireving info about consummed frame (%d).\n", __FUNCTION__, ret);
835972
}
836-
*/
837-
/* FIXME TS */
973+
//TSManagerValid2(m_tsm, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame);
974+
m_ts.Associate(frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame);
975+
//CLog::Log(LOGDEBUG, "%s - size : %d - key consummed : %x\n", __FUNCTION__, frameLengthInfo.nFrameLength + frameLengthInfo.nStuffLength, frameLengthInfo.pFrame);
838976
}//VPU_DEC_ONE_FRM_CONSUMED
839977

840978
if (decRet & VPU_DEC_OUTPUT_DIS)
@@ -844,34 +982,38 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
844982
if(ret != VPU_DEC_RET_SUCCESS)
845983
{
846984
CLog::Log(LOGERROR, "%s - VPU Cannot get output frame(%d).\n", __FUNCTION__, ret);
847-
return VC_ERROR;
985+
goto out_error;
986+
}
987+
if (VpuPushFrame(frameInfo.pDisplayFrameBuf))
988+
{
989+
retSatus |= VC_PICTURE;
990+
m_displayedFrames++;
848991
}
849-
VpuPushFrame(frameInfo.pDisplayFrameBuf);
850-
retSatus |= VC_PICTURE;
851-
} //VPU_DEC_OUTPUT_DIS
992+
} //VPU_DEC_OUTPUT_DIS
852993

853994
if (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS)
854995
{
855-
CLog::Log(LOGERROR, "%s - Unexpected OUTPUT_MOSAIC_DIS.\n", __FUNCTION__);
996+
//TSManagerSend(m_tsm);
997+
CLog::Log(LOGERROR, "%s - Unexpected OUTPUT_MOSAIC_DIS.\n", __FUNCTION__);
856998
}
857999
if (decRet & VPU_DEC_OUTPUT_REPEAT)
8581000
{
1001+
//TSManagerSend(m_tsm);
8591002
CLog::Log(LOGDEBUG, "%s - Frame repeat.\n", __FUNCTION__);
860-
/* FIXME TS*/
8611003
}
8621004
if (decRet & VPU_DEC_OUTPUT_DROPPED)
8631005
{
1006+
//TSManagerSend(m_tsm);
8641007
CLog::Log(LOGDEBUG, "%s - Frame dropped.\n", __FUNCTION__);
865-
/* FIXME TS*/
8661008
}
8671009
if (decRet & VPU_DEC_NO_ENOUGH_BUF)
8681010
{
8691011
CLog::Log(LOGERROR, "%s - No frame buffer available. Queued frame : %d.\n", __FUNCTION__, m_outputFrames.size());
8701012
}
8711013
if (decRet & VPU_DEC_SKIP)
8721014
{
1015+
//TSManagerSend(m_tsm);
8731016
CLog::Log(LOGDEBUG, "%s - Frame skipped.\n", __FUNCTION__);
874-
/* FIXME TS*/
8751017
}
8761018
if (decRet & VPU_DEC_FLUSH)
8771019
{
@@ -913,9 +1055,9 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
9131055
*/
9141056
if (pData == NULL)
9151057
usleep(2000);
916-
CLog::Log(LOGNOTICE, "%s - dont want more data as no buffers are available %d %d in : %x - %d - %f %f \n", __FUNCTION__, GetAvailableBufferNb(), m_outputFrames.size(), pData, iSize, dts, pts);
1058+
CLog::Log(LOGNOTICE, "%s - Don't want more data as no buffers are available %d %d in : %x - %d - %f %f \n", __FUNCTION__, GetAvailableBufferNb(), m_outputFrames.size(), pData, iSize, dts, pts);
9171059
}
918-
1060+
9191061
if (m_outputFrames.size() > 0)
9201062
{
9211063
retSatus |= VC_PICTURE;
@@ -940,23 +1082,41 @@ void CDVDVideoCodecIMX::Reset()
9401082
*/
9411083
}
9421084

1085+
static double GetPlayerPtsSeconds()
1086+
{
1087+
double clock_pts = 0.0;
1088+
CDVDClock *playerclock = CDVDClock::GetMasterClock();
1089+
if (playerclock)
1090+
clock_pts = playerclock->GetClock() / DVD_TIME_BASE;
1091+
1092+
return clock_pts;
1093+
}
1094+
9431095
bool CDVDVideoCodecIMX::GetPicture(DVDVideoPicture* pDvdVideoPicture)
9441096
{
1097+
//TSM_TIMESTAMP ts;
1098+
double currentPlayerPts, pts;
1099+
1100+
if (m_outputFrames.size() == 0)
1101+
return false;
1102+
1103+
currentPlayerPts = GetPlayerPtsSeconds() * (double)DVD_TIME_BASE;
1104+
pts = m_ts.Get(m_outputBuffers[m_outputFrames.front()->index]);
1105+
//CLog::Log(LOGNOTICE, "%s - current pts %f - player : %f\n", __FUNCTION__, pts, currentPlayerPts);
1106+
if (currentPlayerPts > pts)
1107+
pDvdVideoPicture->pts = currentPlayerPts + (1000000.0 * m_hints.fpsscale) / m_hints.fpsrate;
1108+
else
1109+
pDvdVideoPicture->pts = pts;
9451110

946-
/* FIXME TODO :
947-
- Regarding pts computation (integrate fsl TSManager library used by gstreamer)
948-
- Handle V4L in the renderer
949-
*/
950-
pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
9511111
pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
952-
pDvdVideoPicture->iFlags = 0;
1112+
pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
9531113
pDvdVideoPicture->iWidth = m_initInfo.nPicWidth;
9541114
pDvdVideoPicture->iHeight = m_initInfo.nPicHeight;
9551115
pDvdVideoPicture->iDisplayWidth = m_initInfo.nPicWidth;
9561116
pDvdVideoPicture->iDisplayHeight = m_initInfo.nPicHeight;
9571117
pDvdVideoPicture->format = RENDER_FMT_IMX;
9581118
pDvdVideoPicture->imx = this;
959-
return true;
1119+
return true;
9601120
}
9611121

9621122

@@ -973,9 +1133,14 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop)
9731133
{
9741134
config = VPU_DEC_CONF_SKIPMODE;
9751135
if (bDrop)
1136+
{
9761137
param = VPU_DEC_SKIPALL;
977-
else
1138+
}
1139+
else
1140+
{
9781141
param = VPU_DEC_SKIPNONE;
1142+
m_tsSyncRequired = true;
1143+
}
9791144
ret = VPU_DecConfig(m_vpuHandle, config, &param);
9801145
if (ret != VPU_DEC_RET_SUCCESS)
9811146
CLog::Log(LOGERROR, "%s - Error while setting Skip mode : %d.\n", __FUNCTION__, ret);

0 commit comments

Comments
 (0)