StorageItemThumbnail到BitmapImage转换器失败,MediaCapture mp4

时间:2014-08-25 19:57:24

标签: windows-runtime winrt-xaml windows-phone-8.1

我正在使用ValueConverter来获取直接使用WinRT的 MediaCapture 记录的m4文件的缩略图。经过大量的调试和替代方法,我已经确定了下面的转换器代码。我在 GetThumbnailAsync 方法上收到以下错误The component cannot be found. (Exception from HRESULT: 0x88982F50)

我已确认当我使用CopyTo(KnownFolders.VideosLibrary)时,Xbox视频应用和文件资源管理器应用中的视频会显示缩略图

当它是外部视频文件时,转换器似乎工作正常,但不适用于我的某个应用程序的mp4。我的转换器有什么问题,或者你能重现吗?

SEE UPDATE 1 我尝试在首次创建文件时获取缩略图,发生同样的错误。

public class ThumbnailToBitmapImageConverter : IValueConverter
{
    readonly StorageFolder localFolder = ApplicationData.Current.LocalFolder;
    BitmapImage image;

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
            return "images/ExamplePhoto2.jpg";

        if (value == null)
            return "";

        var fileName = (string)value;

        if (string.IsNullOrEmpty(fileName))
            return "";

        var bmi = new BitmapImage();
        bmi.SetSource(Thumb(fileName).Result);
        return bmi;
    }

    private async Task<StorageItemThumbnail> Thumb(string fileName)
    {
        try
        {
            var file = await localFolder.GetFileAsync(fileName)
                .AsTask().ConfigureAwait(false);
            var thumbnail = await file.GetScaledImageAsThumbnailAsync(ThumbnailMode.ListView, 90, ThumbnailOptions.UseCurrentScale)
                .AsTask().ConfigureAwait(false);
            return thumbnail;
        }
        catch (Exception ex)
        {
            new MessageDialog(ex.Message).ShowAsync();
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

更新1

我决定回到我将视频保存到文件的位置并抓取缩略图,然后将其保存到图像以供日后使用。我得到了同样的错误,这里是保存视频后抓取并保存缩略图的代码:

var thumb = await videoStorageFile.GetThumbnailAsync(ThumbnailMode.ListView);
var buffer = new Windows.Storage.Streams.Buffer(Convert.ToUInt32(thumb.Size));
var thumbBuffer = await thumb.ReadAsync(buffer, buffer.Capacity, InputStreamOptions.None);
using (var str = await thumbImageFile.OpenAsync(FileAccessMode.ReadWrite))
{
      await str.WriteAsync(thumbBuffer);
}

1 个答案:

答案 0 :(得分:2)

我没有对此进行测试,但它应该可行。在要绑定到的模型中,使用名为Thumbnail的新类替换缩略图的属性。绑定到该属性而不是您的视频位置。当视频位置发生变化时,请创建一个新的缩略图。

public class VideoViewModel : INotifyPropertyChanged
{
    public string VideoLocation
    {
        get { return _location; }
        set
        {
            _location = value;
            Thumbnail = new Thumbnail(value);
            OnPropertyChanged();
        }
    }

    public Thumbnail Thumbnail
    {
        get { return _thumbnail; }
        set
        {
            _thumbnail = value;
            OnPropertyChanged();
        }
    }
}

缩略图类。这只是一个shell,随时可以填写其余部分

public class Thumbnail : INotifyPropertyChanged
{
    public Thumbnail(string location)
    {
        Image = GetThumbFromVideoAsync(location);
    }

    private Task<BitMapSource> GetThumbFromVideoAsync(string location)
    {
        BitMapSource result;
        // decode

        // set it again to force
        Image = Task.FromResult(result);
    }

    public Task<BitMapSource> Image
    {
        get { return _image; }
        private set
        {
            _image = value;
            OnPropertyChanged();
        }
    }
}

您仍然可以使用值转换器。它会检查任务是否已完成,如果没有,则显示一些默认图像。如果任务出现故障,则可能会显示一些错误图像:

public class ThumbnailToBitmapImageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var thumbnail = value as Thumbnail;
        if (thumbnail == null) return GetDefaultBitmap();

        if (thumbnail.Image.IsCompleted == false) return GetDefaultBitmap();
        if (thumbnail.Image.IsFaulted) return GetBadImage();

        return thumbnail.Image.Result;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }

    private BitMapSource GetDefaultBitmap()
    {
        // load a default image
    }

    private BitMapSource GetBadImage()
    {
        // load a ! image
    }
}