Skip to content

Commit

Permalink
[VideoPlayer] DemuxFFmpeg: ssif remux
Browse files Browse the repository at this point in the history
fix for compiling with libbluray disabled
  • Loading branch information
Anton Fedchin authored and popcornmix committed Apr 3, 2020
1 parent af6925e commit 205d1c4
Show file tree
Hide file tree
Showing 15 changed files with 874 additions and 16 deletions.
5 changes: 5 additions & 0 deletions xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodec.h
Expand Up @@ -235,6 +235,11 @@ class CDVDVideoCodec
*/
virtual void Reopen() {};

/**
* Indicates that the decoder supports extention streams.
*/
virtual bool SupportsExtention() { return false; }

protected:
CProcessInfo &m_processInfo;
};
Expand Down
4 changes: 4 additions & 0 deletions xbmc/cores/VideoPlayer/DVDDemuxers/CMakeLists.txt
Expand Up @@ -5,6 +5,8 @@ set(SOURCES DemuxMultiSource.cpp
DVDDemuxCDDA.cpp
DVDDemuxClient.cpp
DVDDemuxFFmpeg.cpp
DemuxStreamSSIF.cpp
DemuxMVC.cpp
DVDDemuxUtils.cpp
DVDDemuxVobsub.cpp
DVDFactoryDemuxer.cpp)
Expand All @@ -16,6 +18,8 @@ set(HEADERS DemuxMultiSource.h
DVDDemuxCDDA.h
DVDDemuxClient.h
DVDDemuxFFmpeg.h
DemuxStreamSSIF.h
DemuxMVC.h
DVDDemuxUtils.h
DVDDemuxVobsub.h
DVDFactoryDemuxer.h)
Expand Down
93 changes: 85 additions & 8 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
Expand Up @@ -9,6 +9,7 @@
#include "DVDDemuxFFmpeg.h"

#include "DVDCodecs/DVDCodecUtils.h"
#include "DemuxMVC.h"
#include "DVDDemuxUtils.h"
#include "DVDInputStreams/DVDInputStream.h"
#include "DVDInputStreams/DVDInputStreamFFmpeg.h"
Expand Down Expand Up @@ -174,6 +175,7 @@ CDVDDemuxFFmpeg::CDVDDemuxFFmpeg() : CDVDDemux()
m_bMatroska = false;
m_bAVI = false;
m_bSup = false;
m_pSSIF = nullptr;
m_speed = DVD_PLAYSPEED_NORMAL;
m_program = UINT_MAX;
m_pkt.result = -1;
Expand Down Expand Up @@ -569,6 +571,16 @@ bool CDVDDemuxFFmpeg::Open(std::shared_ptr<CDVDInputStream> pInput, bool streami
if (!programProp.isNull())
m_initialProgramNumber = static_cast<int>(programProp.asInteger());

if (!fileinfo)
{
const std::shared_ptr<CDVDInputStream::IExtentionStream> pExt = std::dynamic_pointer_cast<CDVDInputStream::IExtentionStream>(m_pInput);
if (pExt && pExt->HasExtention())
{
delete m_pSSIF;
m_pSSIF = new CDemuxStreamSSIF();
m_pSSIF->SetBluRay(pExt);
}
}
// in case of mpegts and we have not seen pat/pmt, defer creation of streams
if (!skipCreateStreams || m_pFormatContext->nb_programs > 0)
{
Expand Down Expand Up @@ -650,6 +662,9 @@ void CDVDDemuxFFmpeg::Dispose()
m_pkt.result = -1;
av_packet_unref(&m_pkt.pkt);

delete m_pSSIF;
m_pSSIF = nullptr;

if (m_pFormatContext)
{
if (m_ioContext && m_pFormatContext->pb && m_pFormatContext->pb != m_ioContext)
Expand Down Expand Up @@ -699,6 +714,9 @@ void CDVDDemuxFFmpeg::Flush()
m_displayTime = 0;
m_dtsAtDisplayTime = DVD_NOPTS_VALUE;
m_seekToKeyFrame = false;

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

void CDVDDemuxFFmpeg::Abort()
Expand Down Expand Up @@ -1009,6 +1027,17 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
{
Flush();
}
else if (IsProgramChange())
{
// update streams
CreateStreams(m_program);

pPacket = CDVDDemuxUtils::AllocateDemuxPacket(0);
pPacket->iStreamId = DMX_SPECIALID_STREAMCHANGE;
pPacket->demuxerId = m_demuxerId;

return pPacket;
}
// check size and stream index for being in a valid range
else if (m_pkt.pkt.size < 0 ||
m_pkt.pkt.stream_index < 0 ||
Expand All @@ -1026,6 +1055,9 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()

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

if (m_pSSIF)
m_pSSIF->Flush();
}
else
{
Expand All @@ -1050,7 +1082,8 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()

if (IsTransportStreamReady())
{
if (m_program != UINT_MAX)
// libavformat is confused by the interleaved SSIF.
if ((!m_pSSIF || m_pSSIF->IsBluRay()) && 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 @@ -1164,6 +1197,12 @@ DemuxPacket* CDVDDemuxFFmpeg::Read()
pPacket->recoveryPoint = m_seekToKeyFrame;
m_seekToKeyFrame = false;
}
if (stream && m_pSSIF)
{
pPacket = m_pSSIF->AddPacket(pPacket);
if (stream->type == STREAM_DATA && stream->codec == AV_CODEC_ID_H264_MVC && pPacket->iSize)
stream = GetStream(pPacket->iStreamId);
}
if (!stream)
{
CDVDDemuxUtils::FreeDemuxPacket(pPacket);
Expand Down Expand Up @@ -1206,6 +1245,8 @@ bool CDVDDemuxFFmpeg::SeekTime(double time, bool backwards, double* startpts)

return true;
}
else if (m_pSSIF)
m_pSSIF->Flush();

if (!m_pInput->Seek(0, SEEK_POSSIBLE) &&
!m_pInput->IsStreamType(DVDSTREAM_TYPE_FFMPEG))
Expand Down Expand Up @@ -1315,6 +1356,9 @@ bool CDVDDemuxFFmpeg::SeekByte(int64_t pos)
m_pkt.result = -1;
av_packet_unref(&m_pkt.pkt);

if (m_pSSIF)
m_pSSIF->Flush();

return (ret >= 0);
}

Expand Down Expand Up @@ -1557,13 +1601,14 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx)
}
case AVMEDIA_TYPE_VIDEO:
{
if (pStream->codec->codec_id == AV_CODEC_ID_H264_MVC)
if (pStream->codecpar->codec_id == AV_CODEC_ID_H264_MVC)
{
// ignore MVC extension streams, they are handled specially
m_pSSIF = new CDemuxStreamSSIF();
m_pSSIF->SetMVCStreamId(streamIdx);

stream = new CDemuxStream();
stream->type = STREAM_DATA;
stream->disabled = true;
pStream->need_parsing = AVSTREAM_PARSE_NONE;
pStream->codecpar->codec_type = AVMEDIA_TYPE_DATA;
break;
}
CDemuxStreamVideoFFmpeg* st = new CDemuxStreamVideoFFmpeg(pStream);
Expand Down Expand Up @@ -1644,13 +1689,40 @@ CDemuxStream* CDVDDemuxFFmpeg::AddStream(int streamIdx)
if (av_dict_get(pStream->metadata, "title", NULL, 0))
st->m_description = av_dict_get(pStream->metadata, "title", NULL, 0)->value;

if (pStream->codec->codec_id == AV_CODEC_ID_H264)
if (pStream->codecpar->codec_id == AV_CODEC_ID_H264)
{
if (CDVDCodecUtils::IsH264AnnexB(m_pFormatContext->iformat->name, pStream))
{
// TODO
if (m_pSSIF)
{
m_pSSIF->SetH264StreamId(streamIdx);
pStream->codecpar->codec_tag = MKTAG('A', 'M', 'V', 'C');

AVStream* mvcStream = nullptr;
const std::shared_ptr<CDVDInputStream::IExtentionStream> pExt = std::dynamic_pointer_cast<CDVDInputStream::IExtentionStream>(m_pInput);
if (pExt)
{
if (pExt->HasExtention())
{
st->stereo_mode = pExt->AreEyesFlipped() ? "block_rl" : "block_lr";
mvcStream = static_cast<CDemuxMVC*>(pExt->GetExtentionDemux())->GetAVStream();
}
}
else
mvcStream = m_pFormatContext->streams[m_pSSIF->GetMVCStreamId()];

if (mvcStream && pStream->codecpar->extradata_size > 0 && mvcStream->codecpar->extradata_size > 0)
{
uint8_t* extr = pStream->codecpar->extradata;
pStream->codecpar->extradata = (uint8_t*)av_mallocz(pStream->codecpar->extradata_size + mvcStream->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
memcpy(pStream->codecpar->extradata, extr, pStream->codecpar->extradata_size);
memcpy(pStream->codecpar->extradata + pStream->codecpar->extradata_size, mvcStream->codecpar->extradata, mvcStream->codecpar->extradata_size);
pStream->codecpar->extradata_size += mvcStream->codecpar->extradata_size;
av_free(extr);
}
}
}
else if (CDVDCodecUtils::ProcessH264MVCExtradata(pStream->codec->extradata, pStream->codec->extradata_size))
else if (CDVDCodecUtils::ProcessH264MVCExtradata(pStream->codecpar->extradata, pStream->codecpar->extradata_size))
{
pStream->codecpar->codec_tag = MKTAG('M', 'V', 'C', '1');
}
Expand Down Expand Up @@ -1998,6 +2070,11 @@ std::string CDVDDemuxFFmpeg::GetStreamCodecName(int iStreamId)

bool CDVDDemuxFFmpeg::IsProgramChange()
{
// libavformat is confused by the interleaved SSIF.
// disable program management for those
if (m_pSSIF && !m_pSSIF->IsBluRay())
return false;

if (m_program == UINT_MAX)
return false;

Expand Down
2 changes: 2 additions & 0 deletions xbmc/cores/VideoPlayer/DVDDemuxers/DVDDemuxFFmpeg.h
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include "DVDDemux.h"
#include "DemuxStreamSSIF.h"
#include "threads/CriticalSection.h"
#include "threads/SystemClock.h"
#include <map>
Expand Down Expand Up @@ -150,6 +151,7 @@ class CDVDDemuxFFmpeg : public CDVDDemux
bool m_bMatroska;
bool m_bAVI;
bool m_bSup;
CDemuxStreamSSIF* m_pSSIF;
int m_speed;
unsigned int m_program;
unsigned int m_streamsInProgram;
Expand Down

0 comments on commit 205d1c4

Please sign in to comment.