www in docker support

This commit is contained in:
MaddoScientisto 2026-04-22 18:41:37 +02:00
commit c227fce036
2145 changed files with 399596 additions and 58 deletions

View file

@ -0,0 +1,253 @@
package org.jcodec.containers.mp3;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import org.jcodec.common.AudioCodecMeta;
import org.jcodec.common.Codec;
import org.jcodec.common.Demuxer;
import org.jcodec.common.DemuxerTrack;
import org.jcodec.common.DemuxerTrackMeta;
import org.jcodec.common.TrackType;
import org.jcodec.common.UsedViaReflection;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.common.logging.Logger;
import org.jcodec.common.model.Packet;
public class MPEGAudioDemuxer implements Demuxer, DemuxerTrack {
private static final int MAX_FRAME_SIZE = 1728;
private static final int MIN_FRAME_SIZE = 52;
private static int field(int off, int size) {
return (1 << size) - 1 << 16 | off;
}
private static final int CHANNELS = field(6, 2);
private static final int PADDING = field(9, 1);
private static final int SAMPLE_RATE = field(10, 2);
private static final int BITRATE = field(12, 4);
private static final int VERSION = field(19, 2);
private static final int LAYER = field(17, 2);
private static final int SYNC = field(21, 11);
private static final int MPEG1 = 3;
private static final int MPEG2 = 2;
private static final int MPEG25 = 0;
private static int[][][] bitrateTable = new int[][][] { new int[][] { new int[] {
0, 32, 64, 96, 128, 160, 192, 224, 256, 288,
320, 352, 384, 416, 448 }, new int[] {
0, 32, 48, 56, 64, 80, 96, 112, 128, 160,
192, 224, 256, 320, 384 }, new int[] {
0, 32, 40, 48, 56, 64, 80, 96, 112, 128,
160, 192, 224, 256, 320 } }, new int[][] { new int[] {
0, 32, 48, 56, 64, 80, 96, 112, 128, 144,
160, 176, 192, 224, 256 }, new int[] {
0, 8, 16, 24, 32, 40, 48, 56, 64, 80,
96, 112, 128, 144, 160 }, new int[] {
0, 8, 16, 24, 32, 40, 48, 56, 64, 80,
96, 112, 128, 144, 160 } } };
private static int[] freqTab = new int[] { 44100, 48000, 32000 };
private static int[] rateReductTab = new int[] { 2, 0, 1, 0 };
private SeekableByteChannel ch;
private List<DemuxerTrack> tracks;
private int frameNo;
private ByteBuffer readBuffer;
private int runningFour;
private boolean eof;
private DemuxerTrackMeta meta;
private int sampleRate;
private static int getField(int header, int field) {
return header >> (field & 0xFFFF) & field >> 16;
}
public MPEGAudioDemuxer(SeekableByteChannel ch) throws IOException {
this.ch = ch;
this.readBuffer = ByteBuffer.allocate(262144);
readMoreData();
if (this.readBuffer.remaining() < 4) {
this.eof = true;
} else {
this.runningFour = this.readBuffer.getInt();
if (!validHeader(this.runningFour))
this.eof = skipJunk();
extractMeta();
}
this.tracks = new ArrayList<>();
this.tracks.add(this);
}
private void extractMeta() {
if (!validHeader(this.runningFour))
return;
int layer = 3 - getField(this.runningFour, LAYER);
int channelCount = (getField(this.runningFour, CHANNELS) == 3) ? 1 : 2;
int version = getField(this.runningFour, VERSION);
this.sampleRate = freqTab[getField(this.runningFour, SAMPLE_RATE)] >> rateReductTab[version];
AudioCodecMeta codecMeta = AudioCodecMeta.createAudioCodecMeta(".mp3", 16, channelCount, this.sampleRate, ByteOrder.LITTLE_ENDIAN, false, null, null);
Codec codec = (layer == 2) ? Codec.MP3 : ((layer == 1) ? Codec.MP2 : Codec.MP1);
this.meta = new DemuxerTrackMeta(TrackType.AUDIO, codec, 0.0D, null, 0, null, null, codecMeta);
}
public void close() throws IOException {
this.ch.close();
}
public List<? extends DemuxerTrack> getTracks() {
return this.tracks;
}
public List<? extends DemuxerTrack> getVideoTracks() {
return null;
}
public List<? extends DemuxerTrack> getAudioTracks() {
return this.tracks;
}
public Packet nextFrame() throws IOException {
if (this.eof)
return null;
if (!validHeader(this.runningFour))
this.eof = skipJunk();
int frameSize = calcFrameSize(this.runningFour);
ByteBuffer frame = ByteBuffer.allocate(frameSize);
this.eof = readFrame(frame);
frame.flip();
Packet pkt = new Packet(frame, (long)(this.frameNo * 1152), this.sampleRate, 1152L, (long)this.frameNo, Packet.FrameType.KEY, null, 0);
this.frameNo++;
return pkt;
}
private static boolean validHeader(int four) {
if (getField(four, SYNC) != 2047)
return false;
if (getField(four, LAYER) == 0)
return false;
if (getField(four, SAMPLE_RATE) == 3)
return false;
if (getField(four, BITRATE) == 15)
return false;
return true;
}
private void readMoreData() throws IOException {
this.readBuffer.clear();
this.ch.read(this.readBuffer);
this.readBuffer.flip();
}
private static int calcFrameSize(int header) {
int bitrateIdx = getField(header, BITRATE);
int layer = 3 - getField(header, LAYER);
int version = getField(header, VERSION);
int mpeg2 = (version != 3) ? 1 : 0;
int bitRate = bitrateTable[mpeg2][layer][bitrateIdx] * 1000;
int sampleRate = freqTab[getField(header, SAMPLE_RATE)] >> rateReductTab[version];
int padding = getField(header, PADDING);
int lsf = (version == 0 || version == 2) ? 1 : 0;
switch (layer) {
case 0:
return (bitRate * 12 / sampleRate + padding) * 4;
case 1:
return bitRate * 144 / sampleRate + padding;
}
return bitRate * 144 / (sampleRate << lsf) + padding;
}
private boolean readFrame(ByteBuffer frame) throws IOException {
boolean eof = false;
while (frame.hasRemaining()) {
frame.put((byte)(this.runningFour >> 24));
this.runningFour <<= 8;
if (!this.readBuffer.hasRemaining())
readMoreData();
if (this.readBuffer.hasRemaining()) {
this.runningFour |= this.readBuffer.get() & 0xFF;
continue;
}
eof = true;
}
return eof;
}
private boolean skipJunk() throws IOException {
boolean eof = false;
int total = 0;
while (!validHeader(this.runningFour)) {
if (!this.readBuffer.hasRemaining())
readMoreData();
if (!this.readBuffer.hasRemaining()) {
eof = true;
break;
}
this.runningFour <<= 8;
this.runningFour |= this.readBuffer.get() & 0xFF;
total++;
}
Logger.warn(String.format("[mp3demuxer] Skipped %d bytes of junk", total));
return eof;
}
public DemuxerTrackMeta getMeta() {
return this.meta;
}
@UsedViaReflection
public static int probe(ByteBuffer b) {
ByteBuffer fork = b.duplicate();
int valid = 0, total = 0;
int header = fork.getInt();
do {
if (!validHeader(header))
header = skipJunkBB(header, fork);
int size = calcFrameSize(header);
if (fork.remaining() < size)
break;
total++;
if (size > 0) {
NIOUtils.skip(fork, size - 4);
} else {
header = skipJunkBB(header, fork);
}
if (fork.remaining() < 4)
continue;
header = fork.getInt();
if (size < 52 || size > 1728 || !validHeader(header))
continue;
valid++;
} while (fork.remaining() >= 4);
return 100 * valid / total;
}
private static int skipJunkBB(int header, ByteBuffer fork) {
while (!validHeader(header) && fork.hasRemaining()) {
header <<= 8;
header |= fork.get() & 0xFF;
}
return header;
}
}