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

Commit

Permalink
BACKPORT: Adaptive Smoothstreaming
Browse files Browse the repository at this point in the history
  • Loading branch information
koying committed Feb 12, 2017
1 parent 0b3d2eb commit 69cc8d2
Show file tree
Hide file tree
Showing 30 changed files with 1,488 additions and 637 deletions.
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

0 comments on commit 69cc8d2

Please sign in to comment.