Search in sources :

Example 1 with ContentType

use of com.att.aro.core.videoanalysis.pojo.Manifest.ContentType in project VideoOptimzer by attdevsupport.

the class ManifestBuilderDASH method processEncodedSegment.

public void processEncodedSegment(Manifest newManifest, XmlManifestHelper manifestView, String key) {
    // DASH-VOD EncodedSegmentList
    switchManifestCollection(newManifest, key, manifest.getRequestTime());
    newManifest.setVideoType(VideoType.DASH_ENCODEDSEGMENTLIST);
    MPDEncodedSegment mpdEncodedSegment = (MPDEncodedSegment) manifestView.getManifest();
    DashEncodedSegmentParser dashEncodedSegmentParser = new DashEncodedSegmentParser(mpdEncodedSegment, newManifest, manifestCollection, childManifest);
    List<AdaptationSetESL> adaptationSetList = dashEncodedSegmentParser.getAdaptationSet();
    String[] encodedSegmentDurationList = null;
    Double segmentTimeScale = null;
    /* 
		 * Sort Adaptations by minBandwidth, for the purpose of assigning track numbers.
		 * Video tracks will start with track 0
		 * Audio tracks will start with track 0, also
		 */
    SortedMap<Double, AdaptationSetESL> sortedAdaptationSet;
    Map<String, SortedMap<Double, AdaptationSetESL>> sortedAdaptationSets = new HashMap<>();
    Map<String, Integer> trackMap = new HashMap<>();
    Integer track;
    Double bandWidth;
    for (AdaptationSetESL adaptation : adaptationSetList) {
        List<RepresentationESL> representation = adaptation.getRepresentation();
        if (sortedAdaptationSets.containsKey(adaptation.getContentType())) {
            sortedAdaptationSet = sortedAdaptationSets.get(adaptation.getContentType());
        } else {
            sortedAdaptationSet = new TreeMap<>();
            sortedAdaptationSets.put(adaptation.getContentType(), sortedAdaptationSet);
            trackMap.put(createKey(adaptation), 0);
        }
        if ((bandWidth = adaptation.getMinBandwidth()) == null || bandWidth == 0) {
            bandWidth = Double.MAX_VALUE;
            for (RepresentationESL repSet : representation) {
                if (repSet.getBandwidth() == null) {
                    bandWidth = 1.0;
                    break;
                }
                if (repSet.getBandwidth() < bandWidth) {
                    bandWidth = repSet.getBandwidth();
                }
            }
        }
        sortedAdaptationSet.put(bandWidth, adaptation);
    }
    for (SortedMap<Double, AdaptationSetESL> sortedMap : sortedAdaptationSets.values()) {
        for (AdaptationSetESL adaptation : sortedMap.values()) {
            ContentType contentType = manifest.matchContentType(adaptation.getContentType());
            if (adaptation.getEncodedSegmentDurations() != null && adaptation.getEncodedSegmentDurations().getEncodedSegmentDurationList() != null) {
                segmentTimeScale = StringParse.stringToDouble(adaptation.getEncodedSegmentDurations().getTimescale(), 1);
                encodedSegmentDurationList = adaptation.getEncodedSegmentDurations().getEncodedSegmentDurationList().split(";");
            }
            track = trackMap.get(createKey(adaptation));
            SortedMap<Double, RepresentationESL> sortedRepresentationESL = sortRepresentationByBandwidth(adaptation.getRepresentation());
            for (RepresentationESL representation : sortedRepresentationESL.values()) {
                if (representation.getEncodedSegment() != null) {
                    track++;
                    manifest.setTimeScale(StringParse.stringToDouble(representation.getEncodedSegment().getTimescale(), 1));
                    LOG.debug(String.format("representation.getBandwidth() %d:%s", track, representation.getBandwidth()));
                    generateChildManifestFromEncodedSegmentList(newManifest, contentType, track, representation, encodedSegmentDurationList, segmentTimeScale);
                    if (representation.getRepresentationACC() != null) {
                        // audio
                        childManifest.setChannels(representation.getRepresentationACC().getValue());
                    }
                    addToSegmentManifestCollectionMap(childManifest.getUriName());
                }
            }
            trackMap.put(createKey(adaptation), track);
        }
    }
}
Also used : ContentType(com.att.aro.core.videoanalysis.pojo.Manifest.ContentType) HashMap(java.util.HashMap) DashEncodedSegmentParser(com.att.aro.core.videoanalysis.parsers.DashEncodedSegmentParser) MPDEncodedSegment(com.att.aro.core.videoanalysis.parsers.encodedsegment.MPDEncodedSegment) RepresentationESL(com.att.aro.core.videoanalysis.parsers.encodedsegment.RepresentationESL) SortedMap(java.util.SortedMap) AdaptationSetESL(com.att.aro.core.videoanalysis.parsers.encodedsegment.AdaptationSetESL)

