Add DefaultExtractorsFactory.setTsSubtitleFormats

ExoPlayer is unable to detect the presence of subtitle tracks in some
MPEG-TS files that don't fully declare them. It's possible for a
developer to provide the list instead, but doing so is quite awkward
without this helper method. This is consistent for how
`DefaultExtractorsFactory` allows other aspects of the delegate
`Extractor` implementations to be customised.

* Issue: google/ExoPlayer#10175
* Issue: google/ExoPlayer#10505

#minor-release

PiperOrigin-RevId: 490214619
(cherry picked from commit 4853444f0dc90163c257d0e20962604510557df4)
This commit is contained in:
ibaker 2022-11-22 13:09:17 +00:00 committed by christosts
parent fbab7de15e
commit f5276323c6
2 changed files with 52 additions and 2 deletions

View File

@ -11,6 +11,7 @@ redirect_from:
* [Why is seeking inaccurate in some MP3 files?][]
* [Why is seeking in my video slow?][]
* [Why do some MPEG-TS files fail to play?][]
* [Why are subtitles not found in some MPEG-TS files?][]
* [Why do some MP4/FMP4 files play incorrectly?][]
* [Why do some streams fail with HTTP response code 301 or 302?][]
* [Why do some streams fail with UnrecognizedInputFormatException?][]
@ -20,7 +21,7 @@ redirect_from:
* [How can I query whether the stream being played is a live stream?][]
* [How do I keep audio playing when my app is backgrounded?][]
* [Why does ExoPlayer support my content but the Cast extension doesn't?][]
* [Why does content fail to play, but no error is surfaced?]
* [Why does content fail to play, but no error is surfaced?][]
* [How can I get a decoding extension to load and be used for playback?][]
* [Can I play YouTube videos directly with ExoPlayer?][]
* [Video playback is stuttering][]
@ -145,6 +146,31 @@ computationally expensive relative to AUD based frame boundary detection. Use of
`FLAG_ALLOW_NON_IDR_KEYFRAMES` may result in temporary visual corruption at the
start of playback and immediately after seeks when playing some MPEG-TS files.
#### Why are subtitles not found in some MPEG-TS files? ####
Some MPEG-TS files include CEA-608 tracks but don't declare them in the
container metadata, so ExoPlayer is unable to detect them. You can manually
specify that the subtitle track(s) exist by providing a list of expected
subtitle formats to the `DefaultExtractorsFactory`, including the accessibility
channels that can be used to identify them in the MPEG-TS stream:
```java
DefaultExtractorsFactory extractorsFactory =
new DefaultExtractorsFactory()
.setTsSubtitleFormats(
ImmutableList.of(
new Format.Builder()
.setSampleMimeType(MimeTypes.APPLICATION_CEA608)
.setAccessibilityChannel(accessibilityChannel)
// Set other subtitle format info, e.g. language.
.build()));
Player player =
new ExoPlayer.Builder(
context,
new DefaultMediaSourceFactory(context, extractorsFactory))
.build();
```
#### Why do some MP4/FMP4 files play incorrectly? ####
Some MP4/FMP4 files contain edit lists that rewrite the media timeline by
@ -333,6 +359,7 @@ particularly when playing DRM protected or high frame rate content, you can try
[Why is seeking inaccurate in some MP3 files?]: #why-is-seeking-inaccurate-in-some-mp3-files
[Why is seeking in my video slow?]: #why-is-seeking-in-my-video-slow
[Why do some MPEG-TS files fail to play?]: #why-do-some-mpeg-ts-files-fail-to-play
[Why are subtitles not found in some MPEG-TS files?]: #why-are-subtitles-not-found-in-some-mpeg-ts-files
[Why do some MP4/FMP4 files play incorrectly?]: #why-do-some-mp4fmp4-files-play-incorrectly
[Why do some streams fail with HTTP response code 301 or 302?]: #why-do-some-streams-fail-with-http-response-code-301-or-302
[Why do some streams fail with UnrecognizedInputFormatException?]: #why-do-some-streams-fail-with-unrecognizedinputformatexception

View File

@ -21,6 +21,7 @@ import static com.google.android.exoplayer2.util.FileTypes.inferFileTypeFromUri;
import android.net.Uri;
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.PlaybackException;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.extractor.amr.AmrExtractor;
@ -43,6 +44,7 @@ import com.google.android.exoplayer2.extractor.ts.TsPayloadReader;
import com.google.android.exoplayer2.extractor.wav.WavExtractor;
import com.google.android.exoplayer2.util.FileTypes;
import com.google.android.exoplayer2.util.TimestampAdjuster;
import com.google.common.collect.ImmutableList;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@ -126,11 +128,13 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
private @Mp3Extractor.Flags int mp3Flags;
private @TsExtractor.Mode int tsMode;
private @DefaultTsPayloadReaderFactory.Flags int tsFlags;
private ImmutableList<Format> tsSubtitleFormats;
private int tsTimestampSearchBytes;
public DefaultExtractorsFactory() {
tsMode = TsExtractor.MODE_SINGLE_PMT;
tsTimestampSearchBytes = TsExtractor.DEFAULT_TIMESTAMP_SEARCH_BYTES;
tsSubtitleFormats = ImmutableList.of();
}
/**
@ -301,6 +305,20 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
return this;
}
/**
* Sets a list of subtitle formats to pass to the {@link DefaultTsPayloadReaderFactory} used by
* {@link TsExtractor} instances created by the factory.
*
* @see DefaultTsPayloadReaderFactory#DefaultTsPayloadReaderFactory(int, List)
* @param subtitleFormats The subtitle formats.
* @return The factory, for convenience.
*/
@CanIgnoreReturnValue
public synchronized DefaultExtractorsFactory setTsSubtitleFormats(List<Format> subtitleFormats) {
tsSubtitleFormats = ImmutableList.copyOf(subtitleFormats);
return this;
}
/**
* Sets the number of bytes searched to find a timestamp for {@link TsExtractor} instances created
* by the factory.
@ -414,7 +432,12 @@ public final class DefaultExtractorsFactory implements ExtractorsFactory {
extractors.add(new PsExtractor());
break;
case FileTypes.TS:
extractors.add(new TsExtractor(tsMode, tsFlags, tsTimestampSearchBytes));
extractors.add(
new TsExtractor(
tsMode,
new TimestampAdjuster(0),
new DefaultTsPayloadReaderFactory(tsFlags, tsSubtitleFormats),
tsTimestampSearchBytes));
break;
case FileTypes.WAV:
extractors.add(new WavExtractor());