From f2646f164b4b28a94b425dfc5cb4b8f4643521d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 26 Dec 2022 00:30:14 +0100 Subject: [PATCH] Replace movies with commandline --- .../flash/tags/DefineVideoStreamTag.java | 345 ++++++++++++++++-- .../console/CommandLineArgumentParser.java | 15 +- .../jpexs/decompiler/flash/gui/MainPanel.java | 318 +--------------- 3 files changed, 325 insertions(+), 353 deletions(-) diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java index 794bc39e0..42fe3bb8a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/tags/DefineVideoStreamTag.java @@ -26,9 +26,13 @@ import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.exporters.commonshape.Matrix; import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter; import com.jpexs.decompiler.flash.exporters.modes.MovieExportMode; +import com.jpexs.decompiler.flash.flv.FLVInputStream; +import com.jpexs.decompiler.flash.flv.FLVTAG; +import com.jpexs.decompiler.flash.flv.VIDEODATA; import com.jpexs.decompiler.flash.tags.base.BoundedTag; import com.jpexs.decompiler.flash.tags.base.ButtonTag; import com.jpexs.decompiler.flash.tags.base.DrawableTag; +import com.jpexs.decompiler.flash.tags.base.PlaceObjectTypeTag; import com.jpexs.decompiler.flash.tags.base.RenderContext; import com.jpexs.decompiler.flash.timeline.Timeline; import com.jpexs.decompiler.flash.timeline.Timelined; @@ -45,6 +49,7 @@ import com.jpexs.decompiler.flash.types.annotations.SWFVersion; import com.jpexs.decompiler.flash.types.filters.BlendComposite; import com.jpexs.helpers.ByteArrayRange; import com.jpexs.helpers.Helper; +import com.jpexs.helpers.Reference; import com.jpexs.helpers.SerializableImage; import com.jpexs.video.FrameListener; import com.jpexs.video.SimpleMediaPlayer; @@ -57,9 +62,15 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -94,8 +105,8 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim @Reserved @SWFType(value = BasicType.UB, count = 4) public int reserved; - - @SWFType(value = BasicType.UB, count = 3) + + @SWFType(value = BasicType.UB, count = 3) @EnumValue(value = DefineVideoStreamTag.DEBLOCKING_USE_VIDEOPACKET_VALUE, text = "use VIDEOPACKET value") @EnumValue(value = DefineVideoStreamTag.DEBLOCKING_OFF, text = "off") @EnumValue(value = DefineVideoStreamTag.DEBLOCKING_LEVEL1, text = "Level 1 (Fast deblocking filter)") @@ -108,7 +119,7 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim public boolean videoFlagsSmoothing; - @SWFType(BasicType.UI8) + @SWFType(BasicType.UI8) @EnumValue(value = DefineVideoStreamTag.CODEC_JPEG, text = "JPEG (unused)") @EnumValue(value = DefineVideoStreamTag.CODEC_SORENSON_H263, text = "Sorenson H.263") @EnumValue(value = DefineVideoStreamTag.CODEC_SCREEN_VIDEO, text = "Screen video") @@ -134,24 +145,24 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim @Internal private Timeline timeline; - + @Internal private Map frames; - + private static final List players = new ArrayList<>(); private static List tempFiles = new ArrayList<>(); - + @Internal private boolean renderingPaused = false; - public static final int CODEC_JPEG = 1; + public static final int CODEC_JPEG = 1; public static final int CODEC_SORENSON_H263 = 2; public static final int CODEC_SCREEN_VIDEO = 3; public static final int CODEC_VP6 = 4; public static final int CODEC_VP6_ALPHA = 5; public static final int CODEC_SCREEN_VIDEO_V2 = 6; public static final int CODEC_AVC = 7; //Is this FLV only, or SWF too? - + /** * use VIDEOPACKET value */ @@ -178,24 +189,22 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim public static final int DEBLOCKING_LEVEL4 = 5; public static final int DEBLOCKING_RESERVED1 = 6; public static final int DEBLOCKING_RESERVED2 = 7; - - - + static { - Runtime.getRuntime().addShutdownHook(new Thread(){ + Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { - for (SimpleMediaPlayer p:players) { - p.stop(); - } - for (File f:tempFiles) { - f.delete(); - } + for (SimpleMediaPlayer p : players) { + p.stop(); + } + for (File f : tempFiles) { + f.delete(); + } } - + }); } - + /** * Constructor * @@ -276,7 +285,7 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim public static boolean displayAvailable() { return SimpleMediaPlayer.isAvailable(); } - + private void initPlayer() { if (mediaPlayer != null) { // && !mediaPlayer.isFinished()) { return; @@ -319,20 +328,22 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation, boolean stroked, ExportRectangle viewRect, double unzoom) { return transformation.toTransform().createTransformedShape(new Rectangle2D.Double(0, 0, width * SWF.unitDivisor, height * SWF.unitDivisor)); } - + public synchronized void resetPlayer() { - mediaPlayer.stop(); - mediaPlayer = null; + if (mediaPlayer != null) { + mediaPlayer.stop(); + mediaPlayer = null; + } } public synchronized void setPauseRendering(boolean value) { this.renderingPaused = value; activeFrame = null; } - + @Override public synchronized void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix prevTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode) { - + if (renderingPaused || !SimpleMediaPlayer.isAvailable()) { Graphics2D g = (Graphics2D) image.getBufferedImage().getGraphics(); Matrix mat = transformation; @@ -354,28 +365,27 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim if (ratio == -1) { ratio = 0; } - + Set keyFrames = getFrames().keySet(); - + int f = 0; - for(int i = 0; i <= ratio; i++) { + for (int i = 0; i <= ratio; i++) { if (keyFrames.contains(i)) { f = i; } } - + synchronized (DefineVideoStreamTag.class) { - if (!(activeFrame != null && lastFrame == f)) - { + if (!(activeFrame != null && lastFrame == f)) { initPlayer(); - - float oneFr = 0; //1f / (getNumFrames() + 2); - + + float oneFr = 0; //1f / (getNumFrames() + 2); + synchronized (getFrameLock) { activeFrame = null; - } - mediaPlayer.setPosition(((float) f) / (getNumFrames() + 2) - (f == 0 ? 0 : oneFr / 10f)); - + } + mediaPlayer.setPosition(((float) f) / (getNumFrames() + 2) - (f == 0 ? 0 : oneFr / 10f)); + try { synchronized (getFrameLock) { if (activeFrame == null) { @@ -435,7 +445,7 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim initTimeline(); return timeline; } - + private Map getFrames() { if (this.frames != null) { return this.frames; @@ -523,4 +533,261 @@ public class DefineVideoStreamTag extends DrawableTag implements BoundedTag, Tim public int getFrameCount() { return numFrames; } + + public void replace(InputStream fis) throws IOException { + List videoTags = new ArrayList<>(); + + FLVInputStream flvIs = new FLVInputStream(fis); + Reference audioPresent = new Reference<>(false); + Reference videoPresent = new Reference<>(false); + flvIs.readHeader(audioPresent, videoPresent); + List flvTags = flvIs.readTags(); + + for (FLVTAG tag : flvTags) { + if (tag.tagType == FLVTAG.DATATYPE_VIDEO) { + videoTags.add(tag); + } + } + if (!videoTags.isEmpty()) { + FLVTAG firstVideoTag = videoTags.get(0); + VIDEODATA videoData = ((VIDEODATA) firstVideoTag.data); + FLVInputStream dis = new FLVInputStream(new ByteArrayInputStream(videoData.videoData)); + int newWidth = 0; + int newHeight = 0; + switch (videoData.codecId) { + case VIDEODATA.CODEC_SORENSON_H263: + dis.readUB(17); //pictureStartCode + dis.readUB(5); //version + dis.readUB(8); //temporalReference + int pictureSize = (int) dis.readUB(3); + switch (pictureSize) { + case 0: + newWidth = (int) dis.readUB(8); + newHeight = (int) dis.readUB(8); + break; + case 1: + newWidth = (int) dis.readUB(16); + newHeight = (int) dis.readUB(16); + break; + case 2: + newWidth = 352; + newHeight = 288; + break; + case 3: + newWidth = 176; + newHeight = 144; + break; + case 4: + newWidth = 128; + newHeight = 96; + break; + case 5: + newWidth = 320; + newHeight = 240; + break; + case 6: + newWidth = 160; + newHeight = 120; + break; + } + + break; + case VIDEODATA.CODEC_SCREEN_VIDEO: + case VIDEODATA.CODEC_SCREEN_VIDEO_V2: + dis.readUB(4); //blockWidth + newWidth = (int) dis.readUB(12); + dis.readUB(4); //blockHeight + newHeight = (int) dis.readUB(12); + break; + case VIDEODATA.CODEC_VP6: + case VIDEODATA.CODEC_VP6_ALPHA: + int horizontalAdjustment = (int) dis.readUB(4); + int verticalAdjustment = (int) dis.readUB(4); + if (videoData.codecId == VIDEODATA.CODEC_VP6_ALPHA) { + dis.readUI24(); //offsetToAlpha + } + + int frameMode = (int) dis.readUB(1); //frameMode + + dis.readUB(6); //qp + int multiStream = (int) dis.readUB(1); //marker + if (frameMode == 0) { + int vp3VersionNo = (int) dis.readUB(5); + int vpProfile = (int) dis.readUB(2); + dis.readUB(1); //interlace + if (multiStream == 1 || vpProfile == 0) { + dis.readUI16(); //offset + } + int dim_y = dis.readUI8(); + int dim_x = dis.readUI8(); + //dis.readUI8(); //render_y + //dis.readUI8(); //render_x + newWidth = 16 * dim_x - horizontalAdjustment; + newHeight = 16 * dim_y - verticalAdjustment; + } + break; + case VIDEODATA.CODEC_AVC: + throw new IOException("AVC codec is not supported for import"); + case VIDEODATA.CODEC_JPEG: + throw new IOException("JPEG codec is not supported for import"); + } + if (newWidth <= 0 || newHeight <= 0) { + throw new IOException("Invalid dimension"); + } + this.codecID = videoData.codecId; + this.width = newWidth; + this.height = newHeight; + this.videoFlagsDeblocking = DefineVideoStreamTag.DEBLOCKING_OFF; + this.videoFlagsSmoothing = true; + this.numFrames = videoTags.size(); + setPauseRendering(true); + + videoTags.sort(new Comparator() { + @Override + public int compare(FLVTAG o1, FLVTAG o2) { + return Long.compare(o1.timeStamp, o2.tagType); + } + }); + + //remove old VideoFrame tags + Map frames = new HashMap<>(); + SWF.populateVideoFrames(characterID, swf.getTags(), frames); + Timelined timelined = null; + for (VideoFrameTag t : frames.values()) { + t.getTimelined().removeTag(t); + timelined = t.getTimelined(); + } + timelined.resetTimeline(); + + int startFrame = 0; + int placeDepth = -1; + for (Tag t : timelined.getTags()) { + if (t instanceof ShowFrameTag) { + startFrame++; + } + if (t instanceof PlaceObjectTypeTag) { + PlaceObjectTypeTag pt = (PlaceObjectTypeTag) t; + if (pt.getCharacterId() == characterID) { + placeDepth = pt.getDepth(); + break; + } + } + } + + int importLastFrame = -1; + if (timelined != null) { + VideoFrameTag lastVideoFrame = null; + for (FLVTAG ftag : videoTags) { + videoData = ((VIDEODATA) ftag.data); + if (videoData.codecId == VIDEODATA.CODEC_VP6 || videoData.codecId == VIDEODATA.CODEC_VP6_ALPHA) { + int horizontalAdjustment = (int) dis.readUB(4); + int verticalAdjustment = (int) dis.readUB(4); + if (videoData.codecId == VIDEODATA.CODEC_VP6_ALPHA) { + dis.readUI24(); //offsetToAlpha + } + + int frameMode = (int) dis.readUB(1); //frameMode + + dis.readUB(6); //qp + int multiStream = (int) dis.readUB(1); //marker + if (frameMode == 1) { + if (multiStream == 1) { // || version2 == 0) { ??? + dis.readUI16(); //buff2Offset + } + dis.readUB(1); //refreshGoldenFrame + int useLoopFilter = (int) dis.readUB(1); //useLoopFilter + if (useLoopFilter == 1) { + int loopFilterSelector = (int) dis.readUB(1); + if (loopFilterSelector == 0) { + videoFlagsDeblocking = DefineVideoStreamTag.DEBLOCKING_LEVEL1; + } else if (loopFilterSelector == 1) { + videoFlagsDeblocking = DefineVideoStreamTag.DEBLOCKING_LEVEL4; + } + } + } + } + + int idealFrame = startFrame + (int) Math.floor(swf.frameRate * ftag.timeStamp / 1000.0); + if (idealFrame == importLastFrame) { + idealFrame++; + } + int swfFrameNum = -1; + ReadOnlyTagList tagList = timelined.getTags(); + int p = 0; + boolean found = false; + for (; p < tagList.size(); p++) { + Tag t = tagList.get(p); + if (t instanceof ShowFrameTag) { + swfFrameNum++; + if (swfFrameNum == idealFrame) { + found = true; + break; + } + } + } + + //add frames when necessary + if (!found) { + p--; + swfFrameNum++; + for (; swfFrameNum <= idealFrame; swfFrameNum++) { + PlaceObject2Tag placeObject = new PlaceObject2Tag(swf); + placeObject.setTimelined(timelined); + placeObject.depth = placeDepth; + placeObject.placeFlagMove = true; + placeObject.placeFlagHasRatio = true; + placeObject.ratio = swfFrameNum - startFrame; + timelined.addTag(placeObject); + p++; + ShowFrameTag sft = new ShowFrameTag(swf); + sft.setTimelined(timelined); + timelined.addTag(sft); + p++; + } + swfFrameNum--; + } + VideoFrameTag videoFrameTag = new VideoFrameTag(swf); + videoFrameTag.streamID = characterID; + videoFrameTag.frameNum = swfFrameNum - startFrame; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + VIDEODATA vdata = (VIDEODATA) ftag.data; + switch (codecID) { + case DefineVideoStreamTag.CODEC_VP6: + case DefineVideoStreamTag.CODEC_VP6_ALPHA: + baos.write(Arrays.copyOfRange(vdata.videoData, 1 /*strip adjustment*/, vdata.videoData.length)); + break; + default: + baos.write(vdata.videoData); + break; + } + videoFrameTag.videoData = new ByteArrayRange(baos.toByteArray()); + timelined.addTag(p, videoFrameTag); + videoFrameTag.setTimelined(timelined); + importLastFrame = idealFrame; + } + } + + List tagsToRemove = new ArrayList<>(); + for (Tag t : timelined.getTags()) { + if (t instanceof PlaceObjectTypeTag) { + PlaceObjectTypeTag pt = (PlaceObjectTypeTag) t; + if (pt.getDepth() == placeDepth) { + int ratio = pt.getRatio(); + if (ratio > importLastFrame - startFrame) { + tagsToRemove.add(t); + } + } + } + } + for (Tag t : tagsToRemove) { + timelined.removeTag(t); + } + + setModified(true); + timelined.resetTimeline(); + resetTimeline(); + resetPlayer(); + setPauseRendering(false); + } + } } diff --git a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java index 3094ef27d..506c45664 100644 --- a/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java +++ b/src/com/jpexs/decompiler/flash/console/CommandLineArgumentParser.java @@ -220,6 +220,7 @@ import com.jpexs.decompiler.flash.exporters.DualPdfGraphics2D; import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle; import com.jpexs.decompiler.flash.gui.translator.Translator; import com.jpexs.decompiler.flash.importers.SymbolClassImporter; +import com.jpexs.decompiler.flash.tags.DefineVideoStreamTag; import com.jpexs.decompiler.flash.tags.base.HasSeparateAlphaChannel; import com.jpexs.decompiler.flash.tags.base.RenderContext; import com.jpexs.decompiler.flash.tags.base.SoundImportException; @@ -1007,12 +1008,16 @@ public class CommandLineArgumentParser { parseFlashPaperToPdf(selection, zoom, args, charset); } else if (command.equals("replace")) { parseReplace(args, charset, air); + System.exit(0); } else if (command.equals("replacealpha")) { parseReplaceAlpha(args, charset); + System.exit(0); } else if (command.equals("replacecharacter")) { parseReplaceCharacter(args, charset); + System.exit(0); } else if (command.equals("replacecharacterid")) { parseReplaceCharacterId(args, charset); + System.exit(0); } else if (command.equals("convert")) { parseConvert(args, charset); } else if (command.equals("remove")) { @@ -3206,6 +3211,14 @@ public class CommandLineArgumentParser { System.err.println("Import FAILED. Maybe unsuppoted media type? Only MP3 and uncompressed WAV are available."); System.exit(1); } + } else if (characterTag instanceof DefineVideoStreamTag) { + DefineVideoStreamTag movie = (DefineVideoStreamTag)characterTag; + try { + movie.replace(new ByteArrayInputStream(data)); + } catch (IOException iex) { + System.err.println("Import FAILED: "+iex.getMessage()); + System.exit(1); + } } else { System.err.println("The specified tag type is not supported for import"); System.exit(1); @@ -3273,7 +3286,7 @@ public class CommandLineArgumentParser { try { try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(outFile))) { swf.saveTo(fos); - } + } } catch (IOException e) { System.err.println("I/O error during writing"); System.exit(2); diff --git a/src/com/jpexs/decompiler/flash/gui/MainPanel.java b/src/com/jpexs/decompiler/flash/gui/MainPanel.java index 0d615711d..1ec9f503e 100644 --- a/src/com/jpexs/decompiler/flash/gui/MainPanel.java +++ b/src/com/jpexs/decompiler/flash/gui/MainPanel.java @@ -4099,267 +4099,11 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se if (item instanceof DefineVideoStreamTag) { previewPanel.clear(); + DefineVideoStreamTag movie = (DefineVideoStreamTag) item; File selfile = Helper.fixDialogFile(selectedFile); - try (FileInputStream fis = new FileInputStream(selfile.getAbsolutePath())) { - FLVInputStream flvIs = new FLVInputStream(fis); - Reference audioPresent = new Reference<>(false); - Reference videoPresent = new Reference<>(false); - flvIs.readHeader(audioPresent, videoPresent); - List flvTags = flvIs.readTags(); - - DefineVideoStreamTag movie = (DefineVideoStreamTag) item; - - List videoTags = new ArrayList<>(); - for (FLVTAG tag : flvTags) { - if (tag.tagType == FLVTAG.DATATYPE_VIDEO) { - videoTags.add(tag); - } - } - if (!videoTags.isEmpty()) { - FLVTAG firstVideoTag = videoTags.get(0); - VIDEODATA videoData = ((VIDEODATA) firstVideoTag.data); - FLVInputStream dis = new FLVInputStream(new ByteArrayInputStream(videoData.videoData)); - int width = 0; - int height = 0; - switch (videoData.codecId) { - case VIDEODATA.CODEC_SORENSON_H263: - dis.readUB(17); //pictureStartCode - dis.readUB(5); //version - dis.readUB(8); //temporalReference - int pictureSize = (int) dis.readUB(3); - switch (pictureSize) { - case 0: - width = (int) dis.readUB(8); - height = (int) dis.readUB(8); - break; - case 1: - width = (int) dis.readUB(16); - height = (int) dis.readUB(16); - break; - case 2: - width = 352; - height = 288; - break; - case 3: - width = 176; - height = 144; - break; - case 4: - width = 128; - height = 96; - break; - case 5: - width = 320; - height = 240; - break; - case 6: - width = 160; - height = 120; - break; - } - - break; - case VIDEODATA.CODEC_SCREEN_VIDEO: - case VIDEODATA.CODEC_SCREEN_VIDEO_V2: - dis.readUB(4); //blockWidth - width = (int) dis.readUB(12); - dis.readUB(4); //blockHeight - height = (int) dis.readUB(12); - break; - case VIDEODATA.CODEC_VP6: - case VIDEODATA.CODEC_VP6_ALPHA: - int horizontalAdjustment = (int) dis.readUB(4); - int verticalAdjustment = (int) dis.readUB(4); - if (videoData.codecId == VIDEODATA.CODEC_VP6_ALPHA) { - dis.readUI24(); //offsetToAlpha - } - - int frameMode = (int) dis.readUB(1); //frameMode - - dis.readUB(6); //qp - int multiStream = (int) dis.readUB(1); //marker - if (frameMode == 0) { - int vp3VersionNo = (int) dis.readUB(5); - int vpProfile = (int) dis.readUB(2); - dis.readUB(1); //interlace - if (multiStream == 1 || vpProfile == 0) { - dis.readUI16(); //offset - } - int dim_y = dis.readUI8(); - int dim_x = dis.readUI8(); - //dis.readUI8(); //render_y - //dis.readUI8(); //render_x - width = 16 * dim_x - horizontalAdjustment; - height = 16 * dim_y - verticalAdjustment; - } - break; - case VIDEODATA.CODEC_AVC: - throw new IOException("AVC codec is not supported for import"); - case VIDEODATA.CODEC_JPEG: - throw new IOException("JPEG codec is not supported for import"); - } - if (width <= 0 || height <= 0) { - throw new IOException("Invalid dimension"); - } - movie.codecID = videoData.codecId; - movie.width = width; - movie.height = height; - movie.videoFlagsDeblocking = DefineVideoStreamTag.DEBLOCKING_OFF; - movie.videoFlagsSmoothing = true; - movie.numFrames = videoTags.size(); - movie.setPauseRendering(true); - - videoTags.sort(new Comparator() { - @Override - public int compare(FLVTAG o1, FLVTAG o2) { - return Long.compare(o1.timeStamp, o2.tagType); - } - }); - - //remove old VideoFrame tags - Map frames = new HashMap<>(); - SWF swf = movie.getSwf(); - SWF.populateVideoFrames(movie.characterID, swf.getTags(), frames); - Timelined timelined = null; - for (VideoFrameTag t : frames.values()) { - t.getTimelined().removeTag(t); - timelined = t.getTimelined(); - } - timelined.resetTimeline(); - - int startFrame = 0; - boolean startFound = false; - int placeDepth = -1; - for (Tag t : timelined.getTags()) { - if (t instanceof ShowFrameTag) { - startFrame++; - } - if (t instanceof PlaceObjectTypeTag) { - PlaceObjectTypeTag pt = (PlaceObjectTypeTag) t; - if (pt.getCharacterId() == movie.characterID) { - placeDepth = pt.getDepth(); - startFound = true; - break; - } - } - } - - int lastFrame = -1; - if (timelined != null) { - VideoFrameTag lastVideoFrame = null; - for (FLVTAG ftag : videoTags) { - videoData = ((VIDEODATA) ftag.data); - if (videoData.codecId == VIDEODATA.CODEC_VP6 || videoData.codecId == VIDEODATA.CODEC_VP6_ALPHA) { - int horizontalAdjustment = (int) dis.readUB(4); - int verticalAdjustment = (int) dis.readUB(4); - if (videoData.codecId == VIDEODATA.CODEC_VP6_ALPHA) { - dis.readUI24(); //offsetToAlpha - } - - int frameMode = (int) dis.readUB(1); //frameMode - - dis.readUB(6); //qp - int multiStream = (int) dis.readUB(1); //marker - if (frameMode == 1) { - if (multiStream == 1) { // || version2 == 0) { ??? - dis.readUI16(); //buff2Offset - } - dis.readUB(1); //refreshGoldenFrame - int useLoopFilter = (int) dis.readUB(1); //useLoopFilter - if (useLoopFilter == 1) { - int loopFilterSelector = (int)dis.readUB(1); - if (loopFilterSelector == 0) { - movie.videoFlagsDeblocking = DefineVideoStreamTag.DEBLOCKING_LEVEL1; - } else if(loopFilterSelector == 1) { - movie.videoFlagsDeblocking = DefineVideoStreamTag.DEBLOCKING_LEVEL4; - } - } - } - } - - int idealFrame = startFrame + (int) Math.floor(swf.frameRate * ftag.timeStamp / 1000.0); - if (idealFrame == lastFrame) { - idealFrame++; - } - int swfFrameNum = -1; - ReadOnlyTagList tagList = timelined.getTags(); - int p = 0; - boolean found = false; - for (; p < tagList.size(); p++) { - Tag t = tagList.get(p); - if (t instanceof ShowFrameTag) { - swfFrameNum++; - if (swfFrameNum == idealFrame) { - found = true; - break; - } - } - } - - //add frames when necessary - if (!found) { - p--; - swfFrameNum++; - for (; swfFrameNum <= idealFrame; swfFrameNum++) { - PlaceObject2Tag placeObject = new PlaceObject2Tag(swf); - placeObject.setTimelined(timelined); - placeObject.depth = placeDepth; - placeObject.placeFlagMove = true; - placeObject.placeFlagHasRatio = true; - placeObject.ratio = swfFrameNum - startFrame; - timelined.addTag(placeObject); - p++; - ShowFrameTag sft = new ShowFrameTag(swf); - sft.setTimelined(timelined); - timelined.addTag(sft); - p++; - } - swfFrameNum--; - } - VideoFrameTag videoFrameTag = new VideoFrameTag(swf); - videoFrameTag.streamID = movie.characterID; - videoFrameTag.frameNum = swfFrameNum - startFrame; - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - VIDEODATA vdata = (VIDEODATA) ftag.data; - switch (movie.codecID) { - case DefineVideoStreamTag.CODEC_VP6: - case DefineVideoStreamTag.CODEC_VP6_ALPHA: - baos.write(Arrays.copyOfRange(vdata.videoData, 1 /*strip adjustment*/, vdata.videoData.length)); - break; - default: - baos.write(vdata.videoData); - break; - } - videoFrameTag.videoData = new ByteArrayRange(baos.toByteArray()); - timelined.addTag(p, videoFrameTag); - videoFrameTag.setTimelined(timelined); - lastFrame = idealFrame; - } - } - - List tagsToRemove = new ArrayList<>(); - for (Tag t : timelined.getTags()) { - if (t instanceof PlaceObjectTypeTag) { - PlaceObjectTypeTag pt = (PlaceObjectTypeTag) t; - if (pt.getDepth() == placeDepth) { - int ratio = pt.getRatio(); - if (ratio > lastFrame - startFrame) { - tagsToRemove.add(t); - } - } - } - } - for (Tag t : tagsToRemove) { - timelined.removeTag(t); - } - - movie.setModified(true); - timelined.resetTimeline(); - refreshTree(); - movie.resetTimeline(); - movie.resetPlayer(); - movie.setPauseRendering(false); - } + try (FileInputStream fis = new FileInputStream(selfile)) { + movie.replace(fis); + refreshTree(); } catch (IOException ex) { ViewMessages.showMessageDialog(MainPanel.this, translate("error.movie.invalid") + ": "+ex.getMessage(), translate("error"), JOptionPane.ERROR_MESSAGE); } @@ -5870,57 +5614,5 @@ public final class MainPanel extends JPanel implements TreeSelectionListener, Se previewPanel.startEditGenericTag(); } - } - - public static void main(String[] args) throws Exception { - /*FLVInputStream fis = new FLVInputStream(new FileInputStream("c:\\Virtual\\shared\\movie123_source\\white\\frames\\frames_550.flv")); - fis.readHeader(new Reference<>(false), new Reference<>(false)); - int pos = 0; - for(FLVTAG t:fis.readTags()){ - if (t.tagType == 9) { - VIDEODATA vdata = (VIDEODATA)t.data; - FileOutputStream fos = new FileOutputStream("c:\\Virtual\\shared\\movie123_source\\white\\frames\\frames_550."+pos+".bin"); - fos.write(vdata.videoData); - fos.close(); - pos++; - } - //System.out.println("reading tag type "+t.tagType); - }*/ - - FLVInputStream dis = new FLVInputStream(new FileInputStream("c:\\Virtual\\shared\\movie123_source\\white\\frames\\frames_551.0.bin")); - int horizontalAdjustment = (int) dis.readUB(4); - int verticalAdjustment = (int) dis.readUB(4); - int frameMode = (int) dis.readUB(1); //frameMode - System.out.println("frameMode=" + frameMode); - int qp = (int) dis.readUB(6); //qp - System.out.println("qp=" + qp); - int marker = (int) dis.readUB(1); //marker - - System.out.println("horizontalAdjustment=" + horizontalAdjustment); - System.out.println("verticalAdjustment=" + verticalAdjustment); - - System.out.println("marker=" + marker); - if (frameMode == 0) { - int version = (int) dis.readUB(5); - System.out.println("version=" + version); - int version2 = (int) dis.readUB(2); - System.out.println("version2=" + version2); - dis.readUB(1); //interlace - if (marker == 1 || version2 == 0) { - int offset = dis.readUI16(); //offset - System.out.println("offset = " + offset); - } - int dim_y = dis.readUI8(); - int dim_x = dis.readUI8(); - int render_y = dis.readUI8(); //render_y - int render_x = dis.readUI8(); //render_x - System.out.println("dim_y=" + dim_y); - System.out.println("dim_x=" + dim_x); - System.out.println("render_y=" + render_y); - System.out.println("render_x=" + render_x); - System.out.println("width=" + (dim_x * 16 - horizontalAdjustment)); - System.out.println("height=" + (dim_y * 16 - verticalAdjustment)); - } - - } + } }