123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350 |
- // quantumde1 developed software, licensed under MIT license.
- module graphics.playback;
- import std.stdio;
- import raylib;
- import raylib.rlgl;
- import core.stdc.stdlib;
- import core.stdc.string;
- import core.thread;
- import variables;
- import core.sync.mutex;
- import std.array;
- import std.file;
- import system.abstraction;
- extern (C)
- {
- struct libvlc_instance_t;
- struct libvlc_media_t;
- struct libvlc_media_player_t;
- struct libvlc_event_manager_t;
- struct libvlc_event_t;
- long libvlc_media_player_get_length(libvlc_media_player_t* player);
- long libvlc_media_player_get_time(libvlc_media_player_t* player);
- void libvlc_media_player_set_time(libvlc_media_player_t* player, long time);
- libvlc_instance_t* libvlc_new(int argc, const(char)** argv);
- void libvlc_release(libvlc_instance_t* instance);
- libvlc_media_t* libvlc_media_new_location(libvlc_instance_t* instance, const(char)* mrl);
- void libvlc_media_release(libvlc_media_t* media);
- libvlc_media_player_t* libvlc_media_player_new_from_media(libvlc_media_t* media);
- void libvlc_media_player_release(libvlc_media_player_t* player);
- void libvlc_media_player_play(libvlc_media_player_t* player);
- void libvlc_media_player_stop(libvlc_media_player_t* player);
- int libvlc_media_player_get_state(libvlc_media_player_t* player);
- void libvlc_video_set_callbacks(libvlc_media_player_t* player,
- void* function(void*, void**),
- void function(void*, void*, void*),
- void* function(void*),
- void* opaque);
- void libvlc_video_set_format(libvlc_media_player_t* player,
- const(char)* chroma,
- uint width,
- uint height,
- uint pitch);
- void libvlc_video_get_size(libvlc_media_player_t* player,
- uint num,
- uint* px,
- uint* py);
- libvlc_event_manager_t* libvlc_media_player_event_manager(libvlc_media_player_t* player);
- void libvlc_event_attach(libvlc_event_manager_t* event_manager,
- int event_type,
- void function(const(libvlc_event_t)*, void*),
- void* user_data);
- int libvlc_event_detach(libvlc_event_manager_t* event_manager,
- int event_type,
- void function(const(libvlc_event_t)*, void*),
- void* user_data);
- }
- enum libvlc_state_t
- {
- libvlc_NothingSpecial = 0,
- libvlc_Opening,
- libvlc_Buffering,
- libvlc_Playing,
- libvlc_Paused,
- libvlc_Stopped,
- libvlc_Ended,
- libvlc_Error
- }
- enum libvlc_event_type_t
- {
- libvlc_MediaPlayerEndReached = 256
- }
- extern (C) void endReachedCallback(const(libvlc_event_t)* event, void* user_data)
- {
- auto callback = cast(void function(void*)) user_data;
- callback(user_data);
- }
- extern (C) void libvlc_media_player_set_media_player_end_reached_callback(
- libvlc_media_player_t* player,
- void function(void*), void* user_data)
- {
- auto event_manager = libvlc_media_player_event_manager(player);
- libvlc_event_attach(event_manager, libvlc_event_type_t.libvlc_MediaPlayerEndReached, &endReachedCallback,
- cast(void*) user_data);
- }
- struct Video
- {
- uint texW, texH;
- float scale;
- Mutex mutex;
- Texture2D texture;
- ubyte* buffer;
- bool needUpdate;
- libvlc_media_player_t* player;
- }
- extern (C) void* begin_vlc_rendering(void* data, void** p_pixels)
- {
- auto video = cast(Video*) data;
- video.mutex.lock();
- *p_pixels = video.buffer;
- return null;
- }
- extern (C) void end_vlc_rendering(void* data, void* id, void* p_pixels)
- {
- auto video = cast(Video*) data;
- video.needUpdate = true;
- video.mutex.unlock();
- }
- extern (C) void videoEndCallback(void* data)
- {
- videoFinished = true;
- debug debugWriteln("Video ended");
- }
- Video* add_new_video(libvlc_instance_t* libvlc, const(char)* src, const(char)* protocol)
- {
- auto video = cast(Video*) malloc(Video.sizeof);
- if (video is null)
- {
- debug debugWriteln("Failed to allocate memory for video.");
- return null;
- }
- video.mutex = new Mutex;
- auto location = cast(char*) malloc(strlen(protocol) + strlen(src) + 3);
- if (location is null)
- {
- debug debugWriteln("Failed to allocate memory for location.");
- free(video);
- return null;
- }
- sprintf(location, "%s://%s", protocol, src);
- auto media = libvlc_media_new_location(libvlc, location);
- free(location);
- if (media is null)
- {
- debug debugWriteln("Failed to create media.");
- free(video);
- return null;
- }
- video.player = libvlc_media_player_new_from_media(media);
- libvlc_media_release(media);
- if (video.player is null)
- {
- debug debugWriteln("Failed to create media player.");
- free(video);
- return null;
- }
- video.needUpdate = false;
- video.texW = 0;
- video.texH = 0;
- video.buffer = null;
- video.texture.id = 0;
- libvlc_video_set_callbacks(video.player, &begin_vlc_rendering, &end_vlc_rendering, null, video);
- libvlc_media_player_set_media_player_end_reached_callback(video.player, &videoEndCallback, video);
- return video;
- }
- void cleanup_video(Video* video)
- {
- if (video is null)
- return;
- libvlc_media_player_stop(video.player);
- libvlc_media_player_release(video.player);
- if (video.texture.id != 0)
- {
- UnloadTexture(video.texture);
- }
- video.mutex.destroy();
- if (video.buffer !is null)
- {
- MemFree(video.buffer);
- }
- free(video);
- }
- extern (C) int playVideoInternal(char* argv)
- {
- const(char)*[] vlcArgs;
- debug
- {
- vlcArgs = [
- "--verbose=2", "--no-xlib", "--drop-late-frames", "--live-caching=0",
- "--no-lua"
- ];
- }
- else
- {
- vlcArgs = [
- "--verbose=-1", "--no-xlib", "--drop-late-frames", "--live-caching=0",
- "--no-lua"
- ];
- }
- auto libvlc = libvlc_new(cast(int) vlcArgs.length, cast(const(char)**) vlcArgs.ptr);
- if (libvlc is null)
- {
- debug debugWriteln("Something went wrong with libvlc init. Turn on DEBUG in conf/build_type.conf at BUILD_TYPE field to get more logs.");
- videoFinished = true;
- return 0;
- }
- Video*[] video_list;
- auto new_video = add_new_video(libvlc, argv, "file");
- if (new_video is null)
- {
- libvlc_release(libvlc);
- return 0;
- }
- video_list ~= new_video;
- libvlc_media_player_play(new_video.player);
- debug debugWriteln("Video started playing");
- while (!WindowShouldClose())
- {
- auto player = new_video.player;
- if (libvlc_media_player_get_state(player) == libvlc_state_t.libvlc_Ended)
- {
- debug debugWriteln("Video reached end.");
- videoFinished = true;
- }
- if (videoFinished)
- {
- break;
- }
- BeginDrawing();
- ClearBackground(Colors.BLACK);
- UpdateMusicStream(music);
- foreach (video; video_list)
- {
- if (video.buffer is null)
- {
- if (libvlc_media_player_get_state(video.player) == libvlc_state_t.libvlc_Playing)
- {
- libvlc_video_get_size(video.player, 0, &video.texW, &video.texH);
- if (video.texW > 0 && video.texH > 0)
- {
- float screenWidth = cast(float) GetScreenWidth();
- float screenHeight = cast(float) GetScreenHeight();
- float videoAspectRatio = cast(float) video.texW / cast(float) video.texH;
- float screenAspectRatio = screenWidth / screenHeight;
- // Calculate scale based on aspect ratio
- video.scale = (videoAspectRatio < screenAspectRatio) ?
- (screenHeight / cast(float) video.texH) : (
- screenWidth / cast(float) video.texW);
- // Set video format only once
- if (video.texture.id == 0)
- {
- libvlc_video_set_format(video.player, "RV24", video.texW, video.texH, video.texW * 3);
- video.mutex.lock();
- // Load the texture and assign the ID to the texture struct
- video.texture.id = rlLoadTexture(null, video.texW, video.texH, PixelFormat
- .PIXELFORMAT_UNCOMPRESSED_R8G8B8, 1);
- video.texture.width = video.texW;
- video.texture.height = video.texH;
- video.texture.format = PixelFormat.PIXELFORMAT_UNCOMPRESSED_R8G8B8;
- video.texture.mipmaps = 1;
- // Allocate buffer for video frame
- video.buffer = cast(ubyte*) MemAlloc(video.texW * video.texH * 3);
- video.needUpdate = false;
- video.mutex.unlock();
- debug debugWriteln("Video texture initialized");
- }
- }
- }
- }
- else
- {
- if (video.needUpdate)
- {
- video.mutex.lock();
- UpdateTexture(video.texture, video.buffer);
- video.needUpdate = false;
- video.mutex.unlock();
- }
- Vector2 position = {
- (GetScreenWidth() - video.texW * video.scale) * 0.5f, (
- GetScreenHeight() - video.texH * video.scale) * 0.5f
- };
- SetTextureFilter(video.texture, TextureFilter.TEXTURE_FILTER_BILINEAR);
- DrawTextureEx(video.texture, position, 0, video.scale, Colors.WHITE);
- }
- }
-
- if (IsKeyPressed(KeyboardKey.KEY_ENTER))
- {
- foreach (video; video_list)
- {
- cleanup_video(video);
- }
- videoFinished = true;
- video_list.length = 0;
- EndDrawing();
- libvlc_release(libvlc);
- return 0;
- }
- EndDrawing();
- }
- foreach (video; video_list)
- {
- cleanup_video(video);
- }
- videoFinished = true;
- video_list.length = 0;
- libvlc_release(libvlc);
- return 0;
- }
- void playVideo(string filename) {
- version (Posix)
- playVideoInternal(cast(char*)(getcwd() ~ "/" ~ filename));
- version (Windows)
- playVideoInternal(cast(char*)("/" ~ getcwd() ~ "/" ~ filename));
- }
|