Update translations from 2.2.x branch
[vlc.git] / modules / demux / adaptive / Streams.cpp
blobecb3efc68b9b911a89755d861f860a131572eeb9
1 /*
2 * Streams.cpp
3 *****************************************************************************
4 * Copyright (C) 2014 - VideoLAN and VLC authors
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
25 #include "Streams.hpp"
26 #include "logic/AbstractAdaptationLogic.h"
27 #include "http/HTTPConnection.hpp"
28 #include "http/HTTPConnectionManager.h"
29 #include "playlist/BaseRepresentation.h"
30 #include "playlist/SegmentChunk.hpp"
31 #include "plumbing/SourceStream.hpp"
32 #include "plumbing/CommandsQueue.hpp"
33 #include "tools/Debug.hpp"
34 #include <vlc_demux.h>
36 #include <algorithm>
38 using namespace adaptive;
39 using namespace adaptive::http;
41 AbstractStream::AbstractStream(demux_t * demux_)
43 p_realdemux = demux_;
44 format = StreamFormat::UNSUPPORTED;
45 currentChunk = NULL;
46 eof = false;
47 dead = false;
48 disabled = false;
49 discontinuity = false;
50 needrestart = false;
51 inrestart = false;
52 segmentTracker = NULL;
53 demuxersource = NULL;
54 commandsqueue = NULL;
55 demuxer = NULL;
56 fakeesout = NULL;
57 last_buffer_status = buffering_lessthanmin;
58 vlc_mutex_init(&lock);
61 bool AbstractStream::init(const StreamFormat &format_, SegmentTracker *tracker, AbstractConnectionManager *conn)
63 /* Don't even try if not supported or already init */
64 if((unsigned)format_ == StreamFormat::UNSUPPORTED || demuxersource)
65 return false;
67 demuxersource = new (std::nothrow) ChunksSourceStream( VLC_OBJECT(p_realdemux), this );
68 if(demuxersource)
70 CommandsFactory *factory = new (std::nothrow) CommandsFactory();
71 if(factory)
73 commandsqueue = new (std::nothrow) CommandsQueue(factory);
74 if(commandsqueue)
76 fakeesout = new (std::nothrow) FakeESOut(p_realdemux->out, commandsqueue);
77 if(fakeesout)
79 /* All successfull */
80 fakeesout->setExtraInfoProvider( this );
81 format = format_;
82 segmentTracker = tracker;
83 segmentTracker->registerListener(this);
84 segmentTracker->notifyBufferingState(true);
85 connManager = conn;
86 return true;
88 delete commandsqueue;
89 commandsqueue = NULL;
91 else
93 delete factory;
96 delete demuxersource;
99 return false;
102 AbstractStream::~AbstractStream()
104 delete currentChunk;
105 if(segmentTracker)
106 segmentTracker->notifyBufferingState(false);
107 delete segmentTracker;
109 delete demuxer;
110 delete demuxersource;
111 delete fakeesout;
112 delete commandsqueue;
114 vlc_mutex_destroy(&lock);
117 void AbstractStream::prepareRestart(bool b_discontinuity)
119 if(demuxer)
121 /* Enqueue Del Commands for all current ES */
122 demuxer->drain();
123 setTimeOffset(true);
124 /* Enqueue Del Commands for all current ES */
125 fakeesout->scheduleAllForDeletion();
126 if(b_discontinuity)
127 fakeesout->schedulePCRReset();
128 commandsqueue->Commit();
129 /* ignoring demuxer's own Del commands */
130 commandsqueue->setDrop(true);
131 delete demuxer;
132 commandsqueue->setDrop(false);
133 demuxer = NULL;
137 void AbstractStream::setLanguage(const std::string &lang)
139 language = lang;
142 void AbstractStream::setDescription(const std::string &desc)
144 description = desc;
147 mtime_t AbstractStream::getPCR() const
149 vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
150 mtime_t pcr = isDisabled() ? VLC_TS_INVALID : commandsqueue->getPCR();
151 vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
152 return pcr;
155 mtime_t AbstractStream::getMinAheadTime() const
157 if(!segmentTracker)
158 return 0;
159 return segmentTracker->getMinAheadTime();
162 mtime_t AbstractStream::getFirstDTS() const
164 mtime_t dts;
165 vlc_mutex_lock(const_cast<vlc_mutex_t *>(&lock));
166 if(isDisabled())
168 dts = VLC_TS_INVALID;
170 else
172 dts = commandsqueue->getFirstDTS();
173 if(dts == VLC_TS_INVALID)
174 dts = commandsqueue->getPCR();
176 vlc_mutex_unlock(const_cast<vlc_mutex_t *>(&lock));
177 return dts;
180 int AbstractStream::esCount() const
182 return fakeesout->esCount();
185 bool AbstractStream::seekAble() const
187 bool restarting = fakeesout->restarting();
188 bool draining = commandsqueue->isDraining();
189 bool eof = commandsqueue->isEOF();
191 msg_Dbg(p_realdemux, "demuxer %p, fakeesout restarting %d, "
192 "discontinuity %d, commandsqueue draining %d, commandsqueue eof %d",
193 static_cast<void *>(demuxer), restarting, discontinuity, draining, eof);
195 if(!demuxer || restarting || discontinuity || (!eof && draining))
197 msg_Warn(p_realdemux, "not seekable");
198 return false;
200 else
202 return true;
206 bool AbstractStream::isSelected() const
208 return fakeesout->hasSelectedEs();
211 bool AbstractStream::reactivate(mtime_t basetime)
213 if(setPosition(basetime, false))
215 setDisabled(false);
216 return true;
218 else
220 eof = true; /* can't reactivate */
221 return false;
225 bool AbstractStream::startDemux()
227 if(demuxer)
228 return false;
230 demuxersource->Reset();
231 demuxer = createDemux(format);
232 if(!demuxer && format != StreamFormat())
233 msg_Err(p_realdemux, "Failed to create demuxer %p %s", (void *)demuxer,
234 format.str().c_str());
236 return !!demuxer;
239 bool AbstractStream::restartDemux()
241 bool b_ret = true;
242 if(!demuxer)
244 b_ret = startDemux();
246 else if(demuxer->needsRestartOnSeek())
248 inrestart = true;
249 /* Push all ES as recycling candidates */
250 fakeesout->recycleAll();
251 /* Restart with ignoring es_Del pushes to queue when terminating demux */
252 commandsqueue->setDrop(true);
253 demuxer->destroy();
254 commandsqueue->setDrop(false);
255 b_ret = demuxer->create();
256 inrestart = false;
258 else
260 commandsqueue->Commit();
262 return b_ret;
265 void AbstractStream::setDisabled(bool b)
267 if(disabled != b)
268 segmentTracker->notifyBufferingState(!b);
269 disabled = b;
272 bool AbstractStream::isDisabled() const
274 return dead || disabled;
277 bool AbstractStream::canActivate() const
279 return !dead;
282 bool AbstractStream::decodersDrained()
284 return fakeesout->decodersDrained();
287 AbstractStream::buffering_status AbstractStream::getLastBufferStatus() const
289 return last_buffer_status;
292 mtime_t AbstractStream::getDemuxedAmount() const
294 return commandsqueue->getDemuxedAmount();
297 AbstractStream::buffering_status AbstractStream::bufferize(mtime_t nz_deadline,
298 unsigned i_min_buffering, unsigned i_extra_buffering)
300 last_buffer_status = doBufferize(nz_deadline, i_min_buffering, i_extra_buffering);
301 return last_buffer_status;
304 AbstractStream::buffering_status AbstractStream::doBufferize(mtime_t nz_deadline,
305 unsigned i_min_buffering, unsigned i_extra_buffering)
307 vlc_mutex_lock(&lock);
309 /* Ensure it is configured */
310 if(!segmentTracker || !connManager || dead)
312 vlc_mutex_unlock(&lock);
313 return AbstractStream::buffering_end;
316 /* Disable streams that are not selected (alternate streams) */
317 if(esCount() && !isSelected() && !fakeesout->restarting())
319 setDisabled(true);
320 segmentTracker->reset();
321 commandsqueue->Abort(false);
322 msg_Dbg(p_realdemux, "deactivating %s stream %s",
323 format.str().c_str(), description.c_str());
324 vlc_mutex_unlock(&lock);
325 return AbstractStream::buffering_end;
328 if(commandsqueue->isDraining())
330 vlc_mutex_unlock(&lock);
331 return AbstractStream::buffering_suspended;
334 if(!demuxer)
336 format = segmentTracker->getCurrentFormat();
337 if(!startDemux())
339 /* If demux fails because of probing failure / wrong format*/
340 if(discontinuity)
342 msg_Dbg( p_realdemux, "Draining on format change" );
343 prepareRestart();
344 discontinuity = false;
345 commandsqueue->setDraining();
346 vlc_mutex_unlock(&lock);
347 return AbstractStream::buffering_ongoing;
349 dead = true; /* Prevent further retries */
350 commandsqueue->setEOF(true);
351 vlc_mutex_unlock(&lock);
352 return AbstractStream::buffering_end;
356 const int64_t i_total_buffering = i_min_buffering + i_extra_buffering;
358 mtime_t i_demuxed = commandsqueue->getDemuxedAmount();
359 segmentTracker->notifyBufferingLevel(i_min_buffering, i_demuxed, i_total_buffering);
360 if(i_demuxed < i_total_buffering) /* not already demuxed */
362 if(!segmentTracker->segmentsListReady()) /* Live Streams */
364 vlc_mutex_unlock(&lock);
365 return AbstractStream::buffering_suspended;
368 mtime_t nz_extdeadline = commandsqueue->getBufferingLevel() +
369 (i_total_buffering - commandsqueue->getDemuxedAmount()) / (CLOCK_FREQ/4);
370 nz_deadline = std::max(nz_deadline, nz_extdeadline);
372 /* need to read, demuxer still buffering, ... */
373 vlc_mutex_unlock(&lock);
374 int i_ret = demuxer->demux(nz_deadline);
375 vlc_mutex_lock(&lock);
376 if(i_ret != VLC_DEMUXER_SUCCESS)
378 if(discontinuity || needrestart)
380 msg_Dbg(p_realdemux, "Restarting demuxer");
381 prepareRestart(discontinuity);
382 if(discontinuity)
384 msg_Dbg(p_realdemux, "Draining on discontinuity");
385 commandsqueue->setDraining();
386 discontinuity = false;
388 needrestart = false;
389 vlc_mutex_unlock(&lock);
390 return AbstractStream::buffering_ongoing;
392 commandsqueue->setEOF(true);
393 vlc_mutex_unlock(&lock);
394 return AbstractStream::buffering_end;
396 i_demuxed = commandsqueue->getDemuxedAmount();
397 segmentTracker->notifyBufferingLevel(i_min_buffering, i_demuxed, i_total_buffering);
399 vlc_mutex_unlock(&lock);
401 if(i_demuxed < i_total_buffering) /* need to read more */
403 if(i_demuxed < i_min_buffering)
404 return AbstractStream::buffering_lessthanmin; /* high prio */
405 return AbstractStream::buffering_ongoing;
407 return AbstractStream::buffering_full;
410 AbstractStream::status AbstractStream::dequeue(mtime_t nz_deadline, mtime_t *pi_pcr)
412 vlc_mutex_locker locker(&lock);
414 *pi_pcr = nz_deadline;
416 if(commandsqueue->isDraining())
418 AdvDebug(msg_Dbg(p_realdemux, "Stream %s pcr %" PRId64 " dts %" PRId64 " deadline %" PRId64 " [DRAINING]",
419 description.c_str(), commandsqueue->getPCR(), commandsqueue->getFirstDTS(),
420 nz_deadline));
422 *pi_pcr = commandsqueue->Process(p_realdemux->out, VLC_TS_0 + nz_deadline);
423 if(!commandsqueue->isEmpty())
424 return AbstractStream::status_demuxed;
426 if(!commandsqueue->isEOF())
428 commandsqueue->Abort(true); /* reset buffering level and flags */
429 return AbstractStream::status_discontinuity;
433 if(isDisabled() || commandsqueue->isEOF())
435 *pi_pcr = nz_deadline;
436 return AbstractStream::status_eof;
439 AdvDebug(msg_Dbg(p_realdemux, "Stream %s pcr %" PRId64 " dts %" PRId64 " deadline %" PRId64 " buflevel %" PRId64,
440 description.c_str(), commandsqueue->getPCR(), commandsqueue->getFirstDTS(),
441 nz_deadline, commandsqueue->getBufferingLevel()));
443 if(nz_deadline + VLC_TS_0 <= commandsqueue->getBufferingLevel()) /* demuxed */
445 *pi_pcr = commandsqueue->Process( p_realdemux->out, VLC_TS_0 + nz_deadline );
446 return AbstractStream::status_demuxed;
449 return AbstractStream::status_buffering;
452 block_t * AbstractStream::readNextBlock()
454 if (currentChunk == NULL && !eof)
455 currentChunk = segmentTracker->getNextChunk(!fakeesout->restarting(), connManager);
457 if(discontinuity || needrestart)
459 msg_Info(p_realdemux, "Encountered discontinuity");
460 /* Force stream/demuxer to end for this call */
461 return NULL;
464 if(currentChunk == NULL)
466 eof = true;
467 return NULL;
470 const bool b_segment_head_chunk = (currentChunk->getBytesRead() == 0);
472 block_t *block = currentChunk->readBlock();
473 if(block == NULL)
475 delete currentChunk;
476 currentChunk = NULL;
477 return NULL;
480 if (currentChunk->isEmpty())
482 delete currentChunk;
483 currentChunk = NULL;
486 block = checkBlock(block, b_segment_head_chunk);
488 return block;
491 bool AbstractStream::setPosition(mtime_t time, bool tryonly)
493 if(!seekAble())
494 return false;
496 bool ret = segmentTracker->setPositionByTime(time, demuxer->needsRestartOnSeek(), tryonly);
497 if(!tryonly && ret)
499 // clear eof flag before restartDemux() to prevent readNextBlock() fail
500 eof = false;
501 if(demuxer->needsRestartOnSeek())
503 if(currentChunk)
504 delete currentChunk;
505 currentChunk = NULL;
506 needrestart = false;
508 setTimeOffset(-1);
509 setTimeOffset(segmentTracker->getPlaybackTime());
511 if( !restartDemux() )
513 msg_Info(p_realdemux, "Restart demux failed");
514 eof = true;
515 dead = true;
516 ret = false;
518 else
520 commandsqueue->setEOF(false);
523 else commandsqueue->Abort( true );
525 es_out_Control(p_realdemux->out, ES_OUT_SET_NEXT_DISPLAY_TIME,
526 VLC_TS_0 + time);
528 return ret;
531 mtime_t AbstractStream::getPlaybackTime() const
533 return segmentTracker->getPlaybackTime();
536 void AbstractStream::runUpdates()
538 if(!isDisabled())
539 segmentTracker->updateSelected();
542 void AbstractStream::fillExtraFMTInfo( es_format_t *p_fmt ) const
544 if(!p_fmt->psz_language && !language.empty())
545 p_fmt->psz_language = strdup(language.c_str());
546 if(!p_fmt->psz_description && !description.empty())
547 p_fmt->psz_description = strdup(description.c_str());
550 void AbstractStream::setTimeOffset(mtime_t i_offset)
552 /* Check if we need to set an offset as the demuxer
553 * will start from zero from seek point */
554 if(i_offset < 0) /* reset */
556 fakeesout->setExpectedTimestampOffset(0);
558 else if(demuxer)
560 fakeesout->setExpectedTimestampOffset(i_offset);
564 void AbstractStream::trackerEvent(const SegmentTrackerEvent &event)
566 switch(event.type)
568 case SegmentTrackerEvent::DISCONTINUITY:
569 discontinuity = true;
570 break;
572 case SegmentTrackerEvent::FORMATCHANGE:
573 /* Check if our current demux is still valid */
574 if(*event.u.format.f != format)
576 /* Format has changed between segments, we need to drain and change demux */
577 msg_Info(p_realdemux, "Changing stream format %s -> %s",
578 format.str().c_str(), event.u.format.f->str().c_str());
579 format = *event.u.format.f;
581 /* This is an implict discontinuity */
582 discontinuity = true;
584 break;
586 case SegmentTrackerEvent::SWITCHING:
587 if(demuxer && demuxer->needsRestartOnSwitch() && !inrestart)
589 needrestart = true;
591 break;
593 case SegmentTrackerEvent::SEGMENT_CHANGE:
594 if(demuxer && demuxer->needsRestartOnEachSegment() && !inrestart)
596 needrestart = true;
598 break;
600 default:
601 break;