사용자 지정 비디오 효과Custom video effects

이 문서에서는 Ibasicvideoeffect 인터페이스를 구현 하는 Windows 런타임 구성 요소를 만들어 비디오 스트림에 대 한 사용자 지정 효과를 만드는 방법을 설명 합니다.This article describes how to create a Windows Runtime component that implements the IBasicVideoEffect interface to create custom effects for video streams. 사용자 지정 효과는 장치 카메라에 대 한 액세스를 제공 하는 MediaCapture을 비롯 한 다양 한 Windows 런타임 api와 함께 사용할 수 있으며, 미디어 클립에서 복잡 한 컴퍼지션을 만들 수 있는 Mediacomposition을 제공 합니다.Custom effects can be used with several different Windows Runtime APIs including MediaCapture, which provides access to a device's camera, and MediaComposition, which allows you to create complex compositions out of media clips.

앱에 사용자 지정 효과 추가Add a custom effect to your app

사용자 지정 비디오 효과는 Ibasicvideoeffect 인터페이스를 구현 하는 클래스에서 정의 됩니다.A custom video effect is defined in a class that implements the IBasicVideoEffect interface. 이 클래스는 앱의 프로젝트에 직접 포함할 수 없습니다.This class can't be included directly in your app's project. 대신 Windows 런타임 구성 요소를 사용 하 여 비디오 효과 클래스를 호스팅해야 합니다.Instead, you must use a Windows Runtime component to host your video effect class.

비디오 효과에 대 한 Windows 런타임 구성 요소 추가Add a Windows Runtime component for your video effect

  1. Microsoft Visual Studio에서 솔루션을 연 상태에서 파일 메뉴로 이동 하 여 추가- > 새 프로젝트를 선택 합니다.In Microsoft Visual Studio, with your solution open, go to the File menu and select Add->New Project.
  2. Windows 런타임 구성 요소 (유니버설 Windows) 프로젝트 형식을 선택 합니다.Select the Windows Runtime Component (Universal Windows) project type.
  3. 이 예에서는 프로젝트 이름을 VideoEffectComponent로 합니다.For this example, name the project VideoEffectComponent. 이 이름은 나중에 코드에서 참조 됩니다.This name will be referenced in code later.
  4. 확인을 클릭합니다.Click OK.
  5. 프로젝트 템플릿은 Class1.cs 이라는 클래스를 만듭니다.The project template creates a class called Class1.cs. 솔루션 탐색기에서 Class1.cs의 아이콘을 마우스 오른쪽 단추로 클릭 하 고 이름 바꾸기를 선택 합니다.In Solution Explorer, right-click the icon for Class1.cs and select Rename.
  6. 파일의 이름을 ExampleVideoEffect.cs로 바꿉니다.Rename the file to ExampleVideoEffect.cs. Visual Studio에는 새 이름에 대 한 모든 참조를 업데이트할 것인지 묻는 메시지가 표시 됩니다.Visual Studio will show a prompt asking if you want to update all references to the new name. 를 클릭합니다.Click Yes.
  7. ExampleVideoEffect.cs 를 열고 클래스 정의를 업데이트 하 여 Ibasicvideoeffect 인터페이스를 구현 합니다.Open ExampleVideoEffect.cs and update the class definition to implement the IBasicVideoEffect interface.
public sealed class ExampleVideoEffect : IBasicVideoEffect

이 문서의 예제에 사용 된 모든 형식에 액세스 하려면 다음 네임 스페이스를 효과 클래스 파일에 포함 해야 합니다.You need to include the following namespaces in your effect class file in order to access all of the types used in the examples in this article.

using Windows.Media.Effects;
using Windows.Media.MediaProperties;
using Windows.Foundation.Collections;
using Windows.Graphics.DirectX.Direct3D11;
using Windows.Graphics.Imaging;

소프트웨어 처리를 사용 하 여 IBasicVideoEffect 인터페이스 구현Implement the IBasicVideoEffect interface using software processing

비디오 효과는 Ibasicvideoeffect 인터페이스의 모든 메서드 및 속성을 구현 해야 합니다.Your video effect must implement all of the methods and properties of the IBasicVideoEffect interface. 이 섹션에서는 소프트웨어 처리를 사용 하는이 인터페이스의 간단한 구현 과정을 안내 합니다.This section walks you through a simple implementation of this interface that uses software processing.

Close 메서드Close method

시스템은 효과가 종료 될 때 클래스에서 Close 메서드를 호출 합니다.The system will call the Close method on your class when the effect should shut down. 사용자가 만든 리소스를 삭제 하려면이 메서드를 사용 해야 합니다.You should use this method to dispose of any resources you have created. 메서드에 대 한 인수는 효과를 정상적으로 닫 았는 지, 오류가 발생 한 경우 또는 효과가 필요한 인코딩 형식을 지원 하지 않는지를 알 수 있도록 하는 MediaEffectClosedReason 입니다.The argument to the method is a MediaEffectClosedReason that lets you know whether the effect was closed normally, if an error occurred, or if the effect does not support the required encoding format.

public void Close(MediaEffectClosedReason reason)
{
    // Dispose of effect resources
}

DiscardQueuedFrames 메서드DiscardQueuedFrames method

DiscardQueuedFrames 메서드는 효과를 다시 설정 해야 할 때 호출 됩니다.The DiscardQueuedFrames method is called when your effect should reset. 이에 대 한 일반적인 시나리오는 효과가 현재 프레임을 처리 하는 데 사용 하기 위해 이전에 처리 된 프레임을 저장 하는 경우입니다.A typical scenario for this is if your effect stores previously processed frames to use in processing the current frame. 이 메서드를 호출 하면 저장 한 이전 프레임 집합을 삭제 해야 합니다.When this method is called, you should dispose of the set of previous frames you saved. 이 메서드는 누적 비디오 프레임 뿐만 아니라 이전 프레임과 관련 된 모든 상태를 다시 설정 하는 데 사용할 수 있습니다.This method can be used to reset any state related to previous frames, not only accumulated video frames.

private int frameCount;
public void DiscardQueuedFrames()
{
    frameCount = 0;
}

IsReadOnly 속성IsReadOnly property

IsReadOnly 속성을 사용 하면 효과가 효과의 출력에 기록 되는지 여부를 시스템에서 알 수 있습니다.The IsReadOnly property lets the system know if your effect will write to the output of the effect. 앱이 비디오 프레임의 분석만 수행 하는 효과와 같이 비디오 프레임을 수정 하지 않는 경우에는이 속성을 true로 설정 해야 합니다. 이렇게 하면 시스템에서 프레임 입력을 프레임 출력에 효율적으로 복사할 수 있습니다.If your app does not modify the video frames (for example, an effect that only performs analysis of the video frames), you should set this property to true, which will cause the system to efficiently copy the frame input to the frame output for you.

IsReadOnly 속성을 true로 설정 하면 processframe 이 호출 되기 전에 시스템에서 입력 프레임을 출력 프레임에 복사 합니다.When the IsReadOnly property is set to true, the system copies the input frame to the output frame before ProcessFrame is called. IsReadOnly 속성을 true로 설정 하면 processframe의 효과 출력 프레임에 쓰지 않아도 됩니다.Setting the IsReadOnly property to true does not restrict you from writing to the effect's output frames in ProcessFrame.

public bool IsReadOnly { get { return false; } }

SetEncodingProperties 메서드SetEncodingProperties method

시스템은 효과가 적용 되는 비디오 스트림에 대 한 인코딩 속성을 알려 주는 효과에 대해 SetEncodingProperties 를 호출 합니다.The system calls SetEncodingProperties on your effect to let you know the encoding properties for the video stream upon which the effect is operating. 또한이 메서드는 하드웨어 렌더링에 사용 되는 Direct3D 장치에 대 한 참조를 제공 합니다.This method also provides a reference to the Direct3D device used for hardware rendering. 이 장치를 사용 하는 방법은이 문서의 뒷부분에 나오는 하드웨어 처리 예제에 나와 있습니다.The usage of this device is shown in the hardware processing example later in this article.

private VideoEncodingProperties encodingProperties;
public void SetEncodingProperties(VideoEncodingProperties encodingProperties, IDirect3DDevice device)
{
    this.encodingProperties = encodingProperties;
}

