mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-05-30 23:55:40 +00:00
Added: FLA export - generating bin/*.dat files for movies and images
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.xfl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class BinDataOutputStream extends OutputStream {
|
||||
|
||||
private final OutputStream os;
|
||||
|
||||
public BinDataOutputStream(OutputStream os) {
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
os.write(b);
|
||||
}
|
||||
|
||||
public void write(int... values) throws IOException {
|
||||
for (int i : values) {
|
||||
os.write(i);
|
||||
}
|
||||
}
|
||||
|
||||
public void writeUI16(int value) throws IOException {
|
||||
write(value & 0xFF);
|
||||
write((value >> 8) & 0xFF);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
os.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
os.write(b, off, len);
|
||||
}
|
||||
|
||||
public void writeUI32(long value) throws IOException {
|
||||
write((int) (value & 0xFF));
|
||||
write((int) ((value >> 8) & 0xFF));
|
||||
write((int) ((value >> 16) & 0xFF));
|
||||
write((int) ((value >> 24) & 0xFF));
|
||||
}
|
||||
|
||||
public void writeUI64(long value) throws IOException {
|
||||
write((int) (value & 0xFF));
|
||||
write((int) ((value >> 8) & 0xFF));
|
||||
write((int) ((value >> 16) & 0xFF));
|
||||
write((int) ((value >> 24) & 0xFF));
|
||||
write((int) ((value >> 32) & 0xFF));
|
||||
write((int) ((value >> 40) & 0xFF));
|
||||
write((int) ((value >> 48) & 0xFF));
|
||||
write((int) ((value >> 56) & 0xFF));
|
||||
}
|
||||
|
||||
public void writeFloat(float val) throws IOException {
|
||||
writeUI32(Float.floatToIntBits(val));
|
||||
}
|
||||
|
||||
public void writeDouble(double val) throws IOException {
|
||||
writeUI64(Double.doubleToLongBits(val));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.xfl;
|
||||
|
||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ImageBinDataGenerator {
|
||||
|
||||
public void generateBinData(InputStream is, OutputStream os, ImageFormat format) throws IOException {
|
||||
BufferedImage bimg = ImageIO.read(is);
|
||||
if (format == ImageFormat.JPEG) {
|
||||
byte[] buf = new byte[4096];
|
||||
int cnt;
|
||||
while ((cnt = is.read(buf)) > 0) {
|
||||
os.write(buf, 0, cnt);
|
||||
}
|
||||
BinDataOutputStream dw2 = new BinDataOutputStream(os);
|
||||
dw2.writeUI32(0);
|
||||
dw2.writeUI32(0);
|
||||
dw2.writeUI32(20 * bimg.getWidth());
|
||||
dw2.writeUI32(20 * bimg.getHeight());
|
||||
} else {
|
||||
//https://stackoverflow.com/questions/4082812/xfl-what-are-the-bin-dat-files/4082907#4082907
|
||||
os.write(0x03);
|
||||
os.write(0x05);
|
||||
BinDataOutputStream w = new BinDataOutputStream(os);
|
||||
|
||||
int decRowLen = 4 * bimg.getWidth();
|
||||
w.writeUI16(decRowLen);
|
||||
|
||||
w.writeUI16(bimg.getWidth());
|
||||
w.writeUI16(bimg.getHeight());
|
||||
|
||||
w.writeUI32(0);
|
||||
w.writeUI32(0);
|
||||
w.writeUI32(20 * bimg.getWidth());
|
||||
w.writeUI32(20 * bimg.getHeight());
|
||||
|
||||
w.write(0x01); //has transparency
|
||||
w.write(0x01); //compressed variant
|
||||
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
DeflaterOutputStream def = new DeflaterOutputStream(baos, new Deflater(1));
|
||||
|
||||
for (int y = 0; y < bimg.getHeight(); y++) {
|
||||
for (int x = 0; x < bimg.getWidth(); x++) {
|
||||
int rgba = bimg.getRGB(x, y);
|
||||
def.write((rgba >> 24) & 0xFF); //a
|
||||
def.write((rgba >> 16) & 0xFF); //b
|
||||
def.write((rgba >> 8) & 0xFF); //g
|
||||
def.write(rgba & 0xFF); //r
|
||||
}
|
||||
}
|
||||
def.flush();
|
||||
def.finish();
|
||||
byte[] data = baos.toByteArray();
|
||||
int pos = 0;
|
||||
while (pos < data.length) {
|
||||
int cnt = 2048; //it seems that using large chunk sizes like 0xFFFF crashes flash. 2024 is used in CS5.
|
||||
if (pos + cnt > data.length) {
|
||||
cnt = data.length - pos;
|
||||
}
|
||||
w.writeUI16(cnt);
|
||||
os.write(data, pos, cnt);
|
||||
pos += cnt;
|
||||
}
|
||||
w.writeUI16(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2024 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.xfl;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.flv.AUDIODATA;
|
||||
import com.jpexs.decompiler.flash.flv.FLVInputStream;
|
||||
import com.jpexs.decompiler.flash.flv.FLVTAG;
|
||||
import com.jpexs.decompiler.flash.flv.SCRIPTDATA;
|
||||
import com.jpexs.decompiler.flash.flv.SCRIPTDATAVARIABLE;
|
||||
import com.jpexs.decompiler.flash.flv.VIDEODATA;
|
||||
import com.jpexs.decompiler.flash.types.sound.SoundFormat;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class MovieBinDataGenerator {
|
||||
|
||||
public byte[] generateEmptyBinData() {
|
||||
return new byte[]{
|
||||
(byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xA0, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x78, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x59, (byte) 0x40, (byte) 0x18, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0xFE, (byte) 0xFF,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
|
||||
};
|
||||
}
|
||||
|
||||
public void generateBinData(InputStream is, OutputStream os, float fps) throws IOException {
|
||||
BinDataOutputStream df = new BinDataOutputStream(os);
|
||||
FLVInputStream flvIs = new FLVInputStream(is);
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
Reference<Boolean> audioPresent = new Reference<>(false);
|
||||
Reference<Boolean> videoPresent = new Reference<>(false);
|
||||
flvIs.readHeader(audioPresent, videoPresent);
|
||||
List<FLVTAG> flvTags = flvIs.readTags();
|
||||
long lastOffset = 0L;
|
||||
long videoFrameCount = 0;
|
||||
|
||||
int soundFormat = 0;
|
||||
int samplingRate = 0;
|
||||
boolean stereo = false;
|
||||
int videoCodec = 0;
|
||||
boolean hasAudio = false;
|
||||
long maxTimestamp = 0L;
|
||||
for (FLVTAG tag : flvTags) {
|
||||
if (tag.timeStamp > maxTimestamp) {
|
||||
maxTimestamp = tag.timeStamp;
|
||||
}
|
||||
if (tag.data instanceof VIDEODATA) {
|
||||
videoFrameCount++;
|
||||
VIDEODATA vd = (VIDEODATA) tag.data;
|
||||
videoCodec = vd.codecId;
|
||||
}
|
||||
if (tag.data instanceof AUDIODATA) {
|
||||
AUDIODATA ad = (AUDIODATA) tag.data;
|
||||
soundFormat = ad.soundFormat;
|
||||
samplingRate = ad.soundRate;
|
||||
stereo = ad.soundType;
|
||||
hasAudio = true;
|
||||
}
|
||||
}
|
||||
|
||||
long videoDataIndex = 0;
|
||||
for (FLVTAG tag : flvTags) {
|
||||
if (tag.data instanceof SCRIPTDATA) {
|
||||
SCRIPTDATA sd = (SCRIPTDATA) tag.data;
|
||||
if (sd.name.type != 2) {
|
||||
continue;
|
||||
}
|
||||
if (!"onMetaData".equals(sd.name.value)) {
|
||||
continue;
|
||||
}
|
||||
if (sd.value.type != 8) {
|
||||
continue;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> subVals = (List) sd.value.value;
|
||||
for (Object o : subVals) {
|
||||
if (o instanceof SCRIPTDATAVARIABLE) {
|
||||
SCRIPTDATAVARIABLE v = (SCRIPTDATAVARIABLE) o;
|
||||
if ("width".equals(v.variableName)) {
|
||||
width = (int) (double) v.variableData.value;
|
||||
}
|
||||
if ("height".equals(v.variableName)) {
|
||||
height = (int) (double) v.variableData.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
df.write(0x03, videoCodec, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x28, 0x40,
|
||||
0x00, 0x00, 0x00, 0x00);
|
||||
if (hasAudio) {
|
||||
df.write(0x80, 0x88, 0xE5, 0x40, 0x10);
|
||||
} else {
|
||||
df.write(0x00, 0x00, 0x00, 0x00, 0x00);
|
||||
}
|
||||
df.write(0x00, 0x00, 0x00);
|
||||
if (hasAudio) {
|
||||
if (stereo) {
|
||||
df.write(2);
|
||||
} else {
|
||||
df.write(1);
|
||||
}
|
||||
} else {
|
||||
df.write(0);
|
||||
}
|
||||
df.write(0x00, 0x00, 0x00);
|
||||
|
||||
df.writeUI32(width);
|
||||
df.writeUI32(height);
|
||||
df.writeDouble(videoFrameCount / fps);
|
||||
|
||||
df.write(
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x59, 0x40, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
|
||||
);
|
||||
|
||||
}
|
||||
if (tag.data instanceof VIDEODATA) {
|
||||
VIDEODATA vd = (VIDEODATA) tag.data;
|
||||
long startOffset = lastOffset;
|
||||
df.writeUI32(startOffset);
|
||||
df.writeUI32(vd.videoData.length);
|
||||
lastOffset = startOffset + vd.videoData.length;
|
||||
df.write(0x01, 0x00, 0x00, 0x00, 0x04 + (vd.frameType == 1 ? 1 : 0), 0x00, 0x00, 0x00);
|
||||
if (videoDataIndex < videoFrameCount - 1) {
|
||||
df.write(0x01);
|
||||
} else {
|
||||
df.write(0x00);
|
||||
}
|
||||
videoDataIndex++;
|
||||
}
|
||||
}
|
||||
df.writeUI32(lastOffset);
|
||||
for (FLVTAG tag : flvTags) {
|
||||
if (tag.data instanceof VIDEODATA) {
|
||||
VIDEODATA vd = (VIDEODATA) tag.data;
|
||||
df.write(vd.videoData);
|
||||
}
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
for (FLVTAG tag : flvTags) {
|
||||
if (tag.data instanceof AUDIODATA) {
|
||||
AUDIODATA ad = (AUDIODATA) tag.data;
|
||||
baos.write(ad.soundData);
|
||||
}
|
||||
}
|
||||
|
||||
df.writeUI32(1);
|
||||
if (hasAudio) {
|
||||
SoundFormat sf = new SoundFormat(soundFormat, samplingRate, stereo);
|
||||
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
|
||||
sf.decode(new SWFInputStream(new ByteArrayInputStream(baos.toByteArray())), baos2);
|
||||
df.writeUI32(1);
|
||||
df.write(0);
|
||||
df.writeUI32(baos2.size());
|
||||
df.writeUI32(1);
|
||||
df.writeUI32(0);
|
||||
df.write(0);
|
||||
df.writeUI32(baos2.size());
|
||||
df.write(baos2.toByteArray());
|
||||
} else {
|
||||
df.writeUI32(0);
|
||||
df.write(0);
|
||||
}
|
||||
df.write(0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFE, 0xFF, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -161,6 +161,8 @@ import com.jpexs.helpers.utf8.Utf8Helper;
|
||||
import java.awt.Font;
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
@@ -2063,7 +2065,15 @@ public class XFLConverter {
|
||||
writer.writeAttribute("frameRight", image.getWidth());
|
||||
writer.writeAttribute("frameBottom", image.getHeight());
|
||||
writer.writeEndElement();
|
||||
datfiles.put(datFileName, new byte[0]); //empty byte arrays are not written
|
||||
|
||||
ImageBinDataGenerator ibg = new ImageBinDataGenerator();
|
||||
ByteArrayOutputStream iba = new ByteArrayOutputStream();
|
||||
try {
|
||||
ibg.generateBinData(new ByteArrayInputStream(imageBytes), iba, format);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, "Error during bin/dat file generation for image", ex);
|
||||
}
|
||||
datfiles.put(datFileName, iba.toByteArray());
|
||||
statusStack.popStatus();
|
||||
} else if (symbol instanceof DefineSoundTag) {
|
||||
statusStack.pushStatus(symbol.toString());
|
||||
@@ -2134,22 +2144,9 @@ public class XFLConverter {
|
||||
writer.writeAttribute("linkageURL", characterImportLinkageURL.get(symbol));
|
||||
}
|
||||
writer.writeEndElement();
|
||||
//Use the dat file, otherwise it does not work
|
||||
datfiles.put(datFileName, new byte[]{ //Magic numbers, if anybody knows why, please tell me
|
||||
(byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xA0, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x78, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x59, (byte) 0x40, (byte) 0x18, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xFF, (byte) 0xFE, (byte) 0xFF,
|
||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00
|
||||
});
|
||||
|
||||
MovieBinDataGenerator mbd = new MovieBinDataGenerator();
|
||||
datfiles.put(datFileName, mbd.generateEmptyBinData());
|
||||
} else {
|
||||
files.put(symbolFile, data);
|
||||
writer.writeStartElement("DOMVideoItem", new String[]{
|
||||
@@ -2184,6 +2181,19 @@ public class XFLConverter {
|
||||
|
||||
writer.writeAttribute("linkageExportForAS", true);
|
||||
}
|
||||
|
||||
long ts = getTimestamp(swf);
|
||||
String datFileName = "M " + (datfiles.size() + 1) + " " + ts + ".dat";
|
||||
writer.writeAttribute("videoDataHRef", datFileName);
|
||||
MovieBinDataGenerator mbg = new MovieBinDataGenerator();
|
||||
ByteArrayOutputStream bba = new ByteArrayOutputStream();
|
||||
try {
|
||||
mbg.generateBinData(new ByteArrayInputStream(data), bba, swf.frameRate);
|
||||
} catch (IOException ex) {
|
||||
Logger.getLogger(XFLConverter.class.getName()).log(Level.SEVERE, "Error during bin/dat file generation for movie", ex);
|
||||
}
|
||||
datfiles.put(datFileName, bba.toByteArray());
|
||||
|
||||
writer.writeEndElement();
|
||||
}
|
||||
statusStack.popStatus();
|
||||
|
||||
Reference in New Issue
Block a user