Example 2 with ContentType

use of com.att.aro.core.videoanalysis.pojo.Manifest.ContentType in project VideoOptimzer by attdevsupport.

the class ManifestBuilderDASH method processDashIF.

public void processDashIF(Manifest newManifest, XmlManifestHelper manifestView, String key) {
    // DASH-IF parser implementation
    switchManifestCollection(newManifest, key, manifest.getRequestTime());
    newManifest.setVideoType(VideoType.DASH_IF);
    MPD mpd = (MPD) manifestView.getManifest();
    DashIFParser dashIFParser = new DashIFParser(VideoType.DASH, mpd, newManifest, manifestCollection, childManifest);
    List<AdaptationSet> adaptationList = dashIFParser.getAdaptationSet();
    if (adaptationList != null) {
        int audioQualityId = 0;
        int videoQualityId = 0;
        for (AdaptationSet adaptation : adaptationList) {
            ContentType contentType = manifest.matchContentType(adaptation.getContentType());
            // Sort the representations by bandwidth to assign incremental quality id
            List<Representation> sortedRepresentations = adaptation.getRepresentations().stream().sorted(new Comparator<Representation>() {

                @Override
                public int compare(Representation o1, Representation o2) {
                    if (o1 == null || o2 == null) {
                        return 0;
                    }
                    return o1.getBandwidth().compareTo(o2.getBandwidth());
                }
            }).collect(Collectors.toList());
            for (Representation representation : sortedRepresentations) {
                if (representation.getSegmentBase() != null) {
                    if (representation.getSegmentBase().getTimescale() != null) {
                        // TODO: Setting timescale value for manifest is overwritten every time a child manifest is created for individual representation. \
                        // Timescale should be set on the Child Manifest level. Revisit this some time later.
                        manifest.setTimeScale(representation.getSegmentBase().getTimescale().doubleValue());
                    }
                    // Generate child manifests for each individual representation
                    childManifest = createChildManifest(newManifest, "", representation.getBaseURL());
                    if (ContentType.AUDIO.equals(contentType)) {
                        childManifest.setQuality(++audioQualityId);
                        if (adaptation.getContentType().equals("audio")) {
                            if (representation.getAudioChannelConfiguration() != null) {
                                childManifest.setChannels(representation.getAudioChannelConfiguration().getValue());
                            } else if (adaptation.getAudioChannelConfiguration() != null) {
                                childManifest.setChannels(adaptation.getAudioChannelConfiguration().getValue());
                            }
                        }
                    } else if (ContentType.VIDEO.equals(contentType)) {
                        childManifest.setQuality(++videoQualityId);
                    }
                    childManifest.setBandwidth(representation.getBandwidth());
                    childManifest.setCodecs(representation.getCodecs() != null ? representation.getCodecs() : adaptation.getCodecs());
                    childManifest.setVideo(ContentType.VIDEO.equals(contentType));
                    childManifest.setContentType(contentType);
                    if (representation.getHeight() != null) {
                        childManifest.setPixelHeight(representation.getHeight());
                    }
                    if (representation.getWidth() != null) {
                        childManifest.setPixelWidth(representation.getWidth());
                    }
                    if (representation.getAudioChannelConfiguration() != null) {
                        childManifest.setChannels(representation.getAudioChannelConfiguration().getValue());
                    }
                    // Set first segment info to the child manifest
                    SegmentInfo segmentInfo = new SegmentInfo();
                    segmentInfo.setDuration(0);
                    segmentInfo.setStartTime(0);
                    segmentInfo.setSegmentID(0);
                    segmentInfo.setContentType(contentType);
                    segmentInfo.setVideo(childManifest.isVideo());
                    segmentInfo.setQuality(String.valueOf(childManifest.getQuality()));
                    // Add chunk size for the first initializing segment
                    int chunkSize = 0;
                    if (representation.getSegmentBase().getIndexRange() != null) {
                        chunkSize += calcSizeFromSegmentElement(representation.getSegmentBase().getIndexRange(), false);
                    }
                    if (representation.getSegmentBase().getInitialization() != null) {
                        chunkSize += calcSizeFromSegmentElement(representation.getSegmentBase().getInitialization().getRange(), false);
                    }
                    segmentInfo.setSize(chunkSize);
                    // Add segment to child manifest segment list
                    childManifest.addSegment("0-" + String.valueOf(chunkSize != 0 ? chunkSize - 1 : 0), segmentInfo);
                    masterManifest.getSegUrlMatchDef().add(defineUrlMatching(childManifest.getUriName()));
                    manifestCollection.addToSegmentChildManifestTrie(childManifest.getUriName(), childManifest);
                    addToSegmentManifestCollectionMap(childManifest.getUriName());
                } else if (representation.getSegmentList() != null || representation.getSegmentTemplate() != null) {
                    // TODO: Implement Segment List or Template parser
                    LOG.warn("MPD: Represenation segment base is null but segment list or template is not null!");
                }
            }
        }
    }
}
Also used : MPD(com.att.aro.core.videoanalysis.parsers.dashif.MPD) DashIFParser(com.att.aro.core.videoanalysis.parsers.DashIFParser) ContentType(com.att.aro.core.videoanalysis.pojo.Manifest.ContentType) AdaptationSet(com.att.aro.core.videoanalysis.parsers.dashif.AdaptationSet) Representation(com.att.aro.core.videoanalysis.parsers.dashif.Representation) Comparator(java.util.Comparator)

