Skip to content

Commit

Permalink
Expose empty CEA-608 and EMSG tracks for DASH
Browse files Browse the repository at this point in the history
This change exposes declared CEA-608 and EMSG tracks. The
tracks currently provide no samples.

Issue: #2362
Issue: #2176

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=148390849
  • Loading branch information
ojw28 committed Feb 28, 2017
1 parent d99cb28 commit 88fc337
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 28 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.exoplayer2.source;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.FormatHolder;
import com.google.android.exoplayer2.decoder.DecoderInputBuffer;
import java.io.IOException;

/**
* An empty {@link SampleStream}.
*/
public final class EmptySampleStream implements SampleStream {

@Override
public boolean isReady() {
return true;
}

@Override
public void maybeThrowError() throws IOException {
// Do nothing.
}

@Override
public int readData(FormatHolder formatHolder, DecoderInputBuffer buffer,
boolean formatRequired) {
buffer.setFlags(C.BUFFER_FLAG_END_OF_STREAM);
return C.RESULT_BUFFER_READ;
}

@Override
public void skipToKeyframeBefore(long timeUs) {
// Do nothing.
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.google.android.exoplayer2.Format;
import com.google.android.exoplayer2.source.AdaptiveMediaSourceEventListener.EventDispatcher;
import com.google.android.exoplayer2.source.CompositeSequenceableLoader;
import com.google.android.exoplayer2.source.EmptySampleStream;
import com.google.android.exoplayer2.source.MediaPeriod;
import com.google.android.exoplayer2.source.SampleStream;
import com.google.android.exoplayer2.source.SequenceableLoader;
Expand All @@ -27,12 +28,12 @@
import com.google.android.exoplayer2.source.chunk.ChunkSampleStream;
import com.google.android.exoplayer2.source.dash.manifest.AdaptationSet;
import com.google.android.exoplayer2.source.dash.manifest.DashManifest;
import com.google.android.exoplayer2.source.dash.manifest.Period;
import com.google.android.exoplayer2.source.dash.manifest.Representation;
import com.google.android.exoplayer2.source.dash.manifest.SchemeValuePair;
import com.google.android.exoplayer2.trackselection.TrackSelection;
import com.google.android.exoplayer2.upstream.Allocator;
import com.google.android.exoplayer2.upstream.LoaderErrorThrower;
import com.google.android.exoplayer2.util.MimeTypes;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -56,16 +57,16 @@
private ChunkSampleStream<DashChunkSource>[] sampleStreams;
private CompositeSequenceableLoader sequenceableLoader;
private DashManifest manifest;
private int index;
private Period period;
private int periodIndex;
private List<AdaptationSet> adaptationSets;

public DashMediaPeriod(int id, DashManifest manifest, int index,
public DashMediaPeriod(int id, DashManifest manifest, int periodIndex,
DashChunkSource.Factory chunkSourceFactory, int minLoadableRetryCount,
EventDispatcher eventDispatcher, long elapsedRealtimeOffset,
LoaderErrorThrower manifestLoaderErrorThrower, Allocator allocator) {
this.id = id;
this.manifest = manifest;
this.index = index;
this.periodIndex = periodIndex;
this.chunkSourceFactory = chunkSourceFactory;
this.minLoadableRetryCount = minLoadableRetryCount;
this.eventDispatcher = eventDispatcher;
Expand All @@ -74,17 +75,17 @@ public DashMediaPeriod(int id, DashManifest manifest, int index,
this.allocator = allocator;
sampleStreams = newSampleStreamArray(0);
sequenceableLoader = new CompositeSequenceableLoader(sampleStreams);
period = manifest.getPeriod(index);
trackGroups = buildTrackGroups(period);
adaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
trackGroups = buildTrackGroups(adaptationSets);
}

public void updateManifest(DashManifest manifest, int index) {
public void updateManifest(DashManifest manifest, int periodIndex) {
this.manifest = manifest;
this.index = index;
period = manifest.getPeriod(index);
this.periodIndex = periodIndex;
adaptationSets = manifest.getPeriod(periodIndex).adaptationSets;
if (sampleStreams != null) {
for (ChunkSampleStream<DashChunkSource> sampleStream : sampleStreams) {
sampleStream.getChunkSource().updateManifest(manifest, index);
sampleStream.getChunkSource().updateManifest(manifest, periodIndex);
}
callback.onContinueLoadingRequested(this);
}
Expand Down Expand Up @@ -117,7 +118,7 @@ public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamF
SampleStream[] streams, boolean[] streamResetFlags, long positionUs) {
ArrayList<ChunkSampleStream<DashChunkSource>> sampleStreamsList = new ArrayList<>();
for (int i = 0; i < selections.length; i++) {
if (streams[i] != null) {
if (streams[i] instanceof ChunkSampleStream) {
@SuppressWarnings("unchecked")
ChunkSampleStream<DashChunkSource> stream = (ChunkSampleStream<DashChunkSource>) streams[i];
if (selections[i] == null || !mayRetainStreamFlags[i]) {
Expand All @@ -126,11 +127,21 @@ public long selectTracks(TrackSelection[] selections, boolean[] mayRetainStreamF
} else {
sampleStreamsList.add(stream);
}
} else if (streams[i] instanceof EmptySampleStream && selections[i] == null) {
// TODO: Release streams for cea-608 and emsg tracks.
streams[i] = null;
}
if (streams[i] == null && selections[i] != null) {
ChunkSampleStream<DashChunkSource> stream = buildSampleStream(selections[i], positionUs);
sampleStreamsList.add(stream);
streams[i] = stream;
int adaptationSetIndex = trackGroups.indexOf(selections[i].getTrackGroup());
if (adaptationSetIndex < adaptationSets.size()) {
ChunkSampleStream<DashChunkSource> stream = buildSampleStream(adaptationSetIndex,
selections[i], positionUs);
sampleStreamsList.add(stream);
streams[i] = stream;
} else {
// TODO: Output streams for cea-608 and emsg tracks.
streams[i] = new EmptySampleStream();
}
streamResetFlags[i] = true;
}
}
Expand Down Expand Up @@ -184,35 +195,50 @@ public void onContinueLoadingRequested(ChunkSampleStream<DashChunkSource> sample

// Internal methods.

private static TrackGroupArray buildTrackGroups(Period period) {
TrackGroup[] trackGroupArray = new TrackGroup[period.adaptationSets.size()];
for (int i = 0; i < period.adaptationSets.size(); i++) {
AdaptationSet adaptationSet = period.adaptationSets.get(i);
private static TrackGroupArray buildTrackGroups(List<AdaptationSet> adaptationSets) {
int adaptationSetCount = adaptationSets.size();
int eventMessageTrackCount = getEventMessageTrackCount(adaptationSets);
int cea608TrackCount = getCea608TrackCount(adaptationSets);
TrackGroup[] trackGroupArray = new TrackGroup[adaptationSetCount + eventMessageTrackCount
+ cea608TrackCount];
int eventMessageTrackIndex = 0;
int cea608TrackIndex = 0;
for (int i = 0; i < adaptationSetCount; i++) {
AdaptationSet adaptationSet = adaptationSets.get(i);
List<Representation> representations = adaptationSet.representations;
Format[] formats = new Format[representations.size()];
for (int j = 0; j < formats.length; j++) {
formats[j] = representations.get(j).format;
}
trackGroupArray[i] = new TrackGroup(formats);
if (hasEventMessageTrack(adaptationSet)) {
Format format = Format.createSampleFormat(adaptationSet.id + ":emsg",
MimeTypes.APPLICATION_EMSG, null, Format.NO_VALUE, null);
trackGroupArray[adaptationSetCount + eventMessageTrackIndex++] = new TrackGroup(format);
}
if (hasCea608Track(adaptationSet)) {
Format format = Format.createTextSampleFormat(adaptationSet.id + ":cea608",
MimeTypes.APPLICATION_CEA608, null, Format.NO_VALUE, 0, null, null);
trackGroupArray[adaptationSetCount + eventMessageTrackCount + cea608TrackIndex++] =
new TrackGroup(format);
}
}
return new TrackGroupArray(trackGroupArray);
}

private ChunkSampleStream<DashChunkSource> buildSampleStream(TrackSelection selection,
long positionUs) {
int adaptationSetIndex = trackGroups.indexOf(selection.getTrackGroup());
AdaptationSet adaptationSet = period.adaptationSets.get(adaptationSetIndex);
private ChunkSampleStream<DashChunkSource> buildSampleStream(int adaptationSetIndex,
TrackSelection selection, long positionUs) {
AdaptationSet adaptationSet = adaptationSets.get(adaptationSetIndex);
boolean enableEventMessageTrack = hasEventMessageTrack(adaptationSet);
boolean enableCea608Track = hasCea608Track(adaptationSet);
DashChunkSource chunkSource = chunkSourceFactory.createDashChunkSource(
manifestLoaderErrorThrower, manifest, index, adaptationSetIndex, selection,
manifestLoaderErrorThrower, manifest, periodIndex, adaptationSetIndex, selection,
elapsedRealtimeOffset, enableEventMessageTrack, enableCea608Track);
return new ChunkSampleStream<>(adaptationSet.type, chunkSource, this, allocator, positionUs,
minLoadableRetryCount, eventDispatcher);
}

private static int getEventMessageTrackCount(Period period) {
List<AdaptationSet> adaptationSets = period.adaptationSets;
private static int getEventMessageTrackCount(List<AdaptationSet> adaptationSets) {
int inbandEventStreamTrackCount = 0;
for (int i = 0; i < adaptationSets.size(); i++) {
if (hasEventMessageTrack(adaptationSets.get(i))) {
Expand All @@ -233,8 +259,7 @@ private static boolean hasEventMessageTrack(AdaptationSet adaptationSet) {
return false;
}

private static int getCea608TrackCount(Period period) {
List<AdaptationSet> adaptationSets = period.adaptationSets;
private static int getCea608TrackCount(List<AdaptationSet> adaptationSets) {
int cea608TrackCount = 0;
for (int i = 0; i < adaptationSets.size(); i++) {
if (hasCea608Track(adaptationSets.get(i))) {
Expand Down

0 comments on commit 88fc337

Please sign in to comment.