From 1ce33362c94a693b766d42f0dddc8bae2b8a5340 Mon Sep 17 00:00:00 2001 From: olly Date: Tue, 27 Nov 2018 13:14:22 +0000 Subject: [PATCH] Strip private ID3 data from HLS sample formats Issue: #5063 PiperOrigin-RevId: 222975020 --- RELEASENOTES.md | 7 ++- .../exoplayer2/source/SampleQueue.java | 6 +-- .../exoplayer2/source/hls/HlsMediaChunk.java | 2 +- .../source/hls/HlsSampleStreamWrapper.java | 54 ++++++++++++++++++- 4 files changed, 61 insertions(+), 8 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 2a90cba3d5..af974df8aa 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,8 +2,11 @@ ### dev-v2 (not yet released) ### -* HLS: Fix issue causing unnecessary media playlist requests when playing live - streams ([#5059](https://github.com/google/ExoPlayer/issues/5059)). +* HLS: + * Fix issue causing unnecessary media playlist requests when playing live + streams ([#5059](https://github.com/google/ExoPlayer/issues/5059)). + * Fix decoder re-instantiation issue for packed audio streams + ([#5063](https://github.com/google/ExoPlayer/issues/5063)). * MP4: Support Opus and FLAC in the MP4 container, and in DASH ([#4883](https://github.com/google/ExoPlayer/issues/4883)). * DASH: Fix detecting the end of live events diff --git a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java index d6f18665f4..ecc720c656 100644 --- a/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java +++ b/library/core/src/main/java/com/google/android/exoplayer2/source/SampleQueue.java @@ -30,10 +30,8 @@ import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; -/** - * A queue of media samples. - */ -public final class SampleQueue implements TrackOutput { +/** A queue of media samples. */ +public class SampleQueue implements TrackOutput { /** * A listener for changes to the upstream format. diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java index cfb7d1c675..2995f8b0aa 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsMediaChunk.java @@ -42,7 +42,7 @@ import java.util.concurrent.atomic.AtomicInteger; */ /* package */ final class HlsMediaChunk extends MediaChunk { - private static final String PRIV_TIMESTAMP_FRAME_OWNER = + public static final String PRIV_TIMESTAMP_FRAME_OWNER = "com.apple.streaming.transportStreamTimestamp"; private static final AtomicInteger uidSource = new AtomicInteger(); diff --git a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java index e60dacb8f4..39598c4cd8 100644 --- a/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java +++ b/library/hls/src/main/java/com/google/android/exoplayer2/source/hls/HlsSampleStreamWrapper.java @@ -16,6 +16,7 @@ package com.google.android.exoplayer2.source.hls; import android.os.Handler; +import android.support.annotation.Nullable; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.FormatHolder; @@ -24,6 +25,8 @@ import com.google.android.exoplayer2.extractor.DummyTrackOutput; import com.google.android.exoplayer2.extractor.ExtractorOutput; import com.google.android.exoplayer2.extractor.SeekMap; import com.google.android.exoplayer2.extractor.TrackOutput; +import com.google.android.exoplayer2.metadata.Metadata; +import com.google.android.exoplayer2.metadata.id3.PrivFrame; import com.google.android.exoplayer2.source.MediaSourceEventListener.EventDispatcher; import com.google.android.exoplayer2.source.SampleQueue; import com.google.android.exoplayer2.source.SampleQueue.UpstreamFormatChangedListener; @@ -791,7 +794,7 @@ import java.util.List; return createDummyTrackOutput(id, type); } } - SampleQueue trackOutput = new SampleQueue(allocator); + SampleQueue trackOutput = new PrivTimestampStrippingSampleQueue(allocator); trackOutput.setSampleOffsetUs(sampleOffsetUs); trackOutput.sourceId(chunkUid); trackOutput.setUpstreamFormatChangeListener(this); @@ -1126,4 +1129,53 @@ import java.util.List; Log.w(TAG, "Unmapped track with id " + id + " of type " + type); return new DummyTrackOutput(); } + + private static final class PrivTimestampStrippingSampleQueue extends SampleQueue { + + public PrivTimestampStrippingSampleQueue(Allocator allocator) { + super(allocator); + } + + @Override + public void format(Format format) { + super.format(format.copyWithMetadata(getAdjustedMetadata(format.metadata))); + } + + /** + * Strips the private timestamp frame from metadata, if present. See: + * https://github.com/google/ExoPlayer/issues/5063 + */ + @Nullable + private Metadata getAdjustedMetadata(@Nullable Metadata metadata) { + if (metadata == null) { + return null; + } + int length = metadata.length(); + int transportStreamTimestampMetadataIndex = C.INDEX_UNSET; + for (int i = 0; i < length; i++) { + Metadata.Entry metadataEntry = metadata.get(i); + if (metadataEntry instanceof PrivFrame) { + PrivFrame privFrame = (PrivFrame) metadataEntry; + if (HlsMediaChunk.PRIV_TIMESTAMP_FRAME_OWNER.equals(privFrame.owner)) { + transportStreamTimestampMetadataIndex = i; + break; + } + } + } + if (transportStreamTimestampMetadataIndex == C.INDEX_UNSET) { + return metadata; + } + if (length == 1) { + return null; + } + Metadata.Entry[] newMetadataEntries = new Metadata.Entry[length - 1]; + for (int i = 0; i < length; i++) { + if (i != transportStreamTimestampMetadataIndex) { + int newIndex = i < transportStreamTimestampMetadataIndex ? i : i - 1; + newMetadataEntries[newIndex] = metadata.get(i); + } + } + return new Metadata(newMetadataEntries); + } + } }