Example 3 with ContentType

use of com.att.aro.core.videoanalysis.pojo.Manifest.ContentType in project VideoOptimzer by attdevsupport.

the class BufferOccupancyPlot method toolTipGenerator.

public XYToolTipGenerator toolTipGenerator() {
    return new XYToolTipGenerator() {

        @Override
        public String generateToolTip(XYDataset dataset, int series, int item) {
            // Tooltip value
            Number timestamp = dataset.getX(series, item);
            Number bufferSize = dataset.getY(series, item);
            VideoEvent event = videoStream.getByteToolTipDetailMap().get(item).getVideoEvent();
            double segmentID = event.getSegmentID();
            ContentType type = event.getContentType();
            double play = event.getPlayTime();
            return (MessageFormat.format(BUFFEROCCUPANCY_TOOLTIP, String.format("%s", type.toString()), String.format("%.0f", segmentID), String.format("%.2f", (double) bufferSize / (1000 * 1000)), String.format("%.3f", timestamp), String.format("%.3f", play)));
        }
    };
}
Also used : ContentType(com.att.aro.core.videoanalysis.pojo.Manifest.ContentType) XYDataset(org.jfree.data.xy.XYDataset) VideoEvent(com.att.aro.core.videoanalysis.pojo.VideoEvent) XYToolTipGenerator(org.jfree.chart.labels.XYToolTipGenerator)

Example 4 with ContentType

use of com.att.aro.core.videoanalysis.pojo.Manifest.ContentType in project VideoOptimzer by attdevsupport.

the class ManifestBuilderDASH method processSegmentTimeline.

