217 lines
5.4 KiB
Java
217 lines
5.4 KiB
Java
package org.jcodec.common;
|
|
|
|
import java.nio.ByteBuffer;
|
|
import org.jcodec.common.io.NIOUtils;
|
|
|
|
public abstract class RunLength {
|
|
protected IntArrayList counts = IntArrayList.createIntArrayList();
|
|
|
|
public int estimateSize() {
|
|
int[] counts = getCounts();
|
|
int recCount = 0;
|
|
for (int i = 0; i < counts.length; i++, recCount++) {
|
|
int count = counts[i];
|
|
while (count >= 256) {
|
|
recCount++;
|
|
count -= 256;
|
|
}
|
|
}
|
|
return recCount * recSize() + 4;
|
|
}
|
|
|
|
protected abstract int recSize();
|
|
|
|
protected abstract void finish();
|
|
|
|
public int[] getCounts() {
|
|
finish();
|
|
return this.counts.toArray();
|
|
}
|
|
|
|
public static class Integer extends RunLength {
|
|
private static final int MIN_VALUE = -2147483648;
|
|
|
|
private int lastValue;
|
|
|
|
private int count = 0;
|
|
|
|
private IntArrayList values;
|
|
|
|
public Integer() {
|
|
this.lastValue = Integer.MIN_VALUE;
|
|
this.values = IntArrayList.createIntArrayList();
|
|
}
|
|
|
|
public void add(int value) {
|
|
if (this.lastValue == Integer.MIN_VALUE || this.lastValue != value) {
|
|
if (this.lastValue != Integer.MIN_VALUE) {
|
|
this.values.add(this.lastValue);
|
|
this.counts.add(this.count);
|
|
this.count = 0;
|
|
}
|
|
this.lastValue = value;
|
|
}
|
|
this.count++;
|
|
}
|
|
|
|
public int[] getValues() {
|
|
finish();
|
|
return this.values.toArray();
|
|
}
|
|
|
|
protected void finish() {
|
|
if (this.lastValue != Integer.MIN_VALUE) {
|
|
this.values.add(this.lastValue);
|
|
this.counts.add(this.count);
|
|
this.lastValue = Integer.MIN_VALUE;
|
|
this.count = 0;
|
|
}
|
|
}
|
|
|
|
public void serialize(ByteBuffer bb) {
|
|
ByteBuffer dup = bb.duplicate();
|
|
int[] counts = getCounts();
|
|
int[] values = getValues();
|
|
NIOUtils.skip(bb, 4);
|
|
int recCount = 0;
|
|
for (int i = 0; i < counts.length; i++, recCount++) {
|
|
int count = counts[i];
|
|
while (count >= 256) {
|
|
bb.put((byte)-1);
|
|
bb.putInt(values[i]);
|
|
recCount++;
|
|
count -= 256;
|
|
}
|
|
bb.put((byte)(count - 1));
|
|
bb.putInt(values[i]);
|
|
}
|
|
dup.putInt(recCount);
|
|
}
|
|
|
|
public static Integer parse(ByteBuffer bb) {
|
|
Integer rl = new Integer();
|
|
int recCount = bb.getInt();
|
|
for (int i = 0; i < recCount; i++) {
|
|
int count = (bb.get() & 0xFF) + 1;
|
|
int value = bb.getInt();
|
|
rl.counts.add(count);
|
|
rl.values.add(value);
|
|
}
|
|
return rl;
|
|
}
|
|
|
|
protected int recSize() {
|
|
return 5;
|
|
}
|
|
|
|
public int[] flattern() {
|
|
int[] counts = getCounts();
|
|
int total = 0;
|
|
for (int i = 0; i < counts.length; i++)
|
|
total += counts[i];
|
|
int[] values = getValues();
|
|
int[] result = new int[total];
|
|
for (int j = 0, ind = 0; j < counts.length; j++) {
|
|
for (int k = 0; k < counts[j]; k++, ind++)
|
|
result[ind] = values[j];
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public static class Long extends RunLength {
|
|
private static final long MIN_VALUE = -9223372036854775808L;
|
|
|
|
private long lastValue;
|
|
|
|
private int count = 0;
|
|
|
|
private LongArrayList values;
|
|
|
|
public Long() {
|
|
this.lastValue = Long.MIN_VALUE;
|
|
this.values = LongArrayList.createLongArrayList();
|
|
}
|
|
|
|
public void add(long value) {
|
|
if (this.lastValue == Long.MIN_VALUE || this.lastValue != value) {
|
|
if (this.lastValue != Long.MIN_VALUE) {
|
|
this.values.add(this.lastValue);
|
|
this.counts.add(this.count);
|
|
this.count = 0;
|
|
}
|
|
this.lastValue = value;
|
|
}
|
|
this.count++;
|
|
}
|
|
|
|
public int[] getCounts() {
|
|
finish();
|
|
return this.counts.toArray();
|
|
}
|
|
|
|
public long[] getValues() {
|
|
finish();
|
|
return this.values.toArray();
|
|
}
|
|
|
|
protected void finish() {
|
|
if (this.lastValue != Long.MIN_VALUE) {
|
|
this.values.add(this.lastValue);
|
|
this.counts.add(this.count);
|
|
this.lastValue = Long.MIN_VALUE;
|
|
this.count = 0;
|
|
}
|
|
}
|
|
|
|
public void serialize(ByteBuffer bb) {
|
|
ByteBuffer dup = bb.duplicate();
|
|
int[] counts = getCounts();
|
|
long[] values = getValues();
|
|
NIOUtils.skip(bb, 4);
|
|
int recCount = 0;
|
|
for (int i = 0; i < counts.length; i++, recCount++) {
|
|
int count = counts[i];
|
|
while (count >= 256) {
|
|
bb.put((byte)-1);
|
|
bb.putLong(values[i]);
|
|
recCount++;
|
|
count -= 256;
|
|
}
|
|
bb.put((byte)(count - 1));
|
|
bb.putLong(values[i]);
|
|
}
|
|
dup.putInt(recCount);
|
|
}
|
|
|
|
public static Long parse(ByteBuffer bb) {
|
|
Long rl = new Long();
|
|
int recCount = bb.getInt();
|
|
for (int i = 0; i < recCount; i++) {
|
|
int count = (bb.get() & 0xFF) + 1;
|
|
long value = bb.getLong();
|
|
rl.counts.add(count);
|
|
rl.values.add(value);
|
|
}
|
|
return rl;
|
|
}
|
|
|
|
protected int recSize() {
|
|
return 9;
|
|
}
|
|
|
|
public long[] flattern() {
|
|
int[] counts = getCounts();
|
|
int total = 0;
|
|
for (int i = 0; i < counts.length; i++)
|
|
total += counts[i];
|
|
long[] values = getValues();
|
|
long[] result = new long[total];
|
|
for (int j = 0, ind = 0; j < counts.length; j++) {
|
|
for (int k = 0; k < counts[j]; k++, ind++)
|
|
result[ind] = values[j];
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
}
|