2013-03-16 120 views
0

通過遵循tutorial教學how to decode and play video中的代碼,我正在學習Xuggler(一個庫支持Java的視頻流)。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); 
    } 
} 

P.S.如果您想試用此庫,可以找到安裝文件here,然後按照this page上的步驟在Windows上完成安裝此庫。


我發現發生的錯誤,因爲我cahnged原代碼

 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(),然後更改爲acquire()。我認爲這是確定的,因爲沒有「無法打開視頻解碼器的容器:」拋出異常。所以只需按照示例代碼。

回答

1

我經歷了你的代碼,發現你獲得了videoCoder,但你在玩之前沒有open。也許這就是爲什麼你無法解碼它。那麼你可以試試嗎?

if (videoCoder.open() < 0) 
    throw new RuntimeException(
      "could not open video decoder for container: " 
        + filename); 
IVideoResampler resampler = null; 
+0

呃......我的文件是「C:/Users/swnmlab/1.mp4」,它是一個視頻文件... – 2013-03-17 04:38:06

+0

對不起,我的錯。更新了我的答案。 – longhua 2013-03-17 05:20:42

+0

謝謝〜我發現錯誤是由於你的答案中的線索!我會編輯我的問題。 – 2013-03-17 08:55:18

4

open()方法已經過時,應使用開放(NULL,NULL),而不是

if (videoCoder.open(null,null) < 0) 
throw new RuntimeException(
     "could not open video decoder for container: " 
       + filename); 
1

我執行與下面的代碼更改相同的代碼。這些更改是必需的,因爲下面的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; 
    } 

但是,我面臨一個不同的問題,即網絡攝像頭顯示佔用整個屏幕,而不是指定的寬度和高度。

是否更改了代碼設置的高度和寬度不正確?我們應該如何控制尺寸?