diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java index 13a9ca1cd..876a649f7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWF.java @@ -206,7 +206,7 @@ public final class SWF implements SWFContainerItem, Timelined { /** * Movie frame rate */ - public int frameRate; + public float frameRate; /** * Number of frames in movie @@ -767,8 +767,7 @@ public final class SWF implements SWFContainerItem, Timelined { sos.writeUI8(version); sos.writeUI32(0); // placeholder for file length sos.writeRECT(displayRect); - sos.writeUI8(0); - sos.writeUI8(frameRate); + sos.writeFIXED8(frameRate); sos.writeUI16(frameCount); sos.writeTags(tags); @@ -1037,9 +1036,7 @@ public final class SWF implements SWFContainerItem, Timelined { } sis.setPercentMax(fileSize); displayRect = sis.readRECT("displayRect"); - // FIXED8 (16 bit fixed point) frameRate - sis.readUI8("tmpFirstByetOfFrameRate"); // tmpFirstByetOfFrameRate - frameRate = sis.readUI8("frameRate"); + frameRate = sis.readFIXED8("frameRate"); frameCount = sis.readUI16("frameCount"); List tags = sis.readTagList(this, 0, parallelRead, true, !checkOnly, lazy); if (tags.size() > 0 && tags.get(tags.size() - 1).getId() == EndTag.ID) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java index 80b5f7b5a..f85969225 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFInputStream.java @@ -617,11 +617,22 @@ public class SWFInputStream implements AutoCloseable { */ public int readSI8(String name) throws IOException { newDumpLevel(name, "SI8"); + int ret = readSI8Internal(); + endDumpLevel(ret); + return ret; + } + + /** + * Reads one SI8 (Signed 8bit integer) value from the stream + * + * @return SI8 value + * @throws IOException + */ + public int readSI8Internal() throws IOException { int uval = readEx(); if (uval >= 0x80) { uval = -(((~uval) & 0xff) + 1); } - endDumpLevel(uval); return uval; } @@ -636,13 +647,13 @@ public class SWFInputStream implements AutoCloseable { newDumpLevel(name, "FIXED"); int afterPoint = readUI16Internal(); int beforePoint = readUI16Internal(); - double ret = ((double) ((beforePoint << 16) + afterPoint)) / 65536; + double ret = beforePoint + ((double) (afterPoint)) / 65536; endDumpLevel(ret); return ret; } /** - * Reads one FIXED8 (Fixed point 8.8) value from the stream + * Reads one FIXED8 (Fixed point 8.8) signed value from the stream * * @param name * @return FIXED8 value @@ -651,8 +662,13 @@ public class SWFInputStream implements AutoCloseable { public float readFIXED8(String name) throws IOException { newDumpLevel(name, "FIXED8"); int afterPoint = readEx(); - int beforePoint = readEx(); - float ret = beforePoint + (((float) afterPoint) / 256); + int beforePoint = readSI8Internal(); + float ret; + if (beforePoint < 0) { + ret = beforePoint - ((float) afterPoint) / 256; + } else { + ret = beforePoint + ((float) afterPoint) / 256; + } endDumpLevel(ret); return ret; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java index 0fd822caf..e51aa2ce2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/SWFOutputStream.java @@ -295,7 +295,6 @@ public class SWFOutputStream extends OutputStream { public void writeFIXED(double value) throws IOException { long valueLong = (long) (value * (1 << 16)); int beforePoint = (int) valueLong >> 16; - int afterPoint = (int) valueLong % (1 << 16); writeUI16(afterPoint); writeUI16(beforePoint); @@ -308,10 +307,11 @@ public class SWFOutputStream extends OutputStream { * @throws IOException */ public void writeFIXED8(float value) throws IOException { - int beforePoint = (int) getIntPart(value); - int afterPoint = (int) getIntPart((value + (value < 0 ? beforePoint : -beforePoint)) * 256); + final int divisor = 1 << 8; + int beforePoint = (int) value; + int afterPoint = Math.abs((int) (value * divisor)) % divisor; writeUI8(afterPoint); - writeUI8(beforePoint); + writeSI8(beforePoint); } private void writeLong(long value) throws IOException { @@ -578,13 +578,6 @@ public class SWFOutputStream extends OutputStream { return nBits; } - private static long getIntPart(double value) { - if (value < 0) { - return (long) Math.ceil(value); - } - return (long) Math.floor(value); - } - public static int unsignedSize(final int value) { final int val = (value < 0) ? -value - 1 : value; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java index eff02a84e..de78e69e8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/FrameExporter.java @@ -438,14 +438,14 @@ public class FrameExporter { return "[" + rgb.red + "," + rgb.green + "," + rgb.blue + "," + ((rgb instanceof RGBA) ? ((RGBA) rgb).getAlphaFloat() : 1) + "]"; } - public static void makeAVI(Iterator images, int frameRate, File file, EventListener evl) throws IOException { + public static void makeAVI(Iterator images, float frameRate, File file, EventListener evl) throws IOException { if (!images.hasNext()) { return; } AVIWriter out = new AVIWriter(file); BufferedImage img0 = images.next(); - out.addVideoTrack(VideoFormatKeys.ENCODING_AVI_PNG, 1, frameRate, img0.getWidth(), img0.getHeight(), 0, 0); + out.addVideoTrack(VideoFormatKeys.ENCODING_AVI_PNG, 1, (int) frameRate, img0.getWidth(), img0.getHeight(), 0, 0); try { out.write(0, img0, 1); while (images.hasNext()) { @@ -456,7 +456,7 @@ public class FrameExporter { } } - public static void makeGIF(Iterator images, int frameRate, File file, EventListener evl) throws IOException { + public static void makeGIF(Iterator images, float frameRate, File file, EventListener evl) throws IOException { if (!images.hasNext()) { return; } @@ -464,7 +464,7 @@ public class FrameExporter { AnimatedGifEncoder encoder = new AnimatedGifEncoder(); encoder.setRepeat(0); // repeat forever encoder.start(file.getAbsolutePath()); - encoder.setDelay(1000 / frameRate); + encoder.setDelay((int) (1000.0 / frameRate)); while (images.hasNext()) { encoder.addFrame(images.next()); } @@ -472,14 +472,14 @@ public class FrameExporter { encoder.finish(); } - public static void makeGIFOld(Iterator images, int frameRate, File file, EventListener evl) throws IOException { + public static void makeGIFOld(Iterator images, float frameRate, File file, EventListener evl) throws IOException { if (!images.hasNext()) { return; } try (ImageOutputStream output = new FileImageOutputStream(file)) { BufferedImage img0 = images.next(); - GifSequenceWriter writer = new GifSequenceWriter(output, img0.getType(), 1000 / frameRate, true); + GifSequenceWriter writer = new GifSequenceWriter(output, img0.getType(), (int) (1000.0 / frameRate), true); writer.writeToSequence(img0); while (images.hasNext()) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java index 6483aeb33..90cc8c700 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/MovieExporter.java @@ -180,7 +180,7 @@ public class MovieExporter { } baos.write(tag.videoData.getRangeData()); - flv.writeTag(new FLVTAG((int) Math.floor(i * 1000.0f / ((float) swf.frameRate)), new VIDEODATA(frameType, videoStream.codecID, baos.toByteArray()))); + flv.writeTag(new FLVTAG((int) Math.floor(i * 1000.0 / swf.frameRate), new VIDEODATA(frameType, videoStream.codecID, baos.toByteArray()))); } return fos.toByteArray(); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java index 62cab26e1..59b8450c4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/exporters/SoundExporter.java @@ -147,7 +147,7 @@ public class SoundExporter { flv.writeHeader(true, false); List blocks = sh.getBlocks(); - int ms = (int) (1000.0f / ((float) ((Tag) st).getSwf().frameRate)); + int ms = (int) (1000.0 / ((Tag) st).getSwf().frameRate); for (int b = 0; b < blocks.size(); b++) { byte[] data = blocks.get(b).streamSoundData.getRangeData(); if (st.getSoundFormatId() == 2) { //MP3 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java index 0da7e08fe..8cef1db13 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/timeline/Timeline.java @@ -66,7 +66,7 @@ public class Timeline { public RECT displayRect; - public int frameRate; + public float frameRate; public Timelined timelined; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java index c048e0ce8..0461d831d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/xfl/XFLConverter.java @@ -1577,10 +1577,10 @@ public class XFLConverter { mediaLinkStr = " videoFrames = new HashMap<>(); if (tagObj instanceof DefineVideoStreamTag) { DefineVideoStreamTag vs = (DefineVideoStreamTag) tagObj; @@ -634,7 +634,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel if ((tagObj instanceof DefineMorphShapeTag) || (tagObj instanceof DefineMorphShape2Tag)) { frameRate = MainPanel.MORPH_SHAPE_ANIMATION_FRAME_RATE; - frameCount = MainPanel.MORPH_SHAPE_ANIMATION_LENGTH * frameRate; + frameCount = (int) (MainPanel.MORPH_SHAPE_ANIMATION_LENGTH * frameRate); } if (tagObj instanceof DefineSoundTag) { @@ -660,8 +660,7 @@ public class PreviewPanel extends JPersistentSplitPane implements TagEditorPanel int height = outrect.getHeight(); sos2.writeRECT(outrect); - sos2.writeUI8(0); - sos2.writeUI8(frameRate); + sos2.writeFIXED8(frameRate); sos2.writeUI16(frameCount); //framecnt /*FileAttributesTag fa = new FileAttributesTag(); diff --git a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java index 76ef02d6e..fd3a2b504 100644 --- a/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java +++ b/src/com/jpexs/decompiler/flash/gui/SoundTagPlayer.java @@ -299,7 +299,7 @@ public class SoundTagPlayer implements MediaDisplay { } @Override - public int getFrameRate() { + public float getFrameRate() { return (int) (1000000L / FRAME_DIVISOR); } diff --git a/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java b/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java index 335384619..e217c58a1 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java +++ b/src/com/jpexs/decompiler/flash/gui/player/MediaDisplay.java @@ -48,7 +48,7 @@ public interface MediaDisplay extends Closeable { public void setBackground(Color color); - public int getFrameRate(); + public float getFrameRate(); public boolean isLoaded(); diff --git a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java index 6b06ffc76..fb3fd5e15 100644 --- a/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java +++ b/src/com/jpexs/decompiler/flash/gui/player/PlayerControls.java @@ -348,7 +348,7 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { if (currentFrame >= totalFrames) { currentFrame = totalFrames - 1; } - int frameRate = display.getFrameRate(); + float frameRate = display.getFrameRate(); if (totalFrames == 0) { progress.setIndeterminate(true); } else { @@ -360,8 +360,8 @@ public class PlayerControls extends JPanel implements MediaDisplayListener { frameLabel.setText(("" + (currentFrame + 1))); totalFrameLabel.setText("" + totalFrames); if (frameRate != 0) { - timeLabel.setText("(" + formatMs((currentFrame * 1000) / frameRate) + ")"); - totalTimeLabel.setText("(" + formatMs((totalFrames * 1000) / frameRate) + ")"); + timeLabel.setText("(" + formatMs((int) (currentFrame * 1000.0 / frameRate)) + ")"); + totalTimeLabel.setText("(" + formatMs((int) (totalFrames * 1000.0 / frameRate)) + ")"); } if (totalFrames <= 1 && playbackControls.isVisible()) { playbackControls.setVisible(false);