Commit 26146547 authored by François Cartegnie's avatar François Cartegnie 🤞

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

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