Java Code Examples for com.google.android.exoplayer2.C#BUFFER_FLAG_KEY_FRAME

The following examples show how to use com.google.android.exoplayer2.C#BUFFER_FLAG_KEY_FRAME . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: SampleQueue.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
@Override
public void sampleMetadata(
    long timeUs,
    @C.BufferFlags int flags,
    int size,
    int offset,
    @Nullable CryptoData cryptoData) {
  if (pendingFormatAdjustment) {
    format(lastUnadjustedFormat);
  }
  timeUs += sampleOffsetUs;
  if (pendingSplice) {
    if ((flags & C.BUFFER_FLAG_KEY_FRAME) == 0 || !metadataQueue.attemptSplice(timeUs)) {
      return;
    }
    pendingSplice = false;
  }
  long absoluteOffset = totalBytesWritten - size - offset;
  metadataQueue.commitSample(timeUs, flags, absoluteOffset, size, cryptoData);
}
 
Example 2
Source File: SampleMetadataQueue.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Finds the sample in the specified range that's before or at the specified time. If
 * {@code keyframe} is {@code true} then the sample is additionally required to be a keyframe.
 *
 * @param relativeStartIndex The relative index from which to start searching.
 * @param length The length of the range being searched.
 * @param timeUs The specified time.
 * @param keyframe Whether only keyframes should be considered.
 * @return The offset from {@code relativeFirstIndex} to the found sample, or -1 if no matching
 *     sample was found.
 */
private int findSampleBefore(int relativeStartIndex, int length, long timeUs, boolean keyframe) {
  // This could be optimized to use a binary search, however in practice callers to this method
  // normally pass times near to the start of the search region. Hence it's unclear whether
  // switching to a binary search would yield any real benefit.
  int sampleCountToTarget = -1;
  int searchIndex = relativeStartIndex;
  for (int i = 0; i < length && timesUs[searchIndex] <= timeUs; i++) {
    if (!keyframe || (flags[searchIndex] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      // We've found a suitable sample.
      sampleCountToTarget = i;
    }
    searchIndex++;
    if (searchIndex == capacity) {
      searchIndex = 0;
    }
  }
  return sampleCountToTarget;
}
 
Example 3
Source File: SampleMetadataQueue.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
/**
 * Finds the sample in the specified range that's before or at the specified time. If
 * {@code keyframe} is {@code true} then the sample is additionally required to be a keyframe.
 *
 * @param relativeStartIndex The relative index from which to start searching.
 * @param length The length of the range being searched.
 * @param timeUs The specified time.
 * @param keyframe Whether only keyframes should be considered.
 * @return The offset from {@code relativeFirstIndex} to the found sample, or -1 if no matching
 *     sample was found.
 */
private int findSampleBefore(int relativeStartIndex, int length, long timeUs, boolean keyframe) {
  // This could be optimized to use a binary search, however in practice callers to this method
  // normally pass times near to the start of the search region. Hence it's unclear whether
  // switching to a binary search would yield any real benefit.
  int sampleCountToTarget = -1;
  int searchIndex = relativeStartIndex;
  for (int i = 0; i < length && timesUs[searchIndex] <= timeUs; i++) {
    if (!keyframe || (flags[searchIndex] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      // We've found a suitable sample.
      sampleCountToTarget = i;
    }
    searchIndex++;
    if (searchIndex == capacity) {
      searchIndex = 0;
    }
  }
  return sampleCountToTarget;
}
 
Example 4
Source File: TrackSampleTable.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns the sample index of the closest synchronization sample at or after the given timestamp,
 * if one is available.
 *
 * @param timeUs Timestamp adjacent to which to find a synchronization sample.
 * @return index Index of the synchronization sample, or {@link C#INDEX_UNSET} if none.
 */
public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) {
  int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false);
  for (int i = startIndex; i < timestampsUs.length; i++) {
    if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      return i;
    }
  }
  return C.INDEX_UNSET;
}
 
Example 5
Source File: TrackSampleTable.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Returns the sample index of the closest synchronization sample at or before the given
 * timestamp, if one is available.
 *
 * @param timeUs Timestamp adjacent to which to find a synchronization sample.
 * @return Index of the synchronization sample, or {@link C#INDEX_UNSET} if none.
 */
public int getIndexOfEarlierOrEqualSynchronizationSample(long timeUs) {
  // Video frame timestamps may not be sorted, so the behavior of this call can be undefined.
  // Frames are not reordered past synchronization samples so this works in practice.
  int startIndex = Util.binarySearchFloor(timestampsUs, timeUs, true, false);
  for (int i = startIndex; i >= 0; i--) {
    if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      return i;
    }
  }
  return C.INDEX_UNSET;
}
 
Example 6
Source File: DefaultTrackOutput.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Attempts to locate the keyframe before or at the specified time. If
 * {@code allowTimeBeyondBuffer} is {@code false} then it is also required that {@code timeUs}
 * falls within the buffer.
 *
 * @param timeUs The seek time.
 * @param allowTimeBeyondBuffer Whether the skip can succeed if {@code timeUs} is beyond the end
 *     of the buffer.
 * @return The offset of the keyframe's data if the keyframe was present.
 *     {@link C#POSITION_UNSET} otherwise.
 */
public synchronized long skipToKeyframeBefore(long timeUs, boolean allowTimeBeyondBuffer) {
  if (queueSize == 0 || timeUs < timesUs[relativeReadIndex]) {
    return C.POSITION_UNSET;
  }

  if (timeUs > largestQueuedTimestampUs && !allowTimeBeyondBuffer) {
    return C.POSITION_UNSET;
  }

  // This could be optimized to use a binary search, however in practice callers to this method
  // often pass times near to the start of the buffer. Hence it's unclear whether switching to
  // a binary search would yield any real benefit.
  int sampleCount = 0;
  int sampleCountToKeyframe = -1;
  int searchIndex = relativeReadIndex;
  while (searchIndex != relativeWriteIndex) {
    if (timesUs[searchIndex] > timeUs) {
      // We've gone too far.
      break;
    } else if ((flags[searchIndex] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      // We've found a keyframe, and we're still before the seek position.
      sampleCountToKeyframe = sampleCount;
    }
    searchIndex = (searchIndex + 1) % capacity;
    sampleCount++;
  }

  if (sampleCountToKeyframe == -1) {
    return C.POSITION_UNSET;
  }

  queueSize -= sampleCountToKeyframe;
  relativeReadIndex = (relativeReadIndex + sampleCountToKeyframe) % capacity;
  absoluteReadIndex += sampleCountToKeyframe;
  return offsets[relativeReadIndex];
}
 
Example 7
Source File: TrackSampleTable.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns the sample index of the closest synchronization sample at or after the given timestamp,
 * if one is available.
 *
 * @param timeUs Timestamp adjacent to which to find a synchronization sample.
 * @return index Index of the synchronization sample, or {@link C#INDEX_UNSET} if none.
 */
public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) {
  int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false);
  for (int i = startIndex; i < timestampsUs.length; i++) {
    if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      return i;
    }
  }
  return C.INDEX_UNSET;
}
 
Example 8
Source File: TrackSampleTable.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Returns the sample index of the closest synchronization sample at or after the given timestamp,
 * if one is available.
 *
 * @param timeUs Timestamp adjacent to which to find a synchronization sample.
 * @return index Index of the synchronization sample, or {@link C#INDEX_UNSET} if none.
 */
public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) {
  int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false);
  for (int i = startIndex; i < timestampsUs.length; i++) {
    if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      return i;
    }
  }
  return C.INDEX_UNSET;
}
 
Example 9
Source File: TrackSampleTable.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns the sample index of the closest synchronization sample at or after the given timestamp,
 * if one is available.
 *
 * @param timeUs Timestamp adjacent to which to find a synchronization sample.
 * @return index Index of the synchronization sample, or {@link C#INDEX_UNSET} if none.
 */
public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) {
  int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false);
  for (int i = startIndex; i < timestampsUs.length; i++) {
    if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      return i;
    }
  }
  return C.INDEX_UNSET;
}
 
