diff options
author | Santiago Seifert <aquilescanta@google.com> | 2020-04-15 18:05:45 +0100 |
---|---|---|
committer | Santiago Seifert <aquilescanta@google.com> | 2020-04-17 16:26:17 +0100 |
commit | c6955798175589f240fbacd120d289d1148aceae (patch) | |
tree | 5d6735ee58394f9352824dcab89a4ebafef0157b /apex/media | |
parent | 3eea61dd1f1e9e2e10dc5587281bef8487854306 (diff) |
Populate some missing fields in TrackData
Involving MediaFormat and DrmInitData
Bug: 154120292
Test: atest CtsMediaParserTestCases
Change-Id: If1d334633846020c4ffc166f148f9f841f5318a4
Diffstat (limited to 'apex/media')
-rw-r--r-- | apex/media/framework/java/android/media/MediaParser.java | 90 |
1 files changed, 82 insertions, 8 deletions
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java index b3c82bc6bebf..d31d731f5639 100644 --- a/apex/media/framework/java/android/media/MediaParser.java +++ b/apex/media/framework/java/android/media/MediaParser.java @@ -23,12 +23,14 @@ import android.annotation.StringDef; import android.media.MediaCodec.CryptoInfo; import android.net.Uri; import android.text.TextUtils; +import android.util.Log; import android.util.Pair; import android.util.SparseArray; import com.google.android.exoplayer2.C; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.ParserException; +import com.google.android.exoplayer2.drm.DrmInitData.SchemeData; import com.google.android.exoplayer2.extractor.DefaultExtractorInput; import com.google.android.exoplayer2.extractor.Extractor; import com.google.android.exoplayer2.extractor.ExtractorInput; @@ -63,6 +65,8 @@ import java.io.EOFException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; @@ -70,6 +74,7 @@ import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.UUID; /** * Parses media container formats and extracts contained media samples and metadata. @@ -711,11 +716,14 @@ public final class MediaParser { // Private constants. + private static final String TAG = "MediaParser"; private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME; private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME; private static final String TS_MODE_SINGLE_PMT = "single_pmt"; private static final String TS_MODE_MULTI_PMT = "multi_pmt"; private static final String TS_MODE_HLS = "hls"; + @Nullable + private static final Constructor<DrmInitData.SchemeInitData> SCHEME_INIT_DATA_CONSTRUCTOR; // Instance creation methods. @@ -855,6 +863,7 @@ public final class MediaParser { private ExtractorInput mExtractorInput; private long mPendingSeekPosition; private long mPendingSeekTimeMicros; + private boolean mLoggedSchemeInitDataCreationException; // Public methods. @@ -1216,6 +1225,47 @@ public final class MediaParser { } } + private static final class MediaParserDrmInitData extends DrmInitData { + + private final SchemeInitData[] mSchemeDatas; + + private MediaParserDrmInitData(com.google.android.exoplayer2.drm.DrmInitData exoDrmInitData) + throws IllegalAccessException, InstantiationException, InvocationTargetException { + mSchemeDatas = new SchemeInitData[exoDrmInitData.schemeDataCount]; + for (int i = 0; i < mSchemeDatas.length; i++) { + mSchemeDatas[i] = toFrameworkSchemeInitData(exoDrmInitData.get(i)); + } + } + + @Override + @Nullable + public SchemeInitData get(UUID schemeUuid) { + for (SchemeInitData schemeInitData : mSchemeDatas) { + if (schemeInitData.uuid.equals(schemeUuid)) { + return schemeInitData; + } + } + return null; + } + + @Override + public SchemeInitData getSchemeInitDataAt(int index) { + return mSchemeDatas[index]; + } + + @Override + public int getSchemeInitDataCount() { + return mSchemeDatas.length; + } + + private static DrmInitData.SchemeInitData toFrameworkSchemeInitData( + SchemeData exoSchemeData) + throws IllegalAccessException, InvocationTargetException, InstantiationException { + return SCHEME_INIT_DATA_CONSTRUCTOR.newInstance( + exoSchemeData.uuid, exoSchemeData.mimeType, exoSchemeData.data); + } + } + private final class ExtractorOutputAdapter implements ExtractorOutput { private final SparseArray<TrackOutput> mTrackOutputAdapters; @@ -1402,6 +1452,8 @@ public final class MediaParser { setOptionalMediaFormatInt(result, MediaFormat.KEY_PCM_ENCODING, format.pcmEncoding); setOptionalMediaFormatInt(result, MediaFormat.KEY_ROTATION, format.rotationDegrees); setOptionalMediaFormatInt(result, MediaFormat.KEY_SAMPLE_RATE, format.sampleRate); + setOptionalMediaFormatInt( + result, MediaFormat.KEY_CAPTION_SERVICE_NUMBER, format.accessibilityChannel); int selectionFlags = format.selectionFlags; result.setInteger( @@ -1427,15 +1479,16 @@ public final class MediaParser { result.setInteger(MediaFormat.KEY_PIXEL_ASPECT_RATIO_HEIGHT, parHeight); result.setFloat("pixel-width-height-ratio-float", format.pixelWidthHeightRatio); } - + if (format.drmInitData != null) { + // The crypto mode is propagated along with sample metadata. We also include it in the + // format for convenient use from ExoPlayer. + result.setString("crypto-mode-fourcc", format.drmInitData.schemeType); + } // LACK OF SUPPORT FOR: - // format.accessibilityChannel; // format.containerMimeType; // format.id; // format.metadata; - // format.roleFlags; // format.stereoMode; - // format.subsampleOffsetUs; return result; } @@ -1452,10 +1505,19 @@ public final class MediaParser { } } - private static DrmInitData toFrameworkDrmInitData( - com.google.android.exoplayer2.drm.DrmInitData drmInitData) { - // TODO: Implement. - return null; + private DrmInitData toFrameworkDrmInitData( + com.google.android.exoplayer2.drm.DrmInitData exoDrmInitData) { + try { + return exoDrmInitData != null && SCHEME_INIT_DATA_CONSTRUCTOR != null + ? new MediaParserDrmInitData(exoDrmInitData) + : null; + } catch (Throwable e) { + if (!mLoggedSchemeInitDataCreationException) { + mLoggedSchemeInitDataCreationException = true; + Log.e(TAG, "Unable to create SchemeInitData instance."); + } + return null; + } } private static CryptoInfo toCryptoInfo(TrackOutput.CryptoData encryptionData) { @@ -1525,5 +1587,17 @@ public final class MediaParser { expectedTypeByParameterName.put(PARAMETER_TS_DETECT_ACCESS_UNITS, Boolean.class); expectedTypeByParameterName.put(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS, Boolean.class); EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName); + + // TODO: Use constructor statically when available. + Constructor<DrmInitData.SchemeInitData> constructor; + try { + constructor = + DrmInitData.SchemeInitData.class.getConstructor( + UUID.class, String.class, byte[].class); + } catch (Throwable e) { + Log.e(TAG, "Unable to get SchemeInitData constructor."); + constructor = null; + } + SCHEME_INIT_DATA_CONSTRUCTOR = constructor; } } |