Java 类com.google.android.exoplayer2.decoder.DecoderInputBuffer 实例源码

项目:Exoplayer2Radio    文件:HlsSampleStreamWrapper.java   
int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean requireFormat) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }

  while (mediaChunks.size() > 1 && finishedReadingChunk(mediaChunks.getFirst())) {
    mediaChunks.removeFirst();
  }
  HlsMediaChunk currentChunk = mediaChunks.getFirst();
  Format trackFormat = currentChunk.trackFormat;
  if (!trackFormat.equals(downstreamTrackFormat)) {
    eventDispatcher.downstreamFormatChanged(trackType, trackFormat,
        currentChunk.trackSelectionReason, currentChunk.trackSelectionData,
        currentChunk.startTimeUs);
  }
  downstreamTrackFormat = trackFormat;

  return sampleQueues.valueAt(group).readData(formatHolder, buffer, requireFormat,
      loadingFinished, lastSeekPositionUs);
}
项目:Exoplayer2Radio    文件:BaseRenderer.java   
/**
 * Reads from the enabled upstream source. If the upstream source has been read to the end then
 * {@link C#RESULT_BUFFER_READ} is only returned if {@link #setCurrentStreamFinal()} has been
 * called. {@link C#RESULT_NOTHING_READ} is returned otherwise.
 *
 * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
 * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
 *     end of the stream. If the end of the stream has been reached, the
 *     {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
 * @param formatRequired Whether the caller requires that the format of the stream be read even if
 *     it's not changing. A sample will never be read if set to true, however it is still possible
 *     for the end of stream or nothing to be read.
 * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
 *     {@link C#RESULT_BUFFER_READ}.
 */
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  int result = stream.readData(formatHolder, buffer, formatRequired);
  if (result == C.RESULT_BUFFER_READ) {
    if (buffer.isEndOfStream()) {
      readEndOfStream = true;
      return streamIsFinal ? C.RESULT_BUFFER_READ : C.RESULT_NOTHING_READ;
    }
    buffer.timeUs += streamOffsetUs;
  } else if (result == C.RESULT_FORMAT_READ) {
    Format format = formatHolder.format;
    if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
      format = format.copyWithSubsampleOffsetUs(format.subsampleOffsetUs + streamOffsetUs);
      formatHolder.format = format;
    }
  }
  return result;
}
项目:Exoplayer2Radio    文件:ClippingMediaPeriod.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean requireFormat) {
  if (pendingDiscontinuity) {
    return C.RESULT_NOTHING_READ;
  }
  if (sentEos) {
    buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
    return C.RESULT_BUFFER_READ;
  }
  int result = stream.readData(formatHolder, buffer, requireFormat);
  // TODO: Clear gapless playback metadata if a format was read (if applicable).
  if (endUs != C.TIME_END_OF_SOURCE && ((result == C.RESULT_BUFFER_READ
      && buffer.timeUs >= endUs) || (result == C.RESULT_NOTHING_READ
      && mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE))) {
    buffer.clear();
    buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
    sentEos = true;
    return C.RESULT_BUFFER_READ;
  }
  if (result == C.RESULT_BUFFER_READ && !buffer.isEndOfStream()) {
    buffer.timeUs -= startUs;
  }
  return result;
}
项目:Exoplayer2Radio    文件:SingleSampleMediaPeriod.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean requireFormat) {
  if (streamState == STREAM_STATE_END_OF_STREAM) {
    buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
    return C.RESULT_BUFFER_READ;
  } else if (requireFormat || streamState == STREAM_STATE_SEND_FORMAT) {
    formatHolder.format = format;
    streamState = STREAM_STATE_SEND_SAMPLE;
    return C.RESULT_FORMAT_READ;
  }

  Assertions.checkState(streamState == STREAM_STATE_SEND_SAMPLE);
  if (!loadingFinished) {
    return C.RESULT_NOTHING_READ;
  } else {
    buffer.timeUs = 0;
    buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
    buffer.ensureSpaceForWrite(sampleSize);
    buffer.data.put(sampleData, 0, sampleSize);
    streamState = STREAM_STATE_END_OF_STREAM;
    return C.RESULT_BUFFER_READ;
  }
}
项目:Exoplayer2Radio    文件:MediaCodecRenderer.java   
/**
 * @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
 *     constants defined in {@link C}.
 * @param mediaCodecSelector A decoder selector.
 * @param drmSessionManager For use with encrypted media. May be null if support for encrypted
 *     media is not required.
 * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions.
 *     For example a media file may start with a short clear region so as to allow playback to
 *     begin in parallel with key acquisition. This parameter specifies whether the renderer is
 *     permitted to play clear regions of encrypted media files before {@code drmSessionManager}
 *     has obtained the keys necessary to decrypt encrypted regions of the media.
 */
public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector,
    DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
    boolean playClearSamplesWithoutKeys) {
  super(trackType);
  Assertions.checkState(Util.SDK_INT >= 16);
  this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector);
  this.drmSessionManager = drmSessionManager;
  this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
  buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
  flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance();
  formatHolder = new FormatHolder();
  decodeOnlyPresentationTimestamps = new ArrayList<>();
  outputBufferInfo = new MediaCodec.BufferInfo();
  codecReconfigurationState = RECONFIGURATION_STATE_NONE;
  codecReinitializationState = REINITIALIZATION_STATE_NONE;
}
项目:K-Sonic    文件:BaseRenderer.java   
/**
 * Reads from the enabled upstream source. If the upstream source has been read to the end then
 * {@link C#RESULT_BUFFER_READ} is only returned if {@link #setCurrentStreamFinal()} has been
 * called. {@link C#RESULT_NOTHING_READ} is returned otherwise.
 *
 * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
 * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
 *     end of the stream. If the end of the stream has been reached, the
 *     {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
 * @param formatRequired Whether the caller requires that the format of the stream be read even if
 *     it's not changing. A sample will never be read if set to true, however it is still possible
 *     for the end of stream or nothing to be read.
 * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
 *     {@link C#RESULT_BUFFER_READ}.
 */
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  int result = stream.readData(formatHolder, buffer, formatRequired);
  if (result == C.RESULT_BUFFER_READ) {
    if (buffer.isEndOfStream()) {
      readEndOfStream = true;
      return streamIsFinal ? C.RESULT_BUFFER_READ : C.RESULT_NOTHING_READ;
    }
    buffer.timeUs += streamOffsetUs;
  } else if (result == C.RESULT_FORMAT_READ) {
    Format format = formatHolder.format;
    if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
      format = format.copyWithSubsampleOffsetUs(format.subsampleOffsetUs + streamOffsetUs);
      formatHolder.format = format;
    }
  }
  return result;
}
项目:K-Sonic    文件:HlsSampleStreamWrapper.java   
int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean requireFormat) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }

  while (mediaChunks.size() > 1 && finishedReadingChunk(mediaChunks.getFirst())) {
    mediaChunks.removeFirst();
  }
  HlsMediaChunk currentChunk = mediaChunks.getFirst();
  Format trackFormat = currentChunk.trackFormat;
  if (!trackFormat.equals(downstreamTrackFormat)) {
    eventDispatcher.downstreamFormatChanged(trackType, trackFormat,
        currentChunk.trackSelectionReason, currentChunk.trackSelectionData,
        currentChunk.startTimeUs);
  }
  downstreamTrackFormat = trackFormat;

  return sampleQueues.valueAt(group).readData(formatHolder, buffer, requireFormat,
      loadingFinished, lastSeekPositionUs);
}
项目:K-Sonic    文件:ClippingMediaPeriod.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean requireFormat) {
  if (pendingDiscontinuity) {
    return C.RESULT_NOTHING_READ;
  }
  if (sentEos) {
    buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
    return C.RESULT_BUFFER_READ;
  }
  int result = stream.readData(formatHolder, buffer, requireFormat);
  // TODO: Clear gapless playback metadata if a format was read (if applicable).
  if (endUs != C.TIME_END_OF_SOURCE && ((result == C.RESULT_BUFFER_READ
      && buffer.timeUs >= endUs) || (result == C.RESULT_NOTHING_READ
      && mediaPeriod.getBufferedPositionUs() == C.TIME_END_OF_SOURCE))) {
    buffer.clear();
    buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
    sentEos = true;
    return C.RESULT_BUFFER_READ;
  }
  if (result == C.RESULT_BUFFER_READ && !buffer.isEndOfStream()) {
    buffer.timeUs -= startUs;
  }
  return result;
}
项目:K-Sonic    文件:SingleSampleMediaPeriod.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean requireFormat) {
  if (streamState == STREAM_STATE_END_OF_STREAM) {
    buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
    return C.RESULT_BUFFER_READ;
  } else if (requireFormat || streamState == STREAM_STATE_SEND_FORMAT) {
    formatHolder.format = format;
    streamState = STREAM_STATE_SEND_SAMPLE;
    return C.RESULT_FORMAT_READ;
  }

  Assertions.checkState(streamState == STREAM_STATE_SEND_SAMPLE);
  if (!loadingFinished) {
    return C.RESULT_NOTHING_READ;
  } else {
    buffer.timeUs = 0;
    buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
    buffer.ensureSpaceForWrite(sampleSize);
    buffer.data.put(sampleData, 0, sampleSize);
    streamState = STREAM_STATE_END_OF_STREAM;
    return C.RESULT_BUFFER_READ;
  }
}
项目:K-Sonic    文件:MediaCodecRenderer.java   
/**
 * @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
 *     constants defined in {@link C}.
 * @param mediaCodecSelector A decoder selector.
 * @param drmSessionManager For use with encrypted media. May be null if support for encrypted
 *     media is not required.
 * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions.
 *     For example a media file may start with a short clear region so as to allow playback to
 *     begin in parallel with key acquisition. This parameter specifies whether the renderer is
 *     permitted to play clear regions of encrypted media files before {@code drmSessionManager}
 *     has obtained the keys necessary to decrypt encrypted regions of the media.
 */
public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector,
    DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
    boolean playClearSamplesWithoutKeys) {
  super(trackType);
  Assertions.checkState(Util.SDK_INT >= 16);
  this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector);
  this.drmSessionManager = drmSessionManager;
  this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
  buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
  formatHolder = new FormatHolder();
  decodeOnlyPresentationTimestamps = new ArrayList<>();
  outputBufferInfo = new MediaCodec.BufferInfo();
  codecReconfigurationState = RECONFIGURATION_STATE_NONE;
  codecReinitializationState = REINITIALIZATION_STATE_NONE;
}
项目:videoPickPlayer    文件:HlsSampleStreamWrapper.java   
int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }

  while (mediaChunks.size() > 1 && finishedReadingChunk(mediaChunks.getFirst())) {
    mediaChunks.removeFirst();
  }
  HlsMediaChunk currentChunk = mediaChunks.getFirst();
  Format trackFormat = currentChunk.trackFormat;
  if (!trackFormat.equals(downstreamTrackFormat)) {
    eventDispatcher.downstreamFormatChanged(trackType, trackFormat,
        currentChunk.trackSelectionReason, currentChunk.trackSelectionData,
        currentChunk.startTimeUs);
  }
  downstreamTrackFormat = trackFormat;

  return sampleQueues.valueAt(group).readData(formatHolder, buffer, loadingFinished,
      lastSeekPositionUs);
}
项目:videoPickPlayer    文件:ChunkSampleStream.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }

  while (mediaChunks.size() > 1
      && mediaChunks.get(1).getFirstSampleIndex() <= sampleQueue.getReadIndex()) {
    mediaChunks.removeFirst();
  }
  BaseMediaChunk currentChunk = mediaChunks.getFirst();

  Format trackFormat = currentChunk.trackFormat;
  if (!trackFormat.equals(downstreamTrackFormat)) {
    eventDispatcher.downstreamFormatChanged(trackType, trackFormat,
        currentChunk.trackSelectionReason, currentChunk.trackSelectionData,
        currentChunk.startTimeUs);
  }
  downstreamTrackFormat = trackFormat;
  return sampleQueue.readData(formatHolder, buffer, loadingFinished, lastSeekPositionUs);
}
项目:videoPickPlayer    文件:SingleSampleMediaPeriod.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer) {
  if (streamState == STREAM_STATE_END_OF_STREAM) {
    buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
    return C.RESULT_BUFFER_READ;
  } else if (streamState == STREAM_STATE_SEND_FORMAT) {
    formatHolder.format = format;
    streamState = STREAM_STATE_SEND_SAMPLE;
    return C.RESULT_FORMAT_READ;
  }

  Assertions.checkState(streamState == STREAM_STATE_SEND_SAMPLE);
  if (!loadingFinished) {
    return C.RESULT_NOTHING_READ;
  } else {
    buffer.timeUs = 0;
    buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
    buffer.ensureSpaceForWrite(sampleSize);
    buffer.data.put(sampleData, 0, sampleSize);
    streamState = STREAM_STATE_END_OF_STREAM;
    return C.RESULT_BUFFER_READ;
  }
}
项目:videoPickPlayer    文件:MediaCodecRenderer.java   
/**
 * @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
 *     constants defined in {@link C}.
 * @param mediaCodecSelector A decoder selector.
 * @param drmSessionManager For use with encrypted media. May be null if support for encrypted
 *     media is not required.
 * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions.
 *     For example a media file may start with a short clear region so as to allow playback to
 *     begin in parallel with key acquisition. This parameter specifies whether the renderer is
 *     permitted to play clear regions of encrypted media files before {@code drmSessionManager}
 *     has obtained the keys necessary to decrypt encrypted regions of the media.
 */
public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector,
    DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
    boolean playClearSamplesWithoutKeys) {
  super(trackType);
  Assertions.checkState(Util.SDK_INT >= 16);
  this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector);
  this.drmSessionManager = drmSessionManager;
  this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
  buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
  formatHolder = new FormatHolder();
  decodeOnlyPresentationTimestamps = new ArrayList<>();
  outputBufferInfo = new MediaCodec.BufferInfo();
  codecReconfigurationState = RECONFIGURATION_STATE_NONE;
  codecReinitializationState = REINITIALIZATION_STATE_NONE;
}
项目:Komica    文件:VpxDecoder.java   
/**
 * Creates a VP9 decoder.
 *
 * @param numInputBuffers The number of input buffers.
 * @param numOutputBuffers The number of output buffers.
 * @param initialInputBufferSize The initial size of each input buffer.
 * @param exoMediaCrypto The {@link ExoMediaCrypto} object required for decoding encrypted
 *     content. Maybe null and can be ignored if decoder does not handle encrypted content.
 * @throws VpxDecoderException Thrown if an exception occurs when initializing the decoder.
 */
public VpxDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize,
    ExoMediaCrypto exoMediaCrypto) throws VpxDecoderException {
  super(new DecoderInputBuffer[numInputBuffers], new VpxOutputBuffer[numOutputBuffers]);
  if (!VpxLibrary.isAvailable()) {
    throw new VpxDecoderException("Failed to load decoder native libraries.");
  }
  this.exoMediaCrypto = exoMediaCrypto;
  if (exoMediaCrypto != null && !VpxLibrary.vpxIsSecureDecodeSupported()) {
    throw new VpxDecoderException("Vpx decoder does not support secure decode.");
  }
  vpxDecContext = vpxInit();
  if (vpxDecContext == 0) {
    throw new VpxDecoderException("Failed to initialize decoder");
  }
  setInitialInputBufferSize(initialInputBufferSize);
}
项目:Komica    文件:FlacDecoder.java   
/**
 * Creates a Flac decoder.
 *
 * @param numInputBuffers The number of input buffers.
 * @param numOutputBuffers The number of output buffers.
 * @param initializationData Codec-specific initialization data. It should contain only one entry
 *    which is the flac file header.
 * @throws FlacDecoderException Thrown if an exception occurs when initializing the decoder.
 */
public FlacDecoder(int numInputBuffers, int numOutputBuffers, List<byte[]> initializationData)
    throws FlacDecoderException {
  super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]);
  if (initializationData.size() != 1) {
    throw new FlacDecoderException("Initialization data must be of length 1");
  }
  decoderJni = new FlacDecoderJni();
  decoderJni.setData(ByteBuffer.wrap(initializationData.get(0)));
  FlacStreamInfo streamInfo;
  try {
    streamInfo = decoderJni.decodeMetadata();
  } catch (IOException | InterruptedException e) {
    // Never happens.
    throw new IllegalStateException(e);
  }
  if (streamInfo == null) {
    throw new FlacDecoderException("Metadata decoding failed");
  }

  setInitialInputBufferSize(streamInfo.maxFrameSize);
  maxOutputBufferSize = streamInfo.maxDecodedFrameSize();
}
项目:Komica    文件:FlacDecoder.java   
@Override
public FlacDecoderException decode(DecoderInputBuffer inputBuffer,
    SimpleOutputBuffer outputBuffer, boolean reset) {
  if (reset) {
    decoderJni.flush();
  }
  decoderJni.setData(inputBuffer.data);
  ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, maxOutputBufferSize);
  int result;
  try {
    result = decoderJni.decodeSample(outputData);
  } catch (IOException | InterruptedException e) {
    // Never happens.
    throw new IllegalStateException(e);
  }
  if (result < 0) {
    return new FlacDecoderException("Frame decoding failed");
  }
  outputData.position(0);
  outputData.limit(result);
  return null;
}
项目:Komica    文件:FfmpegDecoder.java   
@Override
public FfmpegDecoderException decode(DecoderInputBuffer inputBuffer,
    SimpleOutputBuffer outputBuffer, boolean reset) {
  if (reset) {
    nativeContext = ffmpegReset(nativeContext, extraData);
    if (nativeContext == 0) {
      return new FfmpegDecoderException("Error resetting (see logcat).");
    }
  }
  ByteBuffer inputData = inputBuffer.data;
  int inputSize = inputData.limit();
  ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, OUTPUT_BUFFER_SIZE);
  int result = ffmpegDecode(nativeContext, inputData, inputSize, outputData, OUTPUT_BUFFER_SIZE);
  if (result < 0) {
    return new FfmpegDecoderException("Error decoding (see logcat). Code: " + result);
  }
  if (!hasOutputFormat) {
    channelCount = ffmpegGetChannelCount(nativeContext);
    sampleRate = ffmpegGetSampleRate(nativeContext);
    hasOutputFormat = true;
  }
  outputBuffer.data.position(0);
  outputBuffer.data.limit(result);
  return null;
}
项目:Jockey    文件:FlacDecoder.java   
/**
 * Creates a Flac decoder.
 *
 * @param numInputBuffers The number of input buffers.
 * @param numOutputBuffers The number of output buffers.
 * @param initializationData Codec-specific initialization data. It should contain only one entry
 *    which is the flac file header.
 * @throws FlacDecoderException Thrown if an exception occurs when initializing the decoder.
 */
public FlacDecoder(int numInputBuffers, int numOutputBuffers, List<byte[]> initializationData)
    throws FlacDecoderException {
  super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]);
  if (initializationData.size() != 1) {
    throw new FlacDecoderException("Initialization data must be of length 1");
  }
  decoderJni = new FlacDecoderJni();
  decoderJni.setData(ByteBuffer.wrap(initializationData.get(0)));
  FlacStreamInfo streamInfo;
  try {
    streamInfo = decoderJni.decodeMetadata();
  } catch (IOException | InterruptedException e) {
    // Never happens.
    throw new IllegalStateException(e);
  }
  if (streamInfo == null) {
    throw new FlacDecoderException("Metadata decoding failed");
  }

  setInitialInputBufferSize(streamInfo.maxFrameSize);
  maxOutputBufferSize = streamInfo.maxDecodedFrameSize();
}
项目:Jockey    文件:FlacDecoder.java   
@Override
public FlacDecoderException decode(DecoderInputBuffer inputBuffer,
    SimpleOutputBuffer outputBuffer, boolean reset) {
  if (reset) {
    decoderJni.flush();
  }
  decoderJni.setData(inputBuffer.data);
  ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, maxOutputBufferSize);
  int result;
  try {
    result = decoderJni.decodeSample(outputData);
  } catch (IOException | InterruptedException e) {
    // Never happens.
    throw new IllegalStateException(e);
  }
  if (result < 0) {
    return new FlacDecoderException("Frame decoding failed");
  }
  outputData.position(0);
  outputData.limit(result);
  return null;
}
项目:transistor    文件:LibvpxVideoRenderer.java   
/**
 * @param scaleToFit Whether video frames should be scaled to fit when rendering.
 * @param allowedJoiningTimeMs The maximum duration in milliseconds for which this video renderer
 *     can attempt to seamlessly join an ongoing playback.
 * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
 *     null if delivery of events is not required.
 * @param eventListener A listener of events. May be null if delivery of events is not required.
 * @param maxDroppedFramesToNotify The maximum number of frames that can be dropped between
 *     invocations of {@link VideoRendererEventListener#onDroppedFrames(int, long)}.
 * @param drmSessionManager For use with encrypted media. May be null if support for encrypted
 *     media is not required.
 * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions.
 *     For example a media file may start with a short clear region so as to allow playback to
 *     begin in parallel with key acquisition. This parameter specifies whether the renderer is
 *     permitted to play clear regions of encrypted media files before {@code drmSessionManager}
 *     has obtained the keys necessary to decrypt encrypted regions of the media.
 */
