【问题标题】:How does MediaCapture.StartPreviewToCustomSinkAsync method work?MediaCapture.StartPreviewToCustomSinkAsync 方法如何工作?
【发布时间】:2016-04-13 13:43:00
【问题描述】:

为什么 Windows 文档如此缺乏?似乎不可能找到这个方法应该如何工作的例子StartPreviewToCustomSinkAsync

我想做的是从视频源(通过MediaCapture)获取预览图像,但无法理解此方法的工作原理(尤其是第二个参数IMediaExtension,应该是/做)。

你们有没有机会帮我解决这个问题?

【问题讨论】:

    标签: c# .net windows-runtime windows-phone-8.1


    【解决方案1】:

    如果您只需要不时获取预览框架,Microsoft github 页面上有一个相关示例,尽管它们针对的是 Windows 10。您可能有兴趣迁移您的项目以获取此功能。

    GetPreviewFrame:此示例将捕获预览帧,而不是完整的照片。一旦有了预览帧,它就可以编辑上面的像素。

    以下是相关部分:

    private async Task GetPreviewFrameAsSoftwareBitmapAsync()
    {
        // Get information about the preview
        var previewProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
    
        // Create the video frame to request a SoftwareBitmap preview frame
        var videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, (int)previewProperties.Width, (int)previewProperties.Height);
    
        // Capture the preview frame
        using (var currentFrame = await _mediaCapture.GetPreviewFrameAsync(videoFrame))
        {
            // Collect the resulting frame
            SoftwareBitmap previewFrame = currentFrame.SoftwareBitmap;
    
            // Add a simple green filter effect to the SoftwareBitmap
            EditPixels(previewFrame);
        }
    }
    
    private unsafe void EditPixels(SoftwareBitmap bitmap)
    {
        // Effect is hard-coded to operate on BGRA8 format only
        if (bitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8)
        {
            // In BGRA8 format, each pixel is defined by 4 bytes
            const int BYTES_PER_PIXEL = 4;
    
            using (var buffer = bitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite))
            using (var reference = buffer.CreateReference())
            {
                // Get a pointer to the pixel buffer
                byte* data;
                uint capacity;
                ((IMemoryBufferByteAccess)reference).GetBuffer(out data, out capacity);
    
                // Get information about the BitmapBuffer
                var desc = buffer.GetPlaneDescription(0);
    
                // Iterate over all pixels
                for (uint row = 0; row < desc.Height; row++)
                {
                    for (uint col = 0; col < desc.Width; col++)
                    {
                        // Index of the current pixel in the buffer (defined by the next 4 bytes, BGRA8)
                        var currPixel = desc.StartIndex + desc.Stride * row + BYTES_PER_PIXEL * col;
    
                        // Read the current pixel information into b,g,r channels (leave out alpha channel)
                        var b = data[currPixel + 0]; // Blue
                        var g = data[currPixel + 1]; // Green
                        var r = data[currPixel + 2]; // Red
    
                        // Boost the green channel, leave the other two untouched
                        data[currPixel + 0] = b;
                        data[currPixel + 1] = (byte)Math.Min(g + 80, 255);
                        data[currPixel + 2] = r;
                    }
                }
            }
        }
    }
    

    并在你的班级之外声明:

    [ComImport]
    [Guid("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    unsafe interface IMemoryBufferByteAccess
    {
        void GetBuffer(out byte* buffer, out uint capacity);
    }
    

    当然,您的项目必须允许不安全的代码才能使所有这些工作。

    仔细查看示例,了解如何获取所有详细信息。或者,要进行演练,您可以观看最近的 //build/ 会议中的camera session,其中包括一些相机示例的演练。

    或者,如果你绑定到 8.1,你可以查看Lumia Imaging SDK,它可以notify you when there's a new preview frame available

    【讨论】:

    • 想要保留我已有的代码而不使用 Lumia Imaging SDK,但我最终还是使用了它,因为我的目标也是 WP 8.1。谢谢
    • 这个例子甚至不包括StartPreviewToCustomSinkAsync 函数。我仍然不知道如何使用它。
    【解决方案2】:

    GitHub 上有很多例子。如果您正在为 Windows Phone 8.1 开发 - 示例是 here
    根据this 示例录音如下所示:

    private StspMediaSinkProxy mediaSink;
    mediaSink = new StspMediaSinkProxy();
    
    MediaEncodingProfile encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Qvga);
    
    var mfExtension = await mediaSink.InitializeAsync(encodingProfile.Audio, encodingProfile.Video);
    await mediaCapture.StartRecordToCustomSinkAsync(encodingProfile, mfExtension);
    

    因此,您可以从这个示例中了解如何从 MediaEncodingProfile 获取 IMediaExtension。
    您还没有发布任何代码,但制作预览应该与我提供的代码相似

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-04
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多