Skip to content
This repository has been archived by the owner on Dec 24, 2024. It is now read-only.

BACKPORT: Adaptive Smoothstreaming #756

Open
wants to merge 1 commit into
base: spmc-jarvis
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 25 additions & 19 deletions XBMC.files
Original file line number Diff line number Diff line change
Expand Up @@ -9845,25 +9845,6 @@ xbmc/interfaces/builtins/WeatherBuiltins.h
tools/android/packaging/xbmc/src/org/xbmc/kodi/XBMCProperties.java.in
xbmc/android/jni/AudioDeviceInfo.cpp
xbmc/android/jni/AudioDeviceInfo.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHByteStream.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHByteStream.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHCodecHandler.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHCodecHandler.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHFragmentedSampleReader.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHFragmentedSampleReader.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHFragmentObserver.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHSession.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHSession.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHStream.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHStream.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHTree.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/DASHTree.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/helpers.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/helpers.h
xbmc/cores/dvdplayer/DVDDemuxers/dash/oscompat.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/oscompat.h
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxMPD.cpp
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxMPD.h
xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamNULL.h
xbmc/cores/dvdplayer/Makefile.in
xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in
Expand Down Expand Up @@ -9974,3 +9955,28 @@ xbmc/android/jni/PlaybackState.h
xbmc/android/jni/PlaybackState.cpp
xbmc/android/jni/BitmapFactory.h
xbmc/android/jni/BitmapFactory.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/SmoothTree.cpp
xbmc/cores/dvdplayer/DVDDemuxers/dash/SmoothTree.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/common/AdaptiveTree.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/common/AdaptiveTree.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/parsers/DASHTree.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/parsers/DASHTree.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/parsers/SmoothTree.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/parsers/SmoothTree.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHByteStream.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHByteStream.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHCodecHandler.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHCodecHandler.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHFragmentedSampleReader.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHFragmentedSampleReader.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHFragmentObserver.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHSession.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHSession.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHStream.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/DASHStream.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/helpers.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/helpers.h
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/oscompat.cpp
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/oscompat.h
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxAdaptive.cpp
xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxAdaptive.h
4 changes: 3 additions & 1 deletion XBMC.includes
Original file line number Diff line number Diff line change
Expand Up @@ -2866,7 +2866,6 @@ xbmc/video/jobs
xbmc/video/videosync
tools/android/packaging/xbmc/src/org/xbmc/kodi
system/shaders
xbmc/cores/dvdplayer/DVDInputStreams/dash
tools/android/packaging/xbmc/res/layout
tools/android/packaging/xbmc/res/values
.
Expand All @@ -2882,3 +2881,6 @@ lib/libUPnP
xbmc/network/android
xbmc/listproviders
tools/android/packaging/xbmc/src/org/xbmc/kodi/interfaces
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/common
xbmc/cores/dvdplayer/DVDDemuxers/adaptive/parsers
xbmc/cores/dvdplayer/DVDDemuxers/adaptive
2 changes: 1 addition & 1 deletion tools/depends/target/bento4/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ DEPS= ../../Makefile.include Makefile

