كيفية عرض إطار YUV الخام في برنامج الكاكاو برنامج OpenGL

StackOverflow https://stackoverflow.com/questions/1080545

سؤال

ولقد تم تعيين الطرافة مهمة لكتابة البرنامج الذي يأخذ ملف YUV الخام عينة وعرضه في برنامج الكاكاو برنامج OpenGL.

وأنا متدربة في وظيفتي ولدي القليل أو أي فكرة كيف تبدأ. لقد قرأت ويكيبيديا والمقالات حول YUV، ولكن لم أجد أي رمز مصدر جيد على كيفية فتح ملف YUV الخام، واستخراج البيانات وتحويلها إلى RGB وعرضه في إطار العرض.

وأساسا، أحتاج إلى مساعدة في الجوانب التالية المهمة ، كيف لاستخراج البيانات YUV من ملف YUV عينة ، كيفية تحويل البيانات YUV في الفضاء اللون RGB ، كيف لعرض مساحة اللون RGB في OpenGL. (هذا واحد وأعتقد أنني يمكن معرفة مع مرور الوقت، ولكن أنا حقا بحاجة إلى مساعدة في نقطتين الأولى)

ويرجى إما أن تقول لي الطبقات للاستخدام، أو لي نقطة إلى أماكن أين يمكنني معرفة المزيد عن YUV الرسم / عرض الفيديو

هل كانت مفيدة؟

المحلول

هذه الإجابة ليست صحيحة، راجع إجابات وتعليقات أخرى. الجواب الأصلية تركت أدناه للأجيال القادمة.


<الإضراب> لا يمكن عرضها مباشرة. ستحتاج إلى تحويله إلى نسيج RGB. كما كنت قد جمعت من ويكيبيديا ، وهناك مجموعة من التغيرات على مساحة YUV اللون. تأكد من أنك تستخدم حق واحد.

لكل بكسل، وتحويل من YUV إلى RGB هو تحويل خطي صريح. عليك أن تفعل الشيء نفسه لكل بكسل بشكل مستقل.

وبمجرد تحويل الصورة إلى RGB، يمكنك عرض من خلال إنشاء الملمس. تحتاج إلى استدعاء glGenTextures() ل تخصيص مقبض الملمس، glBindTexture() لربط نسيج إلى سياق تقديم، و glTexImage2D() لتحميل البيانات الملمس لGPU. لجعله، يمكنك استدعاء مرة أخرى glBindTexture()، تليها جعل من رباعية مع الملمس إحداثيات إعداد بشكل صحيح.

// parameters: image:  pointer to raw YUV input data
//             width:  image width (must be a power of 2)
//             height: image height (must be a power of 2)
// returns: a handle to the resulting RGB texture
GLuint makeTextureFromYUV(const float *image, int width, int height)
{
    float *rgbImage = (float *)malloc(width * height * 3 * sizeof(float));  // check for NULL
    float *rgbImagePtr = rgbImage;

    // convert from YUV to RGB (floats used here for simplicity; it's a little
    // trickier with 8-bit ints)
    int y, x;
    for(y = 0; y < height; y++)
    {
        for(x = 0; x < width; x++)
        {
            float Y = *image++;
            float U = *image++;
            float V = *image++;
            *rgbImagePtr++ = Y                + 1.13983f * V;  // R
            *rgbImagePtr++ = Y - 0.39465f * U - 0.58060f * V;  // G
            *rgbImagePtr++ = Y + 2.03211f * U;                 // B
        }
    }

    // create texture
    GLuint texture;
    glGenTextures(1, &texture);

    // bind texture to render context
    glBindTexture(GL_TEXTURE_2D, texture);

    // upload texture data
    glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_FLOAT, rgbImage);

    // don't use mipmapping (since we're not creating any mipmaps); the default
    // minification filter uses mipmapping.  Use linear filtering for minification
    // and magnification.
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    // free data (it's now been copied onto the GPU) and return texture handle
    free(rgbImage);
    return texture;
}

لتقديم:

glBindTexture(GL_TEXTURE_2D, texture);

glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.0f,  0.0f, 0.0f);
    glTexCoord2f(1.0f, 0.0f); glVertex3f(64.0f,  0.0f, 0.0f);
    glTexCoord2f(1.0f, 1.0f); glVertex3f(64.0f, 64.0f, 0.0f);
    glTexCoord2f(0.0f, 1.0f); glVertex3f( 0.0f, 64.0f, 0.0f);
glEnd();

ولا ننسى أن ندعو glEnable(GL_TEXTURE_2D) في مرحلة ما أثناء التهيئة، وندعو glDeleteTextures(1, &texture) أثناء إيقاف التشغيل.

نصائح أخرى

