stream_filter/dash/DASHManager.cpp \
stream_filter/dash/DASHManager.h \
stream_filter/dash/Helper.cpp \
- stream_filter/dash/Helper.h
+ stream_filter/dash/Helper.h \
+ stream_filter/dash/StreamsType.hpp \
+ stream_filter/dash/Streams.cpp \
+ stream_filter/dash/Streams.hpp
libdash_plugin_la_SOURCES += demux/mp4/libmp4.c demux/mp4/libmp4.h
do
{
block_t *block = NULL;
- ret = conManager->read(&block);
+ ret = conManager->read(Streams::VIDEO, &block);
if(ret > 0)
buffer->put(block);
}while(ret > 0 && !buffer->getEOF());
}
else
{
- const Representation *rep = adaptationLogic->getCurrentRepresentation();
+ const Representation *rep = adaptationLogic->getCurrentRepresentation(Streams::VIDEO);
if ( !rep )
return 0;
else
--- /dev/null
+/*
+ * Streams.cpp
+ *****************************************************************************
+ * Copyright (C) 2014 - VideoLAN authors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#include "Streams.hpp"
+
+using namespace dash::Streams;
+
+Stream::Stream(const std::string &mime)
+{
+ type = mimeToType(mime);
+}
+
+Stream::Stream(const Type type)
+{
+ this->type = type;
+}
+
+Type Stream::mimeToType(const std::string &mime)
+{
+ Type mimetype;
+ if (mime == "video/mp4")
+ mimetype = Streams::VIDEO;
+ else if (mime == "audio/mp4")
+ mimetype = Streams::AUDIO;
+ else if (mime == "application/mp4")
+ mimetype = Streams::APPLICATION;
+ else /* unknown of unsupported */
+ mimetype = Streams::UNKNOWN;
+ return mimetype;
+}
+
+bool Stream::operator ==(const Stream &stream) const
+{
+ return stream.type == type;
+}
+/*
+ * Streams.hpp
+ *****************************************************************************
+ * Copyright (C) 2014 - VideoLAN authors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
#ifndef STREAM_HPP
#define STREAM_HPP
-class Stream
+#include <string>
+#include "StreamsType.hpp"
+
+namespace dash
{
-public:
- Stream();
-};
+ namespace Streams
+ {
+ class AbstractStreamOutput;
+
+ class Stream
+ {
+ public:
+ Stream(const std::string &mime);
+ Stream(const Type);
+ bool operator==(const Stream &) const;
+ static Type mimeToType(const std::string &mime);
+
+ private:
+ Type type;
+ };
-#endif // STREAM_HPP
+ }
+}
+#endif // STREAMS_HPP
--- /dev/null
+/*
+ * StreamsType.hpp
+ *****************************************************************************
+ * Copyright (C) 2014 - VideoLAN authors
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2.1 of the License, 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 Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+#ifndef STREAMSTYPE_HPP
+#define STREAMSTYPE_HPP
+
+namespace dash
+{
+ namespace Streams
+ {
+ enum Type
+ {
+ UNKNOWN = 0,
+ VIDEO,
+ AUDIO,
+ APPLICATION
+ };
+
+ static const int count = APPLICATION + 1;
+ }
+}
+
+#endif
AlwaysBestAdaptationLogic::AlwaysBestAdaptationLogic (MPDManager *mpdManager) :
AbstractAdaptationLogic (mpdManager)
{
- this->count = 0;
- this->initSchedule();
+ initSchedule();
}
+
AlwaysBestAdaptationLogic::~AlwaysBestAdaptationLogic ()
{
}
-Chunk* AlwaysBestAdaptationLogic::getNextChunk()
+Chunk* AlwaysBestAdaptationLogic::getNextChunk(Streams::Type type)
{
- if ( this->count < this->schedule.size() )
+ if ( streams[type].count < streams[type].schedule.size() )
{
Chunk *chunk = new Chunk();
- chunk->setUrl(this->schedule.at( this->count )->getUrlSegment());
- this->count++;
+ chunk->setUrl(streams[type].schedule.at( streams[type].count )->getUrlSegment());
+ streams[type].count++;
return chunk;
}
return NULL;
}
-const Representation *AlwaysBestAdaptationLogic::getCurrentRepresentation() const
+const Representation *AlwaysBestAdaptationLogic::getCurrentRepresentation(Streams::Type type) const
{
- if ( this->count < this->schedule.size() )
- return this->schedule.at( this->count )->getRepresentation();
+ if ( streams[type].count < streams[type].schedule.size() )
+ return streams[type].schedule.at( streams[type].count )->getRepresentation();
+
return NULL;
}
if(mpdManager)
{
std::vector<Period *> periods = mpdManager->getPeriods();
- std::vector<Period *>::const_iterator it;
+ if (periods.empty())
+ return;
RepresentationSelector selector;
- for(it=periods.begin(); it!=periods.end(); it++)
+ for(int type=0; type<Streams::count; type++)
{
- Representation *best = selector.select(*it);
+ streams[type].count = 0;
+ Representation *best = selector.select(periods.front(),
+ static_cast<Streams::Type>(type));
if(best)
{
std::vector<ISegment *> segments = best->getSegments();
std::vector<ISegment *>::const_iterator segIt;
for(segIt=segments.begin(); segIt!=segments.end(); segIt++)
{
- schedule.push_back(*segIt);
+ streams[type].schedule.push_back(*segIt);
}
}
}
#include "mpd/MPDManager.hpp"
#include "mpd/Period.h"
#include "mpd/Segment.h"
+#include "Streams.hpp"
#include <vector>
namespace dash
AlwaysBestAdaptationLogic (dash::mpd::MPDManager *mpdManager);
virtual ~AlwaysBestAdaptationLogic ();
- dash::http::Chunk* getNextChunk();
- const mpd::Representation *getCurrentRepresentation() const;
+ virtual dash::http::Chunk* getNextChunk(Streams::Type);
+ const mpd::Representation *getCurrentRepresentation(Streams::Type) const;
private:
- std::vector<mpd::ISegment *> schedule;
- size_t count;
- dash::mpd::Representation *bestRepresentation;
-
- void initSchedule();
+ struct
+ {
+ std::vector<mpd::ISegment *> schedule;
+ size_t count;
+ mpd::Representation *bestRepresentation;
+ } streams[Streams::count];
+ void initSchedule ();
};
}
}
{
}
-Chunk* AlwaysLowestAdaptationLogic::getNextChunk()
+Chunk* AlwaysLowestAdaptationLogic::getNextChunk(Streams::Type type)
{
if(!currentPeriod)
return NULL;
- const Representation *rep = getCurrentRepresentation();
+ const Representation *rep = getCurrentRepresentation(type);
if ( rep == NULL )
return NULL;
{
currentPeriod = mpdManager->getNextPeriod(currentPeriod);
count = 0;
- return getNextChunk();
+ return getNextChunk(type);
}
if ( segments.size() > count )
return NULL;
}
-const Representation *AlwaysLowestAdaptationLogic::getCurrentRepresentation() const
+const Representation *AlwaysLowestAdaptationLogic::getCurrentRepresentation(Streams::Type type) const
{
RepresentationSelector selector;
- return selector.select(currentPeriod, 0);
+ return selector.select(currentPeriod, type, 0);
}
public:
AlwaysLowestAdaptationLogic(dash::mpd::MPDManager *mpdManager);
- virtual dash::http::Chunk* getNextChunk ();
- virtual const dash::mpd::Representation* getCurrentRepresentation() const;
+ virtual dash::http::Chunk* getNextChunk (Streams::Type);
+ virtual const dash::mpd::Representation* getCurrentRepresentation(Streams::Type) const;
private:
dash::mpd::Period *currentPeriod;
#include <adaptationlogic/IDownloadRateObserver.h>
#include "mpd/Representation.h"
#include "buffer/IBufferObserver.h"
+#include "Streams.hpp"
namespace dash
{
RateBased
};
- virtual dash::http::Chunk* getNextChunk () = 0;
- virtual const dash::mpd::Representation* getCurrentRepresentation() const = 0;
+ virtual dash::http::Chunk* getNextChunk (Streams::Type) = 0;
+ virtual const dash::mpd::Representation* getCurrentRepresentation(Streams::Type) const = 0;
/**
* \return The average bitrate in bits per second.
*/
height = var_InheritInteger(mpdManager->getMPD()->getVLCObject(), "dash-prefheight");
}
-Chunk* RateBasedAdaptationLogic::getNextChunk()
+Chunk* RateBasedAdaptationLogic::getNextChunk(Streams::Type type)
{
if(this->currentPeriod == NULL)
return NULL;
- const Representation *rep = getCurrentRepresentation();
+ const Representation *rep = getCurrentRepresentation(type);
if (!rep)
return NULL;
{
this->currentPeriod = this->mpdManager->getNextPeriod(this->currentPeriod);
this->count = 0;
- return this->getNextChunk();
+ return getNextChunk(type);
}
if ( segments.size() > this->count )
return NULL;
}
-const Representation *RateBasedAdaptationLogic::getCurrentRepresentation() const
+const Representation *RateBasedAdaptationLogic::getCurrentRepresentation(Streams::Type type) const
{
if(currentPeriod == NULL)
return NULL;
bitrate = 0;
RepresentationSelector selector;
- Representation *rep = selector.select(currentPeriod, bitrate, width, height);
+ Representation *rep = selector.select(currentPeriod, type, bitrate, width, height);
if ( rep == NULL )
{
- rep = selector.select(currentPeriod);
+ rep = selector.select(currentPeriod, type);
if ( rep == NULL )
return NULL;
}
public:
RateBasedAdaptationLogic (dash::mpd::MPDManager *mpdManager);
- dash::http::Chunk* getNextChunk();
- const dash::mpd::Representation *getCurrentRepresentation() const;
+ virtual dash::http::Chunk* getNextChunk(Streams::Type);
+ const dash::mpd::Representation *getCurrentRepresentation(Streams::Type) const;
private:
size_t count;
{
}
-Representation * RepresentationSelector::select(Period *period) const
+Representation * RepresentationSelector::select(Period *period, Streams::Type type) const
{
- return select(period, std::numeric_limits<uint64_t>::max());
+ return select(period, type, std::numeric_limits<uint64_t>::max());
}
-
-Representation * RepresentationSelector::select(Period *period, uint64_t bitrate) const
+Representation * RepresentationSelector::select(Period *period, Streams::Type type, uint64_t bitrate) const
{
if (period == NULL)
return NULL;
- std::vector<AdaptationSet *> adaptSets = period->getAdaptationSets();
-
+ std::vector<AdaptationSet *> adaptSets = period->getAdaptationSets(type);
Representation *best = NULL;
std::vector<AdaptationSet *>::const_iterator adaptIt;
return best;
}
-Representation * RepresentationSelector::select(Period *period, uint64_t bitrate,
+Representation * RepresentationSelector::select(Period *period, Streams::Type type, uint64_t bitrate,
int width, int height) const
{
if(period == NULL)
std::vector<Representation *> resMatchReps;
/* subset matching WxH */
- std::vector<AdaptationSet *> adaptSets = period->getAdaptationSets();
+ std::vector<AdaptationSet *> adaptSets = period->getAdaptationSets(type);
std::vector<AdaptationSet *>::const_iterator adaptIt;
for(adaptIt=adaptSets.begin(); adaptIt!=adaptSets.end(); adaptIt++)
{
}
if(resMatchReps.empty())
- return select(period, bitrate);
+ return select(period, type, bitrate);
else
return select(resMatchReps, 0, bitrate);
}
public:
RepresentationSelector();
virtual ~RepresentationSelector() {}
- virtual Representation * select(Period *period) const;
- virtual Representation * select(Period *period, uint64_t bitrate) const;
- virtual Representation * select(Period *period, uint64_t bitrate,
+ virtual Representation * select(Period *period, Streams::Type) const;
+ virtual Representation * select(Period *period, Streams::Type, uint64_t bitrate) const;
+ virtual Representation * select(Period *period, Streams::Type, uint64_t bitrate,
int width, int height) const;
protected:
virtual Representation * select(std::vector<Representation *>&reps,
const uint64_t HTTPConnectionManager::CHUNKDEFAULTBITRATE = 1;
HTTPConnectionManager::HTTPConnectionManager (IAdaptationLogic *adaptationLogic, stream_t *stream) :
+ currentChunk (NULL),
adaptationLogic (adaptationLogic),
stream (stream),
chunkCount (0),
void HTTPConnectionManager::closeAllConnections ()
{
vlc_delete_all(this->connectionPool);
- vlc_delete_all(this->downloadQueue);
+ for(int i=0; i<Streams::count; i++)
+ vlc_delete_all(downloadQueue[i]);
+ delete currentChunk;
}
-ssize_t HTTPConnectionManager::read(block_t **pp_block)
+ssize_t HTTPConnectionManager::read(Streams::Type type, block_t **pp_block)
{
Chunk *chunk;
- if(downloadQueue.empty())
+ if(downloadQueue[type].empty())
{
- chunk = adaptationLogic->getNextChunk();
+ chunk = adaptationLogic->getNextChunk(type);
if(!connectChunk(chunk))
return -1;
else
- downloadQueue.push_back(chunk);
+ downloadQueue[type].push_back(chunk);
}
- chunk = downloadQueue.front();
+ chunk = downloadQueue[type].front();
if(chunk->getBytesRead() == 0)
{
this->timeChunk = 0;
delete(chunk);
- downloadQueue.pop_front();
+ downloadQueue[type].pop_front();
- return read(pp_block);
+ return read(type, pp_block);
}
else
{
{
chunk->onDownload(block->p_buffer, block->i_buffer);
delete chunk;
- downloadQueue.pop_front();
+ downloadQueue[type].pop_front();
}
}
#include "http/PersistentConnection.h"
#include "adaptationlogic/IAdaptationLogic.h"
+#include "Streams.hpp"
namespace dash
{
virtual ~HTTPConnectionManager ();
void closeAllConnections ();
- ssize_t read (block_t **);
+ ssize_t read (Streams::Type, block_t **);
void attach (dash::logic::IDownloadRateObserver *observer);
void notify ();
private:
std::vector<dash::logic::IDownloadRateObserver *> rateObservers;
- std::deque<Chunk *> downloadQueue;
+ std::deque<Chunk *> downloadQueue[Streams::count];
+ Chunk *currentChunk;
std::vector<PersistentConnection *> connectionPool;
logic::IAdaptationLogic *adaptationLogic;
stream_t *stream;
return this->adaptationSets;
}
+const std::vector<AdaptationSet*> Period::getAdaptationSets(Streams::Type type) const
+{
+ std::vector<AdaptationSet*> list;
+ std::vector<AdaptationSet*>::const_iterator it;
+ for(it = adaptationSets.begin(); it!= adaptationSets.end(); it++)
+ {
+ if( Streams::Stream::mimeToType((*it)->getMimeType()) == type )
+ list.push_back(*it);
+ }
+ return list;
+}
+
void Period::addAdaptationSet(AdaptationSet *adaptationSet)
{
if ( adaptationSet != NULL )
this->adaptationSets.push_back(adaptationSet);
}
+
+AdaptationSet * Period::getAdaptationSet(Streams::Type type) const
+{
+ std::vector<AdaptationSet *>::const_iterator it;
+ for(it = adaptationSets.begin(); it != adaptationSets.end(); it++)
+ {
+ if ( Streams::Stream::mimeToType((*it)->getMimeType()) == type )
+ return *it;
+ }
+ return NULL;
+}
#include <string>
#include "mpd/AdaptationSet.h"
+#include "Streams.hpp"
namespace dash
{
virtual ~Period ();
const std::vector<AdaptationSet *>& getAdaptationSets () const;
+ const std::vector<AdaptationSet *> getAdaptationSets (Streams::Type) const;
+ AdaptationSet * getAdaptationSet (Streams::Type) const;
void addAdaptationSet (AdaptationSet *AdaptationSet);
private: