Skip to content

Commit

Permalink
[VideoPlayer] ssif remux
Browse files Browse the repository at this point in the history
  • Loading branch information
Anton Fedchin authored and popcornmix committed Jan 31, 2016
1 parent e4d37ae commit ce5d853
Show file tree
Hide file tree
Showing 8 changed files with 268 additions and 8 deletions.
2 changes: 2 additions & 0 deletions project/VS2010Express/XBMC.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@
<ClCompile Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxCC.cpp" />
<ClCompile Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxCDDA.cpp" />
<ClCompile Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxPVRClient.cpp" />
<ClCompile Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxStreamSSIF.cpp" />
<ClCompile Include="..\..\xbmc\cores\VideoPlayer\DVDInputStreams\DVDInputStreamBluray.cpp" />
<ClCompile Include="..\..\xbmc\cores\VideoPlayer\DVDInputStreams\DVDInputStreamPVRManager.cpp" />
<ClCompile Include="..\..\xbmc\cores\FFmpeg.cpp" />
Expand Down Expand Up @@ -950,6 +951,7 @@
<ClInclude Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxCC.h" />
<ClInclude Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxCDDA.h" />
<ClInclude Include="..\..\xbmc\cores\FFmpeg.h" />
<ClInclude Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxStreamSSIF.h" />
<ClInclude Include="..\..\xbmc\cores\VideoPlayer\VideoRenderers\BaseRenderer.h" />
<ClInclude Include="..\..\xbmc\cores\VideoPlayer\VideoRenderers\HwDecRender\DXVAHD.h" />
<ClInclude Include="..\..\xbmc\cores\VideoPlayer\VideoRenderers\OverlayRenderer.h" />
Expand Down
6 changes: 6 additions & 0 deletions project/VS2010Express/XBMC.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -3223,6 +3223,9 @@
<Filter>filesystem\VideoDatabaseDirectory</Filter>
</ClCompile>
<ClCompile Include="..\..\xbmc\InfoScanner.cpp" />
<ClCompile Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxStreamSSIF.cpp">
<Filter>cores\VideoPlayer\DVDDemuxers</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\xbmc\win32\pch.h">
Expand Down Expand Up @@ -6245,6 +6248,9 @@
<Filter>filesystem\VideoDatabaseDirectory</Filter>
</ClInclude>
<ClInclude Include="..\..\xbmc\InfoScanner.h" />
<ClInclude Include="..\..\xbmc\cores\VideoPlayer\DVDDemuxers\DVDDemuxStreamSSIF.h">
<Filter>cores\VideoPlayer\DVDDemuxers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\..\xbmc\win32\XBMC_PC.rc">
Expand Down
48 changes: 41 additions & 7 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux()
m_currentPts = DVD_NOPTS_VALUE;
m_bMatroska = false;
m_bAVI = false;
m_pSSIF = nullptr;
m_speed = DVD_PLAYSPEED_NORMAL;
m_program = UINT_MAX;
m_pkt.result = -1;
Expand Down Expand Up @@ -499,7 +500,7 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput, bool streaminfo, bool filein
if (m_checkvideo)
{
// make sure we start video with an i-frame
//ResetVideoStreams();
ResetVideoStreams();
}
}
else
Expand Down Expand Up @@ -536,6 +537,8 @@ void CDVDDemuxFFmpeg::Dispose()
m_pkt.result = -1;
av_free_packet(&m_pkt.pkt);

SAFE_DELETE(m_pSSIF);

if (m_pFormatContext)
{
for (unsigned int i = 0; i < m_pFormatContext->nb_streams; i++)
Expand Down Expand Up @@ -583,6 +586,9 @@ void CDVDDemuxFFmpeg::Flush()

m_pkt.result = -1;
av_free_packet(&m_pkt.pkt);

if (m_pSSIF)
m_pSSIF->Flush();
}

