我正在编写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等。我不会假装理解。
非常感谢您的帮助!
答案 0 :(得分:0)
我希望你设法修复它,因为我在 2 年后来到这里,但是......
我在使用 xuggle 导入视频时遇到了同样的错误。我知道这是特定文件的问题,因为我用不同的视频进行了测试,但没有收到错误消息。我通过使用 VLC Media Player 将视频转换为相同的文件类型来修复它 - 仍然是具有相同质量的相同视频,但看起来阻止 Java 使用该文件的任何内容都在该转换中丢失了。