use of io.atlasmap.v2.Format in project ExoPlayer by google.
the class ChunkSampleStream method discardDownstreamMediaChunks.
private void discardDownstreamMediaChunks(int primaryStreamReadIndex) {
while (mediaChunks.size() > 1 && mediaChunks.get(1).getFirstSampleIndex(0) <= primaryStreamReadIndex) {
mediaChunks.removeFirst();
}
BaseMediaChunk currentChunk = mediaChunks.getFirst();
Format trackFormat = currentChunk.trackFormat;
if (!trackFormat.equals(primaryDownstreamTrackFormat)) {
eventDispatcher.downstreamFormatChanged(primaryTrackType, trackFormat, currentChunk.trackSelectionReason, currentChunk.trackSelectionData, currentChunk.startTimeUs);
}
primaryDownstreamTrackFormat = trackFormat;
}
use of io.atlasmap.v2.Format in project ExoPlayer by google.
the class AdtsReader method parseAdtsHeader.
/**
* Parses the sample header.
*/
private void parseAdtsHeader() {
adtsScratch.setPosition(0);
if (!hasOutputFormat) {
int audioObjectType = adtsScratch.readBits(2) + 1;
if (audioObjectType != 2) {
// The stream indicates AAC-Main (1), AAC-SSR (3) or AAC-LTP (4). When the stream indicates
// AAC-Main it's more likely that the stream contains HE-AAC (5), which cannot be
// represented correctly in the 2 bit audio_object_type field in the ADTS header. In
// practice when the stream indicates AAC-SSR or AAC-LTP it more commonly contains AAC-LC or
// HE-AAC. Since most Android devices don't support AAC-Main, AAC-SSR or AAC-LTP, and since
// indicating AAC-LC works for HE-AAC streams, we pretend that we're dealing with AAC-LC and
// hope for the best. In practice this often works.
// See: https://github.com/google/ExoPlayer/issues/774
// See: https://github.com/google/ExoPlayer/issues/1383
Log.w(TAG, "Detected audio object type: " + audioObjectType + ", but assuming AAC LC.");
audioObjectType = 2;
}
int sampleRateIndex = adtsScratch.readBits(4);
adtsScratch.skipBits(1);
int channelConfig = adtsScratch.readBits(3);
byte[] audioSpecificConfig = CodecSpecificDataUtil.buildAacAudioSpecificConfig(audioObjectType, sampleRateIndex, channelConfig);
Pair<Integer, Integer> audioParams = CodecSpecificDataUtil.parseAacAudioSpecificConfig(audioSpecificConfig);
Format format = Format.createAudioSampleFormat(formatId, MimeTypes.AUDIO_AAC, null, Format.NO_VALUE, Format.NO_VALUE, audioParams.second, audioParams.first, Collections.singletonList(audioSpecificConfig), null, 0, language);
// In this class a sample is an access unit, but the MediaFormat sample rate specifies the
// number of PCM audio samples per second.
sampleDurationUs = (C.MICROS_PER_SECOND * 1024) / format.sampleRate;
output.format(format);
hasOutputFormat = true;
} else {
adtsScratch.skipBits(10);
}
adtsScratch.skipBits(4);
int sampleSize = adtsScratch.readBits(13) - 2 - /* the sync word */
HEADER_SIZE;
if (hasCrc) {
sampleSize -= CRC_SIZE;
}
setReadingSampleState(output, sampleDurationUs, 0, sampleSize);
}
use of io.atlasmap.v2.Format in project ExoPlayer by google.
the class H262Reader method parseCsdBuffer.
/**
* Parses the {@link Format} and frame duration from a csd buffer.
*
* @param csdBuffer The csd buffer.
* @param formatId The id for the generated format. May be null.
* @return A pair consisting of the {@link Format} and the frame duration in microseconds, or
* 0 if the duration could not be determined.
*/
private static Pair<Format, Long> parseCsdBuffer(CsdBuffer csdBuffer, String formatId) {
byte[] csdData = Arrays.copyOf(csdBuffer.data, csdBuffer.length);
int firstByte = csdData[4] & 0xFF;
int secondByte = csdData[5] & 0xFF;
int thirdByte = csdData[6] & 0xFF;
int width = (firstByte << 4) | (secondByte >> 4);
int height = (secondByte & 0x0F) << 8 | thirdByte;
float pixelWidthHeightRatio = 1f;
int aspectRatioCode = (csdData[7] & 0xF0) >> 4;
switch(aspectRatioCode) {
case 2:
pixelWidthHeightRatio = (4 * height) / (float) (3 * width);
break;
case 3:
pixelWidthHeightRatio = (16 * height) / (float) (9 * width);
break;
case 4:
pixelWidthHeightRatio = (121 * height) / (float) (100 * width);
break;
default:
// Do nothing.
break;
}
Format format = Format.createVideoSampleFormat(formatId, MimeTypes.VIDEO_MPEG2, null, Format.NO_VALUE, Format.NO_VALUE, width, height, Format.NO_VALUE, Collections.singletonList(csdData), Format.NO_VALUE, pixelWidthHeightRatio, null);
long frameDurationUs = 0;
int frameRateCodeMinusOne = (csdData[7] & 0x0F) - 1;
if (0 <= frameRateCodeMinusOne && frameRateCodeMinusOne < FRAME_RATE_VALUES.length) {
double frameRate = FRAME_RATE_VALUES[frameRateCodeMinusOne];
int sequenceExtensionPosition = csdBuffer.sequenceExtensionPosition;
int frameRateExtensionN = (csdData[sequenceExtensionPosition + 9] & 0x60) >> 5;
int frameRateExtensionD = (csdData[sequenceExtensionPosition + 9] & 0x1F);
if (frameRateExtensionN != frameRateExtensionD) {
frameRate *= (frameRateExtensionN + 1d) / (frameRateExtensionD + 1);
}
frameDurationUs = (long) (C.MICROS_PER_SECOND / frameRate);
}
return Pair.create(format, frameDurationUs);
}
use of io.atlasmap.v2.Format in project ExoPlayer by google.
the class HlsMediaPeriod method buildAndPrepareSampleStreamWrappers.
// Internal methods.
private void buildAndPrepareSampleStreamWrappers() {
HlsMasterPlaylist masterPlaylist = playlistTracker.getMasterPlaylist();
// Build the default stream wrapper.
List<HlsUrl> selectedVariants = new ArrayList<>(masterPlaylist.variants);
ArrayList<HlsUrl> definiteVideoVariants = new ArrayList<>();
ArrayList<HlsUrl> definiteAudioOnlyVariants = new ArrayList<>();
for (int i = 0; i < selectedVariants.size(); i++) {
HlsUrl variant = selectedVariants.get(i);
if (variant.format.height > 0 || variantHasExplicitCodecWithPrefix(variant, "avc")) {
definiteVideoVariants.add(variant);
} else if (variantHasExplicitCodecWithPrefix(variant, "mp4a")) {
definiteAudioOnlyVariants.add(variant);
}
}
if (!definiteVideoVariants.isEmpty()) {
// We've identified some variants as definitely containing video. Assume variants within the
// master playlist are marked consistently, and hence that we have the full set. Filter out
// any other variants, which are likely to be audio only.
selectedVariants = definiteVideoVariants;
} else if (definiteAudioOnlyVariants.size() < selectedVariants.size()) {
// We've identified some variants, but not all, as being audio only. Filter them out to leave
// the remaining variants, which are likely to contain video.
selectedVariants.removeAll(definiteAudioOnlyVariants);
} else {
// Leave the enabled variants unchanged. They're likely either all video or all audio.
}
List<HlsUrl> audioRenditions = masterPlaylist.audios;
List<HlsUrl> subtitleRenditions = masterPlaylist.subtitles;
sampleStreamWrappers = new HlsSampleStreamWrapper[1 + /* variants */
audioRenditions.size() + subtitleRenditions.size()];
int currentWrapperIndex = 0;
pendingPrepareCount = sampleStreamWrappers.length;
Assertions.checkArgument(!selectedVariants.isEmpty());
HlsUrl[] variants = new HlsMasterPlaylist.HlsUrl[selectedVariants.size()];
selectedVariants.toArray(variants);
HlsSampleStreamWrapper sampleStreamWrapper = buildSampleStreamWrapper(C.TRACK_TYPE_DEFAULT, variants, masterPlaylist.muxedAudioFormat, masterPlaylist.muxedCaptionFormats);
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
sampleStreamWrapper.setIsTimestampMaster(true);
sampleStreamWrapper.continuePreparing();
// Build audio stream wrappers.
for (int i = 0; i < audioRenditions.size(); i++) {
sampleStreamWrapper = buildSampleStreamWrapper(C.TRACK_TYPE_AUDIO, new HlsUrl[] { audioRenditions.get(i) }, null, Collections.<Format>emptyList());
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
sampleStreamWrapper.continuePreparing();
}
// Build subtitle stream wrappers.
for (int i = 0; i < subtitleRenditions.size(); i++) {
HlsUrl url = subtitleRenditions.get(i);
sampleStreamWrapper = buildSampleStreamWrapper(C.TRACK_TYPE_TEXT, new HlsUrl[] { url }, null, Collections.<Format>emptyList());
sampleStreamWrapper.prepareSingleTrack(url.format);
sampleStreamWrappers[currentWrapperIndex++] = sampleStreamWrapper;
}
}
use of io.atlasmap.v2.Format in project ExoPlayer by google.
the class MediaCodecRenderer method onInputFormatChanged.
/**
* Called when a new format is read from the upstream {@link MediaPeriod}.
*
* @param newFormat The new format.
* @throws ExoPlaybackException If an error occurs reinitializing the {@link MediaCodec}.
*/
protected void onInputFormatChanged(Format newFormat) throws ExoPlaybackException {
Format oldFormat = format;
format = newFormat;
boolean drmInitDataChanged = !Util.areEqual(format.drmInitData, oldFormat == null ? null : oldFormat.drmInitData);
if (drmInitDataChanged) {
if (format.drmInitData != null) {
if (drmSessionManager == null) {
throw ExoPlaybackException.createForRenderer(new IllegalStateException("Media requires a DrmSessionManager"), getIndex());
}
pendingDrmSession = drmSessionManager.acquireSession(Looper.myLooper(), format.drmInitData);
if (pendingDrmSession == drmSession) {
drmSessionManager.releaseSession(pendingDrmSession);
}
} else {
pendingDrmSession = null;
}
}
if (pendingDrmSession == drmSession && codec != null && canReconfigureCodec(codec, codecIsAdaptive, oldFormat, format)) {
codecReconfigured = true;
codecReconfigurationState = RECONFIGURATION_STATE_WRITE_PENDING;
codecNeedsAdaptationWorkaroundBuffer = codecNeedsAdaptationWorkaround && format.width == oldFormat.width && format.height == oldFormat.height;
} else {
if (codecReceivedBuffers) {
// Signal end of stream and wait for any final output buffers before re-initialization.
codecReinitializationState = REINITIALIZATION_STATE_SIGNAL_END_OF_STREAM;
} else {
// There aren't any final output buffers, so perform re-initialization immediately.
releaseCodec();
maybeInitCodec();
}
}
}
Aggregations