Как создать IDirect3DSurface из IBuffer или байтового массива в UWP - PullRequest
0 голосов
/ 25 июня 2018

Я хочу создать видео из нескольких RenderTargetBitmap с в UWP.Я делаю это с помощью MediaClips.Из RenderTargetBitmap я могу получить IBuffer или байтовый массив пикселей.Для создания MediaClip мне нужен либо файл изображения, либо IDirect3DSurface.Создание изображения просто для создания клипа очень дорого, поэтому я подумал об использовании IDirect3DSurface.Как я могу это сделать?Я пробовал это:

        RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
        await renderTargetBitmap.RenderAsync(RenderedGrid, 100, 100);

        IBuffer pixels = await renderTargetBitmap.GetPixelsAsync();
        var values = Enum.GetValues(typeof(DirectXPixelFormat));
        CanvasBitmap bitmap=null;

        foreach (DirectXPixelFormat format in values)
        {
            try
            {
                videoClip = new MediaComposition();
                bitmap = CanvasBitmap.CreateFromBytes(myWidget.Device, pixels, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight, format);
                StorageFile video2 = await storageFolder.CreateFileAsync("video2" + ".mp4", CreationCollisionOption.ReplaceExisting);
                MediaClip d = MediaClip.CreateFromSurface(bitmap, DateTime.Now - previousFrame+new TimeSpan(100));
                videoClip.Clips.Add(d);
                await videoClip.RenderToFileAsync(video2);
                break;
            }
            catch(Exception e)
            {

            }
        }

Я пробую все форматы в DirectXPixelFormat, но ни один не работает.

У меня есть CanvasControl с именем myWidget, который пуст.

Я создаю CanvasBitmap из Ibuffer (CanvasBitmap орудия IDirect3DSurface)

Создайте Mediaclip из CanvasBitmap

Add it to MediaComposition.

Затем я пытаюсь выполнить рендеринг в видеофайл. Когда я пытаюсь сохранить файл, он выдает ошибку

System.Runtime.InteropServices.COMException Поток не в состоянии обработать запрос.

РЕДАКТИРОВАТЬ: я выяснил, где проблема, но не почему и не как ее исправить.

            await videoClip.SaveAsync(video2);
            videoClip= await MediaComposition.LoadAsync(video2);
            var x=await videoClip.RenderToFileAsync(video2);

Теперь с помощью этих трех строк я могу сохранить видео,но используя только третью строку, выдает ошибку выше.Я не могу понять это.Почему сохранение и загрузка решают проблему ??

Ответы [ 2 ]

0 голосов
/ 15 октября 2018

Наиболее вероятная причина в том, что CanvasBitmap имеет базовый объект IDirce3DSurface, а также данные изображения, такие как byte[] или что-то еще, хотя я не уверен в этом.

Если это правда,тогда создание CanvasBitmap из byte[] или IBuffer не повлияет на базовый IDirect3DSurface, будет создана только часть изображения.Вы можете видеть, что, сохраняя этот образ на диске, он не выдает ошибку.

Но Я думаю, что есть обходной путь, если вы хотите пропустить сохранение данных на диске :

Вы можете создать базовый IDirect3DSurface, если выполните Внеэкранное рисование для CanvasRenderTarget .

Итак, вы можете использовать CanvasBitmap для создания CanvasRenderTarget, а затем используйте это CanvasRenderTarget для создания MediaClip:

CanvasRenderTarget rendertarget;
using (CanvasBitmap canvas = CanvasBitmap.CreateFromBytes(CanvasDevice.GetSharedDevice(), pixels, renderTargetBitmap.PixelWidth, renderTargetBitmap.PixelHeight, format))
{
     rendertarget = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), canvas.SizeInPixels.Width, canvas.SizeInPixels.Height, 96);
     using (CanvasDrawingSession ds = rendertarget.CreateDrawingSession())
     {
         ds.Clear(Colors.Black);
         ds.DrawImage(canvas);
     }
}
MediaClip d = MediaClip.CreateFromSurface(renderTarget, TimeSpan.FromMilliseconds(80));
mc.Clips.Add(m);
0 голосов
/ 27 июня 2018

Метод MediaComposition.RenderToFileAsync сохраняет композицию в видеофайл, который можно воспроизвести с помощью стандартных медиаплееров.Из информации об ошибке кажется, что содержимое потока не является правильными данными мультимедиа и не может быть визуализировано непосредственно в видеофайл.

Итак, чтобы создать видео из нескольких RenderTargetBitmaps в UWP, вам следует выбрать способ использования файла изображения.используя метод MediaClip.CreateFromImageFileAsync , сохраняя RenderTargetBitmap в файл, а затем используя его для создания видео.

private async void CreateVideoByConvertRenderBitmapToFile()
{
    var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync("Test", 
        CreationCollisionOption.ReplaceExisting);
    var composition = new MediaComposition();
    for (int i = 0; i < 5; i++)
    {
        RenderTargetBitmap render = new RenderTargetBitmap();
        await render.RenderAsync(RenderGrid);
        MyImage.Source = render;
        var pixel = await render.GetPixelsAsync();
        var file = await folder.CreateFileAsync("test.png", CreationCollisionOption.GenerateUniqueName);
        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.ReadWrite))
        {
            var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
            encoder.SetPixelData(
                BitmapPixelFormat.Bgra8,
                BitmapAlphaMode.Ignore,
                (uint)render.PixelWidth,
                (uint)render.PixelHeight,
                logicalDpi,
                logicalDpi,
                pixel.ToArray());
            await encoder.FlushAsync();
            stream.Dispose();
            MediaClip clip = await MediaClip.CreateFromImageFileAsync(file, TimeSpan.FromSeconds(3));
            composition.Clips.Add(clip);
            MyText.Text = "First frame >>>" + i;
        }
    }
    var video = await ApplicationData.Current.LocalFolder.CreateFileAsync("test.mp4",
        CreationCollisionOption.ReplaceExisting);
    var action = await composition.RenderToFileAsync(video, MediaTrimmingPreference.Precise);
    await folder.DeleteAsync();
}
...