package net.pms.util; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.io.OutputStream; public class DTSAudioOutputStream extends FlowParserOutputStream { private static final Logger logger = LoggerFactory.getLogger(DTSAudioOutputStream.class); private static int bits[] = new int[]{16, 16, 20, 20, 0, 24, 24}; private boolean dts = false; private boolean dtsHD = false; private int framesize; private OutputStream out; private int padding; public DTSAudioOutputStream(OutputStream out) { super(out, 600000); if (out instanceof PCMAudioOutputStream) { PCMAudioOutputStream pout = (PCMAudioOutputStream) out; pout.swapOrderBits = 0; } this.out = out; neededByteNumber = 15; } @Override protected void afterChunkSend() throws IOException { padWithZeros(padding); } @Override protected void analyzeBuffer(byte[] data, int off, int len) { if (data[off + 0] == 100 && data[off + 1] == 88 && data[off + 2] == 32 && data[off + 3] == 37) { dtsHD = true; streamableByteNumber = ((data[off + 6] & 0x0f) << 11) + ((data[off + 7] & 0xff) << 3) + ((data[off + 8] & 0xf0) >> 5) + 1; discard = true; } else if (data[off + 0] == 127 && data[off + 1] == -2 && data[off + 2] == -128 && data[off + 3] == 1) { discard = false; dts = true; streamableByteNumber = framesize; if (framesize == 0) { framesize = ((data[off + 5] & 0x03) << 12) + ((data[off + 6] & 0xff) << 4) + ((data[off + 7] & 0xf0) >> 4) + 1; int bitspersample = ((data[off + 11] & 0x01) << 2) + ((data[off + 12] & 0xfc) >> 6); streamableByteNumber = framesize; //reset of default values int pcm_wrapped_frame_size = 2048; if (out instanceof PCMAudioOutputStream) { PCMAudioOutputStream pout = (PCMAudioOutputStream) out; pout.nbchannels = 2; pout.sampleFrequency = 48000; pout.bitsperSample = 16; pout.init(); } padding = pcm_wrapped_frame_size - framesize; if (bitspersample < 7) { logger.trace("DTS bits per sample: " + bits[bitspersample]); } logger.trace("DTS framesize: " + framesize); } } else { // DTS wrongly extracted ?... searching for start of the frame for (int i = 3; i < 2020; i++) { if (data.length > i && data[i - 3] == 127 && data[i - 2] == -2 && data[i - 1] == -128 && data[i] == 1) { // skip DTS first frame as it's incomplete discard = true; streamableByteNumber = i - 3; break; } else if (data.length > i && data[i - 3] == 100 && data[i - 2] == 88 && data[i - 1] == 32 && data[i] == 37) { // skip DTS-HD first frame discard = true; streamableByteNumber = i - 3; break; } } } } @Override protected void beforeChunkSend() throws IOException { } public boolean isDts() { return dts; } public boolean isDtsHD() { return dtsHD; } }