201 lines
5.1 KiB
Plaintext
201 lines
5.1 KiB
Plaintext
enum Theorafile_VideoState
|
|
{
|
|
Stopped,
|
|
Playing,
|
|
Paused
|
|
}
|
|
|
|
function Theorafile_Open(filename)
|
|
{
|
|
var _handle = ptr(TheorafileGMS_Open(filename));
|
|
show_debug_message("Successfully loaded Theorafile video with handle: " + string(_handle));
|
|
|
|
var _yWidth = TheorafileGMS_Width(_handle);
|
|
var _yHeight = TheorafileGMS_Height(_handle);
|
|
var _frames_per_second = TheorafileGMS_FPS(_handle);
|
|
var _uvWidth = TheorafileGMS_UVWidth(_handle);
|
|
var _uvHeight = TheorafileGMS_UVHeight(_handle);
|
|
|
|
var _bufferSize = TheorafileGMS_RequiredBufferSizeInBytes(_handle);
|
|
|
|
vertex_format_begin();
|
|
vertex_format_add_position();
|
|
vertex_format_add_texcoord();
|
|
var _vformat = vertex_format_end();
|
|
|
|
var _vbuff = vertex_create_buffer();
|
|
vertex_begin(_vbuff, _vformat);
|
|
vertex_position(_vbuff, -1, 1);
|
|
vertex_texcoord(_vbuff, 0, 0);
|
|
vertex_position(_vbuff, 3, 1);
|
|
vertex_texcoord(_vbuff, 2, 0);
|
|
vertex_position(_vbuff, -1, -3);
|
|
vertex_texcoord(_vbuff, 0, 2);
|
|
vertex_end(_vbuff);
|
|
|
|
var _video = {
|
|
handle: _handle,
|
|
bufferSize: _bufferSize,
|
|
yuvBuffer: buffer_create(_bufferSize, buffer_fixed, 4),
|
|
yWidth: _yWidth,
|
|
yHeight: _yHeight,
|
|
uvWidth: _uvWidth,
|
|
uvHeight: _uvHeight,
|
|
framesPerSecond: _frames_per_second,
|
|
ySurface: surface_create(_yWidth, _yHeight),
|
|
uSurface: surface_create(_uvWidth, _uvHeight),
|
|
vSurface: surface_create(_uvWidth, _uvHeight),
|
|
videoSurface: surface_create(_yWidth, _yHeight),
|
|
elapsed_time: 0,
|
|
currentFrame: 0,
|
|
state: Theorafile_VideoState.Stopped,
|
|
looping: false,
|
|
loopCounter: 0,
|
|
timesToLoop: 0,
|
|
triangle_buffer: _vbuff,
|
|
triangle_buffer_format: _vformat
|
|
};
|
|
|
|
// grab the first frame ASAP
|
|
while (TheorafileGMS_ReadVideo(_video.handle, buffer_get_address(_video.yuvBuffer), 1) == 0) { }
|
|
|
|
return _video;
|
|
}
|
|
|
|
function Theorafile_Close(video)
|
|
{
|
|
surface_free(video.ySurface);
|
|
surface_free(video.uSurface);
|
|
surface_free(video.vSurface);
|
|
surface_free(video.videoSurface);
|
|
buffer_delete(video.yuvBuffer);
|
|
vertex_format_delete(video.triangle_buffer_format);
|
|
vertex_delete_buffer(video.triangle_buffer);
|
|
TheorafileGMS_Close(video.handle);
|
|
}
|
|
|
|
function Theorafile_Play(video)
|
|
{
|
|
if (video.state != Theorafile_VideoState.Playing)
|
|
{
|
|
if (video.handle != 0 && TheorafileGMS_HasVideo(video.handle) == 1)
|
|
{
|
|
video.state = Theorafile_VideoState.Playing;
|
|
}
|
|
}
|
|
}
|
|
|
|
function Theorafile_SetLoop(video, loop = true, times = 10000000000000)
|
|
{
|
|
video.looping = loop;
|
|
video.loopCounter = 0;
|
|
video.timesToLoop = times;
|
|
}
|
|
|
|
function Theorafile_Reset(video)
|
|
{
|
|
TheorafileGMS_Reset(video.handle);
|
|
// grab the first frame ASAP
|
|
while (TheorafileGMS_ReadVideo(video.handle, buffer_get_address(video.yuvBuffer), 1) == 0) { }
|
|
|
|
video.elapsed_time = 0;
|
|
video.currentFrame = 0;
|
|
}
|
|
|
|
function Theorafile_Pause(video)
|
|
{
|
|
video.state = Theorafile_VideoState.Paused;
|
|
}
|
|
|
|
function Theorafile_Stop(video)
|
|
{
|
|
Theorafile_Reset(video);
|
|
video.state = Theorafile_VideoState.Stopped;
|
|
}
|
|
|
|
function Theorafile_UpdateTextures(video)
|
|
{
|
|
if (!surface_exists(video.ySurface))
|
|
{
|
|
video.ySurface = surface_create(video.yWidth, video.yHeight);
|
|
}
|
|
|
|
if (!surface_exists(video.uSurface))
|
|
{
|
|
video.uSurface = surface_create(video.uvWidth, video.uvHeight);
|
|
}
|
|
|
|
if (!surface_exists(video.vSurface))
|
|
{
|
|
video.vSurface = surface_create(video.uvWidth, video.uvHeight);
|
|
}
|
|
|
|
var _y_data_length = (video.yWidth * video.yHeight * 4);
|
|
var _uv_data_length = (video.uvWidth * video.uvHeight * 4);
|
|
|
|
buffer_set_surface(video.yuvBuffer, video.ySurface, 0);
|
|
buffer_set_surface(video.yuvBuffer, video.uSurface, _y_data_length);
|
|
buffer_set_surface(video.yuvBuffer, video.vSurface, _y_data_length + _uv_data_length);
|
|
}
|
|
|
|
function Theorafile_UpdateSurface(video)
|
|
{
|
|
if (video.state == Theorafile_VideoState.Playing)
|
|
{
|
|
video.elapsed_time += 1 / room_speed;
|
|
|
|
var _current_frame = floor(video.elapsed_time * video.framesPerSecond);
|
|
|
|
if (_current_frame > video.currentFrame)
|
|
{
|
|
if TheorafileGMS_ReadVideo(video.handle, buffer_get_address(video.yuvBuffer), _current_frame - video.currentFrame) >= 1
|
|
{
|
|
Theorafile_UpdateTextures(video);
|
|
|
|
if !surface_exists(video.videoSurface)
|
|
{
|
|
video.videoSurface = surface_create(video.yWidth, video.yHeight);
|
|
}
|
|
|
|
surface_set_target(video.videoSurface);
|
|
shader_set(YUVToRGB);
|
|
|
|
ySampler = shader_get_sampler_index(YUVToRGB, "y_tex");
|
|
uSampler = shader_get_sampler_index(YUVToRGB, "u_tex");
|
|
vSampler = shader_get_sampler_index(YUVToRGB, "v_tex");
|
|
texture_set_stage(ySampler, surface_get_texture(video.ySurface));
|
|
texture_set_stage(uSampler, surface_get_texture(video.uSurface));
|
|
texture_set_stage(vSampler, surface_get_texture(video.vSurface));
|
|
|
|
vertex_submit(video.triangle_buffer, pr_trianglelist, -1);
|
|
|
|
shader_reset();
|
|
surface_reset_target();
|
|
}
|
|
|
|
video.currentFrame = _current_frame;
|
|
}
|
|
|
|
var _ended = TheorafileGMS_EndOfStream(video.handle);
|
|
|
|
if (_ended)
|
|
{
|
|
Theorafile_Reset(video);
|
|
|
|
if (video.looping)
|
|
{
|
|
video.loopCounter += 1;
|
|
if video.loopCounter > video.timesToLoop
|
|
{
|
|
video.looping = false;
|
|
video.state = Theorafile_VideoState.Stopped;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
video.state = Theorafile_VideoState.Stopped;
|
|
}
|
|
}
|
|
}
|
|
}
|