@Override public int sampleData(ExtractorInput input, int length, boolean allowEndOfInput) throws IOException, InterruptedException { return rollingBuffer.appendData(input, length, allowEndOfInput); }
/** * Clears the queue, returning all allocations to the allocator. */ public void clear() { rollingBuffer.clear(); needKeyframe = true; lastReadTimeUs = Long.MIN_VALUE; spliceOutTimeUs = Long.MIN_VALUE; largestParsedTimestampUs = Long.MIN_VALUE; }
@Override public void sampleMetadata(long timeUs, int flags, int size, int offset, byte[] encryptionKey) { largestParsedTimestampUs = Math.max(largestParsedTimestampUs, timeUs); rollingBuffer.commitSample(timeUs, flags, rollingBuffer.getWritePosition() - size - offset, size, encryptionKey); }
/** * Discards samples from the write side of the queue. * * @param discardFromIndex The absolute index of the first sample to be discarded. */ public void discardUpstreamSamples(int discardFromIndex) { rollingBuffer.discardUpstreamSamples(discardFromIndex); largestParsedTimestampUs = rollingBuffer.peekSample(sampleInfoHolder) ? sampleInfoHolder.timeUs : Long.MIN_VALUE; }
/** * Reads the current sample, advancing the read index to the next sample. * * @param sampleHolder The holder into which the current sample should be written. * @return True if a sample was read. False if there is no current sample. */ public boolean readSample(SampleHolder sampleHolder) { // Write the sample information into the holder and extrasHolder. boolean haveSample = infoQueue.peekSample(sampleHolder, extrasHolder); if (!haveSample) { return false; } // Read encryption data if the sample is encrypted. if (sampleHolder.isEncrypted()) { readEncryptionData(sampleHolder, extrasHolder); } // Write the sample data into the holder. if (sampleHolder.data == null || sampleHolder.data.capacity() < sampleHolder.size) { sampleHolder.replaceBuffer(sampleHolder.size); } if (sampleHolder.data != null) { readData(extrasHolder.offset, sampleHolder.data, sampleHolder.size); } // Advance the read head. long nextOffset = infoQueue.moveToNextSample(); dropDownstreamTo(nextOffset); return true; }
readData(offset, scratch.data, 1); offset++; byte signalByte = scratch.data[0]; sampleHolder.cryptoInfo.iv = new byte[16]; readData(offset, sampleHolder.cryptoInfo.iv, ivSize); offset += ivSize; readData(offset, scratch.data, 2); offset += 2; scratch.setPosition(0); ensureCapacity(scratch, subsampleDataLength); readData(offset, scratch.data, subsampleDataLength); offset += subsampleDataLength; scratch.setPosition(0);
/** * Attempts to skip to the keyframe before the specified time, if it's present in the buffer. * * @param timeUs The seek time. * @return True if the skip was successful. False otherwise. */ public boolean skipToKeyframeBefore(long timeUs) { long nextOffset = infoQueue.skipToKeyframeBefore(timeUs); if (nextOffset == -1) { return false; } dropDownstreamTo(nextOffset); return true; }
/** * Returns the current absolute write index. */ public int getWriteIndex() { return rollingBuffer.getWriteIndex(); }
/** * Returns the current absolute read index. */ public int getReadIndex() { return rollingBuffer.getReadIndex(); }
/** * @param allocator An {@link Allocator} from which allocations for sample data can be obtained. */ public DefaultTrackOutput(Allocator allocator) { rollingBuffer = new RollingSampleBuffer(allocator); sampleInfoHolder = new SampleHolder(SampleHolder.BUFFER_REPLACEMENT_MODE_DISABLED); needKeyframe = true; lastReadTimeUs = Long.MIN_VALUE; spliceOutTimeUs = Long.MIN_VALUE; largestParsedTimestampUs = Long.MIN_VALUE; }
/** * Discards samples from the write side of the buffer. * * @param discardFromIndex The absolute index of the first sample to be discarded. */ public void discardUpstreamSamples(int discardFromIndex) { totalBytesWritten = infoQueue.discardUpstreamSamples(discardFromIndex); dropUpstreamFrom(totalBytesWritten); }
/** * Skips the current sample. */ public void skipSample() { long nextOffset = infoQueue.moveToNextSample(); dropDownstreamTo(nextOffset); }
/** * Reads data from the front of the rolling buffer. * * @param absolutePosition The absolute position from which data should be read. * @param target The buffer into which data should be written. * @param length The number of bytes to read. */ private void readData(long absolutePosition, ByteBuffer target, int length) { int remaining = length; while (remaining > 0) { dropDownstreamTo(absolutePosition); int positionInAllocation = (int) (absolutePosition - totalBytesDropped); int toCopy = Math.min(remaining, allocationLength - positionInAllocation); Allocation allocation = dataQueue.peek(); target.put(allocation.data, allocation.translateOffset(positionInAllocation), toCopy); absolutePosition += toCopy; remaining -= toCopy; } }
@Override public void sampleData(ParsableByteArray buffer, int length) { rollingBuffer.appendData(buffer, length); }
/** * Reads data from the front of the rolling buffer. * * @param absolutePosition The absolute position from which data should be read. * @param target The array into which data should be written. * @param length The number of bytes to read. */ // TODO: Consider reducing duplication of this method and the one above. private void readData(long absolutePosition, byte[] target, int length) { int bytesRead = 0; while (bytesRead < length) { dropDownstreamTo(absolutePosition); int positionInAllocation = (int) (absolutePosition - totalBytesDropped); int toCopy = Math.min(length - bytesRead, allocationLength - positionInAllocation); Allocation allocation = dataQueue.peek(); System.arraycopy(allocation.data, allocation.translateOffset(positionInAllocation), target, bytesRead, toCopy); absolutePosition += toCopy; bytesRead += toCopy; } }
/** * Invoked to write sample data to the output. * * @param dataSource A {@link DataSource} from which to read the sample data. * @param length The maximum length to read from the input. * @param allowEndOfInput True if encountering the end of the input having read no data is * allowed, and should result in {@link C#RESULT_END_OF_INPUT} being returned. False if it * should be considered an error, causing an {@link EOFException} to be thrown. * @return The number of bytes appended. * @throws IOException If an error occurred reading from the input. */ public int sampleData(DataSource dataSource, int length, boolean allowEndOfInput) throws IOException { return rollingBuffer.appendData(dataSource, length, allowEndOfInput); }