[英]Error with java video decoding by Xuggler
我通過遵循指導 如何解碼和播放視頻的教程中的代碼,學習Xuggler(一個庫支持Java的視頻流)。
我以為這段代碼是可靠的,但是當我想播放在窗口上讀取的視頻時,出現錯誤告訴我
Exception in thread "main" java.lang.RuntimeException: got error decoding video in: C:/Users/swnmlab/1.mp4
執行此行時會發生此錯誤
int bytesDecoded = videoCoder.decodeVideo(picture, packet,offset);
我使用調試器進入並發現xuggle-xuggler.jar沒有源附件,以前有人遇到過此問題嗎?
import java.awt.image.BufferedImage;
import com.xuggle.xuggler.ICodec.Type;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IPixelFormat;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
import com.xuggle.xuggler.IVideoResampler;
import com.xuggle.xuggler.Utils;
import com.xuggle.xuggler.demos.VideoImage;
public class DecodeAndPlayVideo {
public static void main(String[] args) {
String filename = "C:/Users/swnmlab/1.mp4";
// Create a Xuggler container object
IContainer container = IContainer.make();
// Open up the container
if (container.open(filename, IContainer.Type.READ, null) < 0)
throw new IllegalArgumentException("could not open file: "
+ filename);
// query how many streams the call to open found
int numStreams = container.getNumStreams();
// and iterate through the streams to find the first video stream
int videoStreamId = -1;
IStreamCoder videoCoder = null;
for (int i = 0; i < numStreams; i++) {
// Find the stream object
IStream stream = container.getStream(i);
// Get the pre-configured decoder that can decode this stream;
IStreamCoder coder = stream.getStreamCoder();
if (coder.getCodecType() == Type.CODEC_TYPE_VIDEO) {
videoStreamId = i;
videoCoder = coder;
break;
}
}
if (videoStreamId == -1)
throw new RuntimeException(
"could not find video stream in container: " + filename);
if (videoCoder.acquire() < 0)
throw new RuntimeException(
"could not open video decoder for container: " + filename);
IVideoResampler resampler = null;
if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24) {
// if this stream is not in BGR24, we're going to need to
// convert it. The VideoResampler does that for us.
resampler = IVideoResampler.make(videoCoder.getWidth(),
videoCoder.getHeight(), IPixelFormat.Type.BGR24,
videoCoder.getWidth(), videoCoder.getHeight(),
videoCoder.getPixelType());
if (resampler == null)
throw new RuntimeException("could not create color space "
+ "resampler for: " + filename);
}
/*
* And once we have that, we draw a window on screen
*/
openJavaWindow();
IPacket packet = IPacket.make();
while (container.readNextPacket(packet) >= 0) {
/*
* Now we have a packet, let's see if it belongs to our video stream
*/
if (packet.getStreamIndex() == videoStreamId) {
IVideoPicture picture = IVideoPicture.make(
videoCoder.getPixelType(), videoCoder.getWidth(),
videoCoder.getHeight());
int offset = 0;
while (offset < packet.getSize()) {
/*
* Now, we decode the video, checking for any errors.
*/
int bytesDecoded = videoCoder.decodeVideo(picture, packet,
offset);
if (bytesDecoded < 0)
throw new RuntimeException(
"got error decoding video in: " + filename);
offset += bytesDecoded;
/*
* Some decoders will consume data in a packet, but will not
* be able to construct a full video picture yet. Therefore
* you should always check if you got a complete picture
* from the decoder
*/
if (picture.isComplete()) {
IVideoPicture newPic = picture;
/*
* If the resampler is not null, that means we didn't
* get the video in BGR24 format and need to convert it
* into BGR24 format.
*/
if (resampler != null) {
// we must resample
newPic = IVideoPicture.make(
resampler.getOutputPixelFormat(),
picture.getWidth(), picture.getHeight());
if (resampler.resample(newPic, picture) < 0)
throw new RuntimeException(
"could not resample video from: "
+ filename);
}
if (newPic.getPixelType() != IPixelFormat.Type.BGR24)
throw new RuntimeException("could not decode video"
+ " as BGR 24 bit data in: " + filename);
@SuppressWarnings("deprecation")
BufferedImage javaImage = Utils.videoPictureToImage(newPic);
// and display it on the Java Swing window
updateJavaWindow(javaImage);
}
}
} else {
/*
* This packet isn't part of our video stream, so we just silently drop it.
*/
do {
} while (false);
}
}
closeJavaWindow();
}
private static VideoImage mScreen = null;
private static void updateJavaWindow(BufferedImage javaImage) {
mScreen.setImage(javaImage);
}
private static void openJavaWindow() {
mScreen = new VideoImage();
}
private static void closeJavaWindow() {
System.exit(0);
}
}
PS如果要嘗試使用此庫,可以在此處找到安裝文件,然后按照本頁上的步驟完成在Windows上的安裝。
我發現錯誤發生是因為我更改了原始代碼
if (videoCoder.open() < 0)
throw new RuntimeException(
"could not open video decoder for container: " + filename);
至
if (videoCoder.acquire() < 0)
throw new RuntimeException(
"could not open video decoder for container: " + filename);
由於open()方法會導致棄用警告,因此我使用自動完成功能來查找類似於open()的方法,然后將其更改為Acquisition()。 我認為還可以,因為沒有拋出“無法為容器打開視頻解碼器:”異常。因此,請遵循示例代碼。
不建議使用open()方法,而應改用open(null,null)
if (videoCoder.open(null,null) < 0)
throw new RuntimeException(
"could not open video decoder for container: "
+ filename);
我檢查了您的代碼,發現您獲得了videoCoder
,但是在播放之前沒有open
它。 也許這就是為什么您無法對其進行解碼的原因。 那你可以試試看嗎?
if (videoCoder.open() < 0)
throw new RuntimeException(
"could not open video decoder for container: "
+ filename);
IVideoResampler resampler = null;
我通過以下代碼更改執行了相同的代碼。 這些更改是必需的,因為不推薦使用以下API。
IMetaData params = IMetaData.make();
IContainerParameters params = IContainerParameters.make();
如圖所示,我使用videoCoder設置了timeBase,Height和Width。
if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO)
{
videoStreamId = i;
videoCoder = coder;
// The timebase here is used as the camera frame rate
videoCoder.setTimeBase(IRational.make(30,1));
// we need to tell the driver what video with and height to use
videoCoder.setWidth(320);
videoCoder.setHeight(240);
break;
}
但是,我面臨一個不同的問題,即攝像頭顯示占據整個屏幕,而不是指定的寬度和高度。
設置高度和寬度的代碼更改不正確嗎? 我們應該如何控制大小?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.