"EXCEPTION_ACCESS_VIOLATION" thrown when reading a video from a file with xuggler
Asked Answered
O

1

7

I am writing java code to take in a video file in mp4 format, apply an effect to it, and then save it into a new file. The code should split the given video into its frames and store them in an array so they can each be used to build the effect. This part of the code is handled by xuggler, so It's difficult for me to identify whats going wrong.

The problem is, before even reading one image of the video an error is thrown back and I have no idea what it's referring to, and extensive googling tells me its something to do with a memory access error.

The even weirder part is that it only happens for some mp4 files, even though they are all mp4 format and should all behave the same way.

I have tried many different mp4 files from different sources and some of them work, some don't, seemingly at random. The mp4 that I am most interested in applying the effect to is one of the ones that doesn't work.

In the following code, I have identified using print statements at various points, that the part of the code causing the error is somewhere within the IMediaListener with variable name media. The listener itself is called by the line while(reader.readPacket()==null); inside of the ActionListener, specifically in the section triggered by pressing the 'sub' button. This is the only place that it is called.

I should note that all of the code associated with xuggler is not my own, as I found it in code demos online. I won't pretend to understand how xuggler works.

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());
            }
        }
    };
}

For a given mp4 that works, the code will finish applying the effect, and then print 'finished' so I know to go and check the output folder, which can be specified in the GUI that initially appears.

For a given mp4 that doesn't work, the following error message is printed into the console, exactly as follows:

#
# 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.
#

the log file it refers to contains a mass of complicated information that I can't understand, talking about register locations and VM's etc.. thing's I won't pretend to understand.

Any help is extremely appreciated!

Ortega answered 30/5, 2019 at 14:9 Comment(0)
A
1

I hope you managed to fix it, since I'm coming to this 2 years later, but...

I had the same error when I was importing a video using xuggle. I knew it was a problem with a specific file since I tested with a different video and did not get the error. I fixed it by converting the video using VLC Media Player to the same file type - still the same video with the same quality but it looks like whatever was preventing Java from using the file was lost in that conversion.

Anhydride answered 7/6, 2021 at 11:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.