www in docker support
This commit is contained in:
parent
539a848e95
commit
c227fce036
2145 changed files with 399596 additions and 58 deletions
|
|
@ -0,0 +1,30 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jcodec.common.AudioFormat;
|
||||
|
||||
public class AudioBuffer {
|
||||
protected ByteBuffer data;
|
||||
|
||||
protected AudioFormat format;
|
||||
|
||||
protected int nFrames;
|
||||
|
||||
public AudioBuffer(ByteBuffer data, AudioFormat format, int nFrames) {
|
||||
this.data = data;
|
||||
this.format = format;
|
||||
this.nFrames = nFrames;
|
||||
}
|
||||
|
||||
public ByteBuffer getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public AudioFormat getFormat() {
|
||||
return this.format;
|
||||
}
|
||||
|
||||
public int getNFrames() {
|
||||
return this.nFrames;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import org.jcodec.common.AudioFormat;
|
||||
|
||||
public class AudioFrame extends AudioBuffer {
|
||||
private long pts;
|
||||
|
||||
private long duration;
|
||||
|
||||
private long timescale;
|
||||
|
||||
private int frameNo;
|
||||
|
||||
public AudioFrame(ByteBuffer buffer, AudioFormat format, int nFrames, long pts, long duration, long timescale, int frameNo) {
|
||||
super(buffer, format, nFrames);
|
||||
this.pts = pts;
|
||||
this.duration = duration;
|
||||
this.timescale = timescale;
|
||||
this.frameNo = frameNo;
|
||||
}
|
||||
|
||||
public long getPts() {
|
||||
return this.pts;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
public long getTimescale() {
|
||||
return this.timescale;
|
||||
}
|
||||
|
||||
public int getFrameNo() {
|
||||
return this.frameNo;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public enum ChannelLabel {
|
||||
MONO, STEREO_LEFT, STEREO_RIGHT, LEFT_TOTAL, RIGHT_TOTAL, FRONT_LEFT, FRONT_RIGHT, CENTER, LFE, REAR_LEFT, REAR_RIGHT, FRONT_CENTER_LEFT, FRONT_CENTER_RIGHT, REAR_CENTER, SIDE_LEFT, SIDE_RIGHT;
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public final class ColorSpace {
|
||||
public static final int MAX_PLANES = 4;
|
||||
|
||||
public int nComp;
|
||||
|
||||
public int[] compPlane;
|
||||
|
||||
public int[] compWidth;
|
||||
|
||||
public int[] compHeight;
|
||||
|
||||
public boolean planar;
|
||||
|
||||
private String _name;
|
||||
|
||||
public int bitsPerPixel;
|
||||
|
||||
private ColorSpace(String name, int nComp, int[] compPlane, int[] compWidth, int[] compHeight, boolean planar) {
|
||||
this._name = name;
|
||||
this.nComp = nComp;
|
||||
this.compPlane = compPlane;
|
||||
this.compWidth = compWidth;
|
||||
this.compHeight = compHeight;
|
||||
this.planar = planar;
|
||||
this.bitsPerPixel = calcBitsPerPixel(nComp, compWidth, compHeight);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
private static int calcBitsPerPixel(int nComp, int[] compWidth, int[] compHeight) {
|
||||
int bitsPerPixel = 0;
|
||||
for (int i = 0; i < nComp; i++)
|
||||
bitsPerPixel += 8 >> compWidth[i] >> compHeight[i];
|
||||
return bitsPerPixel;
|
||||
}
|
||||
|
||||
public int getWidthMask() {
|
||||
return ((this.nComp > 1) ? this.compWidth[1] : 0) ^ 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
public int getHeightMask() {
|
||||
return ((this.nComp > 1) ? this.compHeight[1] : 0) ^ 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
public boolean matches(ColorSpace inputColor) {
|
||||
if (inputColor == this)
|
||||
return true;
|
||||
if (inputColor == ANY || this == ANY)
|
||||
return true;
|
||||
if ((inputColor == ANY_INTERLEAVED || this == ANY_INTERLEAVED || inputColor == ANY_PLANAR || this == ANY_PLANAR) && inputColor.planar == this.planar)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public Size compSize(Size size, int comp) {
|
||||
if (this.compWidth[comp] == 0 && this.compHeight[comp] == 0)
|
||||
return size;
|
||||
return new Size(size.getWidth() >> this.compWidth[comp], size.getHeight() >> this.compHeight[comp]);
|
||||
}
|
||||
|
||||
private static final int[] _000 = new int[] { 0, 0, 0 };
|
||||
|
||||
private static final int[] _011 = new int[] { 0, 1, 1 };
|
||||
|
||||
private static final int[] _012 = new int[] { 0, 1, 2 };
|
||||
|
||||
public static final ColorSpace BGR = new ColorSpace("BGR", 3, _000, _000, _000, false);
|
||||
|
||||
public static final ColorSpace RGB = new ColorSpace("RGB", 3, _000, _000, _000, false);
|
||||
|
||||
public static final ColorSpace YUV420 = new ColorSpace("YUV420", 3, _012, _011, _011, true);
|
||||
|
||||
public static final ColorSpace YUV420J = new ColorSpace("YUV420J", 3, _012, _011, _011, true);
|
||||
|
||||
public static final ColorSpace YUV422 = new ColorSpace("YUV422", 3, _012, _011, _000, true);
|
||||
|
||||
public static final ColorSpace YUV422J = new ColorSpace("YUV422J", 3, _012, _011, _000, true);
|
||||
|
||||
public static final ColorSpace YUV444 = new ColorSpace("YUV444", 3, _012, _000, _000, true);
|
||||
|
||||
public static final ColorSpace YUV444J = new ColorSpace("YUV444J", 3, _012, _000, _000, true);
|
||||
|
||||
public static final ColorSpace YUV422_10 = new ColorSpace("YUV422_10", 3, _012, _011, _000, true);
|
||||
|
||||
public static final ColorSpace GREY = new ColorSpace("GREY", 1, new int[] { 0 }, new int[] { 0 }, new int[] { 0 }, true);
|
||||
|
||||
public static final ColorSpace MONO = new ColorSpace("MONO", 1, _000, _000, _000, true);
|
||||
|
||||
public static final ColorSpace YUV444_10 = new ColorSpace("YUV444_10", 3, _012, _000, _000, true);
|
||||
|
||||
public static final ColorSpace ANY = new ColorSpace("ANY", 0, null, null, null, true);
|
||||
|
||||
public static final ColorSpace ANY_PLANAR = new ColorSpace("ANY_PLANAR", 0, null, null, null, true);
|
||||
|
||||
public static final ColorSpace ANY_INTERLEAVED = new ColorSpace("ANY_INTERLEAVED", 0, null, null, null, false);
|
||||
|
||||
public static final ColorSpace SAME = new ColorSpace("SAME", 0, null, null, null, false);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Frame {
|
||||
private Picture pic;
|
||||
|
||||
private RationalLarge pts;
|
||||
|
||||
private RationalLarge duration;
|
||||
|
||||
private Rational pixelAspect;
|
||||
|
||||
private TapeTimecode tapeTimecode;
|
||||
|
||||
private int frameNo;
|
||||
|
||||
private List<String> messages;
|
||||
|
||||
public Frame(Picture pic, RationalLarge pts, RationalLarge duration, Rational pixelAspect, int frameNo, TapeTimecode tapeTimecode, List<String> messages) {
|
||||
this.pic = pic;
|
||||
this.pts = pts;
|
||||
this.duration = duration;
|
||||
this.pixelAspect = pixelAspect;
|
||||
this.tapeTimecode = tapeTimecode;
|
||||
this.frameNo = frameNo;
|
||||
this.messages = messages;
|
||||
}
|
||||
|
||||
public Picture getPic() {
|
||||
return this.pic;
|
||||
}
|
||||
|
||||
public RationalLarge getPts() {
|
||||
return this.pts;
|
||||
}
|
||||
|
||||
public RationalLarge getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
public Rational getPixelAspect() {
|
||||
return this.pixelAspect;
|
||||
}
|
||||
|
||||
public TapeTimecode getTapeTimecode() {
|
||||
return this.tapeTimecode;
|
||||
}
|
||||
|
||||
public int getFrameNo() {
|
||||
return this.frameNo;
|
||||
}
|
||||
|
||||
public List<String> getMessages() {
|
||||
return this.messages;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class Label {
|
||||
private static final List<Label> _values = new ArrayList<>();
|
||||
|
||||
public static final Label Unknown = new Label(-1);
|
||||
|
||||
public static final Label Unused = new Label(0);
|
||||
|
||||
public static final Label UseCoordinates = new Label(100);
|
||||
|
||||
public static final Label Left = new Label(1);
|
||||
|
||||
public static final Label Right = new Label(2);
|
||||
|
||||
public static final Label Center = new Label(3);
|
||||
|
||||
public static final Label LFEScreen = new Label(4);
|
||||
|
||||
public static final Label LeftSurround = new Label(5);
|
||||
|
||||
public static final Label RightSurround = new Label(6);
|
||||
|
||||
public static final Label LeftCenter = new Label(7);
|
||||
|
||||
public static final Label RightCenter = new Label(8);
|
||||
|
||||
public static final Label CenterSurround = new Label(9);
|
||||
|
||||
public static final Label LeftSurroundDirect = new Label(10);
|
||||
|
||||
public static final Label RightSurroundDirect = new Label(11);
|
||||
|
||||
public static final Label TopCenterSurround = new Label(12);
|
||||
|
||||
public static final Label VerticalHeightLeft = new Label(13);
|
||||
|
||||
public static final Label VerticalHeightCenter = new Label(14);
|
||||
|
||||
public static final Label VerticalHeightRight = new Label(15);
|
||||
|
||||
public static final Label TopBackLeft = new Label(16);
|
||||
|
||||
public static final Label TopBackCenter = new Label(17);
|
||||
|
||||
public static final Label TopBackRight = new Label(18);
|
||||
|
||||
public static final Label RearSurroundLeft = new Label(33);
|
||||
|
||||
public static final Label RearSurroundRight = new Label(34);
|
||||
|
||||
public static final Label LeftWide = new Label(35);
|
||||
|
||||
public static final Label RightWide = new Label(36);
|
||||
|
||||
public static final Label LFE2 = new Label(37);
|
||||
|
||||
public static final Label LeftTotal = new Label(38);
|
||||
|
||||
public static final Label RightTotal = new Label(39);
|
||||
|
||||
public static final Label HearingImpaired = new Label(40);
|
||||
|
||||
public static final Label Narration = new Label(41);
|
||||
|
||||
public static final Label Mono = new Label(42);
|
||||
|
||||
public static final Label DialogCentricMix = new Label(43);
|
||||
|
||||
public static final Label CenterSurroundDirect = new Label(44);
|
||||
|
||||
public static final Label Ambisonic_W = new Label(200);
|
||||
|
||||
public static final Label Ambisonic_X = new Label(201);
|
||||
|
||||
public static final Label Ambisonic_Y = new Label(202);
|
||||
|
||||
public static final Label Ambisonic_Z = new Label(203);
|
||||
|
||||
public static final Label MS_Mid = new Label(204);
|
||||
|
||||
public static final Label MS_Side = new Label(205);
|
||||
|
||||
public static final Label XY_X = new Label(206);
|
||||
|
||||
public static final Label XY_Y = new Label(207);
|
||||
|
||||
public static final Label HeadphonesLeft = new Label(301);
|
||||
|
||||
public static final Label HeadphonesRight = new Label(302);
|
||||
|
||||
public static final Label ClickTrack = new Label(304);
|
||||
|
||||
public static final Label ForeignLanguage = new Label(305);
|
||||
|
||||
public static final Label Discrete = new Label(400);
|
||||
|
||||
public static final Label Discrete_0 = new Label(65536);
|
||||
|
||||
public static final Label Discrete_1 = new Label(65537);
|
||||
|
||||
public static final Label Discrete_2 = new Label(65538);
|
||||
|
||||
public static final Label Discrete_3 = new Label(65539);
|
||||
|
||||
public static final Label Discrete_4 = new Label(65540);
|
||||
|
||||
public static final Label Discrete_5 = new Label(65541);
|
||||
|
||||
public static final Label Discrete_6 = new Label(65542);
|
||||
|
||||
public static final Label Discrete_7 = new Label(65543);
|
||||
|
||||
public static final Label Discrete_8 = new Label(65544);
|
||||
|
||||
public static final Label Discrete_9 = new Label(65545);
|
||||
|
||||
public static final Label Discrete_10 = new Label(65546);
|
||||
|
||||
public static final Label Discrete_11 = new Label(65547);
|
||||
|
||||
public static final Label Discrete_12 = new Label(65548);
|
||||
|
||||
public static final Label Discrete_13 = new Label(65549);
|
||||
|
||||
public static final Label Discrete_14 = new Label(65550);
|
||||
|
||||
public static final Label Discrete_15 = new Label(65551);
|
||||
|
||||
public static final Label Discrete_65535 = new Label(131071);
|
||||
|
||||
final int labelVal;
|
||||
|
||||
public final long bitmapVal;
|
||||
|
||||
public static final Pattern channelMappingRegex = Pattern.compile("[_\\ \\.][a-zA-Z]+$");
|
||||
|
||||
private Label(int val) {
|
||||
this.labelVal = val;
|
||||
this.bitmapVal = (this.labelVal > 18 || this.labelVal < 1) ? 0L : (long)(1 << this.labelVal - 1);
|
||||
_values.add(this);
|
||||
}
|
||||
|
||||
public static Label[] values() {
|
||||
return _values.<Label>toArray(new Label[0]);
|
||||
}
|
||||
|
||||
public static Label getByVal(int val) {
|
||||
Label[] values = values();
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
Label label = values[i];
|
||||
if (label.labelVal == val)
|
||||
return label;
|
||||
}
|
||||
return Mono;
|
||||
}
|
||||
|
||||
public int getVal() {
|
||||
return this.labelVal;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class Packet {
|
||||
public ByteBuffer data;
|
||||
|
||||
public long pts;
|
||||
|
||||
public int timescale;
|
||||
|
||||
public long duration;
|
||||
|
||||
public long frameNo;
|
||||
|
||||
public FrameType frameType;
|
||||
|
||||
public TapeTimecode tapeTimecode;
|
||||
|
||||
public int displayOrder;
|
||||
|
||||
public enum FrameType {
|
||||
KEY, INTER, UNKNOWN;
|
||||
}
|
||||
|
||||
public static Packet createPacket(ByteBuffer data, long pts, int timescale, long duration, long frameNo, FrameType frameType, TapeTimecode tapeTimecode) {
|
||||
return new Packet(data, pts, timescale, duration, frameNo, frameType, tapeTimecode, 0);
|
||||
}
|
||||
|
||||
public static Packet createPacketWithData(Packet other, ByteBuffer data) {
|
||||
return new Packet(data, other.pts, other.timescale, other.duration, other.frameNo, other.frameType, other.tapeTimecode, other.displayOrder);
|
||||
}
|
||||
|
||||
public Packet(ByteBuffer data, long pts, int timescale, long duration, long frameNo, FrameType frameType, TapeTimecode tapeTimecode, int displayOrder) {
|
||||
this.data = data;
|
||||
this.pts = pts;
|
||||
this.timescale = timescale;
|
||||
this.duration = duration;
|
||||
this.frameNo = frameNo;
|
||||
this.frameType = frameType;
|
||||
this.tapeTimecode = tapeTimecode;
|
||||
this.displayOrder = displayOrder;
|
||||
}
|
||||
|
||||
public ByteBuffer getData() {
|
||||
return this.data.duplicate();
|
||||
}
|
||||
|
||||
public long getPts() {
|
||||
return this.pts;
|
||||
}
|
||||
|
||||
public int getTimescale() {
|
||||
return this.timescale;
|
||||
}
|
||||
|
||||
public long getDuration() {
|
||||
return this.duration;
|
||||
}
|
||||
|
||||
public long getFrameNo() {
|
||||
return this.frameNo;
|
||||
}
|
||||
|
||||
public void setTimescale(int timescale) {
|
||||
this.timescale = timescale;
|
||||
}
|
||||
|
||||
public TapeTimecode getTapeTimecode() {
|
||||
return this.tapeTimecode;
|
||||
}
|
||||
|
||||
public void setTapeTimecode(TapeTimecode tapeTimecode) {
|
||||
this.tapeTimecode = tapeTimecode;
|
||||
}
|
||||
|
||||
public int getDisplayOrder() {
|
||||
return this.displayOrder;
|
||||
}
|
||||
|
||||
public void setDisplayOrder(int displayOrder) {
|
||||
this.displayOrder = displayOrder;
|
||||
}
|
||||
|
||||
public FrameType getFrameType() {
|
||||
return this.frameType;
|
||||
}
|
||||
|
||||
public void setFrameType(FrameType frameType) {
|
||||
this.frameType = frameType;
|
||||
}
|
||||
|
||||
public RationalLarge getPtsR() {
|
||||
return RationalLarge.R(this.pts, (long)this.timescale);
|
||||
}
|
||||
|
||||
public double getPtsD() {
|
||||
return (double)this.pts / (double)this.timescale;
|
||||
}
|
||||
|
||||
public double getDurationD() {
|
||||
return (double)this.duration / (double)this.timescale;
|
||||
}
|
||||
|
||||
public void setData(ByteBuffer data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public void setPts(long pts) {
|
||||
this.pts = pts;
|
||||
}
|
||||
|
||||
public static final Comparator<Packet> FRAME_ASC = new Comparator<>() {
|
||||
public int compare(Packet o1, Packet o2) {
|
||||
if (o1 == null && o2 == null)
|
||||
return 0;
|
||||
if (o1 == null)
|
||||
return -1;
|
||||
if (o2 == null)
|
||||
return 1;
|
||||
return (o1.frameNo < o2.frameNo) ? -1 : ((o1.frameNo == o2.frameNo) ? 0 : 1);
|
||||
}
|
||||
};
|
||||
|
||||
public void setDuration(long duration) {
|
||||
this.duration = duration;
|
||||
}
|
||||
|
||||
public boolean isKeyFrame() {
|
||||
return (this.frameType == FrameType.KEY);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.jcodec.common.tools.MathUtil;
|
||||
|
||||
public class Picture {
|
||||
private ColorSpace color;
|
||||
|
||||
private int width;
|
||||
|
||||
private int height;
|
||||
|
||||
private byte[][] data;
|
||||
|
||||
private byte[][] lowBits;
|
||||
|
||||
private int lowBitsNum;
|
||||
|
||||
private Rect crop;
|
||||
|
||||
public static Picture createPicture(int width, int height, byte[][] data, ColorSpace color) {
|
||||
return new Picture(width, height, data, null, color, 0, new Rect(0, 0, width, height));
|
||||
}
|
||||
|
||||
public static Picture createPictureHiBD(int width, int height, byte[][] data, byte[][] lowBits, ColorSpace color, int lowBitsNum) {
|
||||
return new Picture(width, height, data, lowBits, color, lowBitsNum, new Rect(0, 0, width, height));
|
||||
}
|
||||
|
||||
public Picture(int width, int height, byte[][] data, byte[][] lowBits, ColorSpace color, int lowBitsNum, Rect crop) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.data = data;
|
||||
this.lowBits = lowBits;
|
||||
this.color = color;
|
||||
this.lowBitsNum = lowBitsNum;
|
||||
this.crop = crop;
|
||||
if (color != null)
|
||||
for (int i = 0; i < color.nComp; i++) {
|
||||
int mask = 255 >> 8 - color.compWidth[i];
|
||||
if ((width & mask) != 0)
|
||||
throw new IllegalArgumentException("Component " + i + " width should be a multiple of " + (1 << color.compWidth[i]) + " for colorspace: " + String.valueOf(color));
|
||||
if (crop != null && (crop.getWidth() & mask) != 0)
|
||||
throw new IllegalArgumentException("Component " + i + " cropped width should be a multiple of " + (1 << color.compWidth[i]) + " for colorspace: " + String.valueOf(color));
|
||||
mask = 255 >> 8 - color.compHeight[i];
|
||||
if ((height & mask) != 0)
|
||||
throw new IllegalArgumentException("Component " + i + " height should be a multiple of " + (1 << color.compHeight[i]) + " for colorspace: " + String.valueOf(color));
|
||||
if (crop != null && (crop.getHeight() & mask) != 0)
|
||||
throw new IllegalArgumentException("Component " + i + " cropped height should be a multiple of " + (1 << color.compHeight[i]) + " for colorspace: " + String.valueOf(color));
|
||||
}
|
||||
}
|
||||
|
||||
public static Picture copyPicture(Picture other) {
|
||||
return new Picture(other.width, other.height, other.data, other.lowBits, other.color, 0, other.crop);
|
||||
}
|
||||
|
||||
public static Picture create(int width, int height, ColorSpace colorSpace) {
|
||||
return createCropped(width, height, colorSpace, null);
|
||||
}
|
||||
|
||||
public static Picture createCropped(int width, int height, ColorSpace colorSpace, Rect crop) {
|
||||
int[] planeSizes = new int[4];
|
||||
for (int i = 0; i < colorSpace.nComp; i++)
|
||||
planeSizes[colorSpace.compPlane[i]] = planeSizes[colorSpace.compPlane[i]] + (width >> colorSpace.compWidth[i]) * (height >> colorSpace.compHeight[i]);
|
||||
int nPlanes = 0;
|
||||
for (int j = 0; j < 4; j++)
|
||||
nPlanes += (planeSizes[j] != 0) ? 1 : 0;
|
||||
byte[][] data = new byte[nPlanes][];
|
||||
for (int k = 0, plane = 0; k < 4; k++) {
|
||||
if (planeSizes[k] != 0)
|
||||
data[plane++] = new byte[planeSizes[k]];
|
||||
}
|
||||
return new Picture(width, height, data, null, colorSpace, 0, crop);
|
||||
}
|
||||
|
||||
public static Picture createCroppedHiBD(int width, int height, int lowBitsNum, ColorSpace colorSpace, Rect crop) {
|
||||
Picture result = createCropped(width, height, colorSpace, crop);
|
||||
if (lowBitsNum <= 0)
|
||||
return result;
|
||||
byte[][] data = result.getData();
|
||||
int nPlanes = data.length;
|
||||
byte[][] lowBits = new byte[nPlanes][];
|
||||
for (int i = 0, plane = 0; i < nPlanes; i++)
|
||||
lowBits[plane++] = new byte[(data[i]).length];
|
||||
result.setLowBits(lowBits);
|
||||
result.setLowBitsNum(lowBitsNum);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void setLowBitsNum(int lowBitsNum) {
|
||||
this.lowBitsNum = lowBitsNum;
|
||||
}
|
||||
|
||||
private void setLowBits(byte[][] lowBits) {
|
||||
this.lowBits = lowBits;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public byte[] getPlaneData(int plane) {
|
||||
return this.data[plane];
|
||||
}
|
||||
|
||||
public ColorSpace getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public byte[][] getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public byte[][] getLowBits() {
|
||||
return this.lowBits;
|
||||
}
|
||||
|
||||
public Rect getCrop() {
|
||||
return this.crop;
|
||||
}
|
||||
|
||||
public int getPlaneWidth(int plane) {
|
||||
return this.width >> this.color.compWidth[plane];
|
||||
}
|
||||
|
||||
public int getPlaneHeight(int plane) {
|
||||
return this.height >> this.color.compHeight[plane];
|
||||
}
|
||||
|
||||
public boolean compatible(Picture src) {
|
||||
return (src.color == this.color && src.width == this.width && src.height == this.height);
|
||||
}
|
||||
|
||||
public Picture createCompatible() {
|
||||
return create(this.width, this.height, this.color);
|
||||
}
|
||||
|
||||
public void copyFrom(Picture src) {
|
||||
if (!compatible(src))
|
||||
throw new IllegalArgumentException("Can not copy to incompatible picture");
|
||||
for (int plane = 0; plane < this.color.nComp; plane++) {
|
||||
if (this.data[plane] != null)
|
||||
System.arraycopy(src.data[plane], 0, this.data[plane], 0, (this.width >> this.color.compWidth[plane]) * (this.height >> this.color.compHeight[plane]));
|
||||
}
|
||||
}
|
||||
|
||||
public Picture cloneCropped() {
|
||||
if (cropNeeded())
|
||||
return cropped();
|
||||
Picture clone = createCompatible();
|
||||
clone.copyFrom(this);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public Picture cropped() {
|
||||
if (!cropNeeded())
|
||||
return this;
|
||||
Picture result = create(this.crop.getWidth(), this.crop.getHeight(), this.color);
|
||||
if (this.color.planar) {
|
||||
for (int plane = 0; plane < this.data.length; plane++) {
|
||||
if (this.data[plane] != null)
|
||||
cropSub(this.data[plane], this.crop.getX() >> this.color.compWidth[plane], this.crop.getY() >> this.color.compHeight[plane],
|
||||
this.crop.getWidth() >> this.color.compWidth[plane], this.crop.getHeight() >> this.color.compHeight[plane], this.width >> this.color.compWidth[plane],
|
||||
this.crop.getWidth() >> this.color.compWidth[plane], result.data[plane]);
|
||||
}
|
||||
} else {
|
||||
cropSub(this.data[0], this.crop.getX(), this.crop.getY(), this.crop.getWidth(),
|
||||
this.crop.getHeight(), this.width * this.color.nComp, this.crop.getWidth() * this.color.nComp, result.data[0]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean cropNeeded() {
|
||||
return (this.crop != null && (
|
||||
this.crop.getX() != 0 || this.crop.getY() != 0 || this.crop.getWidth() != this.width || this.crop.getHeight() != this.height));
|
||||
}
|
||||
|
||||
private void cropSub(byte[] src, int x, int y, int w, int h, int srcStride, int dstStride, byte[] tgt) {
|
||||
int srcOff = y * srcStride + x, dstOff = 0;
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < dstStride; j++)
|
||||
tgt[dstOff + j] = src[srcOff + j];
|
||||
srcOff += srcStride;
|
||||
dstOff += dstStride;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCrop(Rect crop) {
|
||||
this.crop = crop;
|
||||
}
|
||||
|
||||
public int getCroppedWidth() {
|
||||
return (this.crop == null) ? this.width : this.crop.getWidth();
|
||||
}
|
||||
|
||||
public int getCroppedHeight() {
|
||||
return (this.crop == null) ? this.height : this.crop.getHeight();
|
||||
}
|
||||
|
||||
public int getLowBitsNum() {
|
||||
return this.lowBitsNum;
|
||||
}
|
||||
|
||||
public static Picture fromPictureHiBD(PictureHiBD pic) {
|
||||
int lowBitsNum = pic.getBitDepth() - 8;
|
||||
int lowBitsRound = 1 << lowBitsNum >> 1;
|
||||
Picture result = createCroppedHiBD(pic.getWidth(), pic.getHeight(), lowBitsNum, pic.getColor(),
|
||||
pic.getCrop());
|
||||
for (int i = 0; i < Math.min((pic.getData()).length, (result.getData()).length); i++) {
|
||||
for (int j = 0; j < Math.min((pic.getData()[i]).length, (result.getData()[i]).length); j++) {
|
||||
int val = pic.getData()[i][j];
|
||||
int round = MathUtil.clip(val + lowBitsRound >> lowBitsNum, 0, 255);
|
||||
result.getData()[i][j] = (byte)(round - 128);
|
||||
}
|
||||
}
|
||||
byte[][] lowBits = result.getLowBits();
|
||||
if (lowBits != null)
|
||||
for (int j = 0; j < Math.min((pic.getData()).length, (result.getData()).length); j++) {
|
||||
for (int k = 0; k < Math.min((pic.getData()[j]).length, (result.getData()[j]).length); k++) {
|
||||
int val = pic.getData()[j][k];
|
||||
int round = MathUtil.clip(val + lowBitsRound >> lowBitsNum, 0, 255);
|
||||
lowBits[j][k] = (byte)(val - (round << 2));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public PictureHiBD toPictureHiBD() {
|
||||
PictureHiBD create = PictureHiBD.doCreate(this.width, this.height, this.color, this.lowBitsNum + 8, this.crop);
|
||||
return toPictureHiBDInternal(create);
|
||||
}
|
||||
|
||||
public PictureHiBD toPictureHiBDWithBuffer(int[][] buffer) {
|
||||
PictureHiBD create = new PictureHiBD(this.width, this.height, buffer, this.color, this.lowBitsNum + 8, this.crop);
|
||||
return toPictureHiBDInternal(create);
|
||||
}
|
||||
|
||||
private PictureHiBD toPictureHiBDInternal(PictureHiBD pic) {
|
||||
int[][] dstData = pic.getData();
|
||||
for (int i = 0; i < this.data.length; i++) {
|
||||
int planeSize = getPlaneWidth(i) * getPlaneHeight(i);
|
||||
for (int j = 0; j < planeSize; j++)
|
||||
dstData[i][j] = this.data[i][j] + 128 << this.lowBitsNum;
|
||||
}
|
||||
if (this.lowBits != null)
|
||||
for (int j = 0; j < this.lowBits.length; j++) {
|
||||
int planeSize = getPlaneWidth(j) * getPlaneHeight(j);
|
||||
for (int k = 0; k < planeSize; k++)
|
||||
dstData[j][k] = dstData[j][k] + this.lowBits[j][k];
|
||||
}
|
||||
return pic;
|
||||
}
|
||||
|
||||
public void fill(int val) {
|
||||
for (int i = 0; i < this.data.length; i++)
|
||||
Arrays.fill(this.data[i], (byte)val);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || !(obj instanceof Picture))
|
||||
return false;
|
||||
Picture other = (Picture)obj;
|
||||
if (other.getCroppedWidth() != getCroppedWidth() || other.getCroppedHeight() != getCroppedHeight() ||
|
||||
other.getColor() != this.color)
|
||||
return false;
|
||||
for (int i = 0; i < (getData()).length; i++) {
|
||||
if (!planeEquals(other, i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean planeEquals(Picture other, int plane) {
|
||||
int cw = this.color.compWidth[plane];
|
||||
int ch = this.color.compHeight[plane];
|
||||
int offA = (other.getCrop() == null) ? 0 : ((other.getCrop().getX() >> cw) + (other.getCrop().getY() >> ch) * (
|
||||
other.getWidth() >> cw));
|
||||
int offB = (this.crop == null) ? 0 : ((this.crop.getX() >> cw) + (this.crop.getY() >> ch) * (this.width >> cw));
|
||||
byte[] planeData = other.getPlaneData(plane);
|
||||
for (int i = 0; i < getCroppedHeight() >> ch; i++, offA += other.getWidth() >> cw, offB += this.width >> cw) {
|
||||
for (int j = 0; j < getCroppedWidth() >> cw; j++) {
|
||||
if (planeData[offA + j] != this.data[plane][offB + j])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getStartX() {
|
||||
return (this.crop == null) ? 0 : this.crop.getX();
|
||||
}
|
||||
|
||||
public int getStartY() {
|
||||
return (this.crop == null) ? 0 : this.crop.getY();
|
||||
}
|
||||
|
||||
public boolean isHiBD() {
|
||||
return (this.lowBits != null);
|
||||
}
|
||||
|
||||
public Size getSize() {
|
||||
return new Size(this.width, this.height);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public class PictureHiBD {
|
||||
private ColorSpace color;
|
||||
|
||||
private int width;
|
||||
|
||||
private int height;
|
||||
|
||||
private int[][] data;
|
||||
|
||||
private Rect crop;
|
||||
|
||||
private int bitDepth;
|
||||
|
||||
public static PictureHiBD createPicture(int width, int height, int[][] data, ColorSpace color) {
|
||||
return new PictureHiBD(width, height, data, color, 8, new Rect(0, 0, width, height));
|
||||
}
|
||||
|
||||
public static PictureHiBD createPictureWithDepth(int width, int height, int[][] data, ColorSpace color, int bitDepth) {
|
||||
return new PictureHiBD(width, height, data, color, bitDepth, new Rect(0, 0, width, height));
|
||||
}
|
||||
|
||||
public static PictureHiBD createPictureCropped(int width, int height, int[][] data, ColorSpace color, Rect crop) {
|
||||
return new PictureHiBD(width, height, data, color, 8, crop);
|
||||
}
|
||||
|
||||
public PictureHiBD(int width, int height, int[][] data, ColorSpace color, int bitDepth, Rect crop) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.data = data;
|
||||
this.color = color;
|
||||
this.crop = crop;
|
||||
this.bitDepth = bitDepth;
|
||||
}
|
||||
|
||||
public static PictureHiBD clonePicture(PictureHiBD other) {
|
||||
return new PictureHiBD(other.width, other.height, other.data, other.color, other.bitDepth, other.crop);
|
||||
}
|
||||
|
||||
public static PictureHiBD create(int width, int height, ColorSpace colorSpace) {
|
||||
return doCreate(width, height, colorSpace, 8, null);
|
||||
}
|
||||
|
||||
public static PictureHiBD createWithDepth(int width, int height, ColorSpace colorSpace, int bitDepth) {
|
||||
return doCreate(width, height, colorSpace, bitDepth, null);
|
||||
}
|
||||
|
||||
public static PictureHiBD createCropped(int width, int height, ColorSpace colorSpace, Rect crop) {
|
||||
return doCreate(width, height, colorSpace, 8, crop);
|
||||
}
|
||||
|
||||
public static PictureHiBD doCreate(int width, int height, ColorSpace colorSpace, int bitDepth, Rect crop) {
|
||||
int[] planeSizes = new int[4];
|
||||
for (int i = 0; i < colorSpace.nComp; i++)
|
||||
planeSizes[colorSpace.compPlane[i]] = planeSizes[colorSpace.compPlane[i]] + (width >> colorSpace.compWidth[i]) * (height >> colorSpace.compHeight[i]);
|
||||
int nPlanes = 0;
|
||||
for (int j = 0; j < 4; j++)
|
||||
nPlanes += (planeSizes[j] != 0) ? 1 : 0;
|
||||
int[][] data = new int[nPlanes][];
|
||||
for (int k = 0, plane = 0; k < 4; k++) {
|
||||
if (planeSizes[k] != 0)
|
||||
data[plane++] = new int[planeSizes[k]];
|
||||
}
|
||||
return new PictureHiBD(width, height, data, colorSpace, 8, crop);
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public int[] getPlaneData(int plane) {
|
||||
return this.data[plane];
|
||||
}
|
||||
|
||||
public ColorSpace getColor() {
|
||||
return this.color;
|
||||
}
|
||||
|
||||
public int[][] getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public Rect getCrop() {
|
||||
return this.crop;
|
||||
}
|
||||
|
||||
public int getPlaneWidth(int plane) {
|
||||
return this.width >> this.color.compWidth[plane];
|
||||
}
|
||||
|
||||
public int getPlaneHeight(int plane) {
|
||||
return this.height >> this.color.compHeight[plane];
|
||||
}
|
||||
|
||||
public boolean compatible(PictureHiBD src) {
|
||||
return (src.color == this.color && src.width == this.width && src.height == this.height);
|
||||
}
|
||||
|
||||
public PictureHiBD createCompatible() {
|
||||
return create(this.width, this.height, this.color);
|
||||
}
|
||||
|
||||
public void copyFrom(PictureHiBD src) {
|
||||
if (!compatible(src))
|
||||
throw new IllegalArgumentException("Can not copy to incompatible picture");
|
||||
for (int plane = 0; plane < this.color.nComp; plane++) {
|
||||
if (this.data[plane] != null)
|
||||
System.arraycopy(src.data[plane], 0, this.data[plane], 0, (this.width >> this.color.compWidth[plane]) * (this.height >> this.color.compHeight[plane]));
|
||||
}
|
||||
}
|
||||
|
||||
public PictureHiBD cropped() {
|
||||
if (this.crop == null || (
|
||||
this.crop.getX() == 0 && this.crop.getY() == 0 && this.crop.getWidth() == this.width && this.crop.getHeight() == this.height))
|
||||
return this;
|
||||
PictureHiBD result = create(this.crop.getWidth(), this.crop.getHeight(), this.color);
|
||||
for (int plane = 0; plane < this.color.nComp; plane++) {
|
||||
if (this.data[plane] != null)
|
||||
cropSub(this.data[plane], this.crop.getX() >> this.color.compWidth[plane], this.crop.getY() >> this.color.compHeight[plane],
|
||||
this.crop.getWidth() >> this.color.compWidth[plane], this.crop.getHeight() >> this.color.compHeight[plane], this.width >> this.color.compWidth[plane], result.data[plane]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void cropSub(int[] src, int x, int y, int w, int h, int srcStride, int[] tgt) {
|
||||
int srcOff = y * srcStride + x, dstOff = 0;
|
||||
for (int i = 0; i < h; i++) {
|
||||
for (int j = 0; j < w; j++)
|
||||
tgt[dstOff + j] = src[srcOff + j];
|
||||
srcOff += srcStride;
|
||||
dstOff += w;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCrop(Rect crop) {
|
||||
this.crop = crop;
|
||||
}
|
||||
|
||||
public int getCroppedWidth() {
|
||||
return (this.crop == null) ? this.width : this.crop.getWidth();
|
||||
}
|
||||
|
||||
public int getCroppedHeight() {
|
||||
return (this.crop == null) ? this.height : this.crop.getHeight();
|
||||
}
|
||||
|
||||
public void setBitDepth(int bitDepth) {
|
||||
this.bitDepth = bitDepth;
|
||||
}
|
||||
|
||||
public int getBitDepth() {
|
||||
return this.bitDepth;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null || !(obj instanceof PictureHiBD))
|
||||
return false;
|
||||
PictureHiBD other = (PictureHiBD)obj;
|
||||
if (other.getCroppedWidth() != getCroppedWidth() || other.getCroppedHeight() != getCroppedHeight() ||
|
||||
other.getColor() != this.color)
|
||||
return false;
|
||||
for (int i = 0; i < (getData()).length; i++) {
|
||||
if (!planeEquals(other, i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean planeEquals(PictureHiBD other, int plane) {
|
||||
int cw = this.color.compWidth[plane];
|
||||
int ch = this.color.compHeight[plane];
|
||||
int offA = (other.getCrop() == null) ? 0 : ((
|
||||
other.getCrop().getX() >> cw) + (other.getCrop().getY() >> ch) * (other.getWidth() >> cw));
|
||||
int offB = (this.crop == null) ? 0 : ((this.crop.getX() >> cw) + (this.crop.getY() >> ch) * (this.width >> cw));
|
||||
int[] planeData = other.getPlaneData(plane);
|
||||
for (int i = 0; i < getCroppedHeight() >> ch; i++, offA += other.getWidth() >> cw, offB += this.width >> cw) {
|
||||
for (int j = 0; j < getCroppedWidth() >> cw; j++) {
|
||||
if (planeData[offA + j] != this.data[plane][offB + j])
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public class Plane {
|
||||
int[] data;
|
||||
|
||||
Size size;
|
||||
|
||||
public Plane(int[] data, Size size) {
|
||||
this.data = data;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public int[] getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public Size getSize() {
|
||||
return this.size;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public class Point {
|
||||
private int x;
|
||||
|
||||
private int y;
|
||||
|
||||
public Point(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return this.y;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,204 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import org.jcodec.common.tools.MathUtil;
|
||||
|
||||
public class Rational {
|
||||
public static final Rational ONE = new Rational(1, 1);
|
||||
|
||||
public static final Rational HALF = new Rational(1, 2);
|
||||
|
||||
public static final Rational ZERO = new Rational(0, 1);
|
||||
|
||||
public final int num;
|
||||
|
||||
public final int den;
|
||||
|
||||
public static Rational R(int num, int den) {
|
||||
return new Rational(num, den);
|
||||
}
|
||||
|
||||
public static Rational R1(int num) {
|
||||
return R(num, 1);
|
||||
}
|
||||
|
||||
public Rational(int num, int den) {
|
||||
this.num = num;
|
||||
this.den = den;
|
||||
}
|
||||
|
||||
public int getNum() {
|
||||
return this.num;
|
||||
}
|
||||
|
||||
public int getDen() {
|
||||
return this.den;
|
||||
}
|
||||
|
||||
public static Rational parseRational(String string) {
|
||||
return parse(string);
|
||||
}
|
||||
|
||||
public static Rational parse(String string) {
|
||||
int idx = string.indexOf(":");
|
||||
if (idx < 0)
|
||||
idx = string.indexOf("/");
|
||||
if (idx > 0) {
|
||||
String num = string.substring(0, idx);
|
||||
String den = string.substring(idx + 1);
|
||||
return new Rational(Integer.parseInt(num), Integer.parseInt(den));
|
||||
}
|
||||
return R(Integer.parseInt(string), 1);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int prime = 31;
|
||||
int result = 1;
|
||||
result = 31 * result + this.den;
|
||||
result = 31 * result + this.num;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Rational other = (Rational)obj;
|
||||
if (this.den != other.den)
|
||||
return false;
|
||||
if (this.num != other.num)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int multiplyS(int val) {
|
||||
return (int)((long)this.num * (long)val / (long)this.den);
|
||||
}
|
||||
|
||||
public int divideS(int val) {
|
||||
return (int)((long)this.den * (long)val / (long)this.num);
|
||||
}
|
||||
|
||||
public int divideByS(int val) {
|
||||
return this.num / (this.den * val);
|
||||
}
|
||||
|
||||
public long multiplyLong(long val) {
|
||||
return (long)this.num * val / (long)this.den;
|
||||
}
|
||||
|
||||
public long divideLong(long val) {
|
||||
return (long)this.den * val / (long)this.num;
|
||||
}
|
||||
|
||||
public Rational flip() {
|
||||
return new Rational(this.den, this.num);
|
||||
}
|
||||
|
||||
public boolean smallerThen(Rational sec) {
|
||||
return (this.num * sec.den < sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean greaterThen(Rational sec) {
|
||||
return (this.num * sec.den > sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean smallerOrEqualTo(Rational sec) {
|
||||
return (this.num * sec.den <= sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean greaterOrEqualTo(Rational sec) {
|
||||
return (this.num * sec.den >= sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean equalsRational(Rational other) {
|
||||
return (this.num * other.den == other.num * this.den);
|
||||
}
|
||||
|
||||
public Rational plus(Rational other) {
|
||||
return reduce(this.num * other.den + other.num * this.den, this.den * other.den);
|
||||
}
|
||||
|
||||
public RationalLarge plusLarge(RationalLarge other) {
|
||||
return RationalLarge.reduceLong((long)this.num * other.den + other.num * (long)this.den, (long)this.den * other.den);
|
||||
}
|
||||
|
||||
public Rational minus(Rational other) {
|
||||
return reduce(this.num * other.den - other.num * this.den, this.den * other.den);
|
||||
}
|
||||
|
||||
public RationalLarge minusLarge(RationalLarge other) {
|
||||
return RationalLarge.reduceLong((long)this.num * other.den - other.num * (long)this.den, (long)this.den * other.den);
|
||||
}
|
||||
|
||||
public Rational plusInt(int scalar) {
|
||||
return new Rational(this.num + scalar * this.den, this.den);
|
||||
}
|
||||
|
||||
public Rational minusInt(int scalar) {
|
||||
return new Rational(this.num - scalar * this.den, this.den);
|
||||
}
|
||||
|
||||
public Rational multiplyInt(int scalar) {
|
||||
return new Rational(this.num * scalar, this.den);
|
||||
}
|
||||
|
||||
public Rational divideInt(int scalar) {
|
||||
return new Rational(this.den * scalar, this.num);
|
||||
}
|
||||
|
||||
public Rational divideByInt(int scalar) {
|
||||
return new Rational(this.num, this.den * scalar);
|
||||
}
|
||||
|
||||
public Rational multiply(Rational other) {
|
||||
return reduce(this.num * other.num, this.den * other.den);
|
||||
}
|
||||
|
||||
public RationalLarge multiplyLarge(RationalLarge other) {
|
||||
return RationalLarge.reduceLong((long)this.num * other.num, (long)this.den * other.den);
|
||||
}
|
||||
|
||||
public Rational divide(Rational other) {
|
||||
return reduce(other.num * this.den, other.den * this.num);
|
||||
}
|
||||
|
||||
public RationalLarge divideLarge(RationalLarge other) {
|
||||
return RationalLarge.reduceLong(other.num * (long)this.den, other.den * (long)this.num);
|
||||
}
|
||||
|
||||
public Rational divideBy(Rational other) {
|
||||
return reduce(this.num * other.den, this.den * other.num);
|
||||
}
|
||||
|
||||
public RationalLarge divideByLarge(RationalLarge other) {
|
||||
return RationalLarge.reduceLong((long)this.num * other.den, (long)this.den * other.num);
|
||||
}
|
||||
|
||||
public float scalar() {
|
||||
return (float)this.num / (float)this.den;
|
||||
}
|
||||
|
||||
public int scalarClip() {
|
||||
return this.num / this.den;
|
||||
}
|
||||
|
||||
public static Rational reduce(int num, int den) {
|
||||
int gcd = MathUtil.gcd(num, den);
|
||||
return new Rational(num / gcd, den / gcd);
|
||||
}
|
||||
|
||||
public static Rational reduceRational(Rational r) {
|
||||
return reduce(r.getNum(), r.getDen());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "" + this.num + "/" + this.num;
|
||||
}
|
||||
|
||||
public double toDouble() {
|
||||
return (double)this.num / (double)this.den;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import org.jcodec.common.StringUtils;
|
||||
import org.jcodec.common.tools.MathUtil;
|
||||
|
||||
public class RationalLarge {
|
||||
public static final RationalLarge ONE = new RationalLarge(1L, 1L);
|
||||
|
||||
public static final RationalLarge HALF = new RationalLarge(1L, 2L);
|
||||
|
||||
public static final RationalLarge ZERO = new RationalLarge(0L, 1L);
|
||||
|
||||
final long num;
|
||||
|
||||
final long den;
|
||||
|
||||
public RationalLarge(long num, long den) {
|
||||
this.num = num;
|
||||
this.den = den;
|
||||
}
|
||||
|
||||
public long getNum() {
|
||||
return this.num;
|
||||
}
|
||||
|
||||
public long getDen() {
|
||||
return this.den;
|
||||
}
|
||||
|
||||
public static RationalLarge parse(String string) {
|
||||
String[] split = StringUtils.splitS(string, ":");
|
||||
return (split.length > 1) ? R(Long.parseLong(split[0]), Long.parseLong(split[1])) :
|
||||
R(Long.parseLong(string), 1L);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int prime = 31;
|
||||
int result = 1;
|
||||
result = 31 * result + (int)(this.den ^ this.den >>> 32L);
|
||||
result = 31 * result + (int)(this.num ^ this.num >>> 32L);
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
RationalLarge other = (RationalLarge)obj;
|
||||
if (this.den != other.den)
|
||||
return false;
|
||||
if (this.num != other.num)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public long multiplyS(long scalar) {
|
||||
return this.num * scalar / this.den;
|
||||
}
|
||||
|
||||
public long divideS(long scalar) {
|
||||
return this.den * scalar / this.num;
|
||||
}
|
||||
|
||||
public long divideByS(long scalar) {
|
||||
return this.num / (this.den * scalar);
|
||||
}
|
||||
|
||||
public RationalLarge flip() {
|
||||
return new RationalLarge(this.den, this.num);
|
||||
}
|
||||
|
||||
public static RationalLarge R(long num, long den) {
|
||||
return new RationalLarge(num, den);
|
||||
}
|
||||
|
||||
public static RationalLarge R1(long num) {
|
||||
return R(num, 1L);
|
||||
}
|
||||
|
||||
public boolean lessThen(RationalLarge sec) {
|
||||
return (this.num * sec.den < sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean greaterThen(RationalLarge sec) {
|
||||
return (this.num * sec.den > sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean smallerOrEqualTo(RationalLarge sec) {
|
||||
return (this.num * sec.den <= sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean greaterOrEqualTo(RationalLarge sec) {
|
||||
return (this.num * sec.den >= sec.num * this.den);
|
||||
}
|
||||
|
||||
public boolean equalsLarge(RationalLarge other) {
|
||||
return (this.num * other.den == other.num * this.den);
|
||||
}
|
||||
|
||||
public RationalLarge plus(RationalLarge other) {
|
||||
return reduceLong(this.num * other.den + other.num * this.den, this.den * other.den);
|
||||
}
|
||||
|
||||
public RationalLarge plusR(Rational other) {
|
||||
return reduceLong(this.num * (long)other.den + (long)other.num * this.den, this.den * (long)other.den);
|
||||
}
|
||||
|
||||
public RationalLarge minus(RationalLarge other) {
|
||||
return reduceLong(this.num * other.den - other.num * this.den, this.den * other.den);
|
||||
}
|
||||
|
||||
public RationalLarge minusR(Rational other) {
|
||||
return reduceLong(this.num * (long)other.den - (long)other.num * this.den, this.den * (long)other.den);
|
||||
}
|
||||
|
||||
public RationalLarge plusLong(long scalar) {
|
||||
return new RationalLarge(this.num + scalar * this.den, this.den);
|
||||
}
|
||||
|
||||
public RationalLarge minusLong(long scalar) {
|
||||
return new RationalLarge(this.num - scalar * this.den, this.den);
|
||||
}
|
||||
|
||||
public RationalLarge multiplyLong(long scalar) {
|
||||
return new RationalLarge(this.num * scalar, this.den);
|
||||
}
|
||||
|
||||
public RationalLarge divideLong(long scalar) {
|
||||
return new RationalLarge(this.den * scalar, this.num);
|
||||
}
|
||||
|
||||
public RationalLarge divideByLong(long scalar) {
|
||||
return new RationalLarge(this.num, this.den * scalar);
|
||||
}
|
||||
|
||||
public RationalLarge multiply(RationalLarge other) {
|
||||
return reduceLong(this.num * other.num, this.den * other.den);
|
||||
}
|
||||
|
||||
public RationalLarge multiplyR(Rational other) {
|
||||
return reduceLong(this.num * (long)other.num, this.den * (long)other.den);
|
||||
}
|
||||
|
||||
public RationalLarge divideRL(RationalLarge other) {
|
||||
return reduceLong(other.num * this.den, other.den * this.num);
|
||||
}
|
||||
|
||||
public RationalLarge divideR(Rational other) {
|
||||
return reduceLong((long)other.num * this.den, (long)other.den * this.num);
|
||||
}
|
||||
|
||||
public RationalLarge divideBy(RationalLarge other) {
|
||||
return reduceLong(this.num * other.den, this.den * other.num);
|
||||
}
|
||||
|
||||
public RationalLarge divideByR(Rational other) {
|
||||
return reduceLong(this.num * (long)other.den, this.den * (long)other.num);
|
||||
}
|
||||
|
||||
public double scalar() {
|
||||
return (double)this.num / (double)this.den;
|
||||
}
|
||||
|
||||
public long scalarClip() {
|
||||
return this.num / this.den;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "" + this.num + ":" + this.num;
|
||||
}
|
||||
|
||||
public static RationalLarge reduceLong(long num, long den) {
|
||||
long gcd = MathUtil.gcdLong(num, den);
|
||||
return new RationalLarge(num / gcd, den / gcd);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public class Rect {
|
||||
private int x;
|
||||
|
||||
private int y;
|
||||
|
||||
private int width;
|
||||
|
||||
private int height;
|
||||
|
||||
public Rect(int x, int y, int width, int height) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int prime = 31;
|
||||
int result = 1;
|
||||
result = 31 * result + this.height;
|
||||
result = 31 * result + this.width;
|
||||
result = 31 * result + this.x;
|
||||
result = 31 * result + this.y;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Rect other = (Rect)obj;
|
||||
if (this.height != other.height)
|
||||
return false;
|
||||
if (this.width != other.width)
|
||||
return false;
|
||||
if (this.x != other.x)
|
||||
return false;
|
||||
if (this.y != other.y)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "Rect [x=" + this.x + ", y=" + this.y + ", width=" + this.width + ", height=" + this.height + "]";
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public class Size {
|
||||
private int width;
|
||||
|
||||
private int height;
|
||||
|
||||
public Size(int width, int height) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int prime = 31;
|
||||
int result = 1;
|
||||
result = 31 * result + this.height;
|
||||
result = 31 * result + this.width;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Size other = (Size)obj;
|
||||
if (this.height != other.height)
|
||||
return false;
|
||||
if (this.width != other.width)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
import org.jcodec.common.StringUtils;
|
||||
|
||||
public class TapeTimecode {
|
||||
public static final TapeTimecode ZERO_TAPE_TIMECODE = new TapeTimecode((short)0, (byte)0, (byte)0, (byte)0, false, 0);
|
||||
|
||||
private final short hour;
|
||||
|
||||
private final byte minute;
|
||||
|
||||
private final byte second;
|
||||
|
||||
private final byte frame;
|
||||
|
||||
private final boolean dropFrame;
|
||||
|
||||
private final int tapeFps;
|
||||
|
||||
public TapeTimecode(short hour, byte minute, byte second, byte frame, boolean dropFrame, int tapeFps) {
|
||||
this.hour = hour;
|
||||
this.minute = minute;
|
||||
this.second = second;
|
||||
this.frame = frame;
|
||||
this.dropFrame = dropFrame;
|
||||
this.tapeFps = tapeFps;
|
||||
}
|
||||
|
||||
public short getHour() {
|
||||
return this.hour;
|
||||
}
|
||||
|
||||
public byte getMinute() {
|
||||
return this.minute;
|
||||
}
|
||||
|
||||
public byte getSecond() {
|
||||
return this.second;
|
||||
}
|
||||
|
||||
public byte getFrame() {
|
||||
return this.frame;
|
||||
}
|
||||
|
||||
public boolean isDropFrame() {
|
||||
return this.dropFrame;
|
||||
}
|
||||
|
||||
public int getTapeFps() {
|
||||
return this.tapeFps;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return StringUtils.zeroPad2(this.hour) + ":" + StringUtils.zeroPad2(this.hour) + ":" +
|
||||
StringUtils.zeroPad2(this.minute) +
|
||||
StringUtils.zeroPad2(this.second) + (this.dropFrame ? ";" : ":");
|
||||
}
|
||||
|
||||
public static TapeTimecode tapeTimecode(long frame, boolean dropFrame, int tapeFps) {
|
||||
if (dropFrame) {
|
||||
long D = frame / 17982L;
|
||||
long M = frame % 17982L;
|
||||
frame += 18L * D + 2L * (M - 2L) / 1798L;
|
||||
}
|
||||
long sec = frame / (long)tapeFps;
|
||||
return new TapeTimecode((short)(int)(sec / 3600L), (byte)(int)(sec / 60L % 60L), (byte)(int)(sec % 60L), (byte)(int)(frame % (long)tapeFps), dropFrame, tapeFps);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.jcodec.common.model;
|
||||
|
||||
public enum Unit {
|
||||
FRAME, SEC;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue