2014-12-07 91 views
3

我有一个Windows Phone 8.1 Silverlight应用程序,使用Windows.Media.Editing.MediaComposition类将.gif文件呈现为.mp4。MediaComposition.RenderToFileAsync与许多静态图像崩溃

某些文件会随机崩溃RenderToFileAsync方法。至少有两种不同的错误信息可以接收,一种说明内存不足。

有没有人有任何想法的解决方法,或一些内幕知识如何这应该工作?

摄制:

  • 在VS2013
  • 创建新的C#WP8.1 Silverlight应用程序空白项目添加Usings和对的OnNavigatedTo如下MainPage.xaml.cs中。
  • 在512MB模拟器中运行。观察崩溃(大部分时间)。摆弄我的价值看它工作正常。

    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"); 

    } 

回答

1

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

很诚实的MediaComposition没有设计处理如此大量的剪辑。期望的剪辑平均数量徘徊在五个左右。

不幸的是,我无法得到我能想到的唯一可行的解​​决方法。我认为这个解决方案可能是可行的,但不幸的是,我不能再花费更多时间:您可能需要使用较少数量的剪辑创建多个输出文件。例如,您可以创建一个具有一到二十幅图像的输出文件。然后,您可以创建第二个文件与二十一到四十的图像。然后你可以将这两个文件结合在一起。

我希望这有助于

詹姆斯

+0

感谢。我已经考虑过这个解决方法,但是不能用它来实现它。文档中是否有任何地方指出它不适用于处理这些剪辑数量?无论如何,如果它是从磁盘流入和流出的,为什么还会有一个限制? MediaComposition的文档通常非常稀少。我通过指定输出类型/比特率等来使上述更加可靠。发现了硬方式输出宽度/高度必须是2的倍数时,出现无证另一件事:( – LMK 2014-12-11 03:15:46

+0

以下是回答您的问题:1)文档是不是在API如何处理大量的时间表明确。 2)媒体不像您想象的那样从磁盘流式传输。这是由于该API必须持有大致缓冲窗口加在内存中的关键帧间隔,以便能够进行转码。所有的剪辑对象也提供了大量的开销。这就是说,我与MSDN人合作,以获取更新的文档。 – 2014-12-13 00:16:28

+0

嗨,你能不能也请更新MediaComposition.GetThumbnailAsync的文档(),我得到许多使用timeFromStart是零和组合作品持续时间之间的报道时,我(不同的)应用程序异常。两个例外我得到的是:缩略图timeFromStart是组成范围之外:808260000和System.ArgumentException:值没有在预期的范围内。你传递给这个方法的开始和结束参数有什么规则?文件不存在。 – LMK 2014-12-23 19:41:44

1

我基本上是同样的问题,大量的试验和错误之后,我终于摆脱了我的“值没有在预期范围内”,这造成了许多错误或所有丢失的帧。

我加了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); 
     } 
}