parent
979fd083b4
commit
decb7f58c7
@ -453,12 +453,15 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||||||
}
|
}
|
||||||
String trackName;
|
String trackName;
|
||||||
if (MimeTypes.isVideo(format.mimeType)) {
|
if (MimeTypes.isVideo(format.mimeType)) {
|
||||||
trackName = joinWithSeparator(buildResolutionString(format), buildBitrateString(format));
|
trackName = joinWithSeparator(joinWithSeparator(buildResolutionString(format),
|
||||||
|
buildBitrateString(format)), buildTrackIdString(format));
|
||||||
} else if (MimeTypes.isAudio(format.mimeType)) {
|
} else if (MimeTypes.isAudio(format.mimeType)) {
|
||||||
trackName = joinWithSeparator(joinWithSeparator(buildLanguageString(format),
|
trackName = joinWithSeparator(joinWithSeparator(joinWithSeparator(buildLanguageString(format),
|
||||||
buildAudioPropertyString(format)), buildBitrateString(format));
|
buildAudioPropertyString(format)), buildBitrateString(format)),
|
||||||
|
buildTrackIdString(format));
|
||||||
} else {
|
} else {
|
||||||
trackName = joinWithSeparator(buildLanguageString(format), buildBitrateString(format));
|
trackName = joinWithSeparator(joinWithSeparator(buildLanguageString(format),
|
||||||
|
buildBitrateString(format)), buildTrackIdString(format));
|
||||||
}
|
}
|
||||||
return trackName.length() == 0 ? "unknown" : trackName;
|
return trackName.length() == 0 ? "unknown" : trackName;
|
||||||
}
|
}
|
||||||
@ -487,6 +490,11 @@ public class PlayerActivity extends Activity implements SurfaceHolder.Callback,
|
|||||||
return first.length() == 0 ? second : (second.length() == 0 ? first : first + ", " + second);
|
return first.length() == 0 ? second : (second.length() == 0 ? first : first + ", " + second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String buildTrackIdString(MediaFormat format) {
|
||||||
|
return format.trackId == MediaFormat.NO_VALUE ? ""
|
||||||
|
: String.format(Locale.US, " (%d)", format.trackId);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean onTrackItemClick(MenuItem item, int type) {
|
private boolean onTrackItemClick(MenuItem item, int type) {
|
||||||
if (player == null || item.getGroupId() != MENU_GROUP_TRACKS) {
|
if (player == null || item.getGroupId() != MENU_GROUP_TRACKS) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -45,17 +45,21 @@ public final class MediaFormatTest extends TestCase {
|
|||||||
initData.add(initData2);
|
initData.add(initData2);
|
||||||
|
|
||||||
testConversionToFrameworkFormatV16(MediaFormat.createVideoFormat(
|
testConversionToFrameworkFormatV16(MediaFormat.createVideoFormat(
|
||||||
"video/xyz", 5000, 102400, 1000L, 1280, 720, initData));
|
MediaFormat.NO_VALUE, "video/xyz", 5000, 102400, 1000L, 1280, 720, initData));
|
||||||
testConversionToFrameworkFormatV16(MediaFormat.createVideoFormat(
|
testConversionToFrameworkFormatV16(MediaFormat.createVideoFormat(
|
||||||
"video/xyz", 5000, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, 1280, 720, null));
|
MediaFormat.NO_VALUE, "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, null));
|
MediaFormat.NO_VALUE, "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, null));
|
MediaFormat.NO_VALUE, "audio/xyz", 500, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, 5, 44100,
|
||||||
|
null, null));
|
||||||
testConversionToFrameworkFormatV16(
|
testConversionToFrameworkFormatV16(
|
||||||
MediaFormat.createTextFormat("text/xyz", MediaFormat.NO_VALUE, 1000L, "eng"));
|
MediaFormat.createTextFormat(MediaFormat.NO_VALUE, "text/xyz", MediaFormat.NO_VALUE, 1000L,
|
||||||
|
"eng"));
|
||||||
testConversionToFrameworkFormatV16(
|
testConversionToFrameworkFormatV16(
|
||||||
MediaFormat.createTextFormat("text/xyz", MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, null));
|
MediaFormat.createTextFormat(MediaFormat.NO_VALUE, "text/xyz", MediaFormat.NO_VALUE,
|
||||||
|
C.UNKNOWN_TIME_US, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
|
@ -315,10 +315,10 @@ public final class FrameworkSampleSource implements SampleSource, SampleSourceRe
|
|||||||
}
|
}
|
||||||
long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION)
|
long durationUs = format.containsKey(android.media.MediaFormat.KEY_DURATION)
|
||||||
? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US;
|
? format.getLong(android.media.MediaFormat.KEY_DURATION) : C.UNKNOWN_TIME_US;
|
||||||
MediaFormat mediaFormat = new MediaFormat(mimeType, MediaFormat.NO_VALUE, maxInputSize,
|
MediaFormat mediaFormat = new MediaFormat(MediaFormat.NO_VALUE, mimeType, MediaFormat.NO_VALUE,
|
||||||
durationUs, width, height, rotationDegrees, MediaFormat.NO_VALUE, channelCount, sampleRate,
|
maxInputSize, durationUs, width, height, rotationDegrees, MediaFormat.NO_VALUE,
|
||||||
language, MediaFormat.OFFSET_SAMPLE_RELATIVE, initializationData, false,
|
channelCount, sampleRate, language, MediaFormat.OFFSET_SAMPLE_RELATIVE, initializationData,
|
||||||
MediaFormat.NO_VALUE, MediaFormat.NO_VALUE);
|
false, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE);
|
||||||
mediaFormat.setFrameworkFormatV16(format);
|
mediaFormat.setFrameworkFormatV16(format);
|
||||||
return mediaFormat;
|
return mediaFormat;
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,11 @@ public final class MediaFormat {
|
|||||||
*/
|
*/
|
||||||
public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
|
public static final long OFFSET_SAMPLE_RELATIVE = Long.MAX_VALUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifier for the track represented by the format, or {@link #NO_VALUE} if unknown or not
|
||||||
|
* applicable.
|
||||||
|
*/
|
||||||
|
public final int trackId;
|
||||||
/**
|
/**
|
||||||
* The mime type of the format.
|
* The mime type of the format.
|
||||||
*/
|
*/
|
||||||
@ -134,49 +139,53 @@ public final class MediaFormat {
|
|||||||
private int hashCode;
|
private int hashCode;
|
||||||
private android.media.MediaFormat frameworkMediaFormat;
|
private android.media.MediaFormat frameworkMediaFormat;
|
||||||
|
|
||||||
public static MediaFormat createVideoFormat(String mimeType, int bitrate, int maxInputSize,
|
public static MediaFormat createVideoFormat(int trackId, String mimeType, int bitrate,
|
||||||
long durationUs, int width, int height, List<byte[]> initializationData) {
|
int maxInputSize, long durationUs, int width, int height, List<byte[]> initializationData) {
|
||||||
return createVideoFormat(mimeType, bitrate, maxInputSize, durationUs, width, height,
|
return createVideoFormat(trackId, mimeType, bitrate, maxInputSize, durationUs, width, height,
|
||||||
initializationData, NO_VALUE, NO_VALUE);
|
initializationData, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createVideoFormat(String mimeType, int bitrate, int maxInputSize,
|
public static MediaFormat createVideoFormat(int trackId, String mimeType, int bitrate,
|
||||||
long durationUs, int width, int height, List<byte[]> initializationData, int rotationDegrees,
|
int maxInputSize, long durationUs, int width, int height, List<byte[]> initializationData,
|
||||||
float pixelWidthHeightRatio) {
|
int rotationDegrees, float pixelWidthHeightRatio) {
|
||||||
return new MediaFormat(mimeType, bitrate, maxInputSize, durationUs, width, height,
|
return new MediaFormat(trackId, mimeType, bitrate, maxInputSize, durationUs, width, height,
|
||||||
rotationDegrees, pixelWidthHeightRatio, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE,
|
rotationDegrees, pixelWidthHeightRatio, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE,
|
||||||
initializationData, false, NO_VALUE, NO_VALUE);
|
initializationData, false, NO_VALUE, NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createAudioFormat(String mimeType, int bitrate, int maxInputSize,
|
public static MediaFormat createAudioFormat(int trackId, String mimeType, int bitrate,
|
||||||
long durationUs, int channelCount, int sampleRate, List<byte[]> initializationData,
|
int maxInputSize, long durationUs, int channelCount, int sampleRate,
|
||||||
String language) {
|
List<byte[]> initializationData, String language) {
|
||||||
return new MediaFormat(mimeType, bitrate, maxInputSize, durationUs, NO_VALUE, NO_VALUE,
|
return new MediaFormat(trackId, mimeType, bitrate, maxInputSize, durationUs, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, channelCount, sampleRate, language, 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, long durationUs,
|
public static MediaFormat createTextFormat(int trackId, String mimeType, int bitrate,
|
||||||
String language) {
|
long durationUs, String language) {
|
||||||
return createTextFormat(mimeType, bitrate, durationUs, language, OFFSET_SAMPLE_RELATIVE);
|
return createTextFormat(trackId, mimeType, bitrate, durationUs, language,
|
||||||
|
OFFSET_SAMPLE_RELATIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MediaFormat createTextFormat(String mimeType, int bitrate, long durationUs,
|
public static MediaFormat createTextFormat(int trackId, String mimeType, int bitrate,
|
||||||
String language, long subsampleOffsetUs) {
|
long durationUs, String language, long subsampleOffsetUs) {
|
||||||
return new MediaFormat(mimeType, bitrate, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
return new MediaFormat(trackId, mimeType, bitrate, NO_VALUE, durationUs, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, language, subsampleOffsetUs, null, false, NO_VALUE, NO_VALUE);
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, language, subsampleOffsetUs, null, false, NO_VALUE,
|
||||||
}
|
|
||||||
|
|
||||||
public static MediaFormat createFormatForMimeType(String mimeType, int bitrate, long durationUs) {
|
|
||||||
return new MediaFormat(mimeType, bitrate, NO_VALUE, durationUs, NO_VALUE, NO_VALUE, NO_VALUE,
|
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE, null, false, NO_VALUE,
|
|
||||||
NO_VALUE);
|
NO_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ MediaFormat(String mimeType, int bitrate, int maxInputSize, long durationUs,
|
public static MediaFormat createFormatForMimeType(int trackId, String mimeType, int bitrate,
|
||||||
int width, int height, int rotationDegrees, float pixelWidthHeightRatio, int channelCount,
|
long durationUs) {
|
||||||
int sampleRate, String language, long subsampleOffsetUs, List<byte[]> initializationData,
|
return new MediaFormat(trackId, mimeType, bitrate, NO_VALUE, durationUs, NO_VALUE, NO_VALUE,
|
||||||
boolean adaptive, int maxWidth, int maxHeight) {
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE, null, false, NO_VALUE,
|
||||||
|
NO_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ MediaFormat(int trackId, String mimeType, int bitrate, int maxInputSize,
|
||||||
|
long durationUs, int width, int height, int rotationDegrees, float pixelWidthHeightRatio,
|
||||||
|
int channelCount, int sampleRate, String language, long subsampleOffsetUs,
|
||||||
|
List<byte[]> initializationData, boolean adaptive, int maxWidth, int maxHeight) {
|
||||||
|
this.trackId = trackId;
|
||||||
this.mimeType = Assertions.checkNotEmpty(mimeType);
|
this.mimeType = Assertions.checkNotEmpty(mimeType);
|
||||||
this.bitrate = bitrate;
|
this.bitrate = bitrate;
|
||||||
this.maxInputSize = maxInputSize;
|
this.maxInputSize = maxInputSize;
|
||||||
@ -197,25 +206,25 @@ public final class MediaFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public MediaFormat copyWithMaxVideoDimensions(int maxWidth, int maxHeight) {
|
public MediaFormat copyWithMaxVideoDimensions(int maxWidth, int maxHeight) {
|
||||||
return new MediaFormat(mimeType, bitrate, maxInputSize, durationUs, width, height,
|
return new MediaFormat(trackId, mimeType, bitrate, maxInputSize, durationUs, width, height,
|
||||||
rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, language,
|
rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, language,
|
||||||
subsampleOffsetUs, initializationData, adaptive, maxWidth, maxHeight);
|
subsampleOffsetUs, initializationData, adaptive, maxWidth, maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaFormat copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
public MediaFormat copyWithSubsampleOffsetUs(long subsampleOffsetUs) {
|
||||||
return new MediaFormat(mimeType, bitrate, maxInputSize, durationUs, width, height,
|
return new MediaFormat(trackId, mimeType, bitrate, maxInputSize, durationUs, width, height,
|
||||||
rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, language,
|
rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, language,
|
||||||
subsampleOffsetUs, initializationData, adaptive, maxWidth, maxHeight);
|
subsampleOffsetUs, initializationData, adaptive, maxWidth, maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaFormat copyWithDurationUs(long durationUs) {
|
public MediaFormat copyWithDurationUs(long durationUs) {
|
||||||
return new MediaFormat(mimeType, bitrate, maxInputSize, durationUs, width, height,
|
return new MediaFormat(trackId, mimeType, bitrate, maxInputSize, durationUs, width, height,
|
||||||
rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, language,
|
rotationDegrees, pixelWidthHeightRatio, channelCount, sampleRate, language,
|
||||||
subsampleOffsetUs, initializationData, adaptive, maxWidth, maxHeight);
|
subsampleOffsetUs, initializationData, adaptive, maxWidth, maxHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MediaFormat copyAsAdaptive() {
|
public MediaFormat copyAsAdaptive() {
|
||||||
return new MediaFormat(mimeType, NO_VALUE, NO_VALUE, durationUs, NO_VALUE, NO_VALUE,
|
return new MediaFormat(trackId, mimeType, NO_VALUE, NO_VALUE, durationUs, NO_VALUE, NO_VALUE,
|
||||||
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE, null, true, maxWidth,
|
NO_VALUE, NO_VALUE, NO_VALUE, NO_VALUE, null, OFFSET_SAMPLE_RELATIVE, null, true, maxWidth,
|
||||||
maxHeight);
|
maxHeight);
|
||||||
}
|
}
|
||||||
@ -263,16 +272,17 @@ public final class MediaFormat {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "MediaFormat(" + mimeType + ", " + bitrate + ", " + maxInputSize + ", " + width + ", "
|
return "MediaFormat(" + trackId + ", " + mimeType + ", " + bitrate + ", " + maxInputSize
|
||||||
+ height + ", " + rotationDegrees + ", " + pixelWidthHeightRatio + ", " + channelCount
|
+ ", " + width + ", " + height + ", " + rotationDegrees + ", " + pixelWidthHeightRatio
|
||||||
+ ", " + sampleRate + ", " + language + ", " + durationUs + ", " + adaptive + ", "
|
+ ", " + channelCount + ", " + sampleRate + ", " + language + ", " + durationUs + ", "
|
||||||
+ maxWidth + ", " + maxHeight + ")";
|
+ adaptive + ", " + maxWidth + ", " + maxHeight + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
if (hashCode == 0) {
|
if (hashCode == 0) {
|
||||||
int result = 17;
|
int result = 17;
|
||||||
|
result = 31 * result + trackId;
|
||||||
result = 31 * result + (mimeType == null ? 0 : mimeType.hashCode());
|
result = 31 * result + (mimeType == null ? 0 : mimeType.hashCode());
|
||||||
result = 31 * result + bitrate;
|
result = 31 * result + bitrate;
|
||||||
result = 31 * result + maxInputSize;
|
result = 31 * result + maxInputSize;
|
||||||
@ -310,7 +320,8 @@ public final class MediaFormat {
|
|||||||
|| pixelWidthHeightRatio != other.pixelWidthHeightRatio
|
|| pixelWidthHeightRatio != other.pixelWidthHeightRatio
|
||||||
|| maxWidth != other.maxWidth || maxHeight != other.maxHeight
|
|| maxWidth != other.maxWidth || maxHeight != other.maxHeight
|
||||||
|| channelCount != other.channelCount || sampleRate != other.sampleRate
|
|| channelCount != other.channelCount || sampleRate != other.sampleRate
|
||||||
|| !Util.areEqual(language, other.language) || !Util.areEqual(mimeType, other.mimeType)
|
|| trackId != other.trackId || !Util.areEqual(language, other.language)
|
||||||
|
|| !Util.areEqual(mimeType, other.mimeType)
|
||||||
|| initializationData.size() != other.initializationData.size()) {
|
|| initializationData.size() != other.initializationData.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -608,14 +608,15 @@ public class DashChunkSource implements ChunkSource, Output {
|
|||||||
String mediaMimeType, long durationUs) {
|
String mediaMimeType, long durationUs) {
|
||||||
switch (adaptationSetType) {
|
switch (adaptationSetType) {
|
||||||
case AdaptationSet.TYPE_VIDEO:
|
case AdaptationSet.TYPE_VIDEO:
|
||||||
return MediaFormat.createVideoFormat(mediaMimeType, format.bitrate, MediaFormat.NO_VALUE,
|
return MediaFormat.createVideoFormat(MediaFormat.NO_VALUE, mediaMimeType, format.bitrate,
|
||||||
durationUs, format.width, format.height, null);
|
MediaFormat.NO_VALUE, 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(MediaFormat.NO_VALUE, mediaMimeType, format.bitrate,
|
||||||
durationUs, format.audioChannels, format.audioSamplingRate, null, format.language);
|
MediaFormat.NO_VALUE, durationUs, format.audioChannels, format.audioSamplingRate, null,
|
||||||
case AdaptationSet.TYPE_TEXT:
|
|
||||||
return MediaFormat.createTextFormat(mediaMimeType, format.bitrate, durationUs,
|
|
||||||
format.language);
|
format.language);
|
||||||
|
case AdaptationSet.TYPE_TEXT:
|
||||||
|
return MediaFormat.createTextFormat(MediaFormat.NO_VALUE, mediaMimeType, format.bitrate,
|
||||||
|
durationUs, format.language);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -50,11 +50,6 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
|
|||||||
*/
|
*/
|
||||||
public interface EventListener {
|
public interface EventListener {
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoked each time keys are loaded.
|
|
||||||
*/
|
|
||||||
void onDrmKeysLoaded();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoked when a drm error occurs.
|
* Invoked when a drm error occurs.
|
||||||
*
|
*
|
||||||
@ -391,14 +386,6 @@ public class StreamingDrmSessionManager implements DrmSessionManager {
|
|||||||
try {
|
try {
|
||||||
mediaDrm.provideKeyResponse(sessionId, (byte[]) response);
|
mediaDrm.provideKeyResponse(sessionId, (byte[]) response);
|
||||||
state = STATE_OPENED_WITH_KEYS;
|
state = STATE_OPENED_WITH_KEYS;
|
||||||
if (eventHandler != null && eventListener != null) {
|
|
||||||
eventHandler.post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
eventListener.onDrmKeysLoaded();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
onKeysError(e);
|
onKeysError(e);
|
||||||
}
|
}
|
||||||
|
@ -332,9 +332,10 @@ public final class Mp3Extractor implements Extractor {
|
|||||||
if (seeker == null) {
|
if (seeker == null) {
|
||||||
setupSeeker(extractorInput, headerPosition);
|
setupSeeker(extractorInput, headerPosition);
|
||||||
extractorOutput.seekMap(seeker);
|
extractorOutput.seekMap(seeker);
|
||||||
trackOutput.format(MediaFormat.createAudioFormat(synchronizedHeader.mimeType,
|
trackOutput.format(MediaFormat.createAudioFormat(MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, seeker.getDurationUs(),
|
synchronizedHeader.mimeType, MediaFormat.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES,
|
||||||
synchronizedHeader.channels, synchronizedHeader.sampleRate, null, null));
|
seeker.getDurationUs(), synchronizedHeader.channels, synchronizedHeader.sampleRate, null,
|
||||||
|
null));
|
||||||
}
|
}
|
||||||
|
|
||||||
return headerPosition;
|
return headerPosition;
|
||||||
|
@ -63,8 +63,8 @@ import java.util.List;
|
|||||||
.getContainerAtomOfType(Atom.TYPE_stbl);
|
.getContainerAtomOfType(Atom.TYPE_stbl);
|
||||||
|
|
||||||
Pair<Long, String> mdhdData = parseMdhd(mdia.getLeafAtomOfType(Atom.TYPE_mdhd).data);
|
Pair<Long, String> mdhdData = parseMdhd(mdia.getLeafAtomOfType(Atom.TYPE_mdhd).data);
|
||||||
StsdData stsdData = parseStsd(stbl.getLeafAtomOfType(Atom.TYPE_stsd).data, durationUs,
|
StsdData stsdData = parseStsd(stbl.getLeafAtomOfType(Atom.TYPE_stsd).data, tkhdData.id,
|
||||||
tkhdData.rotationDegrees, mdhdData.second);
|
durationUs, tkhdData.rotationDegrees, mdhdData.second);
|
||||||
return stsdData.mediaFormat == null ? null
|
return stsdData.mediaFormat == null ? null
|
||||||
: new Track(tkhdData.id, trackType, mdhdData.first, durationUs, stsdData.mediaFormat,
|
: new Track(tkhdData.id, trackType, mdhdData.first, durationUs, stsdData.mediaFormat,
|
||||||
stsdData.trackEncryptionBoxes, stsdData.nalUnitLengthFieldLength);
|
stsdData.trackEncryptionBoxes, stsdData.nalUnitLengthFieldLength);
|
||||||
@ -353,10 +353,15 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Parses a stsd atom (defined in 14496-12).
|
* Parses a stsd atom (defined in 14496-12).
|
||||||
*
|
*
|
||||||
|
* @param stsd The stsd atom to parse.
|
||||||
|
* @param trackId The track's identifier in its container.
|
||||||
|
* @param durationUs The duration of the track in microseconds.
|
||||||
|
* @param rotationDegrees The rotation of the track in degrees.
|
||||||
|
* @param language The language of the track.
|
||||||
* @return An object containing the parsed data.
|
* @return An object containing the parsed data.
|
||||||
*/
|
*/
|
||||||
private static StsdData parseStsd(ParsableByteArray stsd, long durationUs, int rotationDegrees,
|
private static StsdData parseStsd(ParsableByteArray stsd, int trackId, long durationUs,
|
||||||
String language) {
|
int rotationDegrees, String language) {
|
||||||
stsd.setPosition(Atom.FULL_HEADER_SIZE);
|
stsd.setPosition(Atom.FULL_HEADER_SIZE);
|
||||||
int numberOfEntries = stsd.readInt();
|
int numberOfEntries = stsd.readInt();
|
||||||
StsdData out = new StsdData(numberOfEntries);
|
StsdData out = new StsdData(numberOfEntries);
|
||||||
@ -369,22 +374,22 @@ import java.util.List;
|
|||||||
|| childAtomType == Atom.TYPE_encv || childAtomType == Atom.TYPE_mp4v
|
|| childAtomType == Atom.TYPE_encv || childAtomType == Atom.TYPE_mp4v
|
||||||
|| childAtomType == Atom.TYPE_hvc1 || childAtomType == Atom.TYPE_hev1
|
|| childAtomType == Atom.TYPE_hvc1 || childAtomType == Atom.TYPE_hev1
|
||||||
|| childAtomType == Atom.TYPE_s263) {
|
|| childAtomType == Atom.TYPE_s263) {
|
||||||
parseVideoSampleEntry(stsd, childStartPosition, childAtomSize, durationUs, rotationDegrees,
|
parseVideoSampleEntry(stsd, childStartPosition, childAtomSize, trackId, durationUs,
|
||||||
out, i);
|
rotationDegrees, out, i);
|
||||||
} else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca
|
} else if (childAtomType == Atom.TYPE_mp4a || childAtomType == Atom.TYPE_enca
|
||||||
|| childAtomType == Atom.TYPE_ac_3 || childAtomType == Atom.TYPE_ec_3
|
|| childAtomType == Atom.TYPE_ac_3 || childAtomType == Atom.TYPE_ec_3
|
||||||
|| 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, trackId,
|
||||||
language, out, i);
|
durationUs, 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(trackId, MimeTypes.APPLICATION_TTML,
|
||||||
MediaFormat.NO_VALUE, durationUs, language);
|
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(trackId, MimeTypes.APPLICATION_TX3G,
|
||||||
MediaFormat.NO_VALUE, durationUs, language);
|
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(trackId, MimeTypes.APPLICATION_TTML,
|
||||||
MediaFormat.NO_VALUE, durationUs, language, 0 /* subsample timing is absolute */);
|
MediaFormat.NO_VALUE, durationUs, language, 0 /* subsample timing is absolute */);
|
||||||
}
|
}
|
||||||
stsd.setPosition(childStartPosition + childAtomSize);
|
stsd.setPosition(childStartPosition + childAtomSize);
|
||||||
@ -393,7 +398,7 @@ import java.util.List;
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void parseVideoSampleEntry(ParsableByteArray parent, int position, int size,
|
private static void parseVideoSampleEntry(ParsableByteArray parent, int position, int size,
|
||||||
long durationUs, int rotationDegrees, StsdData out, int entryIndex) {
|
int trackId, long durationUs, int rotationDegrees, StsdData out, int entryIndex) {
|
||||||
parent.setPosition(position + Atom.HEADER_SIZE);
|
parent.setPosition(position + Atom.HEADER_SIZE);
|
||||||
|
|
||||||
parent.skipBytes(24);
|
parent.skipBytes(24);
|
||||||
@ -455,7 +460,7 @@ import java.util.List;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.mediaFormat = MediaFormat.createVideoFormat(mimeType, MediaFormat.NO_VALUE,
|
out.mediaFormat = MediaFormat.createVideoFormat(trackId, mimeType, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, width, height, initializationData, rotationDegrees,
|
MediaFormat.NO_VALUE, durationUs, width, height, initializationData, rotationDegrees,
|
||||||
pixelWidthHeightRatio);
|
pixelWidthHeightRatio);
|
||||||
}
|
}
|
||||||
@ -585,7 +590,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, String language, StsdData out, int entryIndex) {
|
int size, int trackId, 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,16 +640,16 @@ 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, language);
|
out.mediaFormat = Ac3Util.parseAnnexFAc3Format(parent, trackId, 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, language);
|
out.mediaFormat = Ac3Util.parseAnnexFEAc3Format(parent, trackId, 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(trackId, mimeType, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -656,8 +661,8 @@ import java.util.List;
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
out.mediaFormat = MediaFormat.createAudioFormat(mimeType, MediaFormat.NO_VALUE, sampleSize,
|
out.mediaFormat = MediaFormat.createAudioFormat(trackId, mimeType, MediaFormat.NO_VALUE,
|
||||||
durationUs, channelCount, sampleRate,
|
sampleSize, durationUs, channelCount, sampleRate,
|
||||||
initializationData == null ? null : Collections.singletonList(initializationData),
|
initializationData == null ? null : Collections.singletonList(initializationData),
|
||||||
language);
|
language);
|
||||||
}
|
}
|
||||||
|
@ -155,7 +155,8 @@ 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, null);
|
mediaFormat = Ac3Util.parseFrameAc3Format(headerScratchBits, MediaFormat.NO_VALUE,
|
||||||
|
C.UNKNOWN_TIME_US, null);
|
||||||
output.format(mediaFormat);
|
output.format(mediaFormat);
|
||||||
bitrate = Ac3Util.getBitrate(sampleSize, mediaFormat.sampleRate);
|
bitrate = Ac3Util.getBitrate(sampleSize, mediaFormat.sampleRate);
|
||||||
}
|
}
|
||||||
|
@ -170,9 +170,10 @@ import java.util.Collections;
|
|||||||
Pair<Integer, Integer> audioParams = CodecSpecificDataUtil.parseAacAudioSpecificConfig(
|
Pair<Integer, Integer> audioParams = CodecSpecificDataUtil.parseAacAudioSpecificConfig(
|
||||||
audioSpecificConfig);
|
audioSpecificConfig);
|
||||||
|
|
||||||
MediaFormat mediaFormat = MediaFormat.createAudioFormat(MimeTypes.AUDIO_AAC,
|
MediaFormat mediaFormat = MediaFormat.createAudioFormat(MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, audioParams.second,
|
MimeTypes.AUDIO_AAC, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US,
|
||||||
audioParams.first, Collections.singletonList(audioSpecificConfig), null);
|
audioParams.second, 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;
|
||||||
|
@ -210,9 +210,10 @@ import java.util.List;
|
|||||||
SpsData parsedSpsData = CodecSpecificDataUtil.parseSpsNalUnit(bitArray);
|
SpsData parsedSpsData = CodecSpecificDataUtil.parseSpsNalUnit(bitArray);
|
||||||
|
|
||||||
// Construct and output the format.
|
// Construct and output the format.
|
||||||
output.format(MediaFormat.createVideoFormat(MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE,
|
output.format(MediaFormat.createVideoFormat(MediaFormat.NO_VALUE, MimeTypes.VIDEO_H264,
|
||||||
MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, parsedSpsData.width, parsedSpsData.height,
|
MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, parsedSpsData.width,
|
||||||
initializationData, MediaFormat.NO_VALUE, parsedSpsData.pixelWidthAspectRatio));
|
parsedSpsData.height, initializationData, MediaFormat.NO_VALUE,
|
||||||
|
parsedSpsData.pixelWidthAspectRatio));
|
||||||
hasOutputFormat = true;
|
hasOutputFormat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,9 +294,10 @@ import java.util.Collections;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
output.format(MediaFormat.createVideoFormat(MimeTypes.VIDEO_H265, MediaFormat.NO_VALUE,
|
output.format(MediaFormat.createVideoFormat(MediaFormat.NO_VALUE, MimeTypes.VIDEO_H265,
|
||||||
MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, picWidthInLumaSamples, picHeightInLumaSamples,
|
MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, picWidthInLumaSamples,
|
||||||
Collections.singletonList(csd), MediaFormat.NO_VALUE, pixelWidthHeightRatio));
|
picHeightInLumaSamples, Collections.singletonList(csd), MediaFormat.NO_VALUE,
|
||||||
|
pixelWidthHeightRatio));
|
||||||
hasOutputFormat = true;
|
hasOutputFormat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ import com.google.android.exoplayer.util.ParsableByteArray;
|
|||||||
|
|
||||||
public Id3Reader(TrackOutput output) {
|
public Id3Reader(TrackOutput output) {
|
||||||
super(output);
|
super(output);
|
||||||
output.format(MediaFormat.createFormatForMimeType(MimeTypes.APPLICATION_ID3,
|
output.format(MediaFormat.createFormatForMimeType(MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US));
|
MimeTypes.APPLICATION_ID3, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -160,7 +160,7 @@ import com.google.android.exoplayer.util.ParsableByteArray;
|
|||||||
frameSize = header.frameSize;
|
frameSize = header.frameSize;
|
||||||
if (!hasOutputFormat) {
|
if (!hasOutputFormat) {
|
||||||
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(MediaFormat.NO_VALUE, 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, null);
|
header.channels, header.sampleRate, null, null);
|
||||||
output.format(mediaFormat);
|
output.format(mediaFormat);
|
||||||
|
@ -32,8 +32,8 @@ 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(MediaFormat.NO_VALUE, MimeTypes.APPLICATION_EIA608,
|
||||||
C.UNKNOWN_TIME_US, null));
|
MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -457,7 +457,7 @@ public final class WebmExtractor implements Extractor {
|
|||||||
return;
|
return;
|
||||||
case ID_TRACK_ENTRY:
|
case ID_TRACK_ENTRY:
|
||||||
if (tracks.get(currentTrack.number) == null && isCodecSupported(currentTrack.codecId)) {
|
if (tracks.get(currentTrack.number) == null && isCodecSupported(currentTrack.codecId)) {
|
||||||
currentTrack.initializeOutput(extractorOutput, durationUs);
|
currentTrack.initializeOutput(extractorOutput, currentTrack.number, durationUs);
|
||||||
tracks.put(currentTrack.number, currentTrack);
|
tracks.put(currentTrack.number, currentTrack);
|
||||||
} else {
|
} else {
|
||||||
// We've seen this track entry before, or the codec is unsupported. Do nothing.
|
// We've seen this track entry before, or the codec is unsupported. Do nothing.
|
||||||
@ -1135,7 +1135,8 @@ public final class WebmExtractor implements Extractor {
|
|||||||
/**
|
/**
|
||||||
* Initializes the track with an output.
|
* Initializes the track with an output.
|
||||||
*/
|
*/
|
||||||
public void initializeOutput(ExtractorOutput output, long durationUs) throws ParserException {
|
public void initializeOutput(ExtractorOutput output, int trackId, long durationUs)
|
||||||
|
throws ParserException {
|
||||||
String mimeType;
|
String mimeType;
|
||||||
int maxInputSize = MediaFormat.NO_VALUE;
|
int maxInputSize = MediaFormat.NO_VALUE;
|
||||||
List<byte[]> initializationData = null;
|
List<byte[]> initializationData = null;
|
||||||
@ -1209,13 +1210,14 @@ 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(trackId, mimeType, MediaFormat.NO_VALUE,
|
||||||
durationUs, channelCount, sampleRate, initializationData, language);
|
maxInputSize, 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(trackId, mimeType, MediaFormat.NO_VALUE,
|
||||||
durationUs, width, height, initializationData);
|
maxInputSize, 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, durationUs, language);
|
format = MediaFormat.createTextFormat(trackId, mimeType, MediaFormat.NO_VALUE, durationUs,
|
||||||
|
language);
|
||||||
} else {
|
} else {
|
||||||
throw new ParserException("Unexpected MIME type.");
|
throw new ParserException("Unexpected MIME type.");
|
||||||
}
|
}
|
||||||
|
@ -398,8 +398,9 @@ public class SmoothStreamingChunkSource implements ChunkSource,
|
|||||||
int mp4TrackType;
|
int mp4TrackType;
|
||||||
switch (element.type) {
|
switch (element.type) {
|
||||||
case StreamElement.TYPE_VIDEO:
|
case StreamElement.TYPE_VIDEO:
|
||||||
mediaFormat = MediaFormat.createVideoFormat(format.mimeType, format.bitrate,
|
mediaFormat = MediaFormat.createVideoFormat(MediaFormat.NO_VALUE, format.mimeType,
|
||||||
MediaFormat.NO_VALUE, durationUs, format.width, format.height, Arrays.asList(csdArray));
|
format.bitrate, MediaFormat.NO_VALUE, durationUs, format.width, format.height,
|
||||||
|
Arrays.asList(csdArray));
|
||||||
mp4TrackType = Track.TYPE_vide;
|
mp4TrackType = Track.TYPE_vide;
|
||||||
break;
|
break;
|
||||||
case StreamElement.TYPE_AUDIO:
|
case StreamElement.TYPE_AUDIO:
|
||||||
@ -410,14 +411,14 @@ public class SmoothStreamingChunkSource implements ChunkSource,
|
|||||||
csd = Collections.singletonList(CodecSpecificDataUtil.buildAacAudioSpecificConfig(
|
csd = Collections.singletonList(CodecSpecificDataUtil.buildAacAudioSpecificConfig(
|
||||||
format.audioSamplingRate, format.audioChannels));
|
format.audioSamplingRate, format.audioChannels));
|
||||||
}
|
}
|
||||||
mediaFormat = MediaFormat.createAudioFormat(format.mimeType, format.bitrate,
|
mediaFormat = MediaFormat.createAudioFormat(MediaFormat.NO_VALUE, format.mimeType,
|
||||||
MediaFormat.NO_VALUE, durationUs, format.audioChannels, format.audioSamplingRate, csd,
|
format.bitrate, MediaFormat.NO_VALUE, durationUs, format.audioChannels,
|
||||||
format.language);
|
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, durationUs,
|
mediaFormat = MediaFormat.createTextFormat(MediaFormat.NO_VALUE, format.mimeType,
|
||||||
format.language);
|
format.bitrate, durationUs, format.language);
|
||||||
mp4TrackType = Track.TYPE_text;
|
mp4TrackType = Track.TYPE_text;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -38,12 +38,13 @@ public final class Ac3Util {
|
|||||||
* ETSI TS 102 366 Annex F.
|
* ETSI TS 102 366 Annex F.
|
||||||
*
|
*
|
||||||
* @param data The AC3SpecificBox.
|
* @param data The AC3SpecificBox.
|
||||||
|
* @param trackId The identifier for the track in its container, or {@link MediaFormat#NO_VALUE}.
|
||||||
* @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.
|
* @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 parseAnnexFAc3Format(ParsableByteArray data, long durationUs,
|
public static MediaFormat parseAnnexFAc3Format(ParsableByteArray data, int trackId,
|
||||||
String language) {
|
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];
|
||||||
@ -54,7 +55,7 @@ public final class Ac3Util {
|
|||||||
if ((nextByte & 0x04) != 0) {
|
if ((nextByte & 0x04) != 0) {
|
||||||
channelCount++;
|
channelCount++;
|
||||||
}
|
}
|
||||||
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
|
return MediaFormat.createAudioFormat(trackId, MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,12 +64,13 @@ public final class Ac3Util {
|
|||||||
* ETSI TS 102 366 Annex F.
|
* ETSI TS 102 366 Annex F.
|
||||||
*
|
*
|
||||||
* @param data The EC3SpecificBox.
|
* @param data The EC3SpecificBox.
|
||||||
|
* @param trackId The identifier for the track in its container, or {@link MediaFormat#NO_VALUE}.
|
||||||
* @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.
|
* @param language The language to set on the format.
|
||||||
* @return The E-AC-3 format parsed from data in the header.
|
* @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, int trackId,
|
||||||
String language) {
|
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.
|
||||||
@ -83,7 +85,7 @@ public final class Ac3Util {
|
|||||||
if ((nextByte & 0x01) != 0) {
|
if ((nextByte & 0x01) != 0) {
|
||||||
channelCount++;
|
channelCount++;
|
||||||
}
|
}
|
||||||
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_EC3, MediaFormat.NO_VALUE,
|
return MediaFormat.createAudioFormat(trackId, MimeTypes.AUDIO_EC3, MediaFormat.NO_VALUE,
|
||||||
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
MediaFormat.NO_VALUE, durationUs, channelCount, sampleRate, null, language);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,11 +94,12 @@ public final class Ac3Util {
|
|||||||
* word.
|
* word.
|
||||||
*
|
*
|
||||||
* @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 trackId The identifier for the track in its container, or {@link MediaFormat#NO_VALUE}.
|
||||||
* @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.
|
* @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, int trackId, long durationUs,
|
||||||
String language) {
|
String language) {
|
||||||
// Skip syncword and crc1.
|
// Skip syncword and crc1.
|
||||||
data.skipBits(4 * 8);
|
data.skipBits(4 * 8);
|
||||||
@ -114,7 +117,7 @@ public final class Ac3Util {
|
|||||||
data.skipBits(2); // dsurmod
|
data.skipBits(2); // dsurmod
|
||||||
}
|
}
|
||||||
boolean lfeon = data.readBit();
|
boolean lfeon = data.readBit();
|
||||||
return MediaFormat.createAudioFormat(MimeTypes.AUDIO_AC3, MediaFormat.NO_VALUE,
|
return MediaFormat.createAudioFormat(trackId, 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, language);
|
SAMPLE_RATES[fscod], null, language);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user