use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class WavExtractor method read.
@Override
public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException {
if (wavHeader == null) {
wavHeader = WavHeaderReader.peek(input);
if (wavHeader == null) {
// Should only happen if the media wasn't sniffed.
throw new ParserException("Unsupported or unrecognized wav header.");
}
Format format = Format.createAudioSampleFormat(null, MimeTypes.AUDIO_RAW, null, wavHeader.getBitrate(), MAX_INPUT_SIZE, wavHeader.getNumChannels(), wavHeader.getSampleRateHz(), wavHeader.getEncoding(), null, null, 0, null);
trackOutput.format(format);
bytesPerFrame = wavHeader.getBytesPerFrame();
}
if (!wavHeader.hasDataBounds()) {
WavHeaderReader.skipToData(input, wavHeader);
extractorOutput.seekMap(this);
}
int bytesAppended = trackOutput.sampleData(input, MAX_INPUT_SIZE - pendingBytes, true);
if (bytesAppended != RESULT_END_OF_INPUT) {
pendingBytes += bytesAppended;
}
// Samples must consist of a whole number of frames.
int pendingFrames = pendingBytes / bytesPerFrame;
if (pendingFrames > 0) {
long timeUs = wavHeader.getTimeUs(input.getPosition() - pendingBytes);
int size = pendingFrames * bytesPerFrame;
pendingBytes -= size;
trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, size, pendingBytes, null);
}
return bytesAppended == RESULT_END_OF_INPUT ? RESULT_END_OF_INPUT : RESULT_CONTINUE;
}
use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class MediaCodecRenderer method maybeInitCodec.
@SuppressWarnings("deprecation")
protected final void maybeInitCodec() throws ExoPlaybackException {
if (!shouldInitCodec()) {
return;
}
drmSession = pendingDrmSession;
String mimeType = format.sampleMimeType;
MediaCrypto mediaCrypto = null;
boolean drmSessionRequiresSecureDecoder = false;
if (drmSession != null) {
@DrmSession.State int drmSessionState = drmSession.getState();
if (drmSessionState == DrmSession.STATE_ERROR) {
throw ExoPlaybackException.createForRenderer(drmSession.getError(), getIndex());
} else if (drmSessionState == DrmSession.STATE_OPENED || drmSessionState == DrmSession.STATE_OPENED_WITH_KEYS) {
mediaCrypto = drmSession.getMediaCrypto().getWrappedMediaCrypto();
drmSessionRequiresSecureDecoder = drmSession.requiresSecureDecoderComponent(mimeType);
} else {
// The drm session isn't open yet.
return;
}
}
MediaCodecInfo decoderInfo = null;
try {
decoderInfo = getDecoderInfo(mediaCodecSelector, format, drmSessionRequiresSecureDecoder);
if (decoderInfo == null && drmSessionRequiresSecureDecoder) {
// The drm session indicates that a secure decoder is required, but the device does not have
// one. Assuming that supportsFormat indicated support for the media being played, we know
// that it does not require a secure output path. Most CDM implementations allow playback to
// proceed with a non-secure decoder in this case, so we try our luck.
decoderInfo = getDecoderInfo(mediaCodecSelector, format, false);
if (decoderInfo != null) {
Log.w(TAG, "Drm session requires secure decoder for " + mimeType + ", but " + "no secure decoder available. Trying to proceed with " + decoderInfo.name + ".");
}
}
} catch (DecoderQueryException e) {
throwDecoderInitError(new DecoderInitializationException(format, e, drmSessionRequiresSecureDecoder, DecoderInitializationException.DECODER_QUERY_ERROR));
}
if (decoderInfo == null) {
throwDecoderInitError(new DecoderInitializationException(format, null, drmSessionRequiresSecureDecoder, DecoderInitializationException.NO_SUITABLE_DECODER_ERROR));
}
String codecName = decoderInfo.name;
codecIsAdaptive = decoderInfo.adaptive;
codecNeedsDiscardToSpsWorkaround = codecNeedsDiscardToSpsWorkaround(codecName, format);
codecNeedsFlushWorkaround = codecNeedsFlushWorkaround(codecName);
codecNeedsAdaptationWorkaround = codecNeedsAdaptationWorkaround(codecName);
codecNeedsEosPropagationWorkaround = codecNeedsEosPropagationWorkaround(codecName);
codecNeedsEosFlushWorkaround = codecNeedsEosFlushWorkaround(codecName);
codecNeedsEosOutputExceptionWorkaround = codecNeedsEosOutputExceptionWorkaround(codecName);
codecNeedsMonoChannelCountWorkaround = codecNeedsMonoChannelCountWorkaround(codecName, format);
try {
long codecInitializingTimestamp = SystemClock.elapsedRealtime();
TraceUtil.beginSection("createCodec:" + codecName);
codec = MediaCodec.createByCodecName(codecName);
TraceUtil.endSection();
TraceUtil.beginSection("configureCodec");
configureCodec(decoderInfo, codec, format, mediaCrypto);
TraceUtil.endSection();
TraceUtil.beginSection("startCodec");
codec.start();
TraceUtil.endSection();
long codecInitializedTimestamp = SystemClock.elapsedRealtime();
onCodecInitialized(codecName, codecInitializedTimestamp, codecInitializedTimestamp - codecInitializingTimestamp);
inputBuffers = codec.getInputBuffers();
outputBuffers = codec.getOutputBuffers();
} catch (Exception e) {
throwDecoderInitError(new DecoderInitializationException(format, e, drmSessionRequiresSecureDecoder, codecName));
}
codecHotswapDeadlineMs = getState() == STATE_STARTED ? (SystemClock.elapsedRealtime() + MAX_CODEC_HOTSWAP_TIME_MS) : C.TIME_UNSET;
inputIndex = C.INDEX_UNSET;
outputIndex = C.INDEX_UNSET;
waitingForFirstSyncFrame = true;
decoderCounters.decoderInitCount++;
}
use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class HlsSampleStreamWrapper method readData.
/* package */
int readData(int group, FormatHolder formatHolder, DecoderInputBuffer buffer, boolean requireFormat) {
if (isPendingReset()) {
return C.RESULT_NOTHING_READ;
}
while (mediaChunks.size() > 1 && finishedReadingChunk(mediaChunks.getFirst())) {
mediaChunks.removeFirst();
}
HlsMediaChunk currentChunk = mediaChunks.getFirst();
Format trackFormat = currentChunk.trackFormat;
if (!trackFormat.equals(downstreamTrackFormat)) {
eventDispatcher.downstreamFormatChanged(trackType, trackFormat, currentChunk.trackSelectionReason, currentChunk.trackSelectionData, currentChunk.startTimeUs);
}
downstreamTrackFormat = trackFormat;
return sampleQueues.valueAt(group).readData(formatHolder, buffer, requireFormat, loadingFinished, lastSeekPositionUs);
}
use of com.google.android.exoplayer2.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 com.google.android.exoplayer2.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);
}
Aggregations