ولقد فعلت هذا مع إطارات YUV تم الاستيلاء عليها من كاميرا CCD. لسوء الحظ، هناك عدد من الأشكال YUV مختلفة. وأعتقد أن واحد يستخدم أبل لتنسيق GL_YCBCR_422_APPLE الملمس من الناحية الفنية 2VUY422. لتحويل صورة من إطار YUV422 التي تم إنشاؤها بواسطة كاميرا IIDC فايرواير إلى 2VUY422، لقد استعملت ما يلي:

void yuv422_2vuy422(const unsigned char *theYUVFrame, unsigned char *the422Frame, const unsigned int width, const unsigned int height) 
{
    int i =0, j=0;
    unsigned int numPixels = width * height;
    unsigned int totalNumberOfPasses = numPixels * 2;
    register unsigned int y0, y1, y2, y3, u0, u2, v0, v2;

    while (i < (totalNumberOfPasses) )
    {
        u0 = theYUVFrame[i++]-128;
        y0 = theYUVFrame[i++];
        v0 = theYUVFrame[i++]-128;
        y1 = theYUVFrame[i++];
        u2 = theYUVFrame[i++]-128;
        y2 = theYUVFrame[i++];
        v2 = theYUVFrame[i++]-128;
        y3 = theYUVFrame[i++];

        // U0 Y0 V0 Y1 U2 Y2 V2 Y3

        // Remap the values to 2VUY (YUYS?) (Y422) colorspace for OpenGL
        // Y0 U Y1 V Y2 U Y3 V

        // IIDC cameras are full-range y=[0..255], u,v=[-127..+127], where display is "video range" (y=[16..240], u,v=[16..236])

        the422Frame[j++] = ((y0 * 240) / 255 + 16);
        the422Frame[j++] = ((u0 * 236) / 255 + 128);
        the422Frame[j++] = ((y1 * 240) / 255 + 16);
        the422Frame[j++] = ((v0 * 236) / 255 + 128);
        the422Frame[j++] = ((y2 * 240) / 255 + 16);
        the422Frame[j++] = ((u2 * 236) / 255 + 128);
        the422Frame[j++] = ((y3 * 240) / 255 + 16);
        the422Frame[j++] = ((v2 * 236) / 255 + 128);
    }
}

لعرض كفاءة مصدر YUV الفيديو، قد ترغب في استخدام <لأ href = "http://developer.apple.com/documentation/graphicsimaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/opengl_texturedata.html#// apple_ref / وثيقة / رمز المستخدم / TP40001987-CH407-SW24 "يختلط =" noreferrer "> أبل تمديد تخزين العميل ، والتي يمكنك إعدادها باستخدام شيء كما يلي:

glEnable(GL_TEXTURE_RECTANGLE_EXT);
glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1);

glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, videoImageWidth * videoImageHeight * 2, videoTexture);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE);
glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE);

glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);

glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, videoImageWidth, videoImageHeight, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);    

وهذا يتيح لك بسرعة تغير من البيانات المخزنة ضمن العميل الملمس الفيديو قبل كل إطار للظهور على الشاشة.

لرسم، هل يمكن بعد ذلك استخدام رمز كما يلي:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);         
glEnable(GL_TEXTURE_2D);

glViewport(0, 0, [self frame].size.width, [self frame].size.height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
NSRect bounds = NSRectFromCGRect([self bounds]);
glOrtho( (GLfloat)NSMinX(bounds), (GLfloat)NSMaxX(bounds), (GLfloat)NSMinY(bounds), (GLfloat)NSMaxY(bounds), -1.0, 1.0);

glBindTexture(GL_TEXTURE_RECTANGLE_EXT, 1);
glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, videoImageWidth, videoImageHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_REV_APPLE, videoTexture);

glMatrixMode(GL_TEXTURE);
glLoadIdentity();

glBegin(GL_QUADS);
    glTexCoord2f(0.0f, 0.0f);
    glVertex2f(0.0f, videoImageHeight);

    glTexCoord2f(0.0f, videoImageHeight);
    glVertex2f(0.0f, 0.0f);

    glTexCoord2f(videoImageWidth, videoImageHeight);
    glVertex2f(videoImageWidth, 0.0f);

    glTexCoord2f(videoImageWidth, 0.0f);
    glVertex2f(videoImageWidth, videoImageHeight);      
glEnd();

وتعليق آدم روزنفيلد غير صحيح. على أجهزة ماكينتوش، يمكنك عرض YCbCr (أي ما يعادل رقمي لYUV) القوام باستخدام الشكل والملمس GL_YCBCR_422_APPLE، على النحو المحدد في في APPLE_ycbcr_422 التمديد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top