Skip to content

Commit

Permalink
ADD: [demux] support ssif
Browse files Browse the repository at this point in the history
  • Loading branch information
koying committed May 16, 2015
1 parent 9453405 commit eefc2a9
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 4 deletions.
99 changes: 96 additions & 3 deletions xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
Expand Up @@ -169,6 +169,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux()
m_currentPts = DVD_NOPTS_VALUE;
m_bMatroska = false;
m_bAVI = false;
m_bSSIF = false;
m_speed = DVD_PLAYSPEED_NORMAL;
m_program = UINT_MAX;
m_pkt.result = -1;
Expand Down Expand Up @@ -524,6 +525,12 @@ void CDVDDemuxFFmpeg::Dispose()
av_free(m_ioContext);
}

while (!m_SSIFqueue.empty())
{
CDVDDemuxUtils::FreeDemuxPacket(m_SSIFqueue.front());
m_SSIFqueue.pop();
}

m_ioContext = NULL;
m_pFormatContext = NULL;
m_speed = DVD_PLAYSPEED_NORMAL;
Expand Down Expand Up @@ -695,7 +702,9 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
{
Flush();
}
else if (IsProgramChange())
// libavformat is confused by the interleaved SSIF.
// Disable program management for those
else if (!m_bSSIF && IsProgramChange())
{
// update streams
CreateStreams(m_program);
Expand Down Expand Up @@ -731,7 +740,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_bSSIF && 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 @@ -864,6 +875,71 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
// content has changed
stream = AddStream(pPacket->iStreamId);
}
if (m_bSSIF && stream->iPhysicalId == 0x1011)
{
// Here, we recreate a h264 MVC packet from the base one + buffered MVC NALU's
if (m_SSIFqueue.size() <= 0)
CLog::Log(LOGERROR, "!!! MVC error: no mvc packet: pts(%f) dts(%f) - %lld", pPacket->pts, pPacket->dts, m_pkt.pkt.pts);
else
{
DemuxPacket* mvcpkt = m_SSIFqueue.front();
double tsA = (pPacket->dts != AV_NOPTS_VALUE ? pPacket->dts : pPacket->pts);
double tsB = (mvcpkt->dts != AV_NOPTS_VALUE ? mvcpkt->dts : mvcpkt->pts);
while (tsB < tsA)
{
m_SSIFqueue.pop();
if (m_SSIFqueue.empty())
{
tsB = AV_NOPTS_VALUE;
break;
}
mvcpkt = m_SSIFqueue.front();
tsB = (mvcpkt->dts != AV_NOPTS_VALUE ? mvcpkt->dts : mvcpkt->pts);
}
if (tsA == tsB)
{
m_SSIFqueue.pop();
DemuxPacket* newpkt = CDVDDemuxUtils::AllocateDemuxPacket(pPacket->iSize + mvcpkt->iSize);
newpkt->pts = pPacket->pts;
newpkt->dts = pPacket->dts;
newpkt->duration = pPacket->duration;
newpkt->iGroupId = pPacket->iGroupId;
newpkt->iStreamId = pPacket->iStreamId;
newpkt->iSize = pPacket->iSize + mvcpkt->iSize;
memcpy(newpkt->pData, pPacket->pData, pPacket->iSize);
memcpy(newpkt->pData + pPacket->iSize, mvcpkt->pData, mvcpkt->iSize);
//CLog::Log(LOGDEBUG, ">>> MVC merged packet: %d+%d, pts(%f/%f) dts (%f/%f)", pPacket->iSize, mvcpkt->iSize, pPacket->pts, mvcpkt->pts, pPacket->dts, mvcpkt->dts);

CDVDDemuxUtils::FreeDemuxPacket(pPacket);
CDVDDemuxUtils::FreeDemuxPacket(mvcpkt);
pPacket = newpkt;
}
else
{
CLog::Log(LOGERROR, "!!! MVC error: missing mvc packet: pts(%f) dts(%f) - %lld", pPacket->pts, pPacket->dts, m_pkt.pkt.pts);
}
}
}
}
else if (stream->type == STREAM_DATA)
{
if (m_bSSIF && stream->iPhysicalId == 0x1012)
{
// Buffer the MVC NALU's for later merging with the base h264 packet
// This works because the MVC stream is guaranteed to come first
DemuxPacket* newpkt = CDVDDemuxUtils::AllocateDemuxPacket(pPacket->iSize);
newpkt->iSize = pPacket->iSize;
newpkt->pts = pPacket->pts;
newpkt->dts = pPacket->dts;
newpkt->duration = pPacket->duration;
newpkt->iGroupId = pPacket->iGroupId;
newpkt->iStreamId = pPacket->iStreamId;
memcpy(newpkt->pData, pPacket->pData, newpkt->iSize);
m_SSIFqueue.push(newpkt);
CDVDDemuxUtils::FreeDemuxPacket(pPacket);
pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0);
pPacket->iSize = 0;
}
}
if (!stream)
{
Expand Down Expand Up @@ -1166,6 +1242,12 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId)
st->iFpsScale = 0;
}

