Commit 916065b0 authored by François Cartegnie's avatar François Cartegnie 🤞

demux: adaptative: merge restart & discontinuity states

And add implicit discontinuity on format change.
Use only tracker events to change state (will need to move currentchunk away)
parent dd9a9051
......@@ -22,16 +22,17 @@
#include "playlist/BaseRepresentation.h"
#include "playlist/BaseAdaptationSet.h"
#include "playlist/Segment.h"
#include "playlist/SegmentChunk.hpp"
#include "logic/AbstractAdaptationLogic.h"
using namespace adaptative;
using namespace adaptative::logic;
using namespace adaptative::playlist;
SegmentTrackerEvent::SegmentTrackerEvent(ISegment *s)
SegmentTrackerEvent::SegmentTrackerEvent(SegmentChunk *s)
{
type = DISCONTINUITY;
u.discontinuity.s = s;
u.discontinuity.sc = s;
}
SegmentTrackerEvent::SegmentTrackerEvent(BaseRepresentation *prev, BaseRepresentation *next)
......@@ -41,6 +42,12 @@ SegmentTrackerEvent::SegmentTrackerEvent(BaseRepresentation *prev, BaseRepresent
u.switching.next = next;
}
SegmentTrackerEvent::SegmentTrackerEvent(const StreamFormat *fmt)
{
type = FORMATCHANGE;
u.format.f = fmt;
}
SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, BaseAdaptationSet *adaptSet)
{
count = 0;
......@@ -50,6 +57,7 @@ SegmentTracker::SegmentTracker(AbstractAdaptationLogic *logic_, BaseAdaptationSe
prevRepresentation = NULL;
setAdaptationLogic(logic_);
adaptationSet = adaptSet;
format = StreamFormat::UNSUPPORTED;
}
SegmentTracker::~SegmentTracker()
......@@ -70,6 +78,7 @@ void SegmentTracker::reset()
init_sent = false;
index_sent = false;
initializing = true;
format = StreamFormat::UNSUPPORTED;
}
SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed, HTTPConnectionManager *connManager)
......@@ -98,6 +107,7 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed, HTTPConnectionM
if ( rep == NULL )
return NULL;
if(rep != prevRepresentation)
{
notify(SegmentTrackerEvent(prevRepresentation, rep));
......@@ -129,11 +139,6 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed, HTTPConnectionM
bool b_gap = false;
segment = rep->getNextSegment(BaseRepresentation::INFOTYPE_MEDIA, count, &count, &b_gap);
if(b_gap && count)
{
notify(SegmentTrackerEvent(segment));
}
if(!segment)
{
reset();
......@@ -147,6 +152,19 @@ SegmentChunk * SegmentTracker::getNextChunk(bool switch_allowed, HTTPConnectionM
if(chunk)
count++;
/* We need to check segment/chunk format changes, as we can't rely on representation's (HLS)*/
if(format != chunk->getStreamFormat())
{
format = chunk->getStreamFormat();
notify(SegmentTrackerEvent(&format));
}
/* Handle both implicit and explicit discontinuities */
if( (b_gap && count) || (chunk && chunk->discontinuity) )
{
notify(SegmentTrackerEvent(chunk));
}
return chunk;
}
......
......@@ -20,6 +20,8 @@
#ifndef SEGMENTTRACKER_HPP
#define SEGMENTTRACKER_HPP
#include <StreamFormat.hpp>
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
......@@ -44,7 +46,6 @@ namespace adaptative
class BaseAdaptationSet;
class BaseRepresentation;
class SegmentChunk;
class ISegment;
}
using namespace playlist;
......@@ -54,24 +55,30 @@ namespace adaptative
class SegmentTrackerEvent
{
public:
SegmentTrackerEvent(ISegment *);
SegmentTrackerEvent(SegmentChunk *);
SegmentTrackerEvent(BaseRepresentation *, BaseRepresentation *);
SegmentTrackerEvent(const StreamFormat *);
enum
{
DISCONTINUITY,
SWITCHING,
FORMATCHANGE,
} type;
union
{
struct
{
ISegment *s;
SegmentChunk *sc;
} discontinuity;
struct
{
BaseRepresentation *prev;
BaseRepresentation *next;
} switching;
struct
{
const StreamFormat *f;
} format;
} u;
};
......@@ -103,6 +110,7 @@ namespace adaptative
bool index_sent;
bool init_sent;
uint64_t count;
StreamFormat format;
AbstractAdaptationLogic *logic;
BaseAdaptationSet *adaptationSet;
BaseRepresentation *prevRepresentation;
......
......@@ -20,8 +20,8 @@
#include "Streams.hpp"
#include "http/HTTPConnection.hpp"
#include "http/HTTPConnectionManager.h"
#include "playlist/BaseRepresentation.h"
#include "playlist/SegmentChunk.hpp"
#include "SegmentTracker.hpp"
#include "plumbing/SourceStream.hpp"
#include "plumbing/CommandsQueue.hpp"
#include "tools/Debug.hpp"
......@@ -39,7 +39,6 @@ AbstractStream::AbstractStream(demux_t * demux_, const StreamFormat &format_)
dead = false;
disabled = false;
flushing = false;
restarting_output = false;
discontinuity = false;
segmentTracker = NULL;
pcr = VLC_TS_INVALID;
......@@ -79,6 +78,7 @@ AbstractStream::~AbstractStream()
void AbstractStream::bind(SegmentTracker *tracker, HTTPConnectionManager *conn)
{
segmentTracker = tracker;
segmentTracker->registerListener(this);
connManager = conn;
}
......@@ -139,7 +139,6 @@ bool AbstractStream::seekAble() const
{
return (demuxer &&
!fakeesout->restarting() &&
!restarting_output &&
!discontinuity &&
!flushing );
}
......@@ -225,11 +224,10 @@ AbstractStream::status AbstractStream::demux(mtime_t nz_deadline, bool send)
if(!demuxer && !startDemux())
{
/* If demux fails because of probing failure / wrong format*/
if(restarting_output)
if(discontinuity)
{
msg_Dbg( p_realdemux, "Flushing on format change" );
prepareFormatChange();
restarting_output = false;
discontinuity = false;
flushing = true;
return AbstractStream::status_buffering;
......@@ -243,11 +241,10 @@ AbstractStream::status AbstractStream::demux(mtime_t nz_deadline, bool send)
/* need to read, demuxer still buffering, ... */
if(demuxer->demux(nz_deadline) != VLC_DEMUXER_SUCCESS)
{
if(restarting_output || discontinuity)
if(discontinuity)
{
msg_Dbg( p_realdemux, "Flushing on discontinuity" );
prepareFormatChange();
restarting_output = false;
discontinuity = false;
flushing = true;
return AbstractStream::status_buffering;
......@@ -281,35 +278,19 @@ AbstractStream::status AbstractStream::demux(mtime_t nz_deadline, bool send)
block_t * AbstractStream::readNextBlock(size_t toread)
{
if (currentChunk == NULL)
{
if(!eof)
currentChunk = segmentTracker->getNextChunk(!fakeesout->restarting(), connManager);
if (currentChunk == NULL)
{
eof = true;
return NULL;
}
}
if (currentChunk == NULL && !eof)
currentChunk = segmentTracker->getNextChunk(!fakeesout->restarting(), connManager);
if(format != currentChunk->getStreamFormat())
if(discontinuity)
{
/* Force stream to end for this call */
msg_Info(p_realdemux, "Changing stream format %u->%u",
(unsigned)format, (unsigned)currentChunk->getStreamFormat());
restarting_output = true;
format = currentChunk->getStreamFormat();
/* Next stream will use current unused chunk */
msg_Info(p_realdemux, "Encountered discontinuity");
/* Force stream/demuxer to end for this call */
return NULL;
}
if(currentChunk->discontinuity)
if(currentChunk == NULL)
{
discontinuity = true;
currentChunk->discontinuity = false;
msg_Info(p_realdemux, "Encountered discontinuity");
eof = true;
return NULL;
}
......@@ -387,3 +368,30 @@ void AbstractStream::fillExtraFMTInfo( es_format_t *p_fmt ) const
p_fmt->psz_description = strdup(description.c_str());
}
void AbstractStream::trackerEvent(const SegmentTrackerEvent &event)
{
switch(event.type)
{
case SegmentTrackerEvent::DISCONTINUITY:
discontinuity = true;
break;
case SegmentTrackerEvent::FORMATCHANGE:
/* Check if our current demux is still valid */
if(*event.u.format.f != format)
{
/* Format has changed between segments, we need to drain and change demux */
msg_Info(p_realdemux, "Changing stream format %u->%u",
(unsigned)format, (unsigned)*event.u.format.f);
format = *event.u.format.f;
/* This is an implict discontinuity */
discontinuity = true;
}
break;
case SegmentTrackerEvent::SWITCHING:
default:
break;
}
}
......@@ -27,6 +27,7 @@
#include <vlc_common.h>
#include "StreamFormat.hpp"
#include "ChunksSource.hpp"
#include "SegmentTracker.hpp"
#include "plumbing/Demuxer.hpp"
#include "plumbing/SourceStream.hpp"
......@@ -52,7 +53,8 @@ namespace adaptative
using namespace playlist;
class AbstractStream : public ChunksSource,
public ExtraFMTInfoInterface
public ExtraFMTInfoInterface,
public SegmentTrackerListenerInterface
{
public:
AbstractStream(demux_t *, const StreamFormat &);
......@@ -80,6 +82,7 @@ namespace adaptative
virtual block_t *readNextBlock(size_t); /* impl */
virtual void fillExtraFMTInfo( es_format_t * ) const; /* impl */
virtual void trackerEvent(const SegmentTrackerEvent &); /* impl */
protected:
virtual block_t *checkBlock(block_t *, bool) = 0;
......@@ -89,7 +92,6 @@ namespace adaptative
virtual void prepareFormatChange();
bool restarting_output;
bool discontinuity;
Demuxer *syncdemux;
......
......@@ -120,13 +120,13 @@ block_t * HLSStream::checkBlock(block_t *p_block, bool b_first)
return p_block;
}
AbstractStream * HLSStreamFactory::create(demux_t *realdemux, const StreamFormat &format,
AbstractStream * HLSStreamFactory::create(demux_t *realdemux, const StreamFormat &,
SegmentTracker *tracker, HTTPConnectionManager *manager) const
{
HLSStream *stream;
try
{
stream = new HLSStream(realdemux, format);
stream = new HLSStream(realdemux, StreamFormat(StreamFormat::UNKNOWN));
} catch (int) {
return NULL;
}
......
......@@ -91,7 +91,8 @@ void Representation::debug(vlc_object_t *obj, int indent) const
if(!b_loaded)
{
std::string text(indent + 1, ' ');
text.append(" (not loaded)");
text.append(" (not loaded) ");
text.append(getStreamFormat().str());
msg_Dbg(obj, "%s", text.c_str());
}
}
......
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