void CDVDDemuxFFmpeg::Abort()
Expand Down Expand Up @@ -729,7 +735,9 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
{
Flush();
}
else if (IsProgramChange())
// libavformat is confused by the interleaved SSIF.
// Disable program management for those
else if (!m_pSSIF && IsProgramChange())
{
// update streams
CreateStreams(m_program);
Expand All @@ -756,6 +764,9 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()

m_pkt.result = -1;
av_free_packet(&m_pkt.pkt);

if (m_pSSIF)
m_pSSIF->Flush();
}
else
{
Expand All @@ -765,7 +776,9 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()

if (IsVideoReady())
{
if (m_program != UINT_MAX)
// libavformat is confused by the interleaved SSIF.
// Disable program management for those
if (!m_pSSIF && m_program != UINT_MAX )
{
/* check so packet belongs to selected program */
for (unsigned int i = 0; i < m_pFormatContext->programs[m_program]->nb_stream_indexes; i++)
Expand Down Expand Up @@ -906,6 +919,14 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
stream = AddStream(pPacket->iStreamId);
}
}
if (stream && m_pSSIF)
{
if (stream->type == STREAM_VIDEO ||
stream->type == STREAM_DATA)
pPacket = m_pSSIF->AddPacket(pPacket);
if (stream->type == STREAM_DATA && pPacket->iSize)
stream = GetStreamInternal(pPacket->iStreamId);
}
if (!stream)
{
CLog::Log(LOGERROR, "CDVDDemuxFFmpeg::AddStream - internal error, stream is null");
Expand All @@ -929,6 +950,9 @@ bool CDVDDemuxFFmpeg::SeekTime(int time, bool backwords, double *startpts)
m_pkt.result = -1;
av_free_packet(&m_pkt.pkt);

if (m_pSSIF)
m_pSSIF->Flush();

CDVDInputStream::ISeekTime* ist = dynamic_cast<CDVDInputStream::ISeekTime*>(m_pInput);
if (ist)
{
Expand Down Expand Up @@ -996,6 +1020,9 @@ bool CDVDDemuxFFmpeg::SeekByte(int64_t pos)
m_pkt.result = -1;
av_free_packet(&m_pkt.pkt);

if (m_pSSIF)
m_pSSIF->Flush();

return (ret >= 0);
}

Expand Down Expand Up @@ -1184,11 +1211,13 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId)
{
if (pStream->codec->codec_id == AV_CODEC_ID_H264_MVC)
{
// ignore MVC extension streams, they are handled specially
m_pSSIF = new CDVDDemuxStreamSSIF();
m_pSSIF->SetMVCStreamId(iId);

stream = new CDemuxStream();
stream->type = STREAM_DATA;
stream->disabled = true;
pStream->need_parsing = AVSTREAM_PARSE_NONE;
pStream->codec->codec_type = AVMEDIA_TYPE_DATA;
break;
}
CDemuxStreamVideoFFmpeg* st = new CDemuxStreamVideoFFmpeg(this, pStream);
Expand Down Expand Up @@ -1286,7 +1315,11 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId)
{
if (h264_is_annexb(m_pFormatContext->iformat->name, pStream))
{
// TODO
if (m_pSSIF)
{
m_pSSIF->SetH264StreamId(iId);
pStream->codec->codec_tag = MKTAG('M', 'V', 'C', ' ');
}
}
else
{
Expand Down Expand Up @@ -1402,7 +1435,7 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId)
if (langTag)
strncpy(stream->language, langTag->value, 3);

if( stream->type != STREAM_NONE && pStream->codec->extradata && pStream->codec->extradata_size > 0 )
if (stream->type != STREAM_NONE && pStream->codec->extradata && pStream->codec->extradata_size > 0)
{
stream->ExtraSize = pStream->codec->extradata_size;
stream->ExtraData = new uint8_t[pStream->codec->extradata_size];
Expand Down Expand Up @@ -1825,6 +1858,7 @@ void CDVDDemuxFFmpeg::ResetVideoStreams()
if (st->codec->extradata)
av_free(st->codec->extradata);
st->codec->extradata = NULL;
st->codec->extradata_size = 0;
st->codec->width = 0;
}
}
Expand Down
2 changes: 2 additions & 0 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/

#include "DVDDemux.h"
#include "DVDDemuxStreamSSIF.h"
#include "threads/CriticalSection.h"
#include "threads/SystemClock.h"
#include <map>
Expand Down Expand Up @@ -156,6 +157,7 @@ class CDVDDemuxFFmpeg : public CDVDDemux
double m_currentPts; // used for stream length estimation
bool m_bMatroska;
bool m_bAVI;
CDVDDemuxStreamSSIF* m_pSSIF;
int m_speed;
unsigned m_program;
XbmcThreads::EndTime m_timeout;
Expand Down
166 changes: 166 additions & 0 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxStreamSSIF.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* Copyright (C) 2005-2013 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
* <http://www.gnu.org/licenses/>.
*
*/

#include "DVDDemuxStreamSSIF.h"
#include "DVDClock.h"
#include "DVDDemuxUtils.h"
#include "utils/log.h"

//#define DEBUG_VERBOSE

DemuxPacket* CDVDDemuxStreamSSIF::AddPacket(DemuxPacket* &srcPkt)
{
if (srcPkt->iStreamId != m_h264StreamId &&
srcPkt->iStreamId != m_mvcStreamId)
return srcPkt;

DemuxPacket* newpkt = NULL;
newpkt = CDVDDemuxUtils::AllocateDemuxPacket(srcPkt->iSize);
newpkt->iSize = srcPkt->iSize;

newpkt->pts = srcPkt->pts;
newpkt->dts = srcPkt->dts;
newpkt->duration = srcPkt->duration;
newpkt->iGroupId = srcPkt->iGroupId;
newpkt->iStreamId = srcPkt->iStreamId;
memcpy(newpkt->pData, srcPkt->pData, srcPkt->iSize);

CDVDDemuxUtils::FreeDemuxPacket(srcPkt);
srcPkt = NULL;

if (newpkt->iStreamId == m_h264StreamId)
m_H264queue.push(newpkt);
else if (newpkt->iStreamId == m_mvcStreamId)
m_MVCqueue.push(newpkt);

return GetMVCPacket();
}

void CDVDDemuxStreamSSIF::Flush()
{
while (!m_H264queue.empty())
{
CDVDDemuxUtils::FreeDemuxPacket(m_H264queue.front());
m_H264queue.pop();
}
while (!m_MVCqueue.empty())
{
CDVDDemuxUtils::FreeDemuxPacket(m_MVCqueue.front());
m_MVCqueue.pop();
}
}

DemuxPacket* CDVDDemuxStreamSSIF::MergePacket(DemuxPacket* &srcPkt, DemuxPacket* &appendPkt)
{
DemuxPacket* newpkt = NULL;
newpkt = CDVDDemuxUtils::AllocateDemuxPacket(srcPkt->iSize + appendPkt->iSize);
newpkt->iSize = srcPkt->iSize + appendPkt->iSize;

newpkt->pts = srcPkt->pts;
newpkt->dts = srcPkt->dts;
newpkt->duration = srcPkt->duration;
newpkt->iGroupId = srcPkt->iGroupId;
newpkt->iStreamId = srcPkt->iStreamId;
memcpy(newpkt->pData, srcPkt->pData, srcPkt->iSize);
memcpy(newpkt->pData + srcPkt->iSize, appendPkt->pData, appendPkt->iSize);

CDVDDemuxUtils::FreeDemuxPacket(srcPkt);
srcPkt = NULL;
CDVDDemuxUtils::FreeDemuxPacket(appendPkt);
appendPkt = NULL;

return newpkt;
}

DemuxPacket* CDVDDemuxStreamSSIF::GetMVCPacket()
{
// Here, we recreate a h264 MVC packet from the base one + buffered MVC NALU's
while (!m_H264queue.empty() && !m_MVCqueue.empty())
{
DemuxPacket* h264pkt = m_H264queue.front();
double tsH264 = (h264pkt->dts != DVD_NOPTS_VALUE ? h264pkt->dts : h264pkt->pts);
DemuxPacket* mvcpkt = m_MVCqueue.front();
double tsMVC = (mvcpkt->dts != DVD_NOPTS_VALUE ? mvcpkt->dts : mvcpkt->pts);

if (tsH264 == tsMVC)
{
m_H264queue.pop();
m_MVCqueue.pop();

while (!m_H264queue.empty())
{
DemuxPacket* pkt = m_H264queue.front();
double ts = (pkt->dts != DVD_NOPTS_VALUE ? pkt->dts : pkt->pts);
if (ts == DVD_NOPTS_VALUE)
{
#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, ">>> MVC merge h264 fragment: %6d+%6d, pts(%.3f/%.3f) dts(%.3f/%.3f)", h264pkt->iSize, pkt->iSize, h264pkt->pts*1e-6, pkt->pts*1e-6, h264pkt->dts*1e-6, pkt->dts*1e-6);
#endif
h264pkt = MergePacket(h264pkt, pkt);
m_H264queue.pop();
}
else
break;
}
while (!m_MVCqueue.empty())
{
DemuxPacket* pkt = m_MVCqueue.front();
double ts = (pkt->dts != DVD_NOPTS_VALUE ? pkt->dts : pkt->pts);
if (ts == DVD_NOPTS_VALUE)
{
#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, ">>> MVC merge mvc fragment: %6d+%6d, pts(%.3f/%.3f) dts(%.3f/%.3f)", mvcpkt->iSize, pkt->iSize, mvcpkt->pts*1e-6, pkt->pts*1e-6, mvcpkt->dts*1e-6, pkt->dts*1e-6);
#endif
mvcpkt = MergePacket(mvcpkt, pkt);
m_MVCqueue.pop();
}
else
break;
}

#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, ">>> MVC merge packet: %6d+%6d, pts(%.3f/%.3f) dts(%.3f/%.3f)", h264pkt->iSize, mvcpkt->iSize, h264pkt->pts*1e-6, mvcpkt->pts*1e-6, h264pkt->dts*1e-6, mvcpkt->dts*1e-6);
#endif
return MergePacket(h264pkt, mvcpkt);
}
else if (tsH264 > tsMVC)
{
#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, ">>> MVC discard mvc: %6d, pts(%.3f) dts(%.3f)", mvcpkt->iSize, mvcpkt->pts*1e-6, mvcpkt->dts*1e-6);
#endif
CDVDDemuxUtils::FreeDemuxPacket(mvcpkt);
m_MVCqueue.pop();
}
else
{
#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, ">>> MVC discard h264: %6d, pts(%.3f) dts(%.3f)", h264pkt->iSize, h264pkt->pts*1e-6, h264pkt->dts*1e-6);
#endif
CDVDDemuxUtils::FreeDemuxPacket(h264pkt);
m_H264queue.pop();
}
}

#if defined(DEBUG_VERBOSE)
CLog::Log(LOGDEBUG, ">>> MVC waiting. MVC(%d) H264(%d)", m_MVCqueue.size(), m_H264queue.size());
#endif

return CDVDDemuxUtils::AllocateDemuxPacket(0);
}
Loading

0 comments on commit ce5d853

Please sign in to comment.