public LibvpxVideoRenderer(boolean scaleToFit, long allowedJoiningTimeMs,
    Handler eventHandler, VideoRendererEventListener eventListener,
    int maxDroppedFramesToNotify, DrmSessionManager<ExoMediaCrypto> drmSessionManager,
    boolean playClearSamplesWithoutKeys) {
  super(C.TRACK_TYPE_VIDEO);
  this.scaleToFit = scaleToFit;
  this.allowedJoiningTimeMs = allowedJoiningTimeMs;
  this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
  this.drmSessionManager = drmSessionManager;
  this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
  joiningDeadlineMs = C.TIME_UNSET;
  clearReportedVideoSize();
  formatHolder = new FormatHolder();
  flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance();
  eventDispatcher = new EventDispatcher(eventHandler, eventListener);
  outputMode = VpxDecoder.OUTPUT_MODE_NONE;
  decoderReinitializationState = REINITIALIZATION_STATE_NONE;
}
项目:transistor    文件:FlacDecoder.java   
/**
 * Creates a Flac decoder.
 *
 * @param numInputBuffers The number of input buffers.
 * @param numOutputBuffers The number of output buffers.
 * @param initializationData Codec-specific initialization data. It should contain only one entry
 *    which is the flac file header.
 * @throws FlacDecoderException Thrown if an exception occurs when initializing the decoder.
 */
public FlacDecoder(int numInputBuffers, int numOutputBuffers, List<byte[]> initializationData)
    throws FlacDecoderException {
  super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]);
  if (initializationData.size() != 1) {
    throw new FlacDecoderException("Initialization data must be of length 1");
  }
  decoderJni = new FlacDecoderJni();
  decoderJni.setData(ByteBuffer.wrap(initializationData.get(0)));
  FlacStreamInfo streamInfo;
  try {
    streamInfo = decoderJni.decodeMetadata();
  } catch (IOException | InterruptedException e) {
    // Never happens.
    throw new IllegalStateException(e);
  }
  if (streamInfo == null) {
    throw new FlacDecoderException("Metadata decoding failed");
  }

  setInitialInputBufferSize(streamInfo.maxFrameSize);
  maxOutputBufferSize = streamInfo.maxDecodedFrameSize();
}
项目:transistor    文件:FlacDecoder.java   
@Override
public FlacDecoderException decode(DecoderInputBuffer inputBuffer,
    SimpleOutputBuffer outputBuffer, boolean reset) {
  if (reset) {
    decoderJni.flush();
  }
  decoderJni.setData(inputBuffer.data);
  ByteBuffer outputData = outputBuffer.init(inputBuffer.timeUs, maxOutputBufferSize);
  int result;
  try {
    result = decoderJni.decodeSample(outputData);
  } catch (IOException | InterruptedException e) {
    // Never happens.
    throw new IllegalStateException(e);
  }
  if (result < 0) {
    return new FlacDecoderException("Frame decoding failed");
  }
  outputData.position(0);
  outputData.limit(result);
  return null;
}
项目:transistor    文件:FfmpegDecoder.java   
public FfmpegDecoder(int numInputBuffers, int numOutputBuffers, int initialInputBufferSize,
    String mimeType, List<byte[]> initializationData, boolean outputFloat)
    throws FfmpegDecoderException {
  super(new DecoderInputBuffer[numInputBuffers], new SimpleOutputBuffer[numOutputBuffers]);
  if (!FfmpegLibrary.isAvailable()) {
    throw new FfmpegDecoderException("Failed to load decoder native libraries.");
  }
  codecName = FfmpegLibrary.getCodecName(mimeType);
  extraData = getExtraData(mimeType, initializationData);
  encoding = outputFloat ? C.ENCODING_PCM_FLOAT : C.ENCODING_PCM_16BIT;
  outputBufferSize = outputFloat ? OUTPUT_BUFFER_SIZE_32BIT : OUTPUT_BUFFER_SIZE_16BIT;
  nativeContext = ffmpegInitialize(codecName, extraData, outputFloat);
  if (nativeContext == 0) {
    throw new FfmpegDecoderException("Initialization failed.");
  }
  setInitialInputBufferSize(initialInputBufferSize);
}
项目:transistor    文件:BaseRenderer.java   
/**
 * Reads from the enabled upstream source. If the upstream source has been read to the end then
 * {@link C#RESULT_BUFFER_READ} is only returned if {@link #setCurrentStreamFinal()} has been
 * called. {@link C#RESULT_NOTHING_READ} is returned otherwise.
 *
 * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
 * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
 *     end of the stream. If the end of the stream has been reached, the
 *     {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
 * @param formatRequired Whether the caller requires that the format of the stream be read even if
 *     it's not changing. A sample will never be read if set to true, however it is still possible
 *     for the end of stream or nothing to be read.
 * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
 *     {@link C#RESULT_BUFFER_READ}.
 */
protected final int readSource(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  int result = stream.readData(formatHolder, buffer, formatRequired);
  if (result == C.RESULT_BUFFER_READ) {
    if (buffer.isEndOfStream()) {
      readEndOfStream = true;
      return streamIsFinal ? C.RESULT_BUFFER_READ : C.RESULT_NOTHING_READ;
    }
    buffer.timeUs += streamOffsetUs;
  } else if (result == C.RESULT_FORMAT_READ) {
    Format format = formatHolder.format;
    if (format.subsampleOffsetUs != Format.OFFSET_SAMPLE_RELATIVE) {
      format = format.copyWithSubsampleOffsetUs(format.subsampleOffsetUs + streamOffsetUs);
      formatHolder.format = format;
    }
  }
  return result;
}
项目:transistor    文件:SingleSampleMediaPeriod.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean requireFormat) {
  if (streamState == STREAM_STATE_END_OF_STREAM) {
    buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
    return C.RESULT_BUFFER_READ;
  } else if (requireFormat || streamState == STREAM_STATE_SEND_FORMAT) {
    formatHolder.format = format;
    streamState = STREAM_STATE_SEND_SAMPLE;
    return C.RESULT_FORMAT_READ;
  } else if (loadingFinished) {
    if (loadingSucceeded) {
      buffer.timeUs = 0;
      buffer.addFlag(C.BUFFER_FLAG_KEY_FRAME);
      buffer.ensureSpaceForWrite(sampleSize);
      buffer.data.put(sampleData, 0, sampleSize);
    } else {
      buffer.addFlag(C.BUFFER_FLAG_END_OF_STREAM);
    }
    streamState = STREAM_STATE_END_OF_STREAM;
    return C.RESULT_BUFFER_READ;
  }
  return C.RESULT_NOTHING_READ;
}
项目:transistor    文件:MediaCodecRenderer.java   
/**
 * @param trackType The track type that the renderer handles. One of the {@code C.TRACK_TYPE_*}
 *     constants defined in {@link C}.
 * @param mediaCodecSelector A decoder selector.
 * @param drmSessionManager For use with encrypted media. May be null if support for encrypted
 *     media is not required.
 * @param playClearSamplesWithoutKeys Encrypted media may contain clear (un-encrypted) regions.
 *     For example a media file may start with a short clear region so as to allow playback to
 *     begin in parallel with key acquisition. This parameter specifies whether the renderer is
 *     permitted to play clear regions of encrypted media files before {@code drmSessionManager}
 *     has obtained the keys necessary to decrypt encrypted regions of the media.
 */
public MediaCodecRenderer(int trackType, MediaCodecSelector mediaCodecSelector,
    @Nullable DrmSessionManager<FrameworkMediaCrypto> drmSessionManager,
    boolean playClearSamplesWithoutKeys) {
  super(trackType);
  Assertions.checkState(Util.SDK_INT >= 16);
  this.mediaCodecSelector = Assertions.checkNotNull(mediaCodecSelector);
  this.drmSessionManager = drmSessionManager;
  this.playClearSamplesWithoutKeys = playClearSamplesWithoutKeys;
  buffer = new DecoderInputBuffer(DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED);
  flagsOnlyBuffer = DecoderInputBuffer.newFlagsOnlyInstance();
  formatHolder = new FormatHolder();
  decodeOnlyPresentationTimestamps = new ArrayList<>();
  outputBufferInfo = new MediaCodec.BufferInfo();
  codecReconfigurationState = RECONFIGURATION_STATE_NONE;
  codecReinitializationState = REINITIALIZATION_STATE_NONE;
}
项目:transistor    文件:SimpleDecoderAudioRendererTest.java   
@Before
public void setUp() throws Exception {
  MockitoAnnotations.initMocks(this);
  audioRenderer = new SimpleDecoderAudioRenderer(null, null, null, false, mockAudioSink) {
    @Override
    protected int supportsFormatInternal(DrmSessionManager<ExoMediaCrypto> drmSessionManager,
        Format format) {
      return FORMAT_HANDLED;
    }

    @Override
    protected SimpleDecoder<DecoderInputBuffer, ? extends SimpleOutputBuffer,
        ? extends AudioDecoderException> createDecoder(Format format, ExoMediaCrypto mediaCrypto)
        throws AudioDecoderException {
      return new FakeDecoder();
    }
  };
}
项目:Exoplayer2Radio    文件:DefaultTrackOutput.java   
/**
 * Attempts to read from the queue.
 *
 * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
 * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
 *     end of the stream. If the end of the stream has been reached, the
 *     {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
 * @param formatRequired Whether the caller requires that the format of the stream be read even if
 *     it's not changing. A sample will never be read if set to true, however it is still possible
 *     for the end of stream or nothing to be read.
 * @param loadingFinished True if an empty queue should be considered the end of the stream.
 * @param decodeOnlyUntilUs If a buffer is read, the {@link C#BUFFER_FLAG_DECODE_ONLY} flag will
 *     be set if the buffer's timestamp is less than this value.
 * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
 *     {@link C#RESULT_BUFFER_READ}.
 */
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired,
    boolean loadingFinished, long decodeOnlyUntilUs) {
  int result = infoQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
      downstreamFormat, extrasHolder);
  switch (result) {
    case C.RESULT_FORMAT_READ:
      downstreamFormat = formatHolder.format;
      return C.RESULT_FORMAT_READ;
    case C.RESULT_BUFFER_READ:
      if (!buffer.isEndOfStream()) {
        if (buffer.timeUs < decodeOnlyUntilUs) {
          buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
        }
        // Read encryption data if the sample is encrypted.
        if (buffer.isEncrypted()) {
          readEncryptionData(buffer, extrasHolder);
        }
        // Write the sample data into the holder.
        buffer.ensureSpaceForWrite(extrasHolder.size);
        readData(extrasHolder.offset, buffer.data, extrasHolder.size);
        // Advance the read head.
        dropDownstreamTo(extrasHolder.nextOffset);
      }
      return C.RESULT_BUFFER_READ;
    case C.RESULT_NOTHING_READ:
      return C.RESULT_NOTHING_READ;
    default:
      throw new IllegalStateException();
  }
}
项目:Exoplayer2Radio    文件:ExtractorMediaPeriod.java   
int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  if (notifyReset || isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }

  return sampleQueues.valueAt(track).readData(formatHolder, buffer, formatRequired,
      loadingFinished, lastSeekPositionUs);
}
项目:Exoplayer2Radio    文件:ChunkSampleStream.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }
  discardDownstreamMediaChunks(primarySampleQueue.getReadIndex());
  return primarySampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
      lastSeekPositionUs);
}
项目:Exoplayer2Radio    文件:ChunkSampleStream.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }
  return sampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
      lastSeekPositionUs);
}
项目:Exoplayer2Radio    文件:MediaCodecRenderer.java   
private static MediaCodec.CryptoInfo getFrameworkCryptoInfo(DecoderInputBuffer buffer,
    int adaptiveReconfigurationBytes) {
  MediaCodec.CryptoInfo cryptoInfo = buffer.cryptoInfo.getFrameworkCryptoInfoV16();
  if (adaptiveReconfigurationBytes == 0) {
    return cryptoInfo;
  }
  // There must be at least one sub-sample, although numBytesOfClearData is permitted to be
  // null if it contains no clear data. Instantiate it if needed, and add the reconfiguration
  // bytes to the clear byte count of the first sub-sample.
  if (cryptoInfo.numBytesOfClearData == null) {
    cryptoInfo.numBytesOfClearData = new int[1];
  }
  cryptoInfo.numBytesOfClearData[0] += adaptiveReconfigurationBytes;
  return cryptoInfo;
}
项目:K-Sonic    文件:DefaultTrackOutput.java   
/**
 * Attempts to read from the queue.
 *
 * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
 * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
 *     end of the stream. If the end of the stream has been reached, the
 *     {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
 * @param formatRequired Whether the caller requires that the format of the stream be read even if
 *     it's not changing. A sample will never be read if set to true, however it is still possible
 *     for the end of stream or nothing to be read.
 * @param loadingFinished True if an empty queue should be considered the end of the stream.
 * @param decodeOnlyUntilUs If a buffer is read, the {@link C#BUFFER_FLAG_DECODE_ONLY} flag will
 *     be set if the buffer's timestamp is less than this value.
 * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
 *     {@link C#RESULT_BUFFER_READ}.
 */
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean formatRequired,
    boolean loadingFinished, long decodeOnlyUntilUs) {
  int result = infoQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
      downstreamFormat, extrasHolder);
  switch (result) {
    case C.RESULT_FORMAT_READ:
      downstreamFormat = formatHolder.format;
      return C.RESULT_FORMAT_READ;
    case C.RESULT_BUFFER_READ:
      if (!buffer.isEndOfStream()) {
        if (buffer.timeUs < decodeOnlyUntilUs) {
          buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
        }
        // Read encryption data if the sample is encrypted.
        if (buffer.isEncrypted()) {
          readEncryptionData(buffer, extrasHolder);
        }
        // Write the sample data into the holder.
        buffer.ensureSpaceForWrite(extrasHolder.size);
        readData(extrasHolder.offset, buffer.data, extrasHolder.size);
        // Advance the read head.
        dropDownstreamTo(extrasHolder.nextOffset);
      }
      return C.RESULT_BUFFER_READ;
    case C.RESULT_NOTHING_READ:
      return C.RESULT_NOTHING_READ;
    default:
      throw new IllegalStateException();
  }
}
项目:K-Sonic    文件:ExtractorMediaPeriod.java   
int readData(int track, FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  if (notifyReset || isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }

  return sampleQueues.valueAt(track).readData(formatHolder, buffer, formatRequired,
      loadingFinished, lastSeekPositionUs);
}
项目:K-Sonic    文件:ChunkSampleStream.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }
  discardDownstreamMediaChunks(primarySampleQueue.getReadIndex());
  return primarySampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
      lastSeekPositionUs);
}
项目:K-Sonic    文件:ChunkSampleStream.java   
@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    boolean formatRequired) {
  if (isPendingReset()) {
    return C.RESULT_NOTHING_READ;
  }
  return sampleQueue.readData(formatHolder, buffer, formatRequired, loadingFinished,
      lastSeekPositionUs);
}
项目:K-Sonic    文件:MediaCodecRenderer.java   
private static MediaCodec.CryptoInfo getFrameworkCryptoInfo(DecoderInputBuffer buffer,
    int adaptiveReconfigurationBytes) {
  MediaCodec.CryptoInfo cryptoInfo = buffer.cryptoInfo.getFrameworkCryptoInfoV16();
  if (adaptiveReconfigurationBytes == 0) {
    return cryptoInfo;
  }
  // There must be at least one sub-sample, although numBytesOfClearData is permitted to be
  // null if it contains no clear data. Instantiate it if needed, and add the reconfiguration
  // bytes to the clear byte count of the first sub-sample.
  if (cryptoInfo.numBytesOfClearData == null) {
    cryptoInfo.numBytesOfClearData = new int[1];
  }
  cryptoInfo.numBytesOfClearData[0] += adaptiveReconfigurationBytes;
  return cryptoInfo;
}
项目:videoPickPlayer    文件:DefaultTrackOutput.java   
/**
 * Attempts to read from the queue.
 *
 * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
 * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
 *     end of the stream. If the end of the stream has been reached, the
 *     {@link C#BUFFER_FLAG_END_OF_STREAM} flag will be set on the buffer.
 * @param loadingFinished True if an empty queue should be considered the end of the stream.
 * @param decodeOnlyUntilUs If a buffer is read, the {@link C#BUFFER_FLAG_DECODE_ONLY} flag will
 *     be set if the buffer's timestamp is less than this value.
 * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ} or
 *     {@link C#RESULT_BUFFER_READ}.
 */
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, boolean loadingFinished,
    long decodeOnlyUntilUs) {
  switch (infoQueue.readData(formatHolder, buffer, downstreamFormat, extrasHolder)) {
    case C.RESULT_NOTHING_READ:
      if (loadingFinished) {
        buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
        return C.RESULT_BUFFER_READ;
      }
      return C.RESULT_NOTHING_READ;
    case C.RESULT_FORMAT_READ:
      downstreamFormat = formatHolder.format;
      return C.RESULT_FORMAT_READ;
    case C.RESULT_BUFFER_READ:
      if (buffer.timeUs < decodeOnlyUntilUs) {
        buffer.addFlag(C.BUFFER_FLAG_DECODE_ONLY);
      }
      // Read encryption data if the sample is encrypted.
      if (buffer.isEncrypted()) {
        readEncryptionData(buffer, extrasHolder);
      }
      // Write the sample data into the holder.
      buffer.ensureSpaceForWrite(extrasHolder.size);
      readData(extrasHolder.offset, buffer.data, extrasHolder.size);
      // Advance the read head.
      dropDownstreamTo(extrasHolder.nextOffset);
      return C.RESULT_BUFFER_READ;
    default:
      throw new IllegalStateException();
  }
}
项目:videoPickPlayer    文件:DefaultTrackOutput.java   
/**
 * Attempts to read from the queue.
 *
 * @param formatHolder A {@link FormatHolder} to populate in the case of reading a format.
 * @param buffer A {@link DecoderInputBuffer} to populate in the case of reading a sample or the
 *     end of the stream. If a sample is read then the buffer is populated with information
 *     about the sample, but not its data. The size and absolute position of the data in the
 *     rolling buffer is stored in {@code extrasHolder}, along with an encryption id if present
 *     and the absolute position of the first byte that may still be required after the current
 *     sample has been read.
 * @param downstreamFormat The current downstream {@link Format}. If the format of the next
 *     sample is different to the current downstream format then a format will be read.
 * @param extrasHolder The holder into which extra sample information should be written.
 * @return The result, which can be {@link C#RESULT_NOTHING_READ}, {@link C#RESULT_FORMAT_READ}
 *     or {@link C#RESULT_BUFFER_READ}.
 */
public synchronized int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
    Format downstreamFormat, BufferExtrasHolder extrasHolder) {
  if (queueSize == 0) {
    if (upstreamFormat != null && upstreamFormat != downstreamFormat) {
      formatHolder.format = upstreamFormat;
      return C.RESULT_FORMAT_READ;
    }
    return C.RESULT_NOTHING_READ;
  }

  if (formats[relativeReadIndex] != downstreamFormat) {
    formatHolder.format = formats[relativeReadIndex];
    return C.RESULT_FORMAT_READ;
  }

  buffer.timeUs = timesUs[relativeReadIndex];
  buffer.setFlags(flags[relativeReadIndex]);
  extrasHolder.size = sizes[relativeReadIndex];
  extrasHolder.offset = offsets[relativeReadIndex];
  extrasHolder.encryptionKeyId = encryptionKeys[relativeReadIndex];

  largestDequeuedTimestampUs = Math.max(largestDequeuedTimestampUs, buffer.timeUs);
  queueSize--;
  relativeReadIndex++;
  absoluteReadIndex++;
  if (relativeReadIndex == capacity) {
    // Wrap around.
    relativeReadIndex = 0;
  }

  extrasHolder.nextOffset = queueSize > 0 ? offsets[relativeReadIndex]
      : extrasHolder.offset + extrasHolder.size;
  return C.RESULT_BUFFER_READ;
}