diff --git a/gamemaker/TheorafileGMS/TheorafileGMS.yyp b/gamemaker/TheorafileGMS/TheorafileGMS.yyp
index 1579ae7..1ef60a8 100644
--- a/gamemaker/TheorafileGMS/TheorafileGMS.yyp
+++ b/gamemaker/TheorafileGMS/TheorafileGMS.yyp
@@ -3,6 +3,7 @@
{"id":{"name":"TheorafileGMS","path":"extensions/TheorafileGMS/TheorafileGMS.yy",},"order":0,},
{"id":{"name":"TheorafileGMS_Scripts","path":"scripts/TheorafileGMS_Scripts/TheorafileGMS_Scripts.yy",},"order":0,},
{"id":{"name":"YUVToRGB","path":"shaders/YUVToRGB/YUVToRGB.yy",},"order":0,},
+ {"id":{"name":"Renderer","path":"objects/Renderer/Renderer.yy",},"order":0,},
{"id":{"name":"Room1","path":"rooms/Room1/Room1.yy",},"order":0,},
],
"Options": [
@@ -44,7 +45,9 @@
"TextureGroups": [
{"isScaled":true,"autocrop":true,"border":2,"mipsToGenerate":0,"groupParent":null,"targets":-1,"resourceVersion":"1.3","name":"Default","resourceType":"GMTextureGroup",},
],
- "IncludedFiles": [],
+ "IncludedFiles": [
+ {"CopyToMask":-1,"filePath":"datafiles","resourceVersion":"1.0","name":"celery_man.ogg","resourceType":"GMIncludedFile",},
+ ],
"MetaData": {
"IDEVersion": "2.3.6.595",
},
diff --git a/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.dll b/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.dll
index 304725a..43179a2 100644
Binary files a/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.dll and b/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.dll differ
diff --git a/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.yy b/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.yy
index 6f899da..42c7cb1 100644
--- a/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.yy
+++ b/gamemaker/TheorafileGMS/extensions/TheorafileGMS/TheorafileGMS.yy
@@ -69,6 +69,7 @@
{"name":"TheorafileGMS_EndOfStream","path":"extensions/TheorafileGMS/TheorafileGMS.yy",},
{"name":"TheorafileGMS_ReadVideo","path":"extensions/TheorafileGMS/TheorafileGMS.yy",},
],"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMExtensionFile",},
+ {"filename":"libtheorafile.dll","origname":"","init":"","final":"","kind":1,"uncompress":false,"functions":[],"constants":[],"ProxyFiles":[],"copyToTargets":-1,"order":[],"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMExtensionFile",},
],
"classname": "",
"tvosclassname": null,
@@ -89,7 +90,7 @@
"androidactivityinject": "",
"gradleinject": "",
"androidcodeinjection": "",
- "hasConvertedCodeInjection": false,
+ "hasConvertedCodeInjection": true,
"ioscodeinjection": "",
"tvoscodeinjection": "",
"iosSystemFrameworkEntries": [],
diff --git a/gamemaker/TheorafileGMS/extensions/TheorafileGMS/libtheorafile.dll b/gamemaker/TheorafileGMS/extensions/TheorafileGMS/libtheorafile.dll
new file mode 100644
index 0000000..016b8a8
Binary files /dev/null and b/gamemaker/TheorafileGMS/extensions/TheorafileGMS/libtheorafile.dll differ
diff --git a/gamemaker/TheorafileGMS/objects/Renderer/CleanUp_0.gml b/gamemaker/TheorafileGMS/objects/Renderer/CleanUp_0.gml
new file mode 100644
index 0000000..ce920f6
--- /dev/null
+++ b/gamemaker/TheorafileGMS/objects/Renderer/CleanUp_0.gml
@@ -0,0 +1 @@
+Theorafile_Close(video);
\ No newline at end of file
diff --git a/gamemaker/TheorafileGMS/objects/Renderer/Create_0.gml b/gamemaker/TheorafileGMS/objects/Renderer/Create_0.gml
new file mode 100644
index 0000000..3fb44aa
--- /dev/null
+++ b/gamemaker/TheorafileGMS/objects/Renderer/Create_0.gml
@@ -0,0 +1,3 @@
+video = Theorafile_Open("celery_man.ogg");
+
+Theorafile_Play(video);
diff --git a/gamemaker/TheorafileGMS/objects/Renderer/Draw_0.gml b/gamemaker/TheorafileGMS/objects/Renderer/Draw_0.gml
new file mode 100644
index 0000000..1487f70
--- /dev/null
+++ b/gamemaker/TheorafileGMS/objects/Renderer/Draw_0.gml
@@ -0,0 +1,3 @@
+Theorafile_UpdateSurface(video);
+
+draw_surface_stretched(video.videoSurface, 0, 0, surface_get_width(application_surface), surface_get_height(application_surface));
\ No newline at end of file
diff --git a/gamemaker/TheorafileGMS/objects/Renderer/Renderer.yy b/gamemaker/TheorafileGMS/objects/Renderer/Renderer.yy
new file mode 100644
index 0000000..af36d4d
--- /dev/null
+++ b/gamemaker/TheorafileGMS/objects/Renderer/Renderer.yy
@@ -0,0 +1,35 @@
+{
+ "spriteId": null,
+ "solid": false,
+ "visible": true,
+ "spriteMaskId": null,
+ "persistent": false,
+ "parentObjectId": null,
+ "physicsObject": false,
+ "physicsSensor": false,
+ "physicsShape": 1,
+ "physicsGroup": 1,
+ "physicsDensity": 0.5,
+ "physicsRestitution": 0.1,
+ "physicsLinearDamping": 0.1,
+ "physicsAngularDamping": 0.1,
+ "physicsFriction": 0.2,
+ "physicsStartAwake": true,
+ "physicsKinematic": false,
+ "physicsShapePoints": [],
+ "eventList": [
+ {"isDnD":false,"eventNum":0,"eventType":0,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",},
+ {"isDnD":false,"eventNum":0,"eventType":8,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",},
+ {"isDnD":false,"eventNum":0,"eventType":12,"collisionObjectId":null,"resourceVersion":"1.0","name":"","tags":[],"resourceType":"GMEvent",},
+ ],
+ "properties": [],
+ "overriddenProperties": [],
+ "parent": {
+ "name": "Objects",
+ "path": "folders/Objects.yy",
+ },
+ "resourceVersion": "1.0",
+ "name": "Renderer",
+ "tags": [],
+ "resourceType": "GMObject",
+}
\ No newline at end of file
diff --git a/gamemaker/TheorafileGMS/options/windows/options_windows.yy b/gamemaker/TheorafileGMS/options/windows/options_windows.yy
index 44cc31c..c3699e9 100644
--- a/gamemaker/TheorafileGMS/options/windows/options_windows.yy
+++ b/gamemaker/TheorafileGMS/options/windows/options_windows.yy
@@ -28,7 +28,7 @@
"option_windows_enable_steam": false,
"option_windows_disable_sandbox": false,
"option_windows_steam_use_alternative_launcher": false,
- "option_windows_use_x64": false,
+ "option_windows_use_x64": true,
"resourceVersion": "1.1",
"name": "Windows",
"tags": [],
diff --git a/gamemaker/TheorafileGMS/rooms/Room1/Room1.yy b/gamemaker/TheorafileGMS/rooms/Room1/Room1.yy
index f69dcfa..9f8825d 100644
--- a/gamemaker/TheorafileGMS/rooms/Room1/Room1.yy
+++ b/gamemaker/TheorafileGMS/rooms/Room1/Room1.yy
@@ -13,19 +13,23 @@
{"inherit":false,"visible":false,"xview":0,"yview":0,"wview":1366,"hview":768,"xport":0,"yport":0,"wport":1366,"hport":768,"hborder":32,"vborder":32,"hspeed":-1,"vspeed":-1,"objectId":null,},
],
"layers": [
- {"instances":[],"visible":true,"depth":0,"userdefinedDepth":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"resourceVersion":"1.0","name":"Instances","tags":[],"resourceType":"GMRInstanceLayer",},
+ {"instances":[
+ {"properties":[],"isDnd":false,"objectId":{"name":"Renderer","path":"objects/Renderer/Renderer.yy",},"inheritCode":false,"hasCreationCode":false,"colour":4294967295,"rotation":0.0,"scaleX":1.0,"scaleY":1.0,"imageIndex":0,"imageSpeed":1.0,"inheritedItemId":null,"frozen":false,"ignore":false,"inheritItemSettings":false,"x":0.0,"y":0.0,"resourceVersion":"1.0","name":"inst_4739AA0A","tags":[],"resourceType":"GMRInstance",},
+ ],"visible":true,"depth":0,"userdefinedDepth":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"resourceVersion":"1.0","name":"Instances","tags":[],"resourceType":"GMRInstanceLayer",},
{"spriteId":null,"colour":4278190080,"x":0,"y":0,"htiled":false,"vtiled":false,"hspeed":0.0,"vspeed":0.0,"stretch":false,"animationFPS":15.0,"animationSpeedType":0,"userdefinedAnimFPS":false,"visible":true,"depth":100,"userdefinedDepth":false,"inheritLayerDepth":false,"inheritLayerSettings":false,"gridX":32,"gridY":32,"layers":[],"hierarchyFrozen":false,"resourceVersion":"1.0","name":"Background","tags":[],"resourceType":"GMRBackgroundLayer",},
],
"inheritLayers": false,
"creationCodeFile": "",
"inheritCode": false,
- "instanceCreationOrder": [],
+ "instanceCreationOrder": [
+ {"name":"inst_4739AA0A","path":"rooms/Room1/Room1.yy",},
+ ],
"inheritCreationOrder": false,
"sequenceId": null,
"roomSettings": {
"inheritRoomSettings": false,
- "Width": 1366,
- "Height": 768,
+ "Width": 960,
+ "Height": 540,
"persistent": false,
},
"viewSettings": {
diff --git a/gamemaker/TheorafileGMS/scripts/TheorafileGMS_Scripts/TheorafileGMS_Scripts.gml b/gamemaker/TheorafileGMS/scripts/TheorafileGMS_Scripts/TheorafileGMS_Scripts.gml
index 2977657..247dd36 100644
--- a/gamemaker/TheorafileGMS/scripts/TheorafileGMS_Scripts/TheorafileGMS_Scripts.gml
+++ b/gamemaker/TheorafileGMS/scripts/TheorafileGMS_Scripts/TheorafileGMS_Scripts.gml
@@ -1,34 +1,161 @@
+enum Theorafile_VideoState
+{
+ Stopped,
+ Playing,
+ Paused
+}
+
function Theorafile_Open(filename)
{
- var address = TheorafileGMS_Open(filename);
- if (address == 0)
- {
- show_debug_message("Could not open theora video at filename: " + filename);
- return;
- }
+ var _handle = ptr(TheorafileGMS_Open(filename));
+ show_debug_message("handle: " + string(_handle));
- var _yWidth = TheorafileGMS_Width(filename);
- var _yHeight = TheorafileGMS_Height(filename);
- var _frames_per_second = TheorafileGMS_FPS(filename);
- var _uvWidth = TheorafileGMS_UVWidth(filename);
- var _uvHeight = TheorafileGMS_UVHeight(filename);
+ 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);
return {
- handle: ptr(address),
+ handle: _handle,
+ bufferSize: _bufferSize,
+ yuvBuffer: buffer_create(_bufferSize, buffer_fixed, 4),
yWidth: _yWidth,
yHeight: _yHeight,
uvWidth: _uvWidth,
- uvHeight: _uvHeight
+ 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,
+ looped: false,
+ triangle_buffer: _vbuff,
+ triangle_buffer_format: _vformat
};
}
-function Theorafile_Close(pointer)
+function Theorafile_Close(video)
{
- TheorafileGMS_Close(pointer)
+ buffer_delete(video.yuvBuffer);
+ vertex_format_delete(video.triangle_buffer_format);
+ vertex_delete_buffer(video.triangle_buffer);
+ TheorafileGMS_Close(video.handle);
}
-function Theorafile_Play(pointer)
+function Theorafile_Play(video)
{
-
+ if (video.state == Theorafile_VideoState.Stopped)
+ {
+ if (video.handle != 0 && TheorafileGMS_HasVideo(video.handle) == 1)
+ {
+ video.elapsed_time = 0;
+ video.state = Theorafile_VideoState.Playing;
+ TheorafileGMS_ReadVideo(video.handle, buffer_get_address(video.yuvBuffer), 1);
+ }
+ }
+}
+
+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 = video.elapsed_time * video.framesPerSecond;
+
+ if (floor(_current_frame) > video.currentFrame)
+ {
+ if TheorafileGMS_ReadVideo(video.handle, buffer_get_address(video.yuvBuffer), 1) == 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 = floor(_current_frame);
+ }
+
+ var _ended = TheorafileGMS_EndOfStream(video.handle);
+
+ if (_ended)
+ {
+ video.elapsed_time = 0;
+ video.most_recent_time = 0;
+
+ TheorafileGMS_Reset(video.handle);
+
+ if (video.looped)
+ {
+ video.most_recent_time = get_timer();
+ }
+ else
+ {
+ video.state = Theorafile_VideoState.Stopped;
+ }
+ }
+ }
}
diff --git a/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.fsh b/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.fsh
index 68412ff..8fa31f9 100644
--- a/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.fsh
+++ b/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.fsh
@@ -22,8 +22,8 @@ void main()
vec4 color;
color.x = dot(yuv, Rcoeff);
- color.y = dot(yuv, GCoeff);
- color.z = dot(yuv, BCoeff);
+ color.y = dot(yuv, Gcoeff);
+ color.z = dot(yuv, Bcoeff);
color.w = 1.0;
gl_FragColor = color;
diff --git a/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.vsh b/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.vsh
index 033b69e..26dd4c6 100644
--- a/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.vsh
+++ b/gamemaker/TheorafileGMS/shaders/YUVToRGB/YUVToRGB.vsh
@@ -1,4 +1,4 @@
-attribute vec3 in_Position; // (x,y,z)
+attribute vec2 in_Position; // (x,y,z)
attribute vec2 in_TextureCoord; // (u,v)
varying vec2 v_vTexcoord;
@@ -6,5 +6,5 @@ varying vec2 v_vTexcoord;
void main()
{
v_vTexcoord = in_TextureCoord;
- gl_Position = vec4(in_Position, 1.0);
+ gl_Position = vec4(in_Position, 0.0, 1.0);
}
diff --git a/src/TheorafileGMS.c b/src/TheorafileGMS.c
index 583e2a0..0d5c339 100644
--- a/src/TheorafileGMS.c
+++ b/src/TheorafileGMS.c
@@ -59,7 +59,10 @@ char* TheorafileGMS_Open(char* filename)
return NULL;
}
- return (char*)file;
+ static char retaddr[64];
+ SDL_memset(retaddr, 0, sizeof(retaddr));
+ SDL_snprintf(retaddr, sizeof(retaddr) - 1, "%p%p", (void*)((uintptr_t)file >> 32), file); /* cursed hack for exporting 64-bit pointer */
+ return retaddr;
}
void TheorafileGMS_Close(char* filePointer)
@@ -231,7 +234,6 @@ double TheorafileGMS_ReadVideo(char* filePointer, char* buffer, double numFrames
/* Game Maker doesnt have R8 textures so we have to do this padding bullshit */
char* yuvBuffer = SDL_malloc(requiredBufferSize * 4);
- SDL_memset(yuvBuffer, 0, requiredBufferSize * 4);
int updated = tf_readvideo(file, yuvBuffer, (int)numFrames);
diff --git a/visualc/TheorafileGMS.vcxproj b/visualc/TheorafileGMS.vcxproj
index a344b40..adbf1f5 100644
--- a/visualc/TheorafileGMS.vcxproj
+++ b/visualc/TheorafileGMS.vcxproj
@@ -72,7 +72,7 @@
DebugFull
NotSet
- SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;libucrt.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
+ libucrt.lib;SetupAPI.lib;Version.lib;Winmm.lib;Imm32.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)
false
@@ -85,6 +85,7 @@
false
true
MultiThreaded
+ ../lib/SDL/include;../lib/Theorafile;../lib/Theorafile/lib;$(OutDir)
true