VideoMaterial *VideoMaterial::create(const BufferFormat & format)
{
    VideoMaterial *material = NULL;

    switch (format.videoFormat()) {
    // BGRx
    case GST_VIDEO_FORMAT_BGRx:
    case GST_VIDEO_FORMAT_BGRA:
        material = new VideoMaterialImpl<qtvideosink_glsl_bgrxFragmentShader>;
        material->initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
        break;
    case GST_VIDEO_FORMAT_BGR:
        material = new VideoMaterialImpl<qtvideosink_glsl_bgrxFragmentShader>;
        material->initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
        break;

    // xRGB
    case GST_VIDEO_FORMAT_xRGB:
    case GST_VIDEO_FORMAT_ARGB:
    case GST_VIDEO_FORMAT_AYUV:
        material = new VideoMaterialImpl<qtvideosink_glsl_xrgbFragmentShader>;
        material->initRgbTextureInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, format.frameSize());
        break;

    // RGBx
    case GST_VIDEO_FORMAT_RGB:
    case GST_VIDEO_FORMAT_v308:
        material = new VideoMaterialImpl<qtvideosink_glsl_rgbxFragmentShader>;
        material->initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, format.frameSize());
        break;
    case GST_VIDEO_FORMAT_RGB16:
        material = new VideoMaterialImpl<qtvideosink_glsl_rgbxFragmentShader>;
        material->initRgbTextureInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, format.frameSize());
        break;

    // YUV 420 planar
    case GST_VIDEO_FORMAT_I420:
    case GST_VIDEO_FORMAT_YV12:
        material = new VideoMaterialImpl<qtvideosink_glsl_yuvPlanarFragmentShader>;
        material->initYuv420PTextureInfo(
            (format.videoFormat() == GST_VIDEO_FORMAT_YV12) /* uvSwapped */,
            format.frameSize());
        break;

    default:
        Q_ASSERT(false);
        break;
    }

    material->init(format.colorMatrix());
    return material;
}