MediaComposition.RenderToFileAsync与许多静态图像崩溃

时间:2014-12-07 09:28:03

标签: c# silverlight windows-phone-8

我有一个Windows Phone 8.1 Silverlight应用程序,它使用Windows.Media.Editing.MediaComposition类将.gif文件呈现为.mp4。

某些文件会随机崩溃RenderToFileAsync方法。您可以收到至少两个不同的错误消息,一个表明内存不足。

有没有人对变通方法有任何想法,或者有一些关于如何运作的内幕知识?

摄制:

  • 在VS2013中创建新的c#WP8.1 Silverlight app空白项目
  • 将Usings和OnNavigatedTo添加到MainPage.xaml.cs,如下所示。
  • 在512MB仿真器中运行。观察崩溃(大部分时间)。摆弄i的价值,看它是否正常运作。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using Microsoft.Phone.Controls;
    using Microsoft.Phone.Shell;
    using System.Windows.Media.Imaging;
    using System.IO;
    using Windows.Media.Editing;
    using System.Diagnostics;
    

-

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
    base.OnNavigatedTo(e);
    SystemTray.ProgressIndicator = new ProgressIndicator();
    SystemTray.ProgressIndicator.IsVisible = true;
    SystemTray.ProgressIndicator.IsIndeterminate= true;
    var comp = new MediaComposition();
    var r = new Random();

    for (int i = 0; i < 190; i++)
    {
        var wb = new WriteableBitmap(576, 300);

        for (int iPix = 0; iPix < wb.Pixels.Length; iPix++)
        {
            wb.Pixels[iPix] = r.Next();
        }

        string filename = "file" + i.ToString() + ".jpg";
        var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(filename, Windows.Storage.CreationCollisionOption.ReplaceExisting);
        using (var curr = await file.OpenStreamForWriteAsync())
        {
            wb.SaveJpeg(curr, wb.PixelWidth, wb.PixelHeight, 0, 95);
        }

        var clip = await MediaClip.CreateFromImageFileAsync(file, TimeSpan.FromMilliseconds(60));
        comp.Clips.Add(clip);
    }

    // Ensure add capability to write to video library AND ID_CAP_MEDIALIB_PHOTO and change below to 
    // Windows.Storage.KnownFolders.VideosLibrary to see output in Videos app
    var destFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
    var destFile = await destFolder.CreateFileAsync("test.mp4", Windows.Storage.CreationCollisionOption.ReplaceExisting);

    Debug.WriteLine("Mem use before render to disk: " + Windows.System.MemoryManager.AppMemoryUsage.ToString("N0"));
    await comp.RenderToFileAsync(destFile);
    Debug.WriteLine("Mem use after render to disk: " + Windows.System.MemoryManager.AppMemoryUsage.ToString("N0"));

    SystemTray.ProgressIndicator.IsVisible = false; 
    MessageBox.Show("Done OK");

    }

2 个答案:

答案 0 :(得分:1)

我通过Windows Phone应用程序分析内存分析器运行代码。我可以确认您的应用程序运行到大约150 MB的系统内存限制。 MediaComposition引擎可能需要大量内存,具体取决于输入和输出格式的大小。在您的情况下,您正在添加大量剪辑。可添加的剪辑数量受可用于解码的内存限制。

老实说,MediaComposition不是为处理如此大量的剪辑而设计的。预期的平均片数徘徊在5左右。

不幸的是,我无法获得我能想到的唯一可行的解​​决方法。我认为这个解决方案可能是可行的,但遗憾的是我不能再花费更多的时间了:你可能会使用较少数量的剪辑来创建多个输出文件。例如,您可以创建一个包含图像一到二十的输出文件。然后,您可以使用二十一到四十的图像创建第二个文件。然后,您可以将这两个文件连接在一起。

我希望这有帮助,

詹姆斯

答案 1 :(得分:1)

我有基本相同的问题,经过多次试验和错误,我终于摆脱了我的&#34;价值不在预期的范围内&#34;错误导致许多或所有丢失的帧。

我添加了GC.Collect();就在每个MediaClip.CreateFromImageFileAsync之前。它似乎不会影响性能或导致任何问题,这是我能解决它的唯一方法。希望这可以帮助别人。

以下是我的一些代码,因此您可以看到我正在谈论的内容:

foreach (var thisFrame in frames)
{
        GC.Collect();
        try
        {
               MediaClip clip = await MediaClip.CreateFromImageFileAsync(thisFrame, TimeSpan.FromMilliseconds(36 * speed));
               app.mediaComposition.Clips.Add(clip);
        }
        catch (Exception ex)
        {
               Debug.WriteLine(ex.Message + ex.StackTrace);
        }
}