Compare commits
4 Commits
52662e129b
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97ff779911 | ||
|
|
dacbb2e043 | ||
|
|
27693a8fbf | ||
|
|
427c64ef5d |
44
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
44
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@@ -1,44 +0,0 @@
|
|||||||
name: Bug report
|
|
||||||
description: Report a bug with the godot-cpp template
|
|
||||||
body:
|
|
||||||
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
- Write a descriptive issue title above.
|
|
||||||
- Search [open](https://github.com/godotengine/godot-cpp-template/issues) and [closed](https://github.com/godotengine/godot-cpp-template/issues?q=is%3Aissue+is%3Aclosed) issues to ensure it has not already been reported.
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: Godot version
|
|
||||||
description: >
|
|
||||||
Specify the Git commit hash of your Godot build.
|
|
||||||
placeholder: v4.0.stable.official [92bee43ad]
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: godot-cpp version
|
|
||||||
description: >
|
|
||||||
Specify the Git commit hash of the godot-cpp submodule in your project. You can run `git status` inside the folder to check it.
|
|
||||||
placeholder: v4.0.stable.official [9d1c396c5]
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
attributes:
|
|
||||||
label: System information
|
|
||||||
description: |
|
|
||||||
Specify the OS version.
|
|
||||||
placeholder: Windows 10
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
attributes:
|
|
||||||
label: Issue description
|
|
||||||
description: |
|
|
||||||
Describe your issue briefly. What doesn't work, and how do you expect it to work instead?
|
|
||||||
You can include images or videos with drag and drop, and format code blocks or logs with <code>```</code> tags.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
14
.github/ISSUE_TEMPLATE/config.yml
vendored
14
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,14 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
|
|
||||||
contact_links:
|
|
||||||
- name: Godot proposals
|
|
||||||
url: https://github.com/godotengine/godot-proposals
|
|
||||||
about: Please submit feature proposals on the Godot proposals repository, not here.
|
|
||||||
|
|
||||||
- name: Godot documentation repository
|
|
||||||
url: https://github.com/godotengine/godot-docs
|
|
||||||
about: Please report issues with documentation on the Godot documentation repository, not here.
|
|
||||||
|
|
||||||
- name: Godot community channels
|
|
||||||
url: https://godotengine.org/community
|
|
||||||
about: Please ask for technical support on one of the other community channels, not here.
|
|
||||||
88
.github/workflows/ci.yml
vendored
88
.github/workflows/ci.yml
vendored
@@ -1,88 +0,0 @@
|
|||||||
# For syntax, see https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
|
|
||||||
# This workflow is automatically triggered for every push and pull request, to verify that everything still builds.
|
|
||||||
|
|
||||||
name: Continuous Integration
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
merge_group:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# Test a few selected combinations of parameters ("test case matrix").
|
|
||||||
# While it would be nice to test all needed combinations, in practice this would a waste of CI usage time.
|
|
||||||
# By building just with a few combinations, we only need a few runners,
|
|
||||||
# while still achieving adequate coverage.
|
|
||||||
# To make a full build with all combinations, use the make_build.yml workflow instead.
|
|
||||||
include:
|
|
||||||
- target: { platform: linux, arch: x86_64, os: ubuntu-22.04 }
|
|
||||||
target-type: template_debug
|
|
||||||
float-precision: double
|
|
||||||
- target: { platform: windows, arch: x86_64, os: windows-latest }
|
|
||||||
target-type: template_release
|
|
||||||
float-precision: single
|
|
||||||
- target: { platform: macos, arch: universal, os: macos-latest }
|
|
||||||
target-type: template_debug
|
|
||||||
float-precision: single
|
|
||||||
- target: { platform: android, arch: arm64, os: ubuntu-22.04 }
|
|
||||||
target-type: template_debug
|
|
||||||
float-precision: single
|
|
||||||
- target: { platform: web, arch: wasm32, os: ubuntu-22.04 }
|
|
||||||
target-type: template_release
|
|
||||||
float-precision: double
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.target.os }}
|
|
||||||
steps:
|
|
||||||
# Clone this repository
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
# Lint
|
|
||||||
#- name: Setup clang-format
|
|
||||||
# shell: bash
|
|
||||||
# run: |
|
|
||||||
# python -m pip install clang-format
|
|
||||||
#- name: Run clang-format
|
|
||||||
# shell: bash
|
|
||||||
# run: |
|
|
||||||
# clang-format src/** --dry-run --Werror
|
|
||||||
|
|
||||||
# Add linux x86_32 toolchain
|
|
||||||
- name: Install multilib support
|
|
||||||
if: ${{ matrix.target.platform == 'linux' && matrix.target.arch == 'x86_32' }}
|
|
||||||
run: |
|
|
||||||
sudo apt-get update && sudo apt-get install -y gcc-multilib g++-multilib
|
|
||||||
|
|
||||||
# Setup dependencies
|
|
||||||
- name: Setup godot-cpp
|
|
||||||
uses: ./godot-cpp/.github/actions/setup-godot-cpp
|
|
||||||
with:
|
|
||||||
platform: ${{ matrix.target.platform }}
|
|
||||||
em-version: 3.1.62
|
|
||||||
|
|
||||||
# Build GDExtension (with caches)
|
|
||||||
|
|
||||||
- name: Restore .scons_cache
|
|
||||||
uses: ./godot-cpp/.github/actions/godot-cache-restore
|
|
||||||
with:
|
|
||||||
scons-cache: ${{ github.workspace }}/.scons-cache/
|
|
||||||
cache-name: ${{ matrix.target.platform }}_${{ matrix.target.arch }}_${{ matrix.float-precision }}_${{ matrix.target-type }}
|
|
||||||
|
|
||||||
- name: Build GDExtension Debug Build
|
|
||||||
shell: sh
|
|
||||||
env:
|
|
||||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
|
||||||
run: |
|
|
||||||
scons target=${{ matrix.target-type }} platform=${{ matrix.target.platform }} arch=${{ matrix.target.arch }} precision=${{ matrix.float-precision }}
|
|
||||||
|
|
||||||
- name: Save .scons_cache
|
|
||||||
uses: ./godot-cpp/.github/actions/godot-cache-save
|
|
||||||
with:
|
|
||||||
scons-cache: ${{ github.workspace }}/.scons-cache/
|
|
||||||
cache-name: ${{ matrix.target.platform }}_${{ matrix.target.arch }}_${{ matrix.float-precision }}_${{ matrix.target-type }}
|
|
||||||
104
.github/workflows/make_build.yml
vendored
104
.github/workflows/make_build.yml
vendored
@@ -1,104 +0,0 @@
|
|||||||
# For syntax, see https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax
|
|
||||||
# This workflow is triggered manually on the "Actions" tab on GitHub, and can be used to create releases.
|
|
||||||
|
|
||||||
name: Make a GDExtension build for all supported platforms
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
# A build is made for every possible combination of parameters
|
|
||||||
# You can add or remove entries from the arrays of each parameter to customize which builds you want to run.
|
|
||||||
# See https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow
|
|
||||||
target:
|
|
||||||
[
|
|
||||||
{ platform: linux, arch: x86_64, os: ubuntu-22.04 },
|
|
||||||
{ platform: linux, arch: x86_32, os: ubuntu-22.04 },
|
|
||||||
{ platform: linux, arch: arm64, os: ubuntu-22.04-arm },
|
|
||||||
{ platform: linux, arch: arm32, os: ubuntu-22.04-arm },
|
|
||||||
{ platform: windows, arch: x86_64, os: windows-latest },
|
|
||||||
{ platform: windows, arch: x86_32, os: windows-latest },
|
|
||||||
{ platform: windows, arch: arm64, os: windows-latest },
|
|
||||||
{ platform: macos, arch: universal, os: macos-latest },
|
|
||||||
{ platform: android, arch: x86_64, os: ubuntu-22.04 },
|
|
||||||
{ platform: android, arch: x86_32, os: ubuntu-22.04 },
|
|
||||||
{ platform: android, arch: arm64, os: ubuntu-22.04 },
|
|
||||||
{ platform: android, arch: arm32, os: ubuntu-22.04 },
|
|
||||||
{ platform: ios, arch: arm64, os: macos-latest },
|
|
||||||
{ platform: web, arch: wasm32, os: ubuntu-22.04 },
|
|
||||||
]
|
|
||||||
target-type: [template_debug, template_release]
|
|
||||||
float-precision: [single]
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.target.os }}
|
|
||||||
steps:
|
|
||||||
# Clone this repository
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
|
|
||||||
# Add linux x86_32 toolchain
|
|
||||||
- name: Install multilib support
|
|
||||||
if: ${{ matrix.target.platform == 'linux' && matrix.target.arch == 'x86_32' }}
|
|
||||||
run: |
|
|
||||||
sudo apt-get update && sudo apt-get install -y gcc-multilib g++-multilib
|
|
||||||
|
|
||||||
# Setup dependencies
|
|
||||||
- name: Setup godot-cpp
|
|
||||||
uses: ./godot-cpp/.github/actions/setup-godot-cpp
|
|
||||||
with:
|
|
||||||
platform: ${{ matrix.target.platform }}
|
|
||||||
em-version: 3.1.62
|
|
||||||
|
|
||||||
# Build GDExtension (with caches)
|
|
||||||
|
|
||||||
- name: Restore .scons_cache
|
|
||||||
uses: ./godot-cpp/.github/actions/godot-cache-restore
|
|
||||||
with:
|
|
||||||
scons-cache: ${{ github.workspace }}/.scons-cache/
|
|
||||||
cache-name: ${{ matrix.target.platform }}_${{ matrix.target.arch }}_${{ matrix.float-precision }}_${{ matrix.target-type }}
|
|
||||||
|
|
||||||
- name: Build GDExtension Debug Build
|
|
||||||
shell: sh
|
|
||||||
env:
|
|
||||||
SCONS_CACHE: ${{ github.workspace }}/.scons-cache/
|
|
||||||
run: |
|
|
||||||
scons target=${{ matrix.target-type }} platform=${{ matrix.target.platform }} arch=${{ matrix.target.arch }} precision=${{ matrix.float-precision }}
|
|
||||||
|
|
||||||
- name: Save .scons_cache
|
|
||||||
uses: ./godot-cpp/.github/actions/godot-cache-save
|
|
||||||
with:
|
|
||||||
scons-cache: ${{ github.workspace }}/.scons-cache/
|
|
||||||
cache-name: ${{ matrix.target.platform }}_${{ matrix.target.arch }}_${{ matrix.float-precision }}_${{ matrix.target-type }}
|
|
||||||
|
|
||||||
# Clean up compilation files
|
|
||||||
- name: Windows - Delete compilation files
|
|
||||||
if: ${{ matrix.target.platform == 'windows' }}
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
Remove-Item bin/* -Include *.exp,*.lib,*.pdb -Force
|
|
||||||
|
|
||||||
# Upload the build
|
|
||||||
- name: Upload Artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: godot-cpp-template-${{ matrix.target.platform }}-${{ matrix.target.arch }}-${{ matrix.float-precision }}-${{ matrix.target-type }}
|
|
||||||
path: |
|
|
||||||
${{ github.workspace }}/bin/**
|
|
||||||
|
|
||||||
# Merges all the build artifacts together into a single godot-cpp-template artifact.
|
|
||||||
# If you comment out this step, all the builds will be uploaded individually.
|
|
||||||
merge:
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
needs: build
|
|
||||||
steps:
|
|
||||||
- name: Merge Artifacts
|
|
||||||
uses: actions/upload-artifact/merge@v4
|
|
||||||
with:
|
|
||||||
name: godot-cpp-template
|
|
||||||
pattern: godot-cpp-template-*
|
|
||||||
delete-merged: true
|
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -53,3 +53,5 @@ CMakeUserPresets.json
|
|||||||
|
|
||||||
# stupid godot developers using SCons
|
# stupid godot developers using SCons
|
||||||
build/
|
build/
|
||||||
|
|
||||||
|
godot/
|
||||||
|
|||||||
@@ -49,14 +49,31 @@ project(gdvapi
|
|||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
)
|
)
|
||||||
|
|
||||||
|
find_package(Vulkan REQUIRED)
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
|
pkg_check_modules(AVFORMAT REQUIRED IMPORTED_TARGET libavformat)
|
||||||
|
pkg_check_modules(AVCODEC REQUIRED IMPORTED_TARGET libavcodec)
|
||||||
|
pkg_check_modules(SWSCALE REQUIRED IMPORTED_TARGET libswscale)
|
||||||
|
pkg_check_modules(AVUTIL REQUIRED IMPORTED_TARGET libavutil)
|
||||||
|
|
||||||
add_library(${LIBNAME} SHARED)
|
add_library(${LIBNAME} SHARED)
|
||||||
|
|
||||||
|
target_link_libraries(${LIBNAME} PRIVATE
|
||||||
|
Vulkan::Headers
|
||||||
|
PkgConfig::AVFORMAT
|
||||||
|
PkgConfig::AVCODEC
|
||||||
|
PkgConfig::SWSCALE
|
||||||
|
PkgConfig::AVUTIL
|
||||||
|
)
|
||||||
|
|
||||||
target_sources(${LIBNAME}
|
target_sources(${LIBNAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
src/register_types.cpp
|
src/register_types.cpp
|
||||||
src/register_types.h
|
src/register_types.h
|
||||||
src/example_class.cpp
|
src/gdvapivideostream_class.cpp
|
||||||
src/example_class.h
|
src/gdvapivideostream_class.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Fetch a list of the xml files to use for documentation and add to our target
|
# Fetch a list of the xml files to use for documentation and add to our target
|
||||||
|
|||||||
12
flake.nix
12
flake.nix
@@ -13,6 +13,18 @@
|
|||||||
clang
|
clang
|
||||||
python3
|
python3
|
||||||
godot
|
godot
|
||||||
|
pkg-config
|
||||||
|
|
||||||
|
gst_all_1.gstreamer
|
||||||
|
gst_all_1.gst-plugins-base
|
||||||
|
gst_all_1.gst-plugins-good
|
||||||
|
gst_all_1.gst-plugins-bad
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
vulkan-loader
|
||||||
|
vulkan-headers
|
||||||
|
ffmpeg
|
||||||
];
|
];
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
|
|||||||
BIN
project/badapple.mov
Normal file
BIN
project/badapple.mov
Normal file
Binary file not shown.
@@ -1,57 +0,0 @@
|
|||||||
[configuration]
|
|
||||||
|
|
||||||
entry_symbol = "example_library_init"
|
|
||||||
compatibility_minimum = "4.1"
|
|
||||||
reloadable = false
|
|
||||||
|
|
||||||
[libraries]
|
|
||||||
; Relative paths ensure that our GDExtension can be placed anywhere in the project directory.
|
|
||||||
macos.single.debug = "./macos/libEXTENSION-NAME.macos.template_debug.dylib"
|
|
||||||
macos.double.debug = "./macos/libEXTENSION-NAME.macos.template_debug.double.dylib"
|
|
||||||
macos.single.release = "./macos/libEXTENSION-NAME.macos.template_release.dylib"
|
|
||||||
macos.double.release = "./macos/libEXTENSION-NAME.macos.template_release.double.dylib"
|
|
||||||
|
|
||||||
ios.arm64.single.debug = "./ios/libEXTENSION-NAME.ios.template_debug.arm64.dylib"
|
|
||||||
ios.arm64.double.debug = "./ios/libEXTENSION-NAME.ios.template_debug.arm64.double.dylib"
|
|
||||||
ios.arm64.single.release = "./ios/libEXTENSION-NAME.ios.template_release.arm64.dylib"
|
|
||||||
ios.arm64.double.release = "./ios/libEXTENSION-NAME.ios.template_release.arm64.double.dylib"
|
|
||||||
|
|
||||||
windows.x86_32.single.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_32.dll"
|
|
||||||
windows.x86_32.double.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_32.double.dll"
|
|
||||||
windows.x86_32.single.release = "./windows/EXTENSION-NAME.windows.template_release.x86_32.dll"
|
|
||||||
windows.x86_32.double.release = "./windows/EXTENSION-NAME.windows.template_release.x86_32.double.dll"
|
|
||||||
|
|
||||||
windows.x86_64.single.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_64.dll"
|
|
||||||
windows.x86_64.double.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_64.double.dll"
|
|
||||||
windows.x86_64.single.release = "./windows/EXTENSION-NAME.windows.template_release.x86_64.dll"
|
|
||||||
windows.x86_64.double.release = "./windows/EXTENSION-NAME.windows.template_release.x86_64.double.dll"
|
|
||||||
|
|
||||||
linux.x86_64.single.debug = "./linux/libEXTENSION-NAME.linux.template_debug.x86_64.so"
|
|
||||||
linux.x86_64.double.debug = "./linux/libEXTENSION-NAME.linux.template_debug.x86_64.double.so"
|
|
||||||
linux.x86_64.single.release = "./linux/libEXTENSION-NAME.linux.template_release.x86_64.so"
|
|
||||||
linux.x86_64.double.release = "./linux/libEXTENSION-NAME.linux.template_release.x86_64.double.so"
|
|
||||||
|
|
||||||
linux.arm64.single.debug = "./linux/libEXTENSION-NAME.linux.template_debug.arm64.so"
|
|
||||||
linux.arm64.double.debug = "./linux/libEXTENSION-NAME.linux.template_debug.arm64.double.so"
|
|
||||||
linux.arm64.single.release = "./linux/libEXTENSION-NAME.linux.template_release.arm64.so"
|
|
||||||
linux.arm64.double.release = "./linux/libEXTENSION-NAME.linux.template_release.arm64.double.so"
|
|
||||||
|
|
||||||
linux.rv64.single.debug = "./linux/libEXTENSION-NAME.linux.template_debug.rv64.so"
|
|
||||||
linux.rv64.double.debug = "./linux/libEXTENSION-NAME.linux.template_debug.rv64.double.so"
|
|
||||||
linux.rv64.single.release = "./linux/libEXTENSION-NAME.linux.template_release.rv64.so"
|
|
||||||
linux.rv64.double.release = "./linux/libEXTENSION-NAME.linux.template_release.rv64.double.so"
|
|
||||||
|
|
||||||
android.x86_64.single.debug = "./android/libEXTENSION-NAME.android.template_debug.x86_64.so"
|
|
||||||
android.x86_64.double.debug = "./android/libEXTENSION-NAME.android.template_debug.x86_64.double.so"
|
|
||||||
android.x86_64.single.release = "./android/libEXTENSION-NAME.android.template_release.x86_64.so"
|
|
||||||
android.x86_64.double.release = "./android/libEXTENSION-NAME.android.template_release.x86_64.double.so"
|
|
||||||
|
|
||||||
android.arm64.single.debug = "./android/libEXTENSION-NAME.android.template_debug.arm64.so"
|
|
||||||
android.arm64.double.debug = "./android/libEXTENSION-NAME.android.template_debug.arm64.double.so"
|
|
||||||
android.arm64.single.release = "./android/libEXTENSION-NAME.android.template_release.arm64.so"
|
|
||||||
android.arm64.double.release = "./android/libEXTENSION-NAME.android.template_release.arm64.double.so"
|
|
||||||
|
|
||||||
web.wasm32.single.debug = "./web/libEXTENSION-NAME.web.template_debug.wasm32.nothreads.wasm"
|
|
||||||
web.wasm32.double.debug = "./web/libEXTENSION-NAME.web.template_debug.wasm32.double.nothreads.wasm"
|
|
||||||
web.wasm32.single.release = "./web/libEXTENSION-NAME.web.template_release.wasm32.nothreads.wasm"
|
|
||||||
web.wasm32.double.release = "./web/libEXTENSION-NAME.web.template_release.wasm32.double.nothreads.wasm"
|
|
||||||
7
project/bin/gdvapi.gdextension
Normal file
7
project/bin/gdvapi.gdextension
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[configuration]
|
||||||
|
entry_symbol = "gdvapi_library_init"
|
||||||
|
compatibility_minimum = "4.7"
|
||||||
|
|
||||||
|
[libraries]
|
||||||
|
linux.editor.x86_64 = "res://bin/linux/gdvapi.linux.editor.x86_64.so"
|
||||||
|
linux.template_debug.x86_64 = "res://bin/linux/gdvapi.linux.template_debug.x86_64.so"
|
||||||
1
project/bin/gdvapi.gdextension.uid
Normal file
1
project/bin/gdvapi.gdextension.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://vgmwthvwcljf
|
||||||
@@ -2,5 +2,5 @@ extends Node
|
|||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
var example := ExampleClass.new()
|
#$GDVAPIVideoStream.begin("udp://0.0.0.0:5000")
|
||||||
example.print_type(example)
|
pass
|
||||||
|
|||||||
1
project/example.gd.uid
Normal file
1
project/example.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bkwk40ybs8kgm
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
[gd_scene load_steps=2 format=3 uid="uid://dh0oj81pufivs"]
|
[gd_scene format=3 uid="uid://dh0oj81pufivs"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://example.gd" id="1_jdh55"]
|
[ext_resource type="Script" uid="uid://bkwk40ybs8kgm" path="res://example.gd" id="1_jdh55"]
|
||||||
|
|
||||||
[node name="Node" type="Node"]
|
[node name="Node" type="Node" unique_id=2080300232]
|
||||||
script = ExtResource("1_jdh55")
|
script = ExtResource("1_jdh55")
|
||||||
|
|
||||||
|
[node name="GDVAPIVideoStream" type="GDVAPIVideoStream" parent="." unique_id=1053894928]
|
||||||
|
offset_right = 40.0
|
||||||
|
offset_bottom = 40.0
|
||||||
|
|||||||
49
project/export_presets.cfg
Normal file
49
project/export_presets.cfg
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
[runnable_presets]
|
||||||
|
|
||||||
|
Linux="Linux"
|
||||||
|
|
||||||
|
[preset.0]
|
||||||
|
|
||||||
|
name="Linux"
|
||||||
|
platform="Linux"
|
||||||
|
dedicated_server=false
|
||||||
|
custom_features=""
|
||||||
|
export_filter="all_resources"
|
||||||
|
include_filter=""
|
||||||
|
exclude_filter=""
|
||||||
|
export_path="exports/godot cpp template.x86_64"
|
||||||
|
patches=PackedStringArray()
|
||||||
|
patch_delta_encoding=false
|
||||||
|
patch_delta_compression_level_zstd=19
|
||||||
|
patch_delta_min_reduction=0.1
|
||||||
|
patch_delta_include_filters="*"
|
||||||
|
patch_delta_exclude_filters=""
|
||||||
|
encryption_include_filters=""
|
||||||
|
encryption_exclude_filters=""
|
||||||
|
seed=0
|
||||||
|
encrypt_pck=false
|
||||||
|
encrypt_directory=false
|
||||||
|
script_export_mode=2
|
||||||
|
|
||||||
|
[preset.0.options]
|
||||||
|
|
||||||
|
custom_template/debug=""
|
||||||
|
custom_template/release=""
|
||||||
|
debug/export_console_wrapper=1
|
||||||
|
binary_format/embed_pck=false
|
||||||
|
texture_format/s3tc_bptc=true
|
||||||
|
texture_format/etc2_astc=false
|
||||||
|
shader_baker/enabled=false
|
||||||
|
binary_format/architecture="x86_64"
|
||||||
|
ssh_remote_deploy/enabled=false
|
||||||
|
ssh_remote_deploy/host="user@host_ip"
|
||||||
|
ssh_remote_deploy/port="22"
|
||||||
|
ssh_remote_deploy/extra_args_ssh=""
|
||||||
|
ssh_remote_deploy/extra_args_scp=""
|
||||||
|
ssh_remote_deploy/run_script="#!/usr/bin/env bash
|
||||||
|
export DISPLAY=:0
|
||||||
|
unzip -o -q \"{temp_dir}/{archive_name}\" -d \"{temp_dir}\"
|
||||||
|
\"{temp_dir}/{exe_name}\" {cmd_args}"
|
||||||
|
ssh_remote_deploy/cleanup_script="#!/usr/bin/env bash
|
||||||
|
pkill -x -f \"{temp_dir}/{exe_name} {cmd_args}\"
|
||||||
|
rm -rf \"{temp_dir}\""
|
||||||
BIN
project/exports/badapple.mov
Normal file
BIN
project/exports/badapple.mov
Normal file
Binary file not shown.
BIN
project/exports/godot cpp template.pck
Normal file
BIN
project/exports/godot cpp template.pck
Normal file
Binary file not shown.
4
project/exports/godot cpp template.sh
Executable file
4
project/exports/godot cpp template.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
printf '\033c\033]0;%s\a' godot cpp template
|
||||||
|
base_path="$(dirname "$(realpath "$0")")"
|
||||||
|
"$base_path/godot cpp template.x86_64" "$@"
|
||||||
BIN
project/exports/godot cpp template.x86_64
Executable file
BIN
project/exports/godot cpp template.x86_64
Executable file
Binary file not shown.
@@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.cte
|
|||||||
compress/mode=0
|
compress/mode=0
|
||||||
compress/high_quality=false
|
compress/high_quality=false
|
||||||
compress/lossy_quality=0.7
|
compress/lossy_quality=0.7
|
||||||
|
compress/uastc_level=0
|
||||||
|
compress/rdo_quality_loss=0.0
|
||||||
compress/hdr_compression=1
|
compress/hdr_compression=1
|
||||||
compress/normal_map=0
|
compress/normal_map=0
|
||||||
compress/channel_pack=0
|
compress/channel_pack=0
|
||||||
@@ -25,6 +27,10 @@ mipmaps/generate=false
|
|||||||
mipmaps/limit=-1
|
mipmaps/limit=-1
|
||||||
roughness/mode=0
|
roughness/mode=0
|
||||||
roughness/src_normal=""
|
roughness/src_normal=""
|
||||||
|
process/channel_remap/red=0
|
||||||
|
process/channel_remap/green=1
|
||||||
|
process/channel_remap/blue=2
|
||||||
|
process/channel_remap/alpha=3
|
||||||
process/fix_alpha_border=true
|
process/fix_alpha_border=true
|
||||||
process/premult_alpha=false
|
process/premult_alpha=false
|
||||||
process/normal_map_invert_y=false
|
process/normal_map_invert_y=false
|
||||||
|
|||||||
@@ -8,8 +8,18 @@
|
|||||||
|
|
||||||
config_version=5
|
config_version=5
|
||||||
|
|
||||||
|
[animation]
|
||||||
|
|
||||||
|
compatibility/default_parent_skeleton_in_mesh_instance_3d=true
|
||||||
|
|
||||||
[application]
|
[application]
|
||||||
|
|
||||||
config/name="godot cpp template"
|
config/name="godot cpp template"
|
||||||
config/features=PackedStringArray("4.1", "Forward Plus")
|
run/main_scene="uid://dh0oj81pufivs"
|
||||||
|
config/features=PackedStringArray("4.7", "Forward Plus")
|
||||||
config/icon="res://icon.svg"
|
config/icon="res://icon.svg"
|
||||||
|
|
||||||
|
[display]
|
||||||
|
|
||||||
|
window/size/viewport_width=1920
|
||||||
|
window/size/viewport_height=1080
|
||||||
|
|||||||
BIN
project/test.mp4
Normal file
BIN
project/test.mp4
Normal file
Binary file not shown.
2
server-ffmpeg.sh
Executable file
2
server-ffmpeg.sh
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
ffmpeg -re -i $1 -c copy -f mpegts udp://127.0.0.1:5000
|
||||||
5
server-gst.sh
Normal file
5
server-gst.sh
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
gst-launch-1.0 filesrc location=$1 ! qtdemux name=demux \
|
||||||
|
demux.video_0 ! queue ! h264parse ! mpegtsmux name=mux ! udpsink host=127.0.0.1 port=5000 \
|
||||||
|
demux.audio_0 ! queue ! aacparse ! mux.
|
||||||
5
server_camera.sh
Executable file
5
server_camera.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
ffmpeg -f v4l2 -input_format mjpeg -video_size 1920x1080 -framerate 30 -i "$1" \
|
||||||
|
-c:v libx264 -preset ultrafast -tune zerolatency -g 30 -flags +global_header \
|
||||||
|
-f mpegts udp://127.0.0.1:5000?pkt_size=1316
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
#include "example_class.h"
|
|
||||||
|
|
||||||
void ExampleClass::_bind_methods() {
|
|
||||||
godot::ClassDB::bind_method(D_METHOD("print_type", "variant"), &ExampleClass::print_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExampleClass::print_type(const Variant &p_variant) const {
|
|
||||||
print_line(vformat("Type: %d", p_variant.get_type()));
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "godot_cpp/classes/ref_counted.hpp"
|
|
||||||
#include "godot_cpp/classes/wrapped.hpp"
|
|
||||||
#include "godot_cpp/variant/variant.hpp"
|
|
||||||
|
|
||||||
using namespace godot;
|
|
||||||
|
|
||||||
class ExampleClass : public RefCounted {
|
|
||||||
GDCLASS(ExampleClass, RefCounted)
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
|
||||||
ExampleClass() = default;
|
|
||||||
~ExampleClass() override = default;
|
|
||||||
|
|
||||||
void print_type(const Variant &p_variant) const;
|
|
||||||
};
|
|
||||||
324
src/gdvapivideostream_class.cpp
Normal file
324
src/gdvapivideostream_class.cpp
Normal file
@@ -0,0 +1,324 @@
|
|||||||
|
#include "gdvapivideostream_class.h"
|
||||||
|
#include "godot_cpp/classes/project_settings.hpp"
|
||||||
|
#include "godot_cpp/classes/rd_texture_format.hpp"
|
||||||
|
#include "godot_cpp/classes/rd_texture_view.hpp"
|
||||||
|
#include "godot_cpp/classes/rendering_device.hpp"
|
||||||
|
#include "godot_cpp/classes/rendering_server.hpp"
|
||||||
|
#include "godot_cpp/variant/utility_functions.hpp"
|
||||||
|
#include "godot_cpp/variant/color.hpp"
|
||||||
|
#include "godot_cpp/variant/rect2.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/hwcontext.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
using namespace godot;
|
||||||
|
|
||||||
|
enum HWMode { HW_NONE,
|
||||||
|
HW_VULKAN,
|
||||||
|
HW_VAAPI };
|
||||||
|
static HWMode active_hw_mode = HW_NONE;
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::_bind_methods() {
|
||||||
|
godot::ClassDB::bind_method(D_METHOD("begin", "source"), &GDVAPIVideoStream::begin);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("get_desired_width"), &GDVAPIVideoStream::get_desired_width);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_desired_width", "v"), &GDVAPIVideoStream::set_desired_width);
|
||||||
|
|
||||||
|
ClassDB::bind_method(D_METHOD("get_desired_height"), &GDVAPIVideoStream::get_desired_height);
|
||||||
|
ClassDB::bind_method(D_METHOD("set_desired_height", "v"), &GDVAPIVideoStream::set_desired_height);
|
||||||
|
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "desired_width"), "set_desired_width", "get_desired_width");
|
||||||
|
ADD_PROPERTY(PropertyInfo(Variant::INT, "desired_height"), "set_desired_height", "get_desired_height");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *formats) {
|
||||||
|
for (const enum AVPixelFormat *p = formats; *p != -1; p++) {
|
||||||
|
if (active_hw_mode == HW_VULKAN && *p == AV_PIX_FMT_VULKAN) {
|
||||||
|
return AV_PIX_FMT_VULKAN;
|
||||||
|
}
|
||||||
|
if (active_hw_mode == HW_VAAPI && *p == AV_PIX_FMT_VAAPI) {
|
||||||
|
return AV_PIX_FMT_VAAPI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UtilityFunctions::printerr("[gdvapi] hardware decoding unavailable");
|
||||||
|
active_hw_mode = HW_NONE;
|
||||||
|
return AV_PIX_FMT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::begin(const Variant &source) {
|
||||||
|
String res_path = source;
|
||||||
|
String global_path = ProjectSettings::get_singleton()->globalize_path(res_path);
|
||||||
|
CharString path_utf8 = global_path.utf8();
|
||||||
|
|
||||||
|
fmt_ctx = nullptr;
|
||||||
|
if (avformat_open_input(&fmt_ctx, path_utf8.get_data(), nullptr, nullptr) < 0) {
|
||||||
|
UtilityFunctions::printerr("[gdvapi] failed to open input stream");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
video_stream_idx = -1;
|
||||||
|
for (unsigned int i = 0; i < fmt_ctx->nb_streams; i++) {
|
||||||
|
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||||
|
video_stream_idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (video_stream_idx == -1) return;
|
||||||
|
|
||||||
|
AVStream *stream = fmt_ctx->streams[video_stream_idx];
|
||||||
|
if (stream->avg_frame_rate.den > 0 && stream->avg_frame_rate.num > 0) {
|
||||||
|
double fps = av_q2d(stream->avg_frame_rate);
|
||||||
|
frame_delay = 1.0 / fps;
|
||||||
|
UtilityFunctions::print("[gdvapi] fps: ", fps, " frame delay: ", frame_delay, "s");
|
||||||
|
} else {
|
||||||
|
frame_delay = 1.0 / 60.0; // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
AVCodecParameters *codec_par = fmt_ctx->streams[video_stream_idx]->codecpar;
|
||||||
|
codec = avcodec_find_decoder(codec_par->codec_id);
|
||||||
|
if (!codec)
|
||||||
|
return;
|
||||||
|
|
||||||
|
codec_ctx = avcodec_alloc_context3(codec);
|
||||||
|
if (!codec_ctx)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (avcodec_parameters_to_context(codec_ctx, codec_par) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
active_hw_mode = HW_VULKAN;
|
||||||
|
if (av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VULKAN, nullptr, nullptr, 0) < 0) {
|
||||||
|
UtilityFunctions::print("[gdvapi] vulkan video extensions missing on driver, trying va-api");
|
||||||
|
|
||||||
|
active_hw_mode = HW_VAAPI;
|
||||||
|
if (av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_VAAPI, nullptr, nullptr, 0) < 0) {
|
||||||
|
UtilityFunctions::print("[gdvapi] va-api acceleration unavailable. using software");
|
||||||
|
active_hw_mode = HW_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (active_hw_mode != HW_NONE) {
|
||||||
|
codec_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
|
||||||
|
codec_ctx->get_format = get_hw_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avcodec_open2(codec_ctx, codec, nullptr) < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
frame = av_frame_alloc();
|
||||||
|
sw_frame = av_frame_alloc();
|
||||||
|
packet = av_packet_alloc();
|
||||||
|
|
||||||
|
width = codec_ctx->width;
|
||||||
|
height = codec_ctx->height;
|
||||||
|
texture_init();
|
||||||
|
|
||||||
|
sws_ctx = sws_getContext(
|
||||||
|
width, height, codec_ctx->pix_fmt,
|
||||||
|
width, height, AV_PIX_FMT_RGBA,
|
||||||
|
SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
|
time_accumulator = 0.0;
|
||||||
|
set_process(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::_process(double delta) {
|
||||||
|
if (!fmt_ctx || !codec_ctx) return;
|
||||||
|
|
||||||
|
time_accumulator += delta;
|
||||||
|
|
||||||
|
if (time_accumulator < frame_delay) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_accumulator -= frame_delay;
|
||||||
|
|
||||||
|
bool frame_finished = false;
|
||||||
|
while (!frame_finished && av_read_frame(fmt_ctx, packet) >= 0) {
|
||||||
|
if (packet->stream_index == video_stream_idx) {
|
||||||
|
if (avcodec_send_packet(codec_ctx, packet) >= 0) {
|
||||||
|
while (avcodec_receive_frame(codec_ctx, frame) >= 0) {
|
||||||
|
frame_finished = true;
|
||||||
|
|
||||||
|
RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device();
|
||||||
|
if (!rd || !texture_rd_rid.is_valid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (frame->format == AV_PIX_FMT_VULKAN || frame->format == AV_PIX_FMT_VAAPI) {
|
||||||
|
if (av_hwframe_transfer_data(sw_frame, frame, 0) >= 0) {
|
||||||
|
PackedByteArray gpu_bytes;
|
||||||
|
gpu_bytes.resize(width * height * 4);
|
||||||
|
|
||||||
|
uint8_t *dest_pointers[4] = { gpu_bytes.ptrw(), nullptr, nullptr, nullptr };
|
||||||
|
int dest_linesizes[4] = { width * 4, 0, 0, 0 };
|
||||||
|
|
||||||
|
enum AVPixelFormat src_fmt = (enum AVPixelFormat)sw_frame->format;
|
||||||
|
struct SwsContext *hw_sws = sws_getContext(
|
||||||
|
width, height, src_fmt,
|
||||||
|
width, height, AV_PIX_FMT_RGBA,
|
||||||
|
SWS_BILINEAR, nullptr, nullptr, nullptr);
|
||||||
|
|
||||||
|
if (hw_sws) {
|
||||||
|
sws_scale(hw_sws, sw_frame->data, sw_frame->linesize, 0, height, dest_pointers, dest_linesizes);
|
||||||
|
sws_freeContext(hw_sws);
|
||||||
|
rd->texture_update(texture_rd_rid, 0, gpu_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (frame->data[0] != nullptr) {
|
||||||
|
PackedByteArray rgba_data;
|
||||||
|
rgba_data.resize(width * height * 4);
|
||||||
|
uint8_t *dest_pointers[4] = { rgba_data.ptrw(), nullptr, nullptr, nullptr };
|
||||||
|
int dest_linesizes[4] = { width * 4, 0, 0, 0 };
|
||||||
|
|
||||||
|
if (sws_ctx) {
|
||||||
|
sws_scale(sws_ctx, frame->data, frame->linesize, 0, height, dest_pointers, dest_linesizes);
|
||||||
|
rd->texture_update(texture_rd_rid, 0, rgba_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queue_redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
av_packet_unref(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GDVAPIVideoStream::~GDVAPIVideoStream() {
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::_notification(int p_what) {
|
||||||
|
switch (p_what) {
|
||||||
|
case NOTIFICATION_EXIT_TREE: {
|
||||||
|
cleanup();
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::texture_init() {
|
||||||
|
RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device();
|
||||||
|
if (!rd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (texture_rd_rid.is_valid()) {
|
||||||
|
rd->free_rid(texture_rd_rid);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<RDTextureFormat> format;
|
||||||
|
format.instantiate();
|
||||||
|
format->set_texture_type(RenderingDevice::TEXTURE_TYPE_2D);
|
||||||
|
format->set_format(RenderingDevice::DATA_FORMAT_R8G8B8A8_UNORM);
|
||||||
|
format->set_width(width);
|
||||||
|
format->set_height(height);
|
||||||
|
format->set_depth(1);
|
||||||
|
format->set_array_layers(1);
|
||||||
|
format->set_mipmaps(1);
|
||||||
|
format->set_usage_bits(RenderingDevice::TEXTURE_USAGE_SAMPLING_BIT |
|
||||||
|
RenderingDevice::TEXTURE_USAGE_CAN_UPDATE_BIT);
|
||||||
|
|
||||||
|
PackedByteArray byte_array;
|
||||||
|
byte_array.resize(width * height * 4);
|
||||||
|
|
||||||
|
TypedArray<PackedByteArray> data;
|
||||||
|
data.push_back(byte_array);
|
||||||
|
|
||||||
|
Ref<RDTextureView> view;
|
||||||
|
view.instantiate();
|
||||||
|
|
||||||
|
texture_rd_rid = rd->texture_create(format, view, data);
|
||||||
|
|
||||||
|
if (texture_rd_rid.is_valid()) {
|
||||||
|
godot_texture.instantiate();
|
||||||
|
godot_texture->set_texture_rd_rid(texture_rd_rid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::cleanup() {
|
||||||
|
set_process(false);
|
||||||
|
RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device();
|
||||||
|
|
||||||
|
godot_texture.unref();
|
||||||
|
|
||||||
|
if (rd && texture_rd_rid.is_valid()) {
|
||||||
|
rd->free_rid(texture_rd_rid);
|
||||||
|
texture_rd_rid = RID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sws_ctx) {
|
||||||
|
sws_freeContext(sws_ctx);
|
||||||
|
sws_ctx = nullptr;
|
||||||
|
}
|
||||||
|
if (frame) {
|
||||||
|
av_frame_free(&frame);
|
||||||
|
}
|
||||||
|
if (sw_frame) {
|
||||||
|
av_frame_free(&sw_frame);
|
||||||
|
}
|
||||||
|
if (packet) {
|
||||||
|
av_packet_free(&packet);
|
||||||
|
}
|
||||||
|
if (codec_ctx) {
|
||||||
|
avcodec_free_context(&codec_ctx);
|
||||||
|
}
|
||||||
|
if (hw_device_ctx) {
|
||||||
|
av_buffer_unref(&hw_device_ctx);
|
||||||
|
hw_device_ctx = nullptr;
|
||||||
|
}
|
||||||
|
if (fmt_ctx) {
|
||||||
|
avformat_close_input(&fmt_ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::_draw() {
|
||||||
|
UtilityFunctions::print("_draw called");
|
||||||
|
if (godot_texture.is_valid()) {
|
||||||
|
draw_texture(godot_texture, Point2(0, 0));
|
||||||
|
} else {
|
||||||
|
Rect2 rect = Rect2(0, 0, desiredWidth, desiredHeight);
|
||||||
|
|
||||||
|
Color color = Color(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
draw_rect(rect, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::set_desired_width(const int v) {
|
||||||
|
if (desiredWidth != v) {
|
||||||
|
desiredWidth = v;
|
||||||
|
queue_redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::set_desired_height(const int v) {
|
||||||
|
if (desiredHeight != v) {
|
||||||
|
desiredHeight = v;
|
||||||
|
queue_redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int GDVAPIVideoStream::get_desired_width() const {
|
||||||
|
return desiredWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GDVAPIVideoStream::get_desired_height() const {
|
||||||
|
return desiredHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void GDVAPIVideoStream::_ready() {
|
||||||
|
UtilityFunctions::print("_ready called");
|
||||||
|
queue_redraw();
|
||||||
|
}
|
||||||
67
src/gdvapivideostream_class.h
Normal file
67
src/gdvapivideostream_class.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "godot_cpp/classes/control.hpp"
|
||||||
|
#include "godot_cpp/classes/texture2drd.hpp"
|
||||||
|
#include "godot_cpp/variant/rid.hpp"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/imgutils.h>
|
||||||
|
#include <libswscale/swscale.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace godot {
|
||||||
|
|
||||||
|
class GDVAPIVideoStream : public Control {
|
||||||
|
GDCLASS(GDVAPIVideoStream, Control)
|
||||||
|
|
||||||
|
private:
|
||||||
|
AVFormatContext *fmt_ctx = nullptr;
|
||||||
|
AVCodecContext *codec_ctx = nullptr;
|
||||||
|
const AVCodec *codec = nullptr;
|
||||||
|
AVFrame *frame = nullptr;
|
||||||
|
AVPacket *packet = nullptr;
|
||||||
|
struct SwsContext *sws_ctx = nullptr;
|
||||||
|
int video_stream_idx = -1;
|
||||||
|
int width = 256;
|
||||||
|
int height = 256;
|
||||||
|
AVBufferRef *hw_device_ctx = nullptr;
|
||||||
|
AVFrame *sw_frame = nullptr;
|
||||||
|
|
||||||
|
double frame_delay = 0.0;
|
||||||
|
double time_accumulator = 0.0;
|
||||||
|
|
||||||
|
RID texture_rd_rid;
|
||||||
|
Ref<Texture2DRD> godot_texture;
|
||||||
|
|
||||||
|
|
||||||
|
int desiredWidth = 256;
|
||||||
|
int desiredHeight = 256;
|
||||||
|
|
||||||
|
void cleanup();
|
||||||
|
void texture_init();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
GDVAPIVideoStream() = default;
|
||||||
|
~GDVAPIVideoStream() override;
|
||||||
|
|
||||||
|
void begin(const Variant &source);
|
||||||
|
|
||||||
|
void _process(double delta) override;
|
||||||
|
|
||||||
|
void _notification(int p_what);
|
||||||
|
void _draw() override;
|
||||||
|
void _ready() override;
|
||||||
|
|
||||||
|
void set_desired_width(const int v);
|
||||||
|
int get_desired_width() const;
|
||||||
|
|
||||||
|
void set_desired_height(const int v);
|
||||||
|
int get_desired_height() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,34 +5,32 @@
|
|||||||
#include <godot_cpp/core/defs.hpp>
|
#include <godot_cpp/core/defs.hpp>
|
||||||
#include <godot_cpp/godot.hpp>
|
#include <godot_cpp/godot.hpp>
|
||||||
|
|
||||||
#include "example_class.h"
|
#include "gdvapivideostream_class.h"
|
||||||
|
|
||||||
using namespace godot;
|
using namespace godot;
|
||||||
|
|
||||||
void initialize_gdextension_types(ModuleInitializationLevel p_level)
|
void initialize_gdextension_types(ModuleInitializationLevel p_level) {
|
||||||
{
|
|
||||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GDREGISTER_CLASS(ExampleClass);
|
|
||||||
|
GDREGISTER_RUNTIME_CLASS(GDVAPIVideoStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
|
void uninitialize_gdextension_types(ModuleInitializationLevel p_level) {
|
||||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C" {
|
||||||
{
|
GDExtensionBool GDE_EXPORT gdvapi_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
|
||||||
// Initialization
|
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
||||||
GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization)
|
init_obj.register_initializer(initialize_gdextension_types);
|
||||||
{
|
init_obj.register_terminator(uninitialize_gdextension_types);
|
||||||
GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
|
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
||||||
init_obj.register_initializer(initialize_gdextension_types);
|
|
||||||
init_obj.register_terminator(uninitialize_gdextension_types);
|
|
||||||
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
|
|
||||||
|
|
||||||
return init_obj.init();
|
return init_obj.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user