SegmentInformation.cpp 20 KB
Newer Older
1 2 3
/*
 * SegmentInformation.cpp
 *****************************************************************************
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
4
 * Copyright (C) 2014 - VideoLAN and VLC Authors
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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.
 *****************************************************************************/
20 21 22 23
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

24 25 26 27 28 29
#include "SegmentInformation.hpp"

#include "Segment.h"
#include "SegmentBase.h"
#include "SegmentList.h"
#include "SegmentTemplate.h"
30
#include "SegmentTimeline.h"
31
#include "AbstractPlaylist.hpp"
32
#include "BaseRepresentation.h"
33

34
#include <algorithm>
35
#include <cassert>
36

37
using namespace adaptive::playlist;
38 39

SegmentInformation::SegmentInformation(SegmentInformation *parent_) :
40 41
    ICanonicalUrl( parent_ ),
    TimescaleAble( parent_ )
42 43
{
    parent = parent_;
44
    init();
45 46
}

47
SegmentInformation::SegmentInformation(AbstractPlaylist * parent_) :
48 49
    ICanonicalUrl(parent_),
    TimescaleAble()
50 51
{
    parent = NULL;
52 53 54 55 56
    init();
}

void SegmentInformation::init()
{
57
    baseUrl.Set(NULL);
58 59
    segmentBase = NULL;
    segmentList = NULL;
60
    mediaSegmentTemplate = NULL;
61
    switchpolicy = SWITCH_UNKNOWN;
62 63 64 65 66 67
}

SegmentInformation::~SegmentInformation()
{
    delete segmentBase;
    delete segmentList;
68
    delete mediaSegmentTemplate;
69
    delete baseUrl.Get();
70 71
}

72 73 74 75 76 77 78 79
AbstractPlaylist * SegmentInformation::getPlaylist() const
{
    if(parent)
        return parent->getPlaylist();
    else
        return NULL;
}

80
std::size_t SegmentInformation::getSegments(SegmentInfoType type, std::vector<ISegment *> &retSegments) const
81
{
82
    switch (type)
83
    {
84
        case INFOTYPE_INIT:
85
        {
86
            /* init segments are always single segment */
87 88 89 90 91 92 93 94 95 96 97 98
            if( segmentBase && segmentBase->initialisationSegment.Get() )
            {
                retSegments.push_back( segmentBase->initialisationSegment.Get() );
            }
            else if( segmentList && segmentList->initialisationSegment.Get() )
            {
                retSegments.push_back( segmentList->initialisationSegment.Get() );
            }
            else if( mediaSegmentTemplate && mediaSegmentTemplate->initialisationSegment.Get() )
            {
                retSegments.push_back( mediaSegmentTemplate->initialisationSegment.Get() );
            }
99 100 101 102 103
        }
        break;

        case INFOTYPE_MEDIA:
        {
104
            if( mediaSegmentTemplate )
105
            {
106
                retSegments.push_back( mediaSegmentTemplate );
107
            }
108
            else if ( segmentList && !segmentList->getSegments().empty() )
109
            {
110
                std::vector<ISegment *>::const_iterator it;
111
                for(it=segmentList->getSegments().begin();
112
                    it!=segmentList->getSegments().end(); ++it)
113 114 115 116 117
                {
                    std::vector<ISegment *> list = (*it)->subSegments();
                    retSegments.insert( retSegments.end(), list.begin(), list.end() );
                }
            }
118 119
            else if( segmentBase )
            {
120 121
                std::vector<ISegment *> list = segmentBase->subSegments();
                retSegments.insert( retSegments.end(), list.begin(), list.end() );
122
            }
123
        }
124 125 126 127
        break;

        case INFOTYPE_INDEX:
        {
128 129 130 131 132 133 134 135 136 137
            /* index segments are always single segment */
            if( segmentBase && segmentBase->indexSegment.Get() )
            {
                retSegments.push_back( segmentBase->indexSegment.Get() );
            }
            else if( segmentList && segmentList->indexSegment.Get() )
            {
                retSegments.push_back( segmentList->indexSegment.Get() );
            }
            // templated index ?
138
        }
139 140 141

        default:
        break;
142 143
    }

144
    if( retSegments.empty() && parent )
145
    {
146
        return parent->getSegments( type, retSegments );
147
    }
148
    else
149
    {
150
        return retSegments.size();
151
    }
152 153
}

154
std::size_t SegmentInformation::getAllSegments(std::vector<ISegment *> &retSegments) const
155 156 157
{
    for(int i=0; i<InfoTypeCount; i++)
    {
158
        std::vector<ISegment *> segs;
159 160
        if( getSegments(static_cast<SegmentInfoType>(i), segs) )
            retSegments.insert( retSegments.end(), segs.begin(), segs.end() );
161
    }
162
    return retSegments.size();
163 164
}

165 166
uint64_t SegmentInformation::getLiveStartSegmentNumber(uint64_t def) const
{
167 168
    const mtime_t i_max_buffering = getPlaylist()->getMaxBuffering() +
                                    /* FIXME: add dynamic pts-delay */ CLOCK_FREQ;
169

170 171
    if( mediaSegmentTemplate )
    {
172 173 174 175
        uint64_t start = 0;
        uint64_t end = 0;
        const Timescale timescale = mediaSegmentTemplate->inheritTimescale();

176
        SegmentTimeline *timeline = mediaSegmentTemplate->segmentTimeline.Get();
177
        if( timeline )
178
        {
179 180 181 182 183 184
            start = timeline->minElementNumber();
            end = timeline->maxElementNumber();
            stime_t endtime, duration;
            timeline->getScaledPlaybackTimeDurationBySegmentNumber( end, &endtime, &duration );

            if( endtime + duration <= timescale.ToScaled( i_max_buffering ) )
185
                return start;
186 187 188 189 190 191 192 193 194 195

            uint64_t number = timeline->getElementNumberByScaledPlaybackTime(
                                        endtime + duration - timescale.ToScaled( i_max_buffering ) );
            if( number < start )
                number = start;
            return number;
        }
        /* Else compute, current time and timeshiftdepth based */
        else if( mediaSegmentTemplate->duration.Get() )
        {
196 197 198 199 200
            mtime_t i_delay = getPlaylist()->suggestedPresentationDelay.Get();

            if( i_delay == 0 || i_delay > getPlaylist()->timeShiftBufferDepth.Get() )
                 i_delay = getPlaylist()->timeShiftBufferDepth.Get();

201 202 203
            if( i_delay < getPlaylist()->getMinBuffering() )
                i_delay = getPlaylist()->getMinBuffering();

204 205 206
            const uint64_t startnumber = mediaSegmentTemplate->startNumber.Get();
            end = mediaSegmentTemplate->getCurrentLiveTemplateNumber();

207
            const uint64_t count = timescale.ToScaled( i_delay ) / mediaSegmentTemplate->duration.Get();
208 209 210 211 212 213 214 215 216
            if( startnumber + count >= end )
                start = startnumber;
            else
                start = end - count;

            const uint64_t bufcount = ( 1 + timescale.ToScaled(i_max_buffering) /
                                        mediaSegmentTemplate->duration.Get() );

            return ( end - start > bufcount ) ? end - bufcount : start;
217 218 219 220
        }
    }
    else if ( segmentList && !segmentList->getSegments().empty() )
    {
221
        const Timescale timescale = segmentList->inheritTimescale();
222
        const std::vector<ISegment *> list = segmentList->getSegments();
223 224 225 226 227

        const ISegment *back = list.back();
        const stime_t bufferingstart = back->startTime.Get() + back->duration.Get() - timescale.ToScaled( i_max_buffering );
        uint64_t number;
        if( !segmentList->getSegmentNumberByScaledTime( bufferingstart, &number ) )
228
            return list.front()->getSequenceNumber();
229
        return number;
230 231 232 233
    }
    else if( segmentBase )
    {
        const std::vector<ISegment *> list = segmentBase->subSegments();
234
        if(!list.empty())
235
            return segmentBase->getSequenceNumber();
236 237 238 239 240 241 242 243

        const Timescale timescale = inheritTimescale();
        const ISegment *back = list.back();
        const stime_t bufferingstart = back->startTime.Get() + back->duration.Get() - timescale.ToScaled( i_max_buffering );
        uint64_t number;
        if( !SegmentInfoCommon::getSegmentNumberByScaledTime( list, bufferingstart, &number ) )
            return list.front()->getSequenceNumber();
        return number;
244 245 246 247 248 249 250 251
    }

    if(parent)
        return parent->getLiveStartSegmentNumber(def);
    else
        return def;
}