SupportedEncodingProperties 속성SupportedEncodingProperties property

시스템은 SupportedEncodingProperties 속성을 확인 하 여 효과에서 지원 되는 인코딩 속성을 확인 합니다.The system checks the SupportedEncodingProperties property to determine which encoding properties are supported by your effect. 사용자가 지정한 속성을 사용 하 여 비디오를 인코딩할 수 없는 경우에는 효과에 대해 Close 를 호출 하 여 비디오 파이프라인에서 효과를 제거 합니다.Note that if the consumer of your effect can't encode video using the properties you specify, it will call Close on your effect and will remove your effect from the video pipeline.

public IReadOnlyList<VideoEncodingProperties> SupportedEncodingProperties
{            
    get
    {
        var encodingProperties = new VideoEncodingProperties();
        encodingProperties.Subtype = "ARGB32";
        return new List<VideoEncodingProperties>() { encodingProperties };

        // If the list is empty, the encoding type will be ARGB32.
        // return new List<VideoEncodingProperties>();
    }
}

참고

SupportedEncodingProperties에서 빈 VideoEncodingProperties 개체 목록을 반환 하면 시스템은 기본적으로 ARGB32 encoding으로 표시 됩니다.If you return an empty list of VideoEncodingProperties objects from SupportedEncodingProperties, the system will default to ARGB32 encoding.

 

SupportedMemoryTypes 속성SupportedMemoryTypes property

시스템은 Supportedmemorytypes 속성을 확인 하 여 효과가 소프트웨어 메모리 또는 하드웨어 (GPU) 메모리의 비디오 프레임에 액세스 하는지 여부를 확인 합니다.The system checks the SupportedMemoryTypes property to determine whether your effect will access video frames in software memory or in hardware (GPU) memory. MediaMemoryTypes를 반환 하는 경우에는 영향을 받은 입력 및 출력 프레임에 데이터 를 포함 하 고 있습니다.If you return MediaMemoryTypes.Cpu, your effect will be passed input and output frames that contain image data in SoftwareBitmap objects. MediaMemoryTypes를 반환 하는 경우 IDirect3DSurface 개체에 이미지 데이터가 포함 된 입력 및 출력 프레임에 결과가 전달 됩니다.If you return MediaMemoryTypes.Gpu, your effect will be passed input and output frames that contain image data in IDirect3DSurface objects.

public MediaMemoryTypes SupportedMemoryTypes { get { return MediaMemoryTypes.Cpu; } }

참고

MediaMemoryTypes. GpuAndCpu를 지정 하면 시스템은 GPU 또는 시스템 메모리 중에서 파이프라인에 대해 더 효율적으로 사용 됩니다.If you specify MediaMemoryTypes.GpuAndCpu, the system will use either GPU or system memory, whichever is more efficient for the pipeline. 이 값을 사용 하는 경우 Processframe 메서드를 검사 하 여 메서드에 전달 된 IDirect3DSurface 비트맵 또는 IDirect3DSurface 에 데이터가 포함 되어 있는지 확인 한 다음 그에 따라 프레임을 처리 해야 합니다.When using this value, you must check in the ProcessFrame method to see whether the SoftwareBitmap or IDirect3DSurface passed into the method contains data, and then process the frame accordingly.

 

TimeIndependent 속성TimeIndependent property

Timeindependent 속성을 사용 하면 효과에 균일 한 시간이 필요 하지 않은 경우 시스템에서 알 수 있습니다.The TimeIndependent property lets the system know if your effect does not require uniform timing. True로 설정 되 면 시스템은 성능 향상을 위해 최적화를 사용할 수 있습니다.When set to true, the system can use optimizations that enhance effect performance.

public bool TimeIndependent { get { return true; } }

SetProperties 메서드SetProperties method

SetProperties 메서드를 사용 하면 효과를 사용 하는 앱에서 효과 매개 변수를 조정할 수 있습니다.The SetProperties method allows the app that is using your effect to adjust effect parameters. 속성은 속성 이름 및 값의 IPropertySet 맵으로 전달 됩니다.Properties are passed as an IPropertySet map of property names and values.

