• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.android.exoplayer2.transformer;
18 
19 import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
20 import static com.google.android.exoplayer2.util.Util.SDK_INT;
21 
22 import android.media.MediaFormat;
23 import android.view.Surface;
24 import androidx.annotation.Nullable;
25 import com.google.android.exoplayer2.Format;
26 import com.google.android.exoplayer2.util.MediaFormatUtil;
27 import com.google.android.exoplayer2.util.MimeTypes;
28 import org.checkerframework.checker.nullness.qual.RequiresNonNull;
29 
30 /** A default implementation of {@link Codec.DecoderFactory}. */
31 /* package */ final class DefaultDecoderFactory implements Codec.DecoderFactory {
32 
33   @Override
createForAudioDecoding(Format format)34   public Codec createForAudioDecoding(Format format) throws TransformationException {
35     MediaFormat mediaFormat =
36         MediaFormat.createAudioFormat(
37             checkNotNull(format.sampleMimeType), format.sampleRate, format.channelCount);
38     MediaFormatUtil.maybeSetInteger(
39         mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
40     MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
41 
42     @Nullable
43     String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
44     if (mediaCodecName == null) {
45       throw createTransformationException(format);
46     }
47     return new DefaultCodec(
48         format, mediaFormat, mediaCodecName, /* isDecoder= */ true, /* outputSurface= */ null);
49   }
50 
51   @Override
createForVideoDecoding( Format format, Surface outputSurface, boolean enableRequestSdrToneMapping)52   public Codec createForVideoDecoding(
53       Format format, Surface outputSurface, boolean enableRequestSdrToneMapping)
54       throws TransformationException {
55     MediaFormat mediaFormat =
56         MediaFormat.createVideoFormat(
57             checkNotNull(format.sampleMimeType), format.width, format.height);
58     MediaFormatUtil.maybeSetInteger(mediaFormat, MediaFormat.KEY_ROTATION, format.rotationDegrees);
59     MediaFormatUtil.maybeSetInteger(
60         mediaFormat, MediaFormat.KEY_MAX_INPUT_SIZE, format.maxInputSize);
61     MediaFormatUtil.setCsdBuffers(mediaFormat, format.initializationData);
62     if (SDK_INT >= 29) {
63       // On API levels over 29, Transformer decodes as many frames as possible in one render
64       // cycle. This key ensures no frame dropping when the decoder's output surface is full.
65       mediaFormat.setInteger(MediaFormat.KEY_ALLOW_FRAME_DROP, 0);
66     }
67     if (SDK_INT >= 31 && enableRequestSdrToneMapping) {
68       mediaFormat.setInteger(
69           MediaFormat.KEY_COLOR_TRANSFER_REQUEST, MediaFormat.COLOR_TRANSFER_SDR_VIDEO);
70     }
71 
72     @Nullable
73     String mediaCodecName = EncoderUtil.findCodecForFormat(mediaFormat, /* isDecoder= */ true);
74     if (mediaCodecName == null) {
75       throw createTransformationException(format);
76     }
77     return new DefaultCodec(
78         format, mediaFormat, mediaCodecName, /* isDecoder= */ true, outputSurface);
79   }
80 
81   @RequiresNonNull("#1.sampleMimeType")
createTransformationException(Format format)82   private static TransformationException createTransformationException(Format format) {
83     return TransformationException.createForCodec(
84         new IllegalArgumentException("The requested decoding format is not supported."),
85         MimeTypes.isVideo(format.sampleMimeType),
86         /* isDecoder= */ true,
87         format,
88         /* mediaCodecName= */ null,
89         TransformationException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED);
90   }
91 }
92