com.google.android.exoplayer2.extractor.GaplessInfoHolder Java Examples

The following examples show how to use com.google.android.exoplayer2.extractor.GaplessInfoHolder. 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 TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * @param flags Flags that control the extractor's behavior.
 * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or
 *     {@link C#TIME_UNSET} if forcing is not required.
 */
public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) {
  this.flags = flags;
  this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs;
  scratch = new ParsableByteArray(SCRATCH_LENGTH);
  synchronizedHeader = new MpegAudioHeader();
  gaplessInfoHolder = new GaplessInfoHolder();
  basisTimeUs = C.TIME_UNSET;
  id3Peeker = new Id3Peeker();
}
 
Example #2
Source File: Mp3Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * @param flags Flags that control the extractor's behavior.
 * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or
 *     {@link C#TIME_UNSET} if forcing is not required.
 */
public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) {
  this.flags = flags;
  this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs;
  scratch = new ParsableByteArray(SCRATCH_LENGTH);
  synchronizedHeader = new MpegAudioHeader();
  gaplessInfoHolder = new GaplessInfoHolder();
  basisTimeUs = C.TIME_UNSET;
  id3Peeker = new Id3Peeker();
}
 
Example #3
Source File: Mp4Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
private ArrayList<TrackSampleTable> getTrackSampleTables(
    ContainerAtom moov, GaplessInfoHolder gaplessInfoHolder, boolean ignoreEditLists)
    throws ParserException {
  ArrayList<TrackSampleTable> trackSampleTables = new ArrayList<>();
  for (int i = 0; i < moov.containerChildren.size(); i++) {
    Atom.ContainerAtom atom = moov.containerChildren.get(i);
    if (atom.type != Atom.TYPE_trak) {
      continue;
    }
    Track track =
        AtomParsers.parseTrak(
            atom,
            moov.getLeafAtomOfType(Atom.TYPE_mvhd),
            /* duration= */ C.TIME_UNSET,
            /* drmInitData= */ null,
            ignoreEditLists,
            isQuickTime);
    if (track == null) {
      continue;
    }
    Atom.ContainerAtom stblAtom =
        atom.getContainerAtomOfType(Atom.TYPE_mdia)
            .getContainerAtomOfType(Atom.TYPE_minf)
            .getContainerAtomOfType(Atom.TYPE_stbl);
    TrackSampleTable trackSampleTable = AtomParsers.parseStbl(track, stblAtom, gaplessInfoHolder);
    if (trackSampleTable.sampleCount == 0) {
      continue;
    }
    trackSampleTables.add(trackSampleTable);
  }
  return trackSampleTables;
}
 
Example #4
Source File: MetadataUtil.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns a {@link Format} that is the same as the input format but includes information from the
 * specified sources of metadata.
 */
public static Format getFormatWithMetadata(
    int trackType,
    Format format,
    @Nullable Metadata udtaMetadata,
    @Nullable Metadata mdtaMetadata,
    GaplessInfoHolder gaplessInfoHolder) {
  if (trackType == C.TRACK_TYPE_AUDIO) {
    if (gaplessInfoHolder.hasGaplessInfo()) {
      format =
          format.copyWithGaplessInfo(
              gaplessInfoHolder.encoderDelay, gaplessInfoHolder.encoderPadding);
    }
    // We assume all udta metadata is associated with the audio track.
    if (udtaMetadata != null) {
      format = format.copyWithMetadata(udtaMetadata);
    }
  } else if (trackType == C.TRACK_TYPE_VIDEO && mdtaMetadata != null) {
    // Populate only metadata keys that are known to be specific to video.
    for (int i = 0; i < mdtaMetadata.length(); i++) {
      Metadata.Entry entry = mdtaMetadata.get(i);
      if (entry instanceof MdtaMetadataEntry) {
        MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry;
        if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)
            && mdtaMetadataEntry.typeIndicator == MDTA_TYPE_INDICATOR_FLOAT) {
          try {
            float fps = ByteBuffer.wrap(mdtaMetadataEntry.value).asFloatBuffer().get();
            format = format.copyWithFrameRate(fps);
            format = format.copyWithMetadata(new Metadata(mdtaMetadataEntry));
          } catch (NumberFormatException e) {
            Log.w(TAG, "Ignoring invalid framerate");
          }
        }
      }
    }
  }
  return format;
}
 
Example #5
Source File: MetadataUtil.java    From Telegram-FOSS with GNU General Public License v2.0 5 votes vote down vote up
/**
 * Returns a {@link Format} that is the same as the input format but includes information from the
 * specified sources of metadata.
 */
public static Format getFormatWithMetadata(
    int trackType,
    Format format,
    @Nullable Metadata udtaMetadata,
    @Nullable Metadata mdtaMetadata,
    GaplessInfoHolder gaplessInfoHolder) {
  if (trackType == C.TRACK_TYPE_AUDIO) {
    if (gaplessInfoHolder.hasGaplessInfo()) {
      format =
          format.copyWithGaplessInfo(
              gaplessInfoHolder.encoderDelay, gaplessInfoHolder.encoderPadding);
    }
    // We assume all udta metadata is associated with the audio track.
    if (udtaMetadata != null) {
      format = format.copyWithMetadata(udtaMetadata);
    }
  } else if (trackType == C.TRACK_TYPE_VIDEO && mdtaMetadata != null) {
    // Populate only metadata keys that are known to be specific to video.
    for (int i = 0; i < mdtaMetadata.length(); i++) {
      Metadata.Entry entry = mdtaMetadata.get(i);
      if (entry instanceof MdtaMetadataEntry) {
        MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry;
        if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)
            && mdtaMetadataEntry.typeIndicator == MDTA_TYPE_INDICATOR_FLOAT) {
          try {
            float fps = ByteBuffer.wrap(mdtaMetadataEntry.value).asFloatBuffer().get();
            format = format.copyWithFrameRate(fps);
            format = format.copyWithMetadata(new Metadata(mdtaMetadataEntry));
          } catch (NumberFormatException e) {
            Log.w(TAG, "Ignoring invalid framerate");
          }
        }
      }
    }
  }
  return format;
}
 
Example #6
Source File: Mp3Extractor.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Peeks ID3 data from the input, including gapless playback information.
 *
 * @param input The {@link ExtractorInput} from which data should be peeked.
 * @throws IOException If an error occurred peeking from the input.
 * @throws InterruptedException If the thread was interrupted.
 */
private void peekId3Data(ExtractorInput input) throws IOException, InterruptedException {
  int peekedId3Bytes = 0;
  while (true) {
    input.peekFully(scratch.data, 0, Id3Decoder.ID3_HEADER_LENGTH);
    scratch.setPosition(0);
    if (scratch.readUnsignedInt24() != Id3Decoder.ID3_TAG) {
      // Not an ID3 tag.
      break;
    }
    scratch.skipBytes(3); // Skip major version, minor version and flags.
    int framesLength = scratch.readSynchSafeInt();
    int tagLength = Id3Decoder.ID3_HEADER_LENGTH + framesLength;

    if (metadata == null) {
      byte[] id3Data = new byte[tagLength];
      System.arraycopy(scratch.data, 0, id3Data, 0, Id3Decoder.ID3_HEADER_LENGTH);
      input.peekFully(id3Data, Id3Decoder.ID3_HEADER_LENGTH, framesLength);
      // We need to parse enough ID3 metadata to retrieve any gapless playback information even
      // if ID3 metadata parsing is disabled.
      Id3Decoder.FramePredicate id3FramePredicate = (flags & FLAG_DISABLE_ID3_METADATA) != 0
          ? GaplessInfoHolder.GAPLESS_INFO_ID3_FRAME_PREDICATE : null;
      metadata = new Id3Decoder(id3FramePredicate).decode(id3Data, tagLength);
      if (metadata != null) {
        gaplessInfoHolder.setFromMetadata(metadata);
      }
    } else {
      input.advancePeekPosition(framesLength);
    }

    peekedId3Bytes += tagLength;
  }

  input.resetPeekPosition();
  input.advancePeekPosition(peekedId3Bytes);
}
 
Example #7
Source File: Mp3Extractor.java    From K-Sonic with MIT License 5 votes vote down vote up
/**
 * Constructs a new {@link Mp3Extractor}.
 *
 * @param flags Flags that control the extractor's behavior.
 * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or
 *     {@link C#TIME_UNSET} if forcing is not required.
 */
public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) {
  this.flags = flags;
  this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs;
  scratch = new ParsableByteArray(SCRATCH_LENGTH);
  synchronizedHeader = new MpegAudioHeader();
  gaplessInfoHolder = new GaplessInfoHolder();
  basisTimeUs = C.TIME_UNSET;
}
 
Example #8
Source File: MetadataUtil.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * Returns a {@link Format} that is the same as the input format but includes information from the
 * specified sources of metadata.
 */
public static Format getFormatWithMetadata(
    int trackType,
    Format format,
    @Nullable Metadata udtaMetadata,
    @Nullable Metadata mdtaMetadata,
    GaplessInfoHolder gaplessInfoHolder) {
  if (trackType == C.TRACK_TYPE_AUDIO) {
    if (gaplessInfoHolder.hasGaplessInfo()) {
      format =
          format.copyWithGaplessInfo(
              gaplessInfoHolder.encoderDelay, gaplessInfoHolder.encoderPadding);
    }
    // We assume all udta metadata is associated with the audio track.
    if (udtaMetadata != null) {
      format = format.copyWithMetadata(udtaMetadata);
    }
  } else if (trackType == C.TRACK_TYPE_VIDEO && mdtaMetadata != null) {
    // Populate only metadata keys that are known to be specific to video.
    for (int i = 0; i < mdtaMetadata.length(); i++) {
      Metadata.Entry entry = mdtaMetadata.get(i);
      if (entry instanceof MdtaMetadataEntry) {
        MdtaMetadataEntry mdtaMetadataEntry = (MdtaMetadataEntry) entry;
        if (MDTA_KEY_ANDROID_CAPTURE_FPS.equals(mdtaMetadataEntry.key)
            && mdtaMetadataEntry.typeIndicator == MDTA_TYPE_INDICATOR_FLOAT) {
          try {
            float fps = ByteBuffer.wrap(mdtaMetadataEntry.value).asFloatBuffer().get();
            format = format.copyWithFrameRate(fps);
            format = format.copyWithMetadata(new Metadata(mdtaMetadataEntry));
          } catch (NumberFormatException e) {
            Log.w(TAG, "Ignoring invalid framerate");
          }
        }
      }
    }
  }
  return format;
}
 
Example #9
Source File: Mp4Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private ArrayList<TrackSampleTable> getTrackSampleTables(
    ContainerAtom moov, GaplessInfoHolder gaplessInfoHolder, boolean ignoreEditLists)
    throws ParserException {
  ArrayList<TrackSampleTable> trackSampleTables = new ArrayList<>();
  for (int i = 0; i < moov.containerChildren.size(); i++) {
    Atom.ContainerAtom atom = moov.containerChildren.get(i);
    if (atom.type != Atom.TYPE_trak) {
      continue;
    }
    Track track =
        AtomParsers.parseTrak(
            atom,
            moov.getLeafAtomOfType(Atom.TYPE_mvhd),
            /* duration= */ C.TIME_UNSET,
            /* drmInitData= */ null,
            ignoreEditLists,
            isQuickTime);
    if (track == null) {
      continue;
    }
    Atom.ContainerAtom stblAtom =
        atom.getContainerAtomOfType(Atom.TYPE_mdia)
            .getContainerAtomOfType(Atom.TYPE_minf)
            .getContainerAtomOfType(Atom.TYPE_stbl);
    TrackSampleTable trackSampleTable = AtomParsers.parseStbl(track, stblAtom, gaplessInfoHolder);
    if (trackSampleTable.sampleCount == 0) {
      continue;
    }
    trackSampleTables.add(trackSampleTable);
  }
  return trackSampleTables;
}
 
