Merge pull request #7667 from willtrking:dev-v2-mkv-dovi

PiperOrigin-RevId: 328536503
This commit is contained in:
kim-vde 2020-08-26 16:40:35 +01:00
commit bcad98b9ff
2 changed files with 51 additions and 0 deletions

View File

@ -5,6 +5,9 @@
* Audio: Add an event for the audio position starting to advance, to make it * Audio: Add an event for the audio position starting to advance, to make it
easier for apps to determine when audio playout started easier for apps to determine when audio playout started
([#7577](https://github.com/google/ExoPlayer/issues/7577)). ([#7577](https://github.com/google/ExoPlayer/issues/7577)).
* Extractors:
* Support Dolby Vision extraction in Matroska
([#7267](https://github.com/google/ExoPlayer/issues/7267).
### 2.12.0 (not yet released - targeted for 2020-08-TBD) ### ### 2.12.0 (not yet released - targeted for 2020-08-TBD) ###

View File

@ -48,6 +48,7 @@ import com.google.android.exoplayer2.util.ParsableByteArray;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.android.exoplayer2.video.AvcConfig; import com.google.android.exoplayer2.video.AvcConfig;
import com.google.android.exoplayer2.video.ColorInfo; import com.google.android.exoplayer2.video.ColorInfo;
import com.google.android.exoplayer2.video.DolbyVisionConfig;
import com.google.android.exoplayer2.video.HevcConfig; import com.google.android.exoplayer2.video.HevcConfig;
import java.io.IOException; import java.io.IOException;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
@ -170,6 +171,9 @@ public class MatroskaExtractor implements Extractor {
private static final int ID_FLAG_FORCED = 0x55AA; private static final int ID_FLAG_FORCED = 0x55AA;
private static final int ID_DEFAULT_DURATION = 0x23E383; private static final int ID_DEFAULT_DURATION = 0x23E383;
private static final int ID_MAX_BLOCK_ADDITION_ID = 0x55EE; private static final int ID_MAX_BLOCK_ADDITION_ID = 0x55EE;
private static final int ID_BLOCK_ADDITION_MAPPING = 0x41E4;
private static final int ID_BLOCK_ADD_ID_TYPE = 0x41E7;
private static final int ID_BLOCK_ADD_ID_EXTRA_DATA = 0x41ED;
private static final int ID_NAME = 0x536E; private static final int ID_NAME = 0x536E;
private static final int ID_CODEC_ID = 0x86; private static final int ID_CODEC_ID = 0x86;
private static final int ID_CODEC_PRIVATE = 0x63A2; private static final int ID_CODEC_PRIVATE = 0x63A2;
@ -234,6 +238,17 @@ public class MatroskaExtractor implements Extractor {
*/ */
private static final int BLOCK_ADDITIONAL_ID_VP9_ITU_T_35 = 4; private static final int BLOCK_ADDITIONAL_ID_VP9_ITU_T_35 = 4;
/**
* BlockAddIdType value for Dolby Vision configuration with profile <= 7. See also
* https://www.matroska.org/technical/codec_specs.html.
*/
private static final int BLOCK_ADD_ID_TYPE_DVCC = 0x64766343;
/**
* BlockAddIdType value for Dolby Vision configuration with profile > 7. See also
* https://www.matroska.org/technical/codec_specs.html.
*/
private static final int BLOCK_ADD_ID_TYPE_DVVC = 0x64767643;
private static final int LACING_NONE = 0; private static final int LACING_NONE = 0;
private static final int LACING_XIPH = 1; private static final int LACING_XIPH = 1;
private static final int LACING_FIXED_SIZE = 2; private static final int LACING_FIXED_SIZE = 2;
@ -501,6 +516,7 @@ public class MatroskaExtractor implements Extractor {
case ID_CLUSTER: case ID_CLUSTER:
case ID_TRACKS: case ID_TRACKS:
case ID_TRACK_ENTRY: case ID_TRACK_ENTRY:
case ID_BLOCK_ADDITION_MAPPING:
case ID_AUDIO: case ID_AUDIO:
case ID_VIDEO: case ID_VIDEO:
case ID_CONTENT_ENCODINGS: case ID_CONTENT_ENCODINGS:
@ -535,6 +551,7 @@ public class MatroskaExtractor implements Extractor {
case ID_FLAG_FORCED: case ID_FLAG_FORCED:
case ID_DEFAULT_DURATION: case ID_DEFAULT_DURATION:
case ID_MAX_BLOCK_ADDITION_ID: case ID_MAX_BLOCK_ADDITION_ID:
case ID_BLOCK_ADD_ID_TYPE:
case ID_CODEC_DELAY: case ID_CODEC_DELAY:
case ID_SEEK_PRE_ROLL: case ID_SEEK_PRE_ROLL:
case ID_CHANNELS: case ID_CHANNELS:
@ -562,6 +579,7 @@ public class MatroskaExtractor implements Extractor {
case ID_LANGUAGE: case ID_LANGUAGE:
return EbmlProcessor.ELEMENT_TYPE_STRING; return EbmlProcessor.ELEMENT_TYPE_STRING;
case ID_SEEK_ID: case ID_SEEK_ID:
case ID_BLOCK_ADD_ID_EXTRA_DATA:
case ID_CONTENT_COMPRESSION_SETTINGS: case ID_CONTENT_COMPRESSION_SETTINGS:
case ID_CONTENT_ENCRYPTION_KEY_ID: case ID_CONTENT_ENCRYPTION_KEY_ID:
case ID_SIMPLE_BLOCK: case ID_SIMPLE_BLOCK:
@ -814,6 +832,9 @@ public class MatroskaExtractor implements Extractor {
case ID_MAX_BLOCK_ADDITION_ID: case ID_MAX_BLOCK_ADDITION_ID:
currentTrack.maxBlockAdditionId = (int) value; currentTrack.maxBlockAdditionId = (int) value;
break; break;
case ID_BLOCK_ADD_ID_TYPE:
currentTrack.blockAddIdType = (int) value;
break;
case ID_CODEC_DELAY: case ID_CODEC_DELAY:
currentTrack.codecDelayNs = value; currentTrack.codecDelayNs = value;
break; break;
@ -1076,6 +1097,9 @@ public class MatroskaExtractor implements Extractor {
seekEntryIdBytes.setPosition(0); seekEntryIdBytes.setPosition(0);
seekEntryId = (int) seekEntryIdBytes.readUnsignedInt(); seekEntryId = (int) seekEntryIdBytes.readUnsignedInt();
break; break;
case ID_BLOCK_ADD_ID_EXTRA_DATA:
handleBlockAddIDExtraData(currentTrack, input, contentSize);
break;
case ID_CODEC_PRIVATE: case ID_CODEC_PRIVATE:
currentTrack.codecPrivate = new byte[contentSize]; currentTrack.codecPrivate = new byte[contentSize];
input.readFully(currentTrack.codecPrivate, 0, contentSize); input.readFully(currentTrack.codecPrivate, 0, contentSize);
@ -1244,6 +1268,18 @@ public class MatroskaExtractor implements Extractor {
} }
} }
protected void handleBlockAddIDExtraData(Track track, ExtractorInput input, int contentSize)
throws IOException {
if (track.blockAddIdType == BLOCK_ADD_ID_TYPE_DVVC
|| track.blockAddIdType == BLOCK_ADD_ID_TYPE_DVCC) {
track.dolbyVisionConfigBytes = new byte[contentSize];
input.readFully(track.dolbyVisionConfigBytes, 0, contentSize);
} else {
// Unhandled BlockAddIDExtraData.
input.skipFully(contentSize);
}
}
protected void handleBlockAdditionalData( protected void handleBlockAdditionalData(
Track track, int blockAdditionalId, ExtractorInput input, int contentSize) Track track, int blockAdditionalId, ExtractorInput input, int contentSize)
throws IOException { throws IOException {
@ -1883,6 +1919,7 @@ public class MatroskaExtractor implements Extractor {
public int type; public int type;
public int defaultSampleDurationNs; public int defaultSampleDurationNs;
public int maxBlockAdditionId; public int maxBlockAdditionId;
private int blockAddIdType;
public boolean hasContentEncryption; public boolean hasContentEncryption;
public byte[] sampleStrippedBytes; public byte[] sampleStrippedBytes;
public TrackOutput.CryptoData cryptoData; public TrackOutput.CryptoData cryptoData;
@ -1921,6 +1958,7 @@ public class MatroskaExtractor implements Extractor {
public float whitePointChromaticityY = Format.NO_VALUE; public float whitePointChromaticityY = Format.NO_VALUE;
public float maxMasteringLuminance = Format.NO_VALUE; public float maxMasteringLuminance = Format.NO_VALUE;
public float minMasteringLuminance = Format.NO_VALUE; public float minMasteringLuminance = Format.NO_VALUE;
@Nullable public byte[] dolbyVisionConfigBytes;
// Audio elements. Initially set to their default values. // Audio elements. Initially set to their default values.
public int channelCount = 1; public int channelCount = 1;
@ -2091,6 +2129,16 @@ public class MatroskaExtractor implements Extractor {
throw new ParserException("Unrecognized codec identifier."); throw new ParserException("Unrecognized codec identifier.");
} }
if (dolbyVisionConfigBytes != null) {
@Nullable
DolbyVisionConfig dolbyVisionConfig =
DolbyVisionConfig.parse(new ParsableByteArray(this.dolbyVisionConfigBytes));
if (dolbyVisionConfig != null) {
codecs = dolbyVisionConfig.codecs;
mimeType = MimeTypes.VIDEO_DOLBY_VISION;
}
}
@C.SelectionFlags int selectionFlags = 0; @C.SelectionFlags int selectionFlags = 0;
selectionFlags |= flagDefault ? C.SELECTION_FLAG_DEFAULT : 0; selectionFlags |= flagDefault ? C.SELECTION_FLAG_DEFAULT : 0;
selectionFlags |= flagForced ? C.SELECTION_FLAG_FORCED : 0; selectionFlags |= flagForced ? C.SELECTION_FLAG_FORCED : 0;