YUV 비디오 처리
YUV 색상 형식을 사용하는 비디오 플랫폼에서는 비디오를 그리기 위해 추가적인 단계가 필요합니다. 이 과정에는 셰이더를 사용하여 기본 쿼드에 두 개의 서피스를 그리는 것이 포함됩니다. 먼저 video_draw()
참조 페이지를 읽고 YUV 비디오에 대한 데이터가 무엇인지 확인한 후, 아래의 지침을 따라 비디오를 그리는 방법을 알아보세요.
YUV 셰이더 생성
프로젝트에 셰이더 자산을 생성하고, 그 조각 셰이더(.fsh) 코드를 다음으로 교체합니다:
//
// CUSTOM fragment shader for handling YUV content
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
uniform sampler2D v_chroma;
const float x = 1.164383;
const float y = 1.138393;
const float z = 1.138393;
const vec3 src_bias = vec3(16.0 / 255.0, 128.0 / 255.0, 128.0 / 255.0);
const mat3 src_xform = mat3(1.00000000 * x, 0.00000000 * y, 1.57480000 * z,
1.00000000 * x, -0.18732427 * y, -0.46812427 * z,
1.00000000 * x, 1.85560000 * y, 0.00000000 * z);
void main()
{
float yy = texture2D(gm_BaseTexture, vec2(v_vTexcoord.x, v_vTexcoord.y)).r;
vec2 cbcr = texture2D(v_chroma, vec2(v_vTexcoord.x, v_vTexcoord.y)).rg;
vec3 yuv = vec3(yy, cbcr);
yuv -= src_bias;
yuv *= src_xform;
gl_FragColor = vec4(yuv, 1.0);
}
샘플러 가져오기
객체의 생성 이벤트에서 비디오가 YUV인 경우에만 v_chroma
셰이더 유니폼의 샘플러 ID를 가져옵니다:
var _format = video_get_format();
if (_format == video_format_yuv)
{
videochromasampler = shader_get_sampler_index(shader_YUV, "v_chroma");
}
비디오 그리기
객체의 그리기 이벤트에서 video_draw()
를 호출하고, 첫 번째 배열 위치가 0(비디오가 재생 중임을 의미)인 경우 비디오를 그립니다. 아래 코드는 video_get_format()
함수에 대한 switch 문을 사용합니다. 비디오가 RGBA 형식을 사용하는 경우, 배열의 위치 [1]에 있는 서피스를 간단히 그립니다. 비디오가 YUV 형식을 사용하는 경우, 셰이더를 사용하여 두 개의 서피스(위치 [1] 및 [2])를 기본 쿼드에 그립니다.
var _data = video_draw();
if(_data[0] == 0)
{
switch(video_get_format())
{
case video_format_rgba:
var _surf = _data[1];
draw_surface(_surf,0,0);
break;
// #### YUV PART HERE ####
case video_format_yuv:
var _surf = _data[1];
var _chromasurf = _data[2];
if(surface_exists(_surf) and surface_exists(_chromasurf))
{
shader_set(shader_YUV);
var _tex_id = surface_get_texture(_surf);
var _chroma_tex_id = surface_get_texture(_chromasurf);
texture_set_stage(videochromasampler, _chroma_tex_id);
gpu_set_texfilter(false);
draw_primitive_begin_texture(pr_trianglestrip, _tex_id);
draw_vertex_texture(0, 0, 0, 0);
draw_vertex_texture(surface_get_width(_chromasurf), 0, 1, 0);
draw_vertex_texture(0, surface_get_height(_chromasurf), 0, 1);
draw_vertex_texture(surface_get_width(_chromasurf), surface_get_height(_chromasurf), 1, 1);
draw_primitive_end();
gpu_set_texfilter(true);
shader_reset();
}
break;
}
}
YUV 비디오 처리 과정
case video_format_yuv:
아래의 코드는 다음과 같은 작업을 수행합니다:
- 비디오 서피스(_surf)와 크로마 서피스(_chromasurf)를 가져옵니다.
- 두 서피스가 존재하는지 확인합니다(
surface_exist()
사용). - 셰이더를
shader_YUV
로 설정합니다(새로 생성한 YUV 셰이더). - 두 서피스의 텍스처를 가져옵니다.
- 생성 이벤트에서 가져온 샘플러에 크로마 서피스의 텍스처를 할당합니다.
- 텍스처 필터링을 비활성화합니다.
- 비디오 서피스의 텍스처가 할당된 삼각형 스트립 기본 도형을 그리기 시작합니다.
- 비디오 서피스를 덮는 사각형을 그립니다. 이때 크로마 서피스의 너비와 높이를 사용합니다.
- 기본 도형을 종료합니다.
- 텍스처 필터링을 다시 활성화하고 셰이더를 초기화합니다.
여기서 기본 비디오 서피스는 기본 도형에 의해 그려지고, 크로마 서피스는 셰이더에 의해 혼합됩니다. 이 때문에 크로마 서피스의 텍스처가 샘플러를 통해 셰이더로 전달되었습니다.
단계 | 설명 |
---|---|
1 | 비디오 서피스와 크로마 서피스 가져오기 |
2 | 서피스 존재 여부 확인 |
3 | YUV 셰이더 설정 |
4 | 서피스의 텍스처 가져오기 |
5 | 크로마 서피스 텍스처 할당 |
6 | 텍스처 필터링 비활성화 |
7 | 삼각형 스트립 그리기 시작 |
8 | 비디오 서피스 덮는 사각형 그리기 |
9 | 기본 도형 종료 |
10 | 텍스처 필터링 활성화 및 셰이더 초기화 |
활용 예제
YUV 비디오를 처리하는 방법에 대한 몇 가지 활용 예제는 다음과 같습니다:
// YUV 비디오 재생 예제
if (video_is_playing(video_id)) {
video_draw();
}
// YUV 비디오의 특정 프레임으로 이동
video_seek(video_id, frame_number);
// YUV 비디오의 볼륨 조절
video_set_volume(video_id, volume_level);
// YUV 비디오의 재생 속도 조절
video_set_speed(video_id, playback_speed);
// YUV 비디오의 반복 설정
video_set_loop(video_id, true);
// YUV 비디오의 일시 정지 및 재개
video_pause(video_id);
video_resume(video_id);
이러한 예제들은 YUV 비디오를 효과적으로 처리하고 다양한 기능을 구현하는 데 도움이 됩니다.