mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-14 10:59:01 +00:00
249 lines
7.4 KiB
Java
249 lines
7.4 KiB
Java
package com.jpexs.decompiler.flash.flv;
|
|
|
|
import java.io.IOException;
|
|
import java.io.OutputStream;
|
|
import java.util.List;
|
|
|
|
/**
|
|
*
|
|
* @author JPEXS
|
|
*/
|
|
public class FLVOutputStream extends OutputStream {
|
|
|
|
private OutputStream os;
|
|
private int bitPos = 0;
|
|
private int tempByte = 0;
|
|
private long pos = 0;
|
|
|
|
public FLVOutputStream(OutputStream os) {
|
|
this.os = os;
|
|
}
|
|
|
|
public long getPos() {
|
|
return pos;
|
|
}
|
|
|
|
/**
|
|
* Writes byte to the stream
|
|
*
|
|
* @param b byte to write
|
|
* @throws IOException
|
|
*/
|
|
@Override
|
|
public void write(int b) throws IOException {
|
|
alignByte();
|
|
os.write(b);
|
|
pos++;
|
|
}
|
|
|
|
private void alignByte() throws IOException {
|
|
if (bitPos > 0) {
|
|
bitPos = 0;
|
|
write(tempByte);
|
|
tempByte = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes UI8 (Unsigned 8bit integer) value to the stream
|
|
*
|
|
* @param val UI8 value to write
|
|
* @throws IOException
|
|
*/
|
|
public void writeUI8(int val) throws IOException {
|
|
write(val);
|
|
}
|
|
|
|
/**
|
|
* Writes UI24 (Unsigned 24bit integer) value to the stream
|
|
*
|
|
* @param value UI32 value
|
|
* @throws IOException
|
|
*/
|
|
public void writeUI24(long value) throws IOException {
|
|
write((int) ((value >> 16) & 0xff));
|
|
write((int) ((value >> 8) & 0xff));
|
|
write((int) (value & 0xff));
|
|
|
|
}
|
|
|
|
/**
|
|
* Writes UI32 (Unsigned 32bit integer) value to the stream
|
|
*
|
|
* @param value UI32 value
|
|
* @throws IOException
|
|
*/
|
|
public void writeUI32(long value) throws IOException {
|
|
write((int) ((value >> 24) & 0xff));
|
|
write((int) ((value >> 16) & 0xff));
|
|
write((int) ((value >> 8) & 0xff));
|
|
write((int) (value & 0xff));
|
|
}
|
|
|
|
/**
|
|
* Writes UI16 (Unsigned 16bit integer) value to the stream
|
|
*
|
|
* @param value UI16 value
|
|
* @throws IOException
|
|
*/
|
|
public void writeUI16(int value) throws IOException {
|
|
write((int) ((value >> 8) & 0xff));
|
|
write((int) (value & 0xff));
|
|
}
|
|
|
|
/**
|
|
* Writes UB[nBits] (Unsigned-bit value) value to the stream
|
|
*
|
|
* @param nBits Number of bits which represent value
|
|
* @param value Unsigned value to write
|
|
* @throws IOException
|
|
*/
|
|
public void writeUB(int nBits, long value) throws IOException {
|
|
for (int bit = 0; bit < nBits; bit++) {
|
|
int nb = (int) ((value >> (nBits - 1 - bit)) & 1);
|
|
tempByte += nb * (1 << (7 - bitPos));
|
|
bitPos++;
|
|
if (bitPos == 8) {
|
|
bitPos = 0;
|
|
write(tempByte);
|
|
tempByte = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void writeHeader(boolean audio, boolean video) throws IOException {
|
|
write("FLV".getBytes());
|
|
write(1); //version
|
|
writeUB(5, 0); //must be 0
|
|
writeUB(1, audio ? 1 : 0); //audio present
|
|
writeUB(1, 0); //reserved
|
|
writeUB(1, video ? 1 : 0); //video present
|
|
writeUI32(9); //header size
|
|
writeUI32(0);
|
|
}
|
|
|
|
public void writeTag(FLVTAG tag) throws IOException {
|
|
long posBefore = getPos();
|
|
writeUI8(tag.tagType);
|
|
byte data[] = tag.data.getBytes();
|
|
writeUI24(data.length);
|
|
writeUI24(tag.timeStamp & 0xffffff);
|
|
writeUI8((int) ((tag.timeStamp >> 24) & 0xff));
|
|
writeUI24(0);
|
|
write(data); //codecId 4, frameType 1
|
|
long posAfter = getPos();
|
|
long size = posAfter - posBefore;
|
|
writeUI32(size);
|
|
}
|
|
|
|
public void writeSCRIPTDATASTRING(String s) throws IOException {
|
|
int len = s.getBytes("UTF-8").length;
|
|
writeUI16(len);
|
|
write(s.getBytes("UTF-8"));
|
|
}
|
|
|
|
public void writeSCRIPTDATALONGSTRING(String s) throws IOException {
|
|
int len = s.getBytes("UTF-8").length;
|
|
writeUI32(len);
|
|
write(s.getBytes("UTF-8"));
|
|
}
|
|
|
|
private void writeLong(long value) throws IOException {
|
|
byte writeBuffer[] = new byte[8];
|
|
writeBuffer[3] = (byte) (value >>> 56);
|
|
writeBuffer[2] = (byte) (value >>> 48);
|
|
writeBuffer[1] = (byte) (value >>> 40);
|
|
writeBuffer[0] = (byte) (value >>> 32);
|
|
writeBuffer[7] = (byte) (value >>> 24);
|
|
writeBuffer[6] = (byte) (value >>> 16);
|
|
writeBuffer[5] = (byte) (value >>> 8);
|
|
writeBuffer[4] = (byte) (value);
|
|
write(writeBuffer);
|
|
}
|
|
|
|
public void writeDOUBLE(double value) throws IOException {
|
|
writeLong(Double.doubleToLongBits(value));
|
|
}
|
|
|
|
public void writeSCRIPTDATAOBJECT(SCRIPTDATAOBJECT o) throws IOException {
|
|
writeSCRIPTDATASTRING(o.objectName);
|
|
writeSCRIPTDATAVALUE(o.objectData);
|
|
}
|
|
|
|
public void writeSCRIPTDATAVARIABLE(SCRIPTDATAVARIABLE v) throws IOException {
|
|
writeSCRIPTDATASTRING(v.variableName);
|
|
writeSCRIPTDATAVALUE(v.variableData);
|
|
}
|
|
|
|
public void writeSCRIPTDATAVALUE(SCRIPTDATAVALUE v) throws IOException {
|
|
writeUI8(v.type);
|
|
switch (v.type) {
|
|
case 0:
|
|
writeDOUBLE((double) (Double) v.value);
|
|
break;
|
|
case 1:
|
|
writeUI8((boolean) (Boolean) v.value ? 1 : 0);
|
|
break;
|
|
case 2:
|
|
writeSCRIPTDATASTRING((String) v.value);
|
|
break;
|
|
case 3:
|
|
@SuppressWarnings("unchecked")
|
|
List<SCRIPTDATAOBJECT> objects = (List<SCRIPTDATAOBJECT>) v.value;
|
|
for (SCRIPTDATAOBJECT o : objects) {
|
|
writeSCRIPTDATAOBJECT(o);
|
|
}
|
|
writeUI24(9);//SCRIPTDATAOBJECTEND
|
|
break;
|
|
case 4:
|
|
writeSCRIPTDATASTRING((String) v.value);
|
|
break;
|
|
case 5:
|
|
//null
|
|
break;
|
|
case 6:
|
|
//undefined
|
|
break;
|
|
case 7:
|
|
writeUI16((int) (Integer) v.value);
|
|
break;
|
|
case 8:
|
|
@SuppressWarnings("unchecked")
|
|
List<SCRIPTDATAVARIABLE> variables = (List<SCRIPTDATAVARIABLE>) v.value;
|
|
writeUI32(variables.size());
|
|
for (SCRIPTDATAVARIABLE var : variables) {
|
|
writeSCRIPTDATAVARIABLE(var);
|
|
}
|
|
writeUI24(9);//SCRIPTDATAVARIABLEEND
|
|
break;
|
|
case 9:
|
|
//reserved
|
|
break;
|
|
case 10:
|
|
@SuppressWarnings("unchecked")
|
|
List<SCRIPTDATAVARIABLE> stvariables = (List<SCRIPTDATAVARIABLE>) v.value;
|
|
writeUI32(stvariables.size());
|
|
for (SCRIPTDATAVARIABLE var : stvariables) {
|
|
writeSCRIPTDATAVARIABLE(var);
|
|
}
|
|
break;
|
|
case 11:
|
|
writeSCRIPTDATADATE((SCRIPTDATADATE) v.value);
|
|
break;
|
|
case 12:
|
|
writeSCRIPTDATALONGSTRING((String) v.value);
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
public void writeSI16(int value) throws IOException {
|
|
writeUI16(value);
|
|
}
|
|
|
|
public void writeSCRIPTDATADATE(SCRIPTDATADATE d) throws IOException {
|
|
writeDOUBLE(d.dateTime);
|
|
writeSI16(d.localDateTimeOffset);
|
|
}
|
|
}
|