Example 10
Source File: TrackSampleTable.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns the sample index of the closest synchronization sample at or after the given timestamp,
 * if one is available.
 *
 * @param timeUs Timestamp adjacent to which to find a synchronization sample.
 * @return index Index of the synchronization sample, or {@link C#INDEX_UNSET} if none.
 */
public int getIndexOfLaterOrEqualSynchronizationSample(long timeUs) {
  int startIndex = Util.binarySearchCeil(timestampsUs, timeUs, true, false);
  for (int i = startIndex; i < timestampsUs.length; i++) {
    if ((flags[i] & C.BUFFER_FLAG_KEY_FRAME) != 0) {
      return i;
    }
  }
  return C.INDEX_UNSET;
}
 
Example 11
Source File: H264Reader.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
private void outputSample(int offset) {
  @C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
  int size = (int) (nalUnitStartPosition - samplePosition);
  output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
}
 
Example 12
Source File: H264Reader.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
private void outputSample(int offset) {
  @C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
  int size = (int) (nalUnitStartPosition - samplePosition);
  output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
}
 
Example 13
Source File: H265Reader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
private void outputSample(int offset) {
  @C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
  int size = (int) (nalUnitStartPosition - samplePosition);
  output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
}
 
Example 14
Source File: MatroskaExtractor.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
void endMasterElement(int id) throws ParserException {
  switch (id) {
    case ID_SEGMENT_INFO:
      if (timecodeScale == C.TIME_UNSET) {
        // timecodeScale was omitted. Use the default value.
        timecodeScale = 1000000;
      }
      if (durationTimecode != C.TIME_UNSET) {
        durationUs = scaleTimecodeToUs(durationTimecode);
      }
      break;
    case ID_SEEK:
      if (seekEntryId == UNSET_ENTRY_ID || seekEntryPosition == C.POSITION_UNSET) {
        throw new ParserException("Mandatory element SeekID or SeekPosition not found");
      }
      if (seekEntryId == ID_CUES) {
        cuesContentPosition = seekEntryPosition;
      }
      break;
    case ID_CUES:
      if (!sentSeekMap) {
        extractorOutput.seekMap(buildSeekMap());
        sentSeekMap = true;
      } else {
        // We have already built the cues. Ignore.
      }
      break;
    case ID_BLOCK_GROUP:
      if (blockState != BLOCK_STATE_DATA) {
        // We've skipped this block (due to incompatible track number).
        return;
      }
      // If the ReferenceBlock element was not found for this sample, then it is a keyframe.
      if (!sampleSeenReferenceBlock) {
        blockFlags |= C.BUFFER_FLAG_KEY_FRAME;
      }
      commitSampleToOutput(tracks.get(blockTrackNumber), blockTimeUs);
      blockState = BLOCK_STATE_START;
      break;
    case ID_CONTENT_ENCODING:
      if (currentTrack.hasContentEncryption) {
        if (currentTrack.cryptoData == null) {
          throw new ParserException("Encrypted Track found but ContentEncKeyID was not found");
        }
        currentTrack.drmInitData = new DrmInitData(new SchemeData(C.UUID_NIL,
            MimeTypes.VIDEO_WEBM, currentTrack.cryptoData.encryptionKey));
      }
      break;
    case ID_CONTENT_ENCODINGS:
      if (currentTrack.hasContentEncryption && currentTrack.sampleStrippedBytes != null) {
        throw new ParserException("Combining encryption and compression is not supported");
      }
      break;
    case ID_TRACK_ENTRY:
      if (isCodecSupported(currentTrack.codecId)) {
        currentTrack.initializeOutput(extractorOutput, currentTrack.number);
        tracks.put(currentTrack.number, currentTrack);
      }
      currentTrack = null;
      break;
    case ID_TRACKS:
      if (tracks.size() == 0) {
        throw new ParserException("No valid tracks were found");
      }
      extractorOutput.endTracks();
      break;
    default:
      break;
  }
}
 
Example 15
Source File: MatroskaExtractor.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
void endMasterElement(int id) throws ParserException {
  switch (id) {
    case ID_SEGMENT_INFO:
      if (timecodeScale == C.TIME_UNSET) {
        // timecodeScale was omitted. Use the default value.
        timecodeScale = 1000000;
      }
      if (durationTimecode != C.TIME_UNSET) {
        durationUs = scaleTimecodeToUs(durationTimecode);
      }
      break;
    case ID_SEEK:
      if (seekEntryId == UNSET_ENTRY_ID || seekEntryPosition == C.POSITION_UNSET) {
        throw new ParserException("Mandatory element SeekID or SeekPosition not found");
      }
      if (seekEntryId == ID_CUES) {
        cuesContentPosition = seekEntryPosition;
      }
      break;
    case ID_CUES:
      if (!sentSeekMap) {
        extractorOutput.seekMap(buildSeekMap());
        sentSeekMap = true;
      } else {
        // We have already built the cues. Ignore.
      }
      break;
    case ID_BLOCK_GROUP:
      if (blockState != BLOCK_STATE_DATA) {
        // We've skipped this block (due to incompatible track number).
        return;
      }
      // If the ReferenceBlock element was not found for this sample, then it is a keyframe.
      if (!sampleSeenReferenceBlock) {
        blockFlags |= C.BUFFER_FLAG_KEY_FRAME;
      }
      commitSampleToOutput(tracks.get(blockTrackNumber), blockTimeUs);
      blockState = BLOCK_STATE_START;
      break;
    case ID_CONTENT_ENCODING:
      if (currentTrack.hasContentEncryption) {
        if (currentTrack.cryptoData == null) {
          throw new ParserException("Encrypted Track found but ContentEncKeyID was not found");
        }
        currentTrack.drmInitData = new DrmInitData(new SchemeData(C.UUID_NIL,
            MimeTypes.VIDEO_WEBM, currentTrack.cryptoData.encryptionKey));
      }
      break;
    case ID_CONTENT_ENCODINGS:
      if (currentTrack.hasContentEncryption && currentTrack.sampleStrippedBytes != null) {
        throw new ParserException("Combining encryption and compression is not supported");
      }
      break;
    case ID_TRACK_ENTRY:
      if (isCodecSupported(currentTrack.codecId)) {
        currentTrack.initializeOutput(extractorOutput, currentTrack.number);
        tracks.put(currentTrack.number, currentTrack);
      }
      currentTrack = null;
      break;
    case ID_TRACKS:
      if (tracks.size() == 0) {
        throw new ParserException("No valid tracks were found");
      }
      extractorOutput.endTracks();
      break;
    default:
      break;
  }
}
 
Example 16
Source File: FixedSampleSizeRechunker.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Rechunk the given fixed sample size input to produce a new sequence of samples.
 *
 * @param fixedSampleSize Size in bytes of each sample.
 * @param chunkOffsets Chunk offsets in the MP4 stream to rechunk.
 * @param chunkSampleCounts Sample counts for each of the MP4 stream's chunks.
 * @param timestampDeltaInTimeUnits Timestamp delta between each sample in time units.
 */
public static Results rechunk(int fixedSampleSize, long[] chunkOffsets, int[] chunkSampleCounts,
    long timestampDeltaInTimeUnits) {
  int maxSampleCount = MAX_SAMPLE_SIZE / fixedSampleSize;

  // Count the number of new, rechunked buffers.
  int rechunkedSampleCount = 0;
  for (int chunkSampleCount : chunkSampleCounts) {
    rechunkedSampleCount += Util.ceilDivide(chunkSampleCount, maxSampleCount);
  }

  long[] offsets = new long[rechunkedSampleCount];
  int[] sizes = new int[rechunkedSampleCount];
  int maximumSize = 0;
  long[] timestamps = new long[rechunkedSampleCount];
  int[] flags = new int[rechunkedSampleCount];

  int originalSampleIndex = 0;
  int newSampleIndex = 0;
  for (int chunkIndex = 0; chunkIndex < chunkSampleCounts.length; chunkIndex++) {
    int chunkSamplesRemaining = chunkSampleCounts[chunkIndex];
    long sampleOffset = chunkOffsets[chunkIndex];

    while (chunkSamplesRemaining > 0) {
      int bufferSampleCount = Math.min(maxSampleCount, chunkSamplesRemaining);

      offsets[newSampleIndex] = sampleOffset;
      sizes[newSampleIndex] = fixedSampleSize * bufferSampleCount;
      maximumSize = Math.max(maximumSize, sizes[newSampleIndex]);
      timestamps[newSampleIndex] = (timestampDeltaInTimeUnits * originalSampleIndex);
      flags[newSampleIndex] = C.BUFFER_FLAG_KEY_FRAME;

      sampleOffset += sizes[newSampleIndex];
      originalSampleIndex += bufferSampleCount;

      chunkSamplesRemaining -= bufferSampleCount;
      newSampleIndex++;
    }
  }
  long duration = timestampDeltaInTimeUnits * originalSampleIndex;

  return new Results(offsets, sizes, maximumSize, timestamps, flags, duration);
}
 
Example 17
Source File: SampleMetadataQueue.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
public synchronized void commitSample(long timeUs, @C.BufferFlags int sampleFlags, long offset,
    int size, CryptoData cryptoData) {
  if (upstreamKeyframeRequired) {
    if ((sampleFlags & C.BUFFER_FLAG_KEY_FRAME) == 0) {
      return;
    }
    upstreamKeyframeRequired = false;
  }
  Assertions.checkState(!upstreamFormatRequired);

  isLastSampleQueued = (sampleFlags & C.BUFFER_FLAG_LAST_SAMPLE) != 0;
  largestQueuedTimestampUs = Math.max(largestQueuedTimestampUs, timeUs);

  int relativeEndIndex = getRelativeIndex(length);
  timesUs[relativeEndIndex] = timeUs;
  offsets[relativeEndIndex] = offset;
  sizes[relativeEndIndex] = size;
  flags[relativeEndIndex] = sampleFlags;
  cryptoDatas[relativeEndIndex] = cryptoData;
  formats[relativeEndIndex] = upstreamFormat;
  sourceIds[relativeEndIndex] = upstreamSourceId;

  length++;
  if (length == capacity) {
    // Increase the capacity.
    int newCapacity = capacity + SAMPLE_CAPACITY_INCREMENT;
    int[] newSourceIds = new int[newCapacity];
    long[] newOffsets = new long[newCapacity];
    long[] newTimesUs = new long[newCapacity];
    int[] newFlags = new int[newCapacity];
    int[] newSizes = new int[newCapacity];
    CryptoData[] newCryptoDatas = new CryptoData[newCapacity];
    Format[] newFormats = new Format[newCapacity];
    int beforeWrap = capacity - relativeFirstIndex;
    System.arraycopy(offsets, relativeFirstIndex, newOffsets, 0, beforeWrap);
    System.arraycopy(timesUs, relativeFirstIndex, newTimesUs, 0, beforeWrap);
    System.arraycopy(flags, relativeFirstIndex, newFlags, 0, beforeWrap);
    System.arraycopy(sizes, relativeFirstIndex, newSizes, 0, beforeWrap);
    System.arraycopy(cryptoDatas, relativeFirstIndex, newCryptoDatas, 0, beforeWrap);
    System.arraycopy(formats, relativeFirstIndex, newFormats, 0, beforeWrap);
    System.arraycopy(sourceIds, relativeFirstIndex, newSourceIds, 0, beforeWrap);
    int afterWrap = relativeFirstIndex;
    System.arraycopy(offsets, 0, newOffsets, beforeWrap, afterWrap);
    System.arraycopy(timesUs, 0, newTimesUs, beforeWrap, afterWrap);
    System.arraycopy(flags, 0, newFlags, beforeWrap, afterWrap);
    System.arraycopy(sizes, 0, newSizes, beforeWrap, afterWrap);
    System.arraycopy(cryptoDatas, 0, newCryptoDatas, beforeWrap, afterWrap);
    System.arraycopy(formats, 0, newFormats, beforeWrap, afterWrap);
    System.arraycopy(sourceIds, 0, newSourceIds, beforeWrap, afterWrap);
    offsets = newOffsets;
    timesUs = newTimesUs;
    flags = newFlags;
    sizes = newSizes;
    cryptoDatas = newCryptoDatas;
    formats = newFormats;
    sourceIds = newSourceIds;
    relativeFirstIndex = 0;
    length = capacity;
    capacity = newCapacity;
  }
}
 
Example 18
Source File: H264Reader.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
private void outputSample(int offset) {
  @C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
  int size = (int) (nalUnitStartPosition - samplePosition);
  output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
}
 
Example 19
Source File: FixedSampleSizeRechunker.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Rechunk the given fixed sample size input to produce a new sequence of samples.
 *
 * @param fixedSampleSize Size in bytes of each sample.
 * @param chunkOffsets Chunk offsets in the MP4 stream to rechunk.
 * @param chunkSampleCounts Sample counts for each of the MP4 stream's chunks.
 * @param timestampDeltaInTimeUnits Timestamp delta between each sample in time units.
 */
public static Results rechunk(int fixedSampleSize, long[] chunkOffsets, int[] chunkSampleCounts,
    long timestampDeltaInTimeUnits) {
  int maxSampleCount = MAX_SAMPLE_SIZE / fixedSampleSize;

  // Count the number of new, rechunked buffers.
  int rechunkedSampleCount = 0;
  for (int chunkSampleCount : chunkSampleCounts) {
    rechunkedSampleCount += Util.ceilDivide(chunkSampleCount, maxSampleCount);
  }

  long[] offsets = new long[rechunkedSampleCount];
  int[] sizes = new int[rechunkedSampleCount];
  int maximumSize = 0;
  long[] timestamps = new long[rechunkedSampleCount];
  int[] flags = new int[rechunkedSampleCount];

  int originalSampleIndex = 0;
  int newSampleIndex = 0;
  for (int chunkIndex = 0; chunkIndex < chunkSampleCounts.length; chunkIndex++) {
    int chunkSamplesRemaining = chunkSampleCounts[chunkIndex];
    long sampleOffset = chunkOffsets[chunkIndex];

    while (chunkSamplesRemaining > 0) {
      int bufferSampleCount = Math.min(maxSampleCount, chunkSamplesRemaining);

      offsets[newSampleIndex] = sampleOffset;
      sizes[newSampleIndex] = fixedSampleSize * bufferSampleCount;
      maximumSize = Math.max(maximumSize, sizes[newSampleIndex]);
      timestamps[newSampleIndex] = (timestampDeltaInTimeUnits * originalSampleIndex);
      flags[newSampleIndex] = C.BUFFER_FLAG_KEY_FRAME;

      sampleOffset += sizes[newSampleIndex];
      originalSampleIndex += bufferSampleCount;

      chunkSamplesRemaining -= bufferSampleCount;
      newSampleIndex++;
    }
  }
  long duration = timestampDeltaInTimeUnits * originalSampleIndex;

  return new Results(offsets, sizes, maximumSize, timestamps, flags, duration);
}
 
Example 20
Source File: H265Reader.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
private void outputSample(int offset) {
  @C.BufferFlags int flags = sampleIsKeyframe ? C.BUFFER_FLAG_KEY_FRAME : 0;
  int size = (int) (nalUnitStartPosition - samplePosition);
  output.sampleMetadata(sampleTimeUs, flags, size, offset, null);
}