use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class DtsUtil method parseDtsFormat.
/**
* Returns the DTS format given {@code data} containing the DTS frame according to ETSI TS 102 114
* subsections 5.3/5.4.
*
* @param frame The DTS frame 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 DTS format parsed from data in the header.
*/
public static Format parseDtsFormat(byte[] frame, @Nullable String trackId, @Nullable String language, @Nullable DrmInitData drmInitData) {
ParsableBitArray frameBits = getNormalizedFrameHeader(frame);
// SYNC, FTYPE, SHORT, CPF, NBLKS, FSIZE
frameBits.skipBits(32 + 1 + 5 + 1 + 7 + 14);
int amode = frameBits.readBits(6);
int channelCount = CHANNELS_BY_AMODE[amode];
int sfreq = frameBits.readBits(4);
int sampleRate = SAMPLE_RATE_BY_SFREQ[sfreq];
int rate = frameBits.readBits(5);
int bitrate = rate >= TWICE_BITRATE_KBPS_BY_RATE.length ? Format.NO_VALUE : TWICE_BITRATE_KBPS_BY_RATE[rate] * 1000 / 2;
// MIX, DYNF, TIMEF, AUXF, HDCD, EXT_AUDIO_ID, EXT_AUDIO, ASPF
frameBits.skipBits(10);
// LFF
channelCount += frameBits.readBits(2) > 0 ? 1 : 0;
return new Format.Builder().setId(trackId).setSampleMimeType(MimeTypes.AUDIO_DTS).setAverageBitrate(bitrate).setChannelCount(channelCount).setSampleRate(sampleRate).setDrmInitData(drmInitData).setLanguage(language).build();
}
use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class DefaultTsPayloadReaderFactory method getClosedCaptionFormats.
/**
* If {@link #FLAG_OVERRIDE_CAPTION_DESCRIPTORS} is set, returns a {@link List<Format>} of {@link
* #closedCaptionFormats}. If unset, parses the PMT descriptor information and returns a {@link
* List<Format>} for the declared formats, or {@link #closedCaptionFormats} if the descriptor is
* not present.
*
* @param esInfo The {@link EsInfo} passed to {@link #createPayloadReader(int, EsInfo)}.
* @return A {@link List<Format>} containing list of closed caption formats.
*/
private List<Format> getClosedCaptionFormats(EsInfo esInfo) {
if (isSet(FLAG_OVERRIDE_CAPTION_DESCRIPTORS)) {
return closedCaptionFormats;
}
ParsableByteArray scratchDescriptorData = new ParsableByteArray(esInfo.descriptorBytes);
List<Format> closedCaptionFormats = this.closedCaptionFormats;
while (scratchDescriptorData.bytesLeft() > 0) {
int descriptorTag = scratchDescriptorData.readUnsignedByte();
int descriptorLength = scratchDescriptorData.readUnsignedByte();
int nextDescriptorPosition = scratchDescriptorData.getPosition() + descriptorLength;
if (descriptorTag == DESCRIPTOR_TAG_CAPTION_SERVICE) {
// Note: see ATSC A/65 for detailed information about the caption service descriptor.
closedCaptionFormats = new ArrayList<>();
int numberOfServices = scratchDescriptorData.readUnsignedByte() & 0x1F;
for (int i = 0; i < numberOfServices; i++) {
String language = scratchDescriptorData.readString(3);
int captionTypeByte = scratchDescriptorData.readUnsignedByte();
boolean isDigital = (captionTypeByte & 0x80) != 0;
String mimeType;
int accessibilityChannel;
if (isDigital) {
mimeType = MimeTypes.APPLICATION_CEA708;
accessibilityChannel = captionTypeByte & 0x3F;
} else {
mimeType = MimeTypes.APPLICATION_CEA608;
accessibilityChannel = 1;
}
// easy_reader(1), wide_aspect_ratio(1), reserved(6).
byte flags = (byte) scratchDescriptorData.readUnsignedByte();
// Skip reserved (8).
scratchDescriptorData.skipBytes(1);
@Nullable List<byte[]> initializationData = null;
// The wide_aspect_ratio flag only has meaning for CEA-708.
if (isDigital) {
boolean isWideAspectRatio = (flags & 0x40) != 0;
initializationData = CodecSpecificDataUtil.buildCea708InitializationData(isWideAspectRatio);
}
closedCaptionFormats.add(new Format.Builder().setSampleMimeType(mimeType).setLanguage(language).setAccessibilityChannel(accessibilityChannel).setInitializationData(initializationData).build());
}
} else {
// Unknown descriptor. Ignore.
}
scratchDescriptorData.setPosition(nextDescriptorPosition);
}
return closedCaptionFormats;
}
use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class MpegAudioReader method readHeaderRemainder.
/**
* Attempts to read the remaining two bytes of the frame header.
*
* <p>If a frame header is read in full then the state is changed to {@link #STATE_READING_FRAME},
* the media format is output if this has not previously occurred, the four header bytes are
* output as sample data, and the position of the source is advanced to the byte that immediately
* follows the header.
*
* <p>If a frame header is read in full but cannot be parsed then the state is changed to {@link
* #STATE_READING_HEADER}.
*
* <p>If a frame header is not read in full then the position of the source is advanced to the
* limit, and the method should be called again with the next source to continue the read.
*
* @param source The source from which to read.
*/
@RequiresNonNull("output")
private void readHeaderRemainder(ParsableByteArray source) {
int bytesToRead = min(source.bytesLeft(), HEADER_SIZE - frameBytesRead);
source.readBytes(headerScratch.getData(), frameBytesRead, bytesToRead);
frameBytesRead += bytesToRead;
if (frameBytesRead < HEADER_SIZE) {
// We haven't read the whole header yet.
return;
}
headerScratch.setPosition(0);
boolean parsedHeader = header.setForHeaderData(headerScratch.readInt());
if (!parsedHeader) {
// We thought we'd located a frame header, but we hadn't.
frameBytesRead = 0;
state = STATE_READING_HEADER;
return;
}
frameSize = header.frameSize;
if (!hasOutputFormat) {
frameDurationUs = (C.MICROS_PER_SECOND * header.samplesPerFrame) / header.sampleRate;
Format format = new Format.Builder().setId(formatId).setSampleMimeType(header.mimeType).setMaxInputSize(MpegAudioUtil.MAX_FRAME_SIZE_BYTES).setChannelCount(header.channels).setSampleRate(header.sampleRate).setLanguage(language).build();
output.format(format);
hasOutputFormat = true;
}
headerScratch.setPosition(0);
output.sampleData(headerScratch, HEADER_SIZE);
state = STATE_READING_FRAME;
}
use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class VorbisReader method readHeaders.
@Override
@EnsuresNonNullIf(expression = "#3.format", result = false)
protected boolean readHeaders(ParsableByteArray packet, long position, SetupData setupData) throws IOException {
if (vorbisSetup != null) {
checkNotNull(setupData.format);
return false;
}
vorbisSetup = readSetupHeaders(packet);
if (vorbisSetup == null) {
return true;
}
VorbisSetup vorbisSetup = this.vorbisSetup;
VorbisUtil.VorbisIdHeader idHeader = vorbisSetup.idHeader;
ArrayList<byte[]> codecInitializationData = new ArrayList<>();
codecInitializationData.add(idHeader.data);
codecInitializationData.add(vorbisSetup.setupHeaderData);
@Nullable Metadata metadata = VorbisUtil.parseVorbisComments(ImmutableList.copyOf(vorbisSetup.commentHeader.comments));
setupData.format = new Format.Builder().setSampleMimeType(MimeTypes.AUDIO_VORBIS).setAverageBitrate(idHeader.bitrateNominal).setPeakBitrate(idHeader.bitrateMaximum).setChannelCount(idHeader.channels).setSampleRate(idHeader.sampleRate).setInitializationData(codecInitializationData).setMetadata(metadata).build();
return true;
}
use of com.google.android.exoplayer2.Format in project ExoPlayer by google.
the class Ac3Reader method parseHeader.
/**
* Parses the sample header.
*/
@RequiresNonNull("output")
private void parseHeader() {
headerScratchBits.setPosition(0);
SyncFrameInfo frameInfo = Ac3Util.parseAc3SyncframeInfo(headerScratchBits);
if (format == null || frameInfo.channelCount != format.channelCount || frameInfo.sampleRate != format.sampleRate || !Util.areEqual(frameInfo.mimeType, format.sampleMimeType)) {
format = new Format.Builder().setId(formatId).setSampleMimeType(frameInfo.mimeType).setChannelCount(frameInfo.channelCount).setSampleRate(frameInfo.sampleRate).setLanguage(language).build();
output.format(format);
}
sampleSize = frameInfo.frameSize;
// In this class a sample is an access unit (syncframe in AC-3), but Format#sampleRate
// specifies the number of PCM audio samples per second.
sampleDurationUs = C.MICROS_PER_SECOND * frameInfo.sampleCount / format.sampleRate;
}
Aggregations