【问题标题】:Getting Frames from Video File with MediaComposition and IBasicVideoEffect使用 MediaComposition 和 IBasicVideoEffect 从视频文件中获取帧
【发布时间】:2020-09-18 22:12:42
【问题描述】:

我正在尝试逐帧处理视频文件。我不需要将帧保存到图像。

有一些关于这个主题的问答 (e.g.)。但是MediaComposition.GetThumbnailAsync 很慢。也有FFmpeg UWP 项目有图像采集卡,但也不是很快...

所以我利用了自定义IBasicVideoEffect,它实现了处理每一帧的方法(ProcessFrame)。这正是我需要的。这里的问题是,我不知道如何调用 ProcessFrame 方法。唯一的想法是在 MediaPlayerElement 中播放视频或将具有效果的合成保存到文件中。但我需要在后台快速处理视频文件,无需重播,无需渲染另一个文件。

这里是渲染文件的解决方案(目前更快的图像采集卡...)

//Page.Loaded
private async void LoadedAsync(object sender, RoutedEventArgs e)
{
    //set file to process
    StorageFile videoFile = await Package.Current.InstalledLocation.GetFileAsync("big_buck_bunny.mp4");

    //create clip from file
    MediaClip clip = await MediaClip.CreateFromFileAsync(videoFile);

    //apply "effect" on clip
    var vefdef = new VideoEffectDefinition(typeof(VideoEffectReachFrames).FullName);
    clip.VideoEffectDefinitions.Add(vefdef);

    //create composition
    compositor = new MediaComposition();
    compositor.Clips.Add(clip);
}

MediaComposition compositor;

private async void Button_ClickAsync(object sender, RoutedEventArgs e)
{
    //create temp file 
    var tempFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("tempFile.mp4", CreationCollisionOption.ReplaceExisting);

    //HERE - I need to render file.
    await compositor.RenderToFileAsync(tempFile);//render to file to evoke VideoEffect..
}

以及 Effect 类中的 ProcessFrame 方法:

public void ProcessFrame(ProcessVideoFrameContext context)
{
    //Getting pixel data, I am fine here

    var inputFrameBitmap = context.InputFrame.SoftwareBitmap;
    var frameSize = inputFrameBitmap.PixelWidth * inputFrameBitmap.PixelHeight * 4;

    var frameBuffer = new Buffer((uint)frameSize);
    context.InputFrame.SoftwareBitmap.CopyToBuffer(frameBuffer);
    var framePixels = frameBuffer.ToArray();

    Debug.WriteLine($"Touching 25th red pixel {framePixels[100]}");
}

Whole UWP project.

如何在MediaComposition 的帮助下到达帧而不渲染不必要的文件?

【问题讨论】:

  • 您好,这种渲染是必须的。它需要从字节流转换为图像,并且图像必须序列化为视频。虽然没有在后台显示,但是应用还是需要渲染
  • 我基本上只是在寻找“从字节流转换为图像”...没有办法只使用该过程的那一部分吗?
  • 我不太明白你的意图。事实上,字节流本身就是一个图像。如果渲染一个字节流(例如将其转换为BitmapImage作为Image控件的源),它将显示为图像。如果将字节流保存为文件,则为图像文件(根据文件类型,可能需要编码)
  • 我的意图是获取那个字节流(图像)。问题是我需要将视频渲染到文件以获取单个视频帧(在 ProcessFrame 方法中)。必须有某种方法可以做到这一点......我只是没有找到它,我猜......
  • 您好,目前这个过程可能是必要的,您需要先将字节流编码成图片再进行处理。处理完成后可以删除临时图片

标签: c# uwp


【解决方案1】:

您可以通过实现 C++ UWP 运行时组件并在您的 C# UWP 项目中引用它来使用 Win32 Media Foundation API。 还有 SharpDX.MediaFoundation 库,它是这个 C# API 的包装器。

例如使用SourceReader 类和SourceReader.ReadSample 方法来获取帧的字节。

参考:

http://sharpdx.org/wiki/class-library-api/mediafoundation/

https://docs.microsoft.com/en-us/windows/win32/medfound/microsoft-media-foundation-sdk?redirectedfrom=MSDN

【讨论】:

    猜你喜欢
    • 2022-01-06
    • 2020-06-07
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 1970-01-01
    • 2022-11-27
    相关资源
    最近更新 更多