public void processSegmentTimeline(Manifest newManifest, XmlManifestHelper manifestView, String key, boolean isDynamic) {
    // DASH SegmentTimeline
    newManifest.setVideoType(VideoType.DASH_SEGMENTTIMELINE);
    MPDSegmentTimeline mpdSegmentTimeline = (MPDSegmentTimeline) manifestView.getManifest();
    long mediaPresentationDuration = isoConvertDurationTime(mpdSegmentTimeline.getMediaPresentationDuration());
    Pattern nameRegex = Pattern.compile("\\/([^\\/]*)\\/$");
    String[] urlName;
    if ((urlName = stringParse.parse(mpdSegmentTimeline.getBaseURL(), nameRegex)) != null) {
        newManifest.setUrlName(urlName[0]);
    }
    List<PeriodST> periods = mpdSegmentTimeline.getPeriod();
    if (periods.size() > 1) {
        LOG.debug("period count :" + periods.size() + ", " + newManifest.getUriStr());
        return;
    }
    DashSegmentTimelineParser parseDashdynamic = new DashSegmentTimelineParser(mpdSegmentTimeline, newManifest, manifestCollection, childManifest);
    List<AdaptationSetTL> adaptationSetList = parseDashdynamic.getAdaptationSet();
    for (AdaptationSetTL adaptationSet : adaptationSetList) {
        ContentType contentType = manifest.matchContentType(adaptationSet.getContentType());
        if (adaptationSet.getContentType().equals("text")) {
            // skipping Closed Caption for now
            continue;
        }
        SegmentTemplateST segmentTemplate = adaptationSet.getSegmentTemplate();
        SegmentTimeLineST segmentTimelineST = segmentTemplate.getSegmentTimeline();
        List<SegmentST> segmentList;
        if (segmentTimelineST != null && segmentTimelineST.getSegmentList() != null) {
            segmentList = segmentTimelineST.getSegmentList();
        } else {
            segmentList = new ArrayList<>();
        }
        // segment 0 'moov'
        String initialization = segmentTemplate.getInitialization();
        // segment x 'moof'
        String media = segmentTemplate.getMedia();
        Double presentationTimeOffset = StringParse.stringToDouble(segmentTemplate.getPresentationTimeOffset(), 0);
        Double timescale = StringParse.stringToDouble(segmentTemplate.getTimescale(), 1);
        boolean manifestLiveUpdate;
        if (isDynamic && (lastPresentationTimeOffset == -1D || ((Double.compare(lastPresentationTimeOffset, presentationTimeOffset) != 0)))) {
            lastPresentationTimeOffset = presentationTimeOffset;
            switchManifestCollection(newManifest, key, manifest.getRequestTime());
            manifestLiveUpdate = false;
        } else if (isDynamic) {
            manifestLiveUpdate = isDynamic;
            LOG.info("update manifest");
        } else {
            switchManifestCollection(newManifest, key, manifest.getRequestTime());
            manifestLiveUpdate = false;
        }
        manifest.setTimeScale(timescale);
        Integer qualityID = 0;
        for (RepresentationST representation : adaptationSet.getRepresentation()) {
            int segmentID = 0;
            qualityID++;
            String rid = representation.getContentID();
            // generate REGEX for locating Byte position
            String childUriName = media.replaceAll("\\$(RepresentationID)\\$", rid).replaceAll("\\$(Time)\\$", "(\\\\d+)");
            if (manifestLiveUpdate && ((childManifest = manifestCollection.getUriNameChildMap().get(childUriName)) != null)) {
                PatriciaTrie<SegmentInfo> segmentInfoList = childManifest.getSegmentInfoTrie();
                for (String segmentKey : segmentInfoList.keySet()) {
                    SegmentInfo segmentInfo = segmentInfoList.get(segmentKey);
                    int sid = segmentInfo.getSegmentID();
                    if (segmentID < sid) {
                        segmentID = sid + 1;
                    }
                }
            } else {
                // segment 1-end (moof) a regex for all
                childManifest = createChildManifest(newManifest, "", childUriName);
                childManifest.setPixelHeight(StringParse.stringToDouble(representation.getHeight(), 0).intValue());
                childManifest.setPixelWidth(StringParse.stringToDouble(representation.getWidth(), 0).intValue());
                childManifest.setBandwidth(StringParse.stringToDouble(representation.getBandwidth(), 0));
                childManifest.setQuality(qualityID);
                if (!StringUtils.isEmpty(initialization)) {
                    // segment 0 (moov)
                    String moovUriName = initialization.replaceAll("\\$(RepresentationID)\\$", rid);
                    manifestCollection.addToUriNameChildMap(moovUriName, childManifest);
                }
                manifestCollection.addToSegmentChildManifestTrie(childManifest.getUriName(), childManifest);
            }
            String segmentUriName;
            SegmentInfo segmentInfo;
            Double timePos = 0D;
            Double duration = 0D;
            Double repetition = 0D;
            if (segmentList.size() > 0) {
                SegmentST segment0 = segmentList.get(0);
                timePos = StringParse.stringToDouble(segment0.getStartTime(), 0);
                if (childManifest.getInitialStartTime() == -1) {
                    initialStartTime = timePos;
                    childManifest.setInitialStartTime(initialStartTime);
                }
                // segment moov
                segmentInfo = genSegmentInfo(contentType, timescale, qualityID, segmentID, timePos - initialStartTime, 0D);
                segmentUriName = initialization.replaceAll("\\$(.*)\\$", rid);
                LOG.debug(String.format("moov >> %d :%s", segmentID, segmentUriName));
                masterManifest.getSegUrlMatchDef().add(defineUrlMatching(segmentUriName));
                segmentInfo = childManifest.addSegment(segmentUriName, segmentInfo);
                addToSegmentManifestCollectionMap(segmentUriName);
                // segments moof
                segmentID = 1;
                for (SegmentST segment : segmentList) {
                    duration = StringParse.stringToDouble(segment.getDuration(), 0);
                    repetition = StringParse.stringToDouble(segment.getRepeat(), 0);
                    for (Double countdown = repetition; countdown > -1; countdown--) {
                        segmentInfo = genSegmentInfo(contentType, timescale, qualityID, segmentID, timePos - initialStartTime, duration);
                        segmentUriName = media.replaceAll("\\$(RepresentationID)\\$", rid).replaceAll("\\$(Time)\\$", String.format("%.0f", timePos));
                        masterManifest.getSegUrlMatchDef().add(defineUrlMatching(segmentUriName));
                        addToSegmentManifestCollectionMap(segmentUriName);
                        LOG.debug(String.format("moof >> %d :%s", segmentID, segmentUriName));
                        segmentInfo = childManifest.addSegment(segmentUriName, segmentInfo);
                        timePos += duration;
                        segmentID = segmentInfo.getSegmentID() + 1;
                    }
                }
            }
            addToSegmentManifestCollectionMap(childManifest.getUriName());
        }
        if (getChildManifest() == null) {
            childManifest = createChildManifest(newManifest, "", newManifest.getUriStr());
        }
        if (adaptationSet.getContentType().equals("audio")) {
            if (adaptationSet.getAudioChannelConfiguration() != null) {
                childManifest.setChannels(adaptationSet.getAudioChannelConfiguration().getValue());
            }
        }
    }
}
Also used : MPDSegmentTimeline(com.att.aro.core.videoanalysis.parsers.segmenttimeline.MPDSegmentTimeline) Pattern(java.util.regex.Pattern) ContentType(com.att.aro.core.videoanalysis.pojo.Manifest.ContentType) SegmentTemplateST(com.att.aro.core.videoanalysis.parsers.segmenttimeline.SegmentTemplateST) AdaptationSetTL(com.att.aro.core.videoanalysis.parsers.segmenttimeline.AdaptationSetTL) PeriodST(com.att.aro.core.videoanalysis.parsers.segmenttimeline.PeriodST) DashSegmentTimelineParser(com.att.aro.core.videoanalysis.parsers.DashSegmentTimelineParser) SegmentTimeLineST(com.att.aro.core.videoanalysis.parsers.segmenttimeline.SegmentTimeLineST) SegmentST(com.att.aro.core.videoanalysis.parsers.segmenttimeline.SegmentST) RepresentationST(com.att.aro.core.videoanalysis.parsers.segmenttimeline.RepresentationST)

Example 5 with ContentType

use of com.att.aro.core.videoanalysis.pojo.Manifest.ContentType in project VideoOptimzer by attdevsupport.

the class ManifestBuilderHLS method parseManifestData.

public void parseManifestData(Manifest newManifest, byte[] data) {
    String segmentUriName;
    if (data == null || data.length == 0) {
        LOG.debug("Manifest file is invalid, it has no content");
        return;
    }
    String strData = (new String(data)).trim();
    String[] sData = strData.split("\r\n");
    if (sData == null || sData.length == 1) {
        sData = strData.split("[\n\r]");
    }
    if (sData.length < 2) {
        LOG.debug("Invalid Playlist: " + strData);
        return;
    }
    int scanLength = strData.length() > 500 ? 20 : strData.length();
    if (strData.substring(0, scanLength).contains("#EXTM3U")) {
        newManifest.setVideoType(VideoType.HLS);
        newManifest.setVideoFormat(VideoFormat.UNKNOWN);
    } else {
        LOG.debug(String.format("Unrecognized Manifest:%s \ndata:%s", newManifest.getRequest().getObjNameWithoutParams(), strData));
        return;
    }
    // for #EXT-X-BYTERANGE usage only
    int[] byteRangeOffest = new int[] { 0 };
    adjustDurationNeeded = false;
    String[] flag;
    for (int itr = 0; itr < sData.length; itr++) {
        if (!sData[itr].startsWith("#") || (flag = stringParse.parse(sData[itr], pattern)) == null) {
            continue;
        }
        ContentType contentType;
        switch(flag[0]) {
            // Master & Child -------------------------------
            case // FirstLine of a manifest
            "#EXTM3U":
                // VID-TODO revisit this, want to know the proper key structure
                String key = StringUtils.substringBefore(newManifest.getRequest().getObjNameWithoutParams(), ";");
                if (strData.contains("#EXT-X-STREAM-INF:")) {
                    // master manifest
                    // dealing with a master manifest here, hence need a new ManifestCollection
                    LOG.debug("******* Parsing new Master Manifest (Video Stream)");
                    switchManifestCollection(newManifest, key, manifest.getRequestTime());
                } else if (strData.contains("#EXTINF:")) {
                    // child manifest
                    LOG.debug(" ****** Parsing new Child Manifest");
                    if (manifestCollection == null) {
                        // special handling of childManifest when there is no parent manifest
                        switchManifestCollection(newManifest, key, manifest.getRequestTime());
                    }
                    newManifest.setManifestType(ManifestType.CHILD);
                    newManifest.setMasterManifest(masterManifest);
                    childManifest = locateChildManifest(newManifest);
                    if (childManifest.getManifest() != null && childManifest.getManifest().getChecksumCRC32() == newManifest.getChecksumCRC32()) {
                        LOG.debug("Identical VOD child manifest found, skipping..." + newManifest.getVideoName());
                        return;
                    }
                    if (childManifest.getManifest() == null) {
                        childManifest.setManifest(newManifest);
                    }
                    // set name on (child)manifest
                    childManifest.getManifest().setVideoName(StringUtils.substringBefore(buildUriNameKey(childManifest.getManifest().getRequest()), ";"));
                    if (childManifest.isVideo()) {
                        if (childManifest.getCodecs().contains(",")) {
                            childManifest.setContentType(ContentType.MUXED);
                        } else {
                            childManifest.setContentType(ContentType.VIDEO);
                        }
                    }
                } else {
                    LOG.debug("Unknown HLS manifest:\n" + strData);
                    return;
                }
                break;
            case // Indicates the compatibility version of the playlist file
            "#EXT-X-VERSION":
                break;
            // Master only -------------------------------
            case // Alternate MediaPlaylist
            "#EXT-X-MEDIA":
                // #EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="audio",NAME="eng",DEFAULT=YES,AUTOSELECT=YES,LANGUAGE="eng",URI="06.m3u8"
                // #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="caption_1",DEFAULT=NO,AUTOSELECT=YES,LANGUAGE="ENG",URI="114.m3u8"
                childUriName = StringParse.findLabeledDataFromString("URI=", "\"", sData[itr]);
                childUriName = Util.decodeUrlEncoding(childUriName);
                if (StringUtils.isNotEmpty(childUriName)) {
                    LOG.debug("MEDIA childUriName :" + childUriName);
                    UrlMatchDef urlMatchDef = defineUrlMatching(childUriName);
                    manifest.getSegUrlMatchDef().add(urlMatchDef);
                    LOG.debug("EXT-X-MEDIA defineUrlMatching(childUriName): " + urlMatchDef);
                    childManifest = createChildManifest(null, "", childUriName);
                    childManifest.setVideo(false);
                    switch(StringParse.findLabeledDataFromString("TYPE=", ",", sData[itr])) {
                        case "AUDIO":
                            contentType = ContentType.AUDIO;
                            String channels = StringParse.findLabeledDataFromString("CHANNELS=", ",", sData[itr]);
                            if (StringUtils.isNotEmpty(channels)) {
                                childManifest.setChannels(channels.startsWith("") ? channels.substring(1, channels.length() - 1) : channels);
                            }
                            break;
                        case "CLOSED-CAPTIONS":
                        case "SUBTITLES":
                            contentType = ContentType.SUBTITLES;
                            break;
                        default:
                            contentType = ContentType.UNKNOWN;
                            break;
                    }
                    childManifest.setContentType(contentType);
                    manifest.setContentType(contentType);
                }
                break;
            case // ChildManifest Map itr:metadata-Info, ++itr:childManifestName
            "#EXT-X-STREAM-INF":
                String childParameters = sData[itr];
                childUriName = Util.decodeUrlEncoding(sData[++itr]);
                UrlMatchDef urlMatchDef = defineUrlMatching(childUriName);
                manifest.getSegUrlMatchDef().add(urlMatchDef);
                LOG.debug("EXT-X-STREAM-INF defineUrlMatching(childUriName): " + urlMatchDef);
                childManifest = manifestCollection.getChildManifest(childUriName);
                if (childManifest == null) {
                    // stored in childMap
                    childManifest = createChildManifest(null, childParameters, childUriName);
                }
                break;
            case // "keyframes" I_FrameInfo for fast-forward
            "#EXT-X-I-FRAME-STREAM-INF":
                break;
            // child manifest only -------------------------------
            case "#EXT-X-PLAYLIST-TYPE":
                if ("VOD".equals(StringParse.findLabeledDataFromString("#EXT-X-PLAYLIST-TYPE", ":", sData[itr]))) {
                    newManifest.setPlayListType(Manifest.StreamType.VOD);
                }
                break;
            case "#EXT-X-INDEPENDENT-SEGMENTS":
                break;
            case "#EXT-X-MAP":
                if (manifest.getVideoFormat().equals(VideoFormat.UNKNOWN)) {
                    if (sData[itr].contains(".mp4")) {
                        manifest.setVideoFormat(VideoFormat.MPEG4);
                        manifest.getMasterManifest().setVideoFormat(VideoFormat.MPEG4);
                    } else {
                        manifest.setVideoFormat(VideoFormat.TS);
                        manifest.getMasterManifest().setVideoFormat(VideoFormat.TS);
                    }
                }
                segmentUriName = StringParse.findLabeledDataFromString("URI=", "\"", sData[itr]);
                if (segmentUriName.contains("BUMPER") || segmentUriName.contains("DUB_CARD")) {
                    // Excluding DISCONTINUITY sections for BUMPER & DUB_CARD
                    // Suspect BUMPER is some sort of 1 segment preroll, skipping for now
                    // Suspect DUB_CARDs are advertisements, skipping for now
                    {
                        int skipCount = itr;
                        LOG.debug("Ignoring BUMPER/DUB_SUB:" + segmentUriName + "\nSkip through DISCONTINUITY");
                        for (; itr < sData.length - 1; itr++) {
                            if (sData[itr].contains("#EXT-X-DISCONTINUITY")) {
                                LOG.debug("skipped: " + (itr - skipCount + 1) + " lines");
                                break;
                            }
                        }
                    }
                    break;
                }
                String byteRangeSegmentKey = StringParse.findLabeledDataFromString("BYTERANGE=", "\"", sData[itr]);
                segmentUriName = cleanUriName(segmentUriName);
                urlMatchDef = defineUrlMatching(segmentUriName);
                segmentUriName = prefixParentUrlToSegmentUrl(segmentUriName, urlMatchDef, childManifest);
                masterManifest.getSegUrlMatchDef().add(urlMatchDef);
                newManifest.getSegUrlMatchDef().add(urlMatchDef);
                SegmentInfo segmentInfo = new SegmentInfo();
                segmentInfo.setVideo(false);
                segmentInfo.setDuration(0);
                segmentInfo.setSegmentID(0);
                segmentInfo.setQuality(String.format("%.0f", (double) childManifest.getQuality()));
                byteRangeSegmentKey = brKeyBuilder(byteRangeSegmentKey, segmentUriName, byteRangeOffest);
                childManifest.addSegment(!byteRangeSegmentKey.isEmpty() ? byteRangeSegmentKey : segmentUriName, segmentInfo);
                manifestCollection.addToSegmentTrie(segmentUriName, segmentInfo);
                if (!manifestCollection.getSegmentChildManifestTrie().containsKey(segmentUriName)) {
                    manifestCollection.addToSegmentChildManifestTrie(segmentUriName, childManifest);
                    addToSegmentManifestCollectionMap(segmentUriName);
                }
                break;
            case // Segment duration + media-file
            "#EXTINF":
                if (childManifest == null) {
                    LOG.debug("failed to locate child manifest " + sData[++itr]);
                } else {
                    String parameters = sData[itr];
                    byteRangeSegmentKey = "";
                    String byteRangeTagName = "#EXT-X-BYTERANGE";
                    int byteRangeIdx = sData[itr + 1].indexOf(byteRangeTagName);
                    if (byteRangeIdx != -1) {
                        byteRangeSegmentKey = sData[++itr].substring(byteRangeIdx + 1 + byteRangeTagName.length());
                        segmentUriName = sData[++itr];
                    } else {
                        segmentUriName = sData[++itr];
                    }
                    if (manifest.getVideoFormat().equals(VideoFormat.UNKNOWN)) {
                        if (segmentUriName.contains(".mp4")) {
                            manifest.setVideoFormat(VideoFormat.MPEG4);
                            manifest.getMasterManifest().setVideoFormat(VideoFormat.MPEG4);
                        } else {
                            manifest.setVideoFormat(VideoFormat.TS);
                            manifest.getMasterManifest().setVideoFormat(VideoFormat.TS);
                        }
                    }
                    segmentUriName = cleanUriName(segmentUriName);
                    urlMatchDef = defineUrlMatching(segmentUriName);
                    segmentUriName = prefixParentUrlToSegmentUrl(segmentUriName, urlMatchDef, childManifest);
                    masterManifest.getSegUrlMatchDef().add(urlMatchDef);
                    newManifest.getSegUrlMatchDef().add(urlMatchDef);
                    LOG.debug("EXTINF defineUrlMatching(childUriName): " + urlMatchDef);
                    segmentInfo = createSegmentInfo(childManifest, parameters, segmentUriName);
                    String[] segmentMatch = stringParse.parse(segmentUriName, "-([0-9]*T[0-9]*)-([0-9]*)-");
                    if (segmentMatch != null) {
                        newManifest.getTimeScale();
                        segmentInfo.setStartTime(0);
                    }
                    segmentUriName = Util.decodeUrlEncoding(segmentUriName);
                    segmentUriName = StringUtils.substringBefore(segmentUriName, "?");
                    byteRangeSegmentKey = brKeyBuilder(byteRangeSegmentKey, segmentUriName, byteRangeOffest);
                    if (childManifest.addSegment(!byteRangeSegmentKey.isEmpty() ? byteRangeSegmentKey : segmentUriName, segmentInfo).equals(segmentInfo)) {
                        manifestCollection.addToSegmentTrie(segmentUriName, segmentInfo);
                        manifestCollection.addToTimestampChildManifestMap(manifest.getRequest().getTimeStamp(), childManifest);
                        if (!manifestCollection.getSegmentChildManifestTrie().containsKey(segmentUriName)) {
                            manifestCollection.addToSegmentChildManifestTrie(segmentUriName, childManifest);
                            addToSegmentManifestCollectionMap(segmentUriName);
                        }
                    }
                }
                break;
            case // Segment ENDLIST for VOD (STATIC)
            "#EXT-X-ENDLIST":
                break;
            case // Segment is encrypted using [METHOD=____]
            "#EXT-X-KEY":
                break;
            case // Indicates the sequence number of the first URL that appears in a playlist file
            "#EXT-X-MEDIA-SEQUENCE":
                mediaSequence = StringParse.findLabeledDoubleFromString("#EXT-X-MEDIA-SEQUENCE", ":", sData[itr]);
                if (mediaSequence != null) {
                    if (childManifest.getSequenceStart() < 0) {
                        childManifest.setSequenceStart(mediaSequence.intValue());
                    }
                    manifestCollection.setMinimumSequenceStart(mediaSequence.intValue());
                    if (!sData[sData.length - 1].startsWith("#EXT-X-ENDLIST")) {
                        Integer pointer;
                        if ((pointer = findIndex(sData, childManifest)) != null) {
                            itr = pointer;
                        }
                    }
                }
                break;
            case // Specifies the maximum media-file duration.
            "#EXT-X-TARGETDURATION":
                // processExtXtargetDuration(line);
                break;
            case // YYYY-MM-DDTHH:MM:sss
            "#EXT-X-PROGRAM-DATE-TIME":
                String dateString = StringParse.findLabeledDataFromString("#EXT-X-PROGRAM-DATE-TIME:", "\\$", sData[itr]);
                dateString = dateString.replaceAll("\\+00\\:00", "000Z");
                long programDateTime = Util.parseForUTC(dateString);
                if (masterManifest.updateStreamProgramDateTime(programDateTime)) {
                    // VID-TODO need to resync segments across ManifestCollection
                    LOG.debug("Program time changed, need to resync segments across ManifestCollection");
                }
                if (childManifest.getSegmentStartTime() == 0) {
                    childManifest.setStreamProgramDateTime(programDateTime);
                }
                break;
            case "#USP-X-MEDIA":
                double bandwidth = StringParse.findLabeledDoubleFromString("BANDWIDTH=", ",", sData[itr]);
                childManifest.setBandwidth(bandwidth);
                childManifest.setCodecs(StringParse.findLabeledDataFromString("CODECS=", "\"", sData[itr]));
                String content = StringParse.findLabeledDataFromString("TYPE=", ",", sData[itr]);
                if (StringUtils.isNotEmpty(content)) {
                    if ("AUDIO".equals(content)) {
                        childManifest.setContentType(ContentType.AUDIO);
                        String val = StringParse.findLabeledDataFromString("CHANNELS=", "\"", sData[itr]);
                        if (val.contentEquals("")) {
                            val = "NA ";
                        }
                        LOG.debug("Parsing audio channels values: " + val);
                        childManifest.setChannels(val);
                    } else if ("VIDEO".equals(content)) {
                        childManifest.setContentType(ContentType.VIDEO);
                    }
                }
                break;
            case // #USP-X-TIMESTAMP-MAP:MPEGTS=900000,LOCAL=1970-01-01T00:00:00Z
            "#USP-X-TIMESTAMP-MAP":
                break;
            default:
                break;
        }
    }
    if (manifest.getManifestType().equals(Manifest.ManifestType.MASTER)) {
        assignQuality(manifestCollection);
    }
    if (adjustDurationNeeded) {
        adjustDurations(childManifest);
    }
}
Also used : UrlMatchDef(com.att.aro.core.videoanalysis.pojo.UrlMatchDef) ContentType(com.att.aro.core.videoanalysis.pojo.Manifest.ContentType)

