Java Code Examples for com.google.android.exoplayer2.extractor.MpegAudioHeader#populateHeader()

The following examples show how to use com.google.android.exoplayer2.extractor.MpegAudioHeader#populateHeader() . 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: Mp3Extractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
  if (sampleBytesRemaining == 0) {
    extractorInput.resetPeekPosition();
    if (peekEndOfStreamOrHeader(extractorInput)) {
      return RESULT_END_OF_INPUT;
    }
    scratch.setPosition(0);
    int sampleHeaderData = scratch.readInt();
    if (!headersMatch(sampleHeaderData, synchronizedHeaderData)
        || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) {
      // We have lost synchronization, so attempt to resynchronize starting at the next byte.
      extractorInput.skipFully(1);
      synchronizedHeaderData = 0;
      return RESULT_CONTINUE;
    }
    MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader);
    if (basisTimeUs == C.TIME_UNSET) {
      basisTimeUs = seeker.getTimeUs(extractorInput.getPosition());
      if (forcedFirstSampleTimestampUs != C.TIME_UNSET) {
        long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0);
        basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs;
      }
    }
    sampleBytesRemaining = synchronizedHeader.frameSize;
  }
  int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true);
  if (bytesAppended == C.RESULT_END_OF_INPUT) {
    return RESULT_END_OF_INPUT;
  }
  sampleBytesRemaining -= bytesAppended;
  if (sampleBytesRemaining > 0) {
    return RESULT_CONTINUE;
  }
  long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate);
  trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0,
      null);
  samplesRead += synchronizedHeader.samplesPerFrame;
  sampleBytesRemaining = 0;
  return RESULT_CONTINUE;
}
 
Example 2
Source File: Mp3Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate.
 */
private Seeker getConstantBitrateSeeker(ExtractorInput input)
    throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
  return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader);
}
 
Example 3
Source File: Mp3Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
  if (sampleBytesRemaining == 0) {
    extractorInput.resetPeekPosition();
    if (peekEndOfStreamOrHeader(extractorInput)) {
      return RESULT_END_OF_INPUT;
    }
    scratch.setPosition(0);
    int sampleHeaderData = scratch.readInt();
    if (!headersMatch(sampleHeaderData, synchronizedHeaderData)
        || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) {
      // We have lost synchronization, so attempt to resynchronize starting at the next byte.
      extractorInput.skipFully(1);
      synchronizedHeaderData = 0;
      return RESULT_CONTINUE;
    }
    MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader);
    if (basisTimeUs == C.TIME_UNSET) {
      basisTimeUs = seeker.getTimeUs(extractorInput.getPosition());
      if (forcedFirstSampleTimestampUs != C.TIME_UNSET) {
        long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0);
        basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs;
      }
    }
    sampleBytesRemaining = synchronizedHeader.frameSize;
  }
  int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true);
  if (bytesAppended == C.RESULT_END_OF_INPUT) {
    return RESULT_END_OF_INPUT;
  }
  sampleBytesRemaining -= bytesAppended;
  if (sampleBytesRemaining > 0) {
    return RESULT_CONTINUE;
  }
  long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate);
  trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0,
      null);
  samplesRead += synchronizedHeader.samplesPerFrame;
  sampleBytesRemaining = 0;
  return RESULT_CONTINUE;
}
 
Example 4
Source File: MpegAudioReader.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Attempts to read the remaining two bytes of the frame header.
 * <p>
 * If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
 * the media format is output if this has not previously occurred, the four header bytes are
 * output as sample data, and the position of the source is advanced to the byte that immediately
 * follows the header.
 * <p>
 * If a frame header is read in full but cannot be parsed then the state is changed to
 * {@link #STATE_READING_HEADER}.
 * <p>
 * If a frame header is not read in full then the position of the source is advanced to the limit,
 * and the method should be called again with the next source to continue the read.
 *
 * @param source The source from which to read.
 */
private void readHeaderRemainder(ParsableByteArray source) {
  int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
  source.readBytes(headerScratch.data, frameBytesRead, bytesToRead);
  frameBytesRead += bytesToRead;
  if (frameBytesRead < HEADER_SIZE) {
    // We haven't read the whole header yet.
    return;
  }

  headerScratch.setPosition(0);
  boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header);
  if (!parsedHeader) {
    // We thought we'd located a frame header, but we hadn't.
    frameBytesRead = 0;
    state = STATE_READING_HEADER;
    return;
  }

  frameSize = header.frameSize;
  if (!hasOutputFormat) {
    frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
    Format format = Format.createAudioSampleFormat(formatId, header.mimeType, null,
        Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate,
        null, null, 0, language);
    output.format(format);
    hasOutputFormat = true;
  }

  headerScratch.setPosition(0);
  output.sampleData(headerScratch, HEADER_SIZE);
  state = STATE_READING_FRAME;
}
 
Example 5
Source File: Mp3Extractor.java    From K-Sonic with MIT License 5 votes vote down vote up
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
  if (sampleBytesRemaining == 0) {
    extractorInput.resetPeekPosition();
    if (!extractorInput.peekFully(scratch.data, 0, 4, true)) {
      return RESULT_END_OF_INPUT;
    }
    scratch.setPosition(0);
    int sampleHeaderData = scratch.readInt();
    if ((sampleHeaderData & HEADER_MASK) != (synchronizedHeaderData & HEADER_MASK)
        || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) {
      // We have lost synchronization, so attempt to resynchronize starting at the next byte.
      extractorInput.skipFully(1);
      synchronizedHeaderData = 0;
      return RESULT_CONTINUE;
    }
    MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader);
    if (basisTimeUs == C.TIME_UNSET) {
      basisTimeUs = seeker.getTimeUs(extractorInput.getPosition());
      if (forcedFirstSampleTimestampUs != C.TIME_UNSET) {
        long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0);
        basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs;
      }
    }
    sampleBytesRemaining = synchronizedHeader.frameSize;
  }
  int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true);
  if (bytesAppended == C.RESULT_END_OF_INPUT) {
    return RESULT_END_OF_INPUT;
  }
  sampleBytesRemaining -= bytesAppended;
  if (sampleBytesRemaining > 0) {
    return RESULT_CONTINUE;
  }
  long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate);
  trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0,
      null);
  samplesRead += synchronizedHeader.samplesPerFrame;
  sampleBytesRemaining = 0;
  return RESULT_CONTINUE;
}
 
Example 6
Source File: MpegAudioReader.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Attempts to read the remaining two bytes of the frame header.
 * <p>
 * If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
 * the media format is output if this has not previously occurred, the four header bytes are
 * output as sample data, and the position of the source is advanced to the byte that immediately
 * follows the header.
 * <p>
 * If a frame header is read in full but cannot be parsed then the state is changed to
 * {@link #STATE_READING_HEADER}.
 * <p>
 * If a frame header is not read in full then the position of the source is advanced to the limit,
 * and the method should be called again with the next source to continue the read.
 *
 * @param source The source from which to read.
 */
private void readHeaderRemainder(ParsableByteArray source) {
  int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
  source.readBytes(headerScratch.data, frameBytesRead, bytesToRead);
  frameBytesRead += bytesToRead;
  if (frameBytesRead < HEADER_SIZE) {
    // We haven't read the whole header yet.
    return;
  }

  headerScratch.setPosition(0);
  boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header);
  if (!parsedHeader) {
    // We thought we'd located a frame header, but we hadn't.
    frameBytesRead = 0;
    state = STATE_READING_HEADER;
    return;
  }

  frameSize = header.frameSize;
  if (!hasOutputFormat) {
    frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
    Format format = Format.createAudioSampleFormat(formatId, header.mimeType, null,
        Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate,
        null, null, 0, language);
    output.format(format);
    hasOutputFormat = true;
  }

  headerScratch.setPosition(0);
  output.sampleData(headerScratch, HEADER_SIZE);
  state = STATE_READING_FRAME;
}
 
Example 7
Source File: Mp3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate.
 */
private Seeker getConstantBitrateSeeker(ExtractorInput input)
    throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
  return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader);
}
 
Example 8
Source File: Mp3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
  if (sampleBytesRemaining == 0) {
    extractorInput.resetPeekPosition();
    if (!extractorInput.peekFully(scratch.data, 0, 4, true)) {
      return RESULT_END_OF_INPUT;
    }
    scratch.setPosition(0);
    int sampleHeaderData = scratch.readInt();
    if (!headersMatch(sampleHeaderData, synchronizedHeaderData)
        || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) {
      // We have lost synchronization, so attempt to resynchronize starting at the next byte.
      extractorInput.skipFully(1);
      synchronizedHeaderData = 0;
      return RESULT_CONTINUE;
    }
    MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader);
    if (basisTimeUs == C.TIME_UNSET) {
      basisTimeUs = seeker.getTimeUs(extractorInput.getPosition());
      if (forcedFirstSampleTimestampUs != C.TIME_UNSET) {
        long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0);
        basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs;
      }
    }
    sampleBytesRemaining = synchronizedHeader.frameSize;
  }
  int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true);
  if (bytesAppended == C.RESULT_END_OF_INPUT) {
    return RESULT_END_OF_INPUT;
  }
  sampleBytesRemaining -= bytesAppended;
  if (sampleBytesRemaining > 0) {
    return RESULT_CONTINUE;
  }
  long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate);
  trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0,
      null);
  samplesRead += synchronizedHeader.samplesPerFrame;
  sampleBytesRemaining = 0;
  return RESULT_CONTINUE;
}
 
Example 9
Source File: MpegAudioReader.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Attempts to read the remaining two bytes of the frame header.
 * <p>
 * If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
 * the media format is output if this has not previously occurred, the four header bytes are
 * output as sample data, and the position of the source is advanced to the byte that immediately
 * follows the header.
 * <p>
 * If a frame header is read in full but cannot be parsed then the state is changed to
 * {@link #STATE_READING_HEADER}.
 * <p>
 * If a frame header is not read in full then the position of the source is advanced to the limit,
 * and the method should be called again with the next source to continue the read.
 *
 * @param source The source from which to read.
 */
private void readHeaderRemainder(ParsableByteArray source) {
  int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
  source.readBytes(headerScratch.data, frameBytesRead, bytesToRead);
  frameBytesRead += bytesToRead;
  if (frameBytesRead < HEADER_SIZE) {
    // We haven't read the whole header yet.
    return;
  }

  headerScratch.setPosition(0);
  boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header);
  if (!parsedHeader) {
    // We thought we'd located a frame header, but we hadn't.
    frameBytesRead = 0;
    state = STATE_READING_HEADER;
    return;
  }

  frameSize = header.frameSize;
  if (!hasOutputFormat) {
    frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
    Format format = Format.createAudioSampleFormat(formatId, header.mimeType, null,
        Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate,
        null, null, 0, language);
    output.format(format);
    hasOutputFormat = true;
  }

  headerScratch.setPosition(0);
  output.sampleData(headerScratch, HEADER_SIZE);
  state = STATE_READING_FRAME;
}
 
Example 10
Source File: MpegAudioReader.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Attempts to read the remaining two bytes of the frame header.
 * <p>
 * If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
 * the media format is output if this has not previously occurred, the four header bytes are
 * output as sample data, and the position of the source is advanced to the byte that immediately
 * follows the header.
 * <p>
 * If a frame header is read in full but cannot be parsed then the state is changed to
 * {@link #STATE_READING_HEADER}.
 * <p>
 * If a frame header is not read in full then the position of the source is advanced to the limit,
 * and the method should be called again with the next source to continue the read.
 *
 * @param source The source from which to read.
 */
private void readHeaderRemainder(ParsableByteArray source) {
  int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
  source.readBytes(headerScratch.data, frameBytesRead, bytesToRead);
  frameBytesRead += bytesToRead;
  if (frameBytesRead < HEADER_SIZE) {
    // We haven't read the whole header yet.
    return;
  }

  headerScratch.setPosition(0);
  boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header);
  if (!parsedHeader) {
    // We thought we'd located a frame header, but we hadn't.
    frameBytesRead = 0;
    state = STATE_READING_HEADER;
    return;
  }

  frameSize = header.frameSize;
  if (!hasOutputFormat) {
    frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
    Format format = Format.createAudioSampleFormat(formatId, header.mimeType, null,
        Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate,
        null, null, 0, language);
    output.format(format);
    hasOutputFormat = true;
  }

  headerScratch.setPosition(0);
  output.sampleData(headerScratch, HEADER_SIZE);
  state = STATE_READING_FRAME;
}
 
Example 11
Source File: Mp3Extractor.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate.
 */
private Seeker getConstantBitrateSeeker(ExtractorInput input)
    throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
  return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader);
}
 
Example 12
Source File: Mp3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException {
  if (sampleBytesRemaining == 0) {
    extractorInput.resetPeekPosition();
    if (!extractorInput.peekFully(scratch.data, 0, 4, true)) {
      return RESULT_END_OF_INPUT;
    }
    scratch.setPosition(0);
    int sampleHeaderData = scratch.readInt();
    if (!headersMatch(sampleHeaderData, synchronizedHeaderData)
        || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) {
      // We have lost synchronization, so attempt to resynchronize starting at the next byte.
      extractorInput.skipFully(1);
      synchronizedHeaderData = 0;
      return RESULT_CONTINUE;
    }
    MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader);
    if (basisTimeUs == C.TIME_UNSET) {
      basisTimeUs = seeker.getTimeUs(extractorInput.getPosition());
      if (forcedFirstSampleTimestampUs != C.TIME_UNSET) {
        long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0);
        basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs;
      }
    }
    sampleBytesRemaining = synchronizedHeader.frameSize;
  }
  int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true);
  if (bytesAppended == C.RESULT_END_OF_INPUT) {
    return RESULT_END_OF_INPUT;
  }
  sampleBytesRemaining -= bytesAppended;
  if (sampleBytesRemaining > 0) {
    return RESULT_CONTINUE;
  }
  long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate);
  trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0,
      null);
  samplesRead += synchronizedHeader.samplesPerFrame;
  sampleBytesRemaining = 0;
  return RESULT_CONTINUE;
}
 
Example 13
Source File: MpegAudioReader.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Attempts to read the remaining two bytes of the frame header.
 * <p>
 * If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
 * the media format is output if this has not previously occurred, the four header bytes are
 * output as sample data, and the position of the source is advanced to the byte that immediately
 * follows the header.
 * <p>
 * If a frame header is read in full but cannot be parsed then the state is changed to
 * {@link #STATE_READING_HEADER}.
 * <p>
 * If a frame header is not read in full then the position of the source is advanced to the limit,
 * and the method should be called again with the next source to continue the read.
 *
 * @param source The source from which to read.
 */
private void readHeaderRemainder(ParsableByteArray source) {
  int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
  source.readBytes(headerScratch.data, frameBytesRead, bytesToRead);
  frameBytesRead += bytesToRead;
  if (frameBytesRead < HEADER_SIZE) {
    // We haven't read the whole header yet.
    return;
  }

  headerScratch.setPosition(0);
  boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header);
  if (!parsedHeader) {
    // We thought we'd located a frame header, but we hadn't.
    frameBytesRead = 0;
    state = STATE_READING_HEADER;
    return;
  }

  frameSize = header.frameSize;
  if (!hasOutputFormat) {
    frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
    Format format = Format.createAudioSampleFormat(formatId, header.mimeType, null,
        Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate,
        null, null, 0, language);
    output.format(format);
    hasOutputFormat = true;
  }

  headerScratch.setPosition(0);
  output.sampleData(headerScratch, HEADER_SIZE);
  state = STATE_READING_FRAME;
}
 
Example 14
Source File: Mp3Extractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate.
 */
private Seeker getConstantBitrateSeeker(ExtractorInput input)
    throws IOException, InterruptedException {
  input.peekFully(scratch.data, 0, 4);
  scratch.setPosition(0);
  MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
  return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader);
}
 
Example 15
Source File: MpegAudioReader.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Attempts to read the remaining two bytes of the frame header.
 * <p>
 * If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
 * the media format is output if this has not previously occurred, the four header bytes are
 * output as sample data, and the position of the source is advanced to the byte that immediately
 * follows the header.
 * <p>
 * If a frame header is read in full but cannot be parsed then the state is changed to
 * {@link #STATE_READING_HEADER}.
 * <p>
 * If a frame header is not read in full then the position of the source is advanced to the limit,
 * and the method should be called again with the next source to continue the read.
 *
 * @param source The source from which to read.
 */
private void readHeaderRemainder(ParsableByteArray source) {
  int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
  source.readBytes(headerScratch.data, frameBytesRead, bytesToRead);
  frameBytesRead += bytesToRead;
  if (frameBytesRead < HEADER_SIZE) {
    // We haven't read the whole header yet.
    return;
  }

  headerScratch.setPosition(0);
  boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header);
  if (!parsedHeader) {
    // We thought we'd located a frame header, but we hadn't.
    frameBytesRead = 0;
    state = STATE_READING_HEADER;
    return;
  }

  frameSize = header.frameSize;
  if (!hasOutputFormat) {
    frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
    Format format = Format.createAudioSampleFormat(formatId, header.mimeType, null,
        Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate,
        null, null, 0, language);
    output.format(format);
    hasOutputFormat = true;
  }

  headerScratch.setPosition(0);
  output.sampleData(headerScratch, HEADER_SIZE);
  state = STATE_READING_FRAME;
}
 
Example 16
Source File: Mp3Extractor.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
private boolean synchronize(ExtractorInput input, boolean sniffing)
    throws IOException, InterruptedException {
  int validFrameCount = 0;
  int candidateSynchronizedHeaderData = 0;
  int peekedId3Bytes = 0;
  int searchedBytes = 0;
  int searchLimitBytes = sniffing ? MAX_SNIFF_BYTES : MAX_SYNC_BYTES;
  input.resetPeekPosition();
  if (input.getPosition() == 0) {
    // We need to parse enough ID3 metadata to retrieve any gapless/seeking playback information
    // even if ID3 metadata parsing is disabled.
    boolean parseAllId3Frames = (flags & FLAG_DISABLE_ID3_METADATA) == 0;
    Id3Decoder.FramePredicate id3FramePredicate =
        parseAllId3Frames ? null : REQUIRED_ID3_FRAME_PREDICATE;
    metadata = id3Peeker.peekId3Data(input, id3FramePredicate);
    if (metadata != null) {
      gaplessInfoHolder.setFromMetadata(metadata);
    }
    peekedId3Bytes = (int) input.getPeekPosition();
    if (!sniffing) {
      input.skipFully(peekedId3Bytes);
    }
  }
  while (true) {
    if (peekEndOfStreamOrHeader(input)) {
      if (validFrameCount > 0) {
        // We reached the end of the stream but found at least one valid frame.
        break;
      }
      throw new EOFException();
    }
    scratch.setPosition(0);
    int headerData = scratch.readInt();
    int frameSize;
    if ((candidateSynchronizedHeaderData != 0
        && !headersMatch(headerData, candidateSynchronizedHeaderData))
        || (frameSize = MpegAudioHeader.getFrameSize(headerData)) == C.LENGTH_UNSET) {
      // The header doesn't match the candidate header or is invalid. Try the next byte offset.
      if (searchedBytes++ == searchLimitBytes) {
        if (!sniffing) {
          throw new ParserException("Searched too many bytes.");
        }
        return false;
      }
      validFrameCount = 0;
      candidateSynchronizedHeaderData = 0;
      if (sniffing) {
        input.resetPeekPosition();
        input.advancePeekPosition(peekedId3Bytes + searchedBytes);
      } else {
        input.skipFully(1);
      }
    } else {
      // The header matches the candidate header and/or is valid.
      validFrameCount++;
      if (validFrameCount == 1) {
        MpegAudioHeader.populateHeader(headerData, synchronizedHeader);
        candidateSynchronizedHeaderData = headerData;
      } else if (validFrameCount == 4) {
        break;
      }
      input.advancePeekPosition(frameSize - 4);
    }
  }
  // Prepare to read the synchronized frame.
  if (sniffing) {
    input.skipFully(peekedId3Bytes + searchedBytes);
  } else {
    input.resetPeekPosition();
  }
  synchronizedHeaderData = candidateSynchronizedHeaderData;
  return true;
}
 
Example 17
Source File: Mp3Extractor.java    From K-Sonic with MIT License 4 votes vote down vote up
private boolean synchronize(ExtractorInput input, boolean sniffing)
    throws IOException, InterruptedException {
  int validFrameCount = 0;
  int candidateSynchronizedHeaderData = 0;
  int peekedId3Bytes = 0;
  int searchedBytes = 0;
  int searchLimitBytes = sniffing ? MAX_SNIFF_BYTES : MAX_SYNC_BYTES;
  input.resetPeekPosition();
  if (input.getPosition() == 0) {
    peekId3Data(input);
    peekedId3Bytes = (int) input.getPeekPosition();
    if (!sniffing) {
      input.skipFully(peekedId3Bytes);
    }
  }
  while (true) {
    if (!input.peekFully(scratch.data, 0, 4, validFrameCount > 0)) {
      // We reached the end of the stream but found at least one valid frame.
      break;
    }
    scratch.setPosition(0);
    int headerData = scratch.readInt();
    int frameSize;
    if ((candidateSynchronizedHeaderData != 0
        && (headerData & HEADER_MASK) != (candidateSynchronizedHeaderData & HEADER_MASK))
        || (frameSize = MpegAudioHeader.getFrameSize(headerData)) == C.LENGTH_UNSET) {
      // The header doesn't match the candidate header or is invalid. Try the next byte offset.
      if (searchedBytes++ == searchLimitBytes) {
        if (!sniffing) {
          throw new ParserException("Searched too many bytes.");
        }
        return false;
      }
      validFrameCount = 0;
      candidateSynchronizedHeaderData = 0;
      if (sniffing) {
        input.resetPeekPosition();
        input.advancePeekPosition(peekedId3Bytes + searchedBytes);
      } else {
        input.skipFully(1);
      }
    } else {
      // The header matches the candidate header and/or is valid.
      validFrameCount++;
      if (validFrameCount == 1) {
        MpegAudioHeader.populateHeader(headerData, synchronizedHeader);
        candidateSynchronizedHeaderData = headerData;
      } else if (validFrameCount == 4) {
        break;
      }
      input.advancePeekPosition(frameSize - 4);
    }
  }
  // Prepare to read the synchronized frame.
  if (sniffing) {
    input.skipFully(peekedId3Bytes + searchedBytes);
  } else {
    input.resetPeekPosition();
  }
  synchronizedHeaderData = candidateSynchronizedHeaderData;
  return true;
}
 
Example 18
Source File: Mp3Extractor.java    From K-Sonic with MIT License 4 votes vote down vote up
/**
 * Returns a {@link Seeker} to seek using metadata read from {@code input}, which should provide
 * data from the start of the first frame in the stream. On returning, the input's position will
 * be set to the start of the first frame of audio.
 *
 * @param input The {@link ExtractorInput} from which to read.
 * @throws IOException Thrown if there was an error reading from the stream. Not expected if the
 *     next two frames were already peeked during synchronization.
 * @throws InterruptedException Thrown if reading from the stream was interrupted. Not expected if
 *     the next two frames were already peeked during synchronization.
 * @return a {@link Seeker}.
 */
private Seeker setupSeeker(ExtractorInput input) throws IOException, InterruptedException {
  // Read the first frame which may contain a Xing or VBRI header with seeking metadata.
  ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
  input.peekFully(frame.data, 0, synchronizedHeader.frameSize);

  long position = input.getPosition();
  long length = input.getLength();
  int headerData = 0;
  Seeker seeker = null;

  // Check if there is a Xing header.
  int xingBase = (synchronizedHeader.version & 1) != 0
      ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1
      : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5
  if (frame.limit() >= xingBase + 4) {
    frame.setPosition(xingBase);
    headerData = frame.readInt();
  }
  if (headerData == XING_HEADER || headerData == INFO_HEADER) {
    seeker = XingSeeker.create(synchronizedHeader, frame, position, length);
    if (seeker != null && !gaplessInfoHolder.hasGaplessInfo()) {
      // If there is a Xing header, read gapless playback metadata at a fixed offset.
      input.resetPeekPosition();
      input.advancePeekPosition(xingBase + 141);
      input.peekFully(scratch.data, 0, 3);
      scratch.setPosition(0);
      gaplessInfoHolder.setFromXingHeaderValue(scratch.readUnsignedInt24());
    }
    input.skipFully(synchronizedHeader.frameSize);
  } else if (frame.limit() >= 40) {
    // Check if there is a VBRI header.
    frame.setPosition(36); // MPEG audio header (4 bytes) + 32 bytes.
    headerData = frame.readInt();
    if (headerData == VBRI_HEADER) {
      seeker = VbriSeeker.create(synchronizedHeader, frame, position, length);
      input.skipFully(synchronizedHeader.frameSize);
    }
  }

  if (seeker == null || (!seeker.isSeekable()
      && (flags & FLAG_ENABLE_CONSTANT_BITRATE_SEEKING) != 0)) {
    // Repopulate the synchronized header in case we had to skip an invalid seeking header, which
    // would give an invalid CBR bitrate.
    input.resetPeekPosition();
    input.peekFully(scratch.data, 0, 4);
    scratch.setPosition(0);
    MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader);
    seeker = new ConstantBitrateSeeker(input.getPosition(), synchronizedHeader.bitrate, length);
  }

  return seeker;
}
 
Example 19
Source File: Mp3Extractor.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
private boolean synchronize(ExtractorInput input, boolean sniffing)
    throws IOException, InterruptedException {
  int validFrameCount = 0;
  int candidateSynchronizedHeaderData = 0;
  int peekedId3Bytes = 0;
  int searchedBytes = 0;
  int searchLimitBytes = sniffing ? MAX_SNIFF_BYTES : MAX_SYNC_BYTES;
  input.resetPeekPosition();
  if (input.getPosition() == 0) {
    // We need to parse enough ID3 metadata to retrieve any gapless/seeking playback information
    // even if ID3 metadata parsing is disabled.
    boolean parseAllId3Frames = (flags & FLAG_DISABLE_ID3_METADATA) == 0;
    FramePredicate id3FramePredicate =
        parseAllId3Frames ? null : REQUIRED_ID3_FRAME_PREDICATE;
    metadata = id3Peeker.peekId3Data(input, id3FramePredicate);
    if (metadata != null) {
      gaplessInfoHolder.setFromMetadata(metadata);
    }
    peekedId3Bytes = (int) input.getPeekPosition();
    if (!sniffing) {
      input.skipFully(peekedId3Bytes);
    }
  }
  while (true) {
    if (peekEndOfStreamOrHeader(input)) {
      if (validFrameCount > 0) {
        // We reached the end of the stream but found at least one valid frame.
        break;
      }
      throw new EOFException();
    }
    scratch.setPosition(0);
    int headerData = scratch.readInt();
    int frameSize;
    if ((candidateSynchronizedHeaderData != 0
        && !headersMatch(headerData, candidateSynchronizedHeaderData))
        || (frameSize = MpegAudioHeader.getFrameSize(headerData)) == C.LENGTH_UNSET) {
      // The header doesn't match the candidate header or is invalid. Try the next byte offset.
      if (searchedBytes++ == searchLimitBytes) {
        if (!sniffing) {
          throw new ParserException("Searched too many bytes.");
        }
        return false;
      }
      validFrameCount = 0;
      candidateSynchronizedHeaderData = 0;
      if (sniffing) {
        input.resetPeekPosition();
        input.advancePeekPosition(peekedId3Bytes + searchedBytes);
      } else {
        input.skipFully(1);
      }
    } else {
      // The header matches the candidate header and/or is valid.
      validFrameCount++;
      if (validFrameCount == 1) {
        MpegAudioHeader.populateHeader(headerData, synchronizedHeader);
        candidateSynchronizedHeaderData = headerData;
      } else if (validFrameCount == 4) {
        break;
      }
      input.advancePeekPosition(frameSize - 4);
    }
  }
  // Prepare to read the synchronized frame.
  if (sniffing) {
    input.skipFully(peekedId3Bytes + searchedBytes);
  } else {
    input.resetPeekPosition();
  }
  synchronizedHeaderData = candidateSynchronizedHeaderData;
  return true;
}
 
Example 20
Source File: Mp3Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
private boolean synchronize(ExtractorInput input, boolean sniffing)
    throws IOException, InterruptedException {
  int validFrameCount = 0;
  int candidateSynchronizedHeaderData = 0;
  int peekedId3Bytes = 0;
  int searchedBytes = 0;
  int searchLimitBytes = sniffing ? MAX_SNIFF_BYTES : MAX_SYNC_BYTES;
  input.resetPeekPosition();
  if (input.getPosition() == 0) {
    // We need to parse enough ID3 metadata to retrieve any gapless/seeking playback information
    // even if ID3 metadata parsing is disabled.
    boolean parseAllId3Frames = (flags & FLAG_DISABLE_ID3_METADATA) == 0;
    Id3Decoder.FramePredicate id3FramePredicate =
        parseAllId3Frames ? null : REQUIRED_ID3_FRAME_PREDICATE;
    metadata = id3Peeker.peekId3Data(input, id3FramePredicate);
    if (metadata != null) {
      gaplessInfoHolder.setFromMetadata(metadata);
    }
    peekedId3Bytes = (int) input.getPeekPosition();
    if (!sniffing) {
      input.skipFully(peekedId3Bytes);
    }
  }
  while (true) {
    if (peekEndOfStreamOrHeader(input)) {
      if (validFrameCount > 0) {
        // We reached the end of the stream but found at least one valid frame.
        break;
      }
      throw new EOFException();
    }
    scratch.setPosition(0);
    int headerData = scratch.readInt();
    int frameSize;
    if ((candidateSynchronizedHeaderData != 0
        && !headersMatch(headerData, candidateSynchronizedHeaderData))
        || (frameSize = MpegAudioHeader.getFrameSize(headerData)) == C.LENGTH_UNSET) {
      // The header doesn't match the candidate header or is invalid. Try the next byte offset.
      if (searchedBytes++ == searchLimitBytes) {
        if (!sniffing) {
          throw new ParserException("Searched too many bytes.");
        }
        return false;
      }
      validFrameCount = 0;
      candidateSynchronizedHeaderData = 0;
      if (sniffing) {
        input.resetPeekPosition();
        input.advancePeekPosition(peekedId3Bytes + searchedBytes);
      } else {
        input.skipFully(1);
      }
    } else {
      // The header matches the candidate header and/or is valid.
      validFrameCount++;
      if (validFrameCount == 1) {
        MpegAudioHeader.populateHeader(headerData, synchronizedHeader);
        candidateSynchronizedHeaderData = headerData;
      } else if (validFrameCount == 4) {
        break;
      }
      input.advancePeekPosition(frameSize - 4);
    }
  }
  // Prepare to read the synchronized frame.
  if (sniffing) {
    input.skipFully(peekedId3Bytes + searchedBytes);
  } else {
    input.resetPeekPosition();
  }
  synchronizedHeaderData = candidateSynchronizedHeaderData;
  return true;
}