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