use of androidx.media3.exoplayer.source.ads.AdsLoader.EventListener in project media by androidx.
the class MediaCodecVideoRendererTest method supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToH265orH264Allowed.
@Test
public void supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToH265orH264Allowed() throws Exception {
// Create Dolby media formats that could fall back to H265 or H264.
Format formatDvheDtrFallbackToH265 = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvhe.04.01").build();
Format formatDvheStFallbackToH265 = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvhe.08.01").build();
Format formatDvavSeFallbackToH264 = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvav.09.01").build();
Format formatNoFallbackPossible = new Format.Builder().setSampleMimeType(MimeTypes.VIDEO_DOLBY_VISION).setCodecs("dvav.01.01").build();
// Only provide H264 and H265 decoders with codec profiles needed for fallback.
MediaCodecSelector mediaCodecSelector = (mimeType, requiresSecureDecoder, requiresTunnelingDecoder) -> {
switch(mimeType) {
case MimeTypes.VIDEO_H264:
CodecCapabilities capabilitiesH264 = new CodecCapabilities();
capabilitiesH264.profileLevels = new CodecProfileLevel[] { new CodecProfileLevel(), new CodecProfileLevel() };
capabilitiesH264.profileLevels[0].profile = CodecProfileLevel.AVCProfileBaseline;
capabilitiesH264.profileLevels[0].level = CodecProfileLevel.AVCLevel42;
capabilitiesH264.profileLevels[1].profile = CodecProfileLevel.AVCProfileHigh;
capabilitiesH264.profileLevels[1].level = CodecProfileLevel.AVCLevel42;
return ImmutableList.of(MediaCodecInfo.newInstance(/* name= */
"h264-codec", /* mimeType= */
mimeType, /* codecMimeType= */
mimeType, /* capabilities= */
capabilitiesH264, /* hardwareAccelerated= */
false, /* softwareOnly= */
true, /* vendor= */
false, /* forceDisableAdaptive= */
false, /* forceSecure= */
false));
case MimeTypes.VIDEO_H265:
CodecCapabilities capabilitiesH265 = new CodecCapabilities();
capabilitiesH265.profileLevels = new CodecProfileLevel[] { new CodecProfileLevel(), new CodecProfileLevel() };
capabilitiesH265.profileLevels[0].profile = CodecProfileLevel.HEVCProfileMain;
capabilitiesH265.profileLevels[0].level = CodecProfileLevel.HEVCMainTierLevel41;
capabilitiesH265.profileLevels[1].profile = CodecProfileLevel.HEVCProfileMain10;
capabilitiesH265.profileLevels[1].level = CodecProfileLevel.HEVCHighTierLevel51;
return ImmutableList.of(MediaCodecInfo.newInstance(/* name= */
"h265-codec", /* mimeType= */
mimeType, /* codecMimeType= */
mimeType, /* capabilities= */
capabilitiesH265, /* hardwareAccelerated= */
false, /* softwareOnly= */
true, /* vendor= */
false, /* forceDisableAdaptive= */
false, /* forceSecure= */
false));
default:
return ImmutableList.of();
}
};
MediaCodecVideoRenderer renderer = new MediaCodecVideoRenderer(ApplicationProvider.getApplicationContext(), mediaCodecSelector, /* allowedJoiningTimeMs= */
0, /* eventHandler= */
new Handler(testMainLooper), /* eventListener= */
eventListener, /* maxDroppedFramesToNotify= */
1);
renderer.init(/* index= */
0, PlayerId.UNSET);
@Capabilities int capabilitiesDvheDtrFallbackToH265 = renderer.supportsFormat(formatDvheDtrFallbackToH265);
@Capabilities int capabilitiesDvheStFallbackToH265 = renderer.supportsFormat(formatDvheStFallbackToH265);
@Capabilities int capabilitiesDvavSeFallbackToH264 = renderer.supportsFormat(formatDvavSeFallbackToH264);
@Capabilities int capabilitiesNoFallbackPossible = renderer.supportsFormat(formatNoFallbackPossible);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvheDtrFallbackToH265)).isEqualTo(C.FORMAT_HANDLED);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvheStFallbackToH265)).isEqualTo(C.FORMAT_HANDLED);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesDvavSeFallbackToH264)).isEqualTo(C.FORMAT_HANDLED);
assertThat(RendererCapabilities.getFormatSupport(capabilitiesNoFallbackPossible)).isEqualTo(C.FORMAT_UNSUPPORTED_SUBTYPE);
}
use of androidx.media3.exoplayer.source.ads.AdsLoader.EventListener in project media by androidx.
the class MediaCodecVideoRendererTest method replaceStream_rendersFirstFrameOnlyAfterStartPosition.
@Test
public void replaceStream_rendersFirstFrameOnlyAfterStartPosition() throws Exception {
ShadowLooper shadowLooper = shadowOf(testMainLooper);
FakeSampleStream fakeSampleStream1 = new FakeSampleStream(new DefaultAllocator(/* trimOnReset= */
true, /* individualAllocationSize= */
1024), /* mediaSourceEventDispatcher= */
null, DrmSessionManager.DRM_UNSUPPORTED, new DrmSessionEventListener.EventDispatcher(), /* initialFormat= */
VIDEO_H264, ImmutableList.of(oneByteSample(/* timeUs= */
0, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM));
fakeSampleStream1.writeData(/* startPositionUs= */
0);
FakeSampleStream fakeSampleStream2 = new FakeSampleStream(new DefaultAllocator(/* trimOnReset= */
true, /* individualAllocationSize= */
1024), /* mediaSourceEventDispatcher= */
null, DrmSessionManager.DRM_UNSUPPORTED, new DrmSessionEventListener.EventDispatcher(), /* initialFormat= */
VIDEO_H264, ImmutableList.of(oneByteSample(/* timeUs= */
1_000_000, C.BUFFER_FLAG_KEY_FRAME), END_OF_STREAM_ITEM));
fakeSampleStream2.writeData(/* startPositionUs= */
0);
mediaCodecVideoRenderer.enable(RendererConfiguration.DEFAULT, new Format[] { VIDEO_H264 }, fakeSampleStream1, /* positionUs= */
0, /* joining= */
false, /* mayRenderStartOfStream= */
true, /* startPositionUs= */
0, /* offsetUs */
0);
mediaCodecVideoRenderer.start();
boolean replacedStream = false;
for (int i = 0; i <= 10; i++) {
mediaCodecVideoRenderer.render(/* positionUs= */
i * 10, SystemClock.elapsedRealtime() * 1000);
if (!replacedStream && mediaCodecVideoRenderer.hasReadStreamToEnd()) {
mediaCodecVideoRenderer.replaceStream(new Format[] { VIDEO_H264 }, fakeSampleStream2, /* startPositionUs= */
100, /* offsetUs= */
100);
replacedStream = true;
}
}
// Expect only the first frame of the first stream to have been rendered.
shadowLooper.idle();
verify(eventListener, times(2)).onRenderedFirstFrame(eq(surface), /* renderTimeMs= */
anyLong());
}
use of androidx.media3.exoplayer.source.ads.AdsLoader.EventListener in project media by androidx.
the class MediaCodecVideoRendererTest method render_withMultipleQueued_sendsVideoSizeChangedWithCorrectPixelAspectRatioWhenMultipleQueued.
@Test
public void render_withMultipleQueued_sendsVideoSizeChangedWithCorrectPixelAspectRatioWhenMultipleQueued() throws Exception {
Format pAsp1 = VIDEO_H264.buildUpon().setPixelWidthHeightRatio(1f).build();
Format pAsp2 = VIDEO_H264.buildUpon().setPixelWidthHeightRatio(2f).build();
Format pAsp3 = VIDEO_H264.buildUpon().setPixelWidthHeightRatio(3f).build();
FakeSampleStream fakeSampleStream = new FakeSampleStream(new DefaultAllocator(/* trimOnReset= */
true, /* individualAllocationSize= */
1024), /* mediaSourceEventDispatcher= */
null, DrmSessionManager.DRM_UNSUPPORTED, new DrmSessionEventListener.EventDispatcher(), /* initialFormat= */
pAsp1, ImmutableList.of(oneByteSample(/* timeUs= */
0, C.BUFFER_FLAG_KEY_FRAME)));
fakeSampleStream.writeData(/* startPositionUs= */
0);
mediaCodecVideoRenderer.enable(RendererConfiguration.DEFAULT, new Format[] { pAsp1, pAsp2, pAsp3 }, fakeSampleStream, /* positionUs= */
0, /* joining= */
false, /* mayRenderStartOfStream= */
false, /* startPositionUs= */
0, /* offsetUs */
0);
mediaCodecVideoRenderer.start();
mediaCodecVideoRenderer.render(/* positionUs= */
0, SystemClock.elapsedRealtime() * 1000);
mediaCodecVideoRenderer.render(/* positionUs= */
250, SystemClock.elapsedRealtime() * 1000);
fakeSampleStream.append(ImmutableList.of(format(pAsp2), oneByteSample(/* timeUs= */
5_000), oneByteSample(/* timeUs= */
10_000), format(pAsp3), oneByteSample(/* timeUs= */
15_000), oneByteSample(/* timeUs= */
20_000), END_OF_STREAM_ITEM));
fakeSampleStream.writeData(/* startPositionUs= */
5_000);
mediaCodecVideoRenderer.setCurrentStreamFinal();
int pos = 500;
do {
mediaCodecVideoRenderer.render(/* positionUs= */
pos, SystemClock.elapsedRealtime() * 1000);
pos += 250;
} while (!mediaCodecVideoRenderer.isEnded());
shadowOf(testMainLooper).idle();
ArgumentCaptor<VideoSize> videoSizesCaptor = ArgumentCaptor.forClass(VideoSize.class);
verify(eventListener, times(3)).onVideoSizeChanged(videoSizesCaptor.capture());
assertThat(videoSizesCaptor.getAllValues().stream().map(videoSize -> videoSize.pixelWidthHeightRatio).collect(Collectors.toList())).containsExactly(1f, 2f, 3f);
}
use of androidx.media3.exoplayer.source.ads.AdsLoader.EventListener in project media by androidx.
the class ExoPlayerTest method releaseAfterRendererEvents_triggersPendingVideoEventsInListener.
@Test
public void releaseAfterRendererEvents_triggersPendingVideoEventsInListener() throws Exception {
Surface surface = new Surface(new SurfaceTexture(/* texName= */
0));
ExoPlayer player = new TestExoPlayerBuilder(ApplicationProvider.getApplicationContext()).setRenderersFactory((handler, videoListener, audioListener, textOutput, metadataOutput) -> new Renderer[] { new FakeVideoRenderer(handler, videoListener) }).build();
Player.Listener listener = mock(Player.Listener.class);
player.addListener(listener);
player.setMediaSource(new FakeMediaSource(new FakeTimeline(), ExoPlayerTestRunner.VIDEO_FORMAT));
player.setVideoSurface(surface);
player.prepare();
player.play();
runUntilPlaybackState(player, Player.STATE_READY);
player.release();
surface.release();
ShadowLooper.runMainLooperToNextTask();
// EventListener
verify(listener, atLeastOnce()).onEvents(any(), any());
// VideoListener
verify(listener).onRenderedFirstFrame();
}
use of androidx.media3.exoplayer.source.ads.AdsLoader.EventListener in project media by androidx.
the class DefaultRenderersFactory method buildVideoRenderers.
/**
* Builds video renderers for use by the player.
*
* @param context The {@link Context} associated with the player.
* @param extensionRendererMode The extension renderer mode.
* @param mediaCodecSelector A decoder selector.
* @param enableDecoderFallback Whether to enable fallback to lower-priority decoders if decoder
* initialization fails. This may result in using a decoder that is slower/less efficient than
* the primary decoder.
* @param eventHandler A handler associated with the main thread's looper.
* @param eventListener An event listener.
* @param allowedVideoJoiningTimeMs The maximum duration for which video renderers can attempt to
* seamlessly join an ongoing playback, in milliseconds.
* @param out An array to which the built renderers should be appended.
*/
protected void buildVideoRenderers(Context context, @ExtensionRendererMode int extensionRendererMode, MediaCodecSelector mediaCodecSelector, boolean enableDecoderFallback, Handler eventHandler, VideoRendererEventListener eventListener, long allowedVideoJoiningTimeMs, ArrayList<Renderer> out) {
MediaCodecVideoRenderer videoRenderer = new MediaCodecVideoRenderer(context, getCodecAdapterFactory(), mediaCodecSelector, allowedVideoJoiningTimeMs, enableDecoderFallback, eventHandler, eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
out.add(videoRenderer);
if (extensionRendererMode == EXTENSION_RENDERER_MODE_OFF) {
return;
}
int extensionRendererIndex = out.size();
if (extensionRendererMode == EXTENSION_RENDERER_MODE_PREFER) {
extensionRendererIndex--;
}
try {
// Full class names used for constructor args so the LINT rule triggers if any of them move.
Class<?> clazz = Class.forName("androidx.media3.decoder.vp9.LibvpxVideoRenderer");
Constructor<?> constructor = clazz.getConstructor(long.class, android.os.Handler.class, androidx.media3.exoplayer.video.VideoRendererEventListener.class, int.class);
Renderer renderer = (Renderer) constructor.newInstance(allowedVideoJoiningTimeMs, eventHandler, eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
out.add(extensionRendererIndex++, renderer);
Log.i(TAG, "Loaded LibvpxVideoRenderer.");
} catch (ClassNotFoundException e) {
// Expected if the app was built without the extension.
} catch (Exception e) {
// The extension is present, but instantiation failed.
throw new RuntimeException("Error instantiating VP9 extension", e);
}
try {
// Full class names used for constructor args so the LINT rule triggers if any of them move.
Class<?> clazz = Class.forName("androidx.media3.decoder.av1.Libgav1VideoRenderer");
Constructor<?> constructor = clazz.getConstructor(long.class, android.os.Handler.class, androidx.media3.exoplayer.video.VideoRendererEventListener.class, int.class);
Renderer renderer = (Renderer) constructor.newInstance(allowedVideoJoiningTimeMs, eventHandler, eventListener, MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
out.add(extensionRendererIndex++, renderer);
Log.i(TAG, "Loaded Libgav1VideoRenderer.");
} catch (ClassNotFoundException e) {
// Expected if the app was built without the extension.
} catch (Exception e) {
// The extension is present, but instantiation failed.
throw new RuntimeException("Error instantiating AV1 extension", e);
}
}
Aggregations