mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
Remove pipelining from MetadataRenderer
This reverts <unknown commit> Which was a temporary workaround for Issue: #1874 Also add a loop to ensure we process as many metadata items as applicable in each render() call. PiperOrigin-RevId: 366965504
This commit is contained in:
parent
9510ba4d91
commit
9e0e937c31
3 changed files with 65 additions and 67 deletions
|
|
@ -31,9 +31,7 @@ import com.google.android.exoplayer2.source.SampleStream.ReadDataResult;
|
||||||
import com.google.android.exoplayer2.util.Assertions;
|
import com.google.android.exoplayer2.util.Assertions;
|
||||||
import com.google.android.exoplayer2.util.Util;
|
import com.google.android.exoplayer2.util.Util;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.checkerframework.checker.nullness.compatqual.NullableType;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A renderer for metadata.
|
* A renderer for metadata.
|
||||||
|
|
@ -42,24 +40,18 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
|
||||||
|
|
||||||
private static final String TAG = "MetadataRenderer";
|
private static final String TAG = "MetadataRenderer";
|
||||||
private static final int MSG_INVOKE_RENDERER = 0;
|
private static final int MSG_INVOKE_RENDERER = 0;
|
||||||
// TODO: Holding multiple pending metadata objects is temporary mitigation against
|
|
||||||
// https://github.com/google/ExoPlayer/issues/1874. It should be removed once this issue has been
|
|
||||||
// addressed.
|
|
||||||
private static final int MAX_PENDING_METADATA_COUNT = 5;
|
|
||||||
|
|
||||||
private final MetadataDecoderFactory decoderFactory;
|
private final MetadataDecoderFactory decoderFactory;
|
||||||
private final MetadataOutput output;
|
private final MetadataOutput output;
|
||||||
@Nullable private final Handler outputHandler;
|
@Nullable private final Handler outputHandler;
|
||||||
private final MetadataInputBuffer buffer;
|
private final MetadataInputBuffer buffer;
|
||||||
private final @NullableType Metadata[] pendingMetadata;
|
|
||||||
private final long[] pendingMetadataTimestamps;
|
|
||||||
|
|
||||||
private int pendingMetadataIndex;
|
|
||||||
private int pendingMetadataCount;
|
|
||||||
@Nullable private MetadataDecoder decoder;
|
@Nullable private MetadataDecoder decoder;
|
||||||
private boolean inputStreamEnded;
|
private boolean inputStreamEnded;
|
||||||
private boolean outputStreamEnded;
|
private boolean outputStreamEnded;
|
||||||
private long subsampleOffsetUs;
|
private long subsampleOffsetUs;
|
||||||
|
private long pendingMetadataTimestampUs;
|
||||||
|
@Nullable private Metadata pendingMetadata;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param output The output.
|
* @param output The output.
|
||||||
|
|
@ -90,8 +82,7 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
|
||||||
outputLooper == null ? null : Util.createHandler(outputLooper, /* callback= */ this);
|
outputLooper == null ? null : Util.createHandler(outputLooper, /* callback= */ this);
|
||||||
this.decoderFactory = Assertions.checkNotNull(decoderFactory);
|
this.decoderFactory = Assertions.checkNotNull(decoderFactory);
|
||||||
buffer = new MetadataInputBuffer();
|
buffer = new MetadataInputBuffer();
|
||||||
pendingMetadata = new Metadata[MAX_PENDING_METADATA_COUNT];
|
pendingMetadataTimestampUs = C.TIME_UNSET;
|
||||||
pendingMetadataTimestamps = new long[MAX_PENDING_METADATA_COUNT];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -117,51 +108,18 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPositionReset(long positionUs, boolean joining) {
|
protected void onPositionReset(long positionUs, boolean joining) {
|
||||||
flushPendingMetadata();
|
pendingMetadata = null;
|
||||||
|
pendingMetadataTimestampUs = C.TIME_UNSET;
|
||||||
inputStreamEnded = false;
|
inputStreamEnded = false;
|
||||||
outputStreamEnded = false;
|
outputStreamEnded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(long positionUs, long elapsedRealtimeUs) {
|
public void render(long positionUs, long elapsedRealtimeUs) {
|
||||||
if (!inputStreamEnded && pendingMetadataCount < MAX_PENDING_METADATA_COUNT) {
|
boolean working = true;
|
||||||
buffer.clear();
|
while (working) {
|
||||||
FormatHolder formatHolder = getFormatHolder();
|
readMetadata();
|
||||||
@ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */ 0);
|
working = outputMetadata(positionUs);
|
||||||
if (result == C.RESULT_BUFFER_READ) {
|
|
||||||
if (buffer.isEndOfStream()) {
|
|
||||||
inputStreamEnded = true;
|
|
||||||
} else {
|
|
||||||
buffer.subsampleOffsetUs = subsampleOffsetUs;
|
|
||||||
buffer.flip();
|
|
||||||
@Nullable Metadata metadata = castNonNull(decoder).decode(buffer);
|
|
||||||
if (metadata != null) {
|
|
||||||
List<Metadata.Entry> entries = new ArrayList<>(metadata.length());
|
|
||||||
decodeWrappedMetadata(metadata, entries);
|
|
||||||
if (!entries.isEmpty()) {
|
|
||||||
Metadata expandedMetadata = new Metadata(entries);
|
|
||||||
int index =
|
|
||||||
(pendingMetadataIndex + pendingMetadataCount) % MAX_PENDING_METADATA_COUNT;
|
|
||||||
pendingMetadata[index] = expandedMetadata;
|
|
||||||
pendingMetadataTimestamps[index] = buffer.timeUs;
|
|
||||||
pendingMetadataCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (result == C.RESULT_FORMAT_READ) {
|
|
||||||
subsampleOffsetUs = Assertions.checkNotNull(formatHolder.format).subsampleOffsetUs;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pendingMetadataCount > 0 && pendingMetadataTimestamps[pendingMetadataIndex] <= positionUs) {
|
|
||||||
Metadata metadata = castNonNull(pendingMetadata[pendingMetadataIndex]);
|
|
||||||
invokeRenderer(metadata);
|
|
||||||
pendingMetadata[pendingMetadataIndex] = null;
|
|
||||||
pendingMetadataIndex = (pendingMetadataIndex + 1) % MAX_PENDING_METADATA_COUNT;
|
|
||||||
pendingMetadataCount--;
|
|
||||||
}
|
|
||||||
if (inputStreamEnded && pendingMetadataCount == 0) {
|
|
||||||
outputStreamEnded = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,7 +155,8 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDisabled() {
|
protected void onDisabled() {
|
||||||
flushPendingMetadata();
|
pendingMetadata = null;
|
||||||
|
pendingMetadataTimestampUs = C.TIME_UNSET;
|
||||||
decoder = null;
|
decoder = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,20 +170,6 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void invokeRenderer(Metadata metadata) {
|
|
||||||
if (outputHandler != null) {
|
|
||||||
outputHandler.obtainMessage(MSG_INVOKE_RENDERER, metadata).sendToTarget();
|
|
||||||
} else {
|
|
||||||
invokeRendererInternal(metadata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void flushPendingMetadata() {
|
|
||||||
Arrays.fill(pendingMetadata, null);
|
|
||||||
pendingMetadataIndex = 0;
|
|
||||||
pendingMetadataCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handleMessage(Message msg) {
|
public boolean handleMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
|
|
@ -237,6 +182,56 @@ public final class MetadataRenderer extends BaseRenderer implements Callback {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readMetadata() {
|
||||||
|
if (!inputStreamEnded && pendingMetadata == null) {
|
||||||
|
buffer.clear();
|
||||||
|
FormatHolder formatHolder = getFormatHolder();
|
||||||
|
@ReadDataResult int result = readSource(formatHolder, buffer, /* readFlags= */ 0);
|
||||||
|
if (result == C.RESULT_BUFFER_READ) {
|
||||||
|
if (buffer.isEndOfStream()) {
|
||||||
|
inputStreamEnded = true;
|
||||||
|
} else {
|
||||||
|
buffer.subsampleOffsetUs = subsampleOffsetUs;
|
||||||
|
buffer.flip();
|
||||||
|
@Nullable Metadata metadata = castNonNull(decoder).decode(buffer);
|
||||||
|
if (metadata != null) {
|
||||||
|
List<Metadata.Entry> entries = new ArrayList<>(metadata.length());
|
||||||
|
decodeWrappedMetadata(metadata, entries);
|
||||||
|
if (!entries.isEmpty()) {
|
||||||
|
Metadata expandedMetadata = new Metadata(entries);
|
||||||
|
pendingMetadata = expandedMetadata;
|
||||||
|
pendingMetadataTimestampUs = buffer.timeUs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (result == C.RESULT_FORMAT_READ) {
|
||||||
|
subsampleOffsetUs = Assertions.checkNotNull(formatHolder.format).subsampleOffsetUs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean outputMetadata(long positionUs) {
|
||||||
|
boolean didOutput = false;
|
||||||
|
if (pendingMetadata != null && pendingMetadataTimestampUs <= positionUs) {
|
||||||
|
invokeRenderer(pendingMetadata);
|
||||||
|
pendingMetadata = null;
|
||||||
|
pendingMetadataTimestampUs = C.TIME_UNSET;
|
||||||
|
didOutput = true;
|
||||||
|
}
|
||||||
|
if (inputStreamEnded && pendingMetadata == null) {
|
||||||
|
outputStreamEnded = true;
|
||||||
|
}
|
||||||
|
return didOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void invokeRenderer(Metadata metadata) {
|
||||||
|
if (outputHandler != null) {
|
||||||
|
outputHandler.obtainMessage(MSG_INVOKE_RENDERER, metadata).sendToTarget();
|
||||||
|
} else {
|
||||||
|
invokeRendererInternal(metadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void invokeRendererInternal(Metadata metadata) {
|
private void invokeRendererInternal(Metadata metadata) {
|
||||||
output.onMetadata(metadata);
|
output.onMetadata(metadata);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ $ packager-linux \
|
||||||
</AdaptationSet>
|
</AdaptationSet>
|
||||||
<EventStream schemeIdUri="urn:mpeg:dash:event:callback:2015" timescale="1000" value="1">
|
<EventStream schemeIdUri="urn:mpeg:dash:event:callback:2015" timescale="1000" value="1">
|
||||||
<Event presentationTime="100" duration="1000" id="0" messageData="" />
|
<Event presentationTime="100" duration="1000" id="0" messageData="" />
|
||||||
<Event presentationTime="1000" duration="1000" id="1" messageData="" />
|
<Event presentationTime="100" duration="1000" id="1" messageData="" />
|
||||||
|
<Event presentationTime="1000" duration="1000" id="2" messageData="" />
|
||||||
</EventStream>
|
</EventStream>
|
||||||
</Period>
|
</Period>
|
||||||
<Period id="1" start="PT1.022S">
|
<Period id="1" start="PT1.022S">
|
||||||
|
|
|
||||||
|
|
@ -97,3 +97,5 @@ MetadataOutput:
|
||||||
entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=0, durationMs=1000, value=1
|
entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=0, durationMs=1000, value=1
|
||||||
Metadata[1]:
|
Metadata[1]:
|
||||||
entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=1, durationMs=1000, value=1
|
entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=1, durationMs=1000, value=1
|
||||||
|
Metadata[2]:
|
||||||
|
entry[0] = EMSG: scheme=urn:mpeg:dash:event:callback:2015, id=2, durationMs=1000, value=1
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue