mirror of
https://github.com/androidx/media.git
synced 2025-04-30 06:46:50 +08:00
Merge pull request #1265 from DolbyLaboratories:dlb/ac4-level4/dev_new2
PiperOrigin-RevId: 696157037
This commit is contained in:
commit
74611bbdc0
@ -29,6 +29,8 @@
|
||||
* Add support for transmuxing into alternative backwards compatible
|
||||
formats.
|
||||
* Extractors:
|
||||
* Add AC-4 Level-4 ISO base media file format support
|
||||
([#1265](https://github.com/androidx/media/pull/1265)).
|
||||
* DataSource:
|
||||
* `DataSourceContractTest`: Assert that `DataSource.getUri()` and
|
||||
`getResponseHeaders()` return their 'open' value after a failed call to
|
||||
|
@ -2251,6 +2251,24 @@ public final class Util {
|
||||
}
|
||||
case 12:
|
||||
return AudioFormat.CHANNEL_OUT_7POINT1POINT4;
|
||||
case 24:
|
||||
if (Util.SDK_INT >= 32) {
|
||||
return AudioFormat.CHANNEL_OUT_7POINT1POINT4
|
||||
| AudioFormat.CHANNEL_OUT_FRONT_LEFT_OF_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_FRONT_RIGHT_OF_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_BACK_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_TOP_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_TOP_FRONT_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_TOP_BACK_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_TOP_SIDE_LEFT
|
||||
| AudioFormat.CHANNEL_OUT_TOP_SIDE_RIGHT
|
||||
| AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_LEFT
|
||||
| AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_RIGHT
|
||||
| AudioFormat.CHANNEL_OUT_BOTTOM_FRONT_CENTER
|
||||
| AudioFormat.CHANNEL_OUT_LOW_FREQUENCY_2;
|
||||
} else {
|
||||
return AudioFormat.CHANNEL_INVALID;
|
||||
}
|
||||
default:
|
||||
return AudioFormat.CHANNEL_INVALID;
|
||||
}
|
||||
|
@ -4293,18 +4293,22 @@ public class DefaultTrackSelector extends MappingTrackSelector
|
||||
|
||||
public boolean canBeSpatialized(AudioAttributes audioAttributes, Format format) {
|
||||
int linearChannelCount;
|
||||
if (Objects.equals(format.sampleMimeType, MimeTypes.AUDIO_E_AC3_JOC)
|
||||
&& format.channelCount == 16) {
|
||||
if (Objects.equals(format.sampleMimeType, MimeTypes.AUDIO_E_AC3_JOC)) {
|
||||
// For E-AC3 JOC, the format is object based. When the channel count is 16, this maps to 12
|
||||
// linear channels and the rest are used for objects. See
|
||||
// https://github.com/google/ExoPlayer/pull/10322#discussion_r895265881
|
||||
linearChannelCount = 12;
|
||||
} else if (Objects.equals(format.sampleMimeType, MimeTypes.AUDIO_IAMF)
|
||||
&& format.channelCount == Format.NO_VALUE) {
|
||||
linearChannelCount = format.channelCount == 16 ? 12 : format.channelCount;
|
||||
} else if (Objects.equals(format.sampleMimeType, MimeTypes.AUDIO_IAMF)) {
|
||||
// IAMF with no channel count specified, assume 5.1 channels. This depends on
|
||||
// IamfDecoder.SPATIALIZED_OUTPUT_LAYOUT being set to AudioFormat.CHANNEL_OUT_5POINT1. Any
|
||||
// changes to that constant will require updates to this logic.
|
||||
linearChannelCount = 6;
|
||||
linearChannelCount = format.channelCount == Format.NO_VALUE ? 6 : format.channelCount;
|
||||
} else if (Objects.equals(format.sampleMimeType, MimeTypes.AUDIO_AC4)) {
|
||||
// For AC-4 level 3 or level 4, the format may be object based. When the channel count is
|
||||
// 18 (level 3 17.1 OBI) or 21 (level 4 20.1 OBI), it is mapped to 24 linear channels (some
|
||||
// channels are used for metadata transfer).
|
||||
linearChannelCount =
|
||||
(format.channelCount == 18 || format.channelCount == 21) ? 24 : format.channelCount;
|
||||
} else {
|
||||
linearChannelCount = format.channelCount;
|
||||
}
|
||||
|
@ -15,14 +15,22 @@
|
||||
*/
|
||||
package androidx.media3.extractor;
|
||||
|
||||
import static java.lang.annotation.ElementType.TYPE_USE;
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.C;
|
||||
import androidx.media3.common.DrmInitData;
|
||||
import androidx.media3.common.Format;
|
||||
import androidx.media3.common.MimeTypes;
|
||||
import androidx.media3.common.ParserException;
|
||||
import androidx.media3.common.util.ParsableBitArray;
|
||||
import androidx.media3.common.util.ParsableByteArray;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.Target;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/** Utility methods for parsing AC-4 frames, which are access units in AC-4 bitstreams. */
|
||||
@ -57,6 +65,52 @@ public final class Ac4Util {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Types of channel modes for AC-4 audio as per ETSI TS 103 190-2 V1.1.1 (2015-09), Section
|
||||
* 6.3.2.7.2, Table 79.
|
||||
*/
|
||||
@Documented
|
||||
@Retention(SOURCE)
|
||||
@Target(TYPE_USE)
|
||||
@IntDef({
|
||||
CHANNEL_MODE_UNKNOWN,
|
||||
CHANNEL_MODE_MONO,
|
||||
CHANNEL_MODE_STEREO,
|
||||
CHANNEL_MODE_3_0,
|
||||
CHANNEL_MODE_5_0,
|
||||
CHANNEL_MODE_5_1,
|
||||
CHANNEL_MODE_7_0_34,
|
||||
CHANNEL_MODE_7_1_34,
|
||||
CHANNEL_MODE_7_0_52,
|
||||
CHANNEL_MODE_7_1_52,
|
||||
CHANNEL_MODE_7_0_322,
|
||||
CHANNEL_MODE_7_1_322,
|
||||
CHANNEL_MODE_7_0_4,
|
||||
CHANNEL_MODE_7_1_4,
|
||||
CHANNEL_MODE_9_0_4,
|
||||
CHANNEL_MODE_9_1_4,
|
||||
CHANNEL_MODE_22_2
|
||||
})
|
||||
private @interface ChannelMode {}
|
||||
|
||||
private static final int CHANNEL_MODE_UNKNOWN = -1;
|
||||
private static final int CHANNEL_MODE_MONO = 0;
|
||||
private static final int CHANNEL_MODE_STEREO = 1;
|
||||
private static final int CHANNEL_MODE_3_0 = 2;
|
||||
private static final int CHANNEL_MODE_5_0 = 3;
|
||||
private static final int CHANNEL_MODE_5_1 = 4;
|
||||
private static final int CHANNEL_MODE_7_0_34 = 5;
|
||||
private static final int CHANNEL_MODE_7_1_34 = 6;
|
||||
private static final int CHANNEL_MODE_7_0_52 = 7;
|
||||
private static final int CHANNEL_MODE_7_1_52 = 8;
|
||||
private static final int CHANNEL_MODE_7_0_322 = 9;
|
||||
private static final int CHANNEL_MODE_7_1_322 = 10;
|
||||
private static final int CHANNEL_MODE_7_0_4 = 11;
|
||||
private static final int CHANNEL_MODE_7_1_4 = 12;
|
||||
private static final int CHANNEL_MODE_9_0_4 = 13;
|
||||
private static final int CHANNEL_MODE_9_1_4 = 14;
|
||||
private static final int CHANNEL_MODE_22_2 = 15;
|
||||
|
||||
public static final int AC40_SYNCWORD = 0xAC40;
|
||||
public static final int AC41_SYNCWORD = 0xAC41;
|
||||
|
||||
@ -104,28 +158,467 @@ public final class Ac4Util {
|
||||
|
||||
/**
|
||||
* Returns the AC-4 format given {@code data} containing the AC4SpecificBox according to ETSI TS
|
||||
* 103 190-1 Annex E. The reading position of {@code data} will be modified.
|
||||
* 103 190-1 Annex E.4 (ac4_dsi) and TS 103 190-2 section E.6 (ac4_dsi_v1). The reading position
|
||||
* of {@code data} will be modified.
|
||||
*
|
||||
* @param data The AC4SpecificBox to parse.
|
||||
* @param trackId The track identifier to set on the format.
|
||||
* @param language The language to set on the format.
|
||||
* @param drmInitData {@link DrmInitData} to be included in the format.
|
||||
* @return The AC-4 format parsed from data in the header.
|
||||
* @throws ParserException If an unsupported container feature is encountered while parsing AC-4
|
||||
* Annex E.
|
||||
*/
|
||||
public static Format parseAc4AnnexEFormat(
|
||||
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData) {
|
||||
data.skipBytes(1); // ac4_dsi_version, bitstream_version[0:5]
|
||||
int sampleRate = ((data.readUnsignedByte() & 0x20) >> 5 == 1) ? 48000 : 44100;
|
||||
ParsableByteArray data, String trackId, String language, @Nullable DrmInitData drmInitData)
|
||||
throws ParserException {
|
||||
ParsableBitArray dataBitArray = new ParsableBitArray();
|
||||
dataBitArray.reset(data);
|
||||
|
||||
int dsiSize = dataBitArray.bitsLeft();
|
||||
int ac4DsiVersion = dataBitArray.readBits(3); // ac4_dsi_version
|
||||
if (ac4DsiVersion > 1) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
"Unsupported AC-4 DSI version: " + ac4DsiVersion);
|
||||
}
|
||||
|
||||
int bitstreamVersion = dataBitArray.readBits(7); // bitstream_version
|
||||
int sampleRate = dataBitArray.readBit() ? 48000 : 44100; // fs_index
|
||||
dataBitArray.skipBits(4); // frame_rate_index
|
||||
int numberOfPresentations = dataBitArray.readBits(9); // n_presentations
|
||||
|
||||
if (bitstreamVersion > 1) {
|
||||
if (ac4DsiVersion == 0) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
"Invalid AC-4 DSI version: " + ac4DsiVersion);
|
||||
}
|
||||
if (dataBitArray.readBit()) { // b_program_id
|
||||
dataBitArray.skipBits(16); // short_program_id
|
||||
if (dataBitArray.readBit()) { // b_uuid
|
||||
dataBitArray.skipBits(16 * 8); // program_uuid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ac4DsiVersion == 1) {
|
||||
if (!skipDsiBitrate(dataBitArray)) {
|
||||
throw ParserException.createForUnsupportedContainerFeature("Invalid AC-4 DSI bitrate.");
|
||||
}
|
||||
dataBitArray.byteAlign();
|
||||
}
|
||||
|
||||
Ac4Presentation ac4Presentation = new Ac4Presentation();
|
||||
for (int presentationIdx = 0; presentationIdx < numberOfPresentations; presentationIdx++) {
|
||||
boolean isSingleSubstream = false;
|
||||
boolean isSingleSubstreamGroup = false;
|
||||
int presentationConfig;
|
||||
int presentationVersion;
|
||||
int presentationBytes = 0;
|
||||
int start = 0;
|
||||
|
||||
if (ac4DsiVersion == 0) {
|
||||
isSingleSubstream = dataBitArray.readBit(); // b_single_substream
|
||||
presentationConfig = dataBitArray.readBits(5); // presentation_config
|
||||
presentationVersion = dataBitArray.readBits(5); // presentation_version
|
||||
} else {
|
||||
presentationVersion = dataBitArray.readBits(8); // presentation_version
|
||||
presentationBytes = dataBitArray.readBits(8); // pres_bytes
|
||||
if (presentationBytes == 0xff) {
|
||||
presentationBytes += dataBitArray.readBits(16); // pres_bytes
|
||||
}
|
||||
if (presentationVersion > 2) {
|
||||
dataBitArray.skipBits(presentationBytes * 8);
|
||||
continue;
|
||||
}
|
||||
// record a marker, less the size of the presentation_config
|
||||
start = (dsiSize - dataBitArray.bitsLeft()) / 8;
|
||||
// ac4_presentation_v0_dsi(), ac4_presentation_v1_dsi() and ac4_presentation_v2_dsi()
|
||||
// all start with a presentation_config of 5 bits
|
||||
presentationConfig = dataBitArray.readBits(5); // presentation_config
|
||||
isSingleSubstreamGroup = (presentationConfig == 0x1f);
|
||||
}
|
||||
|
||||
boolean addEmdfSubstreams;
|
||||
if (!(isSingleSubstream || isSingleSubstreamGroup) && presentationConfig == 6) {
|
||||
addEmdfSubstreams = true;
|
||||
} else {
|
||||
ac4Presentation.level = dataBitArray.readBits(3); // mdcompat
|
||||
|
||||
if (dataBitArray.readBit()) { // b_presentation_group_index
|
||||
dataBitArray.skipBits(5); // group_index
|
||||
}
|
||||
|
||||
dataBitArray.skipBits(2); // dsi_frame_rate_multiply_info
|
||||
if (ac4DsiVersion == 1 && (presentationVersion == 1 || presentationVersion == 2)) {
|
||||
dataBitArray.skipBits(2); // dsi_frame_rate_fraction_info
|
||||
}
|
||||
dataBitArray.skipBits(5); // presentation_emdf_version
|
||||
dataBitArray.skipBits(10); // presentation_key_id
|
||||
|
||||
if (ac4DsiVersion == 1) {
|
||||
if (presentationVersion > 0) {
|
||||
ac4Presentation.isChannelCoded = dataBitArray.readBit(); // b_presentation_channel_coded
|
||||
}
|
||||
|
||||
if (ac4Presentation.isChannelCoded) {
|
||||
if (presentationVersion == 1 || presentationVersion == 2) {
|
||||
int channelMode = dataBitArray.readBits(5); // dsi_presentation_ch_mode
|
||||
if (channelMode >= 0 && channelMode <= 15) {
|
||||
ac4Presentation.channelMode = channelMode;
|
||||
}
|
||||
|
||||
if (channelMode >= 11 && channelMode <= 14) {
|
||||
ac4Presentation.hasBackChannels =
|
||||
dataBitArray.readBit(); // pres_b_4_back_channels_present
|
||||
ac4Presentation.topChannelPairs =
|
||||
dataBitArray.readBits(2); // pres_top_channel_pairs
|
||||
}
|
||||
}
|
||||
// presentation_channel_mask in ac4_presentation_v0_dsi()
|
||||
dataBitArray.skipBits(24); // presentation_channel_mask_v1
|
||||
}
|
||||
|
||||
if (presentationVersion == 1 || presentationVersion == 2) {
|
||||
if (dataBitArray.readBit()) { // b_presentation_core_differs
|
||||
if (dataBitArray.readBit()) { // b_presentation_core_channel_coded
|
||||
dataBitArray.skipBits(2); // dsi_presentation_channel_mode_core
|
||||
}
|
||||
}
|
||||
if (dataBitArray.readBit()) { // b_presentation_filter
|
||||
// Ignore b_enable_presentation field since this flag occurs in AC-4 elementary stream
|
||||
// TOC and AC-4 decoder doesn't handle it either.
|
||||
dataBitArray.skipBit(); // b_enable_presentation
|
||||
int filterBytes = dataBitArray.readBits(8); // n_filter_bytes
|
||||
for (int i = 0; i < filterBytes; i++) {
|
||||
dataBitArray.skipBits(8); // filter_data
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isSingleSubstream || isSingleSubstreamGroup) {
|
||||
if (presentationVersion == 0) {
|
||||
parseDsiSubstream(dataBitArray, ac4Presentation);
|
||||
} else {
|
||||
parseDsiSubstreamGroup(dataBitArray, ac4Presentation);
|
||||
}
|
||||
} else {
|
||||
// b_hsf_ext for ac4DsiVersion 0 OR b_multi_pid for ac4DsiVersion 1
|
||||
dataBitArray.skipBit();
|
||||
switch (presentationConfig) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
if (presentationVersion == 0) {
|
||||
for (int substreamId = 0; substreamId < 2; substreamId++) {
|
||||
parseDsiSubstream(dataBitArray, ac4Presentation);
|
||||
}
|
||||
} else {
|
||||
for (int substreamGroupId = 0; substreamGroupId < 2; substreamGroupId++) {
|
||||
parseDsiSubstreamGroup(dataBitArray, ac4Presentation);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
if (presentationVersion == 0) {
|
||||
for (int substreamId = 0; substreamId < 3; substreamId++) {
|
||||
parseDsiSubstream(dataBitArray, ac4Presentation);
|
||||
}
|
||||
} else {
|
||||
for (int substreamGroupId = 0; substreamGroupId < 3; substreamGroupId++) {
|
||||
parseDsiSubstreamGroup(dataBitArray, ac4Presentation);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (presentationVersion == 0) {
|
||||
parseDsiSubstream(dataBitArray, ac4Presentation);
|
||||
} else {
|
||||
int nSubstreamGroupsMinus2 = dataBitArray.readBits(3);
|
||||
for (int substreamGroupId = 0;
|
||||
substreamGroupId < nSubstreamGroupsMinus2 + 2;
|
||||
substreamGroupId++) {
|
||||
parseDsiSubstreamGroup(dataBitArray, ac4Presentation);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
int nSkipBytes = dataBitArray.readBits(7); // n_skip_bytes
|
||||
for (int j = 0; j < nSkipBytes; j++) {
|
||||
dataBitArray.skipBits(8);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
dataBitArray.skipBit(); // b_pre_virtualized
|
||||
addEmdfSubstreams = dataBitArray.readBit(); // b_add_emdf_substreams
|
||||
}
|
||||
if (addEmdfSubstreams) {
|
||||
int nAddEmdfSubstreams = dataBitArray.readBits(7); // n_add_emdf_substreams
|
||||
for (int j = 0; j < nAddEmdfSubstreams; j++) {
|
||||
dataBitArray.skipBits(5 + 10); // substream_emdf_version and substream_key_id
|
||||
}
|
||||
}
|
||||
|
||||
if (presentationVersion > 0) {
|
||||
if (dataBitArray.readBit()) { // b_presentation_bitrate_info
|
||||
if (!skipDsiBitrate(dataBitArray)) {
|
||||
throw ParserException.createForUnsupportedContainerFeature("Can't parse bitrate DSI.");
|
||||
}
|
||||
}
|
||||
|
||||
if (dataBitArray.readBit()) { // b_alternative
|
||||
dataBitArray.byteAlign();
|
||||
int nameLen = dataBitArray.readBits(16); // name_len
|
||||
dataBitArray.skipBytes(nameLen); // presentation_name
|
||||
|
||||
int nTargets = dataBitArray.readBits(5); // n_targets
|
||||
for (int i = 0; i < nTargets; i++) {
|
||||
dataBitArray.skipBits(3); // target_md_compat
|
||||
dataBitArray.skipBits(8); // target_device_category
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dataBitArray.byteAlign();
|
||||
|
||||
if (ac4DsiVersion == 1) {
|
||||
int end = (dsiSize - dataBitArray.bitsLeft()) / 8;
|
||||
int presentationBytesRead = end - start;
|
||||
if (presentationBytes < presentationBytesRead) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
"pres_bytes is smaller than presentation bytes read.");
|
||||
}
|
||||
int skipBytes = presentationBytes - presentationBytesRead;
|
||||
dataBitArray.skipBytes(skipBytes);
|
||||
}
|
||||
// We should know this or something is probably wrong with the bitstream (or we don't support
|
||||
// it)
|
||||
if (ac4Presentation.isChannelCoded && ac4Presentation.channelMode == CHANNEL_MODE_UNKNOWN) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
"Can't determine channel mode of presentation " + presentationIdx);
|
||||
}
|
||||
break; // Successfully parsed the first presentation with presentation version 0, 1 or 2.
|
||||
}
|
||||
|
||||
int channelCount;
|
||||
if (ac4Presentation.isChannelCoded) {
|
||||
channelCount =
|
||||
getAdjustedChannelCount(
|
||||
ac4Presentation.channelMode,
|
||||
ac4Presentation.hasBackChannels,
|
||||
ac4Presentation.topChannelPairs);
|
||||
} else {
|
||||
channelCount = ac4Presentation.numOfUmxObjects;
|
||||
// TODO: There is a bug in ETSI TS 103 190-2 V1.2.1 (2018-02), E.11.11
|
||||
// For AC-4 level 4 stream, the intention is to set 19 to n_umx_objects_minus1 but it is
|
||||
// equal to 15 based on current specification. Dolby has filed a bug report to ETSI.
|
||||
// The following sentence should be deleted after ETSI specification error is fixed.
|
||||
if (ac4Presentation.level == 4) {
|
||||
channelCount = channelCount == 16 ? 21 : channelCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (channelCount <= 0) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
"Can't determine channel count of presentation.");
|
||||
}
|
||||
|
||||
return new Format.Builder()
|
||||
.setId(trackId)
|
||||
.setSampleMimeType(MimeTypes.AUDIO_AC4)
|
||||
.setChannelCount(CHANNEL_COUNT_2)
|
||||
.setChannelCount(channelCount)
|
||||
.setSampleRate(sampleRate)
|
||||
.setDrmInitData(drmInitData)
|
||||
.setLanguage(language)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the AC-4 DSI substream according to TS 103 190-1 v1.2.1 section E.5 and TS 103 190-2
|
||||
* v1.1.1 section E.9. Modifies the reading position of {@code data} to be just after the AC-4 DSI
|
||||
* substream field.
|
||||
*
|
||||
* @param data The {@link ParsableBitArray} containing the AC-4 DSI, positioned at the start of
|
||||
* the substream field.
|
||||
* @param ac4Presentation A structure to store parsed AC-4 presentation information.
|
||||
* @throws ParserException If an unsupported container feature is encountered while parsing the
|
||||
* AC-4 DSI substream.
|
||||
*/
|
||||
private static void parseDsiSubstream(ParsableBitArray data, Ac4Presentation ac4Presentation)
|
||||
throws ParserException {
|
||||
int channelMode = data.readBits(5); // channel_mode
|
||||
data.skipBits(2); // dsi_sf_multiplier
|
||||
|
||||
if (data.readBit()) { // b_bitrate_indicator
|
||||
data.skipBits(5); // b_bitrate_indicator
|
||||
}
|
||||
if (channelMode >= 7 && channelMode <= 10) {
|
||||
data.skipBit(); // add_ch_base
|
||||
}
|
||||
|
||||
if (data.readBit()) { // b_content_type
|
||||
int contentClassifier = data.readBits(3); // content_classifier
|
||||
// For streams based on TS 103 190 part 1 the presentation level channel_mode doesn't exist
|
||||
// and so we use the channel_mode from either the CM or M&E substream (they are mutually
|
||||
// exclusive).
|
||||
if (ac4Presentation.channelMode == CHANNEL_MODE_UNKNOWN
|
||||
&& (channelMode >= 0 && channelMode <= 15)
|
||||
&& (contentClassifier == 0 || contentClassifier == 1)) {
|
||||
ac4Presentation.channelMode = channelMode;
|
||||
}
|
||||
|
||||
if (data.readBit()) { // b_language_indicator
|
||||
skipDsiLanguage(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the AC-4 DSI substream group information according to ETSI TS 103 190-2 v1.1.1 section
|
||||
* E.11. Modifies the reading position of {@code data} to be just after the AC-4 DSI substream
|
||||
* group field.
|
||||
*
|
||||
* @param data The {@link ParsableBitArray} containing the AC-4 DSI, positioned at the start of
|
||||
* the substream group field.
|
||||
* @param ac4Presentation A structure to store parsed AC-4 presentation information.
|
||||
* @throws ParserException If an unsupported container feature is encountered while parsing the
|
||||
* AC-4 DSI substream group.
|
||||
*/
|
||||
private static void parseDsiSubstreamGroup(ParsableBitArray data, Ac4Presentation ac4Presentation)
|
||||
throws ParserException {
|
||||
data.skipBits(2); // b_substreams_present(1), b_hsf_ext(1)
|
||||
boolean channelCoded = data.readBit(); // b_channel_coded
|
||||
int numberOfSubstreams = data.readBits(8); // n_substreams
|
||||
|
||||
for (int i = 0; i < numberOfSubstreams; i++) {
|
||||
data.skipBits(2); // dsi_sf_multiplier
|
||||
if (data.readBit()) { // b_substream_bitrate_indicator
|
||||
data.skipBits(5); // substream_bitrate_indicator
|
||||
}
|
||||
if (channelCoded) {
|
||||
data.skipBits(24); // dsi_substream_channel_mask
|
||||
} else {
|
||||
if (data.readBit()) { // b_ajoc
|
||||
if (!data.readBit()) { // b_static_dmx
|
||||
data.skipBits(4); // n_dmx_objects_minus1
|
||||
}
|
||||
ac4Presentation.numOfUmxObjects = data.readBits(6) + 1; // n_umx_objects_minus1
|
||||
}
|
||||
data.skipBits(4); // objects_assignment_mask
|
||||
}
|
||||
}
|
||||
|
||||
if (data.readBit()) { // b_content_type
|
||||
data.skipBits(3); // content_classifier
|
||||
|
||||
if (data.readBit()) { // b_language_indicator
|
||||
skipDsiLanguage(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips the language information fields in an AC-4 DSI bit stream according to TS 103 190-1
|
||||
* section 4.3.3.8.7. Modifies the reading position of {@code data} to be just after the language
|
||||
* fields.
|
||||
*
|
||||
* @param data The {@link ParsableBitArray} containing the AC-4 DSI, positioned at the start of
|
||||
* the language tag field.
|
||||
* @throws ParserException If the language tag length is invalid.
|
||||
*/
|
||||
private static void skipDsiLanguage(ParsableBitArray data) throws ParserException {
|
||||
int languageTagBytesNumber = data.readBits(6); // n_language_tag_bytes
|
||||
if (languageTagBytesNumber < 2 || languageTagBytesNumber > 42) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
String.format(
|
||||
"Invalid language tag bytes number: %d. Must be between 2 and 42.",
|
||||
languageTagBytesNumber));
|
||||
}
|
||||
// Can't use readBytes() since it is not byte-aligned here.
|
||||
data.skipBits(languageTagBytesNumber * C.BITS_PER_BYTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Skips the bitrate information fields in an AC-4 DSI bit stream. The reading position of {@code
|
||||
* data} will be modified to be just after the bitrate fields, if sufficient bits remain.
|
||||
*
|
||||
* @param data The {@link ParsableBitArray} containing the AC-4 DSI, positioned at the start of
|
||||
* the bitrate information.
|
||||
* @return {@code true} if the bitrate fields were successfully skipped or {@code false} if there
|
||||
* were insufficient bits remaining in {@code data}.
|
||||
*/
|
||||
private static boolean skipDsiBitrate(ParsableBitArray data) {
|
||||
int totalBitsToSkip = 2 + 32 + 32; // bit_rate_mode, bit_rate, bit_rate_precision
|
||||
if (data.bitsLeft() < totalBitsToSkip) {
|
||||
return false;
|
||||
}
|
||||
data.skipBits(totalBitsToSkip);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int getAdjustedChannelCount(
|
||||
@ChannelMode int channelMode, boolean hasBackChannels, int topChannelPairs) {
|
||||
int channelCount = getChannelCountFromChannelMode(channelMode);
|
||||
if (channelMode == CHANNEL_MODE_7_0_4
|
||||
|| channelMode == CHANNEL_MODE_7_1_4
|
||||
|| channelMode == CHANNEL_MODE_9_0_4
|
||||
|| channelMode == CHANNEL_MODE_9_1_4) {
|
||||
|
||||
if (!hasBackChannels) {
|
||||
channelCount -= 2;
|
||||
}
|
||||
|
||||
switch (topChannelPairs) {
|
||||
case 0:
|
||||
channelCount -= 4;
|
||||
break;
|
||||
case 1:
|
||||
channelCount -= 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return channelCount;
|
||||
}
|
||||
|
||||
private static int getChannelCountFromChannelMode(@ChannelMode int channelMode) {
|
||||
switch (channelMode) {
|
||||
case CHANNEL_MODE_MONO:
|
||||
return 1;
|
||||
case CHANNEL_MODE_STEREO:
|
||||
return 2;
|
||||
case CHANNEL_MODE_3_0:
|
||||
return 3;
|
||||
case CHANNEL_MODE_5_0:
|
||||
return 5;
|
||||
case CHANNEL_MODE_5_1:
|
||||
return 6;
|
||||
case CHANNEL_MODE_7_0_34:
|
||||
case CHANNEL_MODE_7_0_52:
|
||||
case CHANNEL_MODE_7_0_322:
|
||||
return 7;
|
||||
case CHANNEL_MODE_7_1_34:
|
||||
case CHANNEL_MODE_7_1_52:
|
||||
case CHANNEL_MODE_7_1_322:
|
||||
return 8;
|
||||
case CHANNEL_MODE_7_0_4:
|
||||
return 11;
|
||||
case CHANNEL_MODE_7_1_4:
|
||||
return 12;
|
||||
case CHANNEL_MODE_9_0_4:
|
||||
return 13;
|
||||
case CHANNEL_MODE_9_1_4:
|
||||
return 14;
|
||||
case CHANNEL_MODE_22_2:
|
||||
return 24;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns AC-4 format information given {@code data} containing a syncframe. The reading position
|
||||
* of {@code data} will be modified.
|
||||
@ -255,5 +748,24 @@ public final class Ac4Util {
|
||||
return value;
|
||||
}
|
||||
|
||||
/** Holds AC-4 presentation information. */
|
||||
private static final class Ac4Presentation {
|
||||
public boolean isChannelCoded;
|
||||
public @ChannelMode int channelMode;
|
||||
public int numOfUmxObjects;
|
||||
public boolean hasBackChannels;
|
||||
public int topChannelPairs;
|
||||
public int level;
|
||||
|
||||
private Ac4Presentation() {
|
||||
isChannelCoded = true;
|
||||
channelMode = CHANNEL_MODE_UNKNOWN;
|
||||
numOfUmxObjects = -1;
|
||||
hasBackChannels = true;
|
||||
topChannelPairs = 2;
|
||||
level = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private Ac4Util() {}
|
||||
}
|
||||
|
@ -107,6 +107,11 @@ public final class Mp4ExtractorParameterizedTest {
|
||||
assertExtractorBehavior("media/mp4/sample_ac4.mp4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mp4SampleWithAc4Level4Track() throws Exception {
|
||||
assertExtractorBehavior("media/mp4/sample_ac4_level4.mp4");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mp4SampleWithEac3Track() throws Exception {
|
||||
assertExtractorBehavior("media/mp4/sample_eac3.mp4");
|
||||
|
@ -0,0 +1,101 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 162700
|
||||
sample count = 20
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 8135, hash B524F88E
|
||||
sample 1:
|
||||
time = 42666
|
||||
flags = 0
|
||||
data = length 8135, hash FB80C2FB
|
||||
sample 2:
|
||||
time = 85333
|
||||
flags = 0
|
||||
data = length 8135, hash 907C0C31
|
||||
sample 3:
|
||||
time = 128000
|
||||
flags = 0
|
||||
data = length 8135, hash FDFBD32B
|
||||
sample 4:
|
||||
time = 170666
|
||||
flags = 0
|
||||
data = length 8135, hash 6CAF0549
|
||||
sample 5:
|
||||
time = 213333
|
||||
flags = 0
|
||||
data = length 8135, hash F5CA1C9A
|
||||
sample 6:
|
||||
time = 256000
|
||||
flags = 0
|
||||
data = length 8135, hash B1B5160D
|
||||
sample 7:
|
||||
time = 298666
|
||||
flags = 0
|
||||
data = length 8135, hash 9E923B3F
|
||||
sample 8:
|
||||
time = 341333
|
||||
flags = 0
|
||||
data = length 8135, hash B1C0BB1F
|
||||
sample 9:
|
||||
time = 384000
|
||||
flags = 0
|
||||
data = length 8135, hash 56F65A03
|
||||
sample 10:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 11:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 12:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 13:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 14:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 15:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 16:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 17:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 18:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 19:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,101 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 162700
|
||||
sample count = 20
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 8135, hash B524F88E
|
||||
sample 1:
|
||||
time = 42666
|
||||
flags = 0
|
||||
data = length 8135, hash FB80C2FB
|
||||
sample 2:
|
||||
time = 85333
|
||||
flags = 0
|
||||
data = length 8135, hash 907C0C31
|
||||
sample 3:
|
||||
time = 128000
|
||||
flags = 0
|
||||
data = length 8135, hash FDFBD32B
|
||||
sample 4:
|
||||
time = 170666
|
||||
flags = 0
|
||||
data = length 8135, hash 6CAF0549
|
||||
sample 5:
|
||||
time = 213333
|
||||
flags = 0
|
||||
data = length 8135, hash F5CA1C9A
|
||||
sample 6:
|
||||
time = 256000
|
||||
flags = 0
|
||||
data = length 8135, hash B1B5160D
|
||||
sample 7:
|
||||
time = 298666
|
||||
flags = 0
|
||||
data = length 8135, hash 9E923B3F
|
||||
sample 8:
|
||||
time = 341333
|
||||
flags = 0
|
||||
data = length 8135, hash B1C0BB1F
|
||||
sample 9:
|
||||
time = 384000
|
||||
flags = 0
|
||||
data = length 8135, hash 56F65A03
|
||||
sample 10:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 11:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 12:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 13:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 14:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 15:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 16:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 17:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 18:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 19:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,61 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 81350
|
||||
sample count = 10
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 1:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 2:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 3:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 4:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 5:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 6:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 7:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 8:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 9:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,61 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 81350
|
||||
sample count = 10
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 1:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 2:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 3:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 4:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 5:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 6:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 7:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 8:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 9:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,101 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 162700
|
||||
sample count = 20
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 8135, hash B524F88E
|
||||
sample 1:
|
||||
time = 42666
|
||||
flags = 0
|
||||
data = length 8135, hash FB80C2FB
|
||||
sample 2:
|
||||
time = 85333
|
||||
flags = 0
|
||||
data = length 8135, hash 907C0C31
|
||||
sample 3:
|
||||
time = 128000
|
||||
flags = 0
|
||||
data = length 8135, hash FDFBD32B
|
||||
sample 4:
|
||||
time = 170666
|
||||
flags = 0
|
||||
data = length 8135, hash 6CAF0549
|
||||
sample 5:
|
||||
time = 213333
|
||||
flags = 0
|
||||
data = length 8135, hash F5CA1C9A
|
||||
sample 6:
|
||||
time = 256000
|
||||
flags = 0
|
||||
data = length 8135, hash B1B5160D
|
||||
sample 7:
|
||||
time = 298666
|
||||
flags = 0
|
||||
data = length 8135, hash 9E923B3F
|
||||
sample 8:
|
||||
time = 341333
|
||||
flags = 0
|
||||
data = length 8135, hash B1C0BB1F
|
||||
sample 9:
|
||||
time = 384000
|
||||
flags = 0
|
||||
data = length 8135, hash 56F65A03
|
||||
sample 10:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 11:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 12:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 13:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 14:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 15:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 16:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 17:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 18:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 19:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,101 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 162700
|
||||
sample count = 20
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 8135, hash B524F88E
|
||||
sample 1:
|
||||
time = 42666
|
||||
flags = 0
|
||||
data = length 8135, hash FB80C2FB
|
||||
sample 2:
|
||||
time = 85333
|
||||
flags = 0
|
||||
data = length 8135, hash 907C0C31
|
||||
sample 3:
|
||||
time = 128000
|
||||
flags = 0
|
||||
data = length 8135, hash FDFBD32B
|
||||
sample 4:
|
||||
time = 170666
|
||||
flags = 0
|
||||
data = length 8135, hash 6CAF0549
|
||||
sample 5:
|
||||
time = 213333
|
||||
flags = 0
|
||||
data = length 8135, hash F5CA1C9A
|
||||
sample 6:
|
||||
time = 256000
|
||||
flags = 0
|
||||
data = length 8135, hash B1B5160D
|
||||
sample 7:
|
||||
time = 298666
|
||||
flags = 0
|
||||
data = length 8135, hash 9E923B3F
|
||||
sample 8:
|
||||
time = 341333
|
||||
flags = 0
|
||||
data = length 8135, hash B1C0BB1F
|
||||
sample 9:
|
||||
time = 384000
|
||||
flags = 0
|
||||
data = length 8135, hash 56F65A03
|
||||
sample 10:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 11:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 12:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 13:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 14:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 15:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 16:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 17:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 18:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 19:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,61 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 81350
|
||||
sample count = 10
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 1:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 2:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 3:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 4:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 5:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 6:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 7:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 8:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 9:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,61 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 81350
|
||||
sample count = 10
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 1:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 2:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 3:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 4:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 5:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 6:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 7:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 8:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 9:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,101 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 162700
|
||||
sample count = 20
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 8135, hash B524F88E
|
||||
sample 1:
|
||||
time = 42666
|
||||
flags = 0
|
||||
data = length 8135, hash FB80C2FB
|
||||
sample 2:
|
||||
time = 85333
|
||||
flags = 0
|
||||
data = length 8135, hash 907C0C31
|
||||
sample 3:
|
||||
time = 128000
|
||||
flags = 0
|
||||
data = length 8135, hash FDFBD32B
|
||||
sample 4:
|
||||
time = 170666
|
||||
flags = 0
|
||||
data = length 8135, hash 6CAF0549
|
||||
sample 5:
|
||||
time = 213333
|
||||
flags = 0
|
||||
data = length 8135, hash F5CA1C9A
|
||||
sample 6:
|
||||
time = 256000
|
||||
flags = 0
|
||||
data = length 8135, hash B1B5160D
|
||||
sample 7:
|
||||
time = 298666
|
||||
flags = 0
|
||||
data = length 8135, hash 9E923B3F
|
||||
sample 8:
|
||||
time = 341333
|
||||
flags = 0
|
||||
data = length 8135, hash B1C0BB1F
|
||||
sample 9:
|
||||
time = 384000
|
||||
flags = 0
|
||||
data = length 8135, hash 56F65A03
|
||||
sample 10:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 11:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 12:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 13:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 14:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 15:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 16:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 17:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 18:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 19:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
@ -0,0 +1,101 @@
|
||||
seekMap:
|
||||
isSeekable = true
|
||||
duration = 853333
|
||||
getPosition(0) = [[timeUs=0, position=665]]
|
||||
getPosition(1) = [[timeUs=1, position=665]]
|
||||
getPosition(426666) = [[timeUs=426666, position=81945]]
|
||||
getPosition(853333) = [[timeUs=853333, position=81945]]
|
||||
numberOfTracks = 1
|
||||
track 0:
|
||||
total output bytes = 162700
|
||||
sample count = 20
|
||||
track duration = 853333
|
||||
format 0:
|
||||
id = 1
|
||||
sampleMimeType = audio/ac4
|
||||
maxInputSize = 8158
|
||||
channelCount = 21
|
||||
sampleRate = 48000
|
||||
language = und
|
||||
metadata = entries=[Mp4Timestamp: creation time=3785281997, modification time=3785281997, timescale=600]
|
||||
sample 0:
|
||||
time = 0
|
||||
flags = 1
|
||||
data = length 8135, hash B524F88E
|
||||
sample 1:
|
||||
time = 42666
|
||||
flags = 0
|
||||
data = length 8135, hash FB80C2FB
|
||||
sample 2:
|
||||
time = 85333
|
||||
flags = 0
|
||||
data = length 8135, hash 907C0C31
|
||||
sample 3:
|
||||
time = 128000
|
||||
flags = 0
|
||||
data = length 8135, hash FDFBD32B
|
||||
sample 4:
|
||||
time = 170666
|
||||
flags = 0
|
||||
data = length 8135, hash 6CAF0549
|
||||
sample 5:
|
||||
time = 213333
|
||||
flags = 0
|
||||
data = length 8135, hash F5CA1C9A
|
||||
sample 6:
|
||||
time = 256000
|
||||
flags = 0
|
||||
data = length 8135, hash B1B5160D
|
||||
sample 7:
|
||||
time = 298666
|
||||
flags = 0
|
||||
data = length 8135, hash 9E923B3F
|
||||
sample 8:
|
||||
time = 341333
|
||||
flags = 0
|
||||
data = length 8135, hash B1C0BB1F
|
||||
sample 9:
|
||||
time = 384000
|
||||
flags = 0
|
||||
data = length 8135, hash 56F65A03
|
||||
sample 10:
|
||||
time = 426666
|
||||
flags = 1
|
||||
data = length 8135, hash D07FA9A1
|
||||
sample 11:
|
||||
time = 469333
|
||||
flags = 0
|
||||
data = length 8135, hash EF26FDDE
|
||||
sample 12:
|
||||
time = 512000
|
||||
flags = 0
|
||||
data = length 8135, hash 8946EEEB
|
||||
sample 13:
|
||||
time = 554666
|
||||
flags = 0
|
||||
data = length 8135, hash AC2E4C99
|
||||
sample 14:
|
||||
time = 597333
|
||||
flags = 0
|
||||
data = length 8135, hash B63A1D8
|
||||
sample 15:
|
||||
time = 640000
|
||||
flags = 0
|
||||
data = length 8135, hash 23119F0F
|
||||
sample 16:
|
||||
time = 682666
|
||||
flags = 0
|
||||
data = length 8135, hash 507972CA
|
||||
sample 17:
|
||||
time = 725333
|
||||
flags = 0
|
||||
data = length 8135, hash E574BC00
|
||||
sample 18:
|
||||
time = 768000
|
||||
flags = 0
|
||||
data = length 8135, hash 52F482FA
|
||||
sample 19:
|
||||
time = 810666
|
||||
flags = 536870912
|
||||
data = length 8135, hash C1A7B518
|
||||
tracksEnded = true
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user