Example #1
0
size_t IsoffMainParser::parseSegmentList(Node * segListNode, SegmentInformation *info)
{
    size_t total = 0;
    if(segListNode)
    {
        std::vector<Node *> segments = DOMHelper::getElementByTagName(segListNode, "SegmentURL", false);
        SegmentList *list;
        if((list = new (std::nothrow) SegmentList(info)))
        {
            parseInitSegment(DOMHelper::getFirstChildElementByName(segListNode, "Initialization"), list, info);

            if(segListNode->hasAttribute("duration"))
                list->duration.Set(Integer<stime_t>(segListNode->getAttributeValue("duration")));

            if(segListNode->hasAttribute("timescale"))
                list->timescale.Set(Integer<uint64_t>(segListNode->getAttributeValue("timescale")));

            uint64_t nzStartTime = 0;
            std::vector<Node *>::const_iterator it;
            for(it = segments.begin(); it != segments.end(); ++it)
            {
                Node *segmentURL = *it;

                Segment *seg = new (std::nothrow) Segment(info);
                if(!seg)
                    continue;

                std::string mediaUrl = segmentURL->getAttributeValue("media");
                if(!mediaUrl.empty())
                    seg->setSourceUrl(mediaUrl);

                if(segmentURL->hasAttribute("mediaRange"))
                {
                    std::string range = segmentURL->getAttributeValue("mediaRange");
                    size_t pos = range.find("-");
                    seg->setByteRange(atoi(range.substr(0, pos).c_str()), atoi(range.substr(pos + 1, range.size()).c_str()));
                }

                if(list->duration.Get())
                {
                    seg->startTime.Set(nzStartTime);
                    seg->duration.Set(list->duration.Get());
                    nzStartTime += list->duration.Get();
                }

                seg->setSequenceNumber(total);

                list->addSegment(seg);
                total++;
            }

            info->setSegmentList(list);
        }
    }
    return total;
}
Example #2
0
size_t IsoffMainParser::parseSegmentBase(Node * segmentBaseNode, SegmentInformation *info)
{
    size_t list_count = 0;

    if(!segmentBaseNode)
        return 0;

    else if(segmentBaseNode->hasAttribute("indexRange"))
    {
        SegmentList *list = new SegmentList();
        Segment *seg;

        size_t start = 0, end = 0;
        if (std::sscanf(segmentBaseNode->getAttributeValue("indexRange").c_str(), "%zu-%zu", &start, &end) == 2)
        {
            IndexSegment *index = new DashIndexSegment(info);
            index->setByteRange(start, end);
            list->indexSegment.Set(index);
            /* index must be before data, so data starts at index end */
            seg = new Segment(info);
            seg->setByteRange(end + 1, 0);
        }
        else
        {
            seg = new Segment(info);
        }

        list_count++;
        list->addSegment(seg);
        info->setSegmentList(list);

        Node *initSeg = DOMHelper::getFirstChildElementByName(segmentBaseNode, "Initialization");
        if(initSeg)
        {
            SegmentBase *base = new SegmentBase();
            parseInitSegment(initSeg, base, info);
            info->setSegmentBase(base);
        }
    }
    else
    {
        SegmentBase *base = new SegmentBase();
        parseInitSegment(DOMHelper::getFirstChildElementByName(segmentBaseNode, "Initialization"), base, info);
        info->setSegmentBase(base);
    }

    return list_count;
}
Example #3
0
void M3U8Parser::parseSegments(vlc_object_t *p_obj, Representation *rep, const std::list<Tag *> &tagslist)
{
    SegmentList *segmentList = new (std::nothrow) SegmentList(rep);

    rep->setTimescale(100);
    rep->b_loaded = true;

    mtime_t totalduration = 0;
    mtime_t nzStartTime = 0;
    mtime_t absReferenceTime = VLC_TS_INVALID;
    uint64_t sequenceNumber = 0;
    bool discontinuity = false;
    std::size_t prevbyterangeoffset = 0;
    const SingleValueTag *ctx_byterange = NULL;
    SegmentEncryption encryption;
    const ValuesListTag *ctx_extinf = NULL;

    std::list<Tag *>::const_iterator it;
    for(it = tagslist.begin(); it != tagslist.end(); ++it)
    {
        const Tag *tag = *it;
        switch(tag->getType())
        {
            /* using static cast as attribute type permits avoiding class check */
            case SingleValueTag::EXTXMEDIASEQUENCE:
            {
                sequenceNumber = (static_cast<const SingleValueTag*>(tag))->getValue().decimal();
            }
            break;

            case ValuesListTag::EXTINF:
            {
                ctx_extinf = static_cast<const ValuesListTag *>(tag);
            }
            break;

            case SingleValueTag::URI:
            {
                const SingleValueTag *uritag = static_cast<const SingleValueTag *>(tag);
                if(uritag->getValue().value.empty())
                {
                    ctx_extinf = NULL;
                    ctx_byterange = NULL;
                    break;
                }

                HLSSegment *segment = new (std::nothrow) HLSSegment(rep, sequenceNumber++);
                if(!segment)
                    break;

                segment->setSourceUrl(uritag->getValue().value);
                if((unsigned)rep->getStreamFormat() == StreamFormat::UNKNOWN)
                    setFormatFromExtension(rep, uritag->getValue().value);

                if(ctx_extinf)
                {
                    if(ctx_extinf->getAttributeByName("DURATION"))
                    {
                        const mtime_t nzDuration = CLOCK_FREQ * ctx_extinf->getAttributeByName("DURATION")->floatingPoint();
                        segment->duration.Set(ctx_extinf->getAttributeByName("DURATION")->floatingPoint() * (uint64_t) rep->getTimescale());
                        segment->startTime.Set(rep->getTimescale().ToScaled(nzStartTime));
                        nzStartTime += nzDuration;
                        totalduration += nzDuration;

                        if(absReferenceTime > VLC_TS_INVALID)
                        {
                            segment->utcTime = absReferenceTime;
                            absReferenceTime += nzDuration;
                        }
                    }
                    ctx_extinf = NULL;
                }

                segmentList->addSegment(segment);

                if(ctx_byterange)
                {
                    std::pair<std::size_t,std::size_t> range = ctx_byterange->getValue().getByteRange();
                    if(range.first == 0) /* first == size, second = offset */
                        range.first = prevbyterangeoffset;
                    prevbyterangeoffset = range.first + range.second;
                    segment->setByteRange(range.first, prevbyterangeoffset - 1);
                    ctx_byterange = NULL;
                }

                if(discontinuity)
                {
                    segment->discontinuity = true;
                    discontinuity = false;
                }

                if(encryption.method != SegmentEncryption::NONE)
                    segment->setEncryption(encryption);
            }
            break;

            case SingleValueTag::EXTXTARGETDURATION:
                rep->targetDuration = static_cast<const SingleValueTag *>(tag)->getValue().decimal();
                break;

            case SingleValueTag::EXTXPLAYLISTTYPE:
                rep->b_live = (static_cast<const SingleValueTag *>(tag)->getValue().value != "VOD");
                break;

            case SingleValueTag::EXTXBYTERANGE:
                ctx_byterange = static_cast<const SingleValueTag *>(tag);
                break;

            case SingleValueTag::EXTXPROGRAMDATETIME:
                rep->b_consistent = false;
                absReferenceTime = VLC_TS_0 +
                        UTCTime(static_cast<const SingleValueTag *>(tag)->getValue().value).mtime();
                break;

            case AttributesTag::EXTXKEY:
            {
                const AttributesTag *keytag = static_cast<const AttributesTag *>(tag);
                if( keytag->getAttributeByName("METHOD") &&
                    keytag->getAttributeByName("METHOD")->value == "AES-128" &&
                    keytag->getAttributeByName("URI") )
                {
                    encryption.method = SegmentEncryption::AES_128;
                    encryption.key.clear();

                    Url keyurl(keytag->getAttributeByName("URI")->quotedString());
                    if(!keyurl.hasScheme())
                    {
                        keyurl.prepend(Helper::getDirectoryPath(rep->getPlaylistUrl().toString()).append("/"));
                    }

                    block_t *p_block = Retrieve::HTTP(p_obj, keyurl.toString());
                    if(p_block)
                    {
                        if(p_block->i_buffer == 16)
                        {
                            encryption.key.resize(16);
                            memcpy(&encryption.key[0], p_block->p_buffer, 16);
                        }
                        block_Release(p_block);
                    }

                    if(keytag->getAttributeByName("IV"))
                    {
                        encryption.iv.clear();
                        encryption.iv = keytag->getAttributeByName("IV")->hexSequence();
                    }
                }
                else
                {
                    /* unsupported or invalid */
                    encryption.method = SegmentEncryption::NONE;
                    encryption.key.clear();
                    encryption.iv.clear();
                }
            }
            break;

            case AttributesTag::EXTXMAP:
            {
                const AttributesTag *keytag = static_cast<const AttributesTag *>(tag);
                const Attribute *uriAttr;
                if(keytag && (uriAttr = keytag->getAttributeByName("URI")) &&
                   !segmentList->initialisationSegment.Get()) /* FIXME: handle discontinuities */
                {
                    InitSegment *initSegment = new (std::nothrow) InitSegment(rep);
                    if(initSegment)
                    {
                        initSegment->setSourceUrl(uriAttr->quotedString());
                        const Attribute *byterangeAttr = keytag->getAttributeByName("BYTERANGE");
                        if(byterangeAttr)
                        {
                            const std::pair<std::size_t,std::size_t> range = byterangeAttr->unescapeQuotes().getByteRange();
                            initSegment->setByteRange(range.first, range.first + range.second - 1);
                        }
                        segmentList->initialisationSegment.Set(initSegment);
                    }
                }
            }
            break;

            case Tag::EXTXDISCONTINUITY:
                discontinuity  = true;
                break;

            case Tag::EXTXENDLIST:
                rep->b_live = false;
                break;
        }
    }

    if(rep->isLive())
    {
        rep->getPlaylist()->duration.Set(0);
    }
    else if(totalduration > rep->getPlaylist()->duration.Get())
    {
        rep->getPlaylist()->duration.Set(totalduration);
    }

    rep->setSegmentList(segmentList);
}