Skip to content

Commit

Permalink
Version 1.3.0 - just read changelog or something
Browse files Browse the repository at this point in the history
  • Loading branch information
sedmelluq committed Jun 2, 2018
1 parent 3586076 commit 2bf2f81
Show file tree
Hide file tree
Showing 133 changed files with 2,121 additions and 650 deletions.
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# Change Log

## [1.3.0] -- 2018-06-02
### Added
- Option for allocation-free frame provision pipeline by allowing to set NonAllocatingAudioFrameBuffer as the default frame buffer implementation and then using the new provide methods that take mutable audio frame instances.
- Ability to set SSL context for internally used HTTP clients. This allows for custom SSL providers such as Conscrypt.
- Support for custom output formats using custom implementations of AudioDataFormat.

### Changed
- Audio frame is now an interface, which is a breaking change for all use cases.
- Removed the concept of audio hooks.

### Fixed
- Some audio sources not freeing their HTTP clients when they were discarded.
- Potential NPE when the only node went down when a track was playing on it.
- Not closing OGG decoders created during track probing (still got closed on finalize).
- Missing Javadocs.

## [1.2.64] -- 2018-06-01
### Fixed
- Fixed WAV files with format header longer than 16 bytes not working.
Expand Down
4 changes: 2 additions & 2 deletions demo-d4j/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ repositories {
}

dependencies {
compile 'com.github.austinv11:Discord4j:2.9.3'
compile 'com.sedmelluq:lavaplayer:1.2.53'
compile 'com.github.austinv11:Discord4j:2.10.1'
compile 'com.sedmelluq:lavaplayer:1.3.0'
runtime 'ch.qos.logback:logback-classic:1.2.3'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public byte[] provide() {
lastFrame = audioPlayer.provide();
}

byte[] data = lastFrame != null ? lastFrame.data : null;
byte[] data = lastFrame != null ? lastFrame.getData() : null;
lastFrame = null;

return data;
Expand Down
4 changes: 2 additions & 2 deletions demo-jda/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ repositories {
}

dependencies {
compile 'net.dv8tion:JDA:3.6.0_354'
compile 'com.sedmelluq:lavaplayer:1.2.53'
compile 'net.dv8tion:JDA:3.6.0_369'
compile 'com.sedmelluq:lavaplayer:1.3.0'
runtime 'ch.qos.logback:logback-classic:1.2.3'
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public byte[] provide20MsAudio() {
lastFrame = audioPlayer.provide();
}

byte[] data = lastFrame != null ? lastFrame.data : null;
byte[] data = lastFrame != null ? lastFrame.getData() : null;
lastFrame = null;

return data;
Expand Down
2 changes: 1 addition & 1 deletion main/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

ext.moduleName = 'lavaplayer'
version = '1.2.64'
version = '1.3.0'

dependencies {
compile 'com.sedmelluq:lavaplayer-common:1.0.6'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Optional meta-information about a stream which may narrow down the list of possible containers.
*/
public class MediaContainerHints {
private static MediaContainerHints NO_INFORMATION = new MediaContainerHints(null, null);
private static final MediaContainerHints NO_INFORMATION = new MediaContainerHints(null, null);

/**
* Mime type, null if not known.
Expand All @@ -20,6 +20,9 @@ private MediaContainerHints(String mimeType, String fileExtension) {
this.fileExtension = fileExtension;
}

/**
* @return <code>true</code> if any hint parameters have a value.
*/
public boolean present() {
return mimeType != null || fileExtension != null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public interface MediaContainerProbe {
* @return Returns result with audio track on supported format, result with unsupported reason set if this is the
* container that the file uses, but this specific file uses a format or codec that is not supported. Returns
* null in case this file does not appear to be using this container format.
* @throws IOException On read error.
*/
MediaContainerDetectionResult probe(AudioReference reference, SeekableInputStream inputStream) throws IOException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ public class AdtsStreamProvider {
private ShortBuffer outputBuffer;
private AdtsPacketHeader previousHeader;
private AudioPipeline downstream;
private Long requestedTimecode;
private Long providedTimecode;

/**
* @param inputStream Input stream to read from.
* @param context Audio processing context.
* @param context Configuration and output information for processing
*/
public AdtsStreamProvider(InputStream inputStream, AudioProcessingContext context) {
this.context = context;
Expand All @@ -39,9 +41,21 @@ public AdtsStreamProvider(InputStream inputStream, AudioProcessingContext contex
this.directBufferBroker = new DirectBufferStreamBroker(2048);
}

/**
* Used to pass the initial position of the stream in case it is part of a chain, to keep timecodes of audio frames
* continuous.
*
* @param requestedTimecode The timecode at which the samples from this stream should be outputted.
* @param providedTimecode The timecode at which this stream starts.
*/
public void setInitialSeek(long requestedTimecode, long providedTimecode) {
this.requestedTimecode = requestedTimecode;
this.providedTimecode = providedTimecode;
}

/**
* Provides frames to the frame consumer.
* @throws InterruptedException
* @throws InterruptedException When interrupted externally (or for seek/stop).
*/
public void provideFrames() throws InterruptedException {
try {
Expand Down Expand Up @@ -84,6 +98,11 @@ private void decodeAndSend(ByteBuffer inputBuffer) throws InterruptedException {
downstream = AudioPipelineFactory.create(context, new PcmFormat(streamInfo.channels, streamInfo.sampleRate));
outputBuffer = ByteBuffer.allocateDirect(2 * streamInfo.frameSize * streamInfo.channels)
.order(ByteOrder.nativeOrder()).asShortBuffer();

if (requestedTimecode != null) {
downstream.seekPerformed(requestedTimecode, providedTimecode);
requestedTimecode = null;
}
}

outputBuffer.clear();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
import com.sedmelluq.discord.lavaplayer.filter.PcmFormat;
import com.sedmelluq.discord.lavaplayer.filter.volume.AudioFrameVolumeChanger;
import com.sedmelluq.discord.lavaplayer.format.AudioDataFormat;
import com.sedmelluq.discord.lavaplayer.format.OpusAudioDataFormat;
import com.sedmelluq.discord.lavaplayer.natives.opus.OpusDecoder;
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
import com.sedmelluq.discord.lavaplayer.track.playback.AudioProcessingContext;
import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -27,6 +28,7 @@ public class OpusPacketRouter {
private final int inputFrequency;
private final int inputChannels;
private final byte[] headerBytes;
private final MutableAudioFrame offeredFrame;

private long currentTimecode;
private OpusDecoder opusDecoder;
Expand All @@ -37,7 +39,7 @@ public class OpusPacketRouter {
private int lastFrameSize;

/**
* @param context Configuration and output information for processing audio
* @param context Configuration and output information for processing
* @param inputFrequency Sample rate of the opus track
* @param inputChannels Number of channels in the opus track
*/
Expand All @@ -46,7 +48,11 @@ public OpusPacketRouter(AudioProcessingContext context, int inputFrequency, int
this.inputFrequency = inputFrequency;
this.inputChannels = inputChannels;
this.headerBytes = new byte[2];
this.offeredFrame = new MutableAudioFrame();
this.lastFrameSize = 0;

offeredFrame.setVolume(100);
offeredFrame.setFormat(context.outputFormat);
}

/**
Expand All @@ -65,7 +71,7 @@ public void seekPerformed(long requestedTimecode, long providedTimecode) {

/**
* Indicates that no more input is coming. Flush any buffers to output.
* @throws InterruptedException
* @throws InterruptedException When interrupted externally (or for seek/stop).
*/
public void flush() throws InterruptedException {
if (downstream != null) {
Expand All @@ -76,7 +82,7 @@ public void flush() throws InterruptedException {
/**
* Process one opus packet.
* @param buffer Byte buffer of the packet
* @throws InterruptedException
* @throws InterruptedException When interrupted externally (or for seek/stop).
*/
public void process(ByteBuffer buffer) throws InterruptedException {
int frameSize = processFrameSize(buffer);
Expand Down Expand Up @@ -118,7 +124,7 @@ private int processFrameSize(ByteBuffer buffer) {
return 0;
} else if (frameSize != lastFrameSize) {
lastFrameSize = frameSize;
inputFormat = new AudioDataFormat(inputChannels, inputFrequency, frameSize, AudioDataFormat.Codec.OPUS);
inputFormat = new OpusAudioDataFormat(inputChannels, inputFrequency, frameSize);
}

currentTimecode += frameSize * 1000 / inputFrequency;
Expand Down Expand Up @@ -154,10 +160,10 @@ private void passDownstream(ByteBuffer buffer, int frameSize) throws Interrupted
}

private void passThrough(ByteBuffer buffer) throws InterruptedException {
byte[] bytes = new byte[buffer.remaining()];
buffer.get(bytes);
offeredFrame.setTimecode(currentTimecode);
offeredFrame.setBuffer(buffer);

context.frameConsumer.consume(new AudioFrame(currentTimecode, bytes, 100, inputFormat));
context.frameBuffer.consume(offeredFrame);
}

private void checkDecoderNecessity() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public FlacTrackProvider(AudioProcessingContext context, FlacTrackInfo info, See

/**
* Decodes audio frames and sends them to frame consumer
* @throws InterruptedException
* @throws InterruptedException When interrupted externally (or for seek/stop).
*/
public void provideFrames() throws InterruptedException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public class FlacFrameHeaderReader {
* @param variableBlock If this is a variable block header. This information was included in the frame sync bytes
* consumed before calling this method.
* @return The frame information.
* @throws IOException
* @throws IOException On read error.
*/
public static FlacFrameInfo readFrameHeader(BitStreamReader bitStreamReader, FlacStreamInfo streamInfo,
boolean variableBlock) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,21 +116,9 @@ private static void applyMidDelta(int[][] rawSampleBuffers, int sampleCount) {

private static void convertToShortPcm(FlacStreamInfo streamInfo, int sampleCount, int[][] rawSampleBuffers, short[][] sampleBuffers) {
if (streamInfo.bitsPerSample < 16) {
int shiftLeft = 16 - streamInfo.bitsPerSample;

for (int channel = 0; channel < streamInfo.channelCount; channel++) {
for (int i = 0; i < sampleCount; i++) {
sampleBuffers[channel][i] = (short) (rawSampleBuffers[channel][i] << shiftLeft);
}
}
increaseSampleSize(streamInfo, sampleCount, rawSampleBuffers, sampleBuffers);
} else if (streamInfo.bitsPerSample > 16) {
int shiftRight = streamInfo.bitsPerSample - 16;

for (int channel = 0; channel < streamInfo.channelCount; channel++) {
for (int i = 0; i < sampleCount; i++) {
sampleBuffers[channel][i] = (short) (rawSampleBuffers[channel][i] >> shiftRight);
}
}
decreaseSampleSize(streamInfo, sampleCount, rawSampleBuffers, sampleBuffers);
} else {
for (int channel = 0; channel < streamInfo.channelCount; channel++) {
for (int i = 0; i < sampleCount; i++) {
Expand All @@ -139,4 +127,24 @@ private static void convertToShortPcm(FlacStreamInfo streamInfo, int sampleCount
}
}
}

private static void increaseSampleSize(FlacStreamInfo streamInfo, int sampleCount, int[][] rawSampleBuffers, short[][] sampleBuffers) {
int shiftLeft = 16 - streamInfo.bitsPerSample;

for (int channel = 0; channel < streamInfo.channelCount; channel++) {
for (int i = 0; i < sampleCount; i++) {
sampleBuffers[channel][i] = (short) (rawSampleBuffers[channel][i] << shiftLeft);
}
}
}

private static void decreaseSampleSize(FlacStreamInfo streamInfo, int sampleCount, int[][] rawSampleBuffers, short[][] sampleBuffers) {
int shiftRight = streamInfo.bitsPerSample - 16;

for (int channel = 0; channel < streamInfo.channelCount; channel++) {
for (int i = 0; i < sampleCount; i++) {
sampleBuffers[channel][i] = (short) (rawSampleBuffers[channel][i] >> shiftRight);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ public MatroskaFileTrack[] getTrackList() {

/**
* Read the headers and tracks from the file.
*
* @throws IOException On read error.
*/
public void readFile() throws IOException {
MatroskaElement ebmlElement = reader.readNextElement(null);
Expand Down Expand Up @@ -282,7 +284,7 @@ private MatroskaCuePoint lastCueNotAfterTimecode(long timecode) {
/**
* Provide data chunks for the specified track consumer
* @param consumer Track data consumer
* @throws InterruptedException
* @throws InterruptedException When interrupted externally (or for seek/stop).
*/
public void provideFrames(MatroskaTrackConsumer consumer) throws InterruptedException {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ public interface MatroskaTrackConsumer {

/**
* Indicates that no more input will come, all remaining buffers should be flushed
* @throws InterruptedException
*
* @throws InterruptedException When interrupted externally (or for seek/stop).
*/
void flush() throws InterruptedException;

/**
* Consume one frame from the track
*
* @param data The data of the frame
* @throws InterruptedException
* @throws InterruptedException When interrupted externally (or for seek/stop).
*/
void consume(ByteBuffer data) throws InterruptedException;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import java.io.IOException;
import java.nio.ByteBuffer;

/**
* Provides information and buffer to read from for a Matroska block.
*/
public interface MatroskaBlock {
/**
* @return The timecode of this block relative to its cluster
Expand All @@ -27,9 +30,11 @@ public interface MatroskaBlock {
/**
* The reader must already be positioned at the frame that is to be read next.
*
* @param reader The reader to use to read the block contents into a buffer.
* @param index The index of the frame to get the buffer for.
* @return A buffer where the range between position and limit contains the data for the specific frame. The contents
* of this buffer are only valid until the next call to this method.
* @throws IOException On read error.
*/
ByteBuffer getNextFrameBuffer(MatroskaFileReader reader, int index) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ public MatroskaElement readNextElement(MatroskaElement parent) throws IOExceptio
return element;
}

/**
* Reads one Matroska block header. The data is of the block is not read, but can be read frame by frame using
* {@link MatroskaBlock#getNextFrameBuffer(MatroskaFileReader, int)}.
*
* @param parent The block parent element.
* @param trackFilter The ID of the track to read data for from the block.
* @return An instance of a block if it contains data for the requested track, <code>null</code> otherwise.
* @throws IOException On read error.
*/
public MatroskaBlock readBlockHeader(MatroskaElement parent, int trackFilter) throws IOException {
if (!mutableBlock.parseHeader(this, parent, trackFilter)) {
return null;
Expand Down
Loading

0 comments on commit 2bf2f81

Please sign in to comment.