if (m_bSSIF && pStream->id == 0x1011)
{
// Mark stream as MVC
pStream->codec->codec_tag = AV_CODEC_ID_H264MVC;
}

st->iWidth = pStream->codec->width;
st->iHeight = pStream->codec->height;
st->fAspect = SelectAspect(pStream, &st->bForcedAspect) * pStream->codec->width / pStream->codec->height;
Expand Down Expand Up @@ -1205,6 +1287,17 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int iId)
{
stream = new CDemuxStream();
stream->type = STREAM_DATA;
if (pStream->id == 0x1012)
{
// This is the MVC stream of a SSIF file
// SSIF's are 2 M2TS streams interleaved:
// - 1 base M2TS with base h264 + audio
// - 1 "extension" M2TS only containing the MVC NALU's of the h264 MVC stream
// The base h264 is always stream 0x1011 and the mvc one is always 0x1012
// The mvc stream always comes first
m_bSSIF = true;
pStream->need_parsing = AVSTREAM_PARSE_NONE;
}
break;
}
case AVMEDIA_TYPE_SUBTITLE:
Expand Down Expand Up @@ -1358,7 +1451,7 @@ void CDVDDemuxFFmpeg::AddStream(int iId, CDemuxStream* stream)
res.first->second = stream;
}
if(g_advancedSettings.m_logLevel > LOG_LEVEL_NORMAL)
CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::AddStream(%d, ...) -> %d", iId, stream->iId);
CLog::Log(LOGDEBUG, "CDVDDemuxFFmpeg::AddStream(%d, ...) -> %d (%d)", iId, stream->iId, stream->orig_type);
}


Expand Down
3 changes: 3 additions & 0 deletions xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.h
Expand Up @@ -25,6 +25,7 @@
#include "threads/SystemClock.h"
#include <map>
#include <vector>
#include <queue>

extern "C" {
#include "libavformat/avformat.h"
Expand Down Expand Up @@ -153,6 +154,8 @@ class CDVDDemuxFFmpeg : public CDVDDemux
double m_currentPts; // used for stream length estimation
bool m_bMatroska;
bool m_bAVI;
bool m_bSSIF;
std::queue<DemuxPacket*> m_SSIFqueue;
int m_speed;
unsigned m_program;
XbmcThreads::EndTime m_timeout;
Expand Down
2 changes: 1 addition & 1 deletion xbmc/settings/AdvancedSettings.cpp
Expand Up @@ -376,7 +376,7 @@ void CAdvancedSettings::Initialize()

m_pictureExtensions = ".png|.jpg|.jpeg|.bmp|.gif|.ico|.tif|.tiff|.tga|.pcx|.cbz|.zip|.cbr|.rar|.dng|.nef|.cr2|.crw|.orf|.arw|.erf|.3fr|.dcr|.x3f|.mef|.raf|.mrw|.pef|.sr2|.rss";
m_musicExtensions = ".nsv|.m4a|.flac|.aac|.strm|.pls|.rm|.rma|.mpa|.wav|.wma|.ogg|.mp3|.mp2|.m3u|.gdm|.imf|.m15|.sfx|.uni|.ac3|.dts|.cue|.aif|.aiff|.wpl|.ape|.mac|.mpc|.mp+|.mpp|.shn|.zip|.rar|.wv|.dsp|.xsp|.xwav|.waa|.wvs|.wam|.gcm|.idsp|.mpdsp|.mss|.spt|.rsd|.sap|.cmc|.cmr|.dmc|.mpt|.mpd|.rmt|.tmc|.tm8|.tm2|.oga|.url|.pxml|.tta|.rss|.wtv|.mka|.tak|.opus|.dff|.dsf";
m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.m3u8|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.mk3d|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv";
m_videoExtensions = ".m4v|.3g2|.3gp|.nsv|.tp|.ts|.ty|.strm|.pls|.rm|.rmvb|.m3u|.m3u8|.ifo|.mov|.qt|.divx|.xvid|.bivx|.vob|.nrg|.img|.iso|.pva|.wmv|.asf|.asx|.ogm|.m2v|.avi|.bin|.dat|.mpg|.mpeg|.mp4|.mkv|.mk3d|.avc|.vp3|.svq3|.nuv|.viv|.dv|.fli|.flv|.rar|.001|.wpl|.zip|.vdr|.dvr-ms|.xsp|.mts|.m2t|.m2ts|.evo|.ogv|.sdp|.avs|.rec|.url|.pxml|.vc1|.h264|.rcv|.rss|.mpls|.webm|.bdmv|.wtv|.ssif";
m_subtitlesExtensions = ".utf|.utf8|.utf-8|.sub|.srt|.smi|.rt|.txt|.ssa|.text|.ssa|.aqt|.jss|.ass|.idx|.ifo|.rar|.zip";
m_discStubExtensions = ".disc";
// internal music extensions
Expand Down

0 comments on commit eefc2a9

Please sign in to comment.