我正在尝试将以下代码转换为Monotouch:
if (videoTextureCache == NULL) {
// Create a new CVOpenGLESTexture cache
CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, self.context, NULL, &videoTextureCache);
if (err) {
NSLog(@"Error at CVOpenGLESTextureCacheCreate %d", err);
}
}
if (videoTextureCache) {
CMSampleBufferRef sampleBuffer = self.videoFrameReader.sampleBuffer;
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
// Create a CVOpenGLESTexture from the CVImageBuffer
size_t frameWidth = CVPixelBufferGetWidth(imageBuffer);
size_t frameHeight = CVPixelBufferGetHeight(imageBuffer);
CVOpenGLESTextureRef texture = NULL;
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
videoTextureCache,
imageBuffer,
NULL,
GL_TEXTURE_2D,
GL_RGBA,
frameWidth,
frameHeight,
GL_BGRA,
GL_UNSIGNED_BYTE,
0,
&texture);
if (!texture || err) {
NSLog(@"CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);
return;
} else {
self.cubeTextureName = CVOpenGLESTextureGetName(texture);
}
// Flush the CVOpenGLESTexture cache and release the texture
CVOpenGLESTextureCacheFlush(videoTextureCache, 0);
CFRelease(texture);
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
这与将视频快速渲染成opengl纹理有关。它在xCode中运行良好,具有出色的性能,但现在我需要让它在Monotouch相关项目中工作。
但是,我对如何移植此代码感到很遗憾,因为我找不到必要的Monotouch绑定,也没有关于上面使用的关键方法的Monotouch相关文档,如CVOpenGLESTextureCacheCreateTextureFromImage和CVOpenGLESTextureCacheCreate。他们是否从Monotouch中丢失了?
有没有办法可以调用它们?
答案 0 :(得分:2)
我对OpenGL不是很熟悉,所以我可能会把样本弄错,但这是一个起点:
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using MonoTouch.CoreVideo;
using MonoTouch.CoreMedia;
using System.Runtime.InteropServices;
using MonoTouch.OpenGLES;
using OpenTK.Platform.iPhoneOS;
using OpenTK.Graphics.ES20;
using OpenTK;
namespace cv1
{
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
UIWindow window;
[DllImport (MonoTouch.Constants.CoreVideoLibrary)]
extern static int CVOpenGLESTextureCacheCreate (IntPtr alloc, IntPtr cache, IntPtr eaglContext, IntPtr textureAttr, out IntPtr cache);
[DllImport (MonoTouch.Constants.CoreVideoLibrary)]
extern static int CVOpenGLESTextureCacheCreateTextureFromImage (IntPtr alloc, IntPtr textureCache, IntPtr sourceImage, IntPtr textureAttr, EnableCap target, PixelFormat internalFormat, int width, int height, int format, DataType type, int planeIndex, out IntPtr texture);
[DllImport (MonoTouch.Constants.CoreVideoLibrary)]
extern static int CVOpenGLESTextureCacheFlush (IntPtr texture, int v);
[DllImport (MonoTouch.Constants.CoreVideoLibrary)]
extern static int CVOpenGLESTextureGetName (IntPtr texture);
[DllImport (MonoTouch.Constants.CoreFoundationLibrary, CharSet=CharSet.Unicode)]
internal extern static IntPtr CFRelease (IntPtr obj);
IntPtr videoTextureCache;
void Stuff (EAGLContext context)
{
int err;
if (videoTextureCache == IntPtr.Zero) {
err = CVOpenGLESTextureCacheCreate (IntPtr.Zero, IntPtr.Zero, context.Handle, IntPtr.Zero, out videoTextureCache);
if (err != 0){
Console.WriteLine ("Error at CVOpenGLESTextureCacheCreate {0}", err);
return;
}
}
CMSampleBuffer sampleBuffer = null; //videoFrameReader.SampleBuffer;
CVPixelBuffer imageBuffer = (CVPixelBuffer) sampleBuffer.GetImageBuffer ();
imageBuffer.Lock (CVOptionFlags.None);
int frameWidth = imageBuffer.Width;
int frameHeight = imageBuffer.Height;
IntPtr texture = IntPtr.Zero;
err = CVOpenGLESTextureCacheCreateTextureFromImage(IntPtr.Zero,
videoTextureCache,
imageBuffer.Handle,
IntPtr.Zero,
EnableCap.Texture2D,
PixelFormat.Rgba,
frameWidth,
frameHeight,
0x10B6,
DataType.UnsignedByte,
0,
out texture);
if (texture == IntPtr.Zero || err != 0) {
Console.WriteLine("CVOpenGLESTextureCacheCreateTextureFromImage failed (error: {0})", err);
return;
} else {
Console.WriteLine ("Texture name: {0}", CVOpenGLESTextureGetName(texture));
}
CVOpenGLESTextureCacheFlush(videoTextureCache, 0);
CFRelease(texture);
imageBuffer.Unlock (CVOptionFlags.None);
}
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);
window.MakeKeyAndVisible ();
return true;
}
}
}
由于您没有提供几个数据点,我只需将它们保留为空值或打印出值而不将其分配给任何数据点。
答案 1 :(得分:0)
非常感谢你,虽然你提供的样本不起作用,但它帮助了我很多。 :)
这是我最终编写的代码(为了清晰起见,我进行了一些编辑):
[DllImport (MonoTouch.Constants.CoreVideoLibrary)]
extern static int CVOpenGLESTextureCacheCreateTextureFromImage (
IntPtr allocator,
IntPtr textureCache,
IntPtr sourceImage,
IntPtr textureAttributes,
int target,
int internalFormat,
int width,
int height,
int format,
int type,
int planeIndex,
ref IntPtr textureOut);
[DllImport (MonoTouch.Constants.CoreVideoLibrary)]
extern static int CVOpenGLESTextureCacheFlush (IntPtr texture, int v);
[DllImport (MonoTouch.Constants.CoreVideoLibrary)]
extern static int CVOpenGLESTextureGetName (IntPtr texture);
[DllImport (MonoTouch.Constants.CoreFoundationLibrary, CharSet=CharSet.Unicode)]
internal extern static IntPtr CFRelease (IntPtr obj);
private IntPtr videoTextureCache;
unsafe public void setTexture(CVImageBuffer sampleBuffer)
{
int err;
if (videoTextureCache == IntPtr.Zero) {
EAGLContext eaglContext=Global.localScreen.view.Context;
err = CVOpenGLESTextureCacheCreate (IntPtr.Zero, IntPtr.Zero, eaglContext.Handle, IntPtr.Zero, out videoTextureCache);
if (err != 0){
Console.WriteLine ("Error at CVOpenGLESTextureCacheCreate {0}", err);
return;
}
}
CVPixelBuffer pixelBuffer = (CVPixelBuffer) sampleBuffer;
pixelBuffer.Lock (CVOptionFlags.None);
int frameWidth = pixelBuffer.Width;
int frameHeight = pixelBuffer.Height;
IntPtr texture = IntPtr.Zero;
err = CVOpenGLESTextureCacheCreateTextureFromImage(IntPtr.Zero,
videoTextureCache,
pixelBuffer.Handle,
IntPtr.Zero,
(int)All.Texture2D,
(int)All.Rgba,
frameWidth,
frameHeight,
(int)All.Bgra,
(int)All.UnsignedByte,
0,
ref texture);
if (texture == IntPtr.Zero || err != 0) {
Console.WriteLine("CVOpenGLESTextureCacheCreateTextureFromImage failed (error: {0})", err);
return;
} else {
Console.WriteLine ("Texture name: {0}", CVOpenGLESTextureGetName(texture));
}
CVOpenGLESTextureCacheFlush(videoTextureCache, 0);
CFRelease(texture);
pixelBuffer.Unlock (CVOptionFlags.None);
}
我仍然有一些奇怪的问题。当播放视频并将各个帧发送到上述方法时,帧以稍微随机的顺序绘制,使视频闪烁,尽管帧确实以正确的顺序进入该方法。
基本上程序流程是这样的:
非常简单,但似乎Monotouch并没有很好地发挥作用。
这很奇怪,因为上面的代码是xCode版本的精确副本,可以正常工作。不知道发生了什么,但我怀疑它与Monotouch中的自动内存管理有关。
此外,如果视频的分辨率不是2的幂,我会得到黑色纹理......使用Objective C时没问题。再次,不知道Monotouch在这里发生了什么...... :(