mirror of
https://github.com/samsonjs/media.git
synced 2026-04-27 15:07:40 +00:00
1) Adds new csi ticks:
exp (ExoPlayer prepare) ffr (First Frame Rendered) psr (Player State Ready). 2) Modifies aci/acc vci/vcc to report timing from ExoPlayer Playback thread. 3) Fix to report pvri and pari for every playback. and other minor bug fixes. PiperOrigin-RevId: 360228206
This commit is contained in:
parent
b5d360c4cd
commit
3f17f5d441
5 changed files with 65 additions and 12 deletions
|
|
@ -2020,8 +2020,8 @@ public class SimpleExoPlayer extends BasePlayer
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRenderedFirstFrame(@Nullable Surface surface) {
|
public void onRenderedFirstFrame(@Nullable Surface surface, long renderTimeMs) {
|
||||||
analyticsCollector.onRenderedFirstFrame(surface);
|
analyticsCollector.onRenderedFirstFrame(surface, renderTimeMs);
|
||||||
if (SimpleExoPlayer.this.surface == surface) {
|
if (SimpleExoPlayer.this.surface == surface) {
|
||||||
for (VideoListener videoListener : videoListeners) {
|
for (VideoListener videoListener : videoListeners) {
|
||||||
videoListener.onRenderedFirstFrame();
|
videoListener.onRenderedFirstFrame();
|
||||||
|
|
|
||||||
|
|
@ -231,6 +231,8 @@ public class AnalyticsCollector
|
||||||
AnalyticsListener.EVENT_AUDIO_DECODER_INITIALIZED,
|
AnalyticsListener.EVENT_AUDIO_DECODER_INITIALIZED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onAudioDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
listener.onAudioDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
||||||
|
listener.onAudioDecoderInitialized(
|
||||||
|
eventTime, decoderName, initializedTimestampMs, initializationDurationMs);
|
||||||
listener.onDecoderInitialized(
|
listener.onDecoderInitialized(
|
||||||
eventTime, C.TRACK_TYPE_AUDIO, decoderName, initializationDurationMs);
|
eventTime, C.TRACK_TYPE_AUDIO, decoderName, initializationDurationMs);
|
||||||
});
|
});
|
||||||
|
|
@ -386,6 +388,8 @@ public class AnalyticsCollector
|
||||||
AnalyticsListener.EVENT_VIDEO_DECODER_INITIALIZED,
|
AnalyticsListener.EVENT_VIDEO_DECODER_INITIALIZED,
|
||||||
listener -> {
|
listener -> {
|
||||||
listener.onVideoDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
listener.onVideoDecoderInitialized(eventTime, decoderName, initializationDurationMs);
|
||||||
|
listener.onVideoDecoderInitialized(
|
||||||
|
eventTime, decoderName, initializedTimestampMs, initializationDurationMs);
|
||||||
listener.onDecoderInitialized(
|
listener.onDecoderInitialized(
|
||||||
eventTime, C.TRACK_TYPE_VIDEO, decoderName, initializationDurationMs);
|
eventTime, C.TRACK_TYPE_VIDEO, decoderName, initializationDurationMs);
|
||||||
});
|
});
|
||||||
|
|
@ -449,13 +453,17 @@ public class AnalyticsCollector
|
||||||
eventTime, width, height, unappliedRotationDegrees, pixelWidthHeightRatio));
|
eventTime, width, height, unappliedRotationDegrees, pixelWidthHeightRatio));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation") // Calling deprecated listener method.
|
||||||
@Override
|
@Override
|
||||||
public final void onRenderedFirstFrame(@Nullable Surface surface) {
|
public final void onRenderedFirstFrame(@Nullable Surface surface, long renderTimeMs) {
|
||||||
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
EventTime eventTime = generateReadingMediaPeriodEventTime();
|
||||||
sendEvent(
|
sendEvent(
|
||||||
eventTime,
|
eventTime,
|
||||||
AnalyticsListener.EVENT_RENDERED_FIRST_FRAME,
|
AnalyticsListener.EVENT_RENDERED_FIRST_FRAME,
|
||||||
listener -> listener.onRenderedFirstFrame(eventTime, surface));
|
listener -> {
|
||||||
|
listener.onRenderedFirstFrame(eventTime, surface);
|
||||||
|
listener.onRenderedFirstFrame(eventTime, surface, renderTimeMs);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
|
||||||
import android.media.MediaCodec;
|
import android.media.MediaCodec;
|
||||||
import android.media.MediaCodec.CodecException;
|
import android.media.MediaCodec.CodecException;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import androidx.annotation.IntDef;
|
import androidx.annotation.IntDef;
|
||||||
|
|
@ -753,8 +754,18 @@ public interface AnalyticsListener {
|
||||||
*
|
*
|
||||||
* @param eventTime The event time.
|
* @param eventTime The event time.
|
||||||
* @param decoderName The decoder that was created.
|
* @param decoderName The decoder that was created.
|
||||||
|
* @param initializedTimestampMs {@link SystemClock#elapsedRealtime()} when initialization
|
||||||
|
* finished.
|
||||||
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
|
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
|
||||||
*/
|
*/
|
||||||
|
default void onAudioDecoderInitialized(
|
||||||
|
EventTime eventTime,
|
||||||
|
String decoderName,
|
||||||
|
long initializedTimestampMs,
|
||||||
|
long initializationDurationMs) {}
|
||||||
|
|
||||||
|
/** @deprecated Use {@link #onAudioDecoderInitialized(EventTime, String, long, long)}. */
|
||||||
|
@Deprecated
|
||||||
default void onAudioDecoderInitialized(
|
default void onAudioDecoderInitialized(
|
||||||
EventTime eventTime, String decoderName, long initializationDurationMs) {}
|
EventTime eventTime, String decoderName, long initializationDurationMs) {}
|
||||||
|
|
||||||
|
|
@ -895,8 +906,18 @@ public interface AnalyticsListener {
|
||||||
*
|
*
|
||||||
* @param eventTime The event time.
|
* @param eventTime The event time.
|
||||||
* @param decoderName The decoder that was created.
|
* @param decoderName The decoder that was created.
|
||||||
|
* @param initializedTimestampMs {@link SystemClock#elapsedRealtime()} when initialization
|
||||||
|
* finished.
|
||||||
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
|
* @param initializationDurationMs The time taken to initialize the decoder in milliseconds.
|
||||||
*/
|
*/
|
||||||
|
default void onVideoDecoderInitialized(
|
||||||
|
EventTime eventTime,
|
||||||
|
String decoderName,
|
||||||
|
long initializedTimestampMs,
|
||||||
|
long initializationDurationMs) {}
|
||||||
|
|
||||||
|
/** @deprecated Use {@link #onVideoDecoderInitialized(EventTime, String, long, long)}. */
|
||||||
|
@Deprecated
|
||||||
default void onVideoDecoderInitialized(
|
default void onVideoDecoderInitialized(
|
||||||
EventTime eventTime, String decoderName, long initializationDurationMs) {}
|
EventTime eventTime, String decoderName, long initializationDurationMs) {}
|
||||||
|
|
||||||
|
|
@ -988,7 +1009,13 @@ public interface AnalyticsListener {
|
||||||
* @param eventTime The event time.
|
* @param eventTime The event time.
|
||||||
* @param surface The {@link Surface} to which a frame has been rendered, or {@code null} if the
|
* @param surface The {@link Surface} to which a frame has been rendered, or {@code null} if the
|
||||||
* renderer renders to something that isn't a {@link Surface}.
|
* renderer renders to something that isn't a {@link Surface}.
|
||||||
|
* @param renderTimeMs {@link SystemClock#elapsedRealtime()} when the first frame was rendered.
|
||||||
*/
|
*/
|
||||||
|
default void onRenderedFirstFrame(
|
||||||
|
EventTime eventTime, @Nullable Surface surface, long renderTimeMs) {}
|
||||||
|
|
||||||
|
/** @deprecated Use {@link #onRenderedFirstFrame(EventTime, Surface, long)} instead. */
|
||||||
|
@Deprecated
|
||||||
default void onRenderedFirstFrame(EventTime eventTime, @Nullable Surface surface) {}
|
default void onRenderedFirstFrame(EventTime eventTime, @Nullable Surface surface) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,12 @@ public interface VideoRendererEventListener {
|
||||||
*
|
*
|
||||||
* @param surface The {@link Surface} to which a first frame has been rendered, or {@code null} if
|
* @param surface The {@link Surface} to which a first frame has been rendered, or {@code null} if
|
||||||
* the renderer renders to something that isn't a {@link Surface}.
|
* the renderer renders to something that isn't a {@link Surface}.
|
||||||
|
* @param renderTimeMs The {@link SystemClock#elapsedRealtime()} when the frame was rendered.
|
||||||
*/
|
*/
|
||||||
|
default void onRenderedFirstFrame(@Nullable Surface surface, long renderTimeMs) {}
|
||||||
|
|
||||||
|
/** @deprecated Use {@link #onRenderedFirstFrame(Surface, long)}. */
|
||||||
|
@Deprecated
|
||||||
default void onRenderedFirstFrame(@Nullable Surface surface) {}
|
default void onRenderedFirstFrame(@Nullable Surface surface) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -246,10 +251,16 @@ public interface VideoRendererEventListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invokes {@link VideoRendererEventListener#onRenderedFirstFrame(Surface)}. */
|
/** Invokes {@link VideoRendererEventListener#onRenderedFirstFrame(Surface, long)}. */
|
||||||
public void renderedFirstFrame(@Nullable Surface surface) {
|
public void renderedFirstFrame(@Nullable Surface surface) {
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
handler.post(() -> castNonNull(listener).onRenderedFirstFrame(surface));
|
// TODO: Replace this timestamp with the actual frame release time.
|
||||||
|
long renderTimeMs = SystemClock.elapsedRealtime();
|
||||||
|
handler.post(
|
||||||
|
() -> {
|
||||||
|
castNonNull(listener).onRenderedFirstFrame(surface);
|
||||||
|
castNonNull(listener).onRenderedFirstFrame(surface, renderTimeMs);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1701,12 +1701,12 @@ public final class AnalyticsCollectorTest {
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
.onVideoDecoderInitialized(
|
.onVideoDecoderInitialized(
|
||||||
individualVideoDecoderInitializedEventTimes.capture(), any(), anyLong());
|
individualVideoDecoderInitializedEventTimes.capture(), any(), anyLong(), anyLong());
|
||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualAudioDecoderInitializedEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualAudioDecoderInitializedEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
.onAudioDecoderInitialized(
|
.onAudioDecoderInitialized(
|
||||||
individualAudioDecoderInitializedEventTimes.capture(), any(), anyLong());
|
individualAudioDecoderInitializedEventTimes.capture(), any(), anyLong(), anyLong());
|
||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoDisabledEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoDisabledEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
|
|
@ -1718,7 +1718,7 @@ public final class AnalyticsCollectorTest {
|
||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualRenderedFirstFrameEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualRenderedFirstFrameEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
.onRenderedFirstFrame(individualRenderedFirstFrameEventTimes.capture(), any());
|
.onRenderedFirstFrame(individualRenderedFirstFrameEventTimes.capture(), any(), anyLong());
|
||||||
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoSizeChangedEventTimes =
|
ArgumentCaptor<AnalyticsListener.EventTime> individualVideoSizeChangedEventTimes =
|
||||||
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
ArgumentCaptor.forClass(AnalyticsListener.EventTime.class);
|
||||||
verify(listener, atLeastOnce())
|
verify(listener, atLeastOnce())
|
||||||
|
|
@ -2184,7 +2184,10 @@ public final class AnalyticsCollectorTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAudioDecoderInitialized(
|
public void onAudioDecoderInitialized(
|
||||||
EventTime eventTime, String decoderName, long initializationDurationMs) {
|
EventTime eventTime,
|
||||||
|
String decoderName,
|
||||||
|
long initializedTimestampMs,
|
||||||
|
long initializationDurationMs) {
|
||||||
reportedEvents.add(new ReportedEvent(EVENT_AUDIO_DECODER_INITIALIZED, eventTime));
|
reportedEvents.add(new ReportedEvent(EVENT_AUDIO_DECODER_INITIALIZED, eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2221,7 +2224,10 @@ public final class AnalyticsCollectorTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onVideoDecoderInitialized(
|
public void onVideoDecoderInitialized(
|
||||||
EventTime eventTime, String decoderName, long initializationDurationMs) {
|
EventTime eventTime,
|
||||||
|
String decoderName,
|
||||||
|
long initializedTimestampMs,
|
||||||
|
long initializationDurationMs) {
|
||||||
reportedEvents.add(new ReportedEvent(EVENT_VIDEO_DECODER_INITIALIZED, eventTime));
|
reportedEvents.add(new ReportedEvent(EVENT_VIDEO_DECODER_INITIALIZED, eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2247,7 +2253,8 @@ public final class AnalyticsCollectorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRenderedFirstFrame(EventTime eventTime, @Nullable Surface surface) {
|
public void onRenderedFirstFrame(
|
||||||
|
EventTime eventTime, @Nullable Surface surface, long renderTimeMs) {
|
||||||
reportedEvents.add(new ReportedEvent(EVENT_RENDERED_FIRST_FRAME, eventTime));
|
reportedEvents.add(new ReportedEvent(EVENT_RENDERED_FIRST_FRAME, eventTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue