Java Code Examples for com.google.android.exoplayer2.extractor.ExtractorInput#resetPeekPosition()

The following examples show how to use com.google.android.exoplayer2.extractor.ExtractorInput#resetPeekPosition() . 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: PsDurationReader.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength());
  long bufferStartStreamPosition = input.getLength() - bytesToRead;
  if (input.getPosition() != bufferStartStreamPosition) {
    seekPositionHolder.position = bufferStartStreamPosition;
    return Extractor.RESULT_SEEK;
  }

  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead);
  packetBuffer.setPosition(0);
  packetBuffer.setLimit(bytesToRead);

  lastScrValue = readLastScrValueFromBuffer(packetBuffer);
  isLastScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 2
Source File: AdtsExtractor.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
private int peekId3Header(ExtractorInput input) throws IOException, InterruptedException {
  int firstFramePosition = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 10);
    scratch.setPosition(0);
    if (scratch.readUnsignedInt24() != ID3_TAG) {
      break;
    }
    scratch.skipBytes(3);
    int length = scratch.readSynchSafeInt();
    firstFramePosition += 10 + length;
    input.advancePeekPosition(length);
  }
  input.resetPeekPosition();
  input.advancePeekPosition(firstFramePosition);
  if (this.firstFramePosition == C.POSITION_UNSET) {
    this.firstFramePosition = firstFramePosition;
  }
  return firstFramePosition;
}
 
Example 3
Source File: PsDurationReader.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
  int searchStartPosition = 0;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

  packetBuffer.reset(bytesToSearch);
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  firstScrValue = readFirstScrValueFromBuffer(packetBuffer);
  isFirstScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 4
Source File: PsDurationReader.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
private int readLastScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  long inputLength = input.getLength();
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, inputLength);
  long searchStartPosition = inputLength - bytesToSearch;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

  packetBuffer.reset(bytesToSearch);
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  lastScrValue = readLastScrValueFromBuffer(packetBuffer);
  isLastScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 5
Source File: OggExtractor.java    From Telegram with GNU General Public License v2.0 6 votes vote down vote up
@Override
public int read(ExtractorInput input, PositionHolder seekPosition)
    throws IOException, InterruptedException {
  if (streamReader == null) {
    if (!sniffInternal(input)) {
      throw new ParserException("Failed to determine bitstream type");
    }
    input.resetPeekPosition();
  }
  if (!streamReaderInitialized) {
    TrackOutput trackOutput = output.track(0, C.TRACK_TYPE_AUDIO);
    output.endTracks();
    streamReader.init(output, trackOutput);
    streamReaderInitialized = true;
  }
  return streamReader.read(input, seekPosition);
}
 
Example 6
Source File: TsDurationReader.java    From Telegram-FOSS with GNU General Public License v2.0 6 votes vote down vote up
private int readFirstPcrValue(ExtractorInput input, PositionHolder seekPositionHolder, int pcrPid)
    throws IOException, InterruptedException {
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
  int searchStartPosition = 0;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

  packetBuffer.reset(bytesToSearch);
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  firstPcrValue = readFirstPcrValueFromBuffer(packetBuffer, pcrPid);
  isFirstPcrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 7
Source File: PsDurationReader.java    From MediaSDK with Apache License 2.0 6 votes vote down vote up
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  int bytesToSearch = (int) Math.min(TIMESTAMP_SEARCH_BYTES, input.getLength());
  int searchStartPosition = 0;
  if (input.getPosition() != searchStartPosition) {
    seekPositionHolder.position = searchStartPosition;
    return Extractor.RESULT_SEEK;
  }

  packetBuffer.reset(bytesToSearch);
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToSearch);

  firstScrValue = readFirstScrValueFromBuffer(packetBuffer);
  isFirstScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 8
Source File: PsDurationReader.java    From TelePlus-Android with GNU General Public License v2.0 6 votes vote down vote up
private int readFirstScrValue(ExtractorInput input, PositionHolder seekPositionHolder)
    throws IOException, InterruptedException {
  if (input.getPosition() != 0) {
    seekPositionHolder.position = 0;
    return Extractor.RESULT_SEEK;
  }

  int bytesToRead = (int) Math.min(DURATION_READ_BYTES, input.getLength());
  input.resetPeekPosition();
  input.peekFully(packetBuffer.data, /* offset= */ 0, bytesToRead);
  packetBuffer.setPosition(0);
  packetBuffer.setLimit(bytesToRead);

  firstScrValue = readFirstScrValueFromBuffer(packetBuffer);
  isFirstScrValueRead = true;
  return Extractor.RESULT_CONTINUE;
}
 
Example 9
Source File: FlacExtractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Peeks ID3 tag data (if present) at the beginning of the input.
 *
 * @return The first ID3 tag decoded into a {@link Metadata} object. May be null if ID3 tag is not
 *     present in the input.
 */
@Nullable
private Metadata peekId3Data(ExtractorInput input) throws IOException, InterruptedException {
  input.resetPeekPosition();
  Id3Decoder.FramePredicate id3FramePredicate =
      isId3MetadataDisabled ? Id3Decoder.NO_FRAMES_PREDICATE : null;
  return id3Peeker.peekId3Data(input, id3FramePredicate);
}
 
Example 10
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 11
Source File: AmrExtractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/** Peeks from the beginning of the input to see if the given AMR signature exists. */
private boolean peekAmrSignature(ExtractorInput input, byte[] amrSignature)
    throws IOException, InterruptedException {
  input.resetPeekPosition();
  byte[] header = new byte[amrSignature.length];
  input.peekFully(header, 0, amrSignature.length);
  return Arrays.equals(header, amrSignature);
}
 
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: DefaultOggSeeker.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Skips to the position of the start of the page containing the {@code targetGranule} and
 * returns the granule of the page previous to the target page.
 *
 * @param input the {@link ExtractorInput} to read from.
 * @param targetGranule the target granule.
 * @param currentGranule the current granule or -1 if it's unknown.
 * @return the granule of the prior page or the {@code currentGranule} if there isn't a prior
 *     page.
 * @throws ParserException thrown if populating the page header fails.
 * @throws IOException thrown if reading from the input fails.
 * @throws InterruptedException thrown if interrupted while reading from the input.
 */
//@VisibleForTesting
long skipToPageOfGranule(ExtractorInput input, long targetGranule, long currentGranule)
    throws IOException, InterruptedException {
  pageHeader.populate(input, false);
  while (pageHeader.granulePosition < targetGranule) {
    input.skipFully(pageHeader.headerSize + pageHeader.bodySize);
    // Store in a member field to be able to resume after IOExceptions.
    currentGranule = pageHeader.granulePosition;
    // Peek next header.
    pageHeader.populate(input, false);
  }
  input.resetPeekPosition();
  return currentGranule;
}
 
Example 14
Source File: Mp3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Consumes the next frame from the {@code input} if it contains VBRI or Xing seeking metadata,
 * returning a {@link Seeker} if the metadata was present and valid, or {@code null} otherwise.
 * After this method returns, the input position is the start of the first frame of audio.
 *
 * @param input The {@link ExtractorInput} from which to read.
 * @return A {@link Seeker} if seeking metadata was present and valid, or {@code null} otherwise.
 * @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.
 */
private Seeker maybeReadSeekFrame(ExtractorInput input) throws IOException, InterruptedException {
  ParsableByteArray frame = new ParsableByteArray(synchronizedHeader.frameSize);
  input.peekFully(frame.data, 0, synchronizedHeader.frameSize);
  int xingBase = (synchronizedHeader.version & 1) != 0
      ? (synchronizedHeader.channels != 1 ? 36 : 21) // MPEG 1
      : (synchronizedHeader.channels != 1 ? 21 : 13); // MPEG 2 or 2.5
  int seekHeader = getSeekFrameHeader(frame, xingBase);
  Seeker seeker;
  if (seekHeader == SEEK_HEADER_XING || seekHeader == SEEK_HEADER_INFO) {
    seeker = XingSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
    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);
    if (seeker != null && !seeker.isSeekable() && seekHeader == SEEK_HEADER_INFO) {
      // Fall back to constant bitrate seeking for Info headers missing a table of contents.
      return getConstantBitrateSeeker(input);
    }
  } else if (seekHeader == SEEK_HEADER_VBRI) {
    seeker = VbriSeeker.create(input.getLength(), input.getPosition(), synchronizedHeader, frame);
    input.skipFully(synchronizedHeader.frameSize);
  } else { // seekerHeader == SEEK_HEADER_UNSET
    // This frame doesn't contain seeking information, so reset the peek position.
    seeker = null;
    input.resetPeekPosition();
  }
  return seeker;
}
 
Example 15
Source File: DefaultHlsExtractorFactory.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
private static boolean sniffQuietly(Extractor extractor, ExtractorInput input)
    throws InterruptedException, IOException {
  boolean result = false;
  try {
    result = extractor.sniff(input);
  } catch (EOFException e) {
    // Do nothing.
  } finally {
    input.resetPeekPosition();
  }
  return result;
}
 
Example 16
Source File: DefaultOggSeeker.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Performs a single step of a seeking binary search, returning the byte position from which data
 * should be provided for the next step, or {@link C#POSITION_UNSET} if the search has converged.
 * If the search has converged then {@link #skipToPageOfTargetGranule(ExtractorInput)} should be
 * called to skip to the target page.
 *
 * @param input The {@link ExtractorInput} to read from.
 * @return The byte position from which data should be provided for the next step, or {@link
 *     C#POSITION_UNSET} if the search has converged.
 * @throws IOException If reading from the input fails.
 * @throws InterruptedException If interrupted while reading from the input.
 */
private long getNextSeekPosition(ExtractorInput input) throws IOException, InterruptedException {
  if (start == end) {
    return C.POSITION_UNSET;
  }

  long currentPosition = input.getPosition();
  if (!skipToNextPage(input, end)) {
    if (start == currentPosition) {
      throw new IOException("No ogg page can be found.");
    }
    return start;
  }

  pageHeader.populate(input, /* quiet= */ false);
  input.resetPeekPosition();

  long granuleDistance = targetGranule - pageHeader.granulePosition;
  int pageSize = pageHeader.headerSize + pageHeader.bodySize;
  if (0 <= granuleDistance && granuleDistance < MATCH_RANGE) {
    return C.POSITION_UNSET;
  }

  if (granuleDistance < 0) {
    end = currentPosition;
    endGranule = pageHeader.granulePosition;
  } else {
    start = input.getPosition() + pageSize;
    startGranule = pageHeader.granulePosition;
  }

  if (end - start < MATCH_BYTE_RANGE) {
    end = start;
    return start;
  }

  long offset = pageSize * (granuleDistance <= 0 ? 2L : 1L);
  long nextPosition =
      input.getPosition()
          - offset
          + (granuleDistance * (end - start) / (endGranule - startGranule));
  return Util.constrainValue(nextPosition, start, end - 1);
}
 
Example 17
Source File: Ac3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 4 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Skip any ID3 headers.
  ParsableByteArray scratch = new ParsableByteArray(10);
  int startPosition = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 10);
    scratch.setPosition(0);
    if (scratch.readUnsignedInt24() != ID3_TAG) {
      break;
    }
    scratch.skipBytes(3);
    int length = scratch.readSynchSafeInt();
    startPosition += 10 + length;
    input.advancePeekPosition(length);
  }
  input.resetPeekPosition();
  input.advancePeekPosition(startPosition);

  int headerPosition = startPosition;
  int validFramesCount = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 5);
    scratch.setPosition(0);
    int syncBytes = scratch.readUnsignedShort();
    if (syncBytes != AC3_SYNC_WORD) {
      validFramesCount = 0;
      input.resetPeekPosition();
      if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
        return false;
      }
      input.advancePeekPosition(headerPosition);
    } else {
      if (++validFramesCount >= 4) {
        return true;
      }
      int frameSize = Ac3Util.parseAc3SyncframeSize(scratch.data);
      if (frameSize == C.LENGTH_UNSET) {
        return false;
      }
      input.advancePeekPosition(frameSize - 5);
    }
  }
}
 
Example 18
Source File: AdtsExtractor.java    From K-Sonic with MIT License 4 votes vote down vote up
@Override
public boolean sniff(ExtractorInput input) throws IOException, InterruptedException {
  // Skip any ID3 headers.
  ParsableByteArray scratch = new ParsableByteArray(10);
  ParsableBitArray scratchBits = new ParsableBitArray(scratch.data);
  int startPosition = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 10);
    scratch.setPosition(0);
    if (scratch.readUnsignedInt24() != ID3_TAG) {
      break;
    }
    scratch.skipBytes(3);
    int length = scratch.readSynchSafeInt();
    startPosition += 10 + length;
    input.advancePeekPosition(length);
  }
  input.resetPeekPosition();
  input.advancePeekPosition(startPosition);

  // Try to find four or more consecutive AAC audio frames, exceeding the MPEG TS packet size.
  int headerPosition = startPosition;
  int validFramesSize = 0;
  int validFramesCount = 0;
  while (true) {
    input.peekFully(scratch.data, 0, 2);
    scratch.setPosition(0);
    int syncBytes = scratch.readUnsignedShort();
    if ((syncBytes & 0xFFF6) != 0xFFF0) {
      validFramesCount = 0;
      validFramesSize = 0;
      input.resetPeekPosition();
      if (++headerPosition - startPosition >= MAX_SNIFF_BYTES) {
        return false;
      }
      input.advancePeekPosition(headerPosition);
    } else {
      if (++validFramesCount >= 4 && validFramesSize > 188) {
        return true;
      }

      // Skip the frame.
      input.peekFully(scratch.data, 0, 4);
      scratchBits.setPosition(14);
      int frameSize = scratchBits.readBits(13);
      // Either the stream is malformed OR we're not parsing an ADTS stream.
      if (frameSize <= 6) {
        return false;
      }
      input.advancePeekPosition(frameSize - 6);
      validFramesSize += frameSize;
    }
  }
}
 
Example 19
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;
}
 
Example 20
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;
}