Skip to content

Commit

Permalink
Add option to map DV profile 7 to HEVC
Browse files Browse the repository at this point in the history
  • Loading branch information
moneytoo committed Jul 25, 2024
1 parent f9d385c commit 54798a4
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ public class DefaultRenderersFactory implements RenderersFactory {
private MediaCodecSelector mediaCodecSelector;
private boolean enableFloatOutput;
private boolean enableAudioTrackPlaybackParams;
private boolean mapDV7ToHevc;

/**
* @param context A {@link Context}.
Expand All @@ -116,6 +117,7 @@ public DefaultRenderersFactory(Context context) {
extensionRendererMode = EXTENSION_RENDERER_MODE_OFF;
allowedVideoJoiningTimeMs = DEFAULT_ALLOWED_VIDEO_JOINING_TIME_MS;
mediaCodecSelector = MediaCodecSelector.DEFAULT;
mapDV7ToHevc = false;
}

/**
Expand All @@ -135,6 +137,12 @@ public final DefaultRenderersFactory setExtensionRendererMode(
return this;
}

@CanIgnoreReturnValue
public DefaultRenderersFactory setMapDV7ToHevc(boolean mapDV7ToHevc) {
this.mapDV7ToHevc = mapDV7ToHevc;
return this;
}

/**
* Enables {@link androidx.media3.exoplayer.mediacodec.MediaCodecRenderer} instances to operate
* their {@link MediaCodec} in asynchronous mode and perform asynchronous queueing.
Expand Down Expand Up @@ -347,7 +355,8 @@ protected void buildVideoRenderers(
enableDecoderFallback,
eventHandler,
eventListener,
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY);
MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY,
mapDV7ToHevc);
out.add(videoRenderer);

if (extensionRendererMode == EXTENSION_RENDERER_MODE_OFF) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -553,7 +553,7 @@ private void onSampleQueueFormatInitialized(
/* compatibilityTrackMimeType= */ null));
@Nullable
String compatibilityTrackMimeType =
MediaCodecUtil.getAlternativeCodecMimeType(newUpstreamFormat);
MediaCodecUtil.getAlternativeCodecMimeType(newUpstreamFormat, false);
if (compatibilityTrackMimeType != null) {
mediaExtractorSampleQueue.setCompatibilityTrackIndex(tracks.size());
tracks.add(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ public boolean isFormatFunctionallySupported(Format format) {

private boolean isSampleMimeTypeSupported(Format format) {
return mimeType.equals(format.sampleMimeType)
|| mimeType.equals(MediaCodecUtil.getAlternativeCodecMimeType(format));
|| mimeType.equals(MediaCodecUtil.getAlternativeCodecMimeType(format, /* mapDV7ToHevc */ false));
}

private boolean isCodecProfileAndLevelSupported(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ public static List<MediaCodecInfo> getDecoderInfosSoftMatch(
format.sampleMimeType, requiresSecureDecoder, requiresTunnelingDecoder);
List<MediaCodecInfo> alternativeDecoderInfos =
getAlternativeDecoderInfos(
mediaCodecSelector, format, requiresSecureDecoder, requiresTunnelingDecoder);
mediaCodecSelector, format, requiresSecureDecoder, requiresTunnelingDecoder, /* mapDV7ToHevc */ false);
return ImmutableList.<MediaCodecInfo>builder()
.addAll(decoderInfos)
.addAll(alternativeDecoderInfos)
Expand Down Expand Up @@ -251,9 +251,10 @@ public static List<MediaCodecInfo> getAlternativeDecoderInfos(
MediaCodecSelector mediaCodecSelector,
Format format,
boolean requiresSecureDecoder,
boolean requiresTunnelingDecoder)
boolean requiresTunnelingDecoder,
boolean mapDV7ToHevc)
throws DecoderQueryException {
@Nullable String alternativeMimeType = getAlternativeCodecMimeType(format);
@Nullable String alternativeMimeType = getAlternativeCodecMimeType(format, mapDV7ToHevc);
if (alternativeMimeType == null) {
return ImmutableList.of();
}
Expand Down Expand Up @@ -344,7 +345,7 @@ public static Pair<Integer, Integer> getCodecProfileAndLevel(Format format) {
* exists.
*/
@Nullable
public static String getAlternativeCodecMimeType(Format format) {
public static String getAlternativeCodecMimeType(Format format, boolean mapDV7ToHevc) {
if (MimeTypes.AUDIO_E_AC3_JOC.equals(format.sampleMimeType)) {
// E-AC3 decoders can decode JOC streams, but in 2-D rather than 3-D.
return MimeTypes.AUDIO_E_AC3;
Expand All @@ -358,7 +359,8 @@ public static String getAlternativeCodecMimeType(Format format) {
if (codecProfileAndLevel != null) {
int profile = codecProfileAndLevel.first;
if (profile == CodecProfileLevel.DolbyVisionProfileDvheDtr
|| profile == CodecProfileLevel.DolbyVisionProfileDvheSt) {
|| profile == CodecProfileLevel.DolbyVisionProfileDvheSt
|| (mapDV7ToHevc && profile == CodecProfileLevel.DolbyVisionProfileDvheDtb)) {
return MimeTypes.VIDEO_H265;
} else if (profile == CodecProfileLevel.DolbyVisionProfileDvavSe) {
return MimeTypes.VIDEO_H264;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ public class MediaCodecVideoRenderer extends MediaCodecRenderer
private final boolean deviceNeedsNoPostProcessWorkaround;
private final VideoFrameReleaseControl videoFrameReleaseControl;
private final VideoFrameReleaseControl.FrameReleaseInfo videoFrameReleaseInfo;
private final boolean mapDV7ToHevc;

private @MonotonicNonNull CodecMaxValues codecMaxValues;
private boolean codecNeedsSetOutputSurfaceWorkaround;
Expand Down Expand Up @@ -199,7 +200,8 @@ public MediaCodecVideoRenderer(
allowedJoiningTimeMs,
/* eventHandler= */ null,
/* eventListener= */ null,
/* maxDroppedFramesToNotify= */ 0);
/* maxDroppedFramesToNotify= */ 0,
/* mapDV7ToHevc= */ false);
}

/**
Expand All @@ -219,7 +221,8 @@ public MediaCodecVideoRenderer(
long allowedJoiningTimeMs,
@Nullable Handler eventHandler,
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify) {
int maxDroppedFramesToNotify,
boolean mapDV7ToHevc) {
this(
context,
MediaCodecAdapter.Factory.getDefault(context),
Expand All @@ -229,7 +232,8 @@ public MediaCodecVideoRenderer(
eventHandler,
eventListener,
maxDroppedFramesToNotify,
/* assumedMinimumCodecOperatingRate= */ 30);
/* assumedMinimumCodecOperatingRate= */ 30,
/* mapDV7ToHevc= */ mapDV7ToHevc);
}

/**
Expand Down Expand Up @@ -263,7 +267,8 @@ public MediaCodecVideoRenderer(
eventHandler,
eventListener,
maxDroppedFramesToNotify,
/* assumedMinimumCodecOperatingRate= */ 30);
/* assumedMinimumCodecOperatingRate= */ 30,
/* mapDV7ToHevc= */ false);
}

/**
Expand All @@ -290,7 +295,8 @@ public MediaCodecVideoRenderer(
boolean enableDecoderFallback,
@Nullable Handler eventHandler,
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify) {
int maxDroppedFramesToNotify,
boolean mapDV7ToHevc) {
this(
context,
codecAdapterFactory,
Expand All @@ -300,7 +306,8 @@ public MediaCodecVideoRenderer(
eventHandler,
eventListener,
maxDroppedFramesToNotify,
/* assumedMinimumCodecOperatingRate= */ 30);
/* assumedMinimumCodecOperatingRate= */ 30,
mapDV7ToHevc);
}