Aggregations

ContentType (com.att.aro.core.videoanalysis.pojo.Manifest.ContentType)5 DashEncodedSegmentParser (com.att.aro.core.videoanalysis.parsers.DashEncodedSegmentParser)1 DashIFParser (com.att.aro.core.videoanalysis.parsers.DashIFParser)1 DashSegmentTimelineParser (com.att.aro.core.videoanalysis.parsers.DashSegmentTimelineParser)1 AdaptationSet (com.att.aro.core.videoanalysis.parsers.dashif.AdaptationSet)1 MPD (com.att.aro.core.videoanalysis.parsers.dashif.MPD)1 Representation (com.att.aro.core.videoanalysis.parsers.dashif.Representation)1 AdaptationSetESL (com.att.aro.core.videoanalysis.parsers.encodedsegment.AdaptationSetESL)1 MPDEncodedSegment (com.att.aro.core.videoanalysis.parsers.encodedsegment.MPDEncodedSegment)1 RepresentationESL (com.att.aro.core.videoanalysis.parsers.encodedsegment.RepresentationESL)1 AdaptationSetTL (com.att.aro.core.videoanalysis.parsers.segmenttimeline.AdaptationSetTL)1 MPDSegmentTimeline (com.att.aro.core.videoanalysis.parsers.segmenttimeline.MPDSegmentTimeline)1 PeriodST (com.att.aro.core.videoanalysis.parsers.segmenttimeline.PeriodST)1 RepresentationST (com.att.aro.core.videoanalysis.parsers.segmenttimeline.RepresentationST)1 SegmentST (com.att.aro.core.videoanalysis.parsers.segmenttimeline.SegmentST)1 SegmentTemplateST (com.att.aro.core.videoanalysis.parsers.segmenttimeline.SegmentTemplateST)1 SegmentTimeLineST (com.att.aro.core.videoanalysis.parsers.segmenttimeline.SegmentTimeLineST)1 UrlMatchDef (com.att.aro.core.videoanalysis.pojo.UrlMatchDef)1 VideoEvent (com.att.aro.core.videoanalysis.pojo.VideoEvent)1 Comparator (java.util.Comparator)1