1

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()のようなメソッドを見つけ、次にacquire()に変更しました。「コンテナのビデオデコーダを開けませんでした:」例外がスローされなかったので、それで問題ないと思いました。サンプルコードに従ってください。

4

3 に答える 3

4

open()メソッドは非推奨です。代わりにopen(null、null)を使用する必要があります

if (videoCoder.open(null,null) < 0)
throw new RuntimeException(
        "could not open video decoder for container: "
                + filename);
于 2013-05-10T09:42:37.680 に答える
2

私はあなたのコードを調べて、あなたがを取得したことを発見しました、しかしあなたはプレイする前にそれvideoCoderをしませんでした。openたぶんそれがあなたがそれを解読できなかった理由です。では、ぜひお試しください。

if (videoCoder.open() < 0)
    throw new RuntimeException(
            "could not open video decoder for container: "
                    + filename);
IVideoResampler resampler = null;
于 2013-03-16T18:31:44.993 に答える
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;
  }

ただし、指定された幅と高さではなく、Webカメラのディスプレイが画面全体を占めるという別の問題に直面しています。

高さと幅を設定するためのコード変更が正しくありませんか?サイズをどのように制御する必要がありますか?

于 2014-06-25T08:21:32.210 に答える