/**
Expand Down Expand Up @@ -333,7 +340,8 @@ public MediaCodecVideoRenderer(
@Nullable Handler eventHandler,
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify,
float assumedMinimumCodecOperatingRate) {
float assumedMinimumCodecOperatingRate,
boolean mapDV7ToHevc) {
this(
context,
codecAdapterFactory,
Expand All @@ -344,7 +352,8 @@ public MediaCodecVideoRenderer(
eventListener,
maxDroppedFramesToNotify,
assumedMinimumCodecOperatingRate,
/* videoSinkProvider= */ null);
/* videoSinkProvider= */ null,
mapDV7ToHevc);
}

/**
Expand Down Expand Up @@ -383,7 +392,8 @@ public MediaCodecVideoRenderer(
@Nullable VideoRendererEventListener eventListener,
int maxDroppedFramesToNotify,
float assumedMinimumCodecOperatingRate,
@Nullable VideoSinkProvider videoSinkProvider) {
@Nullable VideoSinkProvider videoSinkProvider,
boolean mapDV7ToHevc) {
super(
C.TRACK_TYPE_VIDEO,
codecAdapterFactory,
Expand All @@ -392,6 +402,7 @@ public MediaCodecVideoRenderer(
assumedMinimumCodecOperatingRate);
this.context = context.getApplicationContext();
this.maxDroppedFramesToNotify = maxDroppedFramesToNotify;
this.mapDV7ToHevc = mapDV7ToHevc;
this.videoSinkProvider = videoSinkProvider;
eventDispatcher = new EventDispatcher(eventHandler, eventListener);
ownsVideoSink = videoSinkProvider == null;
Expand Down Expand Up @@ -461,7 +472,8 @@ public String getName() {
mediaCodecSelector,
format,
requiresSecureDecryption,
/* requiresTunnelingDecoder= */ false);
/* requiresTunnelingDecoder= */ false,
mapDV7ToHevc);
if (requiresSecureDecryption && decoderInfos.isEmpty()) {
// No secure decoders are available. Fall back to non-secure decoders.
decoderInfos =
Expand All @@ -470,7 +482,8 @@ public String getName() {
mediaCodecSelector,
format,
/* requiresSecureDecoder= */ false,
/* requiresTunnelingDecoder= */ false);
/* requiresTunnelingDecoder= */ false,
mapDV7ToHevc);
}
if (decoderInfos.isEmpty()) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
Expand Down Expand Up @@ -524,7 +537,8 @@ public String getName() {
mediaCodecSelector,
format,
requiresSecureDecryption,
/* requiresTunnelingDecoder= */ true);
/* requiresTunnelingDecoder= */ true,
mapDV7ToHevc);
if (!tunnelingDecoderInfos.isEmpty()) {
MediaCodecInfo tunnelingDecoderInfo =
MediaCodecUtil.getDecoderInfosSortedByFormatSupport(tunnelingDecoderInfos, format)
Expand All @@ -549,7 +563,7 @@ protected List<MediaCodecInfo> getDecoderInfos(
MediaCodecSelector mediaCodecSelector, Format format, boolean requiresSecureDecoder)
throws DecoderQueryException {
return MediaCodecUtil.getDecoderInfosSortedByFormatSupport(
getDecoderInfos(context, mediaCodecSelector, format, requiresSecureDecoder, tunneling),
getDecoderInfos(context, mediaCodecSelector, format, requiresSecureDecoder, tunneling, mapDV7ToHevc),
format);
}

Expand All @@ -576,7 +590,8 @@ private static List<MediaCodecInfo> getDecoderInfos(
MediaCodecSelector mediaCodecSelector,
Format format,
boolean requiresSecureDecoder,
boolean requiresTunnelingDecoder)
boolean requiresTunnelingDecoder,
boolean mapDV7ToHevc)
throws DecoderQueryException {
if (format.sampleMimeType == null) {
return ImmutableList.of();
Expand All @@ -586,7 +601,7 @@ private static List<MediaCodecInfo> getDecoderInfos(
&& !Api26.doesDisplaySupportDolbyVision(context)) {
List<MediaCodecInfo> alternativeDecoderInfos =
MediaCodecUtil.getAlternativeDecoderInfos(
mediaCodecSelector, format, requiresSecureDecoder, requiresTunnelingDecoder);
mediaCodecSelector, format, requiresSecureDecoder, requiresTunnelingDecoder, mapDV7ToHevc);
if (!alternativeDecoderInfos.isEmpty()) {
return alternativeDecoderInfos;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ public void setUp() throws Exception {
/* allowedJoiningTimeMs= */ 0,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1) {
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc= */ false) {
@Override
protected @Capabilities int supportsFormat(
MediaCodecSelector mediaCodecSelector, Format format) {
Expand Down Expand Up @@ -324,7 +325,8 @@ public void render_withBufferLimitEqualToNumberOfSamples_rendersLastFrameAfterEn
/* enableDecoderFallback= */ false,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1);
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc */ false);
mediaCodecVideoRenderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);
mediaCodecVideoRenderer.handleMessage(Renderer.MSG_SET_VIDEO_OUTPUT, surface);
mediaCodecVideoRenderer.enable(
Expand Down Expand Up @@ -435,7 +437,8 @@ public void onContinueLoadingRequested(MediaPeriod source) {
/* enableDecoderFallback= */ false,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1);
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc */ false);
mediaCodecVideoRenderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);
mediaCodecVideoRenderer.handleMessage(Renderer.MSG_SET_VIDEO_OUTPUT, surface);
mediaCodecVideoRenderer.enable(
Expand Down Expand Up @@ -540,7 +543,8 @@ public void onContinueLoadingRequested(MediaPeriod source) {
/* enableDecoderFallback= */ false,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1);
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc */ false);
mediaCodecVideoRenderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);
mediaCodecVideoRenderer.handleMessage(Renderer.MSG_SET_VIDEO_OUTPUT, surface);
mediaCodecVideoRenderer.enable(
Expand Down Expand Up @@ -1086,7 +1090,8 @@ public void supportsFormat_withDolbyVisionMedia_returnsTrueWhenFallbackToH265orH
/* allowedJoiningTimeMs= */ 0,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1);
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc= */ false);
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);

