com.google.android.exoplayer2.extractor.MpegAudioHeader Java Examples
The following examples show how to use
com.google.android.exoplayer2.extractor.MpegAudioHeader.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Mp3Extractor.java From K-Sonic with MIT License | 6 votes |
@Override public int read(ExtractorInput input, PositionHolder seekPosition) throws IOException, InterruptedException { if (synchronizedHeaderData == 0) { try { synchronize(input, false); } catch (EOFException e) { return RESULT_END_OF_INPUT; } } if (seeker == null) { seeker = setupSeeker(input); extractorOutput.seekMap(seeker); trackOutput.format(Format.createAudioSampleFormat(null, synchronizedHeader.mimeType, null, Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, synchronizedHeader.channels, synchronizedHeader.sampleRate, Format.NO_VALUE, gaplessInfoHolder.encoderDelay, gaplessInfoHolder.encoderPadding, null, null, 0, null, (flags & FLAG_DISABLE_ID3_METADATA) != 0 ? null : metadata)); } return readSample(input); }
Example #2
Source File: MpegAudioReader.java From Telegram-FOSS with GNU General Public License v2.0 | 5 votes |
/** * 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. */ private void readHeaderRemainder(ParsableByteArray source) { int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead); source.readBytes(headerScratch.data, frameBytesRead, bytesToRead); frameBytesRead += bytesToRead; if (frameBytesRead < HEADER_SIZE) { // We haven't read the whole header yet. return; } headerScratch.setPosition(0); boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header); 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 = Format.createAudioSampleFormat(formatId, header.mimeType, null, Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate, null, null, 0, language); output.format(format); hasOutputFormat = true; } headerScratch.setPosition(0); output.sampleData(headerScratch, HEADER_SIZE); state = STATE_READING_FRAME; }
Example #3
Source File: Mp3Extractor.java From TelePlus-Android with GNU General Public License v2.0 | 5 votes |
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { if (sampleBytesRemaining == 0) { extractorInput.resetPeekPosition(); if (!extractorInput.peekFully(scratch.data, 0, 4, true)) { return RESULT_END_OF_INPUT; } scratch.setPosition(0); int sampleHeaderData = scratch.readInt(); if (!headersMatch(sampleHeaderData, synchronizedHeaderData) || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) { // We have lost synchronization, so attempt to resynchronize starting at the next byte. extractorInput.skipFully(1); synchronizedHeaderData = 0; return RESULT_CONTINUE; } MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader); if (basisTimeUs == C.TIME_UNSET) { basisTimeUs = seeker.getTimeUs(extractorInput.getPosition()); if (forcedFirstSampleTimestampUs != C.TIME_UNSET) { long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0); basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs; } } sampleBytesRemaining = synchronizedHeader.frameSize; } int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true); if (bytesAppended == C.RESULT_END_OF_INPUT) { return RESULT_END_OF_INPUT; } sampleBytesRemaining -= bytesAppended; if (sampleBytesRemaining > 0) { return RESULT_CONTINUE; } long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate); trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0, null); samplesRead += synchronizedHeader.samplesPerFrame; sampleBytesRemaining = 0; return RESULT_CONTINUE; }
Example #4
Source File: Mp3Extractor.java From TelePlus-Android with GNU General Public License v2.0 | 5 votes |
/** * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate. */ private Seeker getConstantBitrateSeeker(ExtractorInput input) throws IOException, InterruptedException { input.peekFully(scratch.data, 0, 4); scratch.setPosition(0); MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader); return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader); }
Example #5
Source File: MpegAudioReader.java From MediaSDK with Apache License 2.0 | 5 votes |
public MpegAudioReader(String language) { state = STATE_FINDING_HEADER; // The first byte of an MPEG Audio frame header is always 0xFF. headerScratch = new ParsableByteArray(4); headerScratch.data[0] = (byte) 0xFF; header = new MpegAudioHeader(); this.language = language; }
Example #6
Source File: MpegAudioReader.java From K-Sonic with MIT License | 5 votes |
public MpegAudioReader(String language) { state = STATE_FINDING_HEADER; // The first byte of an MPEG Audio frame header is always 0xFF. headerScratch = new ParsableByteArray(4); headerScratch.data[0] = (byte) 0xFF; header = new MpegAudioHeader(); this.language = language; }
Example #7
Source File: MpegAudioReader.java From K-Sonic with MIT License | 5 votes |
/** * 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. */ private void readHeaderRemainder(ParsableByteArray source) { int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead); source.readBytes(headerScratch.data, frameBytesRead, bytesToRead); frameBytesRead += bytesToRead; if (frameBytesRead < HEADER_SIZE) { // We haven't read the whole header yet. return; } headerScratch.setPosition(0); boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header); 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 = Format.createAudioSampleFormat(formatId, header.mimeType, null, Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate, null, null, 0, language); output.format(format); hasOutputFormat = true; } headerScratch.setPosition(0); output.sampleData(headerScratch, HEADER_SIZE); state = STATE_READING_FRAME; }
Example #8
Source File: Mp3Extractor.java From K-Sonic with MIT License | 5 votes |
/** * Constructs a new {@link Mp3Extractor}. * * @param flags Flags that control the extractor's behavior. * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or * {@link C#TIME_UNSET} if forcing is not required. */ public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) { this.flags = flags; this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs; scratch = new ParsableByteArray(SCRATCH_LENGTH); synchronizedHeader = new MpegAudioHeader(); gaplessInfoHolder = new GaplessInfoHolder(); basisTimeUs = C.TIME_UNSET; }
Example #9
Source File: Mp3Extractor.java From K-Sonic with MIT License | 5 votes |
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { if (sampleBytesRemaining == 0) { extractorInput.resetPeekPosition(); if (!extractorInput.peekFully(scratch.data, 0, 4, true)) { return RESULT_END_OF_INPUT; } scratch.setPosition(0); int sampleHeaderData = scratch.readInt(); if ((sampleHeaderData & HEADER_MASK) != (synchronizedHeaderData & HEADER_MASK) || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) { // We have lost synchronization, so attempt to resynchronize starting at the next byte. extractorInput.skipFully(1); synchronizedHeaderData = 0; return RESULT_CONTINUE; } MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader); if (basisTimeUs == C.TIME_UNSET) { basisTimeUs = seeker.getTimeUs(extractorInput.getPosition()); if (forcedFirstSampleTimestampUs != C.TIME_UNSET) { long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0); basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs; } } sampleBytesRemaining = synchronizedHeader.frameSize; } int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true); if (bytesAppended == C.RESULT_END_OF_INPUT) { return RESULT_END_OF_INPUT; } sampleBytesRemaining -= bytesAppended; if (sampleBytesRemaining > 0) { return RESULT_CONTINUE; } long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate); trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0, null); samplesRead += synchronizedHeader.samplesPerFrame; sampleBytesRemaining = 0; return RESULT_CONTINUE; }
Example #10
Source File: XingSeeker.java From K-Sonic with MIT License | 5 votes |
/** * Returns a {@link XingSeeker} for seeking in the stream, if required information is present. * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the * caller should reset it. * * @param mpegAudioHeader The MPEG audio header associated with the frame. * @param frame The data in this audio frame, with its position set to immediately after the * 'Xing' or 'Info' tag. * @param position The position (byte offset) of the start of this frame in the stream. * @param inputLength The length of the stream in bytes. * @return A {@link XingSeeker} for seeking in the stream, or {@code null} if the required * information is not present. */ public static XingSeeker create(MpegAudioHeader mpegAudioHeader, ParsableByteArray frame, long position, long inputLength) { int samplesPerFrame = mpegAudioHeader.samplesPerFrame; int sampleRate = mpegAudioHeader.sampleRate; long firstFramePosition = position + mpegAudioHeader.frameSize; int flags = frame.readInt(); int frameCount; if ((flags & 0x01) != 0x01 || (frameCount = frame.readUnsignedIntToInt()) == 0) { // If the frame count is missing/invalid, the header can't be used to determine the duration. return null; } long durationUs = Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND, sampleRate); if ((flags & 0x06) != 0x06) { // If the size in bytes or table of contents is missing, the stream is not seekable. return new XingSeeker(firstFramePosition, durationUs, inputLength); } long sizeBytes = frame.readUnsignedIntToInt(); frame.skipBytes(1); long[] tableOfContents = new long[99]; for (int i = 0; i < 99; i++) { tableOfContents[i] = frame.readUnsignedByte(); } // TODO: Handle encoder delay and padding in 3 bytes offset by xingBase + 213 bytes: // delay = (frame.readUnsignedByte() << 4) + (frame.readUnsignedByte() >> 4); // padding = ((frame.readUnsignedByte() & 0x0F) << 8) + frame.readUnsignedByte(); return new XingSeeker(firstFramePosition, durationUs, inputLength, tableOfContents, sizeBytes, mpegAudioHeader.frameSize); }
Example #11
Source File: MpegAudioReader.java From Telegram-FOSS with GNU General Public License v2.0 | 5 votes |
public MpegAudioReader(String language) { state = STATE_FINDING_HEADER; // The first byte of an MPEG Audio frame header is always 0xFF. headerScratch = new ParsableByteArray(4); headerScratch.data[0] = (byte) 0xFF; header = new MpegAudioHeader(); this.language = language; }
Example #12
Source File: XingSeeker.java From TelePlus-Android with GNU General Public License v2.0 | 5 votes |
/** * Returns a {@link XingSeeker} for seeking in the stream, if required information is present. * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the * caller should reset it. * * @param inputLength The length of the stream in bytes, or {@link C#LENGTH_UNSET} if unknown. * @param position The position of the start of this frame in the stream. * @param mpegAudioHeader The MPEG audio header associated with the frame. * @param frame The data in this audio frame, with its position set to immediately after the * 'Xing' or 'Info' tag. * @return A {@link XingSeeker} for seeking in the stream, or {@code null} if the required * information is not present. */ public static XingSeeker create(long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame) { int samplesPerFrame = mpegAudioHeader.samplesPerFrame; int sampleRate = mpegAudioHeader.sampleRate; int flags = frame.readInt(); int frameCount; if ((flags & 0x01) != 0x01 || (frameCount = frame.readUnsignedIntToInt()) == 0) { // If the frame count is missing/invalid, the header can't be used to determine the duration. return null; } long durationUs = Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND, sampleRate); if ((flags & 0x06) != 0x06) { // If the size in bytes or table of contents is missing, the stream is not seekable. return new XingSeeker(position, mpegAudioHeader.frameSize, durationUs); } long dataSize = frame.readUnsignedIntToInt(); long[] tableOfContents = new long[100]; for (int i = 0; i < 100; i++) { tableOfContents[i] = frame.readUnsignedByte(); } // TODO: Handle encoder delay and padding in 3 bytes offset by xingBase + 213 bytes: // delay = (frame.readUnsignedByte() << 4) + (frame.readUnsignedByte() >> 4); // padding = ((frame.readUnsignedByte() & 0x0F) << 8) + frame.readUnsignedByte(); if (inputLength != C.LENGTH_UNSET && inputLength != position + dataSize) { Log.w(TAG, "XING data size mismatch: " + inputLength + ", " + (position + dataSize)); } return new XingSeeker(position, mpegAudioHeader.frameSize, durationUs, dataSize, tableOfContents); }
Example #13
Source File: Mp3Extractor.java From Telegram-FOSS with GNU General Public License v2.0 | 5 votes |
/** * @param flags Flags that control the extractor's behavior. * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or * {@link C#TIME_UNSET} if forcing is not required. */ public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) { this.flags = flags; this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs; scratch = new ParsableByteArray(SCRATCH_LENGTH); synchronizedHeader = new MpegAudioHeader(); gaplessInfoHolder = new GaplessInfoHolder(); basisTimeUs = C.TIME_UNSET; id3Peeker = new Id3Peeker(); }
Example #14
Source File: Mp3Extractor.java From Telegram-FOSS with GNU General Public License v2.0 | 5 votes |
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { if (sampleBytesRemaining == 0) { extractorInput.resetPeekPosition(); if (peekEndOfStreamOrHeader(extractorInput)) { return RESULT_END_OF_INPUT; } scratch.setPosition(0); int sampleHeaderData = scratch.readInt(); if (!headersMatch(sampleHeaderData, synchronizedHeaderData) || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) { // We have lost synchronization, so attempt to resynchronize starting at the next byte. extractorInput.skipFully(1); synchronizedHeaderData = 0; return RESULT_CONTINUE; } MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader); if (basisTimeUs == C.TIME_UNSET) { basisTimeUs = seeker.getTimeUs(extractorInput.getPosition()); if (forcedFirstSampleTimestampUs != C.TIME_UNSET) { long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0); basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs; } } sampleBytesRemaining = synchronizedHeader.frameSize; } int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true); if (bytesAppended == C.RESULT_END_OF_INPUT) { return RESULT_END_OF_INPUT; } sampleBytesRemaining -= bytesAppended; if (sampleBytesRemaining > 0) { return RESULT_CONTINUE; } long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate); trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0, null); samplesRead += synchronizedHeader.samplesPerFrame; sampleBytesRemaining = 0; return RESULT_CONTINUE; }
Example #15
Source File: Mp3Extractor.java From Telegram-FOSS with GNU General Public License v2.0 | 5 votes |
/** * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate. */ private Seeker getConstantBitrateSeeker(ExtractorInput input) throws IOException, InterruptedException { input.peekFully(scratch.data, 0, 4); scratch.setPosition(0); MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader); return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader); }
Example #16
Source File: XingSeeker.java From Telegram-FOSS with GNU General Public License v2.0 | 5 votes |
/** * Returns a {@link XingSeeker} for seeking in the stream, if required information is present. * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the * caller should reset it. * * @param inputLength The length of the stream in bytes, or {@link C#LENGTH_UNSET} if unknown. * @param position The position of the start of this frame in the stream. * @param mpegAudioHeader The MPEG audio header associated with the frame. * @param frame The data in this audio frame, with its position set to immediately after the * 'Xing' or 'Info' tag. * @return A {@link XingSeeker} for seeking in the stream, or {@code null} if the required * information is not present. */ public static @Nullable XingSeeker create( long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame) { int samplesPerFrame = mpegAudioHeader.samplesPerFrame; int sampleRate = mpegAudioHeader.sampleRate; int flags = frame.readInt(); int frameCount; if ((flags & 0x01) != 0x01 || (frameCount = frame.readUnsignedIntToInt()) == 0) { // If the frame count is missing/invalid, the header can't be used to determine the duration. return null; } long durationUs = Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND, sampleRate); if ((flags & 0x06) != 0x06) { // If the size in bytes or table of contents is missing, the stream is not seekable. return new XingSeeker(position, mpegAudioHeader.frameSize, durationUs); } long dataSize = frame.readUnsignedIntToInt(); long[] tableOfContents = new long[100]; for (int i = 0; i < 100; i++) { tableOfContents[i] = frame.readUnsignedByte(); } // TODO: Handle encoder delay and padding in 3 bytes offset by xingBase + 213 bytes: // delay = (frame.readUnsignedByte() << 4) + (frame.readUnsignedByte() >> 4); // padding = ((frame.readUnsignedByte() & 0x0F) << 8) + frame.readUnsignedByte(); if (inputLength != C.LENGTH_UNSET && inputLength != position + dataSize) { Log.w(TAG, "XING data size mismatch: " + inputLength + ", " + (position + dataSize)); } return new XingSeeker( position, mpegAudioHeader.frameSize, durationUs, dataSize, tableOfContents); }
Example #17
Source File: MpegAudioReader.java From Telegram with GNU General Public License v2.0 | 5 votes |
public MpegAudioReader(String language) { state = STATE_FINDING_HEADER; // The first byte of an MPEG Audio frame header is always 0xFF. headerScratch = new ParsableByteArray(4); headerScratch.data[0] = (byte) 0xFF; header = new MpegAudioHeader(); this.language = language; }
Example #18
Source File: MpegAudioReader.java From Telegram with GNU General Public License v2.0 | 5 votes |
/** * 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. */ private void readHeaderRemainder(ParsableByteArray source) { int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead); source.readBytes(headerScratch.data, frameBytesRead, bytesToRead); frameBytesRead += bytesToRead; if (frameBytesRead < HEADER_SIZE) { // We haven't read the whole header yet. return; } headerScratch.setPosition(0); boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header); 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 = Format.createAudioSampleFormat(formatId, header.mimeType, null, Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate, null, null, 0, language); output.format(format); hasOutputFormat = true; } headerScratch.setPosition(0); output.sampleData(headerScratch, HEADER_SIZE); state = STATE_READING_FRAME; }
Example #19
Source File: Mp3Extractor.java From Telegram with GNU General Public License v2.0 | 5 votes |
/** * @param flags Flags that control the extractor's behavior. * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or * {@link C#TIME_UNSET} if forcing is not required. */ public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) { this.flags = flags; this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs; scratch = new ParsableByteArray(SCRATCH_LENGTH); synchronizedHeader = new MpegAudioHeader(); gaplessInfoHolder = new GaplessInfoHolder(); basisTimeUs = C.TIME_UNSET; id3Peeker = new Id3Peeker(); }
Example #20
Source File: Mp3Extractor.java From Telegram with GNU General Public License v2.0 | 5 votes |
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { if (sampleBytesRemaining == 0) { extractorInput.resetPeekPosition(); if (peekEndOfStreamOrHeader(extractorInput)) { return RESULT_END_OF_INPUT; } scratch.setPosition(0); int sampleHeaderData = scratch.readInt(); if (!headersMatch(sampleHeaderData, synchronizedHeaderData) || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) { // We have lost synchronization, so attempt to resynchronize starting at the next byte. extractorInput.skipFully(1); synchronizedHeaderData = 0; return RESULT_CONTINUE; } MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader); if (basisTimeUs == C.TIME_UNSET) { basisTimeUs = seeker.getTimeUs(extractorInput.getPosition()); if (forcedFirstSampleTimestampUs != C.TIME_UNSET) { long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0); basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs; } } sampleBytesRemaining = synchronizedHeader.frameSize; } int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true); if (bytesAppended == C.RESULT_END_OF_INPUT) { return RESULT_END_OF_INPUT; } sampleBytesRemaining -= bytesAppended; if (sampleBytesRemaining > 0) { return RESULT_CONTINUE; } long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate); trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0, null); samplesRead += synchronizedHeader.samplesPerFrame; sampleBytesRemaining = 0; return RESULT_CONTINUE; }
Example #21
Source File: Mp3Extractor.java From Telegram with GNU General Public License v2.0 | 5 votes |
/** * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate. */ private Seeker getConstantBitrateSeeker(ExtractorInput input) throws IOException, InterruptedException { input.peekFully(scratch.data, 0, 4); scratch.setPosition(0); MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader); return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader); }
Example #22
Source File: XingSeeker.java From Telegram with GNU General Public License v2.0 | 5 votes |
/** * Returns a {@link XingSeeker} for seeking in the stream, if required information is present. * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the * caller should reset it. * * @param inputLength The length of the stream in bytes, or {@link C#LENGTH_UNSET} if unknown. * @param position The position of the start of this frame in the stream. * @param mpegAudioHeader The MPEG audio header associated with the frame. * @param frame The data in this audio frame, with its position set to immediately after the * 'Xing' or 'Info' tag. * @return A {@link XingSeeker} for seeking in the stream, or {@code null} if the required * information is not present. */ public static @Nullable XingSeeker create( long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame) { int samplesPerFrame = mpegAudioHeader.samplesPerFrame; int sampleRate = mpegAudioHeader.sampleRate; int flags = frame.readInt(); int frameCount; if ((flags & 0x01) != 0x01 || (frameCount = frame.readUnsignedIntToInt()) == 0) { // If the frame count is missing/invalid, the header can't be used to determine the duration. return null; } long durationUs = Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND, sampleRate); if ((flags & 0x06) != 0x06) { // If the size in bytes or table of contents is missing, the stream is not seekable. return new XingSeeker(position, mpegAudioHeader.frameSize, durationUs); } long dataSize = frame.readUnsignedIntToInt(); long[] tableOfContents = new long[100]; for (int i = 0; i < 100; i++) { tableOfContents[i] = frame.readUnsignedByte(); } // TODO: Handle encoder delay and padding in 3 bytes offset by xingBase + 213 bytes: // delay = (frame.readUnsignedByte() << 4) + (frame.readUnsignedByte() >> 4); // padding = ((frame.readUnsignedByte() & 0x0F) << 8) + frame.readUnsignedByte(); if (inputLength != C.LENGTH_UNSET && inputLength != position + dataSize) { Log.w(TAG, "XING data size mismatch: " + inputLength + ", " + (position + dataSize)); } return new XingSeeker( position, mpegAudioHeader.frameSize, durationUs, dataSize, tableOfContents); }
Example #23
Source File: Mp3Extractor.java From TelePlus-Android with GNU General Public License v2.0 | 5 votes |
/** * @param flags Flags that control the extractor's behavior. * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or * {@link C#TIME_UNSET} if forcing is not required. */ public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) { this.flags = flags; this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs; scratch = new ParsableByteArray(SCRATCH_LENGTH); synchronizedHeader = new MpegAudioHeader(); gaplessInfoHolder = new GaplessInfoHolder(); basisTimeUs = C.TIME_UNSET; id3Peeker = new Id3Peeker(); }
Example #24
Source File: MpegAudioReader.java From MediaSDK with Apache License 2.0 | 5 votes |
/** * 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. */ private void readHeaderRemainder(ParsableByteArray source) { int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead); source.readBytes(headerScratch.data, frameBytesRead, bytesToRead); frameBytesRead += bytesToRead; if (frameBytesRead < HEADER_SIZE) { // We haven't read the whole header yet. return; } headerScratch.setPosition(0); boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header); 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 = Format.createAudioSampleFormat(formatId, header.mimeType, null, Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate, null, null, 0, language); output.format(format); hasOutputFormat = true; } headerScratch.setPosition(0); output.sampleData(headerScratch, HEADER_SIZE); state = STATE_READING_FRAME; }
Example #25
Source File: Mp3Extractor.java From MediaSDK with Apache License 2.0 | 5 votes |
/** * @param flags Flags that control the extractor's behavior. * @param forcedFirstSampleTimestampUs A timestamp to force for the first sample, or * {@link C#TIME_UNSET} if forcing is not required. */ public Mp3Extractor(@Flags int flags, long forcedFirstSampleTimestampUs) { this.flags = flags; this.forcedFirstSampleTimestampUs = forcedFirstSampleTimestampUs; scratch = new ParsableByteArray(SCRATCH_LENGTH); synchronizedHeader = new MpegAudioHeader(); gaplessInfoHolder = new GaplessInfoHolder(); basisTimeUs = C.TIME_UNSET; id3Peeker = new Id3Peeker(); }
Example #26
Source File: Mp3Extractor.java From MediaSDK with Apache License 2.0 | 5 votes |
private int readSample(ExtractorInput extractorInput) throws IOException, InterruptedException { if (sampleBytesRemaining == 0) { extractorInput.resetPeekPosition(); if (peekEndOfStreamOrHeader(extractorInput)) { return RESULT_END_OF_INPUT; } scratch.setPosition(0); int sampleHeaderData = scratch.readInt(); if (!headersMatch(sampleHeaderData, synchronizedHeaderData) || MpegAudioHeader.getFrameSize(sampleHeaderData) == C.LENGTH_UNSET) { // We have lost synchronization, so attempt to resynchronize starting at the next byte. extractorInput.skipFully(1); synchronizedHeaderData = 0; return RESULT_CONTINUE; } MpegAudioHeader.populateHeader(sampleHeaderData, synchronizedHeader); if (basisTimeUs == C.TIME_UNSET) { basisTimeUs = seeker.getTimeUs(extractorInput.getPosition()); if (forcedFirstSampleTimestampUs != C.TIME_UNSET) { long embeddedFirstSampleTimestampUs = seeker.getTimeUs(0); basisTimeUs += forcedFirstSampleTimestampUs - embeddedFirstSampleTimestampUs; } } sampleBytesRemaining = synchronizedHeader.frameSize; } int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true); if (bytesAppended == C.RESULT_END_OF_INPUT) { return RESULT_END_OF_INPUT; } sampleBytesRemaining -= bytesAppended; if (sampleBytesRemaining > 0) { return RESULT_CONTINUE; } long timeUs = basisTimeUs + (samplesRead * C.MICROS_PER_SECOND / synchronizedHeader.sampleRate); trackOutput.sampleMetadata(timeUs, C.BUFFER_FLAG_KEY_FRAME, synchronizedHeader.frameSize, 0, null); samplesRead += synchronizedHeader.samplesPerFrame; sampleBytesRemaining = 0; return RESULT_CONTINUE; }
Example #27
Source File: Mp3Extractor.java From MediaSDK with Apache License 2.0 | 5 votes |
/** * Peeks the next frame and returns a {@link ConstantBitrateSeeker} based on its bitrate. */ private Seeker getConstantBitrateSeeker(ExtractorInput input) throws IOException, InterruptedException { input.peekFully(scratch.data, 0, 4); scratch.setPosition(0); MpegAudioHeader.populateHeader(scratch.readInt(), synchronizedHeader); return new ConstantBitrateSeeker(input.getLength(), input.getPosition(), synchronizedHeader); }
Example #28
Source File: XingSeeker.java From MediaSDK with Apache License 2.0 | 5 votes |
/** * Returns a {@link XingSeeker} for seeking in the stream, if required information is present. * Returns {@code null} if not. On returning, {@code frame}'s position is not specified so the * caller should reset it. * * @param inputLength The length of the stream in bytes, or {@link C#LENGTH_UNSET} if unknown. * @param position The position of the start of this frame in the stream. * @param mpegAudioHeader The MPEG audio header associated with the frame. * @param frame The data in this audio frame, with its position set to immediately after the * 'Xing' or 'Info' tag. * @return A {@link XingSeeker} for seeking in the stream, or {@code null} if the required * information is not present. */ public static @Nullable XingSeeker create( long inputLength, long position, MpegAudioHeader mpegAudioHeader, ParsableByteArray frame) { int samplesPerFrame = mpegAudioHeader.samplesPerFrame; int sampleRate = mpegAudioHeader.sampleRate; int flags = frame.readInt(); int frameCount; if ((flags & 0x01) != 0x01 || (frameCount = frame.readUnsignedIntToInt()) == 0) { // If the frame count is missing/invalid, the header can't be used to determine the duration. return null; } long durationUs = Util.scaleLargeTimestamp(frameCount, samplesPerFrame * C.MICROS_PER_SECOND, sampleRate); if ((flags & 0x06) != 0x06) { // If the size in bytes or table of contents is missing, the stream is not seekable. return new XingSeeker(position, mpegAudioHeader.frameSize, durationUs); } long dataSize = frame.readUnsignedIntToInt(); long[] tableOfContents = new long[100]; for (int i = 0; i < 100; i++) { tableOfContents[i] = frame.readUnsignedByte(); } // TODO: Handle encoder delay and padding in 3 bytes offset by xingBase + 213 bytes: // delay = (frame.readUnsignedByte() << 4) + (frame.readUnsignedByte() >> 4); // padding = ((frame.readUnsignedByte() & 0x0F) << 8) + frame.readUnsignedByte(); if (inputLength != C.LENGTH_UNSET && inputLength != position + dataSize) { Log.w(TAG, "XING data size mismatch: " + inputLength + ", " + (position + dataSize)); } return new XingSeeker( position, mpegAudioHeader.frameSize, durationUs, dataSize, tableOfContents); }
Example #29
Source File: MpegAudioReader.java From TelePlus-Android with GNU General Public License v2.0 | 5 votes |
public MpegAudioReader(String language) { state = STATE_FINDING_HEADER; // The first byte of an MPEG Audio frame header is always 0xFF. headerScratch = new ParsableByteArray(4); headerScratch.data[0] = (byte) 0xFF; header = new MpegAudioHeader(); this.language = language; }
Example #30
Source File: MpegAudioReader.java From TelePlus-Android with GNU General Public License v2.0 | 5 votes |
/** * 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. */ private void readHeaderRemainder(ParsableByteArray source) { int bytesToRead = Math.min(source.bytesLeft(), HEADER_SIZE - frameBytesRead); source.readBytes(headerScratch.data, frameBytesRead, bytesToRead); frameBytesRead += bytesToRead; if (frameBytesRead < HEADER_SIZE) { // We haven't read the whole header yet. return; } headerScratch.setPosition(0); boolean parsedHeader = MpegAudioHeader.populateHeader(headerScratch.readInt(), header); 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 = Format.createAudioSampleFormat(formatId, header.mimeType, null, Format.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, header.channels, header.sampleRate, null, null, 0, language); output.format(format); hasOutputFormat = true; } headerScratch.setPosition(0); output.sampleData(headerScratch, HEADER_SIZE); state = STATE_READING_FRAME; }