Commit 26146547 authored by Francois Cartegnie's avatar Francois Cartegnie

demux: adaptative: probe format when missing and container switch (hls)

parent 6d18161d
...@@ -75,7 +75,7 @@ bool PlaylistManager::start(demux_t *demux) ...@@ -75,7 +75,7 @@ bool PlaylistManager::start(demux_t *demux)
const BaseAdaptationSet *set = period->getAdaptationSet(type); const BaseAdaptationSet *set = period->getAdaptationSet(type);
if(set) if(set)
{ {
streams[type] = new (std::nothrow) Stream(type, set->getStreamFormat()); streams[type] = new (std::nothrow) Stream(demux, type, set->getStreamFormat());
if(!streams[type]) if(!streams[type])
continue; continue;
AbstractAdaptationLogic *logic = createLogic(logicType); AbstractAdaptationLogic *logic = createLogic(logicType);
...@@ -91,7 +91,7 @@ bool PlaylistManager::start(demux_t *demux) ...@@ -91,7 +91,7 @@ bool PlaylistManager::start(demux_t *demux)
{ {
if(!tracker || !streamOutputFactory) if(!tracker || !streamOutputFactory)
throw VLC_ENOMEM; throw VLC_ENOMEM;
streams[type]->create(demux, logic, tracker, streamOutputFactory); streams[type]->create(logic, tracker, streamOutputFactory);
} catch (int) { } catch (int) {
delete streams[type]; delete streams[type];
delete logic; delete logic;
......
...@@ -40,3 +40,8 @@ bool StreamFormat::operator ==(const StreamFormat &other) const ...@@ -40,3 +40,8 @@ bool StreamFormat::operator ==(const StreamFormat &other) const
{ {
return formatid == other.formatid; return formatid == other.formatid;
} }
bool StreamFormat::operator !=(const StreamFormat &other) const
{
return formatid != other.formatid;
}
...@@ -32,6 +32,7 @@ namespace adaptative ...@@ -32,6 +32,7 @@ namespace adaptative
~StreamFormat(); ~StreamFormat();
operator unsigned() const; operator unsigned() const;
bool operator==(const StreamFormat &) const; bool operator==(const StreamFormat &) const;
bool operator!=(const StreamFormat &) const;
private: private:
unsigned formatid; unsigned formatid;
......
...@@ -31,13 +31,9 @@ using namespace adaptative; ...@@ -31,13 +31,9 @@ using namespace adaptative;
using namespace adaptative::http; using namespace adaptative::http;
using namespace adaptative::logic; using namespace adaptative::logic;
Stream::Stream(const StreamType type, const StreamFormat &format) Stream::Stream(demux_t * demux_,const StreamType type_, const StreamFormat &format_)
{
init(type, format);
}
void Stream::init(const StreamType type_, const StreamFormat &format_)
{ {
p_demux = demux_;
type = type_; type = type_;
format = format_; format = format_;
output = NULL; output = NULL;
...@@ -45,6 +41,7 @@ void Stream::init(const StreamType type_, const StreamFormat &format_) ...@@ -45,6 +41,7 @@ void Stream::init(const StreamType type_, const StreamFormat &format_)
currentChunk = NULL; currentChunk = NULL;
eof = false; eof = false;
segmentTracker = NULL; segmentTracker = NULL;
streamOutputFactory = NULL;
} }
Stream::~Stream() Stream::~Stream()
...@@ -69,22 +66,23 @@ StreamType Stream::mimeToType(const std::string &mime) ...@@ -69,22 +66,23 @@ StreamType Stream::mimeToType(const std::string &mime)
return mimetype; return mimetype;
} }
void Stream::create(demux_t *demux, AbstractAdaptationLogic *logic, void Stream::create(AbstractAdaptationLogic *logic, SegmentTracker *tracker,
SegmentTracker *tracker, const AbstractStreamOutputFactory *factory) const AbstractStreamOutputFactory *factory)
{ {
updateFormat(demux, format, factory);
adaptationLogic = logic; adaptationLogic = logic;
segmentTracker = tracker; segmentTracker = tracker;
streamOutputFactory = factory;
updateFormat(format);
} }
void Stream::updateFormat(demux_t *demux, StreamFormat &newformat, const AbstractStreamOutputFactory *factory) void Stream::updateFormat(StreamFormat &newformat)
{ {
if( format == newformat && output ) if( format == newformat && output )
return; return;
delete output; delete output;
format = newformat; format = newformat;
output = factory->create(demux, format); output = streamOutputFactory->create(p_demux, format);
if(!output) if(!output)
throw VLC_EGENERIC; throw VLC_EGENERIC;
} }
...@@ -218,6 +216,13 @@ size_t Stream::read(HTTPConnectionManager *connManager) ...@@ -218,6 +216,13 @@ size_t Stream::read(HTTPConnectionManager *connManager)
adaptationLogic->updateDownloadRate(block->i_buffer, time); adaptationLogic->updateDownloadRate(block->i_buffer, time);
chunk->onDownload(&block); chunk->onDownload(&block);
StreamFormat chunkStreamFormat = chunk->getStreamFormat();
if(output && chunkStreamFormat != output->getStreamFormat())
{
msg_Info(p_demux, "Changing stream format");
updateFormat(chunkStreamFormat);
}
if (chunk->getBytesToRead() == 0) if (chunk->getBytesToRead() == 0)
{ {
chunk->getConnection()->releaseChunk(); chunk->getConnection()->releaseChunk();
...@@ -268,11 +273,17 @@ void Stream::prune() ...@@ -268,11 +273,17 @@ void Stream::prune()
segmentTracker->pruneFromCurrent(); segmentTracker->pruneFromCurrent();
} }
AbstractStreamOutput::AbstractStreamOutput(demux_t *demux) AbstractStreamOutput::AbstractStreamOutput(demux_t *demux, const StreamFormat &format_)
{ {
realdemux = demux; realdemux = demux;
pcr = VLC_TS_0; pcr = VLC_TS_0;
group = 0; group = 0;
format = format_;
}
const StreamFormat & AbstractStreamOutput::getStreamFormat() const
{
return format;
} }
AbstractStreamOutput::~AbstractStreamOutput() AbstractStreamOutput::~AbstractStreamOutput()
...@@ -289,8 +300,8 @@ int AbstractStreamOutput::getGroup() const ...@@ -289,8 +300,8 @@ int AbstractStreamOutput::getGroup() const
return group; return group;
} }
BaseStreamOutput::BaseStreamOutput(demux_t *demux, const std::string &name) : BaseStreamOutput::BaseStreamOutput(demux_t *demux, const StreamFormat &format, const std::string &name) :
AbstractStreamOutput(demux) AbstractStreamOutput(demux, format)
{ {
this->name = name; this->name = name;
seekable = true; seekable = true;
......
...@@ -61,13 +61,13 @@ namespace adaptative ...@@ -61,13 +61,13 @@ namespace adaptative
class Stream class Stream
{ {
public: public:
Stream(const StreamType, const StreamFormat &); Stream(demux_t *, const StreamType, const StreamFormat &);
~Stream(); ~Stream();
bool operator==(const Stream &) const; bool operator==(const Stream &) const;
static StreamType mimeToType(const std::string &mime); static StreamType mimeToType(const std::string &mime);
void create(demux_t *, AbstractAdaptationLogic *, void create(AbstractAdaptationLogic *, SegmentTracker *,
SegmentTracker *, const AbstractStreamOutputFactory *); const AbstractStreamOutputFactory *);
void updateFormat(demux_t *, StreamFormat &, const AbstractStreamOutputFactory *); void updateFormat(StreamFormat &);
bool isEOF() const; bool isEOF() const;
mtime_t getPCR() const; mtime_t getPCR() const;
mtime_t getFirstDTS() const; mtime_t getFirstDTS() const;
...@@ -82,8 +82,8 @@ namespace adaptative ...@@ -82,8 +82,8 @@ namespace adaptative
private: private:
SegmentChunk *getChunk(); SegmentChunk *getChunk();
void init(const StreamType, const StreamFormat &);
size_t read(HTTPConnectionManager *); size_t read(HTTPConnectionManager *);
demux_t *p_demux;
StreamType type; StreamType type;
StreamFormat format; StreamFormat format;
AbstractStreamOutput *output; AbstractStreamOutput *output;
...@@ -91,14 +91,17 @@ namespace adaptative ...@@ -91,14 +91,17 @@ namespace adaptative
SegmentTracker *segmentTracker; SegmentTracker *segmentTracker;
SegmentChunk *currentChunk; SegmentChunk *currentChunk;
bool eof; bool eof;
const AbstractStreamOutputFactory *streamOutputFactory;
}; };
class AbstractStreamOutput class AbstractStreamOutput
{ {
public: public:
AbstractStreamOutput(demux_t *); AbstractStreamOutput(demux_t *, const StreamFormat &);
virtual ~AbstractStreamOutput(); virtual ~AbstractStreamOutput();
const StreamFormat & getStreamFormat() const;
virtual void pushBlock(block_t *) = 0; virtual void pushBlock(block_t *) = 0;
virtual mtime_t getPCR() const; virtual mtime_t getPCR() const;
virtual mtime_t getFirstDTS() const = 0; virtual mtime_t getFirstDTS() const = 0;
...@@ -114,6 +117,9 @@ namespace adaptative ...@@ -114,6 +117,9 @@ namespace adaptative
demux_t *realdemux; demux_t *realdemux;
mtime_t pcr; mtime_t pcr;
int group; int group;
private:
StreamFormat format;
}; };
class AbstractStreamOutputFactory class AbstractStreamOutputFactory
...@@ -126,7 +132,7 @@ namespace adaptative ...@@ -126,7 +132,7 @@ namespace adaptative
class BaseStreamOutput : public AbstractStreamOutput class BaseStreamOutput : public AbstractStreamOutput
{ {
public: public:
BaseStreamOutput(demux_t *, const std::string &); BaseStreamOutput(demux_t *, const StreamFormat &, const std::string &);
virtual ~BaseStreamOutput(); virtual ~BaseStreamOutput();
virtual void pushBlock(block_t *); /* reimpl */ virtual void pushBlock(block_t *); /* reimpl */
virtual mtime_t getFirstDTS() const; /* reimpl */ virtual mtime_t getFirstDTS() const; /* reimpl */
......
...@@ -19,9 +19,11 @@ ...@@ -19,9 +19,11 @@
*****************************************************************************/ *****************************************************************************/
#include "SegmentChunk.hpp" #include "SegmentChunk.hpp"
#include "Segment.h" #include "Segment.h"
#include "BaseRepresentation.h"
#include <cassert> #include <cassert>
using namespace adaptative::playlist; using namespace adaptative::playlist;
using namespace adaptative;
SegmentChunk::SegmentChunk(ISegment *segment_, const std::string &url) : SegmentChunk::SegmentChunk(ISegment *segment_, const std::string &url) :
Chunk(url) Chunk(url)
...@@ -46,3 +48,11 @@ void SegmentChunk::onDownload(block_t **pp_block) ...@@ -46,3 +48,11 @@ void SegmentChunk::onDownload(block_t **pp_block)
{ {
segment->onChunkDownload(pp_block, this, rep); segment->onChunkDownload(pp_block, this, rep);
} }
StreamFormat SegmentChunk::getStreamFormat() const
{
if(rep)
return rep->getStreamFormat();
else
return StreamFormat();
}
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <string> #include <string>
#include "ICanonicalUrl.hpp" #include "ICanonicalUrl.hpp"
#include "../http/Chunk.h" #include "../http/Chunk.h"
#include "../StreamFormat.hpp"
namespace adaptative namespace adaptative
{ {
...@@ -40,6 +41,7 @@ namespace adaptative ...@@ -40,6 +41,7 @@ namespace adaptative
virtual ~SegmentChunk(); virtual ~SegmentChunk();
void setRepresentation(BaseRepresentation *); void setRepresentation(BaseRepresentation *);
virtual void onDownload(block_t **); // reimpl virtual void onDownload(block_t **); // reimpl
StreamFormat getStreamFormat() const;
protected: protected:
ISegment *segment; ISegment *segment;
......
...@@ -50,10 +50,10 @@ AbstractStreamOutput *DASHStreamOutputFactory::create(demux_t *demux, const Stre ...@@ -50,10 +50,10 @@ AbstractStreamOutput *DASHStreamOutputFactory::create(demux_t *demux, const Stre
switch(fmt) switch(fmt)
{ {
case DASHStreamFormat::MP4: case DASHStreamFormat::MP4:
return new BaseStreamOutput(demux, "mp4"); return new BaseStreamOutput(demux, format, "mp4");
case DASHStreamFormat::MPEG2TS: case DASHStreamFormat::MPEG2TS:
return new BaseStreamOutput(demux, "ts"); return new BaseStreamOutput(demux, format, "ts");
} }
return NULL; return NULL;
} }
......
...@@ -40,9 +40,14 @@ AbstractStreamOutput *HLSStreamOutputFactory::create(demux_t *demux, const Strea ...@@ -40,9 +40,14 @@ AbstractStreamOutput *HLSStreamOutputFactory::create(demux_t *demux, const Strea
unsigned fmt = format; unsigned fmt = format;
switch(fmt) switch(fmt)
{ {
case HLSStreamFormat::PACKEDAAC:
return new BaseStreamOutput(demux, format, "any");
break;
default: default:
case HLSStreamFormat::UNKNOWN:
case HLSStreamFormat::MPEG2TS: case HLSStreamFormat::MPEG2TS:
return new BaseStreamOutput(demux, "ts"); return new BaseStreamOutput(demux, format, "ts");
} }
return NULL; return NULL;
} }
......
...@@ -30,7 +30,23 @@ namespace hls ...@@ -30,7 +30,23 @@ namespace hls
class HLSStreamFormat : public StreamFormat class HLSStreamFormat : public StreamFormat
{ {
public: public:
static const unsigned MPEG2TS = StreamFormat::UNSUPPORTED + 1; static const unsigned UNKNOWN = StreamFormat::UNSUPPORTED + 1; /* will probe */
static const unsigned MPEG2TS = StreamFormat::UNSUPPORTED + 2;
static const unsigned PACKEDAAC = StreamFormat::UNSUPPORTED + 3;
static StreamFormat mimeToFormat(const std::string &mime)
{
std::string::size_type pos = mime.find("/");
if(pos != std::string::npos)
{
std::string tail = mime.substr(pos + 1);
if(tail == "aac")
return StreamFormat(HLSStreamFormat::PACKEDAAC);
else if (tail == "mp2t")
return StreamFormat(HLSStreamFormat::MPEG2TS);
}
return StreamFormat();
}
}; };
} }
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
*****************************************************************************/ *****************************************************************************/
#include "HLSSegment.hpp" #include "HLSSegment.hpp"
#include "../adaptative/playlist/SegmentChunk.hpp" #include "../adaptative/playlist/SegmentChunk.hpp"
#include "../adaptative/playlist/BaseRepresentation.h"
#include "../HLSStreamFormat.hpp"
#include <vlc_common.h> #include <vlc_common.h>
#include <vlc_block.h> #include <vlc_block.h>
...@@ -50,9 +52,27 @@ HLSSegment::~HLSSegment() ...@@ -50,9 +52,27 @@ HLSSegment::~HLSSegment()
#endif #endif
} }
void HLSSegment::onChunkDownload(block_t **pp_block, SegmentChunk *chunk, BaseRepresentation *) void HLSSegment::checkFormat(block_t *p_block, SegmentChunk *, BaseRepresentation *rep)
{
if(rep->getStreamFormat() == StreamFormat(HLSStreamFormat::UNKNOWN))
{
if(p_block->i_buffer > 3 && !memcmp(p_block->p_buffer, "ID3", 3))
{
rep->setMimeType("audio/aac");
}
else
{
rep->setMimeType("video/mp2t");
}
}
}
void HLSSegment::onChunkDownload(block_t **pp_block, SegmentChunk *chunk, BaseRepresentation *rep)
{ {
block_t *p_block = *pp_block; block_t *p_block = *pp_block;
checkFormat(p_block, chunk, rep);
#ifdef HAVE_GCRYPT #ifdef HAVE_GCRYPT
if(encryption.method == SegmentEncryption::AES_128) if(encryption.method == SegmentEncryption::AES_128)
{ {
......
...@@ -61,6 +61,7 @@ namespace hls ...@@ -61,6 +61,7 @@ namespace hls
protected: protected:
virtual void onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *); /* reimpl */ virtual void onChunkDownload(block_t **, SegmentChunk *, BaseRepresentation *); /* reimpl */
void checkFormat(block_t *, SegmentChunk *, BaseRepresentation *);
uint64_t sequence; uint64_t sequence;
SegmentEncryption encryption; SegmentEncryption encryption;
......
...@@ -45,7 +45,10 @@ Representation::~Representation () ...@@ -45,7 +45,10 @@ Representation::~Representation ()
StreamFormat Representation::getStreamFormat() const StreamFormat Representation::getStreamFormat() const
{ {
return StreamFormat(HLSStreamFormat::MPEG2TS); if(getMimeType().empty())
return StreamFormat(HLSStreamFormat::UNKNOWN);
else
return HLSStreamFormat::mimeToFormat(getMimeType());
} }
bool Representation::isLive() const bool Representation::isLive() const
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment