Parse within GOP sample dependencies in ExtractorsFactory

Add helper methods to Mp4Extractor and FragmentedMp4Extractor
to convert between VideoCodecFlags and *ExtractorFlags

PiperOrigin-RevId: 715307495
This commit is contained in:
dancho 2025-01-14 03:14:00 -08:00 committed by Copybara-Service
parent b25d6ef249
commit 1892435fb3
5 changed files with 73 additions and 6 deletions

View File

@ -155,12 +155,9 @@ public final class BundledChunkExtractor implements ExtractorOutput, ChunkExtrac
if (!parseSubtitlesDuringExtraction) { if (!parseSubtitlesDuringExtraction) {
flags |= FragmentedMp4Extractor.FLAG_EMIT_RAW_SUBTITLE_DATA; flags |= FragmentedMp4Extractor.FLAG_EMIT_RAW_SUBTITLE_DATA;
} }
if ((codecsToParseWithinGopSampleDependencies & C.VIDEO_CODEC_FLAG_H264) != 0) { flags |=
flags |= FragmentedMp4Extractor.FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES; FragmentedMp4Extractor.codecsToParseWithinGopSampleDependenciesAsFlags(
} codecsToParseWithinGopSampleDependencies);
if ((codecsToParseWithinGopSampleDependencies & C.VIDEO_CODEC_FLAG_H265) != 0) {
flags |= FragmentedMp4Extractor.FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265;
}
extractor = extractor =
new FragmentedMp4Extractor( new FragmentedMp4Extractor(
subtitleParserFactory, subtitleParserFactory,

View File

@ -23,6 +23,7 @@ import static androidx.media3.extractor.mp4.Mp4Extractor.FLAG_READ_SEF_DATA;
import android.net.Uri; import android.net.Uri;
import androidx.annotation.GuardedBy; import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.C;
import androidx.media3.common.FileTypes; import androidx.media3.common.FileTypes;
import androidx.media3.common.Format; import androidx.media3.common.Format;
import androidx.media3.common.PlaybackException; import androidx.media3.common.PlaybackException;
@ -154,6 +155,7 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
private int tsTimestampSearchBytes; private int tsTimestampSearchBytes;
private boolean textTrackTranscodingEnabled; private boolean textTrackTranscodingEnabled;
private SubtitleParser.Factory subtitleParserFactory; private SubtitleParser.Factory subtitleParserFactory;
private @C.VideoCodecFlags int codecsToParseWithinGopSampleDependencies;
private @JpegExtractor.Flags int jpegFlags; private @JpegExtractor.Flags int jpegFlags;
public DefaultExtractorsFactory() { public DefaultExtractorsFactory() {
@ -387,6 +389,15 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
return this; return this;
} }
@CanIgnoreReturnValue
@Override
public synchronized DefaultExtractorsFactory
experimentalSetCodecsToParseWithinGopSampleDependencies(
@C.VideoCodecFlags int codecsToParseWithinGopSampleDependencies) {
this.codecsToParseWithinGopSampleDependencies = codecsToParseWithinGopSampleDependencies;
return this;
}
/** /**
* Sets flags for {@link JpegExtractor} instances created by the factory. * Sets flags for {@link JpegExtractor} instances created by the factory.
* *
@ -498,6 +509,8 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
new FragmentedMp4Extractor( new FragmentedMp4Extractor(
subtitleParserFactory, subtitleParserFactory,
fragmentedMp4Flags fragmentedMp4Flags
| FragmentedMp4Extractor.codecsToParseWithinGopSampleDependenciesAsFlags(
codecsToParseWithinGopSampleDependencies)
| (textTrackTranscodingEnabled | (textTrackTranscodingEnabled
? 0 ? 0
: FragmentedMp4Extractor.FLAG_EMIT_RAW_SUBTITLE_DATA))); : FragmentedMp4Extractor.FLAG_EMIT_RAW_SUBTITLE_DATA)));
@ -505,6 +518,8 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
new Mp4Extractor( new Mp4Extractor(
subtitleParserFactory, subtitleParserFactory,
mp4Flags mp4Flags
| Mp4Extractor.codecsToParseWithinGopSampleDependenciesAsFlags(
codecsToParseWithinGopSampleDependencies)
| (textTrackTranscodingEnabled | (textTrackTranscodingEnabled
? 0 ? 0
: Mp4Extractor.FLAG_EMIT_RAW_SUBTITLE_DATA))); : Mp4Extractor.FLAG_EMIT_RAW_SUBTITLE_DATA)));

View File

@ -16,8 +16,10 @@
package androidx.media3.extractor; package androidx.media3.extractor;
import android.net.Uri; import android.net.Uri;
import androidx.media3.common.C;
import androidx.media3.common.MimeTypes; import androidx.media3.common.MimeTypes;
import androidx.media3.common.util.UnstableApi; import androidx.media3.common.util.UnstableApi;
import androidx.media3.extractor.mp4.Mp4Extractor;
import androidx.media3.extractor.text.SubtitleParser; import androidx.media3.extractor.text.SubtitleParser;
import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.util.List; import java.util.List;
@ -66,6 +68,25 @@ public interface ExtractorsFactory {
return this; return this;
} }
/**
* Sets the set of video codecs for which within GOP sample dependency information should be
* parsed as part of extraction. Defaults to {@code 0} - empty set of codecs.
*
* <p>Having access to additional sample dependency information can speed up seeking. See {@link
* Mp4Extractor#FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES}.
*
* <p>This method is experimental and will be renamed or removed in a future release.
*
* @param codecsToParseWithinGopSampleDependencies The set of codecs for which to parse within GOP
* sample dependency information.
* @return This factory, for convenience.
*/
@CanIgnoreReturnValue
default ExtractorsFactory experimentalSetCodecsToParseWithinGopSampleDependencies(
@C.VideoCodecFlags int codecsToParseWithinGopSampleDependencies) {
return this;
}
/** Returns an array of new {@link Extractor} instances. */ /** Returns an array of new {@link Extractor} instances. */
Extractor[] createExtractors(); Extractor[] createExtractors();

View File

@ -430,6 +430,23 @@ public class FragmentedMp4Extractor implements Extractor {
CeaUtil.consume(presentationTimeUs, seiBuffer, ceaTrackOutputs)); CeaUtil.consume(presentationTimeUs, seiBuffer, ceaTrackOutputs));
} }
/**
* Returns {@link Flags} denoting if an extractor should parse within GOP sample dependencies.
*
* @param videoCodecFlags The set of codecs for which to parse within GOP sample dependencies.
*/
public static @Flags int codecsToParseWithinGopSampleDependenciesAsFlags(
@C.VideoCodecFlags int videoCodecFlags) {
@Flags int flags = 0;
if ((videoCodecFlags & C.VIDEO_CODEC_FLAG_H264) != 0) {
flags |= FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES;
}
if ((videoCodecFlags & C.VIDEO_CODEC_FLAG_H265) != 0) {
flags |= FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265;
}
return flags;
}
@Override @Override
public boolean sniff(ExtractorInput input) throws IOException { public boolean sniff(ExtractorInput input) throws IOException {
@Nullable SniffFailure sniffFailure = Sniffer.sniffFragmented(input); @Nullable SniffFailure sniffFailure = Sniffer.sniffFragmented(input);

View File

@ -319,6 +319,23 @@ public final class Mp4Extractor implements Extractor, SeekMap {
tracks = new Mp4Track[0]; tracks = new Mp4Track[0];
} }
/**
* Returns {@link Flags} denoting if an extractor should parse within GOP sample dependencies.
*
* @param videoCodecFlags The set of codecs for which to parse within GOP sample dependencies.
*/
public static @Flags int codecsToParseWithinGopSampleDependenciesAsFlags(
@C.VideoCodecFlags int videoCodecFlags) {
@Flags int flags = 0;
if ((videoCodecFlags & C.VIDEO_CODEC_FLAG_H264) != 0) {
flags |= FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES;
}
if ((videoCodecFlags & C.VIDEO_CODEC_FLAG_H265) != 0) {
flags |= FLAG_READ_WITHIN_GOP_SAMPLE_DEPENDENCIES_H265;
}
return flags;
}
@Override @Override
public boolean sniff(ExtractorInput input) throws IOException { public boolean sniff(ExtractorInput input) throws IOException {
@Nullable @Nullable