문제

샘플 원시 YUV 파일을 가져 와서 Cocoa OpenGL 프로그램에 표시하는 프로그램을 작성하도록 작업을 할당했습니다.

나는 직장에서 인턴이고 시작하는 방법이 거의 없거나 전혀 없습니다. YUV에서 Wikipedia & Articles를 읽었지만 RAW YUV 파일을 열고 데이터를 추출하여 RGB로 변환하여보기 창에 표시하는 방법에 대한 좋은 소스 코드를 찾을 수 없었습니다.

기본적으로 샘플 YUV 파일에서 YUV 데이터를 추출하는 방법 (YUV 데이터를 RGB 색상 공간으로 변환하는 방법)에 대한 도움이 필요합니다. OpenGL에 RGB 색상 공간을 표시하는 방법. (이것은 시간이 지남에 따라 알아낼 수 있다고 생각하지만 처음 두 지점에 대한 도움이 필요합니다)

사용할 수업을 알려 주거나 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) 종료 중.

다른 팁

CCD 카메라에서 캡처 한 YUV 프레임으로 작업을 수행했습니다. 불행히도 여러 가지 YUV 형식이 있습니다. 나는 애플이 사용하는 것을 믿는다 GL_YCBCR_422_APPLE 텍스처 형식은 기술적으로 2VUY422입니다. IIDC FireWire 카메라로 생성 된 YUV422 프레임에서 이미지를 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 비디오 소스를 효율적으로 표시하려면 사용하고 싶을 수도 있습니다. Apple의 클라이언트 스토리지 확장, 다음과 같은 것을 사용하여 설정할 수 있습니다.

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

Adam Rosenfield의 의견이 잘못되었습니다. Mac에서는 YCBCR (YUV와 동등한 디지털) 텍스처를 사용하여 GL_YCBCR_422_APPLE 텍스처 형식, apple_ycbcr_422 확대.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top