20

Java環境でH.264ビデオフレームをデコードする方法を知っている人はいますか?

私のネットワークカメラ製品はRTP/RTSPストリーミングをサポートしています。

ネットワークカメラからのサービス標準RTP/RTSPが提供され、「RTP /RTSPoverHTTP」もサポートしています。

RTSP:TCP 554 RTP開始ポート:UDP 5000

4

5 に答える 5

6

またはXugglerを使用します。RTP、RTMP、HTTP、またはその他のプロトコルで動作し、H264 およびその他のほとんどのコーデックをデコードおよびエンコードできます。また、積極的にメンテナンスされ、無料でオープンソース (LGPL) になっています。

于 2010-02-03T04:21:04.467 に答える
4

「JNI + ffmpeg」を使用するのが最善の解決策だと思います。私の現在のプロジェクトでは、libgdx に基づく Java openGL ゲームで同時に複数のフルスクリーン ビデオを再生する必要があります。ほとんどすべての無料のライブラリを試しましたが、どれも許容できるパフォーマンスではありませんでした。最終的に、ffmpeg で動作するように独自の jni C コードを作成することにしました。これが私のラップトップでの最終的なパフォーマンスです。

  • 環境: CPU: Core i7 Q740 @1.73G、ビデオ: nVidia GeForce GT 435M、OS: Windows 7 64bit、Java: Java7u60 64bit
  • ビデオ: h264rgb / h264 エンコード、無音、解像度: 1366 * 768
  • 解決策: デコード: JNI + ffmpeg v2.2.2、GPU にアップロード: lwjgl を使用して openGL テクスチャを更新
  • パフォーマンス:デコード速度: 700-800FPS、テクスチャのアップロード: 1 フレームあたり約 1 ミリ秒。

最初のバージョンを完成させるのに数日しかかかりませんでした。しかし、最初のバージョンのデコード速度は約 120FPS で、アップロード時間は 1 フレームあたり約 5 ミリ秒でした。数か月の最適化の後、この最終的なパフォーマンスといくつかの追加機能が得られました。これで、遅延なく複数の HD ビデオを同時に再生できるようになりました。

私のゲームのほとんどのビデオの背景は透明です。この種類の透過ビデオは、2 つのビデオ ストリームを含む mp4 ファイルです。一方のストリームには h264rgb でエンコードされた RGB データが格納され、もう一方のストリームには h264 でエンコードされたアルファ データが格納されます。そのため、アルファ ビデオを再生するには、2 つのビデオ ストリームをデコードしてマージし、GPU にアップロードする必要があります。その結果、ゲーム内で不透明な HD ビデオの上に複数の透明な HD ビデオを同時に再生できます。

于 2014-06-13T20:00:16.950 に答える
4

JCodec ( http://jcodec.org ) と呼ばれる純粋な Java ライブラリを使用できます。
1 つの H.264 フレームのデコードは次のように簡単です。

ByteBuffer bb = ... // Your frame data is stored in this buffer
H264Decoder decoder = new H264Decoder();
Picture out = Picture.create(1920, 1088, ColorSpace.YUV_420); // Allocate output frame of max size
Picture real = decoder.decodeFrame(bb, out.getData());
BufferedImage bi = JCodecUtil.toBufferedImage(real); // If you prefere AWT image

コンテナー ( MP4 など) から読み取りたい場合は、便利なヘルパー クラス FrameGrab を使用できます。

int frameNumber = 150;
BufferedImage frame = FrameGrab.getFrame(new File("filename.mp4"), frameNumber);
ImageIO.write(frame, "png", new File("frame_150.png"));

最後に、洗練された完全なサンプルを次に示します。

private static void avc2png(String in, String out) throws IOException {
    SeekableByteChannel sink = null;
    SeekableByteChannel source = null;
    try {
        source = readableFileChannel(in);
        sink = writableFileChannel(out);

        MP4Demuxer demux = new MP4Demuxer(source);

        H264Decoder decoder = new H264Decoder();

        Transform transform = new Yuv420pToRgb(0, 0);

        MP4DemuxerTrack inTrack = demux.getVideoTrack();

        VideoSampleEntry ine = (VideoSampleEntry) inTrack.getSampleEntries()[0];
        Picture target1 = Picture.create((ine.getWidth() + 15) & ~0xf, (ine.getHeight() + 15) & ~0xf,
                ColorSpace.YUV420);
        Picture rgb = Picture.create(ine.getWidth(), ine.getHeight(), ColorSpace.RGB);
        ByteBuffer _out = ByteBuffer.allocate(ine.getWidth() * ine.getHeight() * 6);
        BufferedImage bi = new BufferedImage(ine.getWidth(), ine.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
        AvcCBox avcC = Box.as(AvcCBox.class, Box.findFirst(ine, LeafBox.class, "avcC"));

        decoder.addSps(avcC.getSpsList());
        decoder.addPps(avcC.getPpsList());

        Packet inFrame;
        int totalFrames = (int) inTrack.getFrameCount();
        for (int i = 0; (inFrame = inTrack.getFrames(1)) != null; i++) {
            ByteBuffer data = inFrame.getData();

            Picture dec = decoder.decodeFrame(splitMOVPacket(data, avcC), target1.getData());
            transform.transform(dec, rgb);
            _out.clear();

            AWTUtil.toBufferedImage(rgb, bi);
            ImageIO.write(bi, "png", new File(format(out, i)));
            if (i % 100 == 0)
                System.out.println((i * 100 / totalFrames) + "%");
        }
    } finally {
        if (sink != null)
            sink.close();
        if (source != null)
            source.close();
    }
}
于 2013-05-13T03:35:27.433 に答える
0

Java Media Framework (JMF) を見てみましょう - http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/formats.html

少し前に使っていたので少し未熟でしたが、その後強化されたのかもしれません。

于 2010-01-29T22:29:32.373 に答える