public SeiReader(TrackOutput output) { super(output); output.format(MediaFormat.createTextFormat(MimeTypes.APPLICATION_EIA608, MediaFormat.NO_VALUE, null)); }
/** * Attempts to read the remainder of the frame. * <p> * If a frame is read in full then true is returned. The frame will have been output, and the * position of the source will have been advanced to the byte that immediately follows the end of * the frame. * <p> * If a frame is not read in full then the position of the source will have been 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 readFrameRemainder(ParsableByteArray source) { int bytesToRead = Math.min(source.bytesLeft(), frameSize - frameBytesRead); output.sampleData(source, bytesToRead); frameBytesRead += bytesToRead; if (frameBytesRead < frameSize) { // We haven't read the whole of the frame yet. return; } output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, frameSize, 0, null); timeUs += frameDurationUs; frameBytesRead = 0; state = STATE_FINDING_HEADER; }
MediaFormat.NO_VALUE, MpegAudioHeader.MAX_FRAME_SIZE_BYTES, C.UNKNOWN_TIME_US, header.channels, header.sampleRate, null); output.format(mediaFormat); hasOutputFormat = true; output.sampleData(headerScratch, HEADER_SIZE); state = STATE_READING_FRAME;
/** * Outputs up to {@code length} bytes of sample data to {@code output}, consisting of either * {@link #sampleStrippedBytes} or data read from {@code input}. */ private int readToOutput(ExtractorInput input, TrackOutput output, int length) throws IOException, InterruptedException { int bytesRead; int strippedBytesLeft = sampleStrippedBytes.bytesLeft(); if (strippedBytesLeft > 0) { bytesRead = Math.min(length, strippedBytesLeft); output.sampleData(sampleStrippedBytes, bytesRead); } else { bytesRead = output.sampleData(input, length, false); } sampleBytesRead += bytesRead; sampleBytesWritten += bytesRead; return bytesRead; }
private void outputSample(int offset) { int flags = sampleIsKeyframe ? C.SAMPLE_FLAG_SYNC : 0; int size = (int) (nalUnitStartPosition - samplePosition); output.sampleMetadata(sampleTimeUs, flags, size, offset, null); }
/** * Drains as much buffered data as possible up to {@code length} bytes to {@code trackOutput}. * * @param trackOutput Track output to populate with up to {@code length} bytes of sample data. * @param length Number of bytes to try to read from the buffer. * @return The number of buffered bytes written. */ public int drainToOutput(TrackOutput trackOutput, int length) { if (length == 0) { return 0; } buffer.setPosition(readPosition); int bytesToDrain = Math.min(writePosition - readPosition, length); trackOutput.sampleData(buffer, bytesToDrain); readPosition += bytesToDrain; return bytesToDrain; }
@Override public void packetFinished() { output.sampleMetadata(sampleTimeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null); writingSample = false; }
parseHeader(); headerScratchBytes.setPosition(0); output.sampleData(headerScratchBytes, HEADER_SIZE); state = STATE_READING_SAMPLE; case STATE_READING_SAMPLE: int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead); output.sampleData(data, bytesToRead); bytesRead += bytesToRead; if (bytesRead == sampleSize) { output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null); timeUs += frameDurationUs; state = STATE_FINDING_SYNC;
public Id3Reader(TrackOutput output) { super(output); output.format(MediaFormat.createFormatForMimeType(MimeTypes.APPLICATION_ID3, MediaFormat.NO_VALUE)); }
private int appendSampleEncryptionData(ParsableByteArray sampleEncryptionData) { TrackEncryptionBox encryptionBox = track.sampleDescriptionEncryptionBoxes[fragmentRun.sampleDescriptionIndex]; int vectorSize = encryptionBox.initializationVectorSize; boolean subsampleEncryption = fragmentRun.sampleHasSubsampleEncryptionTable[sampleIndex]; // Write the signal byte, containing the vector size and the subsample encryption flag. encryptionSignalByte.data[0] = (byte) (vectorSize | (subsampleEncryption ? 0x80 : 0)); encryptionSignalByte.setPosition(0); trackOutput.sampleData(encryptionSignalByte, 1); // Write the vector. trackOutput.sampleData(sampleEncryptionData, vectorSize); // If we don't have subsample encryption data, we're done. if (!subsampleEncryption) { return 1 + vectorSize; } // Write the subsample encryption data. int subsampleCount = sampleEncryptionData.readUnsignedShort(); sampleEncryptionData.skipBytes(-2); int subsampleDataLength = 2 + 6 * subsampleCount; trackOutput.sampleData(sampleEncryptionData, subsampleDataLength); return 1 + vectorSize + subsampleDataLength; }
private void commitSampleToOutput(Track track, long timeUs) { if (CODEC_ID_SUBRIP.equals(track.codecId)) { writeSubripSample(track); } track.output.sampleMetadata(timeUs, blockFlags, sampleBytesWritten, 0, track.encryptionKeyId); sampleRead = true; resetSample(); }
@Override public void consume(ParsableByteArray seiBuffer, long pesTimeUs, boolean startOfPacket) { int b; while (seiBuffer.bytesLeft() > 1 /* last byte will be rbsp_trailing_bits */) { // Parse payload type. int payloadType = 0; do { b = seiBuffer.readUnsignedByte(); payloadType += b; } while (b == 0xFF); // Parse payload size. int payloadSize = 0; do { b = seiBuffer.readUnsignedByte(); payloadSize += b; } while (b == 0xFF); // Process the payload. We only support EIA-608 payloads currently. if (Eia608Parser.isSeiMessageEia608(payloadType, payloadSize, seiBuffer)) { output.sampleData(seiBuffer, payloadSize); output.sampleMetadata(pesTimeUs, C.SAMPLE_FLAG_SYNC, payloadSize, 0, null); } else { seiBuffer.skipBytes(payloadSize); } } }
private void parseMediaFormat(NalUnitTargetBuffer sps, NalUnitTargetBuffer pps) { byte[] spsData = new byte[sps.nalLength]; byte[] ppsData = new byte[pps.nalLength]; System.arraycopy(sps.nalData, 0, spsData, 0, sps.nalLength); System.arraycopy(pps.nalData, 0, ppsData, 0, pps.nalLength); List<byte[]> initializationData = new ArrayList<>(); initializationData.add(spsData); initializationData.add(ppsData); // Unescape and parse the SPS unit. NalUnitUtil.unescapeStream(sps.nalData, sps.nalLength); ParsableBitArray bitArray = new ParsableBitArray(sps.nalData); bitArray.skipBits(32); // NAL header SpsData parsedSpsData = CodecSpecificDataUtil.parseSpsNalUnit(bitArray); // Construct and output the format. output.format(MediaFormat.createVideoFormat(MimeTypes.VIDEO_H264, MediaFormat.NO_VALUE, MediaFormat.NO_VALUE, C.UNKNOWN_TIME_US, parsedSpsData.width, parsedSpsData.height, 0, parsedSpsData.pixelWidthAspectRatio, initializationData)); hasOutputFormat = true; }
@Override public void consume(ParsableByteArray data, long pesTimeUs, boolean startOfPacket) { if (startOfPacket) { writingSample = true; sampleTimeUs = pesTimeUs; sampleSize = 0; } if (writingSample) { sampleSize += data.bytesLeft(); output.sampleData(data, data.bytesLeft()); } }
case STATE_READING_SAMPLE: int bytesToRead = Math.min(data.bytesLeft(), sampleSize - bytesRead); output.sampleData(data, bytesToRead); bytesRead += bytesToRead; if (bytesRead == sampleSize) { output.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, sampleSize, 0, null); timeUs += frameDurationUs; bytesRead = 0;
/** * Parses the sample header. */ private void parseHeader() { headerScratchBits.setPosition(0); sampleSize = Ac3Util.parseFrameSize(headerScratchBits); if (mediaFormat == null) { headerScratchBits.setPosition(0); mediaFormat = Ac3Util.parseFrameAc3Format(headerScratchBits); output.format(mediaFormat); bitrate = Ac3Util.getBitrate(sampleSize, mediaFormat.sampleRate); } frameDurationUs = (int) (1000L * 8 * sampleSize / bitrate); }
private void writeSubripSample(Track track) { setSubripSampleEndTimecode(subripSample.data, blockDurationUs); // Note: If we ever want to support DRM protected subtitles then we'll need to output the // appropriate encryption data here. track.output.sampleData(subripSample, subripSample.limit()); sampleBytesWritten += subripSample.limit(); }
if (sampleBytesRemaining > 0) { inputBuffer.mark(); int bytesAppended = trackOutput.sampleData(extractorInput, sampleBytesRemaining, true); if (bytesAppended == C.RESULT_END_OF_INPUT) { return RESULT_END_OF_INPUT; trackOutput.sampleMetadata(timeUs, C.SAMPLE_FLAG_SYNC, synchronizedHeader.frameSize, 0, null); samplesRead += synchronizedHeader.samplesPerFrame; sampleBytesRemaining = 0;
this.output.format(format);
scratch.data[0] = (byte) ENCRYPTION_IV_SIZE; scratch.setPosition(0); output.sampleData(scratch, 1); sampleBytesWritten++; blockFlags |= C.SAMPLE_FLAG_ENCRYPTED; output.sampleData(nalStartCode, 4); sampleBytesWritten += 4; } else { output.sampleData(vorbisNumPageSamples, 4); sampleBytesWritten += 4;