private IPropertySet configuration;
public void SetProperties(IPropertySet configuration)
{
    this.configuration = configuration;
}

이 간단한 예제는 지정 된 값에 따라 각 비디오 프레임의 픽셀을 어둡게 만듭니다.This simple example will dim the pixels in each video frame according to a specified value. 속성이 선언 되 고 TryGetValue가 호출 앱에서 설정한 값을 가져오는 데 사용 됩니다.A property is declared and TryGetValue is used to get the value set by the calling app. 값이 설정 되지 않은 경우 기본값. 5가 사용 됩니다.If no value was set, a default value of .5 is used.

public double FadeValue
{
    get
    {
        object val;
        if (configuration != null && configuration.TryGetValue("FadeValue", out val))
        {
            return (double)val;
        }
        return .5;
    }
}

ProcessFrame 메서드ProcessFrame method

Processframe 메서드는 비디오의 이미지 데이터를 효과에서 수정 하는 위치입니다.The ProcessFrame method is where your effect modifies the image data of the video. 메서드는 프레임당 한 번 호출 되며 ProcessVideoFrameContext 개체에 전달 됩니다.The method is called once per frame and is passed a ProcessVideoFrameContext object. 이 개체에는 처리할 들어오는 프레임 및 비디오 파이프라인의 나머지 부분에 전달할 이미지 데이터를 작성 하는 출력 videoframe 개체를 포함 하는 입력 videoframe 개체가 포함 되어 있습니다.This object contains an input VideoFrame object that contains the incoming frame to be processed and an output VideoFrame object to which you write image data that will be passed on to rest of the video pipeline. 이러한 각 Videoframe 개체는 Direct3DSurface 속성을 포함 하지만 이 속성은 supportedmemorytypes 속성에서 반환 된 값에 따라 결정 됩니다.Each of these VideoFrame objects has a SoftwareBitmap property and a Direct3DSurface property, but which of these can be used is determined by the value you returned from the SupportedMemoryTypes property.

이 예제에서는 소프트웨어 처리를 사용 하는 Processframe 메서드의 간단한 구현을 보여 줍니다.This example shows a simple implementation of the ProcessFrame method using software processing. \Bitmap 개체 작업에 대 한 자세한 내용은 Imaging을 참조 하세요.For more information about working with SoftwareBitmap objects, see Imaging. 하드웨어 처리를 사용 하는 Processframe 구현 예제는이 문서의 뒷부분에 나와 있습니다.An example ProcessFrame implementation using hardware processing is shown later in this article.

T e m 비트맵 의 데이터 버퍼에 액세스 하려면 COM interop 필요 하므로 효과 클래스 파일에 System.Runtime.InteropServices 네임 스페이스를 포함 해야 합니다.Accessing the data buffer of a SoftwareBitmap requires COM interop, so you should include the System.Runtime.InteropServices namespace in your effect class file.

using System.Runtime.InteropServices;

이미지 버퍼에 액세스 하기 위한 인터페이스를 가져오기 위한 효과에 대 한 네임 스페이스 내에 다음 코드를 추가 합니다.Add the following code inside the namespace for your effect to import the interface for accessing the image buffer.

