From 7199b7b5dd1b324f6581c4a880951730daefbb60 Mon Sep 17 00:00:00 2001 From: Anish Date: Sun, 29 Jul 2018 01:31:30 +0530 Subject: Added interface for GDNative Videodecoder. Interface and callback api added for Videodecoder support. Should be able to construct any format videodecoder using only the given interface. GSoC 2018 project. --- modules/gdnative/SCsub | 1 + modules/gdnative/gdnative_api.json | 36 +++ modules/gdnative/gdnative_builders.py | 2 + .../include/videodecoder/godot_videodecoder.h | 75 +++++ modules/gdnative/register_types.cpp | 3 + modules/gdnative/videodecoder/SCsub | 12 + modules/gdnative/videodecoder/register_types.cpp | 45 +++ modules/gdnative/videodecoder/register_types.h | 32 ++ .../videodecoder/resource_importer_av_gdnative.cpp | 96 ++++++ .../videodecoder/resource_importer_av_gdnative.h | 58 ++++ .../videodecoder/video_stream_gdnative.cpp | 336 +++++++++++++++++++++ .../gdnative/videodecoder/video_stream_gdnative.h | 201 ++++++++++++ 12 files changed, 897 insertions(+) create mode 100644 modules/gdnative/include/videodecoder/godot_videodecoder.h create mode 100644 modules/gdnative/videodecoder/SCsub create mode 100644 modules/gdnative/videodecoder/register_types.cpp create mode 100644 modules/gdnative/videodecoder/register_types.h create mode 100644 modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp create mode 100644 modules/gdnative/videodecoder/resource_importer_av_gdnative.h create mode 100644 modules/gdnative/videodecoder/video_stream_gdnative.cpp create mode 100644 modules/gdnative/videodecoder/video_stream_gdnative.h diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index fe2d8c7ce9..235f0b97bb 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -19,6 +19,7 @@ Export('env_gdnative') SConscript("net/SCsub") SConscript("arvr/SCsub") SConscript("pluginscript/SCsub") +SConscript("videodecoder/SCsub") from platform_methods import run_in_subprocess diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index c5a1fa139e..20320e18b1 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -6374,6 +6374,42 @@ ] } ] + }, + { + "name": "videodecoder", + "type": "VIDEODECODER", + "version": { + "major": 0, + "minor": 1 + }, + "next": null, + "api": [ + { + "name": "godot_videodecoder_file_read", + "return_type": "godot_int", + "arguments": [ + ["void *", "file_ptr"], + ["uint8_t *", "buf"], + ["int", "buf_size"] + ] + }, + { + "name": "godot_videodecoder_file_seek", + "return_type": "int64_t", + "arguments": [ + [ "void *", "file_ptr"], + ["int64_t", "pos"], + ["int", "whence"] + ] + }, + { + "name": "godot_videodecoder_register_decoder", + "return_type": "void", + "arguments": [ + ["const godot_videodecoder_interface_gdnative *", "p_interface"] + ] + } + ] } ] } diff --git a/modules/gdnative/gdnative_builders.py b/modules/gdnative/gdnative_builders.py index ff18a3ae69..cd356ce513 100644 --- a/modules/gdnative/gdnative_builders.py +++ b/modules/gdnative/gdnative_builders.py @@ -46,6 +46,7 @@ def _build_gdnative_api_struct_header(api): '#include ', '#include ', '#include ', + '#include ', '', '#define GDNATIVE_API_INIT(options) do { \\\n' + ' \\\n'.join(gdnative_api_init_macro) + ' \\\n } while (0)', '', @@ -244,6 +245,7 @@ def _build_gdnative_wrapper_code(api): '#include ', '#include ', '#include ', + '#include ', '', '#include ', '', diff --git a/modules/gdnative/include/videodecoder/godot_videodecoder.h b/modules/gdnative/include/videodecoder/godot_videodecoder.h new file mode 100644 index 0000000000..360fc0f5f5 --- /dev/null +++ b/modules/gdnative/include/videodecoder/godot_videodecoder.h @@ -0,0 +1,75 @@ +/*************************************************************************/ +/* godot_videodecoder.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GODOT_NATIVEVIDEODECODER_H +#define GODOT_NATIVEVIDEODECODER_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define GODOTAV_API_MAJOR 0 +#define GODOTAV_API_MINOR 1 + +typedef struct +{ + godot_gdnative_api_version version; + void *next; + void *(*constructor)(godot_object *); + void (*destructor)(void *); + const char *(*get_plugin_name)(void); + const char **(*get_supported_extensions)(int *count); + godot_bool (*open_file)(void *, void *); // data struct, and a FileAccess pointer + godot_real (*get_length)(const void *); + godot_real (*get_playback_position)(const void *); + void (*seek)(void *, godot_real); + void (*set_audio_track)(void *, godot_int); + void (*update)(void *, godot_real); + godot_pool_byte_array *(*get_videoframe)(void *); + godot_int (*get_audioframe)(void *, float *, int); + godot_int (*get_channels)(const void *); + godot_int (*get_mix_rate)(const void *); + godot_vector2 (*get_texture_size)(const void *); +} godot_videodecoder_interface_gdnative; + +typedef int (*GDNativeAudioMixCallback)(void *, const float *, int); + +// FileAccess wrappers for custom FFmpeg IO +godot_int GDAPI godot_videodecoder_file_read(void *file_ptr, uint8_t *buf, int buf_size); +int64_t GDAPI godot_videodecoder_file_seek(void *file_ptr, int64_t pos, int whence); +void GDAPI godot_videodecoder_register_decoder(const godot_videodecoder_interface_gdnative *p_interface); + +#ifdef __cplusplus +} +#endif + +#endif /* GODOT_NATIVEVIDEODECODER_H */ diff --git a/modules/gdnative/register_types.cpp b/modules/gdnative/register_types.cpp index 62e87c3651..8ccab959f4 100644 --- a/modules/gdnative/register_types.cpp +++ b/modules/gdnative/register_types.cpp @@ -38,6 +38,7 @@ #include "nativescript/register_types.h" #include "net/register_types.h" #include "pluginscript/register_types.h" +#include "videodecoder/register_types.h" #include "core/engine.h" #include "core/io/resource_loader.h" @@ -326,6 +327,7 @@ void register_gdnative_types() { register_arvr_types(); register_nativescript_types(); register_pluginscript_types(); + register_videodecoder_types(); // run singletons @@ -378,6 +380,7 @@ void unregister_gdnative_types() { } singleton_gdnatives.clear(); + unregister_videodecoder_types(); unregister_pluginscript_types(); unregister_nativescript_types(); unregister_arvr_types(); diff --git a/modules/gdnative/videodecoder/SCsub b/modules/gdnative/videodecoder/SCsub new file mode 100644 index 0000000000..51b0418d6b --- /dev/null +++ b/modules/gdnative/videodecoder/SCsub @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +import os +import methods + +Import('env') +Import('env_modules') + +env_vsdecoder_gdnative = env_modules.Clone() + +env_vsdecoder_gdnative.Append(CPPPATH=['#modules/gdnative/include/']) +env_vsdecoder_gdnative.add_source_files(env.modules_sources, '*.cpp') diff --git a/modules/gdnative/videodecoder/register_types.cpp b/modules/gdnative/videodecoder/register_types.cpp new file mode 100644 index 0000000000..64599365e5 --- /dev/null +++ b/modules/gdnative/videodecoder/register_types.cpp @@ -0,0 +1,45 @@ +/*************************************************************************/ +/* register_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "class_db.h" +#include "resource_importer_av_gdnative.h" +#include "video_stream_gdnative.h" + +void register_videodecoder_types() { + +#ifdef TOOLS_ENABLED + Ref avgdn_import; + avgdn_import.instance(); + ResourceFormatImporter::get_singleton()->add_importer(avgdn_import); +#endif + ClassDB::register_class(); +} +void unregister_videodecoder_types() { +} diff --git a/modules/gdnative/videodecoder/register_types.h b/modules/gdnative/videodecoder/register_types.h new file mode 100644 index 0000000000..dd1943fc47 --- /dev/null +++ b/modules/gdnative/videodecoder/register_types.h @@ -0,0 +1,32 @@ +/*************************************************************************/ +/* register_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +void register_videodecoder_types(); +void unregister_videodecoder_types(); diff --git a/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp b/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp new file mode 100644 index 0000000000..ff9f6118fb --- /dev/null +++ b/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* resource_importer_av_gdnative.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "resource_importer_av_gdnative.h" + +#include "io/resource_saver.h" +#include "os/file_access.h" +#include "scene/resources/texture.h" + +String ResourceImporterAVGDNative::get_importer_name() const { + + return "AVGDNative"; +} + +String ResourceImporterAVGDNative::get_visible_name() const { + + return "AVGDNative"; +} +void ResourceImporterAVGDNative::get_recognized_extensions(List *p_extensions) const { + + Map::Element *el = VideoDecoderServer::get_instance()->get_extensions().front(); + while (el) { + p_extensions->push_back(el->key()); + el = el->next(); + } +} + +String ResourceImporterAVGDNative::get_save_extension() const { + + return "avgdnstr"; +} + +String ResourceImporterAVGDNative::get_resource_type() const { + + return "VideoStreamGDNative"; +} + +bool ResourceImporterAVGDNative::get_option_visibility(const String &p_option, const Map &p_options) const { + + return true; +} + +int ResourceImporterAVGDNative::get_preset_count() const { + + return 0; +} + +String ResourceImporterAVGDNative::get_preset_name(int p_idx) const { + + return String(); +} + +void ResourceImporterAVGDNative::get_import_options(List *r_options, int p_preset) const { + + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); +} + +Error ResourceImporterAVGDNative::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files) { + + VideoStreamGDNative *stream = memnew(VideoStreamGDNative); + stream->set_file(p_source_file); + + Ref avgdn_stream = Ref(stream); + + return ResourceSaver::save(p_save_path + ".avgdnstr", avgdn_stream); +} + +ResourceImporterAVGDNative::ResourceImporterAVGDNative() { +} diff --git a/modules/gdnative/videodecoder/resource_importer_av_gdnative.h b/modules/gdnative/videodecoder/resource_importer_av_gdnative.h new file mode 100644 index 0000000000..0ec96dc72c --- /dev/null +++ b/modules/gdnative/videodecoder/resource_importer_av_gdnative.h @@ -0,0 +1,58 @@ +/*************************************************************************/ +/* resource_importer_av_gdnative.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RESOURCE_IMPORTER_AV_GDNATIVE_H +#define RESOURCE_IMPORTER_AV_GDNATIVE_H + +#include "video_stream_gdnative.h" + +#include "core/io/resource_import.h" + +class ResourceImporterAVGDNative : public ResourceImporter { + GDCLASS(ResourceImporterAVGDNative, ResourceImporter) +public: + virtual String get_importer_name() const; + virtual String get_visible_name() const; + virtual void get_recognized_extensions(List *p_extensions) const; + virtual String get_save_extension() const; + virtual String get_resource_type() const; + + virtual int get_preset_count() const; + virtual String get_preset_name(int p_idx) const; + + virtual void get_import_options(List *r_options, int p_preset = 0) const; + virtual bool get_option_visibility(const String &p_option, const Map &p_options) const; + + virtual Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files = NULL); + + ResourceImporterAVGDNative(); +}; + +#endif diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp new file mode 100644 index 0000000000..a959a4c8ae --- /dev/null +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -0,0 +1,336 @@ +/*************************************************************************/ +/* video_stream_gdnative.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "video_stream_gdnative.h" +#include +#include + +VideoDecoderServer *VideoDecoderServer::instance = NULL; + +static VideoDecoderServer decoder_server; + +// NOTE: Callbacks for the GDNative libraries. +extern "C" { +godot_int GDAPI godot_videodecoder_file_read(void *ptr, uint8_t *buf, int buf_size) { + // ptr is a FileAccess + FileAccess *file = reinterpret_cast(ptr); + + // if file exists + if (file) { + long bytes_read = file->get_buffer(buf, buf_size); + // No bytes to read => EOF + if (bytes_read == 0) { + return 0; + } + return bytes_read; + } + return -1; +} + +int64_t GDAPI godot_videodecoder_file_seek(void *ptr, int64_t pos, int whence) { + // file + FileAccess *file = reinterpret_cast(ptr); + + size_t len = file->get_len(); + if (file) { + switch (whence) { + case SEEK_SET: { + // Just for explicitness + size_t new_pos = static_cast(pos); + if (new_pos > len) { + return -1; + } + file->seek(new_pos); + pos = static_cast(file->get_position()); + return pos; + } break; + case SEEK_CUR: { + // Just in case it doesn't exist + if (pos < 0 && -pos > file->get_position()) { + return -1; + } + pos = pos + static_cast(file->get_position()); + file->seek(pos); + pos = static_cast(file->get_position()); + return pos; + } break; + case SEEK_END: { + // Just in case something goes wrong + if (-pos > len) { + return -1; + } + file->seek_end(pos); + pos = static_cast(file->get_position()); + return pos; + } break; + default: { + // Only 4 possible options, hence default = AVSEEK_SIZE + // Asks to return the length of file + return static_cast(len); + } break; + } + } + // In case nothing works out. + return -1; +} + +void GDAPI godot_videodecoder_register_decoder(const godot_videodecoder_interface_gdnative *p_interface) { + + decoder_server.register_decoder_interface(p_interface); +} +} + +// VideoStreamPlaybackGDNative starts here. + +bool VideoStreamPlaybackGDNative::open_file(const String &p_file) { + ERR_FAIL_COND_V(interface == NULL, false); + file = FileAccess::open(p_file, FileAccess::READ); + bool file_opened = interface->open_file(data_struct, file); + + num_channels = interface->get_channels(data_struct); + mix_rate = interface->get_mix_rate(data_struct); + + godot_vector2 vec = interface->get_texture_size(data_struct); + texture_size = *(Vector2 *)&vec; + + pcm = (float *)memalloc(num_channels * AUX_BUFFER_SIZE * sizeof(float)); + memset(pcm, 0, num_channels * AUX_BUFFER_SIZE * sizeof(float)); + pcm_write_idx = -1; + samples_decoded = 0; + + texture->create((int)texture_size.width, (int)texture_size.height, Image::FORMAT_RGBA8, Texture::FLAG_FILTER | Texture::FLAG_VIDEO_SURFACE); + + return file_opened; +} + +void VideoStreamPlaybackGDNative::update(float p_delta) { + if (!playing || paused) { + return; + } + if (!file) { + return; + } + time += p_delta; + ERR_FAIL_COND(interface == NULL); + interface->update(data_struct, p_delta); + + if (pcm_write_idx >= 0) { + // Previous remains + int mixed = mix_callback(mix_udata, pcm, samples_decoded); + if (mixed == samples_decoded) { + pcm_write_idx = -1; + } else { + samples_decoded -= mixed; + pcm_write_idx += mixed; + } + } + if (pcm_write_idx < 0) { + samples_decoded = interface->get_audioframe(data_struct, pcm, AUX_BUFFER_SIZE); + pcm_write_idx = mix_callback(mix_udata, pcm, samples_decoded); + if (pcm_write_idx == samples_decoded) { + pcm_write_idx = -1; + } else { + samples_decoded -= pcm_write_idx; + } + } + + while (interface->get_playback_position(data_struct) < time) { + + update_texture(); + } +} + +void VideoStreamPlaybackGDNative::update_texture() { + PoolByteArray *pba = (PoolByteArray *)interface->get_videoframe(data_struct); + + if (pba == NULL) { + playing = false; + return; + } + + Ref img = memnew(Image(texture_size.width, texture_size.height, 0, Image::FORMAT_RGBA8, *pba)); + + texture->set_data(img); +} + +// ctor and dtor + +VideoStreamPlaybackGDNative::VideoStreamPlaybackGDNative() : + texture(Ref(memnew(ImageTexture))), + time(0), + mix_udata(NULL), + mix_callback(NULL), + num_channels(-1), + mix_rate(0), + playing(false) {} + +VideoStreamPlaybackGDNative::~VideoStreamPlaybackGDNative() { + cleanup(); +} + +void VideoStreamPlaybackGDNative::cleanup() { + if (data_struct) + interface->destructor(data_struct); + memfree(pcm); + pcm = NULL; + time = 0; + num_channels = -1; + interface = NULL; + data_struct = NULL; +} + +void VideoStreamPlaybackGDNative::set_interface(const godot_videodecoder_interface_gdnative *p_interface) { + ERR_FAIL_COND(p_interface == NULL); + if (interface != NULL) { + cleanup(); + } + interface = p_interface; + data_struct = interface->constructor((godot_object *)this); +} + +// controls + +bool VideoStreamPlaybackGDNative::is_playing() const { + return playing; +} + +bool VideoStreamPlaybackGDNative::is_paused() const { + return paused; +} + +void VideoStreamPlaybackGDNative::play() { + + stop(); + + playing = true; + + delay_compensation = ProjectSettings::get_singleton()->get("audio/video_delay_compensation_ms"); + delay_compensation /= 1000.0; +} + +void VideoStreamPlaybackGDNative::stop() { + if (playing) { + seek(0); + } + playing = false; +} + +void VideoStreamPlaybackGDNative::seek(float p_time) { + ERR_FAIL_COND(interface == NULL); + interface->seek(data_struct, p_time); +} + +void VideoStreamPlaybackGDNative::set_paused(bool p_paused) { + paused = p_paused; +} + +Ref VideoStreamPlaybackGDNative::get_texture() { + return texture; +} + +float VideoStreamPlaybackGDNative::get_length() const { + ERR_FAIL_COND_V(interface == NULL, 0); + return interface->get_length(data_struct); +} + +float VideoStreamPlaybackGDNative::get_playback_position() const { + + ERR_FAIL_COND_V(interface == NULL, 0); + return interface->get_playback_position(data_struct); +} + +bool VideoStreamPlaybackGDNative::has_loop() const { + // TODO: Implement looping? + return false; +} + +void VideoStreamPlaybackGDNative::set_loop(bool p_enable) { + // Do nothing +} + +void VideoStreamPlaybackGDNative::set_audio_track(int p_idx) { + ERR_FAIL_COND(interface == NULL); + interface->set_audio_track(data_struct, p_idx); +} + +void VideoStreamPlaybackGDNative::set_mix_callback(AudioMixCallback p_callback, void *p_userdata) { + + mix_udata = p_userdata; + mix_callback = p_callback; +} + +int VideoStreamPlaybackGDNative::get_channels() const { + ERR_FAIL_COND_V(interface == NULL, 0); + + return (num_channels > 0) ? num_channels : 0; +} + +int VideoStreamPlaybackGDNative::get_mix_rate() const { + ERR_FAIL_COND_V(interface == NULL, 0); + + return mix_rate; +} + +/* --- NOTE VideoStreamGDNative starts here. ----- */ + +Ref VideoStreamGDNative::instance_playback() { + Ref pb = memnew(VideoStreamPlaybackGDNative); + VideoDecoderGDNative *decoder = decoder_server.get_decoder(file.get_extension().to_lower()); + if (decoder == NULL) + return NULL; + pb->set_interface(decoder->interface); + pb->set_audio_track(audio_track); + if (pb->open_file(file)) + return pb; + return NULL; +} + +void VideoStreamGDNative::set_file(const String &p_file) { + + file = p_file; +} + +String VideoStreamGDNative::get_file() { + + return file; +} + +void VideoStreamGDNative::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_file", "file"), &VideoStreamGDNative::set_file); + ClassDB::bind_method(D_METHOD("get_file"), &VideoStreamGDNative::get_file); + + ADD_PROPERTY(PropertyInfo(Variant::STRING, "file", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "set_file", "get_file"); +} + +void VideoStreamGDNative::set_audio_track(int p_track) { + + audio_track = p_track; +} diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h new file mode 100644 index 0000000000..d203a5d04f --- /dev/null +++ b/modules/gdnative/videodecoder/video_stream_gdnative.h @@ -0,0 +1,201 @@ +/*************************************************************************/ +/* video_stream_gdnative.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VIDEO_STREAM_GDNATIVE_H +#define VIDEO_STREAM_GDNATIVE_H + +#include +#include +#include +#include + +struct VideoDecoderGDNative { + String plugin_name; + Vector supported_extensions; + const godot_videodecoder_interface_gdnative *interface; + + VideoDecoderGDNative() : + interface(NULL), + plugin_name("none") {} + + VideoDecoderGDNative(const godot_videodecoder_interface_gdnative *p_interface) : + interface(p_interface), + plugin_name(p_interface->get_plugin_name()) { + _get_supported_extensions(); + } + +private: + void _get_supported_extensions() { + supported_extensions.clear(); + int num_ext; + const char **supported_ext = interface->get_supported_extensions(&num_ext); + for (int i = 0; i < num_ext; i++) { + supported_extensions.push_back(supported_ext[i]); + } + } +}; + +class VideoDecoderServer { +private: + Vector decoders; + Map extensions; + + static VideoDecoderServer *instance; + +public: + static VideoDecoderServer *get_instance() { + return instance; + } + + const Map &get_extensions() { + return extensions; + } + + void register_decoder_interface(const godot_videodecoder_interface_gdnative *p_interface) { + VideoDecoderGDNative *decoder = memnew(VideoDecoderGDNative(p_interface)); + int index = decoders.size(); + for (int i = 0; i < decoder->supported_extensions.size(); i++) { + extensions[decoder->supported_extensions[i]] = index; + } + decoders.push_back(decoder); + } + + VideoDecoderGDNative *get_decoder(const String &extension) { + if (extensions.size() == 0 || !extensions.has(extension)) + return NULL; + return decoders[extensions[extension]]; + } + + VideoDecoderServer() { + instance = this; + } + + ~VideoDecoderServer() { + for (int i = 0; i < decoders.size(); i++) { + memdelete(decoders[i]); + } + decoders.clear(); + instance = NULL; + } +}; + +class VideoStreamPlaybackGDNative : public VideoStreamPlayback { + + GDCLASS(VideoStreamPlaybackGDNative, VideoStreamPlayback); + + Ref texture; + bool playing; + bool paused; + + Vector2 texture_size; + + void *mix_udata; + AudioMixCallback mix_callback; + + int num_channels; + float time; + int mix_rate; + double delay_compensation; + + const int AUX_BUFFER_SIZE = 1024; // Buffer 1024 samples. + float *pcm; + int pcm_write_idx; + int samples_decoded; + + void cleanup(); + void update_texture(); + +protected: + String file_name; + + FileAccess *file = NULL; + + const godot_videodecoder_interface_gdnative *interface = NULL; + void *data_struct = NULL; + +public: + VideoStreamPlaybackGDNative(); + ~VideoStreamPlaybackGDNative(); + + void set_interface(const godot_videodecoder_interface_gdnative *p_interface); + + bool open_file(const String &p_file); + + virtual void stop(); + virtual void play(); + + virtual bool is_playing() const; + + virtual void set_paused(bool p_paused); + virtual bool is_paused() const; + + virtual void set_loop(bool p_enable); + virtual bool has_loop() const; + + virtual float get_length() const; + + virtual float get_playback_position() const; + virtual void seek(float p_time); + + virtual void set_audio_track(int p_idx); + + //virtual int mix(int16_t* p_buffer,int p_frames)=0; + + virtual Ref get_texture(); + virtual void update(float p_delta); + + virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata); + virtual int get_channels() const; + virtual int get_mix_rate() const; +}; + +class VideoStreamGDNative : public VideoStream { + + GDCLASS(VideoStreamGDNative, VideoStream); + RES_BASE_EXTENSION("avgdnstr"); + + String file; + int audio_track; + +protected: + static void + _bind_methods(); + +public: + void set_file(const String &p_file); + String get_file(); + + virtual void set_audio_track(int p_track); + virtual Ref instance_playback(); + + VideoStreamGDNative() {} +}; + +#endif -- cgit v1.2.3 From 012dac9aadbfd69fa2b6233496e9383e27f0e8e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Wed, 12 Dec 2018 15:21:44 +0100 Subject: Fix includes and initialization for GDNative Videodecoder Fixes warnings and a crash when running the destructor with an uninitialized pcm pointer. --- modules/gdnative/videodecoder/SCsub | 3 --- modules/gdnative/videodecoder/register_types.cpp | 5 ++++- .../videodecoder/resource_importer_av_gdnative.cpp | 4 ++-- .../videodecoder/resource_importer_av_gdnative.h | 3 +-- .../videodecoder/video_stream_gdnative.cpp | 22 +++++++++++++++++----- .../gdnative/videodecoder/video_stream_gdnative.h | 17 ++++++++--------- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/modules/gdnative/videodecoder/SCsub b/modules/gdnative/videodecoder/SCsub index 51b0418d6b..8d9c1ff50e 100644 --- a/modules/gdnative/videodecoder/SCsub +++ b/modules/gdnative/videodecoder/SCsub @@ -1,8 +1,5 @@ #!/usr/bin/env python -import os -import methods - Import('env') Import('env_modules') diff --git a/modules/gdnative/videodecoder/register_types.cpp b/modules/gdnative/videodecoder/register_types.cpp index 64599365e5..70eea2e036 100644 --- a/modules/gdnative/videodecoder/register_types.cpp +++ b/modules/gdnative/videodecoder/register_types.cpp @@ -28,7 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "class_db.h" +#include "register_types.h" + +#include "core/class_db.h" #include "resource_importer_av_gdnative.h" #include "video_stream_gdnative.h" @@ -41,5 +43,6 @@ void register_videodecoder_types() { #endif ClassDB::register_class(); } + void unregister_videodecoder_types() { } diff --git a/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp b/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp index ff9f6118fb..7fe8cc89d1 100644 --- a/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp +++ b/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp @@ -30,8 +30,8 @@ #include "resource_importer_av_gdnative.h" -#include "io/resource_saver.h" -#include "os/file_access.h" +#include "core/io/resource_saver.h" +#include "core/os/file_access.h" #include "scene/resources/texture.h" String ResourceImporterAVGDNative::get_importer_name() const { diff --git a/modules/gdnative/videodecoder/resource_importer_av_gdnative.h b/modules/gdnative/videodecoder/resource_importer_av_gdnative.h index 0ec96dc72c..9760ebbe64 100644 --- a/modules/gdnative/videodecoder/resource_importer_av_gdnative.h +++ b/modules/gdnative/videodecoder/resource_importer_av_gdnative.h @@ -31,9 +31,8 @@ #ifndef RESOURCE_IMPORTER_AV_GDNATIVE_H #define RESOURCE_IMPORTER_AV_GDNATIVE_H -#include "video_stream_gdnative.h" - #include "core/io/resource_import.h" +#include "video_stream_gdnative.h" class ResourceImporterAVGDNative : public ResourceImporter { GDCLASS(ResourceImporterAVGDNative, ResourceImporter) diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index a959a4c8ae..ea847f9804 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -29,13 +29,16 @@ /*************************************************************************/ #include "video_stream_gdnative.h" -#include -#include + +#include "core/project_settings.h" +#include "servers/audio_server.h" VideoDecoderServer *VideoDecoderServer::instance = NULL; static VideoDecoderServer decoder_server; +const int AUX_BUFFER_SIZE = 1024; // Buffer 1024 samples. + // NOTE: Callbacks for the GDNative libraries. extern "C" { godot_int GDAPI godot_videodecoder_file_read(void *ptr, uint8_t *buf, int buf_size) { @@ -184,12 +187,20 @@ void VideoStreamPlaybackGDNative::update_texture() { VideoStreamPlaybackGDNative::VideoStreamPlaybackGDNative() : texture(Ref(memnew(ImageTexture))), - time(0), + playing(false), + paused(false), mix_udata(NULL), mix_callback(NULL), num_channels(-1), + time(0), mix_rate(0), - playing(false) {} + delay_compensation(0), + pcm(NULL), + pcm_write_idx(0), + samples_decoded(0), + file(NULL), + interface(NULL), + data_struct(NULL) {} VideoStreamPlaybackGDNative::~VideoStreamPlaybackGDNative() { cleanup(); @@ -198,7 +209,8 @@ VideoStreamPlaybackGDNative::~VideoStreamPlaybackGDNative() { void VideoStreamPlaybackGDNative::cleanup() { if (data_struct) interface->destructor(data_struct); - memfree(pcm); + if (pcm) + memfree(pcm); pcm = NULL; time = 0; num_channels = -1; diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h index d203a5d04f..87ba9c8cc4 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.h +++ b/modules/gdnative/videodecoder/video_stream_gdnative.h @@ -31,15 +31,15 @@ #ifndef VIDEO_STREAM_GDNATIVE_H #define VIDEO_STREAM_GDNATIVE_H -#include -#include -#include -#include +#include "../gdnative.h" +#include "core/os/file_access.h" +#include "scene/resources/texture.h" +#include "scene/resources/video_stream.h" struct VideoDecoderGDNative { + const godot_videodecoder_interface_gdnative *interface; String plugin_name; Vector supported_extensions; - const godot_videodecoder_interface_gdnative *interface; VideoDecoderGDNative() : interface(NULL), @@ -124,7 +124,6 @@ class VideoStreamPlaybackGDNative : public VideoStreamPlayback { int mix_rate; double delay_compensation; - const int AUX_BUFFER_SIZE = 1024; // Buffer 1024 samples. float *pcm; int pcm_write_idx; int samples_decoded; @@ -135,10 +134,10 @@ class VideoStreamPlaybackGDNative : public VideoStreamPlayback { protected: String file_name; - FileAccess *file = NULL; + FileAccess *file; - const godot_videodecoder_interface_gdnative *interface = NULL; - void *data_struct = NULL; + const godot_videodecoder_interface_gdnative *interface; + void *data_struct; public: VideoStreamPlaybackGDNative(); -- cgit v1.2.3 From 72feccf2057e99d9235efb52cbb9bc4ccc0f0e36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Wed, 12 Dec 2018 15:47:57 +0100 Subject: Adapt GDNative VideoStream to use ResourceFormatLoader Same logic as used for Webm and Theora support in #19937 and #21084, fixing issues when exporting projects. --- modules/gdnative/videodecoder/register_types.cpp | 14 ++-- .../videodecoder/resource_importer_av_gdnative.cpp | 96 ---------------------- .../videodecoder/resource_importer_av_gdnative.h | 57 ------------- .../videodecoder/video_stream_gdnative.cpp | 39 +++++++++ .../gdnative/videodecoder/video_stream_gdnative.h | 9 +- 5 files changed, 55 insertions(+), 160 deletions(-) delete mode 100644 modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp delete mode 100644 modules/gdnative/videodecoder/resource_importer_av_gdnative.h diff --git a/modules/gdnative/videodecoder/register_types.cpp b/modules/gdnative/videodecoder/register_types.cpp index 70eea2e036..f2c4ab6d3b 100644 --- a/modules/gdnative/videodecoder/register_types.cpp +++ b/modules/gdnative/videodecoder/register_types.cpp @@ -31,18 +31,20 @@ #include "register_types.h" #include "core/class_db.h" -#include "resource_importer_av_gdnative.h" #include "video_stream_gdnative.h" +static ResourceFormatLoaderVideoStreamGDNative *resource_loader_vsgdnative = NULL; + void register_videodecoder_types() { -#ifdef TOOLS_ENABLED - Ref avgdn_import; - avgdn_import.instance(); - ResourceFormatImporter::get_singleton()->add_importer(avgdn_import); -#endif + resource_loader_vsgdnative = memnew(ResourceFormatLoaderVideoStreamGDNative); + ResourceLoader::add_resource_format_loader(resource_loader_vsgdnative, true); ClassDB::register_class(); } void unregister_videodecoder_types() { + + if (resource_loader_vsgdnative) { + memdelete(resource_loader_vsgdnative); + } } diff --git a/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp b/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp deleted file mode 100644 index 7fe8cc89d1..0000000000 --- a/modules/gdnative/videodecoder/resource_importer_av_gdnative.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/*************************************************************************/ -/* resource_importer_av_gdnative.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "resource_importer_av_gdnative.h" - -#include "core/io/resource_saver.h" -#include "core/os/file_access.h" -#include "scene/resources/texture.h" - -String ResourceImporterAVGDNative::get_importer_name() const { - - return "AVGDNative"; -} - -String ResourceImporterAVGDNative::get_visible_name() const { - - return "AVGDNative"; -} -void ResourceImporterAVGDNative::get_recognized_extensions(List *p_extensions) const { - - Map::Element *el = VideoDecoderServer::get_instance()->get_extensions().front(); - while (el) { - p_extensions->push_back(el->key()); - el = el->next(); - } -} - -String ResourceImporterAVGDNative::get_save_extension() const { - - return "avgdnstr"; -} - -String ResourceImporterAVGDNative::get_resource_type() const { - - return "VideoStreamGDNative"; -} - -bool ResourceImporterAVGDNative::get_option_visibility(const String &p_option, const Map &p_options) const { - - return true; -} - -int ResourceImporterAVGDNative::get_preset_count() const { - - return 0; -} - -String ResourceImporterAVGDNative::get_preset_name(int p_idx) const { - - return String(); -} - -void ResourceImporterAVGDNative::get_import_options(List *r_options, int p_preset) const { - - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "loop"), true)); -} - -Error ResourceImporterAVGDNative::import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files) { - - VideoStreamGDNative *stream = memnew(VideoStreamGDNative); - stream->set_file(p_source_file); - - Ref avgdn_stream = Ref(stream); - - return ResourceSaver::save(p_save_path + ".avgdnstr", avgdn_stream); -} - -ResourceImporterAVGDNative::ResourceImporterAVGDNative() { -} diff --git a/modules/gdnative/videodecoder/resource_importer_av_gdnative.h b/modules/gdnative/videodecoder/resource_importer_av_gdnative.h deleted file mode 100644 index 9760ebbe64..0000000000 --- a/modules/gdnative/videodecoder/resource_importer_av_gdnative.h +++ /dev/null @@ -1,57 +0,0 @@ -/*************************************************************************/ -/* resource_importer_av_gdnative.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md) */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RESOURCE_IMPORTER_AV_GDNATIVE_H -#define RESOURCE_IMPORTER_AV_GDNATIVE_H - -#include "core/io/resource_import.h" -#include "video_stream_gdnative.h" - -class ResourceImporterAVGDNative : public ResourceImporter { - GDCLASS(ResourceImporterAVGDNative, ResourceImporter) -public: - virtual String get_importer_name() const; - virtual String get_visible_name() const; - virtual void get_recognized_extensions(List *p_extensions) const; - virtual String get_save_extension() const; - virtual String get_resource_type() const; - - virtual int get_preset_count() const; - virtual String get_preset_name(int p_idx) const; - - virtual void get_import_options(List *r_options, int p_preset = 0) const; - virtual bool get_option_visibility(const String &p_option, const Map &p_options) const; - - virtual Error import(const String &p_source_file, const String &p_save_path, const Map &p_options, List *r_platform_variants, List *r_gen_files = NULL); - - ResourceImporterAVGDNative(); -}; - -#endif diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.cpp b/modules/gdnative/videodecoder/video_stream_gdnative.cpp index ea847f9804..8239d57a77 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.cpp +++ b/modules/gdnative/videodecoder/video_stream_gdnative.cpp @@ -346,3 +346,42 @@ void VideoStreamGDNative::set_audio_track(int p_track) { audio_track = p_track; } + +/* --- NOTE ResourceFormatLoaderVideoStreamGDNative starts here. ----- */ + +RES ResourceFormatLoaderVideoStreamGDNative::load(const String &p_path, const String &p_original_path, Error *r_error) { + FileAccess *f = FileAccess::open(p_path, FileAccess::READ); + if (!f) { + if (r_error) { + *r_error = ERR_CANT_OPEN; + } + memdelete(f); + return RES(); + } + VideoStreamGDNative *stream = memnew(VideoStreamGDNative); + stream->set_file(p_path); + Ref ogv_stream = Ref(stream); + if (r_error) { + *r_error = OK; + } + return ogv_stream; +} + +void ResourceFormatLoaderVideoStreamGDNative::get_recognized_extensions(List *p_extensions) const { + Map::Element *el = VideoDecoderServer::get_instance()->get_extensions().front(); + while (el) { + p_extensions->push_back(el->key()); + el = el->next(); + } +} + +bool ResourceFormatLoaderVideoStreamGDNative::handles_type(const String &p_type) const { + return ClassDB::is_parent_class(p_type, "VideoStream"); +} + +String ResourceFormatLoaderVideoStreamGDNative::get_resource_type(const String &p_path) const { + String el = p_path.get_extension().to_lower(); + if (VideoDecoderServer::get_instance()->get_extensions().has(el)) + return "VideoStreamGDNative"; + return ""; +} diff --git a/modules/gdnative/videodecoder/video_stream_gdnative.h b/modules/gdnative/videodecoder/video_stream_gdnative.h index 87ba9c8cc4..7712928b33 100644 --- a/modules/gdnative/videodecoder/video_stream_gdnative.h +++ b/modules/gdnative/videodecoder/video_stream_gdnative.h @@ -178,7 +178,6 @@ public: class VideoStreamGDNative : public VideoStream { GDCLASS(VideoStreamGDNative, VideoStream); - RES_BASE_EXTENSION("avgdnstr"); String file; int audio_track; @@ -197,4 +196,12 @@ public: VideoStreamGDNative() {} }; +class ResourceFormatLoaderVideoStreamGDNative : public ResourceFormatLoader { +public: + virtual RES load(const String &p_path, const String &p_original_path = "", Error *r_error = NULL); + virtual void get_recognized_extensions(List *p_extensions) const; + virtual bool handles_type(const String &p_type) const; + virtual String get_resource_type(const String &p_path) const; +}; + #endif -- cgit v1.2.3