252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
/* Returns wanted segment, or next in sequence if not found */
ISegment * SegmentInformation::getNextSegment(SegmentInfoType type, uint64_t i_pos,
                                              uint64_t *pi_newpos, bool *pb_gap) const
{
    *pb_gap = false;
    *pi_newpos = i_pos;
    if( type != INFOTYPE_MEDIA )
        return NULL;

    std::vector<ISegment *> retSegments;
    const size_t size = getSegments( type, retSegments );
    if( size )
    {
        std::vector<ISegment *>::const_iterator it;
        for(it = retSegments.begin(); it != retSegments.end(); ++it)
        {
            ISegment *seg = *it;
            if(seg->isTemplate()) /* we don't care about seq number */
            {
                /* Check if we don't exceed timeline */
                MediaSegmentTemplate *templ = dynamic_cast<MediaSegmentTemplate*>(retSegments[0]);
273 274 275 276 277 278 279 280 281 282 283
                SegmentTimeline *timeline = (templ) ? templ->segmentTimeline.Get() : NULL;
                if(timeline)
                {
                    *pi_newpos = std::max(timeline->minElementNumber(), i_pos);
                    if(timeline->maxElementNumber() < i_pos)
                        return NULL;
                }
                else
                {
                    *pi_newpos = i_pos;
                    /* start number */
284
                    *pi_newpos = std::max((uint64_t)templ->startNumber.Get(), i_pos);
285
                }
286 287 288 289 290 291 292 293 294 295 296 297 298 299
                return seg;
            }
            else if(seg->getSequenceNumber() >= i_pos)
            {
                *pi_newpos = seg->getSequenceNumber();
                *pb_gap = (*pi_newpos != i_pos);
                return seg;
            }
        }
    }

    return NULL;
}

300 301
ISegment * SegmentInformation::getSegment(SegmentInfoType type, uint64_t pos) const
{
302
    std::vector<ISegment *> retSegments;
303
    const size_t size = getSegments( type, retSegments );
304
    if( size )
305
    {
306
        if(size == 1 && retSegments[0]->isTemplate())
307
        {
308 309
            MediaSegmentTemplate *templ = dynamic_cast<MediaSegmentTemplate*>(retSegments[0]);
            if(!templ || templ->segmentTimeline.Get() == NULL ||
310 311
               templ->segmentTimeline.Get()->maxElementNumber() > pos)
                return templ;
312
        }
313
        else
314
        {
315 316 317 318 319 320 321 322 323 324 325 326
            std::vector<ISegment *>::const_iterator it;
            for(it = retSegments.begin(); it != retSegments.end(); ++it)
            {
                ISegment *seg = *it;
                if(seg->getSequenceNumber() >= pos)
                {
                    if(seg->getSequenceNumber() == pos)
                        return seg;
                    else
                        return NULL;
                }
            }
327
        }
328 329
    }

330
    return NULL;
331 332
}

333 334
bool SegmentInformation::getSegmentNumberByTime(mtime_t time, uint64_t *ret) const
{
335
    if( mediaSegmentTemplate )
336
    {
337
        const Timescale timescale = mediaSegmentTemplate->inheritTimescale();
338 339 340 341

        SegmentTimeline *timeline = mediaSegmentTemplate->segmentTimeline.Get();
        if(timeline)
        {
342
            time = timescale.ToScaled(time);
343 344 345 346
            *ret = timeline->getElementNumberByScaledPlaybackTime(time);
            return true;
        }

347
        const stime_t duration = mediaSegmentTemplate->duration.Get();
348
        if( duration )
349
        {
350 351 352 353 354 355 356 357 358
            if( getPlaylist()->isLive() )
            {
                *ret = getLiveStartSegmentNumber( mediaSegmentTemplate->startNumber.Get() );
            }
            else
            {
                *ret = mediaSegmentTemplate->startNumber.Get();
                *ret += timescale.ToScaled(time) / duration;
            }
359 360
            return true;
        }
361
    }
362 363
    else if ( segmentList && !segmentList->getSegments().empty() )
    {
364 365
        const Timescale timescale = segmentList->inheritTimescale();
        time = timescale.ToScaled(time);
366
        return segmentList->getSegmentNumberByScaledTime(time, ret);
367 368
    }
    else if( segmentBase )
369
    {
370 371
        const Timescale timescale = inheritTimescale();
        time = timescale.ToScaled(time);
372
        *ret = 0;
373
        const std::vector<ISegment *> list = segmentBase->subSegments();
374
        return SegmentInfoCommon::getSegmentNumberByScaledTime(list, time, ret);
375
    }
376

377 378 379 380
    if(parent)
        return parent->getSegmentNumberByTime(time, ret);
    else
        return false;
381 382
}

383 384
bool SegmentInformation::getPlaybackTimeDurationBySegmentNumber(uint64_t number,
                                                                mtime_t *time, mtime_t *duration) const
