29
29
30
30
#include " utils/log.h"
31
31
#include " DVDClock.h"
32
-
32
+ // #include "mfw_gst_ts.h"
33
33
34
34
// #define NO_V4L_RENDERING
35
35
39
39
#define _4CC (c1,c2,c3,c4 ) (((uint32_t )(c4)<<24 )|((uint32_t )(c3)<<16 )|((uint32_t )(c2)<<8 )|(uint32_t )(c1))
40
40
#define Align (ptr,align ) (((unsigned int )ptr + (align) - 1 )/(align)*(align))
41
41
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
+
42
142
/* video device on which the video will be rendered (/dev/video17 => /dev/fb1) */
43
143
const char *CDVDVideoCodecIMX::m_v4lDeviceName = " /dev/video17" ;
44
144
/* 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)
257
357
/* Alloc frame buffers from V4L2 for efficient rendering through V4L streaming */
258
358
struct v4l2_requestbuffers bufReq;
259
359
struct v4l2_format fmt;
260
- struct v4l2_control ctrl;
360
+ // struct v4l2_control ctrl;
261
361
int ret, i;
262
362
int width, height;
263
363
int ySize, cSize;
@@ -411,7 +511,7 @@ bool CDVDVideoCodecIMX::VpuAllocFrameBuffers(void)
411
511
412
512
bool CDVDVideoCodecIMX::VpuPushFrame (VpuFrameBuffer *frameBuffer)
413
513
{
414
- int i, ret, type ;
514
+ int i;
415
515
416
516
/* Find Frame */
417
517
for (i=0 ; i<m_vpuFrameBufferNum; i++)
@@ -438,6 +538,9 @@ bool CDVDVideoCodecIMX::VpuPushFrame(VpuFrameBuffer *frameBuffer)
438
538
439
539
void CDVDVideoCodecIMX::RenderFrame (void )
440
540
{
541
+ /* Warning : called from renderer thread
542
+ * Especially do not call any VPU funcrions as they are not thread safe
543
+ */
441
544
struct v4l2_buffer * buffer;
442
545
int ret, type;
443
546
@@ -447,7 +550,9 @@ void CDVDVideoCodecIMX::RenderFrame(void)
447
550
__FUNCTION__);
448
551
return ;
449
552
}
450
-
553
+ /* std::queue is not threadsafe -
554
+ * FIXME add lock (contention should not happen but still..)
555
+ */
451
556
buffer = m_outputFrames.front ();
452
557
m_outputFrames.pop ();
453
558
buffer->timestamp .tv_sec = 0 ;
@@ -548,6 +653,8 @@ CDVDVideoCodecIMX::CDVDVideoCodecIMX()
548
653
m_vpuFrameBufferNum = 0 ;
549
654
m_extraMem.nSize = 0 ;
550
655
m_streamon = false ;
656
+ m_ts = CDTSManager ();
657
+ m_tsSyncRequired = true ;
551
658
}
552
659
553
660
CDVDVideoCodecIMX::~CDVDVideoCodecIMX ()
@@ -564,6 +671,7 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
564
671
}
565
672
566
673
m_nframes = 0 ;
674
+ m_displayedFrames = 0 ;
567
675
m_hints = hints;
568
676
CLog::Log (LOGNOTICE, " Let's decode with iMX VPU\n " );
569
677
@@ -653,6 +761,9 @@ bool CDVDVideoCodecIMX::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
653
761
}
654
762
655
763
InitFB ();
764
+
765
+ // m_tsm = createTSManager (1024);
766
+ // setTSManagerFrameRate(m_tsm, m_hints.fpsrate, m_hints.fpsscale);
656
767
return VpuOpen ();
657
768
}
658
769
@@ -732,13 +843,19 @@ void CDVDVideoCodecIMX::Dispose(void)
732
843
CLog::Log (LOGERROR, " %s - VPU unload failed with error code %d.\n " , __FUNCTION__, ret);
733
844
}
734
845
846
+ /* if (m_tsm != NULL)
847
+ {
848
+ destroyTSManager(m_tsm);
849
+ m_tsm = NULL;
850
+ }*/
851
+
735
852
RestoreFB ();
736
853
return ;
737
854
}
738
855
739
856
int CDVDVideoCodecIMX::Decode (BYTE *pData, int iSize, double dts, double pts)
740
857
{
741
- // VpuDecFrameLengthInfo frameLengthInfo;
858
+ VpuDecFrameLengthInfo frameLengthInfo;
742
859
VpuBufferNode inData;
743
860
VpuDecRetCode ret;
744
861
VpuDecOutFrameInfo frameInfo;
@@ -747,14 +864,34 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
747
864
int demuxer_bytes = iSize;
748
865
uint8_t *demuxer_content = pData;
749
866
bool bitstream_convered = false ;
867
+
868
+
750
869
751
870
if (!m_vpuHandle)
752
871
return VC_ERROR;
753
872
873
+ // CLog::Log(LOGNOTICE, "%s - %x - %d - %f %f \n", __FUNCTION__, pData, iSize, dts, pts);
874
+
754
875
while (VpuDeQueueFrame ());
755
876
756
877
if (pData && iSize)
757
878
{
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
+
758
895
if (m_convert_bitstream)
759
896
{
760
897
// convert demuxer packet from bitstream to bytestream (AnnexB)
@@ -827,14 +964,15 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
827
964
}// VPU_DEC_INIT_OK
828
965
829
966
if (decRet & VPU_DEC_ONE_FRM_CONSUMED)
830
- {/*
967
+ {
831
968
ret = VPU_DecGetConsumedFrameInfo (m_vpuHandle, &frameLengthInfo);
832
969
if (ret != VPU_DEC_RET_SUCCESS)
833
970
{
834
971
CLog::Log (LOGERROR, " %s - VPU error retireving info about consummed frame (%d).\n " , __FUNCTION__, ret);
835
972
}
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);
838
976
}// VPU_DEC_ONE_FRM_CONSUMED
839
977
840
978
if (decRet & VPU_DEC_OUTPUT_DIS)
@@ -844,34 +982,38 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
844
982
if (ret != VPU_DEC_RET_SUCCESS)
845
983
{
846
984
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++;
848
991
}
849
- VpuPushFrame (frameInfo.pDisplayFrameBuf );
850
- retSatus |= VC_PICTURE;
851
- } // VPU_DEC_OUTPUT_DIS
992
+ } // VPU_DEC_OUTPUT_DIS
852
993
853
994
if (decRet & VPU_DEC_OUTPUT_MOSAIC_DIS)
854
995
{
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__);
856
998
}
857
999
if (decRet & VPU_DEC_OUTPUT_REPEAT)
858
1000
{
1001
+ // TSManagerSend(m_tsm);
859
1002
CLog::Log (LOGDEBUG, " %s - Frame repeat.\n " , __FUNCTION__);
860
- /* FIXME TS*/
861
1003
}
862
1004
if (decRet & VPU_DEC_OUTPUT_DROPPED)
863
1005
{
1006
+ // TSManagerSend(m_tsm);
864
1007
CLog::Log (LOGDEBUG, " %s - Frame dropped.\n " , __FUNCTION__);
865
- /* FIXME TS*/
866
1008
}
867
1009
if (decRet & VPU_DEC_NO_ENOUGH_BUF)
868
1010
{
869
1011
CLog::Log (LOGERROR, " %s - No frame buffer available. Queued frame : %d.\n " , __FUNCTION__, m_outputFrames.size ());
870
1012
}
871
1013
if (decRet & VPU_DEC_SKIP)
872
1014
{
1015
+ // TSManagerSend(m_tsm);
873
1016
CLog::Log (LOGDEBUG, " %s - Frame skipped.\n " , __FUNCTION__);
874
- /* FIXME TS*/
875
1017
}
876
1018
if (decRet & VPU_DEC_FLUSH)
877
1019
{
@@ -913,9 +1055,9 @@ int CDVDVideoCodecIMX::Decode(BYTE *pData, int iSize, double dts, double pts)
913
1055
*/
914
1056
if (pData == NULL )
915
1057
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);
917
1059
}
918
-
1060
+
919
1061
if (m_outputFrames.size () > 0 )
920
1062
{
921
1063
retSatus |= VC_PICTURE;
@@ -940,23 +1082,41 @@ void CDVDVideoCodecIMX::Reset()
940
1082
*/
941
1083
}
942
1084
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
+
943
1095
bool CDVDVideoCodecIMX::GetPicture (DVDVideoPicture* pDvdVideoPicture)
944
1096
{
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;
945
1110
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;
951
1111
pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
952
- pDvdVideoPicture->iFlags = 0 ;
1112
+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED ;
953
1113
pDvdVideoPicture->iWidth = m_initInfo.nPicWidth ;
954
1114
pDvdVideoPicture->iHeight = m_initInfo.nPicHeight ;
955
1115
pDvdVideoPicture->iDisplayWidth = m_initInfo.nPicWidth ;
956
1116
pDvdVideoPicture->iDisplayHeight = m_initInfo.nPicHeight ;
957
1117
pDvdVideoPicture->format = RENDER_FMT_IMX;
958
1118
pDvdVideoPicture->imx = this ;
959
- return true ;
1119
+ return true ;
960
1120
}
961
1121
962
1122
@@ -973,9 +1133,14 @@ void CDVDVideoCodecIMX::SetDropState(bool bDrop)
973
1133
{
974
1134
config = VPU_DEC_CONF_SKIPMODE;
975
1135
if (bDrop)
1136
+ {
976
1137
param = VPU_DEC_SKIPALL;
977
- else
1138
+ }
1139
+ else
1140
+ {
978
1141
param = VPU_DEC_SKIPNONE;
1142
+ m_tsSyncRequired = true ;
1143
+ }
979
1144
ret = VPU_DecConfig (m_vpuHandle, config, ¶m);
980
1145
if (ret != VPU_DEC_RET_SUCCESS)
981
1146
CLog::Log (LOGERROR, " %s - Error while setting Skip mode : %d.\n " , __FUNCTION__, ret);
0 commit comments