使用xuggler从文件中读取视频时抛出“ EXCEPTION_ACCESS_VIOLATION”

时间:2019-05-30 14:09:01

标签: java xuggler xuggle

我正在编写Java代码以将视频文件导入mp4格式,对其应用效果,然后将其保存到新文件中。代码应将给定的视频分割为多个帧,并将它们存储在一个数组中,以便每个视频都可以用来构建效果。这部分代码是由xuggler处理的,因此,我很难确定出了什么问题。

问题是,甚至在读取视频图像之前,都会抛出一个错误,并且我不知道它指的是什么,并且广泛的谷歌搜索告诉我它与内存访问错误有关。

更奇怪的是,即使某些mp4文件都是mp4格式,并且都应以相同的方式运行,但这仅适用于某些mp4文件。

我尝试了来自不同来源的许多不同的mp4文件,其中有些可以正常工作,有些则不能正常工作。我最想将效果应用到的mp4是不起作用的其中之一。

在下面的代码中,我已经在不同地方使用print语句进行了标识,导致错误的代码部分位于IMediaListener中带有变量名media的位置。侦听器本身由ActionListener内的行while(reader.readPacket()==null);调用,特别是在按“ sub”按钮触发的部分中。这是唯一被称为的地方。

我应该注意,与xuggler相关的所有代码都不是我自己的,因为我在在线代码演示中找到了它。我不会假装了解xuggler的工作原理。

import java.util.*;
import java.util.concurrent.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.*;
import java.awt.image.*;
import com.xuggle.xuggler.*;
import com.xuggle.mediatool.*;
import com.xuggle.mediatool.event.*;
import java.awt.event.*;
public class mainClass {
    static JFrame win=new JFrame();
    static JPanel dis=new JPanel();
    static JButton sub=new JButton("Submit"),b1=new JButton("Browse"),b2=new JButton("Browse");
    static JTextField input=new JTextField(),output=new JTextField();
    static String savePath="",sourcePath="";
    static JLabel l1=new JLabel("Input:"),l2=new JLabel("Output:");
    static BufferedImage[] images=new BufferedImage[0];
    static Set<Long> timestamps=new HashSet<Long>();
    static int ind=0;
    public static void main(String[]args) {
        win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        win.setResizable(false);
        win.setVisible(true);
        win.add(dis);
        win.setLocation(100,300);
        dis.setPreferredSize(new Dimension(850,80));
        dis.setLayout(null);
        win.pack();
        dis.add(input).setBounds(100,0,550,40);
        dis.add(output).setBounds(100,40,550,40);
        dis.add(sub).setBounds(750,0,100,80);
        dis.add(b1).setBounds(650,0,100,40);
        dis.add(b2).setBounds(650,40,100,40);
        dis.add(l1).setBounds(0,0,100,40);
        dis.add(l2).setBounds(0,40,100,40);
        input.setFocusable(false);
        input.setFont(new Font(Font.SANS_SERIF,Font.PLAIN,22));
        output.setFocusable(false);
        output.setFont(input.getFont());
        sub.setFocusable(false);
        sub.addActionListener(action);
        b1.setFocusable(false);
        b1.addActionListener(action);
        b2.setFocusable(false);
        b2.addActionListener(action);
        l1.setFont(input.getFont());
        l1.setHorizontalAlignment(SwingConstants.CENTER);
        l2.setFont(input.getFont());
        l2.setHorizontalAlignment(SwingConstants.CENTER);
    }
    static IMediaListener media=new MediaListenerAdapter() {
        public void onVideoPicture(IVideoPictureEvent e) {
            timestamps.add(e.getTimeStamp(TimeUnit.MICROSECONDS));
            BufferedImage image=e.getImage();
            BufferedImage[] copy=images;
            images=new BufferedImage[copy.length+1];
            for(int i=0;i<copy.length;i++) {
                images[i]=copy[i];
            }
            images[images.length-1]=image;
        }
    };
    static ActionListener action=new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            if(e.getSource()==sub) {
                if(input.getText().length()>0&output.getText().length()>0) {
                    IMediaReader reader=ToolFactory.makeReader(input.getText());
                    reader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR);
                    reader.addListener(media);
                    while(reader.readPacket()==null);
                    BufferedImage[] pics=images;
                    Long[] times=new Long[timestamps.size()];
                    times=timestamps.toArray(times);
                    for(int i=0;i<pics.length;i++) {
                        int min=i;
                        for(int j=i;j<pics.length;j++) {
                            if(times[j]<times[min]) {
                                min=j;
                            }
                        }
                        Long f1=times[i];
                        times[i]=times[min];
                        times[min]=f1;
                    }
                    timestamps=new HashSet<Long>();
                    long frameSep=(long)(times[times.length-1]/times.length);
                    IMediaWriter writer=ToolFactory.makeWriter(output.getText()+"\\video1.mp4");
                    writer.addVideoStream(0,0,ICodec.ID.CODEC_ID_MPEG4,pics[0].getWidth(),pics[0].getHeight());
                    for(int i=0;i<pics.length+pics[0].getHeight()-1;i++) {
                        BufferedImage image=pics[0];
                        for(int j=0;j<i;j++) {
                            int ind=i-j,ind2=image.getHeight()-j-1;
                            if(ind>=pics.length) {
                                ind=pics.length-1;
                            }
                            if(ind2<0) {
                                ind2=0;
                            }
                            int[] rgbArray=new int[image.getWidth()];
                            pics[ind].getRGB(0, ind2, image.getWidth(), 1, rgbArray, 0, image.getWidth());
                            image.setRGB(0, ind2, image.getWidth(), 1, rgbArray, 0, image.getWidth());
                        }
                        writer.encodeVideo(0, image, frameSep*i, TimeUnit.MICROSECONDS);
                        if(i%((pics.length+pics[0].getHeight()-1)/100)==0) {
                            System.out.println(Double.toString(i/(pics.length+pics[0].getHeight()-1)*100)+" %");
                        }
                    }
                    System.out.println("finished");
                    writer.close();
                }
            }
            if(e.getSource()==b1) {
                JFileChooser fc=new JFileChooser();
                fc.setMultiSelectionEnabled(false);
                fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
                fc.setFileFilter(new FileNameExtensionFilter("mp4 file","mp4"));
                fc.setAcceptAllFileFilterUsed(false);
                if(fc.showOpenDialog(sub)==JFileChooser.APPROVE_OPTION)input.setText(fc.getSelectedFile().getAbsolutePath());
            }
            if(e.getSource()==b2) {
                JFileChooser fc=new JFileChooser();
                fc.setMultiSelectionEnabled(false);
                fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                if(fc.showOpenDialog(sub)==JFileChooser.APPROVE_OPTION)output.setText(fc.getSelectedFile().getAbsolutePath());
            }
        }
    };
}

对于有效的给定mp4,代码将完成效果的应用,然后打印“完成”,所以我知道去检查输出文件夹,该文件夹可以在最初出现的GUI中指定。

对于无法使用的给定mp4,以下错误消息会完全打印到控制台中:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x000000006ee76520, pid=2176, tid=0x00000000000000c0
#
# JRE version: Java(TM) SE Runtime Environment (8.0_211-b12) (build 1.8.0_211-b12)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.211-b12 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C  [xuggle1222138188201648765.dll+0x736520]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\John\eclipse-workspace\Video effects\hs_err_pid2176.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

它所指的日志文件包含大量我不了解的复杂信息,谈论寄存器位置和VM等。我不会假装理解。

非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我希望你设法修复它,因为我在 2 年后来到这里,但是......

我在使用 xuggle 导入视频时遇到了同样的错误。我知道这是特定文件的问题,因为我用不同的视频进行了测试,但没有收到错误消息。我通过使用 VLC Media Player 将视频转换为相同的文件类型来修复它 - 仍然是具有相同质量的相同视频,但看起来阻止 Java 使用该文件的任何内容都在该转换中丢失了。