@Capabilities
Expand Down Expand Up @@ -1171,7 +1176,8 @@ public void supportsFormat_withDolbyVision_setsDecoderSupportFlagsByDisplayDolby
/* allowedJoiningTimeMs= */ 0,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1);
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc= */ false);
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);

@Capabilities int capabilitiesDvheDtr = renderer.supportsFormat(formatDvheDtr);
Expand Down Expand Up @@ -1231,7 +1237,8 @@ public void getDecoderInfo_withNonPerformantHardwareDecoder_returnsHardwareDecod
/* allowedJoiningTimeMs= */ 0,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1);
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc */ false);
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);

List<MediaCodecInfo> mediaCodecInfoList =
Expand Down Expand Up @@ -1274,7 +1281,8 @@ public void getDecoderInfo_softwareDecoderPreferred_returnsSoftwareDecoderFirst(
/* allowedJoiningTimeMs= */ 0,
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1);
/* maxDroppedFramesToNotify= */ 1,
/* mapDV7ToHevc */ false);
renderer.init(/* index= */ 0, PlayerId.UNSET, Clock.DEFAULT);

List<MediaCodecInfo> mediaCodecInfoList =
Expand Down Expand Up @@ -1312,7 +1320,8 @@ public void setOutputSurface(Surface surface) {
/* eventHandler= */ new Handler(testMainLooper),
/* eventListener= */ eventListener,
/* maxDroppedFramesToNotify= */ 1,
/* assumedMinimumCodecOperatingRate= */ 30) {
/* assumedMinimumCodecOperatingRate= */ 30,
/* mapDV7ToHevc */ false) {
@Override
protected @Capabilities int supportsFormat(
MediaCodecSelector mediaCodecSelector, Format format) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,20 @@ private DtsHeader(
1_920, 2_048, 2_304, 2_560, 2_688, 2_816, 2_823, 2_944, 3_072, 3_840, 4_096, 6_144, 7_680
};

/**
* Returns whether a given integer matches a DTS sync word. Synchronization and storage modes are
* defined in ETSI TS 102 114 V1.1.1 (2002-08), Section 5.3.
*
* @param word An integer.
* @return Whether a given integer matches a DTS sync word.
*/
public static boolean isSyncWord(int word) {
return word == SYNC_VALUE_BE
|| word == SYNC_VALUE_LE
|| word == SYNC_VALUE_14B_BE
|| word == SYNC_VALUE_14B_LE;
}

/**
* Maps MaxSampleRate index to sampling frequency in Hz. See ETSI TS 102 114 V1.6.1 (2019-08)
* Table 7-9.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,8 @@ public Renderer[] createRenderers(
/* enableDecoderFallback= */ false,
eventHandler,
videoRendererEventListener,
DefaultRenderersFactory.MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY) {
DefaultRenderersFactory.MAX_DROPPED_VIDEO_FRAME_COUNT_TO_NOTIFY,
/* mapDV7ToHevc= */ false) {
@Override
protected boolean shouldDropOutputBuffer(
long earlyUs, long elapsedRealtimeUs, boolean isLastBuffer) {
Expand Down

1 comment on commit 54798a4

@FongMi
Copy link

@FongMi FongMi commented on 54798a4 Aug 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try this pr?
androidx#1591

Please sign in to comment.