2 * Copyright (C) 2005-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
9 #include "VideoPlayerSubtitle.h"
11 #include "DVDCodecs/DVDFactoryCodec.h"
12 #include "DVDCodecs/Overlay/DVDOverlay.h"
13 #include "DVDCodecs/Overlay/DVDOverlayCodec.h"
14 #include "DVDCodecs/Overlay/DVDOverlaySpu.h"
15 #include "DVDSubtitles/DVDSubtitleParser.h"
16 #include "cores/VideoPlayer/Interface/DemuxPacket.h"
17 #include "cores/VideoPlayer/Interface/TimingConstants.h"
18 #include "utils/log.h"
22 CVideoPlayerSubtitle::CVideoPlayerSubtitle(CDVDOverlayContainer
* pOverlayContainer
, CProcessInfo
&processInfo
)
23 : IDVDStreamPlayer(processInfo
)
25 m_pOverlayContainer
= pOverlayContainer
;
26 m_lastPts
= DVD_NOPTS_VALUE
;
29 CVideoPlayerSubtitle::~CVideoPlayerSubtitle()
35 void CVideoPlayerSubtitle::Flush()
37 SendMessage(std::make_shared
<CDVDMsg
>(CDVDMsg::GENERAL_FLUSH
), 0);
40 void CVideoPlayerSubtitle::SendMessage(std::shared_ptr
<CDVDMsg
> pMsg
, int priority
)
42 std::unique_lock
<CCriticalSection
> lock(m_section
);
44 if (pMsg
->IsType(CDVDMsg::DEMUXER_PACKET
))
46 auto pMsgDemuxerPacket
= std::static_pointer_cast
<CDVDMsgDemuxerPacket
>(pMsg
);
47 DemuxPacket
* pPacket
= pMsgDemuxerPacket
->GetPacket();
51 OverlayMessage result
= m_pOverlayCodec
->Decode(pPacket
);
53 if (result
== OverlayMessage::OC_OVERLAY
)
55 std::shared_ptr
<CDVDOverlay
> overlay
;
57 while ((overlay
= m_pOverlayCodec
->GetOverlay()))
59 m_pOverlayContainer
->ProcessAndAddOverlayIfValid(overlay
);
63 else if (m_streaminfo
.codec
== AV_CODEC_ID_DVD_SUBTITLE
)
65 std::shared_ptr
<CDVDOverlaySpu
> pSPUInfo
=
66 m_dvdspus
.AddData(pPacket
->pData
, pPacket
->iSize
, pPacket
->pts
);
69 CLog::Log(LOGDEBUG
, "CVideoPlayer::ProcessSubData: Got complete SPU packet");
70 m_pOverlayContainer
->ProcessAndAddOverlayIfValid(pSPUInfo
);
75 else if( pMsg
->IsType(CDVDMsg::SUBTITLE_CLUTCHANGE
) )
77 auto pData
= std::static_pointer_cast
<CDVDMsgSubtitleClutChange
>(pMsg
);
78 for (int i
= 0; i
< 16; i
++)
80 uint8_t* color
= m_dvdspus
.m_clut
[i
];
81 uint8_t* t
= (uint8_t*)pData
->m_data
[i
];
83 // pData->m_data[i] points to an uint32_t
84 // Byte swapping is needed between big and little endian systems
85 #ifdef WORDS_BIGENDIAN
87 color
[1] = t
[2]; // Cr
88 color
[2] = t
[3]; // Cb
91 color
[1] = t
[0]; // Cr
92 color
[2] = t
[1]; // Cb
95 m_dvdspus
.m_bHasClut
= true;
97 else if( pMsg
->IsType(CDVDMsg::GENERAL_FLUSH
)
98 || pMsg
->IsType(CDVDMsg::GENERAL_RESET
) )
101 if (m_pSubtitleFileParser
)
102 m_pSubtitleFileParser
->Reset();
105 m_pOverlayCodec
->Flush();
107 /* We must flush active overlays on flush or if we have a file
108 * parser since it will re-populate active items. */
109 if (pMsg
->IsType(CDVDMsg::GENERAL_FLUSH
) || m_pSubtitleFileParser
)
110 m_pOverlayContainer
->Flush();
112 m_lastPts
= DVD_NOPTS_VALUE
;
116 bool CVideoPlayerSubtitle::OpenStream(CDVDStreamInfo
&hints
, std::string
&filename
)
118 std::unique_lock
<CCriticalSection
> lock(m_section
);
121 m_streaminfo
= hints
;
123 // okey check if this is a filesubtitle
124 if(filename
.size() && filename
!= "dvd" )
126 m_pSubtitleFileParser
.reset(CDVDFactorySubtitle::CreateParser(filename
));
127 if (!m_pSubtitleFileParser
)
129 CLog::Log(LOGERROR
, "{} - Unable to create subtitle parser", __FUNCTION__
);
134 CLog::Log(LOGDEBUG
, "Created subtitles parser: {}", m_pSubtitleFileParser
->GetName());
136 if (!m_pSubtitleFileParser
->Open(hints
))
138 CLog::Log(LOGERROR
, "{} - Unable to init subtitle parser", __FUNCTION__
);
142 m_pSubtitleFileParser
->Reset();
146 // dvd's use special subtitle decoder
147 if(hints
.codec
== AV_CODEC_ID_DVD_SUBTITLE
&& filename
== "dvd")
150 m_pOverlayCodec
= CDVDFactoryCodec::CreateOverlayCodec(hints
);
153 CLog::Log(LOGDEBUG
, "Created subtitles overlay codec: {}", m_pOverlayCodec
->GetName());
157 CLog::Log(LOGERROR
, "{} - Unable to init overlay codec", __FUNCTION__
);
161 void CVideoPlayerSubtitle::CloseStream(bool bWaitForBuffers
)
163 std::unique_lock
<CCriticalSection
> lock(m_section
);
165 m_pSubtitleFileParser
.reset();
166 m_pOverlayCodec
.reset();
168 m_dvdspus
.FlushCurrentPacket();
170 if (!bWaitForBuffers
)
171 m_pOverlayContainer
->Clear();
174 void CVideoPlayerSubtitle::Process(double pts
, double offset
)
176 std::unique_lock
<CCriticalSection
> lock(m_section
);
178 if (m_pSubtitleFileParser
)
180 if(pts
== DVD_NOPTS_VALUE
)
183 if (pts
+ DVD_SEC_TO_TIME(1) < m_lastPts
)
185 m_pOverlayContainer
->Clear();
186 m_pSubtitleFileParser
->Reset();
189 if(m_pOverlayContainer
->GetSize() >= 5)
192 std::shared_ptr
<CDVDOverlay
> pOverlay
= m_pSubtitleFileParser
->Parse(pts
);
193 // add all overlays which fit the pts
196 pOverlay
->iPTSStartTime
-= offset
;
197 if(pOverlay
->iPTSStopTime
!= 0.0)
198 pOverlay
->iPTSStopTime
-= offset
;
200 m_pOverlayContainer
->ProcessAndAddOverlayIfValid(pOverlay
);
201 pOverlay
= m_pSubtitleFileParser
->Parse(pts
);
208 bool CVideoPlayerSubtitle::AcceptsData() const
210 // FIXME : This may still be causing problems + magic number :(
211 return m_pOverlayContainer
->GetSize() < 5;