Java 类com.google.android.exoplayer.dash.mpd.Representation 实例源码

项目:miku    文件:DashChunkSource.java   
private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri,
    Representation representation, ChunkExtractorWrapper extractor, DataSource dataSource,
    int trigger) {
  RangedUri requestUri;
  if (initializationUri != null) {
    // It's common for initialization and index data to be stored adjacently. Attempt to merge
    // the two requests together to request both at once.
    requestUri = initializationUri.attemptMerge(indexUri);
    if (requestUri == null) {
      requestUri = initializationUri;
    }
  } else {
    requestUri = indexUri;
  }
  DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length,
      representation.getCacheKey());
  return new InitializationChunk(dataSource, dataSpec, trigger, representation.format, extractor);
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri,
    Representation representation, ChunkExtractorWrapper extractor, DataSource dataSource,
    int manifestIndex, int trigger) {
  RangedUri requestUri;
  if (initializationUri != null) {
    // It's common for initialization and index data to be stored adjacently. Attempt to merge
    // the two requests together to request both at once.
    requestUri = initializationUri.attemptMerge(indexUri);
    if (requestUri == null) {
      requestUri = initializationUri;
    }
  } else {
    requestUri = indexUri;
  }
  DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length,
      representation.getCacheKey());
  return new InitializationChunk(dataSource, dataSpec, trigger, representation.format,
      extractor, manifestIndex);
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
protected Chunk newMediaChunk(
    PeriodHolder periodHolder, RepresentationHolder representationHolder, DataSource dataSource,
    MediaFormat mediaFormat, ExposedTrack enabledTrack, int segmentNum, int trigger) {
  Representation representation = representationHolder.representation;
  Format format = representation.format;
  long startTimeUs = representationHolder.getSegmentStartTimeUs(segmentNum);
  long endTimeUs = representationHolder.getSegmentEndTimeUs(segmentNum);
  RangedUri segmentUri = representationHolder.getSegmentUrl(segmentNum);
  DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
      representation.getCacheKey());

  long sampleOffsetUs = periodHolder.startTimeUs - representation.presentationTimeOffsetUs;
  if (mimeTypeIsRawText(format.mimeType)) {
    return new SingleSampleMediaChunk(dataSource, dataSpec, Chunk.TRIGGER_INITIAL, format,
        startTimeUs, endTimeUs, segmentNum, enabledTrack.trackFormat, null,
        periodHolder.localIndex);
  } else {
    boolean isMediaFormatFinal = (mediaFormat != null);
    return new ContainerMediaChunk(dataSource, dataSpec, trigger, format, startTimeUs, endTimeUs,
        segmentNum, sampleOffsetUs, representationHolder.extractorWrapper, mediaFormat,
        enabledTrack.adaptiveMaxWidth, enabledTrack.adaptiveMaxHeight, periodHolder.drmInitData,
        isMediaFormatFinal, periodHolder.localIndex);
  }
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
private void updateRepresentationIndependentProperties(long periodDurationUs,
    Representation arbitaryRepresentation) {
  DashSegmentIndex segmentIndex = arbitaryRepresentation.getIndex();
  if (segmentIndex != null) {
    int firstSegmentNum = segmentIndex.getFirstSegmentNum();
    int lastSegmentNum = segmentIndex.getLastSegmentNum(periodDurationUs);
    indexIsUnbounded = lastSegmentNum == DashSegmentIndex.INDEX_UNBOUNDED;
    indexIsExplicit = segmentIndex.isExplicit();
    availableStartTimeUs = startTimeUs + segmentIndex.getTimeUs(firstSegmentNum);
    if (!indexIsUnbounded) {
      availableEndTimeUs = startTimeUs + segmentIndex.getTimeUs(lastSegmentNum)
          + segmentIndex.getDurationUs(lastSegmentNum, periodDurationUs);
    }
  } else {
    indexIsUnbounded = false;
    indexIsExplicit = true;
    availableStartTimeUs = startTimeUs;
    availableEndTimeUs = startTimeUs + periodDurationUs;
  }
}
项目:ExoPlayer-Demo    文件:DashChunkSourceTest.java   
private static Representation buildSegmentTimelineRepresentation(long timelineDurationMs,
    long timelineStartTimeMs) {
  List<SegmentTimelineElement> segmentTimeline = new ArrayList<>();
  List<RangedUri> mediaSegments = new ArrayList<>();
  long segmentStartTimeMs = timelineStartTimeMs;
  long byteStart = 0;
  // Create all but the last segment with LIVE_SEGMENT_DURATION_MS.
  int segmentCount = (int) Util.ceilDivide(timelineDurationMs, LIVE_SEGMENT_DURATION_MS);
  for (int i = 0; i < segmentCount - 1; i++) {
    segmentTimeline.add(new SegmentTimelineElement(segmentStartTimeMs, LIVE_SEGMENT_DURATION_MS));
    mediaSegments.add(new RangedUri("", "", byteStart, 500L));
    segmentStartTimeMs += LIVE_SEGMENT_DURATION_MS;
    byteStart += 500;
  }
  // The final segment duration is calculated so that the total duration is timelineDurationMs.
  long finalSegmentDurationMs = (timelineStartTimeMs + timelineDurationMs) - segmentStartTimeMs;
  segmentTimeline.add(new SegmentTimelineElement(segmentStartTimeMs, finalSegmentDurationMs));
  mediaSegments.add(new RangedUri("", "", byteStart, 500L));
  segmentStartTimeMs += finalSegmentDurationMs;
  byteStart += 500;
  // Construct the list.
  MultiSegmentBase segmentBase = new SegmentList(null, 1000, 0, 0, 0, segmentTimeline,
      mediaSegments);
  return Representation.newInstance(null, 0, REGULAR_VIDEO, segmentBase);
}
项目:ExoPlayer    文件:DashChunkSource.java   
private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri,
    Representation representation, ChunkExtractorWrapper extractor, DataSource dataSource,
    int trigger) {
  RangedUri requestUri;
  if (initializationUri != null) {
    // It's common for initialization and index data to be stored adjacently. Attempt to merge
    // the two requests together to request both at once.
    requestUri = initializationUri.attemptMerge(indexUri);
    if (requestUri == null) {
      requestUri = initializationUri;
    }
  } else {
    requestUri = indexUri;
  }
  DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length,
      representation.getCacheKey());
  return new InitializationChunk(dataSource, dataSpec, trigger, representation.format, extractor);
}
项目:ExoPlayer    文件:DashChunkSourceTest.java   
public void testMaxVideoDimensionsLegacy() {
  SingleSegmentBase segmentBase1 = new SingleSegmentBase("https://example.com/1.mp4");
  Representation representation1 =
      Representation.newInstance(0, 0, null, 0, TALL_VIDEO, segmentBase1);

  SingleSegmentBase segmentBase2 = new SingleSegmentBase("https://example.com/2.mp4");
  Representation representation2 =
      Representation.newInstance(0, 0, null, 0, WIDE_VIDEO, segmentBase2);

  DashChunkSource chunkSource = new DashChunkSource(null, null, representation1, representation2);
  MediaFormat out = MediaFormat.createVideoFormat("video/h264", 1, 1, 1, 1, null);
  chunkSource.getMaxVideoDimensions(out);

  assertEquals(WIDE_WIDTH, out.getMaxVideoWidth());
  assertEquals(TALL_HEIGHT, out.getMaxVideoHeight());
}
项目:ExoPlayer    文件:DashChunkSourceTest.java   
private static Representation generateSegmentTimelineRepresentation(long segmentStartMs,
    long periodStartMs, long duration) {
  List<SegmentTimelineElement> segmentTimeline = new ArrayList<>();
  List<RangedUri> mediaSegments = new ArrayList<>();
  long segmentStartTimeMs = segmentStartMs;
  long byteStart = 0;
  for (int i = 0; i < (duration / LIVE_SEGMENT_DURATION_MS); i++) {
    segmentTimeline.add(new SegmentTimelineElement(segmentStartTimeMs, LIVE_SEGMENT_DURATION_MS));
    mediaSegments.add(new RangedUri("", "", byteStart, 500L));
    segmentStartTimeMs += LIVE_SEGMENT_DURATION_MS;
    byteStart += 500;
  }

  int startNumber = (int) ((periodStartMs + segmentStartMs) / LIVE_SEGMENT_DURATION_MS);
  MultiSegmentBase segmentBase = new SegmentList(null, 1000, 0,
      TrackRenderer.UNKNOWN_TIME_US, startNumber, TrackRenderer.UNKNOWN_TIME_US, segmentTimeline,
      mediaSegments);
  return Representation.newInstance(periodStartMs, TrackRenderer.UNKNOWN_TIME_US, null, 0,
      REGULAR_VIDEO, segmentBase);
}
项目:player-sdk-native-android    文件:SimpleDashParser.java   
private void loadDrmInitData(Representation representation) throws IOException {
    Uri initFile = representation.getInitializationUri().getUri();

    FileDataSource initChunkSource = new FileDataSource();
    DataSpec initDataSpec = new DataSpec(initFile);
    int trigger = 2;
    ChunkExtractorWrapper extractorWrapper = new ChunkExtractorWrapper(new FragmentedMp4Extractor());
    InitializationChunk chunk = new InitializationChunk(initChunkSource, initDataSpec, trigger, format, extractorWrapper);
    try {
        chunk.load();
    } catch (InterruptedException e) {
        Log.d(TAG, "Interrupted!", e);
    }
    if (!chunk.isLoadCanceled()) {
        drmInitData = chunk.getDrmInitData();
    }

    if (drmInitData != null) {
        DrmInitData.SchemeInitData schemeInitData = OfflineDrmManager.getWidevineInitData(drmInitData);
        if (schemeInitData != null) {
            widevineInitData = schemeInitData.data;
        }
    }
}
项目:miku    文件:DashChunkSource.java   
private Chunk newMediaChunk(RepresentationHolder representationHolder, DataSource dataSource,
    int segmentNum, int trigger) {
  Representation representation = representationHolder.representation;
  DashSegmentIndex segmentIndex = representationHolder.segmentIndex;

  long startTimeUs = segmentIndex.getTimeUs(segmentNum);
  long endTimeUs = startTimeUs + segmentIndex.getDurationUs(segmentNum);

  int absoluteSegmentNum = segmentNum + representationHolder.segmentNumShift;
  boolean isLastSegment = !currentManifest.dynamic
      && segmentNum == segmentIndex.getLastSegmentNum();

  RangedUri segmentUri = segmentIndex.getSegmentUrl(segmentNum);
  DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
      representation.getCacheKey());

  long sampleOffsetUs = representation.periodStartMs * 1000
      - representation.presentationTimeOffsetUs;
  if (representation.format.mimeType.equals(MimeTypes.TEXT_VTT)) {
    if (representationHolder.vttHeaderOffsetUs != sampleOffsetUs) {
      // Update the VTT header.
      headerBuilder.setLength(0);
      headerBuilder.append(C.WEBVTT_EXO_HEADER).append("=")
          .append(C.WEBVTT_EXO_HEADER_OFFSET).append(sampleOffsetUs)
          .append("\n");
      representationHolder.vttHeader = headerBuilder.toString().getBytes();
      representationHolder.vttHeaderOffsetUs = sampleOffsetUs;
    }
    return new SingleSampleMediaChunk(dataSource, dataSpec, Chunk.TRIGGER_INITIAL,
        representation.format, startTimeUs, endTimeUs, absoluteSegmentNum, isLastSegment,
        MediaFormat.createTextFormat(MimeTypes.TEXT_VTT), null, representationHolder.vttHeader);
  } else {
    return new ContainerMediaChunk(dataSource, dataSpec, trigger, representation.format,
        startTimeUs, endTimeUs, absoluteSegmentNum, isLastSegment, sampleOffsetUs,
        representationHolder.extractorWrapper, representationHolder.format, drmInitData, true);
  }
}
项目:miku    文件:DashChunkSource.java   
private static MediaPresentationDescription buildManifest(List<Representation> representations) {
  Representation firstRepresentation = representations.get(0);
  AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_UNKNOWN, representations);
  Period period = new Period(null, firstRepresentation.periodStartMs,
      firstRepresentation.periodDurationMs, Collections.singletonList(adaptationSet));
  long duration = firstRepresentation.periodDurationMs - firstRepresentation.periodStartMs;
  return new MediaPresentationDescription(-1, duration, -1, false, -1, -1, null, null,
      Collections.singletonList(period));
}
项目:ExoPlayer-Demo    文件:DashTest.java   
private static int[] getRepresentationIndices(AdaptationSet adaptationSet,
    String[] representationIds, boolean canIncludeAdditionalVideoRepresentations)
    throws IOException {
  List<Representation> availableRepresentations = adaptationSet.representations;
  List<Integer> selectedRepresentationIndices = new ArrayList<>();

  // Always select explicitly listed representations, failing if they're missing.
  for (int i = 0; i < representationIds.length; i++) {
    String representationId = representationIds[i];
    boolean foundIndex = false;
    for (int j = 0; j < availableRepresentations.size() && !foundIndex; j++) {
      if (availableRepresentations.get(j).format.id.equals(representationId)) {
        selectedRepresentationIndices.add(j);
        foundIndex = true;
      }
    }
    if (!foundIndex) {
      throw new IllegalStateException("Representation " + representationId + " not found.");
    }
  }

  // Select additional video representations, if supported by the device.
  if (canIncludeAdditionalVideoRepresentations) {
     int[] supportedVideoRepresentationIndices = VideoFormatSelectorUtil.selectVideoFormats(
         availableRepresentations, null, false, true, -1, -1);
     for (int i = 0; i < supportedVideoRepresentationIndices.length; i++) {
       int representationIndex = supportedVideoRepresentationIndices[i];
       if (!selectedRepresentationIndices.contains(representationIndex)) {
         Log.d(TAG, "Adding video format: " + availableRepresentations.get(i).format.id);
         selectedRepresentationIndices.add(representationIndex);
       }
     }

  }

  return Util.toArray(selectedRepresentationIndices);
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
private static MediaPresentationDescription buildManifest(long durationMs,
    int adaptationSetType, List<Representation> representations) {
  AdaptationSet adaptationSet = new AdaptationSet(0, adaptationSetType, representations);
  Period period = new Period(null, 0, Collections.singletonList(adaptationSet));
  return new MediaPresentationDescription(-1, durationMs, -1, false, -1, -1, null, null,
      Collections.singletonList(period));
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
public RepresentationHolder(long periodStartTimeUs, long periodDurationUs,
    Representation representation) {
  this.periodStartTimeUs = periodStartTimeUs;
  this.periodDurationUs = periodDurationUs;
  this.representation = representation;
  String mimeType = representation.format.mimeType;
  mimeTypeIsRawText = mimeTypeIsRawText(mimeType);
  extractorWrapper = mimeTypeIsRawText ? null : new ChunkExtractorWrapper(
      mimeTypeIsWebm(mimeType) ? new WebmExtractor() : new FragmentedMp4Extractor());
  segmentIndex = representation.getIndex();
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
public void updateRepresentation(long newPeriodDurationUs, Representation newRepresentation)
    throws BehindLiveWindowException{
  DashSegmentIndex oldIndex = representation.getIndex();
  DashSegmentIndex newIndex = newRepresentation.getIndex();

  periodDurationUs = newPeriodDurationUs;
  representation = newRepresentation;
  if (oldIndex == null) {
    // Segment numbers cannot shift if the index isn't defined by the manifest.
    return;
  }

  segmentIndex = newIndex;
  if (!oldIndex.isExplicit()) {
    // Segment numbers cannot shift if the index isn't explicit.
    return;
  }

  int oldIndexLastSegmentNum = oldIndex.getLastSegmentNum(periodDurationUs);
  long oldIndexEndTimeUs = oldIndex.getTimeUs(oldIndexLastSegmentNum)
      + oldIndex.getDurationUs(oldIndexLastSegmentNum, periodDurationUs);
  int newIndexFirstSegmentNum = newIndex.getFirstSegmentNum();
  long newIndexStartTimeUs = newIndex.getTimeUs(newIndexFirstSegmentNum);
  if (oldIndexEndTimeUs == newIndexStartTimeUs) {
    // The new index continues where the old one ended, with no overlap.
    segmentNumShift += oldIndex.getLastSegmentNum(periodDurationUs) + 1
        - newIndexFirstSegmentNum;
  } else if (oldIndexEndTimeUs < newIndexStartTimeUs) {
    // There's a gap between the old index and the new one which means we've slipped behind the
    // live window and can't proceed.
    throw new BehindLiveWindowException();
  } else {
    // The new index overlaps with the old one.
    segmentNumShift += oldIndex.getSegmentNum(newIndexStartTimeUs, periodDurationUs)
        - newIndexFirstSegmentNum;
  }
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
public PeriodHolder(int localIndex, MediaPresentationDescription manifest, int manifestIndex,
    ExposedTrack selectedTrack) {
  this.localIndex = localIndex;

  Period period = manifest.getPeriod(manifestIndex);
  long periodDurationUs = getPeriodDurationUs(manifest, manifestIndex);
  AdaptationSet adaptationSet = period.adaptationSets.get(selectedTrack.adaptationSetIndex);
  List<Representation> representations = adaptationSet.representations;

  startTimeUs = period.startMs * 1000;
  drmInitData = getDrmInitData(adaptationSet);

  if (!selectedTrack.isAdaptive()) {
    representationIndices = new int[] {
        getRepresentationIndex(representations, selectedTrack.fixedFormat.id)};
  } else {
    representationIndices = new int[selectedTrack.adaptiveFormats.length];
    for (int j = 0; j < selectedTrack.adaptiveFormats.length; j++) {
      representationIndices[j] = getRepresentationIndex(
          representations, selectedTrack.adaptiveFormats[j].id);
    }
  }

  representationHolders = new HashMap<>();
  for (int i = 0; i < representationIndices.length; i++) {
    Representation representation = representations.get(representationIndices[i]);
    RepresentationHolder representationHolder = new RepresentationHolder(startTimeUs,
        periodDurationUs, representation);
    representationHolders.put(representation.format.id, representationHolder);
  }
  updateRepresentationIndependentProperties(periodDurationUs,
      representations.get(representationIndices[0]));
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
public void updatePeriod(MediaPresentationDescription manifest, int manifestIndex,
    ExposedTrack selectedTrack) throws BehindLiveWindowException {
  Period period = manifest.getPeriod(manifestIndex);
  long periodDurationUs = getPeriodDurationUs(manifest, manifestIndex);
  List<Representation> representations = period.adaptationSets
      .get(selectedTrack.adaptationSetIndex).representations;

  for (int j = 0; j < representationIndices.length; j++) {
    Representation representation = representations.get(representationIndices[j]);
    representationHolders.get(representation.format.id).updateRepresentation(periodDurationUs,
        representation);
  }
  updateRepresentationIndependentProperties(periodDurationUs,
      representations.get(representationIndices[0]));
}
项目:ExoPlayer-Demo    文件:DashChunkSource.java   
private static int getRepresentationIndex(List<Representation> representations,
    String formatId) {
  for (int i = 0; i < representations.size(); i++) {
    Representation representation = representations.get(i);
    if (formatId.equals(representation.format.id)) {
      return i;
    }
  }
  throw new IllegalStateException("Missing format id: " + formatId);
}
项目:ExoPlayer-Demo    文件:DashChunkSourceTest.java   
private static Representation buildSegmentTemplateRepresentation() {
  UrlTemplate initializationTemplate = null;
  UrlTemplate mediaTemplate = UrlTemplate.compile("$RepresentationID$/$Number$");
  MultiSegmentBase segmentBase = new SegmentTemplate(null, 1000, 0, 0, LIVE_SEGMENT_DURATION_MS,
      null, initializationTemplate, mediaTemplate, "http://www.youtube.com");
  return Representation.newInstance(null, 0, REGULAR_VIDEO, segmentBase);
}
项目:ExoPlayer-Demo    文件:DashChunkSourceTest.java   
private static MediaPresentationDescription buildMpd(long durationMs,
    List<Representation> representations, boolean live, boolean limitTimeshiftBuffer) {
  AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_VIDEO, representations);
  Period period = new Period(null, 0, Collections.singletonList(adaptationSet));
  return new MediaPresentationDescription(AVAILABILITY_START_TIME_MS, durationMs, -1, live, -1,
      (limitTimeshiftBuffer) ? LIVE_TIMESHIFT_BUFFER_DEPTH_MS : -1, null, null,
      Collections.singletonList(period));
}
项目:ExoPlayer-Demo    文件:DashChunkSourceTest.java   
private static MediaPresentationDescription buildMultiPeriodVodMpd() {
  List<Period> periods = new ArrayList<>();
  long timeMs = 0;
  long periodDurationMs = VOD_DURATION_MS;
  for (int i = 0; i < 2; i++) {
    Representation representation = buildVodRepresentation(REGULAR_VIDEO);
    AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_VIDEO,
        Collections.singletonList(representation));
    Period period = new Period(null, timeMs, Collections.singletonList(adaptationSet));
    periods.add(period);
    timeMs += periodDurationMs;
  }
  return buildMultiPeriodMpd(timeMs, periods, false, false);
}
项目:ExoPlayer-Demo    文件:DashChunkSourceTest.java   
private static MediaPresentationDescription buildMultiPeriodLiveMpdWithTimeline() {
  List<Period> periods = new ArrayList<>();
  long periodStartTimeMs = 0;
  long periodDurationMs = LIVE_DURATION_MS;
  for (int i = 0; i < MULTI_PERIOD_COUNT; i++) {
    Representation representation = buildSegmentTimelineRepresentation(LIVE_DURATION_MS, 0);
    AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_VIDEO,
        Collections.singletonList(representation));
    Period period = new Period(null, periodStartTimeMs, Collections.singletonList(adaptationSet));
    periods.add(period);
    periodStartTimeMs += periodDurationMs;
  }
  return buildMultiPeriodMpd(periodDurationMs, periods, true, false);
}
项目:ExoPlayer-Demo    文件:DashChunkSourceTest.java   
private static MediaPresentationDescription buildMultiPeriodLiveMpdWithTemplate() {
  List<Period> periods = new ArrayList<>();
  long periodStartTimeMs = 0;
  long periodDurationMs = LIVE_DURATION_MS;
  for (int i = 0; i < MULTI_PERIOD_COUNT; i++) {
    Representation representation = buildSegmentTemplateRepresentation();
    AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_VIDEO,
        Collections.singletonList(representation));
    Period period = new Period(null, periodStartTimeMs, Collections.singletonList(adaptationSet));
    periods.add(period);
    periodStartTimeMs += periodDurationMs;
  }
  return buildMultiPeriodMpd(MULTI_PERIOD_LIVE_DURATION_MS, periods, true, false);
}
项目:android-exoplayer    文件:DashChunkSource.java   
private DashChunkSource(ManifestFetcher<MediaPresentationDescription> manifestFetcher,
    MediaPresentationDescription initialManifest, int adaptationSetIndex,
    int[] representationIndices, DataSource dataSource, FormatEvaluator formatEvaluator,
    long liveEdgeLatencyUs) {
  this.manifestFetcher = manifestFetcher;
  this.currentManifest = initialManifest;
  this.adaptationSetIndex = adaptationSetIndex;
  this.representationIndices = representationIndices;
  this.dataSource = dataSource;
  this.evaluator = formatEvaluator;
  this.liveEdgeLatencyUs = liveEdgeLatencyUs;
  this.evaluation = new Evaluation();
  this.headerBuilder = new StringBuilder();

  psshInfo = getPsshInfo(currentManifest, adaptationSetIndex);
  Representation[] representations = getFilteredRepresentations(currentManifest,
      adaptationSetIndex, representationIndices);
  long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US)
      ? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000;
  this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs);

  this.formats = new Format[representations.length];
  this.representationHolders = new HashMap<String, RepresentationHolder>();
  int maxWidth = 0;
  int maxHeight = 0;
  for (int i = 0; i < representations.length; i++) {
    formats[i] = representations[i].format;
    maxWidth = Math.max(formats[i].width, maxWidth);
    maxHeight = Math.max(formats[i].height, maxHeight);
    Extractor extractor = mimeTypeIsWebm(formats[i].mimeType) ? new WebmExtractor()
        : new FragmentedMp4Extractor();
    representationHolders.put(formats[i].id,
        new RepresentationHolder(representations[i], extractor));
  }
  this.maxWidth = maxWidth;
  this.maxHeight = maxHeight;
  Arrays.sort(formats, new DecreasingBandwidthComparator());
}
项目:android-exoplayer    文件:DashChunkSource.java   
@Override
public void continueBuffering(long playbackPositionUs) {
  if (manifestFetcher == null || !currentManifest.dynamic || fatalError != null) {
    return;
  }

  MediaPresentationDescription newManifest = manifestFetcher.getManifest();
  if (currentManifest != newManifest && newManifest != null) {
    Representation[] newRepresentations = DashChunkSource.getFilteredRepresentations(newManifest,
        adaptationSetIndex, representationIndices);
    for (Representation representation : newRepresentations) {
      RepresentationHolder representationHolder =
          representationHolders.get(representation.format.id);
      DashSegmentIndex oldIndex = representationHolder.segmentIndex;
      DashSegmentIndex newIndex = representation.getIndex();
      int newFirstSegmentNum = newIndex.getFirstSegmentNum();
      int segmentNumShift = oldIndex.getSegmentNum(newIndex.getTimeUs(newFirstSegmentNum))
          - newFirstSegmentNum;
      representationHolder.segmentNumShift += segmentNumShift;
      representationHolder.segmentIndex = newIndex;
    }
    currentManifest = newManifest;
    finishedCurrentManifest = false;
  }

  // TODO: This is a temporary hack to avoid constantly refreshing the MPD in cases where
  // minUpdatePeriod is set to 0. In such cases we shouldn't refresh unless there is explicit
  // signaling in the stream, according to:
  // http://azure.microsoft.com/blog/2014/09/13/dash-live-streaming-with-azure-media-service/
  long minUpdatePeriod = currentManifest.minUpdatePeriod;
  if (minUpdatePeriod == 0) {
    minUpdatePeriod = 5000;
  }

  if (finishedCurrentManifest && (SystemClock.elapsedRealtime()
      > manifestFetcher.getManifestLoadTimestamp() + minUpdatePeriod)) {
    manifestFetcher.requestRefresh();
  }
}
项目:android-exoplayer    文件:DashChunkSource.java   
private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri,
    Representation representation, Extractor extractor, DataSource dataSource,
    int trigger) {
  int expectedExtractorResult = Extractor.RESULT_END_OF_STREAM;
  long indexAnchor = 0;
  RangedUri requestUri;
  if (initializationUri != null) {
    // It's common for initialization and index data to be stored adjacently. Attempt to merge
    // the two requests together to request both at once.
    expectedExtractorResult |= Extractor.RESULT_READ_INIT;
    requestUri = initializationUri.attemptMerge(indexUri);
    if (requestUri != null) {
      expectedExtractorResult |= Extractor.RESULT_READ_INDEX;
      if (extractor.hasRelativeIndexOffsets()) {
        indexAnchor = indexUri.start + indexUri.length;
      }
    } else {
      requestUri = initializationUri;
    }
  } else {
    requestUri = indexUri;
    if (extractor.hasRelativeIndexOffsets()) {
      indexAnchor = indexUri.start + indexUri.length;
    }
    expectedExtractorResult |= Extractor.RESULT_READ_INDEX;
  }
  DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length,
      representation.getCacheKey());

  return new InitializationLoadable(dataSource, dataSpec, trigger, representation.format,
      extractor, expectedExtractorResult, indexAnchor);
}
项目:android-exoplayer    文件:DashChunkSource.java   
private Chunk newMediaChunk(RepresentationHolder representationHolder, DataSource dataSource,
    int segmentNum, int trigger) {
  Representation representation = representationHolder.representation;
  DashSegmentIndex segmentIndex = representationHolder.segmentIndex;

  long startTimeUs = segmentIndex.getTimeUs(segmentNum);
  long endTimeUs = startTimeUs + segmentIndex.getDurationUs(segmentNum);

  boolean isLastSegment = !currentManifest.dynamic
      && segmentNum == segmentIndex.getLastSegmentNum();
  int nextAbsoluteSegmentNum = isLastSegment ? -1
      : (representationHolder.segmentNumShift + segmentNum + 1);

  RangedUri segmentUri = segmentIndex.getSegmentUrl(segmentNum);
  DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
      representation.getCacheKey());

  long presentationTimeOffsetUs = representation.presentationTimeOffsetMs * 1000;
  if (representation.format.mimeType.equals(MimeTypes.TEXT_VTT)) {
    if (representationHolder.vttHeaderOffsetUs != presentationTimeOffsetUs) {
      // Update the VTT header.
      headerBuilder.setLength(0);
      headerBuilder.append(WebvttParser.EXO_HEADER).append("=")
          .append(WebvttParser.OFFSET).append(presentationTimeOffsetUs).append("\n");
      representationHolder.vttHeader = headerBuilder.toString().getBytes();
      representationHolder.vttHeaderOffsetUs = presentationTimeOffsetUs;
    }
    return new SingleSampleMediaChunk(dataSource, dataSpec, representation.format, 0,
        startTimeUs, endTimeUs, nextAbsoluteSegmentNum, null, representationHolder.vttHeader);
  } else {
    return new Mp4MediaChunk(dataSource, dataSpec, representation.format, trigger, startTimeUs,
        endTimeUs, nextAbsoluteSegmentNum, representationHolder.extractor, psshInfo, false,
        presentationTimeOffsetUs);
  }
}
项目:android-exoplayer    文件:DashChunkSource.java   
private static MediaPresentationDescription buildManifest(List<Representation> representations) {
  Representation firstRepresentation = representations.get(0);
  AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_UNKNOWN, representations);
  Period period = new Period(null, firstRepresentation.periodStartMs,
      firstRepresentation.periodDurationMs, Collections.singletonList(adaptationSet));
  long duration = firstRepresentation.periodDurationMs - firstRepresentation.periodStartMs;
  return new MediaPresentationDescription(-1, duration, -1, false, -1, -1, null,
      Collections.singletonList(period));
}
项目:Exoplayer_VLC    文件:DashChunkSource.java   
private DashChunkSource(ManifestFetcher<MediaPresentationDescription> manifestFetcher,
    MediaPresentationDescription initialManifest, int adaptationSetIndex,
    int[] representationIndices, DataSource dataSource, FormatEvaluator formatEvaluator,
    long liveEdgeLatencyUs) {
  this.manifestFetcher = manifestFetcher;
  this.currentManifest = initialManifest;
  this.adaptationSetIndex = adaptationSetIndex;
  this.representationIndices = representationIndices;
  this.dataSource = dataSource;
  this.evaluator = formatEvaluator;
  this.liveEdgeLatencyUs = liveEdgeLatencyUs;
  this.evaluation = new Evaluation();
  this.headerBuilder = new StringBuilder();

  psshInfo = getPsshInfo(currentManifest, adaptationSetIndex);
  Representation[] representations = getFilteredRepresentations(currentManifest,
      adaptationSetIndex, representationIndices);
  long periodDurationUs = (representations[0].periodDurationMs == TrackRenderer.UNKNOWN_TIME_US)
      ? TrackRenderer.UNKNOWN_TIME_US : representations[0].periodDurationMs * 1000;
  this.trackInfo = new TrackInfo(representations[0].format.mimeType, periodDurationUs);

  this.formats = new Format[representations.length];
  this.representationHolders = new HashMap<String, RepresentationHolder>();
  int maxWidth = 0;
  int maxHeight = 0;
  for (int i = 0; i < representations.length; i++) {
    formats[i] = representations[i].format;
    maxWidth = Math.max(formats[i].width, maxWidth);
    maxHeight = Math.max(formats[i].height, maxHeight);
    Extractor extractor = mimeTypeIsWebm(formats[i].mimeType) ? new WebmExtractor()
        : new FragmentedMp4Extractor();
    representationHolders.put(formats[i].id,
        new RepresentationHolder(representations[i], extractor));
  }
  this.maxWidth = maxWidth;
  this.maxHeight = maxHeight;
  Arrays.sort(formats, new DecreasingBandwidthComparator());
}
项目:Exoplayer_VLC    文件:DashChunkSource.java   
@Override
public void continueBuffering(long playbackPositionUs) {
  if (manifestFetcher == null || !currentManifest.dynamic || fatalError != null) {
    return;
  }

  MediaPresentationDescription newManifest = manifestFetcher.getManifest();
  if (currentManifest != newManifest && newManifest != null) {
    Representation[] newRepresentations = DashChunkSource.getFilteredRepresentations(newManifest,
        adaptationSetIndex, representationIndices);
    for (Representation representation : newRepresentations) {
      RepresentationHolder representationHolder =
          representationHolders.get(representation.format.id);
      DashSegmentIndex oldIndex = representationHolder.segmentIndex;
      DashSegmentIndex newIndex = representation.getIndex();
      int newFirstSegmentNum = newIndex.getFirstSegmentNum();
      int segmentNumShift = oldIndex.getSegmentNum(newIndex.getTimeUs(newFirstSegmentNum))
          - newFirstSegmentNum;
      representationHolder.segmentNumShift += segmentNumShift;
      representationHolder.segmentIndex = newIndex;
    }
    currentManifest = newManifest;
    finishedCurrentManifest = false;
  }

  // TODO: This is a temporary hack to avoid constantly refreshing the MPD in cases where
  // minUpdatePeriod is set to 0. In such cases we shouldn't refresh unless there is explicit
  // signaling in the stream, according to:
  // http://azure.microsoft.com/blog/2014/09/13/dash-live-streaming-with-azure-media-service/
  long minUpdatePeriod = currentManifest.minUpdatePeriod;
  if (minUpdatePeriod == 0) {
    minUpdatePeriod = 5000;
  }

  if (finishedCurrentManifest && (SystemClock.elapsedRealtime()
      > manifestFetcher.getManifestLoadTimestamp() + minUpdatePeriod)) {
    manifestFetcher.requestRefresh();
  }
}
项目:Exoplayer_VLC    文件:DashChunkSource.java   
private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri,
    Representation representation, Extractor extractor, DataSource dataSource,
    int trigger) {
  int expectedExtractorResult = Extractor.RESULT_END_OF_STREAM;
  long indexAnchor = 0;
  RangedUri requestUri;
  if (initializationUri != null) {
    // It's common for initialization and index data to be stored adjacently. Attempt to merge
    // the two requests together to request both at once.
    expectedExtractorResult |= Extractor.RESULT_READ_INIT;
    requestUri = initializationUri.attemptMerge(indexUri);
    if (requestUri != null) {
      expectedExtractorResult |= Extractor.RESULT_READ_INDEX;
      if (extractor.hasRelativeIndexOffsets()) {
        indexAnchor = indexUri.start + indexUri.length;
      }
    } else {
      requestUri = initializationUri;
    }
  } else {
    requestUri = indexUri;
    if (extractor.hasRelativeIndexOffsets()) {
      indexAnchor = indexUri.start + indexUri.length;
    }
    expectedExtractorResult |= Extractor.RESULT_READ_INDEX;
  }
  DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length,
      representation.getCacheKey());

  return new InitializationLoadable(dataSource, dataSpec, trigger, representation.format,
      extractor, expectedExtractorResult, indexAnchor);
}
项目:Exoplayer_VLC    文件:DashChunkSource.java   
private Chunk newMediaChunk(RepresentationHolder representationHolder, DataSource dataSource,
    int segmentNum, int trigger) {
  Representation representation = representationHolder.representation;
  DashSegmentIndex segmentIndex = representationHolder.segmentIndex;

  long startTimeUs = segmentIndex.getTimeUs(segmentNum);
  long endTimeUs = startTimeUs + segmentIndex.getDurationUs(segmentNum);

  boolean isLastSegment = !currentManifest.dynamic
      && segmentNum == segmentIndex.getLastSegmentNum();
  int nextAbsoluteSegmentNum = isLastSegment ? -1
      : (representationHolder.segmentNumShift + segmentNum + 1);

  RangedUri segmentUri = segmentIndex.getSegmentUrl(segmentNum);
  DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
      representation.getCacheKey());

  long presentationTimeOffsetUs = representation.presentationTimeOffsetUs;
  if (representation.format.mimeType.equals(MimeTypes.TEXT_VTT)) {
    if (representationHolder.vttHeaderOffsetUs != presentationTimeOffsetUs) {
      // Update the VTT header.
      headerBuilder.setLength(0);
      headerBuilder.append(WebvttParser.EXO_HEADER).append("=")
          .append(WebvttParser.OFFSET).append(presentationTimeOffsetUs).append("\n");
      representationHolder.vttHeader = headerBuilder.toString().getBytes();
      representationHolder.vttHeaderOffsetUs = presentationTimeOffsetUs;
    }
    return new SingleSampleMediaChunk(dataSource, dataSpec, representation.format, 0,
        startTimeUs, endTimeUs, nextAbsoluteSegmentNum, null, representationHolder.vttHeader);
  } else {
    return new ContainerMediaChunk(dataSource, dataSpec, representation.format, trigger,
        startTimeUs, endTimeUs, nextAbsoluteSegmentNum, representationHolder.extractor, psshInfo,
        false, presentationTimeOffsetUs);
  }
}
项目:Exoplayer_VLC    文件:DashChunkSource.java   
private static MediaPresentationDescription buildManifest(List<Representation> representations) {
  Representation firstRepresentation = representations.get(0);
  AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_UNKNOWN, representations);
  Period period = new Period(null, firstRepresentation.periodStartMs,
      firstRepresentation.periodDurationMs, Collections.singletonList(adaptationSet));
  long duration = firstRepresentation.periodDurationMs - firstRepresentation.periodStartMs;
  return new MediaPresentationDescription(-1, duration, -1, false, -1, -1, null,
      Collections.singletonList(period));
}
项目:edx-app-android    文件:DashChunkSource.java   
/**
 * @param dataSource A {@link DataSource} suitable for loading the media data.
 * @param evaluator Selects from the available formats.
 * @param representations The representations to be considered by the source.
 */
public DashChunkSource(DataSource dataSource, FormatEvaluator evaluator,
    Representation... representations) {
  this.dataSource = dataSource;
  this.evaluator = evaluator;
  this.formats = new Format[representations.length];
  this.extractors = new HashMap<String, Extractor>();
  this.segmentIndexes = new HashMap<String, DashSegmentIndex>();
  this.representations = new HashMap<String, Representation>();
  this.trackInfo = new TrackInfo(representations[0].format.mimeType,
      representations[0].periodDurationMs * 1000);
  this.evaluation = new Evaluation();
  int maxWidth = 0;
  int maxHeight = 0;
  for (int i = 0; i < representations.length; i++) {
    formats[i] = representations[i].format;
    maxWidth = Math.max(formats[i].width, maxWidth);
    maxHeight = Math.max(formats[i].height, maxHeight);
    Extractor extractor = formats[i].mimeType.startsWith(MimeTypes.VIDEO_WEBM)
        ? new WebmExtractor() : new FragmentedMp4Extractor();
    extractors.put(formats[i].id, extractor);
    this.representations.put(formats[i].id, representations[i]);
    DashSegmentIndex segmentIndex = representations[i].getIndex();
    if (segmentIndex != null) {
      segmentIndexes.put(formats[i].id, segmentIndex);
    }
  }
  this.maxWidth = maxWidth;
  this.maxHeight = maxHeight;
  Arrays.sort(formats, new DecreasingBandwidthComparator());
}
项目:edx-app-android    文件:DashChunkSource.java   
private Chunk newInitializationChunk(RangedUri initializationUri, RangedUri indexUri,
    Representation representation, Extractor extractor, DataSource dataSource,
    int trigger) {
  int expectedExtractorResult = Extractor.RESULT_END_OF_STREAM;
  long indexAnchor = 0;
  RangedUri requestUri;
  if (initializationUri != null) {
    // It's common for initialization and index data to be stored adjacently. Attempt to merge
    // the two requests together to request both at once.
    expectedExtractorResult |= Extractor.RESULT_READ_INIT;
    requestUri = initializationUri.attemptMerge(indexUri);
    if (requestUri != null) {
      expectedExtractorResult |= Extractor.RESULT_READ_INDEX;
      if (extractor.hasRelativeIndexOffsets()) {
        indexAnchor = indexUri.start + indexUri.length;
      }
    } else {
      requestUri = initializationUri;
    }
  } else {
    requestUri = indexUri;
    if (extractor.hasRelativeIndexOffsets()) {
      indexAnchor = indexUri.start + indexUri.length;
    }
    expectedExtractorResult |= Extractor.RESULT_READ_INDEX;
  }
  DataSpec dataSpec = new DataSpec(requestUri.getUri(), requestUri.start, requestUri.length,
      representation.getCacheKey());
  return new InitializationLoadable(dataSource, dataSpec, trigger, representation.format,
      extractor, expectedExtractorResult, indexAnchor);
}
项目:edx-app-android    文件:DashChunkSource.java   
private Chunk newMediaChunk(Representation representation, DashSegmentIndex segmentIndex,
    Extractor extractor, DataSource dataSource, int segmentNum, int trigger) {
  int lastSegmentNum = segmentIndex.getLastSegmentNum();
  int nextSegmentNum = segmentNum == lastSegmentNum ? -1 : segmentNum + 1;
  long startTimeUs = segmentIndex.getTimeUs(segmentNum);
  long endTimeUs = segmentNum < lastSegmentNum ? segmentIndex.getTimeUs(segmentNum + 1)
      : startTimeUs + segmentIndex.getDurationUs(segmentNum);
  RangedUri segmentUri = segmentIndex.getSegmentUrl(segmentNum);
  DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
      representation.getCacheKey());
  return new Mp4MediaChunk(dataSource, dataSpec, representation.format, trigger, startTimeUs,
      endTimeUs, nextSegmentNum, extractor, false, 0);
}
项目:ExoPlayer    文件:DashChunkSource.java   
private Chunk newMediaChunk(RepresentationHolder representationHolder, DataSource dataSource,
    int segmentNum, int trigger) {
  Representation representation = representationHolder.representation;
  DashSegmentIndex segmentIndex = representationHolder.segmentIndex;

  long startTimeUs = segmentIndex.getTimeUs(segmentNum);
  long endTimeUs = startTimeUs + segmentIndex.getDurationUs(segmentNum);

  int absoluteSegmentNum = segmentNum + representationHolder.segmentNumShift;
  boolean isLastSegment = !currentManifest.dynamic
      && segmentNum == segmentIndex.getLastSegmentNum();

  RangedUri segmentUri = segmentIndex.getSegmentUrl(segmentNum);
  DataSpec dataSpec = new DataSpec(segmentUri.getUri(), segmentUri.start, segmentUri.length,
      representation.getCacheKey());

  long sampleOffsetUs = representation.periodStartMs * 1000
      - representation.presentationTimeOffsetUs;
  if (representation.format.mimeType.equals(MimeTypes.TEXT_VTT)) {
    if (representationHolder.vttHeaderOffsetUs != sampleOffsetUs) {
      // Update the VTT header.
      headerBuilder.setLength(0);
      headerBuilder.append(C.WEBVTT_EXO_HEADER).append("=")
          .append(C.WEBVTT_EXO_HEADER_OFFSET).append(sampleOffsetUs)
          .append("\n");
      representationHolder.vttHeader = headerBuilder.toString().getBytes();
      representationHolder.vttHeaderOffsetUs = sampleOffsetUs;
    }
    return new SingleSampleMediaChunk(dataSource, dataSpec, Chunk.TRIGGER_INITIAL,
        representation.format, startTimeUs, endTimeUs, absoluteSegmentNum, isLastSegment,
        MediaFormat.createTextFormat(MimeTypes.TEXT_VTT), null, representationHolder.vttHeader);
  } else {
    return new ContainerMediaChunk(dataSource, dataSpec, trigger, representation.format,
        startTimeUs, endTimeUs, absoluteSegmentNum, isLastSegment, sampleOffsetUs,
        representationHolder.extractorWrapper, representationHolder.format, drmInitData, true);
  }
}
项目:ExoPlayer    文件:DashChunkSource.java   
private static MediaPresentationDescription buildManifest(List<Representation> representations) {
  Representation firstRepresentation = representations.get(0);
  AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_UNKNOWN, representations);
  Period period = new Period(null, firstRepresentation.periodStartMs,
      firstRepresentation.periodDurationMs, Collections.singletonList(adaptationSet));
  long duration = firstRepresentation.periodDurationMs - firstRepresentation.periodStartMs;
  return new MediaPresentationDescription(-1, duration, -1, false, -1, -1, null, null,
      Collections.singletonList(period));
}
项目:ExoPlayer    文件:DashChunkSourceTest.java   
private static MediaPresentationDescription generateMpd(boolean live,
    List<Representation> representations, boolean limitTimeshiftBuffer) {
  Representation firstRepresentation = representations.get(0);
  AdaptationSet adaptationSet = new AdaptationSet(0, AdaptationSet.TYPE_UNKNOWN, representations);
  Period period = new Period(null, firstRepresentation.periodStartMs,
      firstRepresentation.periodDurationMs, Collections.singletonList(adaptationSet));
  long duration = (live) ? TrackRenderer.UNKNOWN_TIME_US
      : firstRepresentation.periodDurationMs - firstRepresentation.periodStartMs;
  return new MediaPresentationDescription(AVAILABILITY_START_TIME_MS, duration, -1, live, -1,
      (limitTimeshiftBuffer) ? LIVE_TIMESHIFT_BUFFER_DEPTH_MS : -1, null, null,
      Collections.singletonList(period));
}
项目:ExoPlayer    文件:DashChunkSourceTest.java   
private static MediaPresentationDescription generateVodMpd() {
  List<Representation> representations = new ArrayList<>();

  representations.add(generateVodRepresentation(0, VOD_DURATION_MS, TALL_VIDEO));
  representations.add(generateVodRepresentation(0, VOD_DURATION_MS, WIDE_VIDEO));

  return generateMpd(false, representations, false);
}