1

我正在尝试将样本从 Objective C 转换为 Monotouch,但遇到了一些困难。

基本上我想读取一个视频文件,并将帧一一解码为opengl纹理。

这样做的关键是使用 AVAssetReader,但我不确定如何在 Monotouch 中正确设置它。

这是我的代码:

    AVUrlAsset asset=new AVUrlAsset(NSUrl.FromFilename(videoFileName),null);
    assetReader=new AVAssetReader(asset,System.IntPtr.Zero);
    AVAssetTrack videoTrack=asset.Tracks[0];
    NSDictionary videoSettings=new NSDictionary();

    NSString key = CVPixelBuffer.PixelFormatTypeKey;
    NSNumber val=0x754b9d0; //NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]; - Had to hardcode constant as it is not defined in Monotouch?

    videoSettings.SetNativeField(key,val);

//**The program crashes here:
    AVAssetReaderTrackOutput trackOutput=new AVAssetReaderTrackOutput(videoTrack,videoSettings);

    assetReader.AddOutput(trackOutput);
    assetReader.StartReading();

程序在上面指出的那一行崩溃,出现无效参数异常,说明 NSDictionary 的内容格式不正确?我检查了视频文件,它加载良好,“资产”包含有关视频的有效信息。

这是原始的 Objective C 代码:

                NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
                NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
                NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
                AVAssetReaderTrackOutput *trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:videoTrack outputSettings:videoSettings];

                [_assetReader addOutput:trackOutput];
                [_assetReader startReading];

我不是那么喜欢Objective C,所以感谢您的帮助。

编辑:我使用了下面建议的代码

var videoSettings = NSDictionary.FromObjectAndKey (
  new NSNumber ((int) MonoTouch.CoreVideo.CVPixelFormatType.CV32BGRA),
  MonoTouch.CoreVideo.CVPixelBuffer.PixelFormatTypeKey);

并且程序不再崩溃。通过使用以下代码:

        CMSampleBuffer buffer=assetReader.Outputs[0].CopyNextSampleBuffer();
        CVImageBuffer imageBuffer = buffer.GetImageBuffer();

我得到了应该包含视频文件中下一帧的图像缓冲区。通过检查 imageBuffer 对象,我发现它具有与视频文件匹配的宽度和高度等有效数据。

但是,imageBuffer BaseAddress 始终为 0,表示图像没有数据?我试图这样做作为一个测试:

        CVPixelBuffer buffer=(CVPixelBuffer)imageBuffer;
        CIImage image=CIImage.FromImageBuffer(buffer);

并且图像始终返回为空。这是否意味着实际的图像数据不存在,而我的 imageBuffer 对象仅包含帧头信息?

如果是这样,这是 Monotouch 中的错误,还是我设置错误?

我有一个想法,我可能需要等待图像数据准备好,但在这种情况下,我也不知道怎么做。现在很卡...

4

2 回答 2

3

您需要像这样创建 NSDictionary:

var videoSettings = NSDictionary.FromObjectAndKey (
  new NSNumber ((int) MonoTouch.CoreVideo.CVPixelFormatType.CV32BGRA),
  MonoTouch.CoreVideo.CVPixelBuffer.PixelFormatTypeKey);

SetNativeField是完全不同的东西(您将字段设置为CVPixelBuffer.PixelFormatTypeKey0x754b9d0而不是向字典添加键/值对)。

于 2012-01-20T01:37:20.830 回答
1

[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA]; - 必须硬编码常量,因为它没有在 Monotouch 中定义?

您应该可以将其替换为:

CVPixelFormatType.CV32BGRA

请注意,MonoTouch 将此值定义为0x42475241与您的不同。那可能是你的错误。如果不是,我建议您制作一个小型、自包含的测试用例,并将其附加到http://bugzilla.xamarin.com上的错误报告中,我们将对其进行查看。

指向 Objective-c 示例的链接(如果可用)也会有所帮助(此处是对您的问题或错误报告的更新)。

于 2012-01-19T13:12:25.553 回答