385 386 387
{
    SegmentList *segList;
    MediaSegmentTemplate *mediaTemplate;
388

389 390
    if( (mediaTemplate = inheritSegmentTemplate()) )
    {
391 392
        const Timescale timescale = mediaTemplate->inheritTimescale();

393
        stime_t stime, sduration;
394 395
        if(mediaTemplate->segmentTimeline.Get())
        {
396 397
            mediaTemplate->segmentTimeline.Get()->
                getScaledPlaybackTimeDurationBySegmentNumber(number, &stime, &sduration);
398 399 400
        }
        else
        {
401 402
            stime = number * mediaTemplate->duration.Get();
            sduration = mediaTemplate->duration.Get();
403
        }
404 405
        *time = timescale.ToTime(stime);
        *duration = timescale.ToTime(sduration);
406
        return true;
407 408 409
    }
    else if ( (segList = inheritSegmentList()) )
    {
410
        return segList->getPlaybackTimeDurationBySegmentNumber(number, time, duration);
411
    }
412 413
    else
    {
414
        const Timescale timescale = inheritTimescale();
415 416 417
        const ISegment *segment = getSegment(SegmentInfoType::INFOTYPE_MEDIA, number);
        if( segment )
        {
418 419
            *time = timescale.ToTime(segment->startTime.Get());
            *duration = timescale.ToTime(segment->duration.Get());
420 421 422
            return true;
        }
    }
423

424
    return false;
425 426
}

427
SegmentInformation * SegmentInformation::getChildByID(const adaptive::ID &id)
428 429 430 431 432 433 434 435 436 437
{
    std::vector<SegmentInformation *>::const_iterator it;
    for(it=childs.begin(); it!=childs.end(); ++it)
    {
        if( (*it)->getID() == id )
            return *it;
    }
    return NULL;
}

438 439 440 441 442 443 444 445 446
void SegmentInformation::mergeWith(SegmentInformation *updated, mtime_t prunetime)
{
    /* Support Segment List for now */
    if(segmentList && updated->segmentList)
        segmentList->mergeWith(updated->segmentList);

    if(mediaSegmentTemplate && updated->mediaSegmentTemplate)
        mediaSegmentTemplate->mergeWith(updated->mediaSegmentTemplate, prunetime);

447 448
    std::vector<SegmentInformation *>::const_iterator it;
    for(it=childs.begin(); it!=childs.end(); ++it)
449
    {
450 451 452 453
        SegmentInformation *child = *it;
        SegmentInformation *updatedChild = updated->getChildByID(child->getID());
        if(updatedChild)
            child->mergeWith(updatedChild, prunetime);
454
    }
455
    /* FIXME: handle difference */
456 457
}

458 459 460 461 462 463 464 465 466 467 468
void SegmentInformation::mergeWithTimeline(SegmentTimeline *updated)
{
    MediaSegmentTemplate *templ = inheritSegmentTemplate();
    if(templ)
    {
        SegmentTimeline *timeline = templ->segmentTimeline.Get();
        if(timeline)
            timeline->mergeWith(*updated);
    }
}

469 470 471 472 473 474 475 476 477 478 479 480 481
void SegmentInformation::pruneByPlaybackTime(mtime_t time)
{
    if(segmentList)
        segmentList->pruneByPlaybackTime(time);

    if(mediaSegmentTemplate)
        mediaSegmentTemplate->pruneByPlaybackTime(time);

    std::vector<SegmentInformation *>::const_iterator it;
    for(it=childs.begin(); it!=childs.end(); ++it)
        (*it)->pruneByPlaybackTime(time);
}

482 483
void SegmentInformation::pruneBySegmentNumber(uint64_t num)
{
484 485
    assert(dynamic_cast<BaseRepresentation *>(this));

486 487 488
    if(segmentList)
        segmentList->pruneBySegmentNumber(num);

489 490
    if(mediaSegmentTemplate)
         mediaSegmentTemplate->pruneBySequenceNumber(num);
491 492
}

493 494
uint64_t SegmentInformation::translateSegmentNumber(uint64_t num, const SegmentInformation *from) const
{
495 496 497
    mtime_t time, duration;
    if( from->getPlaybackTimeDurationBySegmentNumber(num, &time, &duration) )
        getSegmentNumberByTime(time, &num);
498 499 500
    return num;
}

501
SegmentInformation::SwitchPolicy SegmentInformation::getSwitchPolicy() const
502
{
503 504
    if(switchpolicy == SWITCH_UNKNOWN)
        return (parent) ? parent->getSwitchPolicy() : SWITCH_UNAVAILABLE;
505
    else
506
        return switchpolicy;
507 508
}