[ComImport]
[Guid("5B0D3235-4DBA-4D44-865E-8F1D0E4FD04D")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
unsafe interface IMemoryBufferByteAccess
{
    void GetBuffer(out byte* buffer, out uint capacity);
}

참고

이 기술은 관리 되지 않는 네이티브 이미지 버퍼에 액세스 하므로 안전 하지 않은 코드를 허용 하도록 프로젝트를 구성 해야 합니다.Because this technique accesses a native, unmanaged image buffer, you will need to configure your project to allow unsafe code.

  1. 솔루션 탐색기에서 VideoEffectComponent 프로젝트를 마우스 오른쪽 단추로 클릭 하 고 속성을 선택 합니다.In Solution Explorer, right-click the VideoEffectComponent project and select Properties.
  2. 빌드 탭을 선택합니다.Select the Build tab.
  3. 안전 하지 않은 코드 허용 확인란을 선택 합니다.Select the Allow unsafe code check box.

 

이제 Processframe 메서드 구현을 추가할 수 있습니다.Now you can add the ProcessFrame method implementation. 첫째,이 메서드는 입력 및 출력 소프트웨어 비트맵에서 BitmapBuffer 개체를 가져옵니다.First, this method obtains a BitmapBuffer object from both the input and output software bitmaps. 출력 프레임은 쓰기용으로 열리고 입력은 읽기를 위해 열립니다.Note that the output frame is opened for writing and the input for reading. 그런 다음 CreateReference를 호출 하 여 각 버퍼에 대해 IMemoryBufferReference 를 가져옵니다.Next, an IMemoryBufferReference is obtained for each buffer by calling CreateReference. 그런 다음 IMemoryBufferReference 개체를 위에서 정의한 COM interop 인터페이스로 캐스팅 하 고 IMemoryByteAccess다음 getbuffer를 호출 하 여 실제 데이터 버퍼를 가져옵니다.Then, the actual data buffer is obtained by casting the IMemoryBufferReference objects as the COM interop interface defined above, IMemoryByteAccess, and then calling GetBuffer.

이제 데이터 버퍼를 얻 었으 면 입력 버퍼에서 읽고 출력 버퍼에 쓸 수 있습니다.Now that the data buffers have been obtained, you can read from the input buffer and write to the output buffer. 버퍼의 레이아웃은 버퍼의 너비, stride 및 초기 오프셋에 대 한 정보를 제공 하는 Getplanedescription을 호출 하 여 가져옵니다.The layout of the buffer is obtained by calling GetPlaneDescription, which provides information on the width, stride, and initial offset of the buffer. 픽셀당 비트 수는 SetEncodingProperties 메서드를 사용 하 여 이전에 설정 된 인코딩 속성에 따라 결정 됩니다.The bits per pixel is determined by the encoding properties set previously with the SetEncodingProperties method. 버퍼 형식 정보는 각 픽셀에 대 한 버퍼의 인덱스를 찾는 데 사용 됩니다.The buffer format information is used to find the index into the buffer for each pixel. 원본 버퍼의 픽셀 값이 대상 버퍼에 복사 되 고, 색 값이이 효과에 대해 정의 된 FadeValue 속성을 곱하여 지정 된 양만큼 크기가 지정 됩니다.The pixel value from the source buffer is copied into the target buffer, with the color values being multiplied by the FadeValue property defined for this effect to dim them by the specified amount.

public unsafe void ProcessFrame(ProcessVideoFrameContext context)
{
    using (BitmapBuffer buffer = context.InputFrame.SoftwareBitmap.LockBuffer(BitmapBufferAccessMode.Read))
    using (BitmapBuffer targetBuffer = context.OutputFrame.SoftwareBitmap.LockBuffer(BitmapBufferAccessMode.Write))
    {
        using (var reference = buffer.CreateReference())
        using (var targetReference = targetBuffer.CreateReference())
        {
            byte* dataInBytes;
            uint capacity;
            ((IMemoryBufferByteAccess)reference).GetBuffer(out dataInBytes, out capacity);

            byte* targetDataInBytes;
            uint targetCapacity;
            ((IMemoryBufferByteAccess)targetReference).GetBuffer(out targetDataInBytes, out targetCapacity);

            var fadeValue = FadeValue;

            // Fill-in the BGRA plane
            BitmapPlaneDescription bufferLayout = buffer.GetPlaneDescription(0);
            for (int i = 0; i < bufferLayout.Height; i++)
            {
                for (int j = 0; j < bufferLayout.Width; j++)
                {

                    byte value = (byte)((float)j / bufferLayout.Width * 255);

                    int bytesPerPixel = 4; 
                    if (encodingProperties.Subtype != "ARGB32")
                    {
                        // If you support other encodings, adjust index into the buffer accordingly
                    }
                    

                    int idx = bufferLayout.StartIndex + bufferLayout.Stride * i + bytesPerPixel * j;

                    targetDataInBytes[idx + 0] = (byte)(fadeValue * (float)dataInBytes[idx + 0]);
                    targetDataInBytes[idx + 1] = (byte)(fadeValue * (float)dataInBytes[idx + 1]);
                    targetDataInBytes[idx + 2] = (byte)(fadeValue * (float)dataInBytes[idx + 2]);
                    targetDataInBytes[idx + 3] = dataInBytes[idx + 3];
                }
            }
        }
    }
}

하드웨어 처리를 사용 하 여 IBasicVideoEffect 인터페이스 구현Implement the IBasicVideoEffect interface using hardware processing

하드웨어 (GPU) 처리를 사용 하 여 사용자 지정 비디오 효과를 만드는 것은 위에서 설명한 대로 소프트웨어 처리를 사용 하는 것과 거의 동일 합니다.Creating a custom video effect by using hardware (GPU) processing is almost identical to using software processing as described above. 이 섹션에서는 하드웨어 처리를 사용 하는 효과의 몇 가지 차이점을 보여 줍니다.This section will show the few differences in an effect that uses hardware processing. 이 예제에서는 Win2D Windows 런타임 API를 사용 합니다.This example uses the Win2D Windows Runtime API. Win2D에 대한 자세한 내용은 Win2D 설명서를 참조하세요.For more information about using Win2D, see the Win2D documentation.

다음 단계를 사용 하 여이 문서의 시작 부분에 있는 앱에 사용자 지정 효과 추가 섹션에 설명 된 대로 만든 프로젝트에 Win2D NuGet 패키지를 추가 합니다.Use the following steps to add the Win2D NuGet package to the project you created as described in the Add a custom effect to your app section at the beginning of this article.

Win2D NuGet 패키지를 효과 프로젝트에 추가 하려면To add the Win2D NuGet package to your effect project

  1. 솔루션 탐색기에서 VideoEffectComponent 프로젝트를 마우스 오른쪽 단추로 클릭 하 고 NuGet 패키지 관리를 선택 합니다.In Solution Explorer, right-click the VideoEffectComponent project and select Manage NuGet Packages.
  2. 창 위쪽에서 찾아보기 탭을 선택 합니다.At the top of the window, select the Browse tab.
  3. 검색 상자에 Win2D를 입력 합니다.In the search box, enter Win2D.
  4. Win2D를 선택한 다음 오른쪽 창에서 설치 를 선택 합니다.Select Win2D.uwp, and then select Install in the right pane.
  5. 변경 내용 검토 대화 상자에 설치할 패키지를 표시 합니다.The Review Changes dialog shows you the package to be installed. 확인을 클릭합니다.Click OK.
  6. 패키지 라이선스에 동의 합니다.Accept the package license.

기본 프로젝트 설정에 포함 된 네임 스페이스 외에도 Win2D에서 제공 하는 다음 네임 스페이스를 포함 해야 합니다.In addition to the namespaces included in the basic project setup, you will need to include the following namespaces provided by Win2D.

using Microsoft.Graphics.Canvas.Effects;
using Microsoft.Graphics.Canvas;

이 효과는 이미지 데이터에서 작동 하는 데 GPU 메모리를 사용 하므로 Supportedmemorytypes 속성에서 MediaMemoryTypes 를 반환 해야 합니다.Because this effect will use GPU memory for operating on the image data, you should return MediaMemoryTypes.Gpu from the SupportedMemoryTypes property.

public MediaMemoryTypes SupportedMemoryTypes { get { return MediaMemoryTypes.Gpu; } }

SupportedEncodingProperties 속성을 사용 하 여 효과에서 지원할 인코딩 속성을 설정 합니다.Set the encoding properties that your effect will support with the SupportedEncodingProperties property. Win2D를 사용 하 여 작업 하는 경우 ARGB32 encoding을 사용 해야 합니다.When working with Win2D, you must use ARGB32 encoding.

public IReadOnlyList<VideoEncodingProperties> SupportedEncodingProperties {
    get
    {
        var encodingProperties = new VideoEncodingProperties();
        encodingProperties.Subtype = "ARGB32";
        return new List<VideoEncodingProperties>() { encodingProperties };
    }
}

SetEncodingProperties 메서드를 사용 하 여 메서드로 전달 된 IDirect3DDevice 에서 새 Win2D CanvasDevice 개체를 만듭니다.Use the SetEncodingProperties method to create a new Win2D CanvasDevice object from the IDirect3DDevice passed into the method.

private CanvasDevice canvasDevice;
public void SetEncodingProperties(VideoEncodingProperties encodingProperties, IDirect3DDevice device)
{
    canvasDevice = CanvasDevice.CreateFromDirect3D11Device(device);
}

SetProperties 구현은 이전 소프트웨어 처리 예제와 동일 합니다.The SetProperties implementation is identical to the previous software processing example. 이 예제에서는 BlurAmount 속성을 사용 하 여 Win2D 흐림 효과를 구성 합니다.This example uses a BlurAmount property to configure a Win2D blur effect.

private IPropertySet configuration;
public void SetProperties(IPropertySet configuration)
{
    this.configuration = configuration;
}
public double BlurAmount
{
    get
    {
        object val;
        if (configuration != null && configuration.TryGetValue("BlurAmount", out val))
        {
            return (double)val;
        }
        return 3;
    }
}

마지막 단계는 이미지 데이터를 실제로 처리 하는 Processframe 메서드를 구현 하는 것입니다.The last step is to implement the ProcessFrame method that actually processes the image data.

Win2D Api를 사용 하 여 입력 프레임의 Direct3DSurface 속성에서 CanvasBitmap 를 만듭니다.Using Win2D APIs, a CanvasBitmap is created from the input frame's Direct3DSurface property. CanvasRenderTarget 는 출력 프레임의 Direct3DSurface 에서 만들어지며이 렌더링 대상에서 CanvasDrawingSession 생성 됩니다.A CanvasRenderTarget is created from the output frame's Direct3DSurface and a CanvasDrawingSession is created from this render target. 새 Win2D GaussianBlurEffectBlurAmount 속성을 사용 하 여 초기화 됩니다 .이 속성은 SetProperties를 통해 노출 됩니다.A new Win2D GaussianBlurEffect is initialized, using the BlurAmount property our effect exposes via SetProperties. 마지막으로, 흐림 효과를 사용 하 여 CanvasDrawingSession DrawImage 메서드를 호출 하 여 렌더링 대상에 입력 비트맵을 그립니다.Finally, the CanvasDrawingSession.DrawImage method is called to draw the input bitmap to the render target using the blur effect.

public void ProcessFrame(ProcessVideoFrameContext context)
{

    using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromDirect3D11Surface(canvasDevice, context.InputFrame.Direct3DSurface))
    using (CanvasRenderTarget renderTarget = CanvasRenderTarget.CreateFromDirect3D11Surface(canvasDevice, context.OutputFrame.Direct3DSurface))
    using (CanvasDrawingSession ds = renderTarget.CreateDrawingSession())
    {


        var gaussianBlurEffect = new GaussianBlurEffect
        {
            Source = inputBitmap,
            BlurAmount = (float)BlurAmount,
            Optimization = EffectOptimization.Speed
        };

        ds.DrawImage(gaussianBlurEffect);

    }
}

앱에 사용자 지정 효과 추가Adding your custom effect to your app

앱에서 비디오 효과를 사용 하려면 앱에 효과 프로젝트에 대 한 참조를 추가 해야 합니다.To use your video effect from your app, you must add a reference to the effect project to your app.

  1. 솔루션 탐색기의 앱 프로젝트에서 참조 를 마우스 오른쪽 단추로 클릭 하 고 참조 추가를 선택 합니다.In Solution Explorer, under your app project, right-click References and select Add reference.
  2. 프로젝트 탭을 확장 하 고 솔루션을 선택한 다음 효과 프로젝트 이름에 대 한 확인란을 선택 합니다.Expand the Projects tab, select Solution, and then select the check box for your effect project name. 이 예에서는 이름이 VideoEffectComponent입니다.For this example, the name is VideoEffectComponent.
  3. 확인을 클릭합니다.Click OK.

카메라 비디오 스트림에 사용자 지정 효과 추가Add your custom effect to a camera video stream

간단한 카메라 미리 보기 액세스문서의 단계에 따라 카메라에서 간단한 미리 보기 스트림을 설정할 수 있습니다.You can set up a simple preview stream from the camera by following the steps in the article Simple camera preview access. 이러한 단계를 수행 하면 카메라의 비디오 스트림에 액세스 하는 데 사용 되는 초기화 된 MediaCapture 개체가 제공 됩니다.Following those steps will provide you with an initialized MediaCapture object that is used to access the camera's video stream.