Example #10
Source File: Mp4Extractor.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
private ArrayList<TrackSampleTable> getTrackSampleTables(
    ContainerAtom moov, GaplessInfoHolder gaplessInfoHolder, boolean ignoreEditLists)
    throws ParserException {
  ArrayList<TrackSampleTable> trackSampleTables = new ArrayList<>();
  for (int i = 0; i < moov.containerChildren.size(); i++) {
    Atom.ContainerAtom atom = moov.containerChildren.get(i);
    if (atom.type != Atom.TYPE_trak) {
      continue;
    }
    Track track =
        AtomParsers.parseTrak(
            atom,
            moov.getLeafAtomOfType(Atom.TYPE_mvhd),
            /* duration= */ C.TIME_UNSET,
            /* drmInitData= */ null,
            ignoreEditLists,
            isQuickTime);
    if (track == null) {
      continue;
    }
    Atom.ContainerAtom stblAtom =
        atom.getContainerAtomOfType(Atom.TYPE_mdia)
            .getContainerAtomOfType(Atom.TYPE_minf)
            .getContainerAtomOfType(Atom.TYPE_stbl);
    TrackSampleTable trackSampleTable = AtomParsers.parseStbl(track, stblAtom, gaplessInfoHolder);
    if (trackSampleTable.sampleCount == 0) {
      continue;
    }
    trackSampleTables.add(trackSampleTable);
  }
  return trackSampleTables;
}
 
Example #11
Source File: Mp3Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
/**
 * @param flags Flags that control the extractor's behavior.
 * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or
 *     {@link C#TIME_UNSET} if forcing is not required.
 */
public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) {
  this.flags = flags;
  this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs;
  scratch = new ParsableByteArray(SCRATCH_LENGTH);
  synchronizedHeader = new MpegAudioHeader();
  gaplessInfoHolder = new GaplessInfoHolder();
  basisTimeUs = C.TIME_UNSET;
  id3Peeker = new Id3Peeker();
}
 
Example #12
Source File: Mp4Extractor.java    From TelePlus-Android with GNU General Public License v2.0 5 votes vote down vote up
private ArrayList<TrackSampleTable> getTrackSampleTables(
    ContainerAtom moov, GaplessInfoHolder gaplessInfoHolder, boolean ignoreEditLists)
    throws ParserException {
  ArrayList<TrackSampleTable> trackSampleTables = new ArrayList<>();
  for (int i = 0; i < moov.containerChildren.size(); i++) {
    Atom.ContainerAtom atom = moov.containerChildren.get(i);
    if (atom.type != Atom.TYPE_trak) {
      continue;
    }
    Track track =
        AtomParsers.parseTrak(
            atom,
            moov.getLeafAtomOfType(Atom.TYPE_mvhd),
            /* duration= */ C.TIME_UNSET,
            /* drmInitData= */ null,
            ignoreEditLists,
            isQuickTime);
    if (track == null) {
      continue;
    }
    Atom.ContainerAtom stblAtom =
        atom.getContainerAtomOfType(Atom.TYPE_mdia)
            .getContainerAtomOfType(Atom.TYPE_minf)
            .getContainerAtomOfType(Atom.TYPE_stbl);
    TrackSampleTable trackSampleTable = AtomParsers.parseStbl(track, stblAtom, gaplessInfoHolder);
    if (trackSampleTable.sampleCount == 0) {
      continue;
    }
    trackSampleTables.add(trackSampleTable);
  }
  return trackSampleTables;
}
 
Example #13
Source File: Mp3Extractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
/**
 * @param flags Flags that control the extractor's behavior.
 * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or
 *     {@link C#TIME_UNSET} if forcing is not required.
 */
public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) {
  this.flags = flags;
  this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs;
  scratch = new ParsableByteArray(SCRATCH_LENGTH);
  synchronizedHeader = new MpegAudioHeader();
  gaplessInfoHolder = new GaplessInfoHolder();
  basisTimeUs = C.TIME_UNSET;
  id3Peeker = new Id3Peeker();
}
 
Example #14
Source File: Mp4Extractor.java    From MediaSDK with Apache License 2.0 5 votes vote down vote up
private ArrayList<TrackSampleTable> getTrackSampleTables(
    ContainerAtom moov, GaplessInfoHolder gaplessInfoHolder, boolean ignoreEditLists)
    throws ParserException {
  ArrayList<TrackSampleTable> trackSampleTables = new ArrayList<>();
  for (int i = 0; i < moov.containerChildren.size(); i++) {
    ContainerAtom atom = moov.containerChildren.get(i);
    if (atom.type != Atom.TYPE_trak) {
      continue;
    }
    Track track =
        AtomParsers.parseTrak(
            atom,
            moov.getLeafAtomOfType(Atom.TYPE_mvhd),
            /* duration= */ C.TIME_UNSET,
            /* drmInitData= */ null,
            ignoreEditLists,
            isQuickTime);
    if (track == null) {
      continue;
    }
    ContainerAtom stblAtom =
        atom.getContainerAtomOfType(Atom.TYPE_mdia)
            .getContainerAtomOfType(Atom.TYPE_minf)
            .getContainerAtomOfType(Atom.TYPE_stbl);
    TrackSampleTable trackSampleTable = AtomParsers.parseStbl(track, stblAtom, gaplessInfoHolder);
    if (trackSampleTable.sampleCount == 0) {
      continue;
    }
    trackSampleTables.add(trackSampleTable);
  }
  return trackSampleTables;
}
 
Example #15
Source File: Mp3Extractor.java    From Telegram with GNU General Public License v2.0 5 votes vote down vote up
/**
 * @param flags Flags that control the extractor's behavior.
 * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or
 *     {@link C#TIME_UNSET} if forcing is not required.
 */
public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) {
  this.flags = flags;
  this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs;
  scratch = new ParsableByteArray(SCRATCH_LENGTH);
  synchronizedHeader = new MpegAudioHeader();
  gaplessInfoHolder = new GaplessInfoHolder();
  basisTimeUs = C.TIME_UNSET;
  id3Peeker = new Id3Peeker();
}
 
Example #16
Source File: Mp4Extractor.java    From K-Sonic with MIT License 4 votes vote down vote up
/**
 * Updates the stored track metadata to reflect the contents of the specified moov atom.
 */
private void processMoovAtom(ContainerAtom moov) throws ParserException {
  long durationUs = C.TIME_UNSET;
  List<Mp4Track> tracks = new ArrayList<>();
  long earliestSampleOffset = Long.MAX_VALUE;

  Metadata metadata = null;
  GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder();
  Atom.LeafAtom udta = moov.getLeafAtomOfType(Atom.TYPE_udta);
  if (udta != null) {
    metadata = AtomParsers.parseUdta(udta, isQuickTime);
    if (metadata != null) {
      gaplessInfoHolder.setFromMetadata(metadata);
    }
  }

  for (int i = 0; i < moov.containerChildren.size(); i++) {
    Atom.ContainerAtom atom = moov.containerChildren.get(i);
    if (atom.type != Atom.TYPE_trak) {
      continue;
    }

    Track track = AtomParsers.parseTrak(atom, moov.getLeafAtomOfType(Atom.TYPE_mvhd),
        C.TIME_UNSET, null, isQuickTime);
    if (track == null) {
      continue;
    }

    Atom.ContainerAtom stblAtom = atom.getContainerAtomOfType(Atom.TYPE_mdia)
        .getContainerAtomOfType(Atom.TYPE_minf).getContainerAtomOfType(Atom.TYPE_stbl);
    TrackSampleTable trackSampleTable = AtomParsers.parseStbl(track, stblAtom, gaplessInfoHolder);
    if (trackSampleTable.sampleCount == 0) {
      continue;
    }

    Mp4Track mp4Track = new Mp4Track(track, trackSampleTable,
        extractorOutput.track(i, track.type));
    // Each sample has up to three bytes of overhead for the start code that replaces its length.
    // Allow ten source samples per output sample, like the platform extractor.
    int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
    Format format = track.format.copyWithMaxInputSize(maxInputSize);
    if (track.type == C.TRACK_TYPE_AUDIO) {
      if (gaplessInfoHolder.hasGaplessInfo()) {
        format = format.copyWithGaplessInfo(gaplessInfoHolder.encoderDelay,
            gaplessInfoHolder.encoderPadding);
      }
      if (metadata != null) {
        format = format.copyWithMetadata(metadata);
      }
    }
    mp4Track.trackOutput.format(format);

    durationUs = Math.max(durationUs, track.durationUs);
    tracks.add(mp4Track);

    long firstSampleOffset = trackSampleTable.offsets[0];
    if (firstSampleOffset < earliestSampleOffset) {
      earliestSampleOffset = firstSampleOffset;
    }
  }
  this.durationUs = durationUs;
  this.tracks = tracks.toArray(new Mp4Track[tracks.size()]);
  extractorOutput.endTracks();
  extractorOutput.seekMap(this);
}
 
Example #17
Source File: Mp4Extractor.java    From Telegram with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Updates the stored track metadata to reflect the contents of the specified moov atom.
 */
private void processMoovAtom(ContainerAtom moov) throws ParserException {
  int firstVideoTrackIndex = C.INDEX_UNSET;
  long durationUs = C.TIME_UNSET;
  List<Mp4Track> tracks = new ArrayList<>();

  // Process metadata.
  Metadata udtaMetadata = null;
  GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder();
  Atom.LeafAtom udta = moov.getLeafAtomOfType(Atom.TYPE_udta);
  if (udta != null) {
    udtaMetadata = AtomParsers.parseUdta(udta, isQuickTime);
    if (udtaMetadata != null) {
      gaplessInfoHolder.setFromMetadata(udtaMetadata);
    }
  }
  Metadata mdtaMetadata = null;
  Atom.ContainerAtom meta = moov.getContainerAtomOfType(Atom.TYPE_meta);
  if (meta != null) {
    mdtaMetadata = AtomParsers.parseMdtaFromMeta(meta);
  }

  boolean ignoreEditLists = (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS) != 0;
  ArrayList<TrackSampleTable> trackSampleTables =
      getTrackSampleTables(moov, gaplessInfoHolder, ignoreEditLists);

  int trackCount = trackSampleTables.size();
  for (int i = 0; i < trackCount; i++) {
    TrackSampleTable trackSampleTable = trackSampleTables.get(i);
    Track track = trackSampleTable.track;
    long trackDurationUs =
        track.durationUs != C.TIME_UNSET ? track.durationUs : trackSampleTable.durationUs;
    durationUs = Math.max(durationUs, trackDurationUs);
    Mp4Track mp4Track = new Mp4Track(track, trackSampleTable,
        extractorOutput.track(i, track.type));

    // Each sample has up to three bytes of overhead for the start code that replaces its length.
    // Allow ten source samples per output sample, like the platform extractor.
    int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
    Format format = track.format.copyWithMaxInputSize(maxInputSize);
    if (track.type == C.TRACK_TYPE_VIDEO
        && trackDurationUs > 0
        && trackSampleTable.sampleCount > 1) {
      float frameRate = trackSampleTable.sampleCount / (trackDurationUs / 1000000f);
      format = format.copyWithFrameRate(frameRate);
    }
    format =
        MetadataUtil.getFormatWithMetadata(
            track.type, format, udtaMetadata, mdtaMetadata, gaplessInfoHolder);
    mp4Track.trackOutput.format(format);

    if (track.type == C.TRACK_TYPE_VIDEO && firstVideoTrackIndex == C.INDEX_UNSET) {
      firstVideoTrackIndex = tracks.size();
    }
    tracks.add(mp4Track);
  }
  this.firstVideoTrackIndex = firstVideoTrackIndex;
  this.durationUs = durationUs;
  this.tracks = tracks.toArray(new Mp4Track[0]);
  accumulatedSampleSizes = calculateAccumulatedSampleSizes(this.tracks);

  extractorOutput.endTracks();
  extractorOutput.seekMap(this);
}
 
Example #18
Source File: Mp4Extractor.java    From Telegram-FOSS with GNU General Public License v2.0 4 votes vote down vote up
/**
 * Updates the stored track metadata to reflect the contents of the specified moov atom.
 */
private void processMoovAtom(ContainerAtom moov) throws ParserException {
  int firstVideoTrackIndex = C.INDEX_UNSET;
  long durationUs = C.TIME_UNSET;
  List<Mp4Track> tracks = new ArrayList<>();

  // Process metadata.
  Metadata udtaMetadata = null;
  GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder();
  Atom.LeafAtom udta = moov.getLeafAtomOfType(Atom.TYPE_udta);
  if (udta != null) {
    udtaMetadata = AtomParsers.parseUdta(udta, isQuickTime);
    if (udtaMetadata != null) {
      gaplessInfoHolder.setFromMetadata(udtaMetadata);
    }
  }
  Metadata mdtaMetadata = null;
  Atom.ContainerAtom meta = moov.getContainerAtomOfType(Atom.TYPE_meta);
  if (meta != null) {
    mdtaMetadata = AtomParsers.parseMdtaFromMeta(meta);
  }

  boolean ignoreEditLists = (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS) != 0;
  ArrayList<TrackSampleTable> trackSampleTables =
      getTrackSampleTables(moov, gaplessInfoHolder, ignoreEditLists);

  int trackCount = trackSampleTables.size();
  for (int i = 0; i < trackCount; i++) {
    TrackSampleTable trackSampleTable = trackSampleTables.get(i);
    Track track = trackSampleTable.track;
    long trackDurationUs =
        track.durationUs != C.TIME_UNSET ? track.durationUs : trackSampleTable.durationUs;
    durationUs = Math.max(durationUs, trackDurationUs);
    Mp4Track mp4Track = new Mp4Track(track, trackSampleTable,
        extractorOutput.track(i, track.type));

    // Each sample has up to three bytes of overhead for the start code that replaces its length.
    // Allow ten source samples per output sample, like the platform extractor.
    int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
    Format format = track.format.copyWithMaxInputSize(maxInputSize);
    if (track.type == C.TRACK_TYPE_VIDEO
        && trackDurationUs > 0
        && trackSampleTable.sampleCount > 1) {
      float frameRate = trackSampleTable.sampleCount / (trackDurationUs / 1000000f);
      format = format.copyWithFrameRate(frameRate);
    }
    format =
        MetadataUtil.getFormatWithMetadata(
            track.type, format, udtaMetadata, mdtaMetadata, gaplessInfoHolder);
    mp4Track.trackOutput.format(format);

    if (track.type == C.TRACK_TYPE_VIDEO && firstVideoTrackIndex == C.INDEX_UNSET) {
      firstVideoTrackIndex = tracks.size();
    }
    tracks.add(mp4Track);
  }
  this.firstVideoTrackIndex = firstVideoTrackIndex;
  this.durationUs = durationUs;
  this.tracks = tracks.toArray(new Mp4Track[0]);
  accumulatedSampleSizes = calculateAccumulatedSampleSizes(this.tracks);

  extractorOutput.endTracks();
  extractorOutput.seekMap(this);
}
 
Example #19
Source File: Mp3Extractor.java    From TelePlus-Android 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 playback information even
    // if ID3 metadata parsing is disabled.
    boolean onlyDecodeGaplessInfoFrames = (flags & FLAG_DISABLE_ID3_METADATA) != 0;
    Id3Decoder.FramePredicate id3FramePredicate =
        onlyDecodeGaplessInfoFrames ? GaplessInfoHolder.GAPLESS_INFO_ID3_FRAME_PREDICATE : null;
    metadata = id3Peeker.peekId3Data(input, id3FramePredicate);
    if (metadata != null) {
      gaplessInfoHolder.setFromMetadata(metadata);
    }
    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
        && !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 TelePlus-Android 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 playback information even
    // if ID3 metadata parsing is disabled.
    boolean onlyDecodeGaplessInfoFrames = (flags & FLAG_DISABLE_ID3_METADATA) != 0;
    Id3Decoder.FramePredicate id3FramePredicate =
        onlyDecodeGaplessInfoFrames ? GaplessInfoHolder.GAPLESS_INFO_ID3_FRAME_PREDICATE : null;
    metadata = id3Peeker.peekId3Data(input, id3FramePredicate);
    if (metadata != null) {
      gaplessInfoHolder.setFromMetadata(metadata);
    }
    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
        && !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 #21
Source File: Mp4Extractor.java    From MediaSDK with Apache License 2.0 4 votes vote down vote up
/**
 * Updates the stored track metadata to reflect the contents of the specified moov atom.
 */
private void processMoovAtom(ContainerAtom moov) throws ParserException {
  int firstVideoTrackIndex = C.INDEX_UNSET;
  long durationUs = C.TIME_UNSET;
  List<Mp4Track> tracks = new ArrayList<>();

  // Process metadata.
  Metadata udtaMetadata = null;
  GaplessInfoHolder gaplessInfoHolder = new GaplessInfoHolder();
  Atom.LeafAtom udta = moov.getLeafAtomOfType(Atom.TYPE_udta);
  if (udta != null) {
    udtaMetadata = AtomParsers.parseUdta(udta, isQuickTime);
    if (udtaMetadata != null) {
      gaplessInfoHolder.setFromMetadata(udtaMetadata);
    }
  }
  Metadata mdtaMetadata = null;
  ContainerAtom meta = moov.getContainerAtomOfType(Atom.TYPE_meta);
  if (meta != null) {
    mdtaMetadata = AtomParsers.parseMdtaFromMeta(meta);
  }

  boolean ignoreEditLists = (flags & FLAG_WORKAROUND_IGNORE_EDIT_LISTS) != 0;
  ArrayList<TrackSampleTable> trackSampleTables =
      getTrackSampleTables(moov, gaplessInfoHolder, ignoreEditLists);

  int trackCount = trackSampleTables.size();
  for (int i = 0; i < trackCount; i++) {
    TrackSampleTable trackSampleTable = trackSampleTables.get(i);
    Track track = trackSampleTable.track;
    long trackDurationUs =
        track.durationUs != C.TIME_UNSET ? track.durationUs : trackSampleTable.durationUs;
    durationUs = Math.max(durationUs, trackDurationUs);
    Mp4Track mp4Track = new Mp4Track(track, trackSampleTable,
        extractorOutput.track(i, track.type));

    // Each sample has up to three bytes of overhead for the start code that replaces its length.
    // Allow ten source samples per output sample, like the platform extractor.
    int maxInputSize = trackSampleTable.maximumSize + 3 * 10;
    Format format = track.format.copyWithMaxInputSize(maxInputSize);
    if (track.type == C.TRACK_TYPE_VIDEO
        && trackDurationUs > 0
        && trackSampleTable.sampleCount > 1) {
      float frameRate = trackSampleTable.sampleCount / (trackDurationUs / 1000000f);
      format = format.copyWithFrameRate(frameRate);
    }
    format =
        MetadataUtil.getFormatWithMetadata(
            track.type, format, udtaMetadata, mdtaMetadata, gaplessInfoHolder);
    mp4Track.trackOutput.format(format);

    if (track.type == C.TRACK_TYPE_VIDEO && firstVideoTrackIndex == C.INDEX_UNSET) {
      firstVideoTrackIndex = tracks.size();
    }
    tracks.add(mp4Track);
  }
  this.firstVideoTrackIndex = firstVideoTrackIndex;
  this.durationUs = durationUs;
  this.tracks = tracks.toArray(new Mp4Track[0]);
  accumulatedSampleSizes = calculateAccumulatedSampleSizes(this.tracks);

  extractorOutput.endTracks();
  extractorOutput.seekMap(this);
}