509 510 511 512 513 514 515 516
mtime_t SegmentInformation::getPeriodStart() const
{
    if(parent)
        return parent->getPeriodStart();
    else
        return 0;
}

517
void SegmentInformation::appendSegmentList(SegmentList *list, bool restamp)
518
{
519 520
    if(segmentList)
    {
521
        segmentList->mergeWith(list, restamp);
522 523 524 525 526 527
        delete list;
    }
    else
    {
        segmentList = list;
    }
528 529 530 531
}

void SegmentInformation::setSegmentBase(SegmentBase *base)
{
532 533
    if(segmentBase)
        delete segmentBase;
534 535 536
    segmentBase = base;
}

537
void SegmentInformation::setSegmentTemplate(MediaSegmentTemplate *templ)
538
{
539 540 541 542 543
    if(mediaSegmentTemplate)
    {
        mediaSegmentTemplate->mergeWith(templ, 0);
        delete templ;
    }
544 545
    else
        mediaSegmentTemplate = templ;
546 547
}

548
static void insertIntoSegment(std::vector<ISegment *> &seglist, size_t start,
549
                              size_t end, stime_t time, stime_t duration)
550
{
551
    std::vector<ISegment *>::iterator segIt;
552
    for(segIt = seglist.begin(); segIt < seglist.end(); ++segIt)
553
    {
554
        ISegment *segment = *segIt;
555
        if(segment->getClassId() == Segment::CLASSID_SEGMENT &&
556
           (end == 0 || segment->contains(end)))
557
        {
558
            SubSegment *subsegment = new SubSegment(segment, start, (end != 0) ? end : 0);
559
            subsegment->startTime.Set(time);
560
            subsegment->duration.Set(duration);
561 562 563 564 565 566 567 568
            segment->addSubSegment(subsegment);
            break;
        }
    }
}

void SegmentInformation::SplitUsingIndex(std::vector<SplitPoint> &splitlist)
{
569 570
    std::vector<ISegment *> seglist;
    getSegments(INFOTYPE_MEDIA, seglist);
571 572
    size_t prevstart = 0;
    stime_t prevtime = 0;
573
    const Timescale timescale = inheritTimescale();
574

575
    SplitPoint split = {0,0,0};
576
    std::vector<SplitPoint>::const_iterator splitIt;
577
    for(splitIt = splitlist.begin(); splitIt < splitlist.end(); ++splitIt)
578
    {
579 580 581 582
        split = *splitIt;
        if(splitIt != splitlist.begin())
        {
            /* do previous splitpoint */
583
            const stime_t duration = timescale.ToScaled(split.duration);
584
            insertIntoSegment(seglist, prevstart, split.offset - 1, prevtime, duration);
585 586
        }
        prevstart = split.offset;
587
        prevtime = timescale.ToScaled(split.time);
588 589
    }

590 591
    if(splitlist.size() == 1)
    {
592
        const stime_t duration = timescale.ToScaled(split.duration);
593
        insertIntoSegment(seglist, prevstart, 0, prevtime, duration);
594 595
    }
    else if(splitlist.size() > 1)
596
    {
597
        const stime_t duration = timescale.ToScaled(split.duration);
598
        insertIntoSegment(seglist, prevstart, split.offset - 1, prevtime, duration);
599 600 601
    }
}

602
void SegmentInformation::setSwitchPolicy(SegmentInformation::SwitchPolicy policy)
603
{
604
    switchpolicy = policy;
605 606
}

607 608 609 610 611 612 613 614 615 616 617 618 619 620 621
Url SegmentInformation::getUrlSegment() const
{
    if(baseUrl.Get() && baseUrl.Get()->hasScheme())
    {
        return *(baseUrl.Get());
    }
    else
    {
        Url ret = getParentUrlSegment();
        if (baseUrl.Get())
            ret.append(*(baseUrl.Get()));
        return ret;
    }
}

622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
SegmentBase * SegmentInformation::inheritSegmentBase() const
{
    if(segmentBase)
        return segmentBase;
    else if (parent)
        return parent->inheritSegmentBase();
    else
        return NULL;
}

SegmentList * SegmentInformation::inheritSegmentList() const
{
    if(segmentList)
        return segmentList;
    else if (parent)
        return parent->inheritSegmentList();
    else
        return NULL;
}

642
MediaSegmentTemplate * SegmentInformation::inheritSegmentTemplate() const
643
{
644 645
    if(mediaSegmentTemplate)
        return mediaSegmentTemplate;
646
    else if (parent)
647
        return parent->inheritSegmentTemplate();
648 649 650
    else
        return NULL;
}