카메라 스트림에 사용자 지정 비디오 효과를 추가 하려면 먼저 새 VideoEffectDefinition 개체를 만들어 효과에 대 한 네임 스페이스 및 클래스 이름을 전달 합니다.To add your custom video effect to a camera stream, first create a new VideoEffectDefinition object, passing in the namespace and class name for your effect. 그런 다음 MediaCapture 개체의 addvideoeffect 메서드를 호출 하 여 지정 된 스트림에 효과를 추가 합니다.Next, call the MediaCapture object's AddVideoEffect method to add your effect to the specified stream. 이 예에서는 Mediastreamtype 값을 사용 하 여 미리 보기 스트림에 효과를 추가 하도록 지정 합니다.This example uses the MediaStreamType.VideoPreview value to specify that the effect should be added to the preview stream. 앱에서 비디오 캡처를 지 원하는 경우 VideoRecord를 사용 하 여 캡처 스트림에 효과를 추가할 수도 있습니다 .If your app supports video capture, you could also use MediaStreamType.VideoRecord to add the effect to the capture stream. Addvideoeffect 사용자 지정 효과를 나타내는 imediaextension 개체를 반환 합니다.AddVideoEffect returns an IMediaExtension object representing your custom effect. SetProperties 메서드를 사용 하 여 효과에 대 한 구성을 설정할 수 있습니다.You can use the SetProperties method to set the configuration for your effect.

