Как перенести этот код opengl из xcode в Monotouch? - PullRequest
0 голосов
/ 07 марта 2012

Я пытаюсь преобразовать следующий код в 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?

Есть ли способ, которым я могу их вызвать?

Ответы [ 2 ]

2 голосов
/ 07 марта 2012

Я не очень знаком с 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;
        }
    }
}

Поскольку вы не предоставили пару точек данных, мне просто нужно было оставить их как нулевые значения или распечатать значение, не назначая его ни для чего.

0 голосов
/ 08 марта 2012

Большое вам спасибо, хотя предоставленный вами образец не сработал, он мне очень помог. :)

Это код, с которым я закончил (я немного отредактировал его для ясности):

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

    }

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

В основном поток программы выглядит так:

  1. Извлечение видеокадра (я знаю, что они действительно идут в правильном порядке)
  2. Подайте кадр вышеописанным способом и создайте текстуру
  3. Рисование текстуры (фактически рисуется кадр +/- 5 кадров из текущего кадра)

Очень просто, но, кажется, Monotouch плохо играет.

Это странно, поскольку приведенный выше код является точной копией версии xCode, которая работает нормально. Не уверен, что происходит, но я подозреваю, что это связано с автоматическим управлением памятью в Monotouch.

Кроме того, если видео имеет разрешение не в два раза больше, я получаю черную текстуру ... Не проблема при использовании Objective C. Опять же, не уверен, что здесь происходит с Monotouch ... (

...