1 /* 2 * Copyright (C) 2016 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 package org.mozilla.thirdparty.com.google.android.exoplayer2.extractor; 17 18 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.amr.AmrExtractor; 19 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.flac.FlacExtractor; 20 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.flv.FlvExtractor; 21 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor; 22 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.mp3.Mp3Extractor; 23 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.mp4.FragmentedMp4Extractor; 24 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.mp4.Mp4Extractor; 25 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ogg.OggExtractor; 26 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ts.Ac3Extractor; 27 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ts.Ac4Extractor; 28 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ts.AdtsExtractor; 29 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ts.DefaultTsPayloadReaderFactory; 30 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ts.PsExtractor; 31 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ts.TsExtractor; 32 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.ts.TsPayloadReader; 33 import org.mozilla.thirdparty.com.google.android.exoplayer2.extractor.wav.WavExtractor; 34 import org.mozilla.thirdparty.com.google.android.exoplayer2.util.TimestampAdjuster; 35 import java.lang.reflect.Constructor; 36 37 /** 38 * An {@link ExtractorsFactory} that provides an array of extractors for the following formats: 39 * 40 * <ul> 41 * <li>MP4, including M4A ({@link Mp4Extractor}) 42 * <li>fMP4 ({@link FragmentedMp4Extractor}) 43 * <li>Matroska and WebM ({@link MatroskaExtractor}) 44 * <li>Ogg Vorbis/FLAC ({@link OggExtractor} 45 * <li>MP3 ({@link Mp3Extractor}) 46 * <li>AAC ({@link AdtsExtractor}) 47 * <li>MPEG TS ({@link TsExtractor}) 48 * <li>MPEG PS ({@link PsExtractor}) 49 * <li>FLV ({@link FlvExtractor}) 50 * <li>WAV ({@link WavExtractor}) 51 * <li>AC3 ({@link Ac3Extractor}) 52 * <li>AC4 ({@link Ac4Extractor}) 53 * <li>AMR ({@link AmrExtractor}) 54 * <li>FLAC 55 * <ul> 56 * <li>If available, the FLAC extension extractor is used. 57 * <li>Otherwise, the core {@link FlacExtractor} is used. Note that Android devices do not 58 * generally include a FLAC decoder before API 27. This can be worked around by using 59 * the FLAC extension or the FFmpeg extension. 60 * </ul> 61 * </ul> 62 */ 63 public final class DefaultExtractorsFactory implements ExtractorsFactory { 64 65 private static final Constructor<? extends Extractor> FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR; 66 67 static { 68 Constructor<? extends Extractor> flacExtensionExtractorConstructor = null; 69 try { 70 // LINT.IfChange 71 @SuppressWarnings("nullness:argument.type.incompatible") 72 boolean isFlacNativeLibraryAvailable = 73 Boolean.TRUE.equals( 74 Class.forName("com.google.android.exoplayer2.ext.flac.FlacLibrary") 75 .getMethod("isAvailable") 76 .invoke(/* obj= */ null)); 77 if (isFlacNativeLibraryAvailable) { 78 flacExtensionExtractorConstructor = 79 Class.forName("com.google.android.exoplayer2.ext.flac.FlacExtractor") 80 .asSubclass(Extractor.class) 81 .getConstructor(); 82 } 83 // LINT.ThenChange(../../../../../../../../proguard-rules.txt) 84 } catch (ClassNotFoundException e) { 85 // Expected if the app was built without the FLAC extension. 86 } catch (Exception e) { 87 // The FLAC extension is present, but instantiation failed. 88 throw new RuntimeException("Error instantiating FLAC extension", e); 89 } 90 FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR = flacExtensionExtractorConstructor; 91 } 92 93 private boolean constantBitrateSeekingEnabled; 94 private @AdtsExtractor.Flags int adtsFlags; 95 private @AmrExtractor.Flags int amrFlags; 96 private @MatroskaExtractor.Flags int matroskaFlags; 97 private @Mp4Extractor.Flags int mp4Flags; 98 private @FragmentedMp4Extractor.Flags int fragmentedMp4Flags; 99 private @Mp3Extractor.Flags int mp3Flags; 100 private @TsExtractor.Mode int tsMode; 101 private @DefaultTsPayloadReaderFactory.Flags int tsFlags; 102 DefaultExtractorsFactory()103 public DefaultExtractorsFactory() { 104 tsMode = TsExtractor.MODE_SINGLE_PMT; 105 } 106 107 /** 108 * Convenience method to set whether approximate seeking using constant bitrate assumptions should 109 * be enabled for all extractors that support it. If set to true, the flags required to enable 110 * this functionality will be OR'd with those passed to the setters when creating extractor 111 * instances. If set to false then the flags passed to the setters will be used without 112 * modification. 113 * 114 * @param constantBitrateSeekingEnabled Whether approximate seeking using a constant bitrate 115 * assumption should be enabled for all extractors that support it. 116 * @return The factory, for convenience. 117 */ setConstantBitrateSeekingEnabled( boolean constantBitrateSeekingEnabled)118 public synchronized DefaultExtractorsFactory setConstantBitrateSeekingEnabled( 119 boolean constantBitrateSeekingEnabled) { 120 this.constantBitrateSeekingEnabled = constantBitrateSeekingEnabled; 121 return this; 122 } 123 124 /** 125 * Sets flags for {@link AdtsExtractor} instances created by the factory. 126 * 127 * @see AdtsExtractor#AdtsExtractor(int) 128 * @param flags The flags to use. 129 * @return The factory, for convenience. 130 */ setAdtsExtractorFlags( @dtsExtractor.Flags int flags)131 public synchronized DefaultExtractorsFactory setAdtsExtractorFlags( 132 @AdtsExtractor.Flags int flags) { 133 this.adtsFlags = flags; 134 return this; 135 } 136 137 /** 138 * Sets flags for {@link AmrExtractor} instances created by the factory. 139 * 140 * @see AmrExtractor#AmrExtractor(int) 141 * @param flags The flags to use. 142 * @return The factory, for convenience. 143 */ setAmrExtractorFlags(@mrExtractor.Flags int flags)144 public synchronized DefaultExtractorsFactory setAmrExtractorFlags(@AmrExtractor.Flags int flags) { 145 this.amrFlags = flags; 146 return this; 147 } 148 149 /** 150 * Sets flags for {@link MatroskaExtractor} instances created by the factory. 151 * 152 * @see MatroskaExtractor#MatroskaExtractor(int) 153 * @param flags The flags to use. 154 * @return The factory, for convenience. 155 */ setMatroskaExtractorFlags( @atroskaExtractor.Flags int flags)156 public synchronized DefaultExtractorsFactory setMatroskaExtractorFlags( 157 @MatroskaExtractor.Flags int flags) { 158 this.matroskaFlags = flags; 159 return this; 160 } 161 162 /** 163 * Sets flags for {@link Mp4Extractor} instances created by the factory. 164 * 165 * @see Mp4Extractor#Mp4Extractor(int) 166 * @param flags The flags to use. 167 * @return The factory, for convenience. 168 */ setMp4ExtractorFlags(@p4Extractor.Flags int flags)169 public synchronized DefaultExtractorsFactory setMp4ExtractorFlags(@Mp4Extractor.Flags int flags) { 170 this.mp4Flags = flags; 171 return this; 172 } 173 174 /** 175 * Sets flags for {@link FragmentedMp4Extractor} instances created by the factory. 176 * 177 * @see FragmentedMp4Extractor#FragmentedMp4Extractor(int) 178 * @param flags The flags to use. 179 * @return The factory, for convenience. 180 */ setFragmentedMp4ExtractorFlags( @ragmentedMp4Extractor.Flags int flags)181 public synchronized DefaultExtractorsFactory setFragmentedMp4ExtractorFlags( 182 @FragmentedMp4Extractor.Flags int flags) { 183 this.fragmentedMp4Flags = flags; 184 return this; 185 } 186 187 /** 188 * Sets flags for {@link Mp3Extractor} instances created by the factory. 189 * 190 * @see Mp3Extractor#Mp3Extractor(int) 191 * @param flags The flags to use. 192 * @return The factory, for convenience. 193 */ setMp3ExtractorFlags(@p3Extractor.Flags int flags)194 public synchronized DefaultExtractorsFactory setMp3ExtractorFlags(@Mp3Extractor.Flags int flags) { 195 mp3Flags = flags; 196 return this; 197 } 198 199 /** 200 * Sets the mode for {@link TsExtractor} instances created by the factory. 201 * 202 * @see TsExtractor#TsExtractor(int, TimestampAdjuster, TsPayloadReader.Factory) 203 * @param mode The mode to use. 204 * @return The factory, for convenience. 205 */ setTsExtractorMode(@sExtractor.Mode int mode)206 public synchronized DefaultExtractorsFactory setTsExtractorMode(@TsExtractor.Mode int mode) { 207 tsMode = mode; 208 return this; 209 } 210 211 /** 212 * Sets flags for {@link DefaultTsPayloadReaderFactory}s used by {@link TsExtractor} instances 213 * created by the factory. 214 * 215 * @see TsExtractor#TsExtractor(int) 216 * @param flags The flags to use. 217 * @return The factory, for convenience. 218 */ setTsExtractorFlags( @efaultTsPayloadReaderFactory.Flags int flags)219 public synchronized DefaultExtractorsFactory setTsExtractorFlags( 220 @DefaultTsPayloadReaderFactory.Flags int flags) { 221 tsFlags = flags; 222 return this; 223 } 224 225 @Override createExtractors()226 public synchronized Extractor[] createExtractors() { 227 Extractor[] extractors = new Extractor[14]; 228 extractors[0] = new MatroskaExtractor(matroskaFlags); 229 extractors[1] = new FragmentedMp4Extractor(fragmentedMp4Flags); 230 extractors[2] = new Mp4Extractor(mp4Flags); 231 extractors[3] = 232 new Mp3Extractor( 233 mp3Flags 234 | (constantBitrateSeekingEnabled 235 ? Mp3Extractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING 236 : 0)); 237 extractors[4] = 238 new AdtsExtractor( 239 adtsFlags 240 | (constantBitrateSeekingEnabled 241 ? AdtsExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING 242 : 0)); 243 extractors[5] = new Ac3Extractor(); 244 extractors[6] = new TsExtractor(tsMode, tsFlags); 245 extractors[7] = new FlvExtractor(); 246 extractors[8] = new OggExtractor(); 247 extractors[9] = new PsExtractor(); 248 extractors[10] = new WavExtractor(); 249 extractors[11] = 250 new AmrExtractor( 251 amrFlags 252 | (constantBitrateSeekingEnabled 253 ? AmrExtractor.FLAG_ENABLE_CONSTANT_BITRATE_SEEKING 254 : 0)); 255 extractors[12] = new Ac4Extractor(); 256 if (FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR != null) { 257 try { 258 extractors[13] = FLAC_EXTENSION_EXTRACTOR_CONSTRUCTOR.newInstance(); 259 } catch (Exception e) { 260 // Should never happen. 261 throw new IllegalStateException("Unexpected error creating FLAC extractor", e); 262 } 263 } else { 264 extractors[13] = new FlacExtractor(); 265 } 266 return extractors; 267 } 268 269 } 270