효과가 추가 된 후에는 StartPreviewAsync 를 호출 하 여 미리 보기 스트림을 시작 합니다.After the effect has been added, StartPreviewAsync is called to start the preview stream.

var videoEffectDefinition = new VideoEffectDefinition("VideoEffectComponent.ExampleVideoEffect");

IMediaExtension videoEffect =
   await mediaCapture.AddVideoEffectAsync(videoEffectDefinition, MediaStreamType.VideoPreview);

videoEffect.SetProperties(new PropertySet() { { "FadeValue", .25 } });

await mediaCapture.StartPreviewAsync();

MediaComposition의 클립에 사용자 지정 효과 추가Add your custom effect to a clip in a MediaComposition

비디오 클립에서 미디어 컴퍼지션을 만드는 방법에 대 한 일반적인 지침은 미디어 컴포지션 및 편집을 참조 하세요.For general guidance for creating media compositions from video clips, see Media compositions and editing. 다음 코드 조각에서는 사용자 지정 비디오 효과를 사용 하는 간단한 미디어 컴포지션의 생성을 보여 줍니다.The following code snippet shows the creation of a simple media composition that uses a custom video effect. Mediaclip 개체는 CreateFromFileAsync를 호출 하 고 fileopenpicker를 사용 하 여 사용자가 선택한 비디오 파일을 전달 하 여 생성 되며, 새 mediacomposition에 클립이 추가 됩니다.A MediaClip object is created by calling CreateFromFileAsync, passing in a video file that was selected by the user with a FileOpenPicker, and the clip is added to a new MediaComposition. 그런 다음 새 VideoEffectDefinition 개체를 만들어 효과에 대 한 네임 스페이스 및 클래스 이름을 생성자에 전달 합니다.Next a new VideoEffectDefinition object is created, passing in the namespace and class name for your effect to the constructor. 마지막으로 효과 정의가 Mediaclip 개체의 VideoEffectDefinitions 컬렉션에 추가 됩니다.Finally, the effect definition is added to the VideoEffectDefinitions collection of the MediaClip object.

MediaComposition composition = new MediaComposition();
var clip = await MediaClip.CreateFromFileAsync(pickedFile);
composition.Clips.Add(clip);

var videoEffectDefinition = new VideoEffectDefinition("VideoEffectComponent.ExampleVideoEffect", new PropertySet() { { "FadeValue", .5 } });

clip.VideoEffectDefinitions.Add(videoEffectDefinition);