0

次を使用して、Direct3D9デバイスでビデオを再生しようとしています。

  1. nVLC-ファイルからRGB32フレームをフェッチするため
  2. SlimDX-テクスチャを使用してビデオデバイスに実際にフレームを表示します。

これがRGB32フレームを受信するための私のコードです。

    _videoWrapper.SetCallback(delegate(Bitmap frame)
                            {
                                if (_mainContentSurface == null || _dead) 
                                    return;

                                var bmpData = frame.LockBits(new Rectangle(0, 0, frame.Width, frame.Height), ImageLockMode.ReadOnly, frame.PixelFormat);
                                var ptr = bmpData.Scan0;

                                var size = bmpData.Stride * frame.Height;
                                _mainContentSurface.Buffer = new byte[size];

                                System.Runtime.InteropServices.Marshal.Copy(ptr, _mainContentSurface.Buffer, 0, size);

                                _mainContentSurface.SetTexture(_mainContentSurface.Buffer, frame.Width, frame.Height);
                                _secondaryContentSurface.SetTexture(_mainContentSurface.Buffer, frame.Width, frame.Height); // same buffer to second WINDOW

                                _mainContentSurface.VideoFrameRate.Value =_videoWrapper.ActualFrameRate;

                                frame.UnlockBits(bmpData);
                            });

そして、これがSetTextureの実際の使用法であり、テクスチャを正方形にマッピングします。

public void SetTexture(byte[] image, int width, int height)
{
    if (Context9 != null && Context9.Device != null)
    {
        if (IsFormClosed)
            return;

        // rendering is seperate from the "FRAME FETCH" thread, if it makes sense.
        // also note that we recreate video texture if needed.
        _renderWindow.BeginInvoke(new Action(() =>
                                {
                                    if (_image == null || _currentVideoTextureWidth != width || _currentVideoTextureHeight != height)
                                    {
                                        if(_image != null)
                                            _image.Dispose();

                                        _image = new Texture(Context9.Device, width, height, 0, Usage.Dynamic, Format.A8R8G8B8,
                                                            Pool.Default);

                                        _currentVideoTextureWidth = width;
                                        _currentVideoTextureHeight = height;

                                        if(_image == null)
                                            throw new Exception("Video card does not support textures power of TWO or dynamic textures. Get a video card");
                                    }

                                    //upload data into texture.
                                    var data = _image.LockRectangle(0, LockFlags.None);
                                    data.Data.Write(image, 0, image.Length);
                                    _image.UnlockRectangle(0);
                                }));
    }
}

そして最後に実際のレンダリング:

    Context9.Device.SetStreamSource(0, _videoVertices, 0, Vertex.SizeBytes);
    Context9.Device.VertexFormat = Vertex.Format;

    // Setup our texture. Using Textures introduces the texture stage states,
    // which govern how Textures get blended together (in the case of multiple
    // Textures) and lighting information.
    Context9.Device.SetTexture(0, _image);

    // The sampler states govern how smooth the texture is displayed.
    Context9.Device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear);
    Context9.Device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear);
    Context9.Device.SetSamplerState(0, SamplerState.MipFilter, TextureFilter.Linear);

    // Now drawing 2 triangles, for a quad.
    Context9.Device.DrawPrimitives(PrimitiveType.TriangleList, 0, 2);

今、それは私のマシンで動作します。問題なく。すべてのビデオファイルとすべての位置で。しかし、WinXPを確認したところ、画像が完全に壊れていました。これは、機能していないものと機能しているものの両方のスクリーンショットです。

http://www.upload.ee/image/2941734/untitled.PNG

http://www.upload.ee/image/2941762/Untitled2.png

最初の画像では、それらは_maincontentSurfaceと_secondaryContentSurfaceであることに注意してください。誰かが何が問題になるのか考えていますか?

4

1 に答える 1

0

テクスチャを毎回再作成する必要はなく、動的として作成するだけです。

this.Texture = new Texture(device, w, h, 1, Usage.Dynamic, Format.X8R8G8B8, Pool.Default);

コピーの問題については、ストライドが原因である可能性があります(行の長さは、パディングされているため異なる場合があります)。

テクスチャの行ピッチを取得するには:

    public int GetRowPitch()
    {
        if (rowpitch == -1)
        {
            DataRectangle dr = this.Texture.LockRectangle(0, LockFlags.Discard);
            this.rowpitch = dr.Pitch;
            this.Texture.UnlockRectangle(0);
        }
        return rowpitch;
    }

テクスチャの行のピッチがフレームのピッチと等しい場合は、同じようにコピーできます。それ以外の場合は、次のようにコピーできます。

    public void WriteDataPitch(IntPtr ptr, int len)
    {
        DataRectangle dr = this.Texture.LockRectangle(0, LockFlags.Discard);

        int pos = 0;
        int stride = this.Width * 4;

        byte* data = (byte*)ptr.ToPointer();
        for (int i = 0; i < this.Height; i++)
        {
            dr.Data.WriteRange((IntPtr)data, this.Width * 4);

            pos += dr.Pitch;
            dr.Data.Position = pos;
            data += stride;
        }
        this.Texture.UnlockRectangle(0);
    }

Slimdxで完全に機能するvlcプレーヤーの例が必要な場合は、それを入手したことを知らせてください(うまくまとめる必要があります)

于 2013-01-19T18:49:05.867 に答える