mirror of
https://github.com/androidx/media.git
synced 2025-05-11 01:31:40 +08:00
parent
b6f15a17e0
commit
d7697176ed
@ -450,30 +450,41 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||||||
private static String buildTrackName(MediaFormat format) {
|
private static String buildTrackName(MediaFormat format) {
|
||||||
if (format.adaptive) {
|
if (format.adaptive) {
|
||||||
return "auto";
|
return "auto";
|
||||||
} else if (MimeTypes.isVideo(format.mimeType)) {
|
|
||||||
return buildResolutionString(format) + buildBitrateString(format);
|
|
||||||
} else if (MimeTypes.isAudio(format.mimeType)) {
|
|
||||||
return buildAudioPropertyString(format) + buildBitrateString(format);
|
|
||||||
} else if (!TextUtils.isEmpty(format.language)) {
|
|
||||||
return format.language + buildBitrateString(format);
|
|
||||||
} else {
|
|
||||||
return "unknown" + buildBitrateString(format);
|
|
||||||
}
|
}
|
||||||
|
String trackName;
|
||||||
|
if (MimeTypes.isVideo(format.mimeType)) {
|
||||||
|
trackName = joinWithSeparator(buildResolutionString(format), buildBitrateString(format));
|
||||||
|
} else if (MimeTypes.isAudio(format.mimeType)) {
|
||||||
|
trackName = joinWithSeparator(joinWithSeparator(buildLanguageString(format),
|
||||||
|
buildAudioPropertyString(format)), buildBitrateString(format));
|
||||||
|
} else {
|
||||||
|
trackName = joinWithSeparator(buildLanguageString(format), buildBitrateString(format));
|
||||||
|
}
|
||||||
|
return trackName.length() == 0 ? "unknown" : trackName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildResolutionString(MediaFormat format) {
|
private static String buildResolutionString(MediaFormat format) {
|
||||||
return format.width == MediaFormat.NO_VALUE || format.height == MediaFormat.NO_VALUE
|
return format.width == MediaFormat.NO_VALUE || format.height == MediaFormat.NO_VALUE
|
||||||
? "video" : format.width + "x" + format.height;
|
? "" : format.width + "x" + format.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildAudioPropertyString(MediaFormat format) {
|
private static String buildAudioPropertyString(MediaFormat format) {
|
||||||
return format.channelCount == MediaFormat.NO_VALUE || format.sampleRate == MediaFormat.NO_VALUE
|
return format.channelCount == MediaFormat.NO_VALUE || format.sampleRate == MediaFormat.NO_VALUE
|
||||||
? "audio" : format.channelCount + "ch, " + format.sampleRate + "Hz";
|
? "" : format.channelCount + "ch, " + format.sampleRate + "Hz";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String buildLanguageString(MediaFormat format) {
|
||||||
|
return TextUtils.isEmpty(format.language) || "und".equals(format.language) ? ""
|
||||||
|
: format.language;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String buildBitrateString(MediaFormat format) {
|
private static String buildBitrateString(MediaFormat format) {
|
||||||
return format.bitrate == MediaFormat.NO_VALUE ? ""
|
return format.bitrate == MediaFormat.NO_VALUE ? ""
|
||||||
: String.format(Locale.US, " (%.2fMbit)", format.bitrate / 1000000f);
|
: String.format(Locale.US, "%.2fMbit", format.bitrate / 1000000f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String joinWithSeparator(String first, String second) {
|
||||||
|
return first.length() == 0 ? second : (second.length() == 0 ? first : first + ", " + second);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean onTrackItemClick(MenuItem item, int type) {
|
private boolean onTrackItemClick(MenuItem item, int type) {
|
||||||
|
@ -49,13 +49,13 @@ public final class MediaFormatTest extends TestCase {
|
|||||||
testConversionToFrameworkFormatV16(MediaFormat.createVideoFormat(
|
testConversionToFrameworkFormatV16(MediaFormat.createVideoFormat(
|
||||||
"video/xyz", 5000, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, 1280, 720, null));
|
"video/xyz", 5000, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, 1280, 720, null));
|
||||||
testConversionToFrameworkFormatV16(MediaFormat.createAudioFormat(
|
testConversionToFrameworkFormatV16(MediaFormat.createAudioFormat(
|
||||||
"audio/xyz", 500, 128, 1000L, 5, 44100, initData));
|
"audio/xyz", 500, 128, 1000L, 5, 44100, initData, null));
|
||||||
testConversionToFrameworkFormatV16(MediaFormat.createAudioFormat(
|
testConversionToFrameworkFormatV16(MediaFormat.createAudioFormat(
|
||||||
"audio/xyz", 500, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, 5, 44100, null));
|
"audio/xyz", 500, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, 5, 44100, null, null));
|
||||||
testConversionToFrameworkFormatV16(
|
testConversionToFrameworkFormatV16(
|
||||||
MediaFormat.createTextFormat("text/xyz", MediaFormat.NO_VALUE, "eng", 1000L));
|
MediaFormat.createTextFormat("text/xyz", MediaFormat.NO_VALUE, 1000L, "eng"));
|
||||||
testConversionToFrameworkFormatV16(
|
testConversionToFrameworkFormatV16(
|
||||||
MediaFormat.createTextFormat("text/xyz", MediaFormat.NO_VALUE, null, C.UNKNOWN_TIME_US));
|
MediaFormat.createTextFormat("text/xyz", MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
|
@ -149,19 +149,20 @@ public final class MediaFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createAudioFormat(String mimeType, int bitrate, int maxInputSize,
|
public static MediaFormat createAudioFormat(String mimeType, int bitrate, int maxInputSize,
|
||||||
long durationUs, int channelCount, int sampleRate, List<byte[]> initializationData) {
|
long durationUs, int channelCount, int sampleRate, List<byte[]> initializationData,
|
||||||
|
String language) {
|
||||||
return new MediaFormat(mimeType, bitrate, maxInputSize, durationUs, NO_VALUE, NO_VALUE,
|
return new MediaFormat(mimeType, bitrate, maxInputSize, durationUs, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, channelCount, sampleRate, null, OFFSET_SAMPLE_RELATIVE,
|
NO_VALUE, NO_VALUE, channelCount, sampleRate, language, OFFSET_SAMPLE_RELATIVE,
|
||||||
initializationData, false, NO_VALUE, NO_VALUE);
|
initializationData, false, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createTextFormat(String mimeType, int bitrate, String language,
|
public static MediaFormat createTextFormat(String mimeType, int bitrate, long durationUs,
|
||||||
long durationUs) {
|
String language) {
|
||||||
return createTextFormat(mimeType, bitrate, language, durationUs, OFFSET_SAMPLE_RELATIVE);
|
return createTextFormat(mimeType, bitrate, durationUs, language, OFFSET_SAMPLE_RELATIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createTextFormat(String mimeType, int bitrate, String language,
|
public static MediaFormat createTextFormat(String mimeType, int bitrate, long durationUs,
|
||||||
long durationUs, long subsampleOffsetUs) {
|
String language, long subsampleOffsetUs) {
|
||||||
return new MediaFormat(mimeType, bitrate, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new MediaFormat(mimeType, bitrate, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, language, subsampleOffsetUs, null, false, NO_VALUE, NO_VALUE);
|
NO_VALUE, NO_VALUE, NO_VALUE, language, subsampleOffsetUs, null, false, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
@ -610,10 +610,10 @@ public class DashChunkSource implements ChunkSource, Output {
|
|||||||
durationUs, format.width, format.height, null);
|
durationUs, format.width, format.height, null);
|
||||||
case AdaptationSet.TYPE_AUDIO:
|
case AdaptationSet.TYPE_AUDIO:
|
||||||
return MediaFormat.createAudioFormat(mediaMimeType, format.bitrate, MediaFormat.NO_VALUE,
|
return MediaFormat.createAudioFormat(mediaMimeType, format.bitrate, MediaFormat.NO_VALUE,
|
||||||
durationUs, format.audioChannels, format.audioSamplingRate, null);
|
durationUs, format.audioChannels, format.audioSamplingRate, null, format.language);
|
||||||
case AdaptationSet.TYPE_TEXT:
|
case AdaptationSet.TYPE_TEXT:
|
||||||
return MediaFormat.createTextFormat(mediaMimeType, format.bitrate, format.language,
|
return MediaFormat.createTextFormat(mediaMimeType, format.bitrate, durationUs,
|
||||||
durationUs);
|
format.language);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
extractorOutput.seekMap(seeker);
|
extractorOutput.seekMap(seeker);
|
||||||
trackOutput.format(MediaFormat.createAudioFormat(synchronizedHeader.mimeType,
|
trackOutput.format(MediaFormat.createAudioFormat(synchronizedHeader.mimeType,
|
||||||
MediaFormat.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, seeker.getDurationUs(),
|
MediaFormat.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, seeker.getDurationUs(),
|
||||||
synchronizedHeader.channels, synchronizedHeader.sampleRate, null));
|
synchronizedHeader.channels, synchronizedHeader.sampleRate, null, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
return headerPosition;
|
return headerPosition;
|
||||||
|
@ -376,16 +376,16 @@ import java.util.List;
|
|||||||
|| childAtomType == Atom.TYPE_dtsc || childAtomType == Atom.TYPE_dtse
|
|| childAtomType == Atom.TYPE_dtsc || childAtomType == Atom.TYPE_dtse
|
||||||
|| childAtomType == Atom.TYPE_dtsh || childAtomType == Atom.TYPE_dtsl) {
|
|| childAtomType == Atom.TYPE_dtsh || childAtomType == Atom.TYPE_dtsl) {
|
||||||
parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, durationUs,
|
parseAudioSampleEntry(stsd, childAtomType, childStartPosition, childAtomSize, durationUs,
|
||||||
out, i);
|
language, out, i);
|
||||||
} else if (childAtomType == Atom.TYPE_TTML) {
|
} else if (childAtomType == Atom.TYPE_TTML) {
|
||||||
out.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TTML,
|
out.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TTML,
|
||||||
MediaFormat.NO_VALUE, language, durationUs);
|
MediaFormat.NO_VALUE, durationUs, language);
|
||||||
} else if (childAtomType == Atom.TYPE_tx3g) {
|
} else if (childAtomType == Atom.TYPE_tx3g) {
|
||||||
out.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TX3G,
|
out.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TX3G,
|
||||||
MediaFormat.NO_VALUE, language, durationUs);
|
MediaFormat.NO_VALUE, durationUs, language);
|
||||||
} else if (childAtomType == Atom.TYPE_stpp) {
|
} else if (childAtomType == Atom.TYPE_stpp) {
|
||||||
out.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TTML,
|
out.mediaFormat = MediaFormat.createTextFormat(MimeTypes.APPLICATION_TTML,
|
||||||
MediaFormat.NO_VALUE, language, durationUs, 0 /* subsample timing is absolute */);
|
MediaFormat.NO_VALUE, durationUs, language, 0 /* subsample timing is absolute */);
|
||||||
}
|
}
|
||||||
stsd.setPosition(childStartPosition + childAtomSize);
|
stsd.setPosition(childStartPosition + childAtomSize);
|
||||||
}
|
}
|
||||||
@ -585,7 +585,7 @@ import java.util.List;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType, int position,
|
private static void parseAudioSampleEntry(ParsableByteArray parent, int atomType, int position,
|
||||||
int size, long durationUs, StsdData out, int entryIndex) {
|
int size, long durationUs, String language, StsdData out, int entryIndex) {
|
||||||
parent.setPosition(position + Atom.HEADER_SIZE);
|
parent.setPosition(position + Atom.HEADER_SIZE);
|
||||||
parent.skipBytes(16);
|
parent.skipBytes(16);
|
||||||
int channelCount = parent.readUnsignedShort();
|
int channelCount = parent.readUnsignedShort();
|
||||||
@ -635,17 +635,17 @@ import java.util.List;
|
|||||||
// TODO: Choose the right AC-3 track based on the contents of dac3/dec3.
|
// TODO: Choose the right AC-3 track based on the contents of dac3/dec3.
|
||||||
// TODO: Add support for encryption (by setting out.trackEncryptionBoxes).
|
// TODO: Add support for encryption (by setting out.trackEncryptionBoxes).
|
||||||
parent.setPosition(Atom.HEADER_SIZE + childStartPosition);
|
parent.setPosition(Atom.HEADER_SIZE + childStartPosition);
|
||||||
out.mediaFormat = Ac3Util.parseAnnexFAc3Format(parent, durationUs);
|
out.mediaFormat = Ac3Util.parseAnnexFAc3Format(parent, durationUs, language);
|
||||||
return;
|
return;
|
||||||
} else if (atomType == Atom.TYPE_ec_3 && childAtomType == Atom.TYPE_dec3) {
|
} else if (atomType == Atom.TYPE_ec_3 && childAtomType == Atom.TYPE_dec3) {
|
||||||
parent.setPosition(Atom.HEADER_SIZE + childStartPosition);
|
parent.setPosition(Atom.HEADER_SIZE + childStartPosition);
|
||||||
out.mediaFormat = Ac3Util.parseAnnexFEAc3Format(parent, durationUs);
|
out.mediaFormat = Ac3Util.parseAnnexFEAc3Format(parent, durationUs, language);
|
||||||
return;
|
return;
|
||||||
} else if ((atomType == Atom.TYPE_dtsc || atomType == Atom.TYPE_dtse
|
} else if ((atomType == Atom.TYPE_dtsc || atomType == Atom.TYPE_dtse
|
||||||
|| atomType == Atom.TYPE_dtsh || atomType == Atom.TYPE_dtsl)
|
|| atomType == Atom.TYPE_dtsh || atomType == Atom.TYPE_dtsl)
|
||||||
&& childAtomType == Atom.TYPE_ddts) {
|
&& childAtomType == Atom.TYPE_ddts) {
|
||||||
out.mediaFormat = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE,
|
out.mediaFormat = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null);
|
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
childPosition += childAtomSize;
|
childPosition += childAtomSize;
|
||||||
@ -658,7 +658,8 @@ import java.util.List;
|
|||||||
|
|
||||||
out.mediaFormat = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE, sampleSize,
|
out.mediaFormat = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE, sampleSize,
|
||||||
durationUs, channelCount, sampleRate,
|
durationUs, channelCount, sampleRate,
|
||||||
initializationData == null ? null : Collections.singletonList(initializationData));
|
initializationData == null ? null : Collections.singletonList(initializationData),
|
||||||
|
language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns codec-specific initialization data contained in an esds box. */
|
/** Returns codec-specific initialization data contained in an esds box. */
|
||||||
|
@ -155,7 +155,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
|
|||||||
sampleSize = Ac3Util.parseFrameSize(headerScratchBits);
|
sampleSize = Ac3Util.parseFrameSize(headerScratchBits);
|
||||||
if (mediaFormat == null) {
|
if (mediaFormat == null) {
|
||||||
headerScratchBits.setPosition(0);
|
headerScratchBits.setPosition(0);
|
||||||
mediaFormat = Ac3Util.parseFrameAc3Format(headerScratchBits, C.UNKNOWN_TIME_US);
|
mediaFormat = Ac3Util.parseFrameAc3Format(headerScratchBits, C.UNKNOWN_TIME_US, null);
|
||||||
output.format(mediaFormat);
|
output.format(mediaFormat);
|
||||||
bitrate = Ac3Util.getBitrate(sampleSize, mediaFormat.sampleRate);
|
bitrate = Ac3Util.getBitrate(sampleSize, mediaFormat.sampleRate);
|
||||||
}
|
}
|
||||||
|
@ -172,7 +172,7 @@ import java.util.Collections;
|
|||||||
|
|
||||||
MediaFormat mediaFormat = MediaFormat.createAudioFormat(MimeTypes.AUDIO_AAC,
|
MediaFormat mediaFormat = MediaFormat.createAudioFormat(MimeTypes.AUDIO_AAC,
|
||||||
MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, audioParams.second,
|
MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, audioParams.second,
|
||||||
audioParams.first, Collections.singletonList(audioSpecificConfig));
|
audioParams.first, Collections.singletonList(audioSpecificConfig), null);
|
||||||
frameDurationUs = (C.MICROS_PER_SECOND * 1024L) / mediaFormat.sampleRate;
|
frameDurationUs = (C.MICROS_PER_SECOND * 1024L) / mediaFormat.sampleRate;
|
||||||
output.format(mediaFormat);
|
output.format(mediaFormat);
|
||||||
hasOutputFormat = true;
|
hasOutputFormat = true;
|
||||||
|
@ -162,7 +162,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
|
|||||||
frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
|
frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
|
||||||
MediaFormat mediaFormat = MediaFormat.createAudioFormat(header.mimeType,
|
MediaFormat mediaFormat = MediaFormat.createAudioFormat(header.mimeType,
|
||||||
MediaFormat.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, C.UNKNOWN_TIME_US,
|
MediaFormat.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, C.UNKNOWN_TIME_US,
|
||||||
header.channels, header.sampleRate, null);
|
header.channels, header.sampleRate, null, null);
|
||||||
output.format(mediaFormat);
|
output.format(mediaFormat);
|
||||||
hasOutputFormat = true;
|
hasOutputFormat = true;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
|
|||||||
public SeiReader(TrackOutput output) {
|
public SeiReader(TrackOutput output) {
|
||||||
super(output);
|
super(output);
|
||||||
output.format(MediaFormat.createTextFormat(MimeTypes.APPLICATION_EIA608, MediaFormat.NO_VALUE,
|
output.format(MediaFormat.createTextFormat(MimeTypes.APPLICATION_EIA608, MediaFormat.NO_VALUE,
|
||||||
null, C.UNKNOWN_TIME_US));
|
C.UNKNOWN_TIME_US, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1210,12 +1210,12 @@ public final class WebmExtractor implements Extractor {
|
|||||||
MediaFormat format;
|
MediaFormat format;
|
||||||
if (MimeTypes.isAudio(mimeType)) {
|
if (MimeTypes.isAudio(mimeType)) {
|
||||||
format = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE, maxInputSize,
|
format = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE, maxInputSize,
|
||||||
durationUs, channelCount, sampleRate, initializationData);
|
durationUs, channelCount, sampleRate, initializationData, language);
|
||||||
} else if (MimeTypes.isVideo(mimeType)) {
|
} else if (MimeTypes.isVideo(mimeType)) {
|
||||||
format = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE, maxInputSize,
|
format = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE, maxInputSize,
|
||||||
durationUs, width, height, initializationData);
|
durationUs, width, height, initializationData);
|
||||||
} else if (MimeTypes.APPLICATION_SUBRIP.equals(mimeType)) {
|
} else if (MimeTypes.APPLICATION_SUBRIP.equals(mimeType)) {
|
||||||
format = MediaFormat.createTextFormat(mimeType, MediaFormat.NO_VALUE, language, durationUs);
|
format = MediaFormat.createTextFormat(mimeType, MediaFormat.NO_VALUE, durationUs, language);
|
||||||
} else {
|
} else {
|
||||||
throw new ParserException("Unexpected MIME type.");
|
throw new ParserException("Unexpected MIME type.");
|
||||||
}
|
}
|
||||||
|
@ -411,12 +411,13 @@ public class SmoothStreamingChunkSource implements ChunkSource,
|
|||||||
format.audioSamplingRate, format.audioChannels));
|
format.audioSamplingRate, format.audioChannels));
|
||||||
}
|
}
|
||||||
mediaFormat = MediaFormat.createAudioFormat(format.mimeType, format.bitrate,
|
mediaFormat = MediaFormat.createAudioFormat(format.mimeType, format.bitrate,
|
||||||
MediaFormat.NO_VALUE, durationUs, format.audioChannels, format.audioSamplingRate, csd);
|
MediaFormat.NO_VALUE, durationUs, format.audioChannels, format.audioSamplingRate, csd,
|
||||||
|
format.language);
|
||||||
mp4TrackType = Track.TYPE_soun;
|
mp4TrackType = Track.TYPE_soun;
|
||||||
break;
|
break;
|
||||||
case StreamElement.TYPE_TEXT:
|
case StreamElement.TYPE_TEXT:
|
||||||
mediaFormat = MediaFormat.createTextFormat(format.mimeType, format.bitrate, format.language,
|
mediaFormat = MediaFormat.createTextFormat(format.mimeType, format.bitrate, durationUs,
|
||||||
durationUs);
|
format.language);
|
||||||
mp4TrackType = Track.TYPE_text;
|
mp4TrackType = Track.TYPE_text;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -39,9 +39,11 @@ public final class Ac3Util {
|
|||||||
*
|
*
|
||||||
* @param data The AC3SpecificBox.
|
* @param data The AC3SpecificBox.
|
||||||
* @param durationUs The duration to set on the format, in microseconds.
|
* @param durationUs The duration to set on the format, in microseconds.
|
||||||
* @return The FAc3 format parsed from data in the header.
|
* @param language The language to set on the format.
|
||||||
|
* @return The AC-3 format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static MediaFormat parseAnnexFAc3Format(ParsableByteArray data, long durationUs) {
|
public static MediaFormat parseAnnexFAc3Format(ParsableByteArray data, long durationUs,
|
||||||
|
String language) {
|
||||||
// fscod (sample rate code)
|
// fscod (sample rate code)
|
||||||
int fscod = (data.readUnsignedByte() & 0xC0) >> 6;
|
int fscod = (data.readUnsignedByte() & 0xC0) >> 6;
|
||||||
int sampleRate = SAMPLE_RATES[fscod];
|
int sampleRate = SAMPLE_RATES[fscod];
|
||||||
@ -53,18 +55,20 @@ public final class Ac3Util {
|
|||||||
channelCount++;
|
channelCount++;
|
||||||
}
|
}
|
||||||
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
|
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null);
|
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the AC-3 format given {@code data} containing the EC3SpecificBox according to
|
* Returns the E-AC-3 format given {@code data} containing the EC3SpecificBox according to
|
||||||
* ETSI TS 102 366 Annex F.
|
* ETSI TS 102 366 Annex F.
|
||||||
*
|
*
|
||||||
* @param data The EC3SpecificBox.
|
* @param data The EC3SpecificBox.
|
||||||
* @param durationUs The duration to set on the format, in microseconds.
|
* @param durationUs The duration to set on the format, in microseconds.
|
||||||
* @return The FEAc3 format parsed from data in the header.
|
* @param language The language to set on the format.
|
||||||
|
* @return The E-AC-3 format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static MediaFormat parseAnnexFEAc3Format(ParsableByteArray data, long durationUs) {
|
public static MediaFormat parseAnnexFEAc3Format(ParsableByteArray data, long durationUs,
|
||||||
|
String language) {
|
||||||
data.skipBytes(2); // Skip data_rate and num_ind_sub.
|
data.skipBytes(2); // Skip data_rate and num_ind_sub.
|
||||||
|
|
||||||
// Read only the first substream.
|
// Read only the first substream.
|
||||||
@ -80,7 +84,7 @@ public final class Ac3Util {
|
|||||||
channelCount++;
|
channelCount++;
|
||||||
}
|
}
|
||||||
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_EC3, MediaFormat.NO_VALUE,
|
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_EC3, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null);
|
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,9 +93,11 @@ public final class Ac3Util {
|
|||||||
*
|
*
|
||||||
* @param data Data to parse, positioned at the start of the syncword.
|
* @param data Data to parse, positioned at the start of the syncword.
|
||||||
* @param durationUs The duration to set on the format, in microseconds.
|
* @param durationUs The duration to set on the format, in microseconds.
|
||||||
|
* @param language The language to set on the format.
|
||||||
* @return The AC-3 format parsed from data in the header.
|
* @return The AC-3 format parsed from data in the header.
|
||||||
*/
|
*/
|
||||||
public static MediaFormat parseFrameAc3Format(ParsableBitArray data, long durationUs) {
|
public static MediaFormat parseFrameAc3Format(ParsableBitArray data, long durationUs,
|
||||||
|
String language) {
|
||||||
// Skip syncword and crc1.
|
// Skip syncword and crc1.
|
||||||
data.skipBits(4 * 8);
|
data.skipBits(4 * 8);
|
||||||
|
|
||||||
@ -110,7 +116,7 @@ public final class Ac3Util {
|
|||||||
boolean lfeon = data.readBit();
|
boolean lfeon = data.readBit();
|
||||||
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
|
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, CHANNEL_COUNTS[acmod] + (lfeon ? 1 : 0),
|
MediaFormat.NO_VALUE, durationUs, CHANNEL_COUNTS[acmod] + (lfeon ? 1 : 0),
|
||||||
SAMPLE_RATES[fscod], null);
|
SAMPLE_RATES[fscod], null, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user