# lib name, version
LIBNAME=Bento4
VERSION=HEAD
VERSION=inputstream
SOURCE=archive
ARCHIVE=$(VERSION).tar.gz
GIT_BASE_URL=https://github.com/koying
Expand Down
282 changes: 282 additions & 0 deletions xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxAdaptive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,282 @@
/*
* Copyright (C) 2016 Christian Browet
* Copyright (C) 2016-2016 peak3d
* 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 "DVDDemuxAdaptive.h"

#include "DVDDemuxPacket.h"
#include "DVDDemuxUtils.h"
#include "DVDInputStreams/DVDInputStream.h"

#include "adaptive/DASHByteStream.h"

#ifdef TARGET_ANDROID
#include "android/jni/SystemProperties.h"
#endif
#ifdef TARGET_WINDOWS
#pragma comment(lib, "libexpat.lib")
#pragma comment(lib, "ap4.lib")
#endif

#include "utils/StringUtils.h"
#include "utils/log.h"

CDVDDemuxAdaptive::CDVDDemuxAdaptive()
: CDVDDemux()
{
CLog::Log(LOGDEBUG, "CDVDDemuxAdaptive::%s", __FUNCTION__);
}

CDVDDemuxAdaptive::~CDVDDemuxAdaptive()
{
CLog::Log(LOGDEBUG, "CDVDDemuxAdaptive::%s", __FUNCTION__);
}

bool CDVDDemuxAdaptive::Open(CDVDInputStream* pInput, uint32_t maxWidth, uint32_t maxHeight)
{
CLog::Log(LOGINFO, "CDVDDemuxAdaptive - matching against %d x %d", maxWidth, maxHeight);

CDASHSession::MANIFEST_TYPE type = CDASHSession::MANIFEST_TYPE_UNKNOWN;

if (pInput->GetFileItem().GetMimeType() == "video/vnd.mpeg.dash.mpd" || pInput->GetFileItem().IsType(".mpd")) //MPD
type = CDASHSession::MANIFEST_TYPE_MPD;
else if (pInput->GetFileItem().GetMimeType() == "application/vnd.ms-sstr+xml" || pInput->GetFileItem().IsType(".ismc") || pInput->GetFileItem().IsType(".ism")) //ISM
type = CDASHSession::MANIFEST_TYPE_ISM;

if (type == CDASHSession::MANIFEST_TYPE_UNKNOWN)
return false;

m_session.reset(new CDASHSession(type, pInput->GetFileName(), maxWidth, maxHeight, "", "", "special://profile/"));

if (!m_session->initialize())
{
m_session = nullptr;
return false;
}
return true;
}

void CDVDDemuxAdaptive::Dispose()
{
}

void CDVDDemuxAdaptive::Reset()
{
}

void CDVDDemuxAdaptive::Abort()
{
}

void CDVDDemuxAdaptive::Flush()
{
}

DemuxPacket*CDVDDemuxAdaptive::Read()
{
if (!m_session)
return NULL;

CDASHFragmentedSampleReader *sr(m_session->GetNextSample());

if (m_session->CheckChange())
{
DemuxPacket *p = CDVDDemuxUtils::AllocateDemuxPacket(0);
p->iStreamId = DMX_SPECIALID_STREAMCHANGE;
CLog::Log(LOGDEBUG, "DMX_SPECIALID_STREAMCHANGE");
return p;
}

if (sr)
{
DemuxPacket *p = CDVDDemuxUtils::AllocateDemuxPacket(sr->GetSampleDataSize());
p->dts = sr->DTS() * 1000000;
p->pts = sr->PTS() * 1000000;
p->duration = sr->GetDuration() * 1000000;
p->iStreamId = sr->GetStreamId();
p->iGroupId = 0;
p->iSize = sr->GetSampleDataSize();
memcpy(p->pData, sr->GetSampleData(), p->iSize);

CLog::Log(LOGDEBUG, "DTS: %0.4f, PTS:%0.4f, ID: %u SZ: %d", p->dts, p->pts, p->iStreamId, p->iSize);

sr->ReadSample();
return p;
}
return NULL;
}

bool CDVDDemuxAdaptive::SeekTime(int time, bool backwards, double* startpts)
{
if (!m_session)
return false;

return m_session->SeekTime(static_cast<double>(time)*0.001f, 0, !backwards);
}

void CDVDDemuxAdaptive::SetSpeed(int speed)
{
}

int CDVDDemuxAdaptive::GetNrOfStreams()
{
int n = 0;
if (m_session)
n = m_session->GetStreamCount();

return n;
}

CDemuxStream* CDVDDemuxAdaptive::GetStream(int streamid)
{
CDASHSession::STREAM *stream(m_session->GetStream(streamid));
if (!stream)
{
CLog::Log(LOGERROR, "CDVDDemuxAdaptive::GetStream(%d): error getting stream", streamid);
return nullptr;
}

return stream->dmuxstrm;
}

void CDVDDemuxAdaptive::EnableStream(int streamid, bool enable)
{
CLog::Log(LOGDEBUG, "EnableStream(%d: %s)", streamid, enable?"true":"false");

if (!m_session)
return;

CDASHSession::STREAM *stream(m_session->GetStream(streamid));
if (!stream)
return;

if (enable)
{
if (stream->enabled)
return;

stream->enabled = true;

stream->stream_.start_stream(~0, m_session->GetWidth(), m_session->GetHeight());
const adaptive::AdaptiveTree::Representation *rep(stream->stream_.getRepresentation());
CLog::Log(LOGDEBUG, "Selecting stream with conditions: w: %u, h: %u, bw: %u",
stream->stream_.getWidth(), stream->stream_.getHeight(), stream->stream_.getBandwidth());

if (!stream->stream_.select_stream(true, false, stream->dmuxstrm->iPhysicalId >> 16))
{
CLog::Log(LOGERROR, "Unable to select stream!");
return stream->disable();
}

if(rep != stream->stream_.getRepresentation())
{
m_session->UpdateStream(*stream);
m_session->CheckChange(true);
}

stream->input_ = new CDASHByteStream(&stream->stream_);
static const AP4_Track::Type TIDC[adaptive::AdaptiveTree::STREAM_TYPE_COUNT] = {
AP4_Track::TYPE_UNKNOWN,
AP4_Track::TYPE_VIDEO,
AP4_Track::TYPE_AUDIO,
AP4_Track::TYPE_TEXT };

AP4_Movie* movie = nullptr;
if (m_session->GetManifestType() == CDASHSession::MANIFEST_TYPE_ISM && stream->stream_.getRepresentation()->get_initialization() == nullptr)
{
//We'll create a Movie out of the things we got from manifest file
//note: movie will be deleted in destructor of stream->input_file_
movie = new AP4_Movie();

AP4_SyntheticSampleTable* sample_table = new AP4_SyntheticSampleTable();
AP4_SampleDescription *sample_descryption = new AP4_SampleDescription(AP4_SampleDescription::TYPE_UNKNOWN, 0, 0);
if (stream->stream_.getAdaptationSet()->encrypted)
{
static const AP4_UI08 default_key[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
AP4_ContainerAtom schi(AP4_ATOM_TYPE_SCHI);
schi.AddChild(new AP4_TencAtom(AP4_CENC_ALGORITHM_ID_CTR, 8, default_key));
sample_descryption = new AP4_ProtectedSampleDescription(0, sample_descryption, 0, AP4_PROTECTION_SCHEME_TYPE_PIFF, 0, "", &schi);
}
sample_table->AddSampleDescription(sample_descryption);

movie->AddTrack(new AP4_Track(TIDC[stream->stream_.get_type()], sample_table, ~0, stream->stream_.getRepresentation()->timescale_, 0, stream->stream_.getRepresentation()->timescale_, 0, "", 0, 0));
//Create a dumy MOOV Atom to tell Bento4 its a fragmented stream
AP4_MoovAtom *moov = new AP4_MoovAtom();
moov->AddChild(new AP4_ContainerAtom(AP4_ATOM_TYPE_MVEX));
movie->SetMoovAtom(moov);
}

stream->input_file_ = new AP4_File(*stream->input_, AP4_DefaultAtomFactory::Instance_, true, movie);
movie = stream->input_file_->GetMovie();
if (movie == NULL)
{
CLog::Log(LOGERROR, "No MOOV in stream!");
return stream->disable();
}

AP4_Track *track = movie->GetTrack(TIDC[stream->stream_.get_type()]);
if (!track)
{
CLog::Log(LOGERROR, "No suitable track found in stream");
return stream->disable();
}

stream->reader_ = new CDASHFragmentedSampleReader(stream->input_, movie, track, streamid, m_session->GetSingleSampleDecryptor(), m_session->GetPresentationTimeOffset());
stream->reader_->SetObserver(dynamic_cast<IDASHFragmentObserver*>(m_session.get()));

if (!stream->dmuxstrm->ExtraSize && stream->reader_->GetExtraDataSize())
{
// ExtraData is now available......
stream->dmuxstrm->ExtraSize = stream->reader_->GetExtraDataSize();
stream->dmuxstrm->ExtraData = (uint8_t*)malloc(stream->dmuxstrm->ExtraSize);
memcpy((void*)stream->dmuxstrm->ExtraData, stream->reader_->GetExtraData(), stream->dmuxstrm->ExtraSize);
// Set the session Changed to force new GetStreamInfo call from kodi -> addon
m_session->CheckChange(true);
}
return;
}
CLog::Log(LOGDEBUG, ">>>> ERROR");
return stream->disable();
}

int CDVDDemuxAdaptive::GetStreamLength()
{
if (!m_session)
return 0;

return static_cast<int>(m_session->GetTotalTime()*1000);
}

std::string CDVDDemuxAdaptive::GetFileName()
{
if (!m_session)
return "";

return m_session->GetUrl();
}

void CDVDDemuxAdaptive::GetStreamCodecName(int iStreamId, std::string& strName)
{
strName = "";

CDASHSession::STREAM *stream(m_session->GetStream(iStreamId));
if (stream)
strName = stream->codecName;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@

#include <memory>

#include "dash/DASHSession.h"
#include "adaptive/DASHSession.h"

class CDVDDemuxMPD : public CDVDDemux
class CDVDDemuxAdaptive : public CDVDDemux
{
public:
CDVDDemuxMPD();
virtual ~CDVDDemuxMPD();
CDVDDemuxAdaptive();
virtual ~CDVDDemuxAdaptive();

bool Open(CDVDInputStream* pInput, uint32_t maxWidth, uint32_t maxHeight);
void Dispose();
Expand All @@ -50,5 +50,5 @@ class CDVDDemuxMPD : public CDVDDemux
virtual void GetStreamCodecName(int iStreamId, std::string &strName);

protected:
std::shared_ptr<CDASHSession> m_MPDsession;
std::shared_ptr<CDASHSession> m_session;
};
Loading