Compare commits
No commits in common. "master" and "ffms-video-player" have entirely different histories.
master
...
ffms-video
64841 changed files with 48840 additions and 13854439 deletions
73
.gitattributes
vendored
73
.gitattributes
vendored
|
@ -1,73 +0,0 @@
|
|||
#
|
||||
# Image
|
||||
#
|
||||
*.xcf filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||
*.bmp filter=lfs diff=lfs merge=lfs -text
|
||||
*.avif filter=lfs diff=lfs merge=lfs -text
|
||||
*.tiff filter=lfs diff=lfs merge=lfs -text
|
||||
*.ico filter=lfs diff=lfs merge=lfs -text
|
||||
*.jxl filter=lfs diff=lfs merge=lfs -text
|
||||
*.pcx filter=lfs diff=lfs merge=lfs -text
|
||||
*.pnm filter=lfs diff=lfs merge=lfs -text
|
||||
*.pgm filter=lfs diff=lfs merge=lfs -text
|
||||
*.qoi filter=lfs diff=lfs merge=lfs -text
|
||||
*.tga filter=lfs diff=lfs merge=lfs -text
|
||||
*.webp filter=lfs diff=lfs merge=lfs -text
|
||||
*.tif filter=lfs diff=lfs merge=lfs -text
|
||||
*.jbg filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
#
|
||||
# Other Binary
|
||||
#
|
||||
*.exe filter=lfs diff=lfs merge=lfs -text
|
||||
*.dll filter=lfs diff=lfs merge=lfs -text
|
||||
*.dat filter=lfs diff=lfs merge=lfs -text
|
||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
#
|
||||
# Audio
|
||||
#
|
||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||
*.flac filter=lfs diff=lfs merge=lfs -text
|
||||
*.vgz filter=lfs diff=lfs merge=lfs -text
|
||||
*.nsf filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp3 filter=lfs diff=lfs merge=lfs -text
|
||||
*.mod filter=lfs diff=lfs merge=lfs -text
|
||||
*.it filter=lfs diff=lfs merge=lfs -text
|
||||
*.itz filter=lfs diff=lfs merge=lfs -text
|
||||
*.MOD filter=lfs diff=lfs merge=lfs -text
|
||||
*.med filter=lfs diff=lfs merge=lfs -text
|
||||
*.xm filter=lfs diff=lfs merge=lfs -text
|
||||
*.oxm filter=lfs diff=lfs merge=lfs -text
|
||||
*.raw filter=lfs diff=lfs merge=lfs -text
|
||||
*.ogg filter=lfs diff=lfs merge=lfs -text
|
||||
*.opus filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
#
|
||||
# Document
|
||||
#
|
||||
*.odt filter=lfs diff=lfs merge=lfs -text
|
||||
*.pdf filter=lfs diff=lfs merge=lfs -text
|
||||
*.docx filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
#
|
||||
# Video
|
||||
#
|
||||
*.mkv filter=lfs diff=lfs merge=lfs -text
|
||||
*.avi filter=lfs diff=lfs merge=lfs -text
|
||||
*.mov filter=lfs diff=lfs merge=lfs -text
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.mpg filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
#
|
||||
# Archive
|
||||
#
|
||||
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
||||
*.xz filter=lfs diff=lfs merge=lfs -text
|
||||
*.lz filter=lfs diff=lfs merge=lfs -text
|
||||
*.lzma filter=lfs diff=lfs merge=lfs -text
|
||||
*.gz filter=lfs diff=lfs merge=lfs -text
|
||||
*.tar filter=lfs diff=lfs merge=lfs -text
|
13
.gitignore
vendored
13
.gitignore
vendored
|
@ -1,9 +1,8 @@
|
|||
*~
|
||||
**/.builddir/
|
||||
**/.git-hidden/
|
||||
**/.github/
|
||||
cmake-build-debug/
|
||||
*.log
|
||||
*.user
|
||||
temp/
|
||||
*#
|
||||
*.ISO
|
||||
*.iso
|
||||
*.m4v
|
||||
*.index
|
||||
*.avi
|
||||
*.vob
|
||||
|
|
245
CHANGELOG
245
CHANGELOG
|
@ -1,245 +0,0 @@
|
|||
SINGE 2.10
|
||||
==========
|
||||
|
||||
Released March 26th, 2024
|
||||
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- spriteDraw() now has two more forms. In addition to being able to draw
|
||||
regular sprites and streteched sprites it can now draw both using the
|
||||
sprite's center as the anchor instead of the upper right. This is highly
|
||||
useful when dealing with rotated sprites.
|
||||
|
||||
- Animated sprites! Both animated GIF and WEBP images are supported.
|
||||
|
||||
- Sprite anti-aliasing, scaling and rotation! Optional separate X & Y scaling.
|
||||
|
||||
- Video anti-aliasing, scaling and rotation! Optional separate X & Y scaling.
|
||||
|
||||
- Multiple audio track support for videos. New command line options to select
|
||||
which default audio track you want (-o or --audio). For games with multiple
|
||||
languages, you can specify AUDIO_TRACK in the games.dat as well.
|
||||
|
||||
- New keyboard methods to make handling input easier, especially multiple
|
||||
keypresses for diagonal movement.
|
||||
|
||||
- controllerGetButton() added.
|
||||
|
||||
- SINGE_DEAD_ZONE global variable now available based on the DEAD_ZONE
|
||||
controller configuration option.
|
||||
|
||||
- SINGE_FRAMEWORK_VERSION variable added.
|
||||
|
||||
- DIR variable added providing directory to the running script.
|
||||
|
||||
- All new Lua library handling. Previously Singe "injected" libraries
|
||||
directly into the script context. Now there is a proper Lua module search
|
||||
handler. Scripts can properly require() modules from the following:
|
||||
- Lua Standard Library
|
||||
- Lua Auxillary Library
|
||||
- LuaFileSystem
|
||||
- LuaSocket
|
||||
- LuaSec
|
||||
- LuaRS232
|
||||
- timerwheel
|
||||
- binaryheap
|
||||
- Copas
|
||||
- json
|
||||
|
||||
- New command line option: -p (or --program). This is similar to the
|
||||
existing -t (or --trace) option. Where "trace" displays and logs script
|
||||
execution, "program" displays and logs Singe internals. This should make
|
||||
troubleshooting difficult setups and odd script crashes easier.
|
||||
|
||||
- Auto-installer for the new GAME, TOOL, and PATCH archive formats to make
|
||||
managing games easier.
|
||||
|
||||
- ZeroBrane Studio (https://studio.zerobrane.com) integration for live
|
||||
debugging of running Singe scripts! A full IDE for developing games!
|
||||
|
||||
|
||||
Fixes
|
||||
-----
|
||||
|
||||
- USB controllers now work in games launched from the included menu.
|
||||
|
||||
- Default controller DEAD_ZONE increased.
|
||||
|
||||
- Framework.singe was missing keyboard mode constants. MODE_NORMAL and
|
||||
MODE_FULL are now included.
|
||||
|
||||
- SINGE 2.00 added two new input events but never had them in the framework.
|
||||
SWITCH_BUTTON4 and SWITCH_TILT are now available.
|
||||
|
||||
- Taking screenshots could sometimes crash Singe.
|
||||
|
||||
- PNG files no longer generate warnings on the console.
|
||||
|
||||
- Non-VLDP videos now honor command line volume settings.
|
||||
|
||||
- Menu system now performs "natural sorting" of game titles instead of brain
|
||||
dead "computer sorting". It should make a lot more sense paging through
|
||||
games now.
|
||||
|
||||
- Building Singe depended on a lot of undocumented software cobbled together
|
||||
from other projects. This has been vastly improved and should be usable by
|
||||
actual humans now. Humans running Linux anyway.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
SINGE 2.00
|
||||
==========
|
||||
|
||||
Released October 25th, 2020
|
||||
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- Complete rewrite! No more dependency on Daphne.
|
||||
|
||||
- Support for almost every (non-patent encumbered) video and audio format
|
||||
that can be played by FFMPEG.
|
||||
|
||||
- High definition video.
|
||||
|
||||
- 32 bit color.
|
||||
|
||||
- Additional videos can be played on top the laserdisc video.
|
||||
|
||||
- Scaled sprites.
|
||||
|
||||
- Graphics overlay resolution no longer dependent on video resolution.
|
||||
|
||||
- Analog controllers.
|
||||
|
||||
- LuaSocket and LuaFileSystem added to runtime.
|
||||
|
||||
- Ability to chain scripts together for menus or launchers.
|
||||
|
||||
- Specify if you want gun games to display on-screen crosshairs or not.
|
||||
|
||||
- Menu for launching games included.
|
||||
|
||||
- Many updates to Framework.singe to support the new APIs.
|
||||
|
||||
- New APIs:
|
||||
- controllerGetAxis
|
||||
- discGetHeight
|
||||
- discGetWidth
|
||||
- fontUnload
|
||||
- mouseGetPosition
|
||||
- mouseSetCaptured
|
||||
- overlayBox
|
||||
- overlayCircle
|
||||
- overlayEllipse
|
||||
- overlayLine
|
||||
- overlayPlot
|
||||
- overlaySetResolution
|
||||
- scriptExecute
|
||||
- scriptPush
|
||||
- singeWantsCrosshairs
|
||||
- soundUnload
|
||||
- spriteGetHeight
|
||||
- spriteGetWidth
|
||||
- spriteUnload
|
||||
- videoDraw
|
||||
- videoGetFrame
|
||||
- videoGetFrameCount
|
||||
- videoGetHeight
|
||||
- videoGetVolume
|
||||
- videoGetWidth
|
||||
- videoIsPlaying
|
||||
- videoLoad
|
||||
- videoPause
|
||||
- videoPlay
|
||||
- videoSeek
|
||||
- videoSetVolume
|
||||
- videoUnload
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
SINGE 1.14 - 1.19
|
||||
=================
|
||||
|
||||
Released ?
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- Unofficial fan builds.
|
||||
- Stand-alone releases.
|
||||
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- New API functions:
|
||||
- discPauseAtFrame
|
||||
- mouseEnable
|
||||
- mouseDisable
|
||||
- mouseHowMany
|
||||
- mouseSetMode
|
||||
- singeDisablePauseKey
|
||||
- singeEnablePauseKey
|
||||
- singeGetScriptPath
|
||||
- singeSetGameName
|
||||
- soundFullStop
|
||||
- soundGetVolume
|
||||
- soundIsPlaying
|
||||
- soundPause
|
||||
- soundResume
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
SINGE 1.10 - 1.14
|
||||
=================
|
||||
|
||||
Released ?
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- Unofficial fan builds.
|
||||
- DLL releases for Daphne.
|
||||
|
||||
|
||||
New Features
|
||||
------------
|
||||
|
||||
- New API functions:
|
||||
- discGetState
|
||||
- keyboardGetMode
|
||||
- keyboardSetMode
|
||||
- singeGetPauseFlag
|
||||
- singeSetPauseFlag
|
||||
- singeQuit
|
||||
- singeVersion
|
||||
- soundStop
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
SINGE 1.00
|
||||
==========
|
||||
|
||||
Released 2006
|
||||
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
||||
- Original add-on for Daphne.
|
||||
- Shipped with the ActionMax "emulator" and games.
|
||||
|
419
CMakeLists.txt
419
CMakeLists.txt
|
@ -1,419 +0,0 @@
|
|||
#
|
||||
# Singe 2
|
||||
# Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public Licens
|
||||
# as published by the Free Software Foundation; either version 3
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
project(singe2)
|
||||
|
||||
|
||||
if(NOT DEFINED KANGAROO_OS)
|
||||
set(KANGAROO_OS linux)
|
||||
endif()
|
||||
if(NOT DEFINED KANGAROO_ARCH)
|
||||
set(KANGAROO_ARCH x86_64)
|
||||
endif()
|
||||
|
||||
set(BUILD_DIR ${CMAKE_SOURCE_DIR}/.builddir/${KANGAROO_OS}/${KANGAROO_ARCH})
|
||||
|
||||
|
||||
set(SINGE_SOURCE
|
||||
src/main.h
|
||||
src/singe.c
|
||||
src/singe.h
|
||||
src/util.h
|
||||
src/embedded.h
|
||||
src/frameFile.h
|
||||
src/main.c
|
||||
src/common.h
|
||||
src/videoPlayer.c
|
||||
src/stddclmr.h
|
||||
src/frameFile.c
|
||||
src/videoPlayer.h
|
||||
src/util.c
|
||||
)
|
||||
|
||||
|
||||
set(ARG_PARSER_SOURCE
|
||||
thirdparty/arg_parser/carg_parser.c
|
||||
thirdparty/arg_parser/carg_parser.h
|
||||
)
|
||||
|
||||
|
||||
set(JBIG_SOURCE
|
||||
thirdparty/jbigkit/libjbig/jbig.c
|
||||
thirdparty/jbigkit/libjbig/jbig.h
|
||||
thirdparty/jbigkit/libjbig/jbig_ar.c
|
||||
thirdparty/jbigkit/libjbig/jbig_ar.h
|
||||
)
|
||||
|
||||
|
||||
set(LUA_SOURCE
|
||||
thirdparty/lua/src/lmem.h
|
||||
thirdparty/lua/src/ltm.h
|
||||
thirdparty/lua/src/lutf8lib.c
|
||||
thirdparty/lua/src/ldo.h
|
||||
thirdparty/lua/src/ldump.c
|
||||
thirdparty/lua/src/lstring.h
|
||||
thirdparty/lua/src/lparser.h
|
||||
thirdparty/lua/src/lcorolib.c
|
||||
thirdparty/lua/src/loslib.c
|
||||
thirdparty/lua/src/lparser.c
|
||||
thirdparty/lua/src/ltablib.c
|
||||
thirdparty/lua/src/ltable.c
|
||||
thirdparty/lua/src/ljumptab.h
|
||||
thirdparty/lua/src/luaconf.h
|
||||
thirdparty/lua/src/lstate.c
|
||||
thirdparty/lua/src/lobject.h
|
||||
thirdparty/lua/src/lstate.h
|
||||
thirdparty/lua/src/ldo.c
|
||||
thirdparty/lua/src/lfunc.c
|
||||
thirdparty/lua/src/lmathlib.c
|
||||
thirdparty/lua/src/lua.h
|
||||
thirdparty/lua/src/lauxlib.h
|
||||
thirdparty/lua/src/ltm.c
|
||||
thirdparty/lua/src/lstrlib.c
|
||||
thirdparty/lua/src/lapi.h
|
||||
thirdparty/lua/src/lopcodes.c
|
||||
thirdparty/lua/src/lvm.h
|
||||
thirdparty/lua/src/linit.c
|
||||
thirdparty/lua/src/lobject.c
|
||||
thirdparty/lua/src/ldebug.c
|
||||
thirdparty/lua/src/lctype.c
|
||||
thirdparty/lua/src/lgc.c
|
||||
thirdparty/lua/src/lzio.h
|
||||
thirdparty/lua/src/lgc.h
|
||||
thirdparty/lua/src/lctype.h
|
||||
thirdparty/lua/src/lopcodes.h
|
||||
thirdparty/lua/src/llimits.h
|
||||
thirdparty/lua/src/lprefix.h
|
||||
thirdparty/lua/src/llex.h
|
||||
thirdparty/lua/src/lundump.c
|
||||
thirdparty/lua/src/lbaselib.c
|
||||
thirdparty/lua/src/loadlib.c
|
||||
thirdparty/lua/src/ldblib.c
|
||||
thirdparty/lua/src/ldebug.h
|
||||
thirdparty/lua/src/lundump.h
|
||||
thirdparty/lua/src/lopnames.h
|
||||
thirdparty/lua/src/ltable.h
|
||||
thirdparty/lua/src/lmem.c
|
||||
thirdparty/lua/src/lcode.h
|
||||
thirdparty/lua/src/lua.hpp
|
||||
thirdparty/lua/src/lauxlib.c
|
||||
thirdparty/lua/src/liolib.c
|
||||
thirdparty/lua/src/lapi.c
|
||||
thirdparty/lua/src/lcode.c
|
||||
thirdparty/lua/src/llex.c
|
||||
thirdparty/lua/src/lstring.c
|
||||
thirdparty/lua/src/lvm.c
|
||||
thirdparty/lua/src/lualib.h
|
||||
thirdparty/lua/src/lfunc.h
|
||||
thirdparty/lua/src/lzio.c
|
||||
)
|
||||
|
||||
|
||||
set(LUA_FILESYSTEM_SOURCE
|
||||
thirdparty/luafilesystem/src/lfs.c
|
||||
thirdparty/luafilesystem/src/lfs.h
|
||||
)
|
||||
|
||||
|
||||
set(LUA_SOCKET_SOURCE
|
||||
thirdparty/luasocket/src/luasocket.h
|
||||
thirdparty/luasocket/src/luasocket.c
|
||||
thirdparty/luasocket/src/timeout.h
|
||||
thirdparty/luasocket/src/timeout.c
|
||||
thirdparty/luasocket/src/buffer.h
|
||||
thirdparty/luasocket/src/buffer.c
|
||||
thirdparty/luasocket/src/io.h
|
||||
thirdparty/luasocket/src/io.c
|
||||
thirdparty/luasocket/src/auxiliar.h
|
||||
thirdparty/luasocket/src/auxiliar.c
|
||||
thirdparty/luasocket/src/compat.h
|
||||
thirdparty/luasocket/src/compat.c
|
||||
thirdparty/luasocket/src/options.h
|
||||
thirdparty/luasocket/src/options.c
|
||||
thirdparty/luasocket/src/inet.h
|
||||
thirdparty/luasocket/src/inet.c
|
||||
thirdparty/luasocket/src/except.h
|
||||
thirdparty/luasocket/src/except.c
|
||||
thirdparty/luasocket/src/select.h
|
||||
thirdparty/luasocket/src/select.c
|
||||
thirdparty/luasocket/src/tcp.h
|
||||
thirdparty/luasocket/src/tcp.c
|
||||
thirdparty/luasocket/src/udp.h
|
||||
thirdparty/luasocket/src/udp.c
|
||||
thirdparty/luasocket/src/mime.h
|
||||
thirdparty/luasocket/src/mime.c
|
||||
thirdparty/luasocket/src/socket.h
|
||||
thirdparty/luasocket/src/pierror.h
|
||||
)
|
||||
if(WIN32)
|
||||
set(LUA_SOCKET_SOURCE
|
||||
${LUA_SOCKET_SOURCE}
|
||||
thirdparty/luasocket/src/wsocket.h
|
||||
thirdparty/luasocket/src/wsocket.c
|
||||
)
|
||||
ELSE()
|
||||
set(LUA_SOCKET_SOURCE
|
||||
${LUA_SOCKET_SOURCE}
|
||||
thirdparty/luasocket/src/usocket.h
|
||||
thirdparty/luasocket/src/usocket.c
|
||||
thirdparty/luasocket/src/unix.h
|
||||
thirdparty/luasocket/src/unix.c
|
||||
thirdparty/luasocket/src/unixstream.h
|
||||
thirdparty/luasocket/src/unixstream.c
|
||||
thirdparty/luasocket/src/unixdgram.c
|
||||
thirdparty/luasocket/src/unixdgram.h
|
||||
thirdparty/luasocket/src/serial.c
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
|
||||
set(LUASEC_SOURCE
|
||||
thirdparty/luasec/src/compat.h
|
||||
thirdparty/luasec/src/config.c
|
||||
${BUILD_DIR}/generated/luasec_options.c
|
||||
thirdparty/luasec/src/context.c
|
||||
thirdparty/luasec/src/context.h
|
||||
thirdparty/luasec/src/ec.c
|
||||
thirdparty/luasec/src/ec.h
|
||||
thirdparty/luasec/src/options.h
|
||||
thirdparty/luasec/src/ssl.c
|
||||
thirdparty/luasec/src/ssl.h
|
||||
thirdparty/luasec/src/x509.c
|
||||
thirdparty/luasec/src/x509.h
|
||||
)
|
||||
|
||||
|
||||
set(LUA_RS232_SOURCE
|
||||
thirdparty/librs232/bindings/lua/luars232.c
|
||||
thirdparty/librs232/src/rs232.c
|
||||
)
|
||||
if(WIN32)
|
||||
set(LUA_RS232_SOURCE
|
||||
${LUA_RS232_SOURCE}
|
||||
thirdparty/librs232/src/rs232_windows.c
|
||||
)
|
||||
ELSE()
|
||||
set(LUA_RS232_SOURCE
|
||||
${LUA_RS232_SOURCE}
|
||||
thirdparty/librs232/src/rs232_posix.c
|
||||
)
|
||||
ENDIF()
|
||||
|
||||
|
||||
set(UTHASH_SOURCE
|
||||
thirdparty/uthash/src/uthash.h
|
||||
thirdparty/uthash/src/utlist.h
|
||||
)
|
||||
|
||||
|
||||
set(MANYMOUSE_SOURCE
|
||||
thirdparty/manymouse/linux_evdev.c
|
||||
thirdparty/manymouse/macosx_hidmanager.c
|
||||
thirdparty/manymouse/macosx_hidutilities.c
|
||||
thirdparty/manymouse/manymouse.c
|
||||
thirdparty/manymouse/manymouse.h
|
||||
thirdparty/manymouse/windows_wminput.c
|
||||
thirdparty/manymouse/x11_xinput2.c
|
||||
)
|
||||
|
||||
|
||||
set(SDL2_GFX_SOURCE
|
||||
thirdparty/SDL2_gfx/SDL2_rotozoom.h
|
||||
thirdparty/SDL2_gfx/SDL2_rotozoom.c
|
||||
)
|
||||
|
||||
|
||||
add_executable(${CMAKE_PROJECT_NAME}
|
||||
${SINGE_SOURCE}
|
||||
${ARG_PARSER_SOURCE}
|
||||
${JBIG_SOURCE}
|
||||
${LUA_SOURCE}
|
||||
${LUA_FILESYSTEM_SOURCE}
|
||||
${LUA_SOCKET_SOURCE}
|
||||
${LUASEC_SOURCE}
|
||||
${LUA_RS232_SOURCE}
|
||||
${UTHASH_SOURCE}
|
||||
${MANYMOUSE_SOURCE}
|
||||
${SDL2_GFX_SOURCE}
|
||||
)
|
||||
|
||||
|
||||
# Perform pre-build operations.
|
||||
#add_custom_target(BUILD_PREREQS
|
||||
# COMMAND ${BUILD_DIR}-deps.sh "${CMAKE_SOURCE_DIR}"
|
||||
# BYPRODUCTS
|
||||
# ${CMAKE_SOURCE_DIR}/thirdparty-installed/lib/libarchive.a
|
||||
#)
|
||||
#add_dependencies(${CMAKE_PROJECT_NAME} BUILD_PREREQS)
|
||||
|
||||
|
||||
if(WIN32)
|
||||
# Note: _WIN32_WINNT=0x0600 sets the minimum compatible version of
|
||||
# Windows to Vista. The function inet_pton() does not exist before then.
|
||||
set(DEFINE_LIST
|
||||
-Dmain=SDL_main
|
||||
-D_WIN32_WINNT=0x0600
|
||||
)
|
||||
else()
|
||||
set(DEFINE_LIST)
|
||||
endif()
|
||||
target_compile_options(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
${DEFINE_LIST}
|
||||
-DRS232_STATIC
|
||||
-DFFMS_STATIC
|
||||
-Wno-deprecated-declarations
|
||||
)
|
||||
|
||||
|
||||
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
${BUILD_DIR}
|
||||
${BUILD_DIR}/include
|
||||
${BUILD_DIR}/include/SDL2
|
||||
thirdparty/lua/src
|
||||
thirdparty/luasec/src
|
||||
thirdparty/librs232/include
|
||||
)
|
||||
|
||||
|
||||
target_link_directories(${CMAKE_PROJECT_NAME} PUBLIC
|
||||
${BUILD_DIR}/lib
|
||||
)
|
||||
|
||||
|
||||
if(${KANGAROO_OS} STREQUAL "linux")
|
||||
set(LIB_LIST
|
||||
-lX11
|
||||
-lvdpau
|
||||
${BUILD_DIR}/lib/libjpeg.a
|
||||
${BUILD_DIR}/lib/libpng.a
|
||||
-lstdc++
|
||||
)
|
||||
endif()
|
||||
if(${KANGAROO_OS} STREQUAL "pi")
|
||||
set(LIB_LIST
|
||||
${BUILD_DIR}/lib/libjpeg.a
|
||||
${BUILD_DIR}/lib/libpng.a
|
||||
-lstdc++
|
||||
)
|
||||
endif()
|
||||
if(${KANGAROO_OS} STREQUAL "macos")
|
||||
set(LIB_LIST
|
||||
-Wl,-framework,CoreVideo
|
||||
-Wl,-framework,Cocoa
|
||||
-Wl,-framework,IOKit
|
||||
-Wl,-framework,ForceFeedback
|
||||
-Wl,-framework,Carbon
|
||||
-Wl,-framework,CoreAudio
|
||||
-Wl,-framework,AudioToolbox
|
||||
-Wl,-framework,AVFoundation
|
||||
-Wl,-framework,Foundation
|
||||
-Wl,-weak_framework,GameController
|
||||
-Wl,-weak_framework,Metal
|
||||
-Wl,-weak_framework,QuartzCore
|
||||
-Wl,-weak_framework,CoreHaptics
|
||||
-liconv
|
||||
-lc++
|
||||
${OSXCROSS_TARGET_DIR}/darwin/libclang_rt.osx.a
|
||||
)
|
||||
endif()
|
||||
if(${KANGAROO_OS} STREQUAL "windows")
|
||||
set(LIB_LIST
|
||||
-mwindows
|
||||
-static
|
||||
-lmingw32
|
||||
-latomic
|
||||
-lole32
|
||||
-luser32
|
||||
-lkernel32
|
||||
-lgdi32
|
||||
-lwinmm
|
||||
-limm32
|
||||
-loleaut32
|
||||
-lversion
|
||||
-luuid
|
||||
-ladvapi32
|
||||
-lsetupapi
|
||||
-lshell32
|
||||
-ldinput8
|
||||
-lws2_32
|
||||
-lbcrypt
|
||||
-lssp
|
||||
-lcrypt32
|
||||
${BUILD_DIR}/lib/libjpeg.a
|
||||
${BUILD_DIR}/lib/libpng.a
|
||||
-lstdc++
|
||||
)
|
||||
endif()
|
||||
set(LIB_LIST
|
||||
${LIB_LIST}
|
||||
${BUILD_DIR}/lib/libarchive.a
|
||||
${BUILD_DIR}/lib/libavcodec.a
|
||||
${BUILD_DIR}/lib/libavdevice.a
|
||||
${BUILD_DIR}/lib/libavfilter.a
|
||||
${BUILD_DIR}/lib/libavformat.a
|
||||
# ${BUILD_DIR}/lib/libavif.a
|
||||
${BUILD_DIR}/lib/libavutil.a
|
||||
# ${BUILD_DIR}/lib/libbrotlicommon-static.a
|
||||
# ${BUILD_DIR}/lib/libbrotlidec-static.a
|
||||
${BUILD_DIR}/lib/libbz2_static.a
|
||||
# ${BUILD_DIR}/lib/libdav1d.a
|
||||
${BUILD_DIR}/lib/libffms2.a
|
||||
${BUILD_DIR}/lib/libfreetype.a
|
||||
# ${BUILD_DIR}/lib/libharfbuzz.a
|
||||
# ${BUILD_DIR}/lib/libhwy.a
|
||||
# ${BUILD_DIR}/lib/libjxl_dec.a
|
||||
${BUILD_DIR}/lib/liblzma.a
|
||||
${BUILD_DIR}/lib/libopus.a
|
||||
${BUILD_DIR}/lib/libopusfile.a
|
||||
${BUILD_DIR}/lib/libogg.a
|
||||
${BUILD_DIR}/lib/libpostproc.a
|
||||
${BUILD_DIR}/lib/libSDL2.a
|
||||
${BUILD_DIR}/lib/libSDL2_image.a
|
||||
${BUILD_DIR}/lib/libSDL2main.a
|
||||
${BUILD_DIR}/lib/libSDL2_mixer.a
|
||||
${BUILD_DIR}/lib/libSDL2_test.a
|
||||
${BUILD_DIR}/lib/libSDL2_ttf.a
|
||||
${BUILD_DIR}/lib/libswresample.a
|
||||
${BUILD_DIR}/lib/libswscale.a
|
||||
# ${BUILD_DIR}/lib/libtiff.a
|
||||
${BUILD_DIR}/lib/libwavpack.a
|
||||
${BUILD_DIR}/lib/libwebp.a
|
||||
${BUILD_DIR}/lib/libwebpdemux.a
|
||||
${BUILD_DIR}/lib/libxmp.a
|
||||
${BUILD_DIR}/lib/libz.a
|
||||
${BUILD_DIR}/lib/libzstd.a
|
||||
${BUILD_DIR}/lib/libcrypto.a
|
||||
${BUILD_DIR}/lib/libssl.a
|
||||
)
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
# -Wl,--start-group
|
||||
${LIB_LIST}
|
||||
${LIB_LIST}
|
||||
${LIB_LIST}
|
||||
# -Wl,--end-group
|
||||
-pthread
|
||||
-lm
|
||||
)
|
||||
|
||||
|
||||
install(TARGETS ${CMAKE_PROJECT_NAME})
|
674
COPYING
674
COPYING
|
@ -1,674 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
67
INSTALL
67
INSTALL
|
@ -1,67 +0,0 @@
|
|||
SINGE 2.10
|
||||
==========
|
||||
|
||||
(For the latest version of this document, visit https://kangaroopunch.com!)
|
||||
|
||||
Welcome to Singe! The Somewhat Interactive Nostalgic Game Engine!
|
||||
|
||||
|
||||
INSTALLATION & UPGRADE
|
||||
======================
|
||||
|
||||
For the initial installation, create an empty directory and place the Singe
|
||||
binary inside it. Run the binary with no command line options to cause it
|
||||
to generate all the files needed to make Singe work properly. For example:
|
||||
|
||||
C:\Singe2\
|
||||
C:\Singe2\Singe.exe
|
||||
|
||||
Once you run Singe.exe you'll see additional files and directories:
|
||||
|
||||
C:\Singe2\Singe\ (Several files created in this folder.)
|
||||
C:\Singe2\Menu.bat (Or .sh on UNIX-ish OSs.)
|
||||
|
||||
To install games, simply unpack them and place their directory inside the
|
||||
directory you created. For example, ActionMax.7z contains a folder named
|
||||
"ActionMax". Place it here:
|
||||
|
||||
C:\Singe2\ActionMax\
|
||||
|
||||
For all Singe 2 and later games, it will automatically appear in the menu.
|
||||
|
||||
To upgrade, back up any changes you may have made to files inside the Singe
|
||||
subdirectory that was generated during installation. (You really shouldn't
|
||||
be changing things in there!) Delete the Singe subdirectory, Menu.bat (or
|
||||
.sh) and run the new Singe binary with no command line arguments to generate
|
||||
the new files.
|
||||
|
||||
|
||||
COMMAND LINE
|
||||
============
|
||||
___ ___ _ _ ___ ___
|
||||
/ __|_ _| \| |/ __| __| Somewhat Interactive Nostalgic Game Engine v2.10
|
||||
\__ \| || .` | (_ | _| Copyright (c) 2006-2024 Scott C. Duensing
|
||||
|___/___|_|\_|\___|___| https://KangarooPunch.com https://SingeEngine.com
|
||||
|
||||
Usage: Singe-v2.10-Windows-x86_64.exe [OPTIONS] scriptName{.singe}
|
||||
|
||||
-a, --aspect=N:D force aspect ratio
|
||||
-c, --showcalculated show calculated framefile values for debugging
|
||||
-d, --datadir=PATHNAME alternate location for written files
|
||||
-e, --volume_nonvldp=PERCENT specify sound effects volume in percent
|
||||
-f, --fullscreen run in full screen mode
|
||||
-h, --help this display
|
||||
-k, --nologos kill the splash screens
|
||||
-l, --volume_vldp=PERCENT specify laserdisc volume in percent
|
||||
-m, --nomouse disable mouse
|
||||
-n, --nocrosshair request game not display gun crosshairs
|
||||
-o, --audio=TRACK select default track for audio output
|
||||
-p, --program trace Singe execution to screen and file
|
||||
-s, --nosound, --mutesound mutes all sound
|
||||
-t, --trace trace script execution to screen and file
|
||||
-u, --stretch use ugly stretched video
|
||||
-v, --framefile=FILENAME use an alternate video file
|
||||
-w, --fullscreen_window run in windowed full screen mode
|
||||
-x, --xresolution=VALUE specify horizontal resolution
|
||||
-y, --yresolution=VALUE specify vertical resolution
|
||||
-z, --noconsole zero console output
|
33
LICENSES
33
LICENSES
|
@ -1,33 +0,0 @@
|
|||
Singe was made possible by a number of third-party software libraries
|
||||
generously provided as open source by their respective authors. Without
|
||||
these tools, Singe would not exist.
|
||||
|
||||
|
||||
arg_parser BSD-2-Clause http://savannah.nongnu.org/projects/arg-parser
|
||||
binaryheap.lua MIT http://tieske.github.io/binaryheap.lua
|
||||
bzip2 bzip2-1.0.6 https://sourceware.org/bzip2
|
||||
copas MIT https://lunarmodules.github.io/copas
|
||||
ffmpeg LGPL-2.1 https://ffmpeg.org
|
||||
ffms2 GPL-3.0-only https://github.com/FFMS/ffms2
|
||||
jbigkit GPL-2.0 https://www.cl.cam.ac.uk/~mgk25/jbigkit
|
||||
json.lua MIT https://github.com/rxi/json.lua
|
||||
libarchive BSD-2-Clause https://libarchive.org
|
||||
librs232 MIT https://github.com/srdgame/librs232
|
||||
lua MIT https://www.lua.org
|
||||
luafilesystem MIT https://lunarmodules.github.io/luafilesystem
|
||||
luasec MIT https://github.com/lunarmodules/luasec
|
||||
luasocket MIT https://lunarmodules.github.io/luasocket
|
||||
manymouse Zlib https://icculus.org/manymouse
|
||||
openssl Apache-2.0 https://www.openssl.org
|
||||
SDL2 Zlib https://www.libsdl.org
|
||||
SDL2_gfx LGPL-2.1 https://github.com/ferzkopp/SDL_gfx
|
||||
SDL2_image Zlib https://www.libsdl.org
|
||||
SDL2_mixer Zlib https://www.libsdl.org
|
||||
SDL2_ttf Zlib https://www.libsdl.org
|
||||
timerwheel.lua MIT https://tieske.github.io/timerwheel.lua
|
||||
uthash BSD-1-Clause https://troydhanson.github.io/uthash
|
||||
vlc GPL-2.0 https://www.videolan.org/vlc
|
||||
xz Public-Domain https://github.com/tukaani-project/xz
|
||||
zlib Zlib https://zlib.net
|
||||
zstd BSD-3-Clause https://facebook.github.io/zstd
|
||||
|
BIN
assets/180503_01_PurpleGrid.mp4
(Stored with Git LFS)
BIN
assets/180503_01_PurpleGrid.mp4
(Stored with Git LFS)
Binary file not shown.
BIN
assets/BreatheFire-65pg.ttf
(Stored with Git LFS)
BIN
assets/BreatheFire-65pg.ttf
(Stored with Git LFS)
Binary file not shown.
|
@ -1,535 +0,0 @@
|
|||
--[[
|
||||
*
|
||||
* Singe 2
|
||||
* Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
--]]
|
||||
|
||||
|
||||
-- Singe 2.xx Features -------------------------------------------------------
|
||||
|
||||
|
||||
SINGE_FRAMEWORK_VERSION = 2.10
|
||||
|
||||
if singeGetScriptPath ~= nil then
|
||||
DIR = singeGetScriptPath():match("(.*[/\\])") or "./"
|
||||
end
|
||||
|
||||
|
||||
function utilDeepCopy(orig)
|
||||
local orig_type = type(orig)
|
||||
local copy
|
||||
if orig_type == 'table' then
|
||||
copy = {}
|
||||
for orig_key, orig_value in next, orig, nil do
|
||||
copy[utilDeepCopy(orig_key)] = utilDeepCopy(orig_value)
|
||||
end
|
||||
setmetatable(copy, utilDeepCopy(getmetatable(orig)))
|
||||
else -- number, string, boolean, etc
|
||||
copy = orig
|
||||
end
|
||||
return copy
|
||||
end
|
||||
|
||||
|
||||
function utilDump(o)
|
||||
if type(o) == 'table' then
|
||||
local s = '{ '
|
||||
for k,v in pairs(o) do
|
||||
if type(k) ~= 'number' then
|
||||
k = '"'..k..'"'
|
||||
end
|
||||
s = s .. '['..k..'] = ' .. utilDump(v) .. ','
|
||||
end
|
||||
return s .. '} '
|
||||
else
|
||||
return tostring(o)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function utilGetTableSize(t)
|
||||
local count = 0
|
||||
for _, __ in pairs(t) do
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
|
||||
function utilTrim(s)
|
||||
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
||||
end
|
||||
|
||||
|
||||
SCANCODE = {
|
||||
A = { name = "A", value = 4 },
|
||||
B = { name = "B", value = 5 },
|
||||
C = { name = "C", value = 6 },
|
||||
D = { name = "D", value = 7 },
|
||||
E = { name = "E", value = 8 },
|
||||
F = { name = "F", value = 9 },
|
||||
G = { name = "G", value = 10 },
|
||||
H = { name = "H", value = 11 },
|
||||
I = { name = "I", value = 12 },
|
||||
J = { name = "J", value = 13 },
|
||||
K = { name = "K", value = 14 },
|
||||
L = { name = "L", value = 15 },
|
||||
M = { name = "M", value = 16 },
|
||||
N = { name = "N", value = 17 },
|
||||
O = { name = "O", value = 18 },
|
||||
P = { name = "P", value = 19 },
|
||||
Q = { name = "Q", value = 20 },
|
||||
R = { name = "R", value = 21 },
|
||||
S = { name = "S", value = 22 },
|
||||
T = { name = "T", value = 23 },
|
||||
U = { name = "U", value = 24 },
|
||||
V = { name = "V", value = 25 },
|
||||
W = { name = "W", value = 26 },
|
||||
X = { name = "X", value = 27 },
|
||||
Y = { name = "Y", value = 28 },
|
||||
Z = { name = "Z", value = 29 },
|
||||
MAIN_1 = { name = "MAIN_1", value = 30 },
|
||||
MAIN_2 = { name = "MAIN_2", value = 31 },
|
||||
MAIN_3 = { name = "MAIN_3", value = 32 },
|
||||
MAIN_4 = { name = "MAIN_4", value = 33 },
|
||||
MAIN_5 = { name = "MAIN_5", value = 34 },
|
||||
MAIN_6 = { name = "MAIN_6", value = 35 },
|
||||
MAIN_7 = { name = "MAIN_7", value = 36 },
|
||||
MAIN_8 = { name = "MAIN_8", value = 37 },
|
||||
MAIN_9 = { name = "MAIN_9", value = 38 },
|
||||
MAIN_0 = { name = "MAIN_0", value = 39 },
|
||||
RETURN = { name = "RETURN", value = 40 },
|
||||
ESCAPE = { name = "ESCAPE", value = 41 },
|
||||
BACKSPACE = { name = "BACKSPACE", value = 42 },
|
||||
TAB = { name = "TAB", value = 43 },
|
||||
SPACE = { name = "SPACE", value = 44 },
|
||||
MINUS = { name = "MINUS", value = 45 },
|
||||
EQUALS = { name = "EQUALS", value = 46 },
|
||||
LEFTBRACKET = { name = "LEFTBRACKET", value = 47 },
|
||||
RIGHTBRACKET = { name = "RIGHTBRACKET", value = 48 },
|
||||
BACKSLASH = { name = "BACKSLASH", value = 49 },
|
||||
NONUSHASH = { name = "NONUSHASH", value = 50 },
|
||||
SEMICOLON = { name = "SEMICOLON", value = 51 },
|
||||
APOSTROPHE = { name = "APOSTROPHE", value = 52 },
|
||||
GRAVE = { name = "GRAVE", value = 53 },
|
||||
COMMA = { name = "COMMA", value = 54 },
|
||||
PERIOD = { name = "PERIOD", value = 55 },
|
||||
SLASH = { name = "SLASH", value = 56 },
|
||||
CAPSLOCK = { name = "CAPSLOCK", value = 57 },
|
||||
F1 = { name = "F1", value = 58 },
|
||||
F2 = { name = "F2", value = 59 },
|
||||
F3 = { name = "F3", value = 60 },
|
||||
F4 = { name = "F4", value = 61 },
|
||||
F5 = { name = "F5", value = 62 },
|
||||
F6 = { name = "F6", value = 63 },
|
||||
F7 = { name = "F7", value = 64 },
|
||||
F8 = { name = "F8", value = 65 },
|
||||
F9 = { name = "F9", value = 66 },
|
||||
F10 = { name = "F10", value = 67 },
|
||||
F11 = { name = "F11", value = 68 },
|
||||
F12 = { name = "F12", value = 69 },
|
||||
PRINTSCREEN = { name = "PRINTSCREEN", value = 70 },
|
||||
SCROLLLOCK = { name = "SCROLLLOCK", value = 71 },
|
||||
PAUSE = { name = "PAUSE", value = 72 },
|
||||
INSERT = { name = "INSERT", value = 73 },
|
||||
HOME = { name = "HOME", value = 74 },
|
||||
PAGEUP = { name = "PAGEUP", value = 75 },
|
||||
DELETE = { name = "DELETE", value = 76 },
|
||||
END = { name = "END", value = 77 },
|
||||
PAGEDOWN = { name = "PAGEDOWN", value = 78 },
|
||||
RIGHT = { name = "RIGHT", value = 79 },
|
||||
LEFT = { name = "LEFT", value = 80 },
|
||||
DOWN = { name = "DOWN", value = 81 },
|
||||
UP = { name = "UP", value = 82 },
|
||||
NUMLOCKCLEAR = { name = "NUMLOCKCLEAR", value = 83 },
|
||||
KP_DIVIDE = { name = "KP_DIVIDE", value = 84 },
|
||||
KP_MULTIPLY = { name = "KP_MULTIPLY", value = 85 },
|
||||
KP_MINUS = { name = "KP_MINUS", value = 86 },
|
||||
KP_PLUS = { name = "KP_PLUS", value = 87 },
|
||||
KP_ENTER = { name = "KP_ENTER", value = 88 },
|
||||
KP_1 = { name = "KP_1", value = 89 },
|
||||
KP_2 = { name = "KP_2", value = 90 },
|
||||
KP_3 = { name = "KP_3", value = 91 },
|
||||
KP_4 = { name = "KP_4", value = 92 },
|
||||
KP_5 = { name = "KP_5", value = 93 },
|
||||
KP_6 = { name = "KP_6", value = 94 },
|
||||
KP_7 = { name = "KP_7", value = 95 },
|
||||
KP_8 = { name = "KP_8", value = 96 },
|
||||
KP_9 = { name = "KP_9", value = 97 },
|
||||
KP_0 = { name = "KP_0", value = 98 },
|
||||
KP_PERIOD = { name = "KP_PERIOD", value = 99 },
|
||||
NONUSBACKSLASH = { name = "NONUSBACKSLASH", value = 100 },
|
||||
APPLICATION = { name = "APPLICATION", value = 101 },
|
||||
POWER = { name = "POWER", value = 102 },
|
||||
KP_EQUALS = { name = "KP_EQUALS", value = 103 },
|
||||
F13 = { name = "F13", value = 104 },
|
||||
F14 = { name = "F14", value = 105 },
|
||||
F15 = { name = "F15", value = 106 },
|
||||
F16 = { name = "F16", value = 107 },
|
||||
F17 = { name = "F17", value = 108 },
|
||||
F18 = { name = "F18", value = 109 },
|
||||
F19 = { name = "F19", value = 110 },
|
||||
F20 = { name = "F20", value = 111 },
|
||||
F21 = { name = "F21", value = 112 },
|
||||
F22 = { name = "F22", value = 113 },
|
||||
F23 = { name = "F23", value = 114 },
|
||||
F24 = { name = "F24", value = 115 },
|
||||
EXECUTE = { name = "EXECUTE", value = 116 },
|
||||
HELP = { name = "HELP", value = 117 },
|
||||
MENU = { name = "MENU", value = 118 },
|
||||
SELECT = { name = "SELECT", value = 119 },
|
||||
STOP = { name = "STOP", value = 120 },
|
||||
AGAIN = { name = "AGAIN", value = 121 },
|
||||
UNDO = { name = "UNDO", value = 122 },
|
||||
CUT = { name = "CUT", value = 123 },
|
||||
COPY = { name = "COPY", value = 124 },
|
||||
PASTE = { name = "PASTE", value = 125 },
|
||||
FIND = { name = "FIND", value = 126 },
|
||||
MUTE = { name = "MUTE", value = 127 },
|
||||
VOLUMEUP = { name = "VOLUMEUP", value = 128 },
|
||||
VOLUMEDOWN = { name = "VOLUMEDOWN", value = 129 },
|
||||
KP_COMMA = { name = "KP_COMMA", value = 133 },
|
||||
KP_EQUALSAS400 = { name = "KP_EQUALSAS400", value = 134 },
|
||||
INTERNATIONAL1 = { name = "INTERNATIONAL1", value = 135 },
|
||||
INTERNATIONAL2 = { name = "INTERNATIONAL2", value = 136 },
|
||||
INTERNATIONAL3 = { name = "INTERNATIONAL3", value = 137 },
|
||||
INTERNATIONAL4 = { name = "INTERNATIONAL4", value = 138 },
|
||||
INTERNATIONAL5 = { name = "INTERNATIONAL5", value = 139 },
|
||||
INTERNATIONAL6 = { name = "INTERNATIONAL6", value = 140 },
|
||||
INTERNATIONAL7 = { name = "INTERNATIONAL7", value = 141 },
|
||||
INTERNATIONAL8 = { name = "INTERNATIONAL8", value = 142 },
|
||||
INTERNATIONAL9 = { name = "INTERNATIONAL9", value = 143 },
|
||||
LANG1 = { name = "LANG1", value = 144 },
|
||||
LANG2 = { name = "LANG2", value = 145 },
|
||||
LANG3 = { name = "LANG3", value = 146 },
|
||||
LANG4 = { name = "LANG4", value = 147 },
|
||||
LANG5 = { name = "LANG5", value = 148 },
|
||||
LANG6 = { name = "LANG6", value = 149 },
|
||||
LANG7 = { name = "LANG7", value = 150 },
|
||||
LANG8 = { name = "LANG8", value = 151 },
|
||||
LANG9 = { name = "LANG9", value = 152 },
|
||||
ALTERASE = { name = "ALTERASE", value = 153 },
|
||||
SYSREQ = { name = "SYSREQ", value = 154 },
|
||||
CANCEL = { name = "CANCEL", value = 155 },
|
||||
CLEAR = { name = "CLEAR", value = 156 },
|
||||
PRIOR = { name = "PRIOR", value = 157 },
|
||||
RETURN2 = { name = "RETURN2", value = 158 },
|
||||
SEPARATOR = { name = "SEPARATOR", value = 159 },
|
||||
OUT = { name = "OUT", value = 160 },
|
||||
OPER = { name = "OPER", value = 161 },
|
||||
CLEARAGAIN = { name = "CLEARAGAIN", value = 162 },
|
||||
CRSEL = { name = "CRSEL", value = 163 },
|
||||
EXSEL = { name = "EXSEL", value = 164 },
|
||||
KP_00 = { name = "KP_00", value = 176 },
|
||||
KP_000 = { name = "KP_000", value = 177 },
|
||||
THOUSANDSSEPARATOR = { name = "THOUSANDSSEPARATOR", value = 178 },
|
||||
DECIMALSEPARATOR = { name = "DECIMALSEPARATOR", value = 179 },
|
||||
CURRENCYUNIT = { name = "CURRENCYUNIT", value = 180 },
|
||||
CURRENCYSUBUNIT = { name = "CURRENCYSUBUNIT", value = 181 },
|
||||
KP_LEFTPAREN = { name = "KP_LEFTPAREN", value = 182 },
|
||||
KP_RIGHTPAREN = { name = "KP_RIGHTPAREN", value = 183 },
|
||||
KP_LEFTBRACE = { name = "KP_LEFTBRACE", value = 184 },
|
||||
KP_RIGHTBRACE = { name = "KP_RIGHTBRACE", value = 185 },
|
||||
KP_TAB = { name = "KP_TAB", value = 186 },
|
||||
KP_BACKSPACE = { name = "KP_BACKSPACE", value = 187 },
|
||||
KP_A = { name = "KP_A", value = 188 },
|
||||
KP_B = { name = "KP_B", value = 189 },
|
||||
KP_C = { name = "KP_C", value = 190 },
|
||||
KP_D = { name = "KP_D", value = 191 },
|
||||
KP_E = { name = "KP_E", value = 192 },
|
||||
KP_F = { name = "KP_F", value = 193 },
|
||||
KP_XOR = { name = "KP_XOR", value = 194 },
|
||||
KP_POWER = { name = "KP_POWER", value = 195 },
|
||||
KP_PERCENT = { name = "KP_PERCENT", value = 196 },
|
||||
KP_LESS = { name = "KP_LESS", value = 197 },
|
||||
KP_GREATER = { name = "KP_GREATER", value = 198 },
|
||||
KP_AMPERSAND = { name = "KP_AMPERSAND", value = 199 },
|
||||
KP_DBLAMPERSAND = { name = "KP_DBLAMPERSAND", value = 200 },
|
||||
KP_VERTICALBAR = { name = "KP_VERTICALBAR", value = 201 },
|
||||
KP_DBLVERTICALBAR = { name = "KP_DBLVERTICALBAR", value = 202 },
|
||||
KP_COLON = { name = "KP_COLON", value = 203 },
|
||||
KP_HASH = { name = "KP_HASH", value = 204 },
|
||||
KP_SPACE = { name = "KP_SPACE", value = 205 },
|
||||
KP_AT = { name = "KP_AT", value = 206 },
|
||||
KP_EXCLAM = { name = "KP_EXCLAM", value = 207 },
|
||||
KP_MEMSTORE = { name = "KP_MEMSTORE", value = 208 },
|
||||
KP_MEMRECALL = { name = "KP_MEMRECALL", value = 209 },
|
||||
KP_MEMCLEAR = { name = "KP_MEMCLEAR", value = 210 },
|
||||
KP_MEMADD = { name = "KP_MEMADD", value = 211 },
|
||||
KP_MEMSUBTRACT = { name = "KP_MEMSUBTRACT", value = 212 },
|
||||
KP_MEMMULTIPLY = { name = "KP_MEMMULTIPLY", value = 213 },
|
||||
KP_MEMDIVIDE = { name = "KP_MEMDIVIDE", value = 214 },
|
||||
KP_PLUSMINUS = { name = "KP_PLUSMINUS", value = 215 },
|
||||
KP_CLEAR = { name = "KP_CLEAR", value = 216 },
|
||||
KP_CLEARENTRY = { name = "KP_CLEARENTRY", value = 217 },
|
||||
KP_BINARY = { name = "KP_BINARY", value = 218 },
|
||||
KP_OCTAL = { name = "KP_OCTAL", value = 219 },
|
||||
KP_DECIMAL = { name = "KP_DECIMAL", value = 220 },
|
||||
KP_HEXADECIMAL = { name = "KP_HEXADECIMAL", value = 221 },
|
||||
LCTRL = { name = "LCTRL", value = 224 },
|
||||
LSHIFT = { name = "LSHIFT", value = 225 },
|
||||
LALT = { name = "LALT", value = 226 },
|
||||
LGUI = { name = "LGUI", value = 227 },
|
||||
RCTRL = { name = "RCTRL", value = 228 },
|
||||
RSHIFT = { name = "RSHIFT", value = 229 },
|
||||
RALT = { name = "RALT", value = 230 },
|
||||
RGUI = { name = "RGUI", value = 231 },
|
||||
MODE = { name = "MODE", value = 257 },
|
||||
AUDIONEXT = { name = "AUDIONEXT", value = 258 },
|
||||
AUDIOPREV = { name = "AUDIOPREV", value = 259 },
|
||||
AUDIOSTOP = { name = "AUDIOSTOP", value = 260 },
|
||||
AUDIOPLAY = { name = "AUDIOPLAY", value = 261 },
|
||||
AUDIOMUTE = { name = "AUDIOMUTE", value = 262 },
|
||||
MEDIASELECT = { name = "MEDIASELECT", value = 263 },
|
||||
WWW = { name = "WWW", value = 264 },
|
||||
MAIL = { name = "MAIL", value = 265 },
|
||||
CALCULATOR = { name = "CALCULATOR", value = 266 },
|
||||
COMPUTER = { name = "COMPUTER", value = 267 },
|
||||
AC_SEARCH = { name = "AC_SEARCH", value = 268 },
|
||||
AC_HOME = { name = "AC_HOME", value = 269 },
|
||||
AC_BACK = { name = "AC_BACK", value = 270 },
|
||||
AC_FORWARD = { name = "AC_FORWARD", value = 271 },
|
||||
AC_STOP = { name = "AC_STOP", value = 272 },
|
||||
AC_REFRESH = { name = "AC_REFRESH", value = 273 },
|
||||
AC_BOOKMARKS = { name = "AC_BOOKMARKS", value = 274 },
|
||||
BRIGHTNESSDOWN = { name = "BRIGHTNESSDOWN", value = 275 },
|
||||
BRIGHTNESSUP = { name = "BRIGHTNESSUP", value = 276 },
|
||||
DISPLAYSWITCH = { name = "DISPLAYSWITCH", value = 277 },
|
||||
KBDILLUMTOGGLE = { name = "KBDILLUMTOGGLE", value = 278 },
|
||||
KBDILLUMDOWN = { name = "KBDILLUMDOWN", value = 279 },
|
||||
KBDILLUMUP = { name = "KBDILLUMUP", value = 280 },
|
||||
EJECT = { name = "EJECT", value = 281 },
|
||||
SLEEP = { name = "SLEEP", value = 282 },
|
||||
APP1 = { name = "APP1", value = 283 },
|
||||
APP2 = { name = "APP2", value = 284 },
|
||||
AUDIOREWIND = { name = "AUDIOREWIND", value = 285 },
|
||||
AUDIOFASTFORWARD = { name = "AUDIOFASTFORWARD", value = 286 }
|
||||
}
|
||||
|
||||
SCANCODE_MIN = 4 -- Lowest value
|
||||
SCANCODE_MAX = 286 -- Highest value, not the number of items in the table.
|
||||
|
||||
MODIFIER = {
|
||||
NONE = { name = "NONE", value = 0x0000 },
|
||||
LSHIFT = { name = "LSHIFT", value = 0x0001 },
|
||||
RSHIFT = { name = "RSHIFT", value = 0x0002 },
|
||||
LCTRL = { name = "LCTRL", value = 0x0040 },
|
||||
RCTRL = { name = "RCTRL", value = 0x0080 },
|
||||
LALT = { name = "LALT", value = 0x0100 },
|
||||
RALT = { name = "RALT", value = 0x0200 },
|
||||
LGUI = { name = "LGUI", value = 0x0400 },
|
||||
RGUI = { name = "RGUI", value = 0x0800 },
|
||||
NUM = { name = "NUM", value = 0x1000 },
|
||||
CAPS = { name = "CAPS", value = 0x2000 },
|
||||
MODE = { name = "MODE", value = 0x4000 },
|
||||
SCROLL = { name = "SCROLL", value = 0x8000 },
|
||||
|
||||
SHIFT = { name = "SHIFT", value = 0x0001 + 0x0002 },
|
||||
CTRL = { name = "CTRL", value = 0x0040 + 0x0080 },
|
||||
ALT = { name = "ALT", value = 0x0100 + 0x0200 },
|
||||
GUI = { name = "GUI", value = 0x0400 + 0x0800 }
|
||||
}
|
||||
|
||||
GAMEPAD_0 = {
|
||||
AXIS_LEFT_X = { name = "AXIS_LEFT_X", value = 500 },
|
||||
AXIS_LEFT_X_L = { name = "AXIS_LEFT_X_L", value = 501 },
|
||||
AXIS_LEFT_X_R = { name = "AXIS_LEFT_X_R", value = 502 },
|
||||
AXIS_LEFT_Y = { name = "AXIS_LEFT_Y", value = 503 },
|
||||
AXIS_LEFT_Y_U = { name = "AXIS_LEFT_Y_U", value = 504 },
|
||||
AXIS_LEFT_Y_D = { name = "AXIS_LEFT_Y_D", value = 505 },
|
||||
AXIS_RIGHT_X = { name = "AXIS_RIGHT_X", value = 506 },
|
||||
AXIS_RIGHT_X_L = { name = "AXIS_RIGHT_X_L", value = 507 },
|
||||
AXIS_RIGHT_X_R = { name = "AXIS_RIGHT_X_R", value = 508 },
|
||||
AXIS_RIGHT_Y = { name = "AXIS_RIGHT_Y", value = 509 },
|
||||
AXIS_RIGHT_Y_U = { name = "AXIS_RIGHT_Y_U", value = 510 },
|
||||
AXIS_RIGHT_Y_D = { name = "AXIS_RIGHT_Y_D", value = 511 },
|
||||
AXIS_LEFT_TRIGGER = { name = "AXIS_LEFT_TRIGGER", value = 512 },
|
||||
AXIS_LEFT_TRIGGER_N = { name = "AXIS_LEFT_TRIGGER_N", value = 513 },
|
||||
AXIS_LEFT_TRIGGER_P = { name = "AXIS_LEFT_TRIGGER_P", value = 514 },
|
||||
AXIS_RIGHT_TRIGGER = { name = "AXIS_RIGHT_TRIGGER", value = 515 },
|
||||
AXIS_RIGHT_TRIGGER_N = { name = "AXIS_RIGHT_TRIGGER_N", value = 516 },
|
||||
AXIS_RIGHT_TRIGGER_P = { name = "AXIS_RIGHT_TRIGGER_P", value = 517 },
|
||||
BUTTON_A = { name = "BUTTON_A", value = 518 },
|
||||
BUTTON_B = { name = "BUTTON_B", value = 519 },
|
||||
BUTTON_X = { name = "BUTTON_X", value = 520 },
|
||||
BUTTON_Y = { name = "BUTTON_Y", value = 521 },
|
||||
BUTTON_BACK = { name = "BUTTON_BACK", value = 522 },
|
||||
BUTTON_GUIDE = { name = "BUTTON_GUIDE", value = 523 },
|
||||
BUTTON_START = { name = "BUTTON_START", value = 524 },
|
||||
BUTTON_LEFT_STICK = { name = "BUTTON_LEFT_STICK", value = 525 },
|
||||
BUTTON_RIGHT_STICK = { name = "BUTTON_RIGHT_STICK", value = 526 },
|
||||
BUTTON_LEFT_BUMPER = { name = "BUTTON_LEFT_BUMPER", value = 527 },
|
||||
BUTTON_RIGHT_BUMPER = { name = "BUTTON_RIGHT_BUMPER", value = 528 },
|
||||
DPAD_UP = { name = "DPAD_UP", value = 529 },
|
||||
DPAD_DOWN = { name = "DPAD_DOWN", value = 530 },
|
||||
DPAD_LEFT = { name = "DPAD_LEFT", value = 531 },
|
||||
DPAD_RIGHT = { name = "DPAD_RIGHT", value = 532 }
|
||||
}
|
||||
|
||||
GAMEPAD_0_MIN = 500 -- Lowest value
|
||||
GAMEPAD_0_MAX = 532 -- Highest value, not the number of items in the table.
|
||||
|
||||
GAMEPAD_1 = utilDeepCopy(GAMEPAD_0)
|
||||
GAMEPAD_2 = utilDeepCopy(GAMEPAD_0)
|
||||
GAMEPAD_3 = utilDeepCopy(GAMEPAD_0)
|
||||
|
||||
for key, value in pairs(GAMEPAD_0) do
|
||||
GAMEPAD_1[key].value = GAMEPAD_1[key].value + 100
|
||||
GAMEPAD_2[key].value = GAMEPAD_2[key].value + 200
|
||||
GAMEPAD_3[key].value = GAMEPAD_3[key].value + 300
|
||||
end
|
||||
|
||||
GAMEPAD_1_MIN = GAMEPAD_0_MAX + 100
|
||||
GAMEPAD_1_MAX = GAMEPAD_0_MAX + 100
|
||||
|
||||
GAMEPAD_2_MIN = GAMEPAD_0_MAX + 200
|
||||
GAMEPAD_2_MAX = GAMEPAD_0_MAX + 200
|
||||
|
||||
GAMEPAD_3_MIN = GAMEPAD_0_MAX + 300
|
||||
GAMEPAD_3_MAX = GAMEPAD_0_MAX + 300
|
||||
|
||||
GAMEPAD_AXIS_LEFT_X = 0
|
||||
GAMEPAD_AXIS_LEFT_Y = 1
|
||||
GAMEPAD_AXIS_RIGHT_X = 2
|
||||
GAMEPAD_AXIS_RIGHT_Y = 3
|
||||
GAMEPAD_AXIS_LEFT_TRIGGER = 4
|
||||
GAMEPAD_AXIS_RIGHT_TRIGGER = 5
|
||||
|
||||
MOUSE_0 = {
|
||||
BUTTON_LEFT = { name = "BUTTON_LEFT", value = 1000 },
|
||||
BUTTON_RIGHT = { name = "BUTTON_RIGHT", value = 1001 },
|
||||
BUTTON_MIDDLE = { name = "BUTTON_MIDDLE", value = 1002 },
|
||||
BUTTON_X1 = { name = "BUTTON_X1", value = 1003 },
|
||||
BUTTON_X2 = { name = "BUTTON_X2", value = 1004 },
|
||||
WHEEL_UP = { name = "WHEEL_UP", value = 1005 },
|
||||
WHEEL_DOWN = { name = "WHEEL_DOWN", value = 1006 }
|
||||
}
|
||||
|
||||
MOUSE_0_MIN = 1000
|
||||
MOUSE_0_MAX = 1006
|
||||
|
||||
MOUSE_1 = utilDeepCopy(MOUSE_0)
|
||||
MOUSE_2 = utilDeepCopy(MOUSE_0)
|
||||
MOUSE_3 = utilDeepCopy(MOUSE_0)
|
||||
|
||||
for key, value in pairs(MOUSE_0) do
|
||||
MOUSE_1[key].value = MOUSE_1[key].value + 100
|
||||
MOUSE_2[key].value = MOUSE_2[key].value + 200
|
||||
MOUSE_3[key].value = MOUSE_3[key].value + 300
|
||||
end
|
||||
|
||||
MOUSE_1_MIN = MOUSE_0_MAX + 100
|
||||
MOUSE_1_MAX = MOUSE_0_MAX + 100
|
||||
|
||||
MOUSE_2_MIN = MOUSE_0_MAX + 200
|
||||
MOUSE_2_MAX = MOUSE_0_MAX + 200
|
||||
|
||||
MOUSE_3_MIN = MOUSE_0_MAX + 300
|
||||
MOUSE_3_MAX = MOUSE_0_MAX + 300
|
||||
|
||||
SWITCH_BUTTON4 = 21
|
||||
SWITCH_TILT = 22
|
||||
SWITCH_GRAB = 23
|
||||
|
||||
MOUSE_SINGLE = 100
|
||||
MOUSE_MANY = 200
|
||||
|
||||
RENDER_SMOOTH = 1
|
||||
RENDER_PIXELATED = 0
|
||||
|
||||
if videoGetLanguageDescription ~= nil then
|
||||
discGetLanguageDescription = videoGetLanguageDescription
|
||||
end
|
||||
|
||||
|
||||
-- Singe 1.xx Features -------------------------------------------------------
|
||||
|
||||
|
||||
if discSetFPS ~= nil then
|
||||
discSetFPS(29.97)
|
||||
discSearch(1)
|
||||
end
|
||||
|
||||
SWITCH_UP = 0
|
||||
SWITCH_LEFT = 1
|
||||
SWITCH_DOWN = 2
|
||||
SWITCH_RIGHT = 3
|
||||
SWITCH_START1 = 4
|
||||
SWITCH_START2 = 5
|
||||
SWITCH_BUTTON1 = 6
|
||||
SWITCH_BUTTON2 = 7
|
||||
SWITCH_BUTTON3 = 8
|
||||
SWITCH_COIN1 = 9
|
||||
SWITCH_COIN2 = 10
|
||||
SWITCH_SKILL1 = 11
|
||||
SWITCH_SKILL2 = 12
|
||||
SWITCH_SKILL3 = 13
|
||||
SWITCH_SERVICE = 14
|
||||
SWITCH_TEST = 15
|
||||
SWITCH_RESET = 16
|
||||
SWITCH_SCREENSHOT = 17
|
||||
SWITCH_QUIT = 18
|
||||
SWITCH_PAUSE = 19
|
||||
SWITCH_CONSOLE = 20
|
||||
SWITCH_BUTTON4 = 21 -- Added in Singe 2.00
|
||||
SWITCH_TILT = 22 -- Added in Singe 2.00
|
||||
|
||||
FONT_QUALITY_SOLID = 1
|
||||
FONT_QUALITY_SHADED = 2
|
||||
FONT_QUALITY_BLENDED = 3
|
||||
|
||||
SOUND_ERROR_INVALID = -1
|
||||
SOUND_REMOVE_HANDLE = -1
|
||||
SOUND_ERROR_FULL = -2
|
||||
|
||||
OVERLAY_NOT_UPDATED = 0
|
||||
OVERLAY_UPDATED = 1
|
||||
|
||||
SINGLE_MOUSE = 100
|
||||
MANY_MOUSE = 200
|
||||
|
||||
MODE_NORMAL = 0
|
||||
MODE_FULL = 1
|
||||
|
||||
-- Make old random number calls still work
|
||||
random = {}
|
||||
random.new = math.random
|
||||
|
||||
-- Map old Daphne calls to Singe calls
|
||||
if singeGetHeight ~= nil then
|
||||
daphneGetHeight = singeGetHeight
|
||||
daphneGetWidth = singeGetWidth
|
||||
daphneScreenshot = singeScreenshot
|
||||
end
|
||||
|
||||
|
||||
-- Singe 2.10 Threaded Application Support ------------------------------------
|
||||
|
||||
|
||||
if singeMain ~= nil then
|
||||
onOverlayUpdate = function()
|
||||
coroutine.resume(SINGE_SELF)
|
||||
return(OVERLAY_UPDATED)
|
||||
end
|
||||
singeYield = coroutine.yield
|
||||
SINGE_SELF = coroutine.create(singeMain)
|
||||
end
|
||||
|
||||
|
BIN
assets/FreeSansBold.ttf
(Stored with Git LFS)
BIN
assets/FreeSansBold.ttf
(Stored with Git LFS)
Binary file not shown.
2467
assets/Manual.lyx
2467
assets/Manual.lyx
File diff suppressed because it is too large
Load diff
|
@ -1,380 +0,0 @@
|
|||
--[[
|
||||
*
|
||||
* Singe 2
|
||||
* Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
--]]
|
||||
|
||||
|
||||
dofile("Singe/Framework.singe")
|
||||
|
||||
lfs = require("lfs")
|
||||
|
||||
|
||||
function cleanTitle(a)
|
||||
local output = string.lower(a)
|
||||
output = string.gsub(output, '%p', ' ')
|
||||
output = string.gsub(output, '^ +', '')
|
||||
output = string.gsub(output, '^the ', '')
|
||||
output = string.gsub(output, '^a ', '')
|
||||
output = string.gsub(output, '^an ', '')
|
||||
return output
|
||||
end
|
||||
|
||||
|
||||
function compareTitles(a, b)
|
||||
return cleanTitle(a.TITLE) < cleanTitle(b.TITLE)
|
||||
end
|
||||
|
||||
|
||||
function loadGameAssets()
|
||||
|
||||
SPRITE_CABINET = spriteLoad(GAME_LIST[GAME_SELECTED].CABINET)
|
||||
SPRITE_MARQUEE = spriteLoad(GAME_LIST[GAME_SELECTED].MARQUEE)
|
||||
VIDEO_ATTRACT = videoLoad(GAME_LIST[GAME_SELECTED].ATTRACT)
|
||||
if GAME_LIST[GAME_SELECTED].AUDIO_TRACK then
|
||||
videoSetAudioTrack(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].AUDIO_TRACK)
|
||||
end
|
||||
videoPlay(VIDEO_ATTRACT)
|
||||
videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START)
|
||||
-- videoSetVolume(VIDEO_ATTRACT, 0, 0)
|
||||
|
||||
-- Build text sprites
|
||||
local textBox = GAME_LIST[GAME_SELECTED].DESCRIPTION .. WRAP_BREAK .. WRAP_BREAK ..
|
||||
"Year: " .. GAME_LIST[GAME_SELECTED].YEAR .. WRAP_BREAK ..
|
||||
"Genre: " .. GAME_LIST[GAME_SELECTED].GENRE .. WRAP_BREAK ..
|
||||
"Platform: " .. GAME_LIST[GAME_SELECTED].PLATFORM .. WRAP_BREAK ..
|
||||
"Developer: " .. GAME_LIST[GAME_SELECTED].DEVELOPER .. WRAP_BREAK ..
|
||||
"Publisher: " .. GAME_LIST[GAME_SELECTED].PUBLISHER .. WRAP_BREAK .. WRAP_BREAK ..
|
||||
"Singe Port: " .. GAME_LIST[GAME_SELECTED].CREATOR .. WRAP_BREAK ..
|
||||
"Source: " .. GAME_LIST[GAME_SELECTED].SOURCE
|
||||
wrapText(textBox, TEXT_W)
|
||||
|
||||
TEXT_LINE_COUNT = utilGetTableSize(TEXT_SPRITE_LIST)
|
||||
TEXT_LINE_TOP = 1
|
||||
|
||||
end
|
||||
|
||||
|
||||
function onInputPressed(what)
|
||||
|
||||
-- Are we displaying the grid background?
|
||||
if (discGetFrame() >= DISC_GRID_START) then
|
||||
|
||||
if what == SWITCH_UP then
|
||||
if TEXT_LINE_TOP > 1 then
|
||||
TEXT_LINE_TOP = TEXT_LINE_TOP - 1
|
||||
end
|
||||
end
|
||||
|
||||
if what == SWITCH_DOWN then
|
||||
if TEXT_LINE_TOP < TEXT_LINE_COUNT - TEXT_LINE_LIMIT + 1 then
|
||||
TEXT_LINE_TOP = TEXT_LINE_TOP + 1
|
||||
end
|
||||
end
|
||||
|
||||
if what == SWITCH_LEFT then
|
||||
GAME_SELECTED = GAME_SELECTED - 1
|
||||
if GAME_SELECTED < 1 then
|
||||
GAME_SELECTED = GAME_COUNT
|
||||
end
|
||||
unloadGameAssets()
|
||||
loadGameAssets()
|
||||
end
|
||||
|
||||
if what == SWITCH_RIGHT then
|
||||
GAME_SELECTED = GAME_SELECTED + 1
|
||||
if GAME_SELECTED > GAME_COUNT then
|
||||
GAME_SELECTED = 1
|
||||
end
|
||||
unloadGameAssets()
|
||||
loadGameAssets()
|
||||
end
|
||||
|
||||
if what == SWITCH_START1 or what == SWITCH_START2 or what == SWITCH_BUTTON1 or what == SWITCH_BUTTON2 or what == SWITCH_BUTTON3 or what == SWITCH_BUTTON4 then
|
||||
-- Start next game
|
||||
SHUTDOWN_FROM_PUSH = true
|
||||
scriptPush(GAME_LIST[GAME_SELECTED])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function onOverlayUpdate()
|
||||
|
||||
local x = 0
|
||||
local y = 0
|
||||
local c = 0
|
||||
local t = 0
|
||||
|
||||
overlayClear()
|
||||
|
||||
-- Are we displaying the grid background?
|
||||
if (discGetFrame() >= DISC_GRID_START) then
|
||||
|
||||
-- Cabinet image
|
||||
x = CABINET_X + (CABINET_W - spriteGetWidth(SPRITE_CABINET)) * 0.5
|
||||
y = CABINET_Y + (CABINET_H - spriteGetHeight(SPRITE_CABINET)) * 0.5
|
||||
spriteDraw(x, y, SPRITE_CABINET)
|
||||
|
||||
-- Marquee Image
|
||||
x = MARQUEE_X + (MARQUEE_W - spriteGetWidth(SPRITE_MARQUEE)) * 0.5
|
||||
y = MARQUEE_Y + (MARQUEE_H - spriteGetHeight(SPRITE_MARQUEE)) * 0.5
|
||||
spriteDraw(x, y, SPRITE_MARQUEE)
|
||||
|
||||
-- Attract Mode Video
|
||||
videoDraw(VIDEO_ATTRACT, VIDEO_X, VIDEO_Y, VIDEO_X + VIDEO_W, VIDEO_Y + VIDEO_H)
|
||||
if videoGetFrame(VIDEO_ATTRACT) > GAME_LIST[GAME_SELECTED].ATTRACT_END then
|
||||
videoSeek(VIDEO_ATTRACT, GAME_LIST[GAME_SELECTED].ATTRACT_START)
|
||||
end
|
||||
|
||||
-- Game Description
|
||||
colorForeground(255, 255, 255, 255)
|
||||
y = TEXT_Y
|
||||
c = 0
|
||||
t = 1
|
||||
for _, handle in ipairs(TEXT_SPRITE_LIST) do
|
||||
-- Find height of font and number of lines that fit
|
||||
if TEXT_LINE_HEIGHT == 0 then
|
||||
if (handle >= 0) then
|
||||
TEXT_LINE_HEIGHT = spriteGetHeight(handle)
|
||||
TEXT_LINE_LIMIT = math.floor(TEXT_H / TEXT_LINE_HEIGHT)
|
||||
end
|
||||
end
|
||||
-- Only display what is visible in the window
|
||||
if (t >= TEXT_LINE_TOP) then
|
||||
if (c < TEXT_LINE_LIMIT) then
|
||||
if (handle >= 0) then
|
||||
spriteDraw(TEXT_X, y, handle)
|
||||
end
|
||||
y = y + TEXT_LINE_HEIGHT + 1
|
||||
c = c + 1
|
||||
end
|
||||
end
|
||||
t = t + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Loop video?
|
||||
if (discGetFrame() >= DISC_LAST_FRAME) then
|
||||
discSkipToFrame(DISC_GRID_START)
|
||||
end
|
||||
|
||||
return(OVERLAY_UPDATED)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function onShutdown()
|
||||
unloadGameAssets()
|
||||
saveConfig(not SHUTDOWN_FROM_PUSH)
|
||||
end
|
||||
|
||||
|
||||
function saveConfig(showIntro)
|
||||
if GAME_COUNT > 0 then
|
||||
-- Save what game we're currently viewing
|
||||
local cfg = io.open(CONFIG_FILE, "w")
|
||||
cfg:write("GAME_SELECTED = " .. GAME_SELECTED .. "\n")
|
||||
cfg:write("SHOW_INTRO = " .. tostring(showIntro) .. "\n")
|
||||
cfg:close()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function unloadGameAssets()
|
||||
spriteUnload(SPRITE_CABINET)
|
||||
spriteUnload(SPRITE_MARQUEE)
|
||||
videoUnload(VIDEO_ATTRACT)
|
||||
for _, handle in ipairs(TEXT_SPRITE_LIST) do
|
||||
if handle >= 0 then
|
||||
spriteUnload(handle)
|
||||
end
|
||||
end
|
||||
TEXT_SPRITE_LIST = {}
|
||||
end
|
||||
|
||||
|
||||
function wrapText(text, maxWidth)
|
||||
local words = {}
|
||||
local toWrap = ""
|
||||
local line = ""
|
||||
local lastLine = ""
|
||||
local fragment = ""
|
||||
local doBreak = false
|
||||
local spriteTemp = -1
|
||||
local trimBreak = utilTrim(WRAP_BREAK)
|
||||
|
||||
-- Break input into words
|
||||
toWrap = text .. WRAP_BREAK
|
||||
for w in toWrap:gmatch("%S+") do
|
||||
words[#words+1] = w
|
||||
end
|
||||
|
||||
-- Iterate over words and try to fit them in the space given
|
||||
for _, word in ipairs(words) do
|
||||
|
||||
-- Is this an intentional break?
|
||||
if word == trimBreak then
|
||||
doBreak = true
|
||||
else
|
||||
-- Add this word to the line
|
||||
line = utilTrim(line .. " " .. word)
|
||||
-- Do we even have text?
|
||||
if string.len(line) > 0 then
|
||||
-- Is the line too long to fit now?
|
||||
spriteTemp = fontToSprite(line)
|
||||
if spriteGetWidth(spriteTemp) > maxWidth then
|
||||
doBreak = true
|
||||
fragment = word
|
||||
line = lastLine
|
||||
else
|
||||
fragment = ""
|
||||
end
|
||||
spriteUnload(spriteTemp)
|
||||
end
|
||||
end
|
||||
lastLine = line
|
||||
|
||||
-- Did we find a break?
|
||||
if doBreak then
|
||||
-- Did we get anything to print?
|
||||
if string.len(line) > 0 then
|
||||
table.insert(TEXT_SPRITE_LIST, fontToSprite(line))
|
||||
else
|
||||
-- Blank line
|
||||
table.insert(TEXT_SPRITE_LIST, -1)
|
||||
end
|
||||
-- Reset for next line
|
||||
line = fragment
|
||||
fragment = ""
|
||||
doBreak = false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Search for games.dat files in subdirectories
|
||||
GAME_LIST = {}
|
||||
GAME_COUNT = 0
|
||||
for dir in lfs.dir(".") do
|
||||
if dir ~= "." and dir ~= ".." then
|
||||
local dirattr = lfs.attributes(dir)
|
||||
if dirattr.mode == "directory" then
|
||||
for file in lfs.dir(dir .. "/.") do
|
||||
if file == "games.dat" then
|
||||
-- Load games.dat
|
||||
dofile(dir .. "/games.dat")
|
||||
for key,value in pairs(GAMES) do
|
||||
table.insert(GAME_LIST, value)
|
||||
GAME_COUNT = GAME_COUNT + 1
|
||||
end
|
||||
GAMES = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.sort(GAME_LIST, compareTitles)
|
||||
|
||||
if GAME_COUNT == 0 then
|
||||
debugPrint("No games found! Exiting.")
|
||||
singeQuit()
|
||||
else
|
||||
overlaySetResolution(vldpGetWidth(), vldpGetHeight())
|
||||
|
||||
freeSans18 = fontLoad("Singe/FreeSansBold.ttf", 18)
|
||||
fontQuality(FONT_QUALITY_BLENDED)
|
||||
fontSelect(freeSans18)
|
||||
|
||||
DISC_GRID_START = 180
|
||||
DISC_LAST_FRAME = 359
|
||||
|
||||
MARGIN_X = 25
|
||||
MARGIN_Y = 25
|
||||
|
||||
VIDEO_W = 320
|
||||
VIDEO_H = 200
|
||||
|
||||
MARQUEE_H = 75
|
||||
|
||||
MARQUEE_W = VIDEO_W
|
||||
MARQUEE_X = overlayGetWidth() - MARGIN_X - MARQUEE_W
|
||||
MARQUEE_Y = MARGIN_Y
|
||||
|
||||
VIDEO_X = overlayGetWidth() - MARGIN_X - VIDEO_W
|
||||
VIDEO_Y = MARGIN_Y + MARQUEE_H + MARGIN_Y
|
||||
|
||||
TEXT_W = VIDEO_W
|
||||
TEXT_X = overlayGetWidth() - MARGIN_X - TEXT_W
|
||||
TEXT_Y = VIDEO_Y + VIDEO_H + MARGIN_Y
|
||||
TEXT_H = overlayGetHeight() - MARGIN_Y - TEXT_Y
|
||||
|
||||
CABINET_X = MARGIN_X
|
||||
CABINET_Y = MARGIN_Y
|
||||
CABINET_W = VIDEO_X - MARGIN_X - CABINET_X
|
||||
CABINET_H = overlayGetHeight() - MARGIN_Y - CABINET_Y
|
||||
|
||||
--[[
|
||||
Cabinet is 325x430
|
||||
Marquee is 320x75
|
||||
Video is 320x200
|
||||
Text is 320x105
|
||||
--]]
|
||||
--[[
|
||||
debugPrint("Cabinet is " .. CABINET_W .. "x" .. CABINET_H)
|
||||
debugPrint("Marquee is " .. MARQUEE_W .. "x" .. MARQUEE_H)
|
||||
debugPrint(" Video is " .. VIDEO_W .. "x" .. VIDEO_H)
|
||||
debugPrint(" Text is " .. TEXT_W .. "x" .. TEXT_H)
|
||||
--]]
|
||||
|
||||
WRAP_BREAK = " [!wb!] "
|
||||
TEXT_LINE_TOP = 1
|
||||
TEXT_LINE_LIMIT = 0
|
||||
TEXT_LINE_COUNT = 0
|
||||
TEXT_LINE_HEIGHT = 0
|
||||
TEXT_SPRITE_LIST = {}
|
||||
|
||||
SHUTDOWN_FROM_PUSH = false
|
||||
|
||||
-- Load configuration
|
||||
SHOW_INTRO = true
|
||||
CONFIG_FILE = singeGetDataPath() .. "menu.dat"
|
||||
local confattr = lfs.attributes(CONFIG_FILE)
|
||||
if confattr then
|
||||
dofile(CONFIG_FILE)
|
||||
if GAME_SELECTED > GAME_COUNT then
|
||||
GAME_SELECTED = GAME_COUNT
|
||||
end
|
||||
else
|
||||
GAME_SELECTED = 1
|
||||
end
|
||||
|
||||
discPlay()
|
||||
if (not SHOW_INTRO) then
|
||||
discSkipToFrame(DISC_GRID_START)
|
||||
end
|
||||
|
||||
-- Prime the pump
|
||||
loadGameAssets()
|
||||
end
|
|
@ -1,117 +0,0 @@
|
|||
--[[
|
||||
*
|
||||
* Singe 2
|
||||
* Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
--]]
|
||||
|
||||
|
||||
local socket = require("socket")
|
||||
local copas = require("copas")
|
||||
local https = require("copas.http").request
|
||||
|
||||
|
||||
dofile("Singe/Framework.singe")
|
||||
|
||||
|
||||
function get(url)
|
||||
local download = {}
|
||||
download.url = url
|
||||
download.finished = false
|
||||
copas.addthread(function(d)
|
||||
d.result, d.error = https(d.url)
|
||||
d.finished = true
|
||||
end,
|
||||
download)
|
||||
return download
|
||||
end
|
||||
|
||||
|
||||
function onInputPressed(what)
|
||||
|
||||
if what == SWITCH_LEFT then
|
||||
discStepBackward()
|
||||
end
|
||||
|
||||
if what == SWITCH_RIGHT then
|
||||
discStepForward()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function onOverlayUpdate()
|
||||
|
||||
copas.step()
|
||||
|
||||
colorBackground(0, 0, 0, 127) -- this dims the background 50%
|
||||
overlayClear()
|
||||
|
||||
overlayPrint(1, 1, dldGameList.url.." "..(dldGameList.finished and 'true' or 'false'))
|
||||
if dldGameList.finished then
|
||||
overlayPrint(1, 2, dldGameList.error)
|
||||
overlayPrint(1, 3, dldGameList.result)
|
||||
end
|
||||
|
||||
colorForeground(255, 0, 0)
|
||||
overlayBox(0, 0, overlayGetWidth() - 1, overlayGetHeight() - 1)
|
||||
|
||||
spriteDraw((overlayGetWidth() - spriteGetWidth(sprServiceMenu)) / 2, 25, sprServiceMenu)
|
||||
|
||||
return(OVERLAY_UPDATED)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function onShutdown()
|
||||
|
||||
spriteUnload(sprServiceMenu)
|
||||
fontUnload(fntSans18)
|
||||
fontUnload(fntSans32)
|
||||
|
||||
end
|
||||
|
||||
|
||||
copas.running = true
|
||||
|
||||
dldGameList = get("https://kangaroopunch.com/api/singeSoftware")
|
||||
|
||||
overlaySetResolution(vldpGetWidth(), vldpGetHeight())
|
||||
|
||||
DISC_SINGE_LOGO = 140
|
||||
|
||||
discSkipToFrame(DISC_SINGE_LOGO)
|
||||
discPause()
|
||||
|
||||
fontQuality(FONT_QUALITY_BLENDED)
|
||||
fntSans18 = fontLoad("Singe/FreeSansBold.ttf", 18)
|
||||
fntSans32 = fontLoad("Singe/FreeSansBold.ttf", 32)
|
||||
|
||||
fontSelect(fntSans32)
|
||||
sprServiceMenu = fontToSprite("Singe Service Menu")
|
||||
|
||||
|
||||
|
||||
--[[
|
||||
|
||||
Game Management
|
||||
|
||||
|
||||
--]]
|
||||
|
BIN
assets/Singe Engine Intro.mpg
(Stored with Git LFS)
BIN
assets/Singe Engine Intro.mpg
(Stored with Git LFS)
Binary file not shown.
|
@ -1,52 +0,0 @@
|
|||
--[[
|
||||
*
|
||||
* Singe 2
|
||||
* Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
--]]
|
||||
|
||||
|
||||
-- Default Mappings
|
||||
|
||||
DEAD_ZONE = 15000
|
||||
|
||||
INPUT_UP = { SCANCODE.UP, SCANCODE.KP_8, GAMEPAD_0.AXIS_LEFT_Y_U, GAMEPAD_0.AXIS_RIGHT_Y_U, GAMEPAD_0.DPAD_UP }
|
||||
INPUT_LEFT = { SCANCODE.LEFT, SCANCODE.KP_4, GAMEPAD_0.AXIS_LEFT_X_L, GAMEPAD_0.AXIS_RIGHT_X_L, GAMEPAD_0.DPAD_LEFT }
|
||||
INPUT_DOWN = { SCANCODE.DOWN, SCANCODE.KP_2, GAMEPAD_0.AXIS_LEFT_Y_D, GAMEPAD_0.AXIS_RIGHT_Y_D, GAMEPAD_0.DPAD_DOWN }
|
||||
INPUT_RIGHT = { SCANCODE.RIGHT, SCANCODE.KP_6, GAMEPAD_0.AXIS_LEFT_X_R, GAMEPAD_0.AXIS_RIGHT_X_R, GAMEPAD_0.DPAD_RIGHT }
|
||||
INPUT_1P_COIN = { SCANCODE.MAIN_5, SCANCODE.C, GAMEPAD_0.BUTTON_LEFT_BUMPER }
|
||||
INPUT_2P_COIN = { SCANCODE.MAIN_6 }
|
||||
INPUT_1P_START = { SCANCODE.MAIN_1, GAMEPAD_0.BUTTON_RIGHT_BUMPER }
|
||||
INPUT_2P_START = { SCANCODE.MAIN_2 }
|
||||
INPUT_ACTION_1 = { SCANCODE.SPACE, SCANCODE.LCTRL, GAMEPAD_0.BUTTON_A, MOUSE_0.BUTTON_RIGHT }
|
||||
INPUT_ACTION_2 = { SCANCODE.LALT, GAMEPAD_0.BUTTON_B, MOUSE_0.BUTTON_MIDDLE }
|
||||
INPUT_ACTION_3 = { SCANCODE.LSHIFT, GAMEPAD_0.BUTTON_X, MOUSE_0.BUTTON_LEFT }
|
||||
INPUT_ACTION_4 = { SCANCODE.RSHIFT, GAMEPAD_0.BUTTON_Y, MOUSE_0.BUTTON_X1 }
|
||||
INPUT_SKILL_EASY = { SCANCODE.KP_DIVIDE }
|
||||
INPUT_SKILL_MEDIUM = { SCANCODE.KP_MULTIPLY }
|
||||
INPUT_SKILL_HARD = { SCANCODE.KP_MINUS }
|
||||
INPUT_SERVICE = { SCANCODE.MAIN_9 }
|
||||
INPUT_TEST_MODE = { SCANCODE.F2 }
|
||||
INPUT_RESET_CPU = { SCANCODE.F3 }
|
||||
INPUT_SCREENSHOT = { SCANCODE.F12, SCANCODE.F11, GAMEPAD_0.BUTTON_BACK }
|
||||
INPUT_QUIT = { SCANCODE.ESCAPE, SCANCODE.Q }
|
||||
INPUT_PAUSE = { SCANCODE.P, GAMEPAD_0.BUTTON_START }
|
||||
INPUT_CONSOLE = { SCANCODE.GRAVE }
|
||||
INPUT_TILT = { SCANCODE.T }
|
||||
INPUT_GRAB = { SCANCODE.G }
|
BIN
assets/font.xcf
(Stored with Git LFS)
BIN
assets/font.xcf
(Stored with Git LFS)
Binary file not shown.
BIN
assets/icon.xcf
(Stored with Git LFS)
BIN
assets/icon.xcf
(Stored with Git LFS)
Binary file not shown.
BIN
assets/indexing.xcf
(Stored with Git LFS)
BIN
assets/indexing.xcf
(Stored with Git LFS)
Binary file not shown.
BIN
assets/kangarooPunchLogo.xcf
(Stored with Git LFS)
BIN
assets/kangarooPunchLogo.xcf
(Stored with Git LFS)
Binary file not shown.
BIN
assets/laserDisc.xcf
(Stored with Git LFS)
BIN
assets/laserDisc.xcf
(Stored with Git LFS)
Binary file not shown.
BIN
assets/magnifyingGlass.xcf
(Stored with Git LFS)
BIN
assets/magnifyingGlass.xcf
(Stored with Git LFS)
Binary file not shown.
BIN
assets/singeLogo.xcf
(Stored with Git LFS)
BIN
assets/singeLogo.xcf
(Stored with Git LFS)
Binary file not shown.
569
build-all.sh
569
build-all.sh
|
@ -1,569 +0,0 @@
|
|||
#!/bin/bash -x
|
||||
|
||||
#
|
||||
# Singe 2
|
||||
# Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public Licens
|
||||
# as published by the Free Software Foundation; either version 3
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
#
|
||||
|
||||
|
||||
G_BUILDROOT=${PWD}
|
||||
G_BUILDDIR=.builddir
|
||||
G_TARGET=
|
||||
G_GENERATED=
|
||||
|
||||
|
||||
function buildAll() {
|
||||
local OS=$1
|
||||
local ARCH=$2
|
||||
local COMMON=
|
||||
local OPT1=
|
||||
|
||||
# Activate toolchain for this platform.
|
||||
source <(../toolchains/toolchains.sh use ${ARCH} ${OS})
|
||||
|
||||
G_TARGET=${G_BUILDROOT}/${G_BUILDDIR}/${OS}/${ARCH}
|
||||
G_GENERATED=${G_TARGET}/generated
|
||||
COMMON="-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${G_TARGET} -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_FILE}"
|
||||
|
||||
export LDFLAGS="-L${G_TARGET}/lib ${LDFLAGS}"
|
||||
export CFLAGS="-I${G_TARGET}/include ${CFLAGS}"
|
||||
export CXXFLAGS="-I${G_TARGET}/include ${CXXFLAGS}"
|
||||
export LD_LIBRARY_PATH="${G_TARGET}/lib"
|
||||
export PKG_CONFIG_LIBDIR="${G_TARGET}/lib/pkgconfig"
|
||||
|
||||
mkdir -p ${G_GENERATED}
|
||||
|
||||
# Needed for Pi sysroot.
|
||||
if [[ "${OS}" == "pi" ]]; then
|
||||
export CFLAGS="--sysroot=${SYSROOT} ${CFLAGS}"
|
||||
export CXXFLAGS="--sysroot=${SYSROOT} ${CXXFLAGS}"
|
||||
sudo chroot ${SYSROOT} apt-get -y install libasound-dev libxi-dev libvdpau-dev
|
||||
fi
|
||||
|
||||
if [[ 1 == 1 ]]; then
|
||||
pushd thirdparty/bzip2
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} \
|
||||
-DENABLE_SHARED_LIB=off \
|
||||
-DENABLE_STATIC_LIB=on \
|
||||
-DENABLE_LIB_ONLY=on \
|
||||
..
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/xz
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} \
|
||||
-DBUILD_SHARED_LIBS=off \
|
||||
-DBUILD_TESTING=off \
|
||||
..
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/zlib
|
||||
clearAndEnterBuild
|
||||
CFLAGS="-I${PWD}" ../configure \
|
||||
--prefix=${G_TARGET} \
|
||||
--static
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/zstd
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} \
|
||||
-DZSTD_BUILD_SHARED=off \
|
||||
-DZSTD_BUILD_STATIC=on \
|
||||
-DZSTD_BUILD_PROGRAMS=off \
|
||||
../build/cmake
|
||||
make install
|
||||
popd
|
||||
fi
|
||||
|
||||
pushd thirdparty/SDL2
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} \
|
||||
-DSDL_SHARED=off \
|
||||
-DSDL_STATIC=on \
|
||||
..
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/SDL2_image
|
||||
clearAndEnterBuild
|
||||
CFLAGS="-Iexternal/libpng ${CFLAGS}" \
|
||||
cmake ${COMMON} \
|
||||
-DBUILD_SHARED_LIBS=off \
|
||||
-DSDL2IMAGE_DEPS_SHARED=off \
|
||||
-DSDL2IMAGE_SAMPLES=off \
|
||||
-DSDL2IMAGE_TESTS=off \
|
||||
-DSDL2IMAGE_VENDORED=on \
|
||||
-DSDL2IMAGE_BACKEND_STB=off \
|
||||
-DSDL2IMAGE_AVIF=off \
|
||||
-DSDL2IMAGE_JXL=off \
|
||||
-DSDL2IMAGE_TIF=off \
|
||||
-DSDL2IMAGE_WEBP=on \
|
||||
-DSDL2_LIBRARY="${G_TARGET}/lib/libSDL2.a" \
|
||||
-DSDL2_INCLUDE_DIR="${G_TARGET}/include/SDL2" \
|
||||
-DWEBP_BUILD_ANIM_UTILS=off \
|
||||
-DWEBP_BUILD_CWEBP=off \
|
||||
-DWEBP_BUILD_DWEBP=off \
|
||||
-DWEBP_BUILD_GIF2WEBP=off \
|
||||
-DWEBP_BUILD_IMG2WEBP=off \
|
||||
-DWEBP_BUILD_VWEBP=off \
|
||||
-DWEBP_BUILD_WEBPINFO=off \
|
||||
-DWEBP_BUILD_WEBPMUX=off \
|
||||
-DWEBP_BUILD_EXTRAS=off \
|
||||
..
|
||||
# 'make install' failes on zlib, which we don't want anyway.
|
||||
make
|
||||
cp -f ../include/SDL_image.h "${G_TARGET}/include/SDL2/."
|
||||
cp -f libSDL2_image.a "${G_TARGET}/lib/."
|
||||
cp -f external/libwebp/libwebp.a "${G_TARGET}/lib/."
|
||||
cp -f external/libwebp/libwebpdemux.a "${G_TARGET}/lib/."
|
||||
if [[ "${OS}" != "macos" ]]; then
|
||||
cp -f external/jpeg/libjpeg.a "${G_TARGET}/lib/."
|
||||
cp -f external/libpng/libpng.a "${G_TARGET}/lib/."
|
||||
fi
|
||||
popd
|
||||
|
||||
pushd thirdparty/SDL2_mixer
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} \
|
||||
-DBUILD_SHARED_LIBS=off \
|
||||
-DSDL2MIXER_CMD=off \
|
||||
-DSDL2MIXER_DEPS_SHARED=off \
|
||||
-DSDL2MIXER_VENDORED=on \
|
||||
-DSDL2MIXER_SAMPLES=off \
|
||||
-DSDL2_DIR=${G_TARGET}/lib/cmake/SDL2 \
|
||||
-DWAVPACK_ENABLE_ASM=no \
|
||||
..
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/SDL2_ttf
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} \
|
||||
-DBUILD_SHARED_LIBS=off \
|
||||
-DSDL2TTF_VENDORED=on \
|
||||
-DSDL2TTF_HARFBUZZ=off \
|
||||
-DSDL2TTF_SAMPLES=off \
|
||||
-DSDL2_DIR=${G_TARGET}/lib/cmake/SDL2 \
|
||||
..
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/libarchive
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} \
|
||||
-DBUILD_SHARED_LIBS=off \
|
||||
-DBUILD_TESTING=off \
|
||||
-DENABLE_CAT=off \
|
||||
-DENABLE_CNG=off \
|
||||
-DENABLE_CPIO=off \
|
||||
-DENABLE_EXPAT=off \
|
||||
-DENABLE_ICONV=off \
|
||||
-DENABLE_LIBB2=off \
|
||||
-DENABLE_LIBGCC=off \
|
||||
-DENABLE_LIBXML2=off \
|
||||
-DENABLE_LZ4=off \
|
||||
-DENABLE_LZO=off \
|
||||
-DENABLE_MBEDTLS=off \
|
||||
-DENABLE_NETTLE=off \
|
||||
-DENABLE_OPENSSL=off \
|
||||
-DENABLE_PCREPOSIX=off \
|
||||
-DENABLE_TAR=off \
|
||||
-DENABLE_TEST=off \
|
||||
-DENABLE_UNZIP=off \
|
||||
-DPOSIX_REGEX_LIB=libc \
|
||||
-DUSE_BZIP2_STATIC=on \
|
||||
-DBZIP2_INCLUDE_DIR="${G_TARGET}/include" \
|
||||
-DBZIP2_LIBRARIES="${G_TARGET}/lib/libbz2_static.a" \
|
||||
-DZLIB_ROOT="${G_TARGET}" \
|
||||
-DLIBLZMA_INCLUDE_DIR="${G_TARGET}/include" \
|
||||
-DLIBLZMA_LIBRARY="${G_TARGET}/lib/liblzma.a" \
|
||||
-DZSTD_INCLUDE_DIR="${G_TARGET}/include" \
|
||||
-DZSTD_LIBRARY="${G_TARGET}/lib/libzstd.a" \
|
||||
-DWINDOWS_VERSION=VISTA \
|
||||
..
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/openssl
|
||||
clearAndEnterBuild
|
||||
if [[ "${OS}" == "windows" ]]; then
|
||||
if [[ "${ARCH}" == "x86" ]]; then
|
||||
OPT1="mingw"
|
||||
else
|
||||
OPT1="mingw64"
|
||||
fi
|
||||
else
|
||||
OPT1=""
|
||||
fi
|
||||
if [[ "${OS}" == "pi" ]]; then
|
||||
if [[ "${ARCH}" == "aarch64" ]]; then
|
||||
OPT1="linux-aarch64"
|
||||
else
|
||||
OPT1="linux-arm4"
|
||||
fi
|
||||
fi
|
||||
if [[ "${OS}" == "macos" ]]; then
|
||||
if [[ "${ARCH}" == "aarch64" ]]; then
|
||||
OPT1="darwin64-arm64"
|
||||
else
|
||||
OPT1="darwin64-x86_64"
|
||||
fi
|
||||
fi
|
||||
../Configure ${OPT1} \
|
||||
--prefix="${G_TARGET}" \
|
||||
--libdir=lib \
|
||||
--with-zlib-include="${G_TARGET}/include" \
|
||||
--with-zlib-lib="${G_TARGET}/lib" \
|
||||
--with-zstd-include="${G_TARGET}/include" \
|
||||
--with-zstd-lib="${G_TARGET}/lib" \
|
||||
no-apps \
|
||||
no-docs \
|
||||
no-dso \
|
||||
no-dynamic-engine \
|
||||
no-module \
|
||||
no-shared \
|
||||
no-tests \
|
||||
zlib \
|
||||
enable-zstd
|
||||
make install
|
||||
popd
|
||||
|
||||
lua thirdparty/luasec/src/options.lua -g "${G_TARGET}/include/openssl/ssl.h" > "${G_TARGET}/generated/luasec_options.c"
|
||||
mkdir -p "${G_TARGET}/include/luasocket"
|
||||
cp -f \
|
||||
thirdparty/luasocket/src/*.h \
|
||||
"${G_TARGET}/include/luasocket/."
|
||||
|
||||
if [[ "${OS}" == "pi" ]]; then
|
||||
# Hack to make ffmpeg compile.
|
||||
mkdir -p "${G_TARGET}/include/sys"
|
||||
echo "/* File no longer used */" > "${G_TARGET}/include/sys/sysctl.h"
|
||||
fi
|
||||
pushd thirdparty/ffmpeg
|
||||
clearAndEnterBuild
|
||||
# https://trac.ffmpeg.org/wiki/CompilationGuide/CrossCompilingForWindows
|
||||
../configure \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--disable-debug \
|
||||
--disable-muxers \
|
||||
--disable-hwaccels \
|
||||
--disable-encoders \
|
||||
--disable-filters \
|
||||
--disable-network \
|
||||
--disable-devices \
|
||||
--disable-doc \
|
||||
--disable-programs \
|
||||
--enable-gpl \
|
||||
--enable-version3 \
|
||||
--extra-ldflags="-L${G_TARGET}/lib" \
|
||||
--prefix=${G_TARGET} \
|
||||
--arch=${ARCH} \
|
||||
--target-os=${CROSS_OS} \
|
||||
--cross-prefix=${TRIPLE}- \
|
||||
--cc="${CC}" \
|
||||
--cxx="${CXX}" \
|
||||
--ranlib="${RANLIB}"
|
||||
make install
|
||||
popd
|
||||
|
||||
pushd thirdparty/ffms2
|
||||
#libtoolize --force
|
||||
#aclocal
|
||||
#autoheader
|
||||
#automake --force-missing --add-missing
|
||||
#autoupdate
|
||||
#autoconf
|
||||
#./autogen.sh
|
||||
#make distclean || true
|
||||
clearAndEnterBuild
|
||||
../configure \
|
||||
--prefix=${G_TARGET} \
|
||||
--with-zlib=${G_TARGET} \
|
||||
--enable-static \
|
||||
--disable-shared \
|
||||
--target=${TRIPLE} \
|
||||
--host=${TRIPLE} \
|
||||
--build=x86_64-linux
|
||||
make install-libLTLIBRARIES # This weird target prevents building the command line tools.
|
||||
popd
|
||||
|
||||
# === Known FFMPEG Types ===
|
||||
createExtensionHeader ffmpeg > ${G_GENERATED}/extensions.h
|
||||
|
||||
# === Overlay Font ===
|
||||
createEmbeddedImage font
|
||||
|
||||
# === Window Icon ===
|
||||
createEmbeddedImage icon
|
||||
|
||||
# === Kangaroo Punch Logo ===
|
||||
createEmbeddedImage kangarooPunchLogo
|
||||
|
||||
# === Singe Logo ===
|
||||
createEmbeddedImage singeLogo
|
||||
|
||||
# === Laser Disc ===
|
||||
createEmbeddedImage laserDisc
|
||||
|
||||
# === Magnifying Glass ===
|
||||
createEmbeddedImage magnifyingGlass
|
||||
|
||||
# === "Indexing" Text ===
|
||||
createEmbeddedImage indexing
|
||||
|
||||
# === Singe Menu Font ===
|
||||
createEmbeddedBinary assets/FreeSansBold.ttf ${G_GENERATED}/FreeSansBold_ttf.h FREESANSBOLD_TTF_H
|
||||
|
||||
# === Singe Menu Background Video ===
|
||||
ffmpeg -i "assets/Singe Engine Intro.mpg" -filter:v 'crop=ih/3*4:ih' -vf scale=720:480 -c:v libx264 -c:a aac -f matroska ${G_TARGET}/temp1.mkv
|
||||
ffmpeg -i assets/180503_01_PurpleGrid.mp4 -filter:v 'crop=ih/3*4:ih' -vf scale=720:480 -c:v libx264 -c:a aac -f matroska ${G_TARGET}/temp2.mkv
|
||||
ffmpeg -f concat -safe 0 -i <(echo -e "file ${G_TARGET}/temp1.mkv\nfile ${G_TARGET}/temp2.mkv\n") -c copy ${G_TARGET}/menuBackground.mkv
|
||||
createEmbeddedBinary ${G_TARGET}/menuBackground.mkv ${G_GENERATED}/menuBackground_mkv.h MENUBACKGROUND_MKV_H
|
||||
rm ${G_TARGET}/temp1.mkv ${G_TARGET}/temp2.mkv ${G_TARGET}/menuBackground.mkv
|
||||
|
||||
# === LuaSocket ===
|
||||
createEmbeddedBinary thirdparty/luasocket/src/ftp.lua ${G_GENERATED}/ftp_lua.h FTP_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/headers.lua ${G_GENERATED}/headers_lua.h HEADERS_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/http.lua ${G_GENERATED}/http_lua.h HTTP_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/ltn12.lua ${G_GENERATED}/ltn12_lua.h LTN12_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/mbox.lua ${G_GENERATED}/mbox_lua.h MBOX_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/mime.lua ${G_GENERATED}/mime_lua.h MIME_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/smtp.lua ${G_GENERATED}/smtp_lua.h SMTP_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/socket.lua ${G_GENERATED}/socket_lua.h SOCKET_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/tp.lua ${G_GENERATED}/tp_lua.h TP_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasocket/src/url.lua ${G_GENERATED}/url_lua.h URL_LUA_H
|
||||
|
||||
# === LuaSec ===
|
||||
createEmbeddedBinary thirdparty/luasec/src/https.lua ${G_GENERATED}/https_lua.h HTTPS_LUA_H
|
||||
createEmbeddedBinary thirdparty/luasec/src/ssl.lua ${G_GENERATED}/ssl_lua.h SSL_LUA_H
|
||||
|
||||
# === LuaRS232 ===
|
||||
createEmbeddedBinary thirdparty/librs232/bindings/lua/rs232.lua ${G_GENERATED}/rs232_lua.h RS232_LUA_H
|
||||
|
||||
# === Copas ===
|
||||
createEmbeddedBinary thirdparty/copas/src/copas.lua ${G_GENERATED}/copas_lua.h COPAS_LUA_H
|
||||
createEmbeddedBinary thirdparty/copas/src/copas/ftp.lua ${G_GENERATED}/copas_ftp_lua.h COPAS_FTP_LUA_H copas
|
||||
createEmbeddedBinary thirdparty/copas/src/copas/http.lua ${G_GENERATED}/copas_http_lua.h COPAS_HTTP_LUA_H copas
|
||||
createEmbeddedBinary thirdparty/copas/src/copas/smtp.lua ${G_GENERATED}/copas_smtp_lua.h COPAS_SMTP_LUA_H copas
|
||||
createEmbeddedBinary thirdparty/copas/src/copas/lock.lua ${G_GENERATED}/copas_lock_lua.h COPAS_LOCK_LUA_H copas
|
||||
createEmbeddedBinary thirdparty/copas/src/copas/queue.lua ${G_GENERATED}/copas_queue_lua.h COPAS_QUEUE_LUA_H copas
|
||||
createEmbeddedBinary thirdparty/copas/src/copas/semaphore.lua ${G_GENERATED}/copas_semaphore_lua.h COPAS_SEMAPHORE_LUA_H copas
|
||||
createEmbeddedBinary thirdparty/copas/src/copas/timer.lua ${G_GENERATED}/copas_timer_lua.h COPAS_TIMER_LUA_H copas
|
||||
|
||||
# === binaryheap.lua ===
|
||||
createEmbeddedBinary thirdparty/binaryheap.lua/src/binaryheap.lua ${G_GENERATED}/binaryheap_lua.h BINARYHEAP_LUA_H
|
||||
|
||||
# === timerwheel.lua ===
|
||||
createEmbeddedBinary thirdparty/timerwheel.lua/src/timerwheel/timerwheel.lua ${G_GENERATED}/timerwheel_lua.h TIMERWHEEL_LUA_H
|
||||
|
||||
# === json.lua ===
|
||||
createEmbeddedBinary thirdparty/json.lua/json.lua ${G_GENERATED}/json_lua.h JSON_LUA_H
|
||||
|
||||
# === Singe Framework ===
|
||||
createEmbeddedBinary assets/Framework.singe ${G_GENERATED}/Framework_singe.h FRAMEWORK_SINGE_H
|
||||
|
||||
# === Default Config ===
|
||||
createEmbeddedBinary assets/controls.cfg ${G_GENERATED}/controls_cfg.h CONTROLS_CFG_H
|
||||
|
||||
# === Singe Menu App ===
|
||||
createEmbeddedBinary assets/Menu.singe ${G_GENERATED}/Menu_singe.h MENU_SINGE_H
|
||||
|
||||
# === Singe Manual ===
|
||||
#lyx -batch -f all -E pdf ${G_GENERATED}/Manual.pdf assets/Manual.lyx
|
||||
#createEmbeddedBinary ${G_GENERATED}/Manual.pdf ${G_GENERATED}/Manual_pdf.h MANUAL_H
|
||||
|
||||
pushd ${G_TARGET}
|
||||
clearAndEnterBuild
|
||||
cmake ${COMMON} ${G_BUILDROOT}
|
||||
make
|
||||
#upx -9 --force singe2${SUFFIX}
|
||||
mv -f singe2${SUFFIX} ${G_BUILDROOT}/${G_BUILDDIR}/Singe-v2.10-${OS^}-${ARCH}${SUFFIX}
|
||||
popd
|
||||
}
|
||||
|
||||
|
||||
function clearAndEnterBuild() {
|
||||
[[ -d ${G_BUILDDIR} ]] && rm -rf ${G_BUILDDIR}
|
||||
mkdir -p ${G_BUILDDIR}
|
||||
cd ${G_BUILDDIR}
|
||||
}
|
||||
|
||||
|
||||
function createEmbeddedBinary() {
|
||||
local BINFILE=$1
|
||||
local SOURCEFILE=$2 # This is assumed to be an absolute path
|
||||
local BLOCKER=$3
|
||||
local PREFIX=$4
|
||||
local FILENAME=$(basename ${BINFILE})
|
||||
local DIRNAME=$(dirname ${BINFILE})
|
||||
|
||||
outputLicense > ${SOURCEFILE}
|
||||
outputHeader ${BLOCKER} >> ${SOURCEFILE}
|
||||
printf "\n#ifdef EMBED_HERE\n\n" >> ${SOURCEFILE}
|
||||
pushd ${DIRNAME}
|
||||
xxd -i ${FILENAME} >> ${SOURCEFILE}
|
||||
popd
|
||||
if [[ ! -z ${PREFIX} ]]; then
|
||||
PREFIX=${PREFIX}_
|
||||
sed -i "s/unsigned char /unsigned char ${PREFIX}/" ${SOURCEFILE}
|
||||
sed -i "s/unsigned int /unsigned int ${PREFIX}/" ${SOURCEFILE}
|
||||
fi
|
||||
printf "\n#else // EMBED_HERE\n\n" >> ${SOURCEFILE}
|
||||
printf "extern unsigned char ${PREFIX}${FILENAME/\./_}[];\n" >> ${SOURCEFILE}
|
||||
printf "extern unsigned int ${PREFIX}${FILENAME/\./_}_len;\n" >> ${SOURCEFILE}
|
||||
printf "\n#endif // EMBED_HERE\n\n" >> ${SOURCEFILE}
|
||||
outputFooter ${BLOCKER} >> ${SOURCEFILE}
|
||||
}
|
||||
|
||||
|
||||
function createEmbeddedImage() {
|
||||
local BASENAME=$1
|
||||
|
||||
pushd assets
|
||||
convert -flatten -background rgba\(0,0,0,0\) ${BASENAME}.xcf ${G_GENERATED}/${BASENAME}.png
|
||||
createEmbeddedBinary ${G_GENERATED}/${BASENAME}.png ${G_GENERATED}/${BASENAME}.h ${BASENAME^^}_H
|
||||
rm ${G_GENERATED}/${BASENAME}.png
|
||||
popd
|
||||
}
|
||||
|
||||
|
||||
function createExtensionHeader() {
|
||||
local FFMPEG=$1
|
||||
local a=
|
||||
local c=0
|
||||
|
||||
outputLicense
|
||||
outputHeader FFMPEG_EXTENSIONS_H
|
||||
printf "static char *ffmpegExtensions[] = {\n"
|
||||
printf "\t"
|
||||
getExtensions "${FFMPEG}" | sort | uniq -u | while read a; do
|
||||
printf "\"${a}\", "
|
||||
c=$((c + 1))
|
||||
if [[ ${c} -ge 10 ]]; then
|
||||
printf "\n\t"
|
||||
c=0
|
||||
fi
|
||||
done
|
||||
printf "0\n};"
|
||||
outputFooter FFMPEG_EXTENSIONS_H
|
||||
}
|
||||
|
||||
|
||||
function getExtensions() {
|
||||
local FFMPEG=$1
|
||||
local a=
|
||||
local b=
|
||||
local c=
|
||||
local d=
|
||||
local e=
|
||||
local f=
|
||||
local g=
|
||||
|
||||
"${FFMPEG}" -demuxers 2> /dev/null | while read a b c; do
|
||||
if [[ "${a}x" == "Dx" ]]; then
|
||||
"${FFMPEG}" -h demuxer=${b} 2> /dev/null | grep "Common extensions" | while read d e f; do
|
||||
g=${f/./}
|
||||
echo -e "${g//,/\\n}"
|
||||
done
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function outputFooter() {
|
||||
local BLOCKER=$1
|
||||
|
||||
printf "\n#pragma GCC diagnostic pop\n\n\n#endif // ${BLOCKER}\n"
|
||||
}
|
||||
|
||||
|
||||
function outputHeader() {
|
||||
local BLOCKER=$1
|
||||
|
||||
printf "\n\n#ifndef ${BLOCKER}\n#define ${BLOCKER}\n\n\n"
|
||||
printf "// ===== THIS FILE IS AUTOMATICALLY GENERATED - DO NOT EDIT =====\n\n\n"
|
||||
printf "#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wunused-variable\"\n"
|
||||
}
|
||||
|
||||
|
||||
function outputLicense() {
|
||||
cat <<- LICENSE
|
||||
/*
|
||||
*
|
||||
* Singe 2
|
||||
* Copyright (C) 2006-2024 Scott Duensing <scott@kangaroopunch.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 3
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
LICENSE
|
||||
}
|
||||
|
||||
|
||||
# -e = stop script on errors
|
||||
# -u = stop script on undefined variable
|
||||
# -o pipefail = stop pipeline if any step fails
|
||||
set -e
|
||||
|
||||
|
||||
mkdir -p ${G_BUILDDIR}
|
||||
|
||||
|
||||
# These are required for the build.
|
||||
sudo apt-get install -y \
|
||||
xxd \
|
||||
imagemagick \
|
||||
lua5.4 \
|
||||
lyx \
|
||||
ffmpeg \
|
||||
libasound-dev \
|
||||
libxi-dev \
|
||||
libvdpau-dev \
|
||||
upx-ucl
|
||||
|
||||
|
||||
buildAll linux x86_64 2>&1 | tee ${G_BUILDDIR}/linux-x86_64.log
|
||||
buildAll macos aarch64 2>&1 | tee ${G_BUILDDIR}/macos-aarch64.log
|
||||
buildAll pi aarch64 2>&1 | tee ${G_BUILDDIR}/pi-aarch64.log
|
||||
buildAll windows x86_64 2>&1 | tee ${G_BUILDDIR}/windows-x86_64.log
|
||||
|
||||
|
||||
# === UNSUPPORTED ===
|
||||
|
||||
#buildAll macos x86_64 2>&1 | tee ${G_BUILDDIR}/macos-x86_64.log
|
||||
#buildAll linux x86
|
||||
#buildAll macos x86 #***TODO*** Needs older SDL2
|
||||
#buildAll windows x86
|
4
ffms2/.gitmodules
vendored
Normal file
4
ffms2/.gitmodules
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
[submodule "test/googletest"]
|
||||
path = test/googletest
|
||||
url = https://github.com/google/googletest
|
||||
branch = master
|
44
ffms2/.travis.yml
Normal file
44
ffms2/.travis.yml
Normal file
|
@ -0,0 +1,44 @@
|
|||
language: cpp
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-6
|
||||
- g++-6
|
||||
- yasm
|
||||
before_install:
|
||||
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-6 60 --slave /usr/bin/g++ g++ /usr/bin/g++-6
|
||||
- compiler: clang
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- llvm-toolchain-trusty-4.0
|
||||
packages:
|
||||
- clang-4.0
|
||||
- yasm
|
||||
before_install:
|
||||
- sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-4.0 60 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-4.0
|
||||
|
||||
install:
|
||||
- git clone git://git.videolan.org/ffmpeg.git --depth=1 ffmpeg
|
||||
- cd ffmpeg
|
||||
- ./configure --disable-avfilter --disable-devices --disable-doc --disable-encoders --disable-filters --disable-hwaccels --disable-muxers --disable-network
|
||||
- make -j2
|
||||
- sudo make install
|
||||
- cd ..
|
||||
script:
|
||||
- ./autogen.sh --enable-static --disable-shared || cat config.log
|
||||
- make V=1 CXXFLAGS='-Werror -Wno-error=deprecated-declarations' -j2 -k
|
||||
- make test-sync
|
||||
- make test -j2 -k
|
||||
notifications:
|
||||
email:
|
||||
- on_success: change
|
||||
- on_failure: change
|
81
ffms2/Makefile.am
Normal file
81
ffms2/Makefile.am
Normal file
|
@ -0,0 +1,81 @@
|
|||
ACLOCAL_AMFLAGS = -I m4
|
||||
AUTOMAKE_OPTIONS = foreign
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = ffms2.pc
|
||||
|
||||
dist_doc_DATA = doc/ffms2-api.md doc/ffms2-changelog.md
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I. \
|
||||
-I$(top_srcdir)/include \
|
||||
-I$(top_srcdir)/src/config \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
-DFFMS_EXPORTS \
|
||||
-D__STDC_CONSTANT_MACROS \
|
||||
@FFMPEG_CFLAGS@ \
|
||||
@ZLIB_CPPFLAGS@ \
|
||||
-include config.h
|
||||
AM_CXXFLAGS = -std=c++11 -fvisibility=hidden
|
||||
|
||||
lib_LTLIBRARIES = src/core/libffms2.la
|
||||
src_core_libffms2_la_LDFLAGS = @src_core_libffms2_la_LDFLAGS@
|
||||
src_core_libffms2_la_LIBADD = @FFMPEG_LIBS@ @ZLIB_LDFLAGS@ -lz @LTUNDEF@
|
||||
src_core_libffms2_la_SOURCES = \
|
||||
src/core/audiosource.cpp \
|
||||
src/core/audiosource.h \
|
||||
src/core/ffms.cpp \
|
||||
src/core/filehandle.cpp \
|
||||
src/core/filehandle.h \
|
||||
src/core/indexing.cpp \
|
||||
src/core/indexing.h \
|
||||
src/core/track.cpp \
|
||||
src/core/track.h \
|
||||
src/core/utils.cpp \
|
||||
src/core/utils.h \
|
||||
src/core/videosource.cpp \
|
||||
src/core/videosource.h \
|
||||
src/core/videoutils.cpp \
|
||||
src/core/videoutils.h \
|
||||
src/core/zipfile.cpp \
|
||||
src/core/zipfile.h \
|
||||
src/vapoursynth/VapourSynth.h \
|
||||
src/vapoursynth/vapoursource.cpp \
|
||||
src/vapoursynth/vapoursource.h \
|
||||
src/vapoursynth/vapoursynth.cpp
|
||||
|
||||
include_HEADERS = $(top_srcdir)/include/ffms.h $(top_srcdir)/include/ffmscompat.h
|
||||
|
||||
bin_PROGRAMS = src/index/ffmsindex
|
||||
src_index_ffmsindex_SOURCES = src/index/ffmsindex.cpp
|
||||
src_index_ffmsindex_LDADD = src/core/libffms2.la
|
||||
|
||||
.PHONY: test test-build test-clean test-sync test-run
|
||||
clean-local: test-clean
|
||||
|
||||
SAMPLES_DIR = $(abs_top_builddir)/test/samples
|
||||
SAMPLES_URL = https://storage.googleapis.com/ffms2tests
|
||||
|
||||
test: test-setup test-build test-run
|
||||
|
||||
test-setup:
|
||||
@$(MKDIR_P) $(abs_top_builddir)/test
|
||||
@$(MKDIR_P) $(SAMPLES_DIR)
|
||||
@if [ ! -e "$(abs_top_builddir)/test/Makefile" ]; then \
|
||||
$(LN_S) $(abs_top_srcdir)/test/Makefile $(abs_top_builddir)/test/Makefile; \
|
||||
fi
|
||||
|
||||
test-build: test-setup src/core/libffms2.la
|
||||
@if [ ! -d "$(abs_top_srcdir)/test/googletest" ]; then \
|
||||
echo "googletest submodule not initalized."; \
|
||||
fi
|
||||
@$(MAKE) -C test USER_DIR=$(abs_top_srcdir) SAMPLES_DIR=$(SAMPLES_DIR) CXX=$(CXX) AR=$(AR)
|
||||
|
||||
test-sync: test-setup
|
||||
@$(MAKE) -C test sync USER_DIR=$(abs_top_srcdir) SAMPLES_DIR=$(SAMPLES_DIR) SAMPLES_URL=$(SAMPLES_URL) CXX=$(CXX) AR=$(AR)
|
||||
|
||||
test-run: test-build
|
||||
@$(MAKE) -C test run USER_DIR=$(abs_top_srcdir) SAMPLES_DIR=$(SAMPLES_DIR) CXX=$(CXX) AR=$(AR) -k
|
||||
|
||||
test-clean:
|
||||
@$(MAKE) -C test clean USER_DIR=$(abs_top_srcdir) CXX=$(CXX) AR=$(AR)
|
1157
ffms2/Makefile.in
Normal file
1157
ffms2/Makefile.in
Normal file
File diff suppressed because it is too large
Load diff
1470
ffms2/aclocal.m4
vendored
Normal file
1470
ffms2/aclocal.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
7
ffms2/build-msvc/Readme.txt
Normal file
7
ffms2/build-msvc/Readme.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
BUILD INSTRUCTIONS
|
||||
|
||||
The included projects require Visual Studio 2017.
|
||||
|
||||
Libraries needed: recent FFmpeg, zlib, Avisynth+ (MT branch) headers.
|
||||
|
||||
All include and library paths are set to be relative to the ffms2 directory by default.
|
|
@ -23,34 +23,32 @@
|
|||
<ProjectGuid>{2CF8C7D2-55E5-4861-A58A-A79B84D0D9EA}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ffms2</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
|
||||
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
@ -76,28 +74,34 @@
|
|||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;../../ffmpeg32/include;../../zlib32;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>../../ffmpeg32/lib;../../zlib32;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;../../ffmpeg64/include;../../zlib64;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>../../ffmpeg64/lib;../../zlib64;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;../../ffmpeg32/include;../../zlib32;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>../../ffmpeg32/lib;../../zlib32;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)obj\$(Platform)\$(Configuration)\</IntDir>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;$(IncludePath)</IncludePath>
|
||||
<IncludePath>../include;../../AviSynthPlus/avs_core/include;../../ffmpeg64/include;../../zlib64;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>../../ffmpeg64/lib;../../zlib64;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>FFMS_EXPORTS;_CRT_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;FFMS_WIN_DEBUG;WIN32;_DEBUG;_WINDOWS;_USRDLL;FFMS2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
@ -105,11 +109,13 @@
|
|||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>psapi.lib;uuid.lib;oleaut32.lib;shlwapi.lib;gdi32.lib;vfw32.lib;secur32.lib;ws2_32.lib;mfplat.lib;mfuuid.lib;strmiids.lib;ole32.lib;user32.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libavutil.a;libavcodec.a;libavformat.a;libswscale.a;libswresample.a;zlib.lib;ws2_32.lib;secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>FFMS_EXPORTS;_CRT_SECURE_NO_WARNINGS;__STDC_CONSTANT_MACROS;FFMS_WIN_DEBUG;_DEBUG;_WINDOWS;_USRDLL;FFMS2_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
@ -117,12 +123,14 @@
|
|||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<AdditionalDependencies>psapi.lib;uuid.lib;oleaut32.lib;shlwapi.lib;gdi32.lib;vfw32.lib;secur32.lib;ws2_32.lib;mfplat.lib;mfuuid.lib;strmiids.lib;ole32.lib;user32.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libavutil.a;libavcodec.a;libavformat.a;libswscale.a;libswresample.a;zlib.lib;ws2_32.lib;secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
|
@ -133,12 +141,14 @@
|
|||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>psapi.lib;uuid.lib;oleaut32.lib;shlwapi.lib;gdi32.lib;vfw32.lib;secur32.lib;ws2_32.lib;mfplat.lib;mfuuid.lib;strmiids.lib;ole32.lib;user32.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libavutil.a;libavcodec.a;libavformat.a;libswscale.a;libswresample.a;zlib.lib;ws2_32.lib;secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
|
@ -149,7 +159,7 @@
|
|||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>psapi.lib;uuid.lib;oleaut32.lib;shlwapi.lib;gdi32.lib;vfw32.lib;secur32.lib;ws2_32.lib;mfplat.lib;mfuuid.lib;strmiids.lib;ole32.lib;user32.lib;bcrypt.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>libavutil.a;libavcodec.a;libavformat.a;libswscale.a;libswresample.a;zlib.lib;ws2_32.lib;secur32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
@ -164,8 +174,8 @@
|
|||
<ClCompile Include="..\src\core\videosource.cpp" />
|
||||
<ClCompile Include="..\src\core\videoutils.cpp" />
|
||||
<ClCompile Include="..\src\core\zipfile.cpp" />
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursource4.cpp" />
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursynth4.cpp" />
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursource.cpp" />
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursynth.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\ffms.h" />
|
||||
|
@ -179,9 +189,9 @@
|
|||
<ClInclude Include="..\src\core\videosource.h" />
|
||||
<ClInclude Include="..\src\core\videoutils.h" />
|
||||
<ClInclude Include="..\src\core\zipfile.h" />
|
||||
<ClInclude Include="..\src\vapoursynth\vapoursource4.h" />
|
||||
<ClInclude Include="..\src\vapoursynth\VapourSynth4.h" />
|
||||
<ClInclude Include="..\src\vapoursynth\VSHelper4.h" />
|
||||
<ClInclude Include="..\src\vapoursynth\vapoursource.h" />
|
||||
<ClInclude Include="..\src\vapoursynth\VapourSynth.h" />
|
||||
<ClInclude Include="..\src\vapoursynth\VSHelper.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
|
@ -42,6 +42,12 @@
|
|||
<ClCompile Include="..\src\core\videoutils.cpp">
|
||||
<Filter>Video</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursource.cpp">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursynth.cpp">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\core\indexing.cpp">
|
||||
<Filter>Indexing</Filter>
|
||||
</ClCompile>
|
||||
|
@ -57,12 +63,6 @@
|
|||
<ClCompile Include="..\src\avisynth\avssources.cpp">
|
||||
<Filter>Avisynth</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursource4.cpp">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\vapoursynth\vapoursynth4.cpp">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\include\ffms.h">
|
||||
|
@ -86,6 +86,15 @@
|
|||
<ClInclude Include="..\src\core\videoutils.h">
|
||||
<Filter>Video</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\vapoursynth\vapoursource.h">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\vapoursynth\VapourSynth.h">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\vapoursynth\VSHelper.h">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\core\indexing.h">
|
||||
<Filter>Indexing</Filter>
|
||||
</ClInclude>
|
||||
|
@ -98,14 +107,5 @@
|
|||
<ClInclude Include="..\src\avisynth\avssources.h">
|
||||
<Filter>Avisynth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\vapoursynth\vapoursource4.h">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\vapoursynth\VapourSynth4.h">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\vapoursynth\VSHelper4.h">
|
||||
<Filter>Vapoursynth</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -23,34 +23,32 @@
|
|||
<ProjectGuid>{8665C229-CA77-4B41-ADC5-F3998F0C85A6}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ffmsindex</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<VcpkgTriplet Condition="'$(Platform)'=='x64'">x64-windows-static</VcpkgTriplet>
|
||||
<VcpkgTriplet Condition="'$(Platform)'=='Win32'">x86-windows-static</VcpkgTriplet>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
@ -168,9 +166,6 @@
|
|||
<Project>{2cf8c7d2-55e5-4861-a58a-a79b84d0d9ea}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\src\index\ffmsindex.manifest" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
|
@ -9,9 +9,6 @@
|
|||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Manifests">
|
||||
<UniqueIdentifier>{25d75b48-9985-40fd-be86-bd4ca73d5209}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\index\ffmsindex.cpp">
|
||||
|
@ -26,9 +23,4 @@
|
|||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="..\src\index\ffmsindex.manifest">
|
||||
<Filter>Manifests</Filter>
|
||||
</Manifest>
|
||||
</ItemGroup>
|
||||
</Project>
|
347
ffms2/compile
Executable file
347
ffms2/compile
Executable file
|
@ -0,0 +1,347 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand '-c -o'.
|
||||
|
||||
scriptversion=2012-10-14.11; # UTC
|
||||
|
||||
# Copyright (C) 1999-2014 Free Software Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.com>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
nl='
|
||||
'
|
||||
|
||||
# We need space, tab and new line, in precisely that order. Quoting is
|
||||
# there to prevent tools from complaining about whitespace usage.
|
||||
IFS=" "" $nl"
|
||||
|
||||
file_conv=
|
||||
|
||||
# func_file_conv build_file lazy
|
||||
# Convert a $build file to $host form and store it in $file
|
||||
# Currently only supports Windows hosts. If the determined conversion
|
||||
# type is listed in (the comma separated) LAZY, no conversion will
|
||||
# take place.
|
||||
func_file_conv ()
|
||||
{
|
||||
file=$1
|
||||
case $file in
|
||||
/ | /[!/]*) # absolute file, and not a UNC file
|
||||
if test -z "$file_conv"; then
|
||||
# lazily determine how to convert abs files
|
||||
case `uname -s` in
|
||||
MINGW*)
|
||||
file_conv=mingw
|
||||
;;
|
||||
CYGWIN*)
|
||||
file_conv=cygwin
|
||||
;;
|
||||
*)
|
||||
file_conv=wine
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
case $file_conv/,$2, in
|
||||
*,$file_conv,*)
|
||||
;;
|
||||
mingw/*)
|
||||
file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'`
|
||||
;;
|
||||
cygwin/*)
|
||||
file=`cygpath -m "$file" || echo "$file"`
|
||||
;;
|
||||
wine/*)
|
||||
file=`winepath -w "$file" || echo "$file"`
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# func_cl_dashL linkdir
|
||||
# Make cl look for libraries in LINKDIR
|
||||
func_cl_dashL ()
|
||||
{
|
||||
func_file_conv "$1"
|
||||
if test -z "$lib_path"; then
|
||||
lib_path=$file
|
||||
else
|
||||
lib_path="$lib_path;$file"
|
||||
fi
|
||||
linker_opts="$linker_opts -LIBPATH:$file"
|
||||
}
|
||||
|
||||
# func_cl_dashl library
|
||||
# Do a library search-path lookup for cl
|
||||
func_cl_dashl ()
|
||||
{
|
||||
lib=$1
|
||||
found=no
|
||||
save_IFS=$IFS
|
||||
IFS=';'
|
||||
for dir in $lib_path $LIB
|
||||
do
|
||||
IFS=$save_IFS
|
||||
if $shared && test -f "$dir/$lib.dll.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.dll.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/$lib.lib"; then
|
||||
found=yes
|
||||
lib=$dir/$lib.lib
|
||||
break
|
||||
fi
|
||||
if test -f "$dir/lib$lib.a"; then
|
||||
found=yes
|
||||
lib=$dir/lib$lib.a
|
||||
break
|
||||
fi
|
||||
done
|
||||
IFS=$save_IFS
|
||||
|
||||
if test "$found" != yes; then
|
||||
lib=$lib.lib
|
||||
fi
|
||||
}
|
||||
|
||||
# func_cl_wrapper cl arg...
|
||||
# Adjust compile command to suit cl
|
||||
func_cl_wrapper ()
|
||||
{
|
||||
# Assume a capable shell
|
||||
lib_path=
|
||||
shared=:
|
||||
linker_opts=
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.[oO][bB][jJ])
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fo"$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
func_file_conv "$2"
|
||||
set x "$@" -Fe"$file"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
-I)
|
||||
eat=1
|
||||
func_file_conv "$2" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-I*)
|
||||
func_file_conv "${1#-I}" mingw
|
||||
set x "$@" -I"$file"
|
||||
shift
|
||||
;;
|
||||
-l)
|
||||
eat=1
|
||||
func_cl_dashl "$2"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-l*)
|
||||
func_cl_dashl "${1#-l}"
|
||||
set x "$@" "$lib"
|
||||
shift
|
||||
;;
|
||||
-L)
|
||||
eat=1
|
||||
func_cl_dashL "$2"
|
||||
;;
|
||||
-L*)
|
||||
func_cl_dashL "${1#-L}"
|
||||
;;
|
||||
-static)
|
||||
shared=false
|
||||
;;
|
||||
-Wl,*)
|
||||
arg=${1#-Wl,}
|
||||
save_ifs="$IFS"; IFS=','
|
||||
for flag in $arg; do
|
||||
IFS="$save_ifs"
|
||||
linker_opts="$linker_opts $flag"
|
||||
done
|
||||
IFS="$save_ifs"
|
||||
;;
|
||||
-Xlinker)
|
||||
eat=1
|
||||
linker_opts="$linker_opts $2"
|
||||
;;
|
||||
-*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*.cc | *.CC | *.cxx | *.CXX | *.[cC]++)
|
||||
func_file_conv "$1"
|
||||
set x "$@" -Tp"$file"
|
||||
shift
|
||||
;;
|
||||
*.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO])
|
||||
func_file_conv "$1" mingw
|
||||
set x "$@" "$file"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
if test -n "$linker_opts"; then
|
||||
linker_opts="-link$linker_opts"
|
||||
fi
|
||||
exec "$@" $linker_opts
|
||||
exit 1
|
||||
}
|
||||
|
||||
eat=
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand '-c -o'.
|
||||
Remove '-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file 'INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
cl | *[/\\]cl | cl.exe | *[/\\]cl.exe )
|
||||
func_cl_wrapper "$@" # Doesn't return...
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as 'compile cc -o foo foo.c'.
|
||||
# So we strip '-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no '-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# '.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use '[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
1480
ffms2/config.guess
vendored
Executable file
1480
ffms2/config.guess
vendored
Executable file
File diff suppressed because it is too large
Load diff
1801
ffms2/config.sub
vendored
Executable file
1801
ffms2/config.sub
vendored
Executable file
File diff suppressed because it is too large
Load diff
19020
ffms2/configure
vendored
Executable file
19020
ffms2/configure
vendored
Executable file
File diff suppressed because it is too large
Load diff
151
ffms2/configure.ac
Normal file
151
ffms2/configure.ac
Normal file
|
@ -0,0 +1,151 @@
|
|||
AC_PREREQ([2.58])
|
||||
AC_INIT([ffms2],[esyscmd([sh version.sh])])
|
||||
AC_CONFIG_SRCDIR([src/core/ffms.cpp])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AM_INIT_AUTOMAKE([1.11 subdir-objects])
|
||||
AM_SILENT_RULES([yes])
|
||||
AM_MAINTAINER_MODE([disable])
|
||||
|
||||
VERSION_INFO="4:0:0"
|
||||
|
||||
AC_MSG_CHECKING([if debug build is enabled])
|
||||
|
||||
AC_ARG_ENABLE([debug],
|
||||
[AC_HELP_STRING([--enable-debug],
|
||||
[Enable debug build. [default=no]])],
|
||||
[enable_debug=yes],
|
||||
[enable_debug=no]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT([$enable_debug])
|
||||
|
||||
if test "$enable_debug" = yes; then
|
||||
OPT_FLAGS="-O0 -g"
|
||||
else
|
||||
OPT_FLAGS="-O3"
|
||||
fi
|
||||
|
||||
if test -z "$CFLAGS"; then
|
||||
CFLAGS="$OPT_FLAGS -Wall -Wextra"
|
||||
fi
|
||||
|
||||
if test -z "$CXXFLAGS"; then
|
||||
CXXFLAGS="$OPT_FLAGS -Wall -Wextra"
|
||||
fi
|
||||
|
||||
AC_CONFIG_HEADERS([src/config/config.h])
|
||||
AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_PROG_LN_S
|
||||
AC_PROG_MKDIR_P
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
AS_CASE([$host],
|
||||
[*mingw* | *cygwin*], [
|
||||
AC_ENABLE_STATIC
|
||||
AC_DISABLE_SHARED
|
||||
], [
|
||||
AC_ENABLE_SHARED
|
||||
AC_DISABLE_STATIC])
|
||||
|
||||
AC_PROG_LIBTOOL
|
||||
|
||||
if echo "$host" | $GREP "cygwin" >/dev/null 2>&1 && test "$enable_shared" = "yes"; then
|
||||
AC_MSG_ERROR([Shared build is broken on cygwin.
|
||||
Please remove --enable-shared from your configure options or build with another --host.])
|
||||
fi
|
||||
|
||||
dnl Workaround for a bug in libtool
|
||||
dnl The windows libtool uses a file magic checking method that only accepts
|
||||
dnl dynamic libraries. Change it for libtool's alternative checking method.
|
||||
if test "$lt_cv_file_magic_cmd" = "func_win32_libid" ; then
|
||||
deplibs_check_method='file_magic file format pei*-(i386|x86-64)|(.*architecture: i386)?'
|
||||
file_magic_cmd='$OBJDUMP -f'
|
||||
fi
|
||||
|
||||
FFMS_VERSION="$(sh $(dirname -- "$0")/version.sh)"
|
||||
AC_SUBST([FFMS_VERSION])
|
||||
|
||||
CHECK_ZLIB
|
||||
|
||||
dnl Save CFLAGS and LIBS for later, as anything else we add will be from pkg-config
|
||||
dnl and thus should be separate in our .pc file.
|
||||
_CFLAGS="$CFLAGS"
|
||||
_CPPFLAGS="$CPPFLAGS"
|
||||
_LIBS="$LIBS"
|
||||
|
||||
PKG_PROG_PKG_CONFIG([0.22])
|
||||
pkgconfigdir="\$(libdir)/pkgconfig"
|
||||
AC_SUBST(pkgconfigdir)
|
||||
|
||||
PKG_CHECK_MODULES(FFMPEG, [libavformat >= 53.20.0 libavcodec >= 53.24.0 libswscale >= 0.7.0 libavutil >= 51.21.0 libswresample >= 1.0.0])
|
||||
|
||||
dnl As of 0eec06ed8747923faa6a98e474f224d922dc487d ffmpeg only adds -lrt to lavc's
|
||||
dnl LIBS, but lavu needs it, so move it to the end if it's present
|
||||
FFMPEG_LIBS=$(echo $FFMPEG_LIBS | sed 's/\(.*\)-lrt \(.*\)/\1\2 -lrt/')
|
||||
|
||||
AC_SUBST([FFMPEG_CFLAGS])
|
||||
AC_SUBST([FFMPEG_LIBS])
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -D__STDC_CONSTANT_MACROS"
|
||||
CFLAGS="$_CFLAGS $FFMPEG_CFLAGS"
|
||||
|
||||
AC_DEFUN([TEST_FFMPEG],
|
||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
]],[[
|
||||
avcodec_register_all();
|
||||
swscale_version();
|
||||
]])], [eval $1=yes], [eval $1=no])
|
||||
])
|
||||
|
||||
AC_MSG_CHECKING([whether FFmpeg works])
|
||||
LIBS="$_LIBS $FFMPEG_LIBS"
|
||||
TEST_FFMPEG([FFMPEG_WORKS])
|
||||
AC_MSG_RESULT([$FFMPEG_WORKS])
|
||||
if test "$FFMPEG_WORKS" = no; then
|
||||
AC_MSG_FAILURE([cannot link with FFmpeg])
|
||||
fi
|
||||
|
||||
src_core_libffms2_la_LDFLAGS=""
|
||||
AC_MSG_CHECKING([whether -Wl,-Bsymbolic is needed])
|
||||
if test "$enable_shared" = yes; then
|
||||
_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS -shared $lt_prog_compiler_pic"
|
||||
TEST_FFMPEG([no_bsymbolic])
|
||||
if test "$no_bsymbolic" = "no"; then
|
||||
LDFLAGS="$LDFLAGS -Wl,-Bsymbolic"
|
||||
TEST_FFMPEG([bsymbolic])
|
||||
if test "$bsymbolic" = "yes"; then
|
||||
src_core_libffms2_la_LDFLAGS="$src_core_libffms2_la_LDFLAGS -Wl-Bsymbolic"
|
||||
else
|
||||
AC_MSG_RESULT($bsymbolic)
|
||||
AC_MSG_FAILURE([cannot build ffms2 as a shared library])
|
||||
fi
|
||||
else
|
||||
bsymbolic=no
|
||||
fi
|
||||
LDFLAGS="$_LDFLAGS"
|
||||
src_core_libffms2_la_LDFLAGS="$src_core_libffms2_la_LDFLAGS -version-info $VERSION_INFO"
|
||||
else
|
||||
bsymbolic=no
|
||||
fi
|
||||
AC_SUBST([src_core_libffms2_la_LDFLAGS])
|
||||
|
||||
CFLAGS="$_CFLAGS"
|
||||
CPPFLAGS="$_CPPFLAGS"
|
||||
LIBS="$_LIBS"
|
||||
AC_MSG_RESULT($bsymbolic)
|
||||
|
||||
if echo "$host" | $GREP "mingw" >/dev/null 2>&1; then
|
||||
LTUNDEF="-no-undefined"
|
||||
fi
|
||||
AC_SUBST([LTUNDEF])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
ffms2.pc
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
791
ffms2/depcomp
Executable file
791
ffms2/depcomp
Executable file
|
@ -0,0 +1,791 @@
|
|||
#! /bin/sh
|
||||
# depcomp - compile a program generating dependencies as side-effects
|
||||
|
||||
scriptversion=2016-01-11.22; # UTC
|
||||
|
||||
# Copyright (C) 1999-2017 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try '$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Run PROGRAMS ARGS to compile a file, generating dependencies
|
||||
as side-effects.
|
||||
|
||||
Environment variables:
|
||||
depmode Dependency tracking mode.
|
||||
source Source file read by 'PROGRAMS ARGS'.
|
||||
object Object file output by 'PROGRAMS ARGS'.
|
||||
DEPDIR directory where to store dependencies.
|
||||
depfile Dependency file to output.
|
||||
tmpdepfile Temporary file to use when outputting dependencies.
|
||||
libtool Whether libtool is used (yes/no).
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "depcomp $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
# Get the directory component of the given path, and save it in the
|
||||
# global variables '$dir'. Note that this directory component will
|
||||
# be either empty or ending with a '/' character. This is deliberate.
|
||||
set_dir_from ()
|
||||
{
|
||||
case $1 in
|
||||
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
|
||||
*) dir=;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the suffix-stripped basename of the given path, and save it the
|
||||
# global variable '$base'.
|
||||
set_base_from ()
|
||||
{
|
||||
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
|
||||
}
|
||||
|
||||
# If no dependency file was actually created by the compiler invocation,
|
||||
# we still have to create a dummy depfile, to avoid errors with the
|
||||
# Makefile "include basename.Plo" scheme.
|
||||
make_dummy_depfile ()
|
||||
{
|
||||
echo "#dummy" > "$depfile"
|
||||
}
|
||||
|
||||
# Factor out some common post-processing of the generated depfile.
|
||||
# Requires the auxiliary global variable '$tmpdepfile' to be set.
|
||||
aix_post_process_depfile ()
|
||||
{
|
||||
# If the compiler actually managed to produce a dependency file,
|
||||
# post-process it.
|
||||
if test -f "$tmpdepfile"; then
|
||||
# Each line is of the form 'foo.o: dependency.h'.
|
||||
# Do two passes, one to just change these to
|
||||
# $object: dependency.h
|
||||
# and one to simply output
|
||||
# dependency.h:
|
||||
# which is needed to avoid the deleted-header problem.
|
||||
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
|
||||
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
|
||||
} > "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
}
|
||||
|
||||
# A tabulation character.
|
||||
tab=' '
|
||||
# A newline character.
|
||||
nl='
|
||||
'
|
||||
# Character ranges might be problematic outside the C locale.
|
||||
# These definitions help.
|
||||
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
|
||||
lower=abcdefghijklmnopqrstuvwxyz
|
||||
digits=0123456789
|
||||
alpha=${upper}${lower}
|
||||
|
||||
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
|
||||
echo "depcomp: Variables source, object and depmode must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
|
||||
depfile=${depfile-`echo "$object" |
|
||||
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
|
||||
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
|
||||
|
||||
rm -f "$tmpdepfile"
|
||||
|
||||
# Avoid interferences from the environment.
|
||||
gccflag= dashmflag=
|
||||
|
||||
# Some modes work just like other modes, but use different flags. We
|
||||
# parameterize here, but still list the modes in the big case below,
|
||||
# to make depend.m4 easier to write. Note that we *cannot* use a case
|
||||
# here, because this file can only contain one case statement.
|
||||
if test "$depmode" = hp; then
|
||||
# HP compiler uses -M and no extra arg.
|
||||
gccflag=-M
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
if test "$depmode" = dashXmstdout; then
|
||||
# This is just like dashmstdout with a different argument.
|
||||
dashmflag=-xM
|
||||
depmode=dashmstdout
|
||||
fi
|
||||
|
||||
cygpath_u="cygpath -u -f -"
|
||||
if test "$depmode" = msvcmsys; then
|
||||
# This is just like msvisualcpp but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvisualcpp
|
||||
fi
|
||||
|
||||
if test "$depmode" = msvc7msys; then
|
||||
# This is just like msvc7 but w/o cygpath translation.
|
||||
# Just convert the backslash-escaped backslashes to single forward
|
||||
# slashes to satisfy depend.m4
|
||||
cygpath_u='sed s,\\\\,/,g'
|
||||
depmode=msvc7
|
||||
fi
|
||||
|
||||
if test "$depmode" = xlc; then
|
||||
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
|
||||
gccflag=-qmakedep=gcc,-MF
|
||||
depmode=gcc
|
||||
fi
|
||||
|
||||
case "$depmode" in
|
||||
gcc3)
|
||||
## gcc 3 implements dependency tracking that does exactly what
|
||||
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
|
||||
## it if -MD -MP comes after the -MF stuff. Hmm.
|
||||
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
|
||||
## the command line argument order; so add the flags where they
|
||||
## appear in depend2.am. Note that the slowdown incurred here
|
||||
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
|
||||
*) set fnord "$@" "$arg" ;;
|
||||
esac
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
done
|
||||
"$@"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
mv "$tmpdepfile" "$depfile"
|
||||
;;
|
||||
|
||||
gcc)
|
||||
## Note that this doesn't just cater to obsosete pre-3.x GCC compilers.
|
||||
## but also to in-use compilers like IMB xlc/xlC and the HP C compiler.
|
||||
## (see the conditional assignment to $gccflag above).
|
||||
## There are various ways to get dependency output from gcc. Here's
|
||||
## why we pick this rather obscure method:
|
||||
## - Don't want to use -MD because we'd like the dependencies to end
|
||||
## up in a subdir. Having to rename by hand is ugly.
|
||||
## (We might end up doing this anyway to support other compilers.)
|
||||
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
|
||||
## -MM, not -M (despite what the docs say). Also, it might not be
|
||||
## supported by the other compilers which use the 'gcc' depmode.
|
||||
## - Using -M directly means running the compiler twice (even worse
|
||||
## than renaming).
|
||||
if test -z "$gccflag"; then
|
||||
gccflag=-MD,
|
||||
fi
|
||||
"$@" -Wp,"$gccflag$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The second -e expression handles DOS-style file names with drive
|
||||
# letters.
|
||||
sed -e 's/^[^:]*: / /' \
|
||||
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
|
||||
## This next piece of magic avoids the "deleted header file" problem.
|
||||
## The problem is that when a header file which appears in a .P file
|
||||
## is deleted, the dependency causes make to die (because there is
|
||||
## typically no way to rebuild the header). We avoid this by adding
|
||||
## dummy dependencies for each header file. Too bad gcc doesn't do
|
||||
## this for us directly.
|
||||
## Some versions of gcc put a space before the ':'. On the theory
|
||||
## that the space means something, we add a space to the output as
|
||||
## well. hp depmode also adds that space, but also prefixes the VPATH
|
||||
## to the object. Take care to not repeat it in the output.
|
||||
## Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
## correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
sgi)
|
||||
if test "$libtool" = yes; then
|
||||
"$@" "-Wp,-MDupdate,$tmpdepfile"
|
||||
else
|
||||
"$@" -MDupdate "$tmpdepfile"
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
|
||||
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
|
||||
echo "$object : \\" > "$depfile"
|
||||
# Clip off the initial element (the dependent). Don't try to be
|
||||
# clever and replace this with sed code, as IRIX sed won't handle
|
||||
# lines with more than a fixed number of characters (4096 in
|
||||
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
|
||||
# the IRIX cc adds comments like '#:fec' to the end of the
|
||||
# dependency line.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
|
||||
| tr "$nl" ' ' >> "$depfile"
|
||||
echo >> "$depfile"
|
||||
# The second pass generates a dummy entry for each header file.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
|
||||
>> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
xlc)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
aix)
|
||||
# The C for AIX Compiler uses -M and outputs the dependencies
|
||||
# in a .u file. In older versions, this file always lives in the
|
||||
# current directory. Also, the AIX compiler puts '$object:' at the
|
||||
# start of each line; $object doesn't have directory information.
|
||||
# Version 6 uses the directory in both cases.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$base.u
|
||||
tmpdepfile3=$dir.libs/$base.u
|
||||
"$@" -Wc,-M
|
||||
else
|
||||
tmpdepfile1=$dir$base.u
|
||||
tmpdepfile2=$dir$base.u
|
||||
tmpdepfile3=$dir$base.u
|
||||
"$@" -M
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
tcc)
|
||||
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
|
||||
# FIXME: That version still under development at the moment of writing.
|
||||
# Make that this statement remains true also for stable, released
|
||||
# versions.
|
||||
# It will wrap lines (doesn't matter whether long or short) with a
|
||||
# trailing '\', as in:
|
||||
#
|
||||
# foo.o : \
|
||||
# foo.c \
|
||||
# foo.h \
|
||||
#
|
||||
# It will put a trailing '\' even on the last line, and will use leading
|
||||
# spaces rather than leading tabs (at least since its commit 0394caf7
|
||||
# "Emit spaces for -MD").
|
||||
"$@" -MD -MF "$tmpdepfile"
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
|
||||
# We have to change lines of the first kind to '$object: \'.
|
||||
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
|
||||
# And for each line of the second kind, we have to emit a 'dep.h:'
|
||||
# dummy dependency, to avoid the deleted-header problem.
|
||||
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
## The order of this option in the case statement is important, since the
|
||||
## shell code in configure will try each of these formats in the order
|
||||
## listed in this file. A plain '-MD' option would be understood by many
|
||||
## compilers, so we must ensure this comes after the gcc and icc options.
|
||||
pgcc)
|
||||
# Portland's C compiler understands '-MD'.
|
||||
# Will always output deps to 'file.d' where file is the root name of the
|
||||
# source file under compilation, even if file resides in a subdirectory.
|
||||
# The object file name does not affect the name of the '.d' file.
|
||||
# pgcc 10.2 will output
|
||||
# foo.o: sub/foo.c sub/foo.h
|
||||
# and will wrap long lines using '\' :
|
||||
# foo.o: sub/foo.c ... \
|
||||
# sub/foo.h ... \
|
||||
# ...
|
||||
set_dir_from "$object"
|
||||
# Use the source, not the object, to determine the base name, since
|
||||
# that's sadly what pgcc will do too.
|
||||
set_base_from "$source"
|
||||
tmpdepfile=$base.d
|
||||
|
||||
# For projects that build the same source file twice into different object
|
||||
# files, the pgcc approach of using the *source* file root name can cause
|
||||
# problems in parallel builds. Use a locking strategy to avoid stomping on
|
||||
# the same $tmpdepfile.
|
||||
lockdir=$base.d-lock
|
||||
trap "
|
||||
echo '$0: caught signal, cleaning up...' >&2
|
||||
rmdir '$lockdir'
|
||||
exit 1
|
||||
" 1 2 13 15
|
||||
numtries=100
|
||||
i=$numtries
|
||||
while test $i -gt 0; do
|
||||
# mkdir is a portable test-and-set.
|
||||
if mkdir "$lockdir" 2>/dev/null; then
|
||||
# This process acquired the lock.
|
||||
"$@" -MD
|
||||
stat=$?
|
||||
# Release the lock.
|
||||
rmdir "$lockdir"
|
||||
break
|
||||
else
|
||||
# If the lock is being held by a different process, wait
|
||||
# until the winning process is done or we timeout.
|
||||
while test -d "$lockdir" && test $i -gt 0; do
|
||||
sleep 1
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
fi
|
||||
i=`expr $i - 1`
|
||||
done
|
||||
trap - 1 2 13 15
|
||||
if test $i -le 0; then
|
||||
echo "$0: failed to acquire lock after $numtries attempts" >&2
|
||||
echo "$0: check lockdir '$lockdir'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
# Each line is of the form `foo.o: dependent.h',
|
||||
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
|
||||
# Do two passes, one to just change these to
|
||||
# `$object: dependent.h' and one to simply `dependent.h:'.
|
||||
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
hp2)
|
||||
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
|
||||
# compilers, which have integrated preprocessors. The correct option
|
||||
# to use with these is +Maked; it writes dependencies to a file named
|
||||
# 'foo.d', which lands next to the object file, wherever that
|
||||
# happens to be.
|
||||
# Much of this is similar to the tru64 case; see comments there.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
if test "$libtool" = yes; then
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir.libs/$base.d
|
||||
"$@" -Wc,+Maked
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
"$@" +Maked
|
||||
fi
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
if test -f "$tmpdepfile"; then
|
||||
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
|
||||
# Add 'dependent.h:' lines.
|
||||
sed -ne '2,${
|
||||
s/^ *//
|
||||
s/ \\*$//
|
||||
s/$/:/
|
||||
p
|
||||
}' "$tmpdepfile" >> "$depfile"
|
||||
else
|
||||
make_dummy_depfile
|
||||
fi
|
||||
rm -f "$tmpdepfile" "$tmpdepfile2"
|
||||
;;
|
||||
|
||||
tru64)
|
||||
# The Tru64 compiler uses -MD to generate dependencies as a side
|
||||
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
|
||||
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
|
||||
# dependencies in 'foo.d' instead, so we check for that too.
|
||||
# Subdirectories are respected.
|
||||
set_dir_from "$object"
|
||||
set_base_from "$object"
|
||||
|
||||
if test "$libtool" = yes; then
|
||||
# Libtool generates 2 separate objects for the 2 libraries. These
|
||||
# two compilations output dependencies in $dir.libs/$base.o.d and
|
||||
# in $dir$base.o.d. We have to check for both files, because
|
||||
# one of the two compilations can be disabled. We should prefer
|
||||
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
|
||||
# automatically cleaned when .libs/ is deleted, while ignoring
|
||||
# the former would cause a distcleancheck panic.
|
||||
tmpdepfile1=$dir$base.o.d # libtool 1.5
|
||||
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
|
||||
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
|
||||
"$@" -Wc,-MD
|
||||
else
|
||||
tmpdepfile1=$dir$base.d
|
||||
tmpdepfile2=$dir$base.d
|
||||
tmpdepfile3=$dir$base.d
|
||||
"$@" -MD
|
||||
fi
|
||||
|
||||
stat=$?
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
exit $stat
|
||||
fi
|
||||
|
||||
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
|
||||
do
|
||||
test -f "$tmpdepfile" && break
|
||||
done
|
||||
# Same post-processing that is required for AIX mode.
|
||||
aix_post_process_depfile
|
||||
;;
|
||||
|
||||
msvc7)
|
||||
if test "$libtool" = yes; then
|
||||
showIncludes=-Wc,-showIncludes
|
||||
else
|
||||
showIncludes=-showIncludes
|
||||
fi
|
||||
"$@" $showIncludes > "$tmpdepfile"
|
||||
stat=$?
|
||||
grep -v '^Note: including file: ' "$tmpdepfile"
|
||||
if test $stat -ne 0; then
|
||||
rm -f "$tmpdepfile"
|
||||
exit $stat
|
||||
fi
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
# The first sed program below extracts the file names and escapes
|
||||
# backslashes for cygpath. The second sed program outputs the file
|
||||
# name when reading, but also accumulates all include files in the
|
||||
# hold buffer in order to output them again at the end. This only
|
||||
# works with sed implementations that can handle large buffers.
|
||||
sed < "$tmpdepfile" -n '
|
||||
/^Note: including file: *\(.*\)/ {
|
||||
s//\1/
|
||||
s/\\/\\\\/g
|
||||
p
|
||||
}' | $cygpath_u | sort -u | sed -n '
|
||||
s/ /\\ /g
|
||||
s/\(.*\)/'"$tab"'\1 \\/p
|
||||
s/.\(.*\) \\/\1:/
|
||||
H
|
||||
$ {
|
||||
s/.*/'"$tab"'/
|
||||
G
|
||||
p
|
||||
}' >> "$depfile"
|
||||
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvc7msys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
#nosideeffect)
|
||||
# This comment above is used by automake to tell side-effect
|
||||
# dependency tracking mechanisms from slower ones.
|
||||
|
||||
dashmstdout)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout, regardless of -o.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
test -z "$dashmflag" && dashmflag=-M
|
||||
# Require at least two characters before searching for ':'
|
||||
# in the target name. This is to cope with DOS-style filenames:
|
||||
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
|
||||
"$@" $dashmflag |
|
||||
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
cat < "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process this sed invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
tr ' ' "$nl" < "$tmpdepfile" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
dashXmstdout)
|
||||
# This case only exists to satisfy depend.m4. It is never actually
|
||||
# run, as this mode is specially recognized in the preamble.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
makedepend)
|
||||
"$@" || exit $?
|
||||
# Remove any Libtool call
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
# X makedepend
|
||||
shift
|
||||
cleared=no eat=no
|
||||
for arg
|
||||
do
|
||||
case $cleared in
|
||||
no)
|
||||
set ""; shift
|
||||
cleared=yes ;;
|
||||
esac
|
||||
if test $eat = yes; then
|
||||
eat=no
|
||||
continue
|
||||
fi
|
||||
case "$arg" in
|
||||
-D*|-I*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
# Strip any option that makedepend may not understand. Remove
|
||||
# the object too, otherwise makedepend will parse it as a source file.
|
||||
-arch)
|
||||
eat=yes ;;
|
||||
-*|$object)
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"; shift ;;
|
||||
esac
|
||||
done
|
||||
obj_suffix=`echo "$object" | sed 's/^.*\././'`
|
||||
touch "$tmpdepfile"
|
||||
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
|
||||
rm -f "$depfile"
|
||||
# makedepend may prepend the VPATH from the source file name to the object.
|
||||
# No need to regex-escape $object, excess matching of '.' is harmless.
|
||||
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
|
||||
# Some versions of the HPUX 10.20 sed can't process the last invocation
|
||||
# correctly. Breaking it into two sed invocations is a workaround.
|
||||
sed '1,2d' "$tmpdepfile" \
|
||||
| tr ' ' "$nl" \
|
||||
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
|
||||
| sed -e 's/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile" "$tmpdepfile".bak
|
||||
;;
|
||||
|
||||
cpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
# Remove '-o $object'.
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case $arg in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift # fnord
|
||||
shift # $arg
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
"$@" -E \
|
||||
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
|
||||
| sed '$ s: \\$::' > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
cat < "$tmpdepfile" >> "$depfile"
|
||||
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvisualcpp)
|
||||
# Important note: in order to support this mode, a compiler *must*
|
||||
# always write the preprocessed file to stdout.
|
||||
"$@" || exit $?
|
||||
|
||||
# Remove the call to Libtool.
|
||||
if test "$libtool" = yes; then
|
||||
while test "X$1" != 'X--mode=compile'; do
|
||||
shift
|
||||
done
|
||||
shift
|
||||
fi
|
||||
|
||||
IFS=" "
|
||||
for arg
|
||||
do
|
||||
case "$arg" in
|
||||
-o)
|
||||
shift
|
||||
;;
|
||||
$object)
|
||||
shift
|
||||
;;
|
||||
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
|
||||
set fnord "$@"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set fnord "$@" "$arg"
|
||||
shift
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
"$@" -E 2>/dev/null |
|
||||
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
|
||||
rm -f "$depfile"
|
||||
echo "$object : \\" > "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
|
||||
echo "$tab" >> "$depfile"
|
||||
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
|
||||
rm -f "$tmpdepfile"
|
||||
;;
|
||||
|
||||
msvcmsys)
|
||||
# This case exists only to let depend.m4 do its work. It works by
|
||||
# looking at the text of this script. This case will never be run,
|
||||
# since it is checked for above.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
none)
|
||||
exec "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Unknown depmode $depmode" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC0"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -65,7 +65,7 @@ If you want a progress report on the indexing, you can use the supplied `ffmsind
|
|||
### FFIndex
|
||||
```
|
||||
FFIndex(string source, string cachefile = source + ".ffindex", int indexmask = -1,
|
||||
int errorhandling = 3, bool overwrite = false, bool enable_drefs = false, bool use_absolute_path = false)
|
||||
int errorhandling = 3, bool overwrite = false)
|
||||
```
|
||||
Indexes a number of tracks in a given source file and writes the index file to disk, where it can be picked up and used by `FFVideoSource` or `FFAudioSource`.
|
||||
Normally you do not need to call this function manually; it's invoked automatically if necessary by `FFVideoSource`/`FFAudioSource`.
|
||||
|
@ -106,12 +106,6 @@ Possible values are:
|
|||
If set to true, `FFIndex()` will reindex the source file and overwrite the index file even if the index file already exists and is valid.
|
||||
Mostly useful for trackmask changes and testing.
|
||||
|
||||
##### bint enable_drefs = False
|
||||
Corresponds to the FFmpeg demuxer option of the same name. You will know if you need it.
|
||||
|
||||
##### bint use_absolute_path = False
|
||||
Corresponds to the FFmpeg demuxer option of the same name. You will know if you need it.
|
||||
|
||||
### FFVideoSource
|
||||
```
|
||||
FFVideoSource(string source, int track = -1, bool cache = true,
|
||||
|
@ -214,14 +208,13 @@ For convenience the last used FFMS function in a script sets the global variable
|
|||
```
|
||||
FFAudioSource(string source, int track = -1, bool cache = true,
|
||||
string cachefile = source + ".ffindex", int adjustdelay = -1,
|
||||
int fillgaps = -1, float drc_scale = 0,
|
||||
string varprefix = "")
|
||||
```
|
||||
Opens audio.
|
||||
Invokes indexing of all tracks if no valid index file is found, or if the requested track isn't present in the index.
|
||||
|
||||
#### Arguments
|
||||
Are exactly the same as to `FFVideoSource`, but with these additional options:
|
||||
Are exactly the same as to `FFVideoSource`, with one exception:
|
||||
|
||||
##### int adjustdelay = -1
|
||||
Controls how audio delay is handled, i.e. what happens if the first audio sample in the file doesn't have a timestamp of zero.
|
||||
|
@ -236,15 +229,6 @@ The following arguments are valid:
|
|||
-2 obviously does the same thing as -1 if the first video frame of the first video track starts at time zero.
|
||||
In some containers this will always be the case, in others (most notably 188-byte MPEG TS) it will almost never happen.
|
||||
|
||||
##### int fillgaps = -1
|
||||
Determines how audio with discontinuous timestamps are handled.
|
||||
- **-1**: Apply zero filled gaps to audio in containers where it's usually necessary.
|
||||
- **0**: Never zero fill gaps.
|
||||
- **1**: Always zero fill gaps.
|
||||
|
||||
##### float drc_scale = 0
|
||||
Controls the amount of DRC that's applied to (E)AC-3 audio. 0 means no DRC and 1 means fully applied DRC in accordance with how it's flagged in the stream.
|
||||
|
||||
### FFmpegSource2/FFMS2
|
||||
```
|
||||
FFmpegSource2/FFMS2(string source, int vtrack = -1, int atrack = -2, bool cache = true,
|
|
@ -1,26 +1,6 @@
|
|||
# FFmpegSource2 Changelog
|
||||
- 2.xxx
|
||||
- Fixed all issues with FFmpeg 6.0 which is now the minimum requirement
|
||||
- Added HDR10+ and DolbyVision metadata
|
||||
- Fixed audio decoding that could otherwise get stuck in an infinite loop on certain files
|
||||
- Fixed framerate in Avisynth when using VFR=>CFR mode
|
||||
- Dropped VapourSynth API3 support
|
||||
- Indexer now has a configurable progress update interval
|
||||
- Alpha planes are now correctly marked as being full range
|
||||
- The full set of demuxer options can now be passed using the FFMS2 API
|
||||
- Now sets channel layout in Avisynth+
|
||||
|
||||
- 2.3000
|
||||
- Added support for VapourSynth API4 (Myrsloik)
|
||||
- Added basic Avisynth+ frame property support (Myrsloik)
|
||||
- Added Rotation and Flip properties for VapourSynth (Myrsloik)
|
||||
- Added long path support for ffmsindex in windows (Myrsloik)
|
||||
- The audio gap fill logic is now optional and usually disabled by default (Myrsloik)
|
||||
- Allow the drc_scale option to be set when decoding audio (Myrsloik)
|
||||
- Allow the enable_drefs and use_absolute_path demuxer options to be used when indexing (Myrsloik)
|
||||
|
||||
- 2.40
|
||||
- Avisynth+ linux support (qyot27)
|
||||
- 2.2000
|
||||
- Added LastEndTime track property to make it possible to take the last frame's duration into account (Myrsloik)
|
||||
- Removed several deprecated functions and enums from the API (Myrsloik)
|
||||
- No longer assumes sub 1 fps framerates are invalid (Myrsloik)
|
|
@ -44,7 +44,7 @@ If you want a progress report on the indexing, you can use the supplied `ffmsind
|
|||
### Index
|
||||
```
|
||||
ffms2.Index(string source[, string cachefile = source + ".ffindex", int[] indextracks = [],
|
||||
int errorhandling = 3, bint overwrite = False, bint enable_drefs = False, bint use_absolute_path = False])
|
||||
int errorhandling = 3, bint overwrite = False])
|
||||
```
|
||||
Indexes a number of tracks in a given source file and writes the index file to disk, where it can be picked up and used by `Source`.
|
||||
Normally you do not need to call this function manually; it's invoked automatically if necessary by `Source`.
|
||||
|
@ -81,12 +81,6 @@ Possible values are:
|
|||
If set to true, `FFIndex()` will reindex the source file and overwrite the index file even if the index file already exists and is valid.
|
||||
Mostly useful for trackmask changes and testing.
|
||||
|
||||
##### bint enable_drefs = False
|
||||
Corresponds to the FFmpeg demuxer option of the same name. You will know if you need it.
|
||||
|
||||
##### bint use_absolute_path = False
|
||||
Corresponds to the FFmpeg demuxer option of the same name. You will know if you need it.
|
||||
|
||||
### Source
|
||||
```
|
||||
ffms2.Source(string source[, int track = -1, bint cache = True,
|
|
@ -22,7 +22,7 @@
|
|||
#define FFMS_H
|
||||
|
||||
// Version format: major - minor - micro - bump
|
||||
#define FFMS_VERSION ((3 << 24) | (1 << 16) | (1 << 8) | 0)
|
||||
#define FFMS_VERSION ((2 << 24) | (31 << 16) | (0 << 8) | 0)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
@ -206,12 +206,6 @@ typedef enum FFMS_AudioDelayModes {
|
|||
FFMS_DELAY_FIRST_VIDEO_TRACK = -1
|
||||
} FFMS_AudioDelayModes;
|
||||
|
||||
typedef enum FFMS_AudioGapFillModes {
|
||||
FFMS_GAP_FILL_AUTO = -1,
|
||||
FFMS_GAP_FILL_DISABLED = 0,
|
||||
FFMS_GAP_FILL_ENABLED = -1
|
||||
} FFMS_AudioGapFillModes;
|
||||
|
||||
typedef enum FFMS_ChromaLocations {
|
||||
FFMS_LOC_UNSPECIFIED = 0,
|
||||
FFMS_LOC_LEFT = 1,
|
||||
|
@ -338,12 +332,6 @@ typedef struct FFMS_Frame {
|
|||
int HasContentLightLevel; /* Non-zero if the 2 fields below are valid */
|
||||
unsigned int ContentLightLevelMax;
|
||||
unsigned int ContentLightLevelAverage;
|
||||
/* Introduced in FFMS_VERSION ((3 << 24) | (0 << 16) | (1 << 8) | 0) */
|
||||
uint8_t *DolbyVisionRPU;
|
||||
int DolbyVisionRPUSize;
|
||||
/* Introduced in FFMS_VERSION ((3 << 24) | (1 << 16) | (1 << 8) | 0) */
|
||||
uint8_t *HDR10Plus;
|
||||
int HDR10PlusSize;
|
||||
} FFMS_Frame;
|
||||
|
||||
typedef struct FFMS_TrackTimeBase {
|
||||
|
@ -376,7 +364,7 @@ typedef struct FFMS_VideoProperties {
|
|||
double FirstTime;
|
||||
double LastTime;
|
||||
/* Introduced in FFMS_VERSION ((2 << 24) | (24 << 16) | (0 << 8) | 0) */
|
||||
int Rotation; /* A positive number in degrees */
|
||||
int Rotation;
|
||||
int Stereo3DType;
|
||||
int Stereo3DFlags;
|
||||
/* Introduced in FFMS_VERSION ((2 << 24) | (30 << 16) | (0 << 8) | 0) */
|
||||
|
@ -393,7 +381,7 @@ typedef struct FFMS_VideoProperties {
|
|||
unsigned int ContentLightLevelMax;
|
||||
unsigned int ContentLightLevelAverage;
|
||||
/* Introduced in FFMS_VERSION ((2 << 24) | (31 << 16) | (0 << 8) | 0) */
|
||||
int Flip; /* -1 = Vertical flip, 1 = Horizontal flip */
|
||||
int Flip;
|
||||
} FFMS_VideoProperties;
|
||||
|
||||
typedef struct FFMS_AudioProperties {
|
||||
|
@ -409,11 +397,6 @@ typedef struct FFMS_AudioProperties {
|
|||
double LastEndTime;
|
||||
} FFMS_AudioProperties;
|
||||
|
||||
typedef struct FFMS_KeyValuePair {
|
||||
const char *Key;
|
||||
const char *Value;
|
||||
} FFMS_KeyValuePair;
|
||||
|
||||
typedef int (FFMS_CC *TIndexCallback)(int64_t Current, int64_t Total, void *ICPrivate);
|
||||
|
||||
/* Most functions return 0 on success */
|
||||
|
@ -425,7 +408,6 @@ FFMS_API(int) FFMS_GetLogLevel();
|
|||
FFMS_API(void) FFMS_SetLogLevel(int Level);
|
||||
FFMS_API(FFMS_VideoSource *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FFMS_Index *Index, int Threads, int SeekMode, FFMS_ErrorInfo *ErrorInfo);
|
||||
FFMS_API(FFMS_AudioSource *) FFMS_CreateAudioSource(const char *SourceFile, int Track, FFMS_Index *Index, int DelayMode, FFMS_ErrorInfo *ErrorInfo);
|
||||
FFMS_API(FFMS_AudioSource *) FFMS_CreateAudioSource2(const char *SourceFile, int Track, FFMS_Index *Index, int DelayMode, int FillGaps, double DrcScale, FFMS_ErrorInfo *ErrorInfo);
|
||||
FFMS_API(void) FFMS_DestroyVideoSource(FFMS_VideoSource *V);
|
||||
FFMS_API(void) FFMS_DestroyAudioSource(FFMS_AudioSource *A);
|
||||
FFMS_API(const FFMS_VideoProperties *) FFMS_GetVideoProperties(FFMS_VideoSource *V);
|
||||
|
@ -458,7 +440,6 @@ FFMS_API(FFMS_Track *) FFMS_GetTrackFromAudio(FFMS_AudioSource *A);
|
|||
FFMS_API(const FFMS_TrackTimeBase *) FFMS_GetTimeBase(FFMS_Track *T);
|
||||
FFMS_API(int) FFMS_WriteTimecodes(FFMS_Track *T, const char *TimecodeFile, FFMS_ErrorInfo *ErrorInfo);
|
||||
FFMS_API(FFMS_Indexer *) FFMS_CreateIndexer(const char *SourceFile, FFMS_ErrorInfo *ErrorInfo);
|
||||
FFMS_API(FFMS_Indexer *) FFMS_CreateIndexer2(const char *SourceFile, const FFMS_KeyValuePair *DemuxerOptions, int NumOptions, FFMS_ErrorInfo *ErrorInfo);
|
||||
FFMS_API(void) FFMS_TrackIndexSettings(FFMS_Indexer *Indexer, int Track, int Index, int); /* Pass 0 to last argument, kapt to preserve abi. Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
|
||||
FFMS_API(void) FFMS_TrackTypeIndexSettings(FFMS_Indexer *Indexer, int TrackType, int Index, int); /* Pass 0 to last argument, kapt to preserve abi. Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
|
||||
FFMS_API(void) FFMS_SetProgressCallback(FFMS_Indexer *Indexer, TIndexCallback IC, void *ICPrivate); /* Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
|
|
@ -21,6 +21,18 @@
|
|||
#ifndef FFMSCOMPAT_H
|
||||
#define FFMSCOMPAT_H
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define ffms_used __attribute__((used))
|
||||
#else
|
||||
# define ffms_used
|
||||
#endif
|
||||
|
||||
#define VERSION_CHECK(LIB, cmp, major, minor, micro) ((LIB) cmp (AV_VERSION_INT(major, minor, micro)))
|
||||
|
||||
#if VERSION_CHECK(LIBAVFORMAT_VERSION_INT, <, 58, 9, 100)
|
||||
# define FFMS_REGISTER() av_register_all();
|
||||
#else
|
||||
# define FFMS_REGISTER()
|
||||
#endif
|
||||
|
||||
#endif // FFMSCOMPAT_H
|
508
ffms2/install-sh
Executable file
508
ffms2/install-sh
Executable file
|
@ -0,0 +1,508 @@
|
|||
#!/bin/sh
|
||||
# install - install a program, script, or datafile
|
||||
|
||||
scriptversion=2014-09-12.12; # UTC
|
||||
|
||||
# This originates from X11R5 (mit/util/scripts/install.sh), which was
|
||||
# later released in X11R6 (xc/config/util/install.sh) with the
|
||||
# following copyright and license.
|
||||
#
|
||||
# Copyright (C) 1994 X Consortium
|
||||
#
|
||||
# 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
|
||||
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
|
||||
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#
|
||||
# Except as contained in this notice, the name of the X Consortium shall not
|
||||
# be used in advertising or otherwise to promote the sale, use or other deal-
|
||||
# ings in this Software without prior written authorization from the X Consor-
|
||||
# tium.
|
||||
#
|
||||
#
|
||||
# FSF changes to this file are in the public domain.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# 'make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch.
|
||||
|
||||
tab=' '
|
||||
nl='
|
||||
'
|
||||
IFS=" $tab$nl"
|
||||
|
||||
# Set DOITPROG to "echo" to test this script.
|
||||
|
||||
doit=${DOITPROG-}
|
||||
doit_exec=${doit:-exec}
|
||||
|
||||
# Put in absolute file names if you don't have them in your path;
|
||||
# or use environment vars.
|
||||
|
||||
chgrpprog=${CHGRPPROG-chgrp}
|
||||
chmodprog=${CHMODPROG-chmod}
|
||||
chownprog=${CHOWNPROG-chown}
|
||||
cmpprog=${CMPPROG-cmp}
|
||||
cpprog=${CPPROG-cp}
|
||||
mkdirprog=${MKDIRPROG-mkdir}
|
||||
mvprog=${MVPROG-mv}
|
||||
rmprog=${RMPROG-rm}
|
||||
stripprog=${STRIPPROG-strip}
|
||||
|
||||
posix_mkdir=
|
||||
|
||||
# Desired mode of installed file.
|
||||
mode=0755
|
||||
|
||||
chgrpcmd=
|
||||
chmodcmd=$chmodprog
|
||||
chowncmd=
|
||||
mvcmd=$mvprog
|
||||
rmcmd="$rmprog -f"
|
||||
stripcmd=
|
||||
|
||||
src=
|
||||
dst=
|
||||
dir_arg=
|
||||
dst_arg=
|
||||
|
||||
copy_on_change=false
|
||||
is_target_a_directory=possibly
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
|
||||
or: $0 [OPTION]... SRCFILES... DIRECTORY
|
||||
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
|
||||
or: $0 [OPTION]... -d DIRECTORIES...
|
||||
|
||||
In the 1st form, copy SRCFILE to DSTFILE.
|
||||
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
|
||||
In the 4th, create DIRECTORIES.
|
||||
|
||||
Options:
|
||||
--help display this help and exit.
|
||||
--version display version info and exit.
|
||||
|
||||
-c (ignored)
|
||||
-C install only if different (preserve the last data modification time)
|
||||
-d create directories instead of installing files.
|
||||
-g GROUP $chgrpprog installed files to GROUP.
|
||||
-m MODE $chmodprog installed files to MODE.
|
||||
-o USER $chownprog installed files to USER.
|
||||
-s $stripprog installed files.
|
||||
-t DIRECTORY install into DIRECTORY.
|
||||
-T report an error if DSTFILE is a directory.
|
||||
|
||||
Environment variables override the default commands:
|
||||
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
|
||||
RMPROG STRIPPROG
|
||||
"
|
||||
|
||||
while test $# -ne 0; do
|
||||
case $1 in
|
||||
-c) ;;
|
||||
|
||||
-C) copy_on_change=true;;
|
||||
|
||||
-d) dir_arg=true;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift;;
|
||||
|
||||
--help) echo "$usage"; exit $?;;
|
||||
|
||||
-m) mode=$2
|
||||
case $mode in
|
||||
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
|
||||
echo "$0: invalid mode: $mode" >&2
|
||||
exit 1;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift;;
|
||||
|
||||
-s) stripcmd=$stripprog;;
|
||||
|
||||
-t)
|
||||
is_target_a_directory=always
|
||||
dst_arg=$2
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
shift;;
|
||||
|
||||
-T) is_target_a_directory=never;;
|
||||
|
||||
--version) echo "$0 $scriptversion"; exit $?;;
|
||||
|
||||
--) shift
|
||||
break;;
|
||||
|
||||
-*) echo "$0: invalid option: $1" >&2
|
||||
exit 1;;
|
||||
|
||||
*) break;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
# We allow the use of options -d and -T together, by making -d
|
||||
# take the precedence; this is for compatibility with GNU install.
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
if test -n "$dst_arg"; then
|
||||
echo "$0: target directory not allowed when installing a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
|
||||
# When -d is used, all remaining arguments are directories to create.
|
||||
# When -t is used, the destination is already specified.
|
||||
# Otherwise, the last argument is the destination. Remove it from $@.
|
||||
for arg
|
||||
do
|
||||
if test -n "$dst_arg"; then
|
||||
# $@ is not empty: it contains at least $arg.
|
||||
set fnord "$@" "$dst_arg"
|
||||
shift # fnord
|
||||
fi
|
||||
shift # arg
|
||||
dst_arg=$arg
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $dst_arg in
|
||||
-* | [=\(\)!]) dst_arg=./$dst_arg;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
if test $# -eq 0; then
|
||||
if test -z "$dir_arg"; then
|
||||
echo "$0: no input file specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
# It's OK to call 'install-sh -d' without argument.
|
||||
# This can happen when creating conditional directories.
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
if test $# -gt 1 || test "$is_target_a_directory" = always; then
|
||||
if test ! -d "$dst_arg"; then
|
||||
echo "$0: $dst_arg: Is not a directory." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -z "$dir_arg"; then
|
||||
do_exit='(exit $ret); exit $ret'
|
||||
trap "ret=129; $do_exit" 1
|
||||
trap "ret=130; $do_exit" 2
|
||||
trap "ret=141; $do_exit" 13
|
||||
trap "ret=143; $do_exit" 15
|
||||
|
||||
# Set umask so as not to create temps with too-generous modes.
|
||||
# However, 'strip' requires both read and write access to temps.
|
||||
case $mode in
|
||||
# Optimize common cases.
|
||||
*644) cp_umask=133;;
|
||||
*755) cp_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw='% 200'
|
||||
fi
|
||||
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
|
||||
*)
|
||||
if test -z "$stripcmd"; then
|
||||
u_plus_rw=
|
||||
else
|
||||
u_plus_rw=,u+rw
|
||||
fi
|
||||
cp_umask=$mode$u_plus_rw;;
|
||||
esac
|
||||
fi
|
||||
|
||||
for src
|
||||
do
|
||||
# Protect names problematic for 'test' and other utilities.
|
||||
case $src in
|
||||
-* | [=\(\)!]) src=./$src;;
|
||||
esac
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
dst=$src
|
||||
dstdir=$dst
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
if test ! -f "$src" && test ! -d "$src"; then
|
||||
echo "$0: $src does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -z "$dst_arg"; then
|
||||
echo "$0: no destination specified." >&2
|
||||
exit 1
|
||||
fi
|
||||
dst=$dst_arg
|
||||
|
||||
# If destination is a directory, append the input filename; won't work
|
||||
# if double slashes aren't ignored.
|
||||
if test -d "$dst"; then
|
||||
if test "$is_target_a_directory" = never; then
|
||||
echo "$0: $dst_arg: Is a directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
dstdir=$dst
|
||||
dst=$dstdir/`basename "$src"`
|
||||
dstdir_status=0
|
||||
else
|
||||
dstdir=`dirname "$dst"`
|
||||
test -d "$dstdir"
|
||||
dstdir_status=$?
|
||||
fi
|
||||
fi
|
||||
|
||||
obsolete_mkdir_used=false
|
||||
|
||||
if test $dstdir_status != 0; then
|
||||
case $posix_mkdir in
|
||||
'')
|
||||
# Create intermediate dirs using mode 755 as modified by the umask.
|
||||
# This is like FreeBSD 'install' as of 1997-10-28.
|
||||
umask=`umask`
|
||||
case $stripcmd.$umask in
|
||||
# Optimize common cases.
|
||||
*[2367][2367]) mkdir_umask=$umask;;
|
||||
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
|
||||
|
||||
*[0-7])
|
||||
mkdir_umask=`expr $umask + 22 \
|
||||
- $umask % 100 % 40 + $umask % 20 \
|
||||
- $umask % 10 % 4 + $umask % 2
|
||||
`;;
|
||||
*) mkdir_umask=$umask,go-w;;
|
||||
esac
|
||||
|
||||
# With -d, create the new directory with the user-specified mode.
|
||||
# Otherwise, rely on $mkdir_umask.
|
||||
if test -n "$dir_arg"; then
|
||||
mkdir_mode=-m$mode
|
||||
else
|
||||
mkdir_mode=
|
||||
fi
|
||||
|
||||
posix_mkdir=false
|
||||
case $umask in
|
||||
*[123567][0-7][0-7])
|
||||
# POSIX mkdir -p sets u+wx bits regardless of umask, which
|
||||
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
|
||||
;;
|
||||
*)
|
||||
# $RANDOM is not portable (e.g. dash); use it when possible to
|
||||
# lower collision chance
|
||||
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
|
||||
trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0
|
||||
|
||||
# As "mkdir -p" follows symlinks and we work in /tmp possibly; so
|
||||
# create the $tmpdir first (and fail if unsuccessful) to make sure
|
||||
# that nobody tries to guess the $tmpdir name.
|
||||
if (umask $mkdir_umask &&
|
||||
$mkdirprog $mkdir_mode "$tmpdir" &&
|
||||
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
|
||||
then
|
||||
if test -z "$dir_arg" || {
|
||||
# Check for POSIX incompatibilities with -m.
|
||||
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
|
||||
# other-writable bit of parent directory when it shouldn't.
|
||||
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
|
||||
test_tmpdir="$tmpdir/a"
|
||||
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
|
||||
case $ls_ld_tmpdir in
|
||||
d????-?r-*) different_mode=700;;
|
||||
d????-?--*) different_mode=755;;
|
||||
*) false;;
|
||||
esac &&
|
||||
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
|
||||
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
|
||||
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
|
||||
}
|
||||
}
|
||||
then posix_mkdir=:
|
||||
fi
|
||||
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
|
||||
else
|
||||
# Remove any dirs left behind by ancient mkdir implementations.
|
||||
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
|
||||
fi
|
||||
trap '' 0;;
|
||||
esac;;
|
||||
esac
|
||||
|
||||
if
|
||||
$posix_mkdir && (
|
||||
umask $mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
|
||||
)
|
||||
then :
|
||||
else
|
||||
|
||||
# The umask is ridiculous, or mkdir does not conform to POSIX,
|
||||
# or it failed possibly due to a race condition. Create the
|
||||
# directory the slow way, step by step, checking for races as we go.
|
||||
|
||||
case $dstdir in
|
||||
/*) prefix='/';;
|
||||
[-=\(\)!]*) prefix='./';;
|
||||
*) prefix='';;
|
||||
esac
|
||||
|
||||
oIFS=$IFS
|
||||
IFS=/
|
||||
set -f
|
||||
set fnord $dstdir
|
||||
shift
|
||||
set +f
|
||||
IFS=$oIFS
|
||||
|
||||
prefixes=
|
||||
|
||||
for d
|
||||
do
|
||||
test X"$d" = X && continue
|
||||
|
||||
prefix=$prefix$d
|
||||
if test -d "$prefix"; then
|
||||
prefixes=
|
||||
else
|
||||
if $posix_mkdir; then
|
||||
(umask=$mkdir_umask &&
|
||||
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
|
||||
# Don't fail if two instances are running concurrently.
|
||||
test -d "$prefix" || exit 1
|
||||
else
|
||||
case $prefix in
|
||||
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
|
||||
*) qprefix=$prefix;;
|
||||
esac
|
||||
prefixes="$prefixes '$qprefix'"
|
||||
fi
|
||||
fi
|
||||
prefix=$prefix/
|
||||
done
|
||||
|
||||
if test -n "$prefixes"; then
|
||||
# Don't fail if two instances are running concurrently.
|
||||
(umask $mkdir_umask &&
|
||||
eval "\$doit_exec \$mkdirprog $prefixes") ||
|
||||
test -d "$dstdir" || exit 1
|
||||
obsolete_mkdir_used=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$dir_arg"; then
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
|
||||
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
|
||||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
|
||||
else
|
||||
|
||||
# Make a couple of temp file names in the proper directory.
|
||||
dsttmp=$dstdir/_inst.$$_
|
||||
rmtmp=$dstdir/_rm.$$_
|
||||
|
||||
# Trap to clean up those temp files at exit.
|
||||
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
|
||||
|
||||
# Copy the file name to the temp name.
|
||||
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits.
|
||||
#
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $cpprog $src $dsttmp" command.
|
||||
#
|
||||
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
|
||||
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
|
||||
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
|
||||
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
|
||||
|
||||
# If -C, don't bother to copy if it wouldn't change the file.
|
||||
if $copy_on_change &&
|
||||
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
|
||||
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
|
||||
set -f &&
|
||||
set X $old && old=:$2:$4:$5:$6 &&
|
||||
set X $new && new=:$2:$4:$5:$6 &&
|
||||
set +f &&
|
||||
test "$old" = "$new" &&
|
||||
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
|
||||
then
|
||||
rm -f "$dsttmp"
|
||||
else
|
||||
# Rename the file to the real destination.
|
||||
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
|
||||
|
||||
# The rename failed, perhaps because mv can't rename something else
|
||||
# to itself, or perhaps because mv is so ancient that it does not
|
||||
# support -f.
|
||||
{
|
||||
# Now remove or move aside any old file at destination location.
|
||||
# We try this two ways since rm can't unlink itself on some
|
||||
# systems and the destination file might be busy for other
|
||||
# reasons. In this case, the final cleanup might fail but the new
|
||||
# file should still install successfully.
|
||||
{
|
||||
test ! -f "$dst" ||
|
||||
$doit $rmcmd -f "$dst" 2>/dev/null ||
|
||||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
|
||||
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
|
||||
} ||
|
||||
{ echo "$0: cannot unlink or rename $dst" >&2
|
||||
(exit 1); exit 1
|
||||
}
|
||||
} &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
$doit $mvcmd "$dsttmp" "$dst"
|
||||
}
|
||||
fi || exit 1
|
||||
|
||||
trap '' 0
|
||||
fi
|
||||
done
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
11156
ffms2/ltmain.sh
Normal file
11156
ffms2/ltmain.sh
Normal file
File diff suppressed because it is too large
Load diff
8387
ffms2/m4/libtool.m4
vendored
Normal file
8387
ffms2/m4/libtool.m4
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
@ -23,12 +23,6 @@
|
|||
#include "avssources.h"
|
||||
#include "../core/utils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define AVS_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define AVS_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
|
||||
static AVSValue __cdecl CreateFFIndex(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
|
||||
if (!Args[0].Defined())
|
||||
Env->ThrowError("FFIndex: No source specified");
|
||||
|
@ -40,8 +34,6 @@ static AVSValue __cdecl CreateFFIndex(AVSValue Args, void* UserData, IScriptEnvi
|
|||
int IndexMask = Args[2].AsInt(-1);
|
||||
int ErrorHandling = Args[3].AsInt(FFMS_IEH_IGNORE);
|
||||
bool OverWrite = Args[4].AsBool(false);
|
||||
bool EnableDrefs = Args[5].AsBool(false);
|
||||
bool UseAbsolutePath = Args[6].AsBool(false);
|
||||
|
||||
std::string DefaultCache(Source);
|
||||
DefaultCache.append(".ffindex");
|
||||
|
@ -51,8 +43,7 @@ static AVSValue __cdecl CreateFFIndex(AVSValue Args, void* UserData, IScriptEnvi
|
|||
ErrorInfo E;
|
||||
FFMS_Index *Index = FFMS_ReadIndex(CacheFile, &E);
|
||||
if (OverWrite || !Index || (Index && FFMS_IndexBelongsToFile(Index, Source, 0) != FFMS_ERROR_SUCCESS)) {
|
||||
FFMS_KeyValuePair LAVFOpts[] = {{ "enable_drefs", EnableDrefs ? "1" : "0" }, { "use_absolute_path", UseAbsolutePath ? "1" : "0" }};
|
||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer2(Source, LAVFOpts, 2, &E);
|
||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(Source, &E);
|
||||
if (!Indexer)
|
||||
Env->ThrowError("FFIndex: %s", E.Buffer);
|
||||
|
||||
|
@ -198,9 +189,7 @@ static AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScri
|
|||
bool Cache = Args[2].AsBool(true);
|
||||
const char *CacheFile = Args[3].AsString("");
|
||||
int AdjustDelay = Args[4].AsInt(-1);
|
||||
int FillGaps = Args[5].AsInt(-1);
|
||||
double DrcScale = Args[6].AsFloat(0);
|
||||
const char *VarPrefix = Args[7].AsString("");
|
||||
const char *VarPrefix = Args[5].AsString("");
|
||||
|
||||
if (Track <= -2)
|
||||
Env->ThrowError("FFAudioSource: No audio track selected");
|
||||
|
@ -278,7 +267,7 @@ static AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScri
|
|||
AvisynthAudioSource *Filter;
|
||||
|
||||
try {
|
||||
Filter = new AvisynthAudioSource(Source, Track, Index, AdjustDelay, FillGaps, DrcScale, VarPrefix, Env);
|
||||
Filter = new AvisynthAudioSource(Source, Track, Index, AdjustDelay, VarPrefix, Env);
|
||||
} catch (...) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
throw;
|
||||
|
@ -289,25 +278,25 @@ static AVSValue __cdecl CreateFFAudioSource(AVSValue Args, void* UserData, IScri
|
|||
}
|
||||
|
||||
static AVSValue __cdecl CreateFFmpegSource2(AVSValue Args, void* UserData, IScriptEnvironment* Env) {
|
||||
const char *FFIArgNames[] = { "source", "cachefile", "indexmask", "overwrite", "enable_drefs", "use_absolute_path"};
|
||||
const char *FFIArgNames[] = { "source", "cachefile", "indexmask", "overwrite" };
|
||||
const char *FFVArgNames[] = { "source", "track", "cache", "cachefile", "fpsnum", "fpsden", "threads", "timecodes", "seekmode", "rffmode", "width", "height", "resizer", "colorspace", "varprefix" };
|
||||
const char *FFAArgNames[] = { "source", "track", "cache", "cachefile", "adjustdelay", "fill_gaps", "drc_scale", "varprefix"};
|
||||
const char *FFAArgNames[] = { "source", "track", "cache", "cachefile", "adjustdelay", "varprefix" };
|
||||
|
||||
bool Cache = Args[3].AsBool(true);
|
||||
bool WithAudio = Args[2].AsInt(-2) > -2;
|
||||
if (Cache) {
|
||||
AVSValue FFIArgs[] = { Args[0], Args[4], WithAudio ? -1 : 0, Args[10], Args[17], Args[18]};
|
||||
AVSValue FFIArgs[] = { Args[0], Args[4], WithAudio ? -1 : 0, Args[10] };
|
||||
static_assert((sizeof(FFIArgs) / sizeof(FFIArgs[0])) == (sizeof(FFIArgNames) / sizeof(FFIArgNames[0])), "Arg error");
|
||||
Env->Invoke("FFIndex", AVSValue(FFIArgs, sizeof(FFIArgs) / sizeof(FFIArgs[0])), FFIArgNames);
|
||||
}
|
||||
|
||||
AVSValue FFVArgs[] = { Args[0], Args[1], Args[3], Args[4], Args[5], Args[6], Args[7], Args[8], Args[9], Args[15], Args[11], Args[12], Args[13], Args[14], Args[21] };
|
||||
AVSValue FFVArgs[] = { Args[0], Args[1], Args[3], Args[4], Args[5], Args[6], Args[7], Args[8], Args[9], Args[15], Args[11], Args[12], Args[13], Args[14], Args[17] };
|
||||
static_assert((sizeof(FFVArgs) / sizeof(FFVArgs[0])) == (sizeof(FFVArgNames) / sizeof(FFVArgNames[0])), "Arg error");
|
||||
AVSValue Video = Env->Invoke("FFVideoSource", AVSValue(FFVArgs, sizeof(FFVArgs) / sizeof(FFVArgs[0])), FFVArgNames);
|
||||
|
||||
AVSValue Audio;
|
||||
if (WithAudio) {
|
||||
AVSValue FFAArgs[] = { Args[0], Args[2], Args[3], Args[4], Args[16], Args[19], Args[20], Args[21] };
|
||||
AVSValue FFAArgs[] = { Args[0], Args[2], Args[3], Args[4], Args[16], Args[17] };
|
||||
static_assert((sizeof(FFAArgs) / sizeof(FFAArgs[0])) == (sizeof(FFAArgNames) / sizeof(FFAArgNames[0])), "Arg error");
|
||||
Audio = Env->Invoke("FFAudioSource", AVSValue(FFAArgs, sizeof(FFAArgs) / sizeof(FFAArgs[0])), FFAArgNames);
|
||||
AVSValue ADArgs[] = { Video, Audio };
|
||||
|
@ -347,15 +336,15 @@ static AVSValue __cdecl FFGetVersion(AVSValue Args, void* UserData, IScriptEnvir
|
|||
|
||||
const AVS_Linkage *AVS_linkage = nullptr;
|
||||
|
||||
extern "C" AVS_EXPORT const char* __stdcall AvisynthPluginInit3(IScriptEnvironment* Env, const AVS_Linkage* const vectors) {
|
||||
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit3(IScriptEnvironment* Env, const AVS_Linkage* const vectors) {
|
||||
AVS_linkage = vectors;
|
||||
|
||||
Env->AddFunction("FFIndex", "[source]s[cachefile]s[indexmask]i[errorhandling]i[overwrite]b[enable_drefs]b[use_absolute_path]b", CreateFFIndex, nullptr);
|
||||
Env->AddFunction("FFIndex", "[source]s[cachefile]s[indexmask]i[errorhandling]i[overwrite]b", CreateFFIndex, nullptr);
|
||||
Env->AddFunction("FFVideoSource", "[source]s[track]i[cache]b[cachefile]s[fpsnum]i[fpsden]i[threads]i[timecodes]s[seekmode]i[rffmode]i[width]i[height]i[resizer]s[colorspace]s[varprefix]s", CreateFFVideoSource, nullptr);
|
||||
Env->AddFunction("FFAudioSource", "[source]s[track]i[cache]b[cachefile]s[adjustdelay]i[fill_gaps]i[drc_scale]f[varprefix]s", CreateFFAudioSource, nullptr);
|
||||
Env->AddFunction("FFAudioSource", "[source]s[track]i[cache]b[cachefile]s[adjustdelay]i[varprefix]s", CreateFFAudioSource, nullptr);
|
||||
|
||||
Env->AddFunction("FFmpegSource2", "[source]s[vtrack]i[atrack]i[cache]b[cachefile]s[fpsnum]i[fpsden]i[threads]i[timecodes]s[seekmode]i[overwrite]b[width]i[height]i[resizer]s[colorspace]s[rffmode]i[adjustdelay]i[enable_drefs]b[use_absolute_path]b[fill_gaps]i[drc_scale]f[varprefix]s", CreateFFmpegSource2, nullptr);
|
||||
Env->AddFunction("FFMS2", "[source]s[vtrack]i[atrack]i[cache]b[cachefile]s[fpsnum]i[fpsden]i[threads]i[timecodes]s[seekmode]i[overwrite]b[width]i[height]i[resizer]s[colorspace]s[rffmode]i[adjustdelay]i[enable_drefs]b[use_absolute_path]b[fill_gaps]i[drc_scale]f[varprefix]s", CreateFFmpegSource2, nullptr);
|
||||
Env->AddFunction("FFmpegSource2", "[source]s[vtrack]i[atrack]i[cache]b[cachefile]s[fpsnum]i[fpsden]i[threads]i[timecodes]s[seekmode]i[overwrite]b[width]i[height]i[resizer]s[colorspace]s[rffmode]i[adjustdelay]i[varprefix]s", CreateFFmpegSource2, nullptr);
|
||||
Env->AddFunction("FFMS2", "[source]s[vtrack]i[atrack]i[cache]b[cachefile]s[fpsnum]i[fpsden]i[threads]i[timecodes]s[seekmode]i[overwrite]b[width]i[height]i[resizer]s[colorspace]s[rffmode]i[adjustdelay]i[varprefix]s", CreateFFmpegSource2, nullptr);
|
||||
|
||||
Env->AddFunction("FFImageSource", "[source]s[width]i[height]i[resizer]s[colorspace]s[varprefix]s", CreateFFImageSource, nullptr);
|
||||
Env->AddFunction("FFCopyrightInfringement", "[source]s", CreateFFCopyrightInfringement, nullptr);
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
#define NOMINMAX
|
||||
#include "avssources.h"
|
||||
#include "../vapoursynth/VSHelper4.h"
|
||||
#include "../core/utils.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -152,7 +151,7 @@ AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, FFMS
|
|||
Env->ThrowError("FFVideoSource: No RFF flags present");
|
||||
}
|
||||
|
||||
int RepeatMin = FFMS_GetFrameInfo(VTrack, 0)->RepeatPict;
|
||||
int RepeatMin = FFMS_GetFrameInfo(VTrack, 0)->RepeatPict;;
|
||||
int NumFields = 0;
|
||||
|
||||
for (int i = 0; i < VP->NumFrames; i++) {
|
||||
|
@ -256,13 +255,6 @@ AvisynthVideoSource::AvisynthVideoSource(const char *SourceFile, int Track, FFMS
|
|||
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFCROP_BOTTOM"), VP->CropBottom);
|
||||
|
||||
Env->SetGlobalVar("FFVAR_PREFIX", this->VarPrefix);
|
||||
|
||||
has_at_least_v8 = true;
|
||||
try {
|
||||
Env->CheckVersion(8);
|
||||
} catch (const AvisynthError &) {
|
||||
has_at_least_v8 = false;
|
||||
}
|
||||
}
|
||||
|
||||
AvisynthVideoSource::~AvisynthVideoSource() {
|
||||
|
@ -533,12 +525,10 @@ PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
|
|||
n = std::min(std::max(n, 0), VI.num_frames - 1);
|
||||
|
||||
PVideoFrame Dst = Env->NewVideoFrame(VI);
|
||||
AVSMap *props = has_at_least_v8 ? Env->getFramePropsRW(Dst) : nullptr;
|
||||
|
||||
ErrorInfo E;
|
||||
const FFMS_Frame *Frame;
|
||||
if (RFFMode > 0) {
|
||||
Frame = FFMS_GetFrame(V, std::min(FieldList[n].Top, FieldList[n].Bottom), &E);
|
||||
const FFMS_Frame *Frame = FFMS_GetFrame(V, std::min(FieldList[n].Top, FieldList[n].Bottom), &E);
|
||||
if (Frame == nullptr)
|
||||
Env->ThrowError("FFVideoSource: %s", E.Buffer);
|
||||
if (FieldList[n].Top == FieldList[n].Bottom) {
|
||||
|
@ -553,42 +543,18 @@ PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
|
|||
}
|
||||
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), -1);
|
||||
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFPICT_TYPE"), static_cast<int>('U'));
|
||||
if (has_at_least_v8) {
|
||||
Env->propSetInt(props, "_DurationNum", FPSNum, 0);
|
||||
Env->propSetInt(props, "_DurationDen", FPSDen, 0);
|
||||
// don't set absolute time since it's ill-defined
|
||||
}
|
||||
} else {
|
||||
const FFMS_Frame *Frame;
|
||||
|
||||
if (FPSNum > 0 && FPSDen > 0) {
|
||||
double currentTime = FFMS_GetVideoProperties(V)->FirstTime +
|
||||
(double)(n * (int64_t)FPSDen) / FPSNum;
|
||||
Frame = FFMS_GetFrameByTime(V, currentTime, &E);
|
||||
Frame = FFMS_GetFrameByTime(V, FFMS_GetVideoProperties(V)->FirstTime +
|
||||
(double)(n * (int64_t)FPSDen) / FPSNum, &E);
|
||||
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), -1);
|
||||
if (has_at_least_v8) {
|
||||
Env->propSetInt(props, "_DurationNum", FPSDen, 0);
|
||||
Env->propSetInt(props, "_DurationDen", FPSNum, 0);
|
||||
Env->propSetFloat(props, "_AbsoluteTime", currentTime, 0);
|
||||
}
|
||||
} else {
|
||||
Frame = FFMS_GetFrame(V, n, &E);
|
||||
FFMS_Track *T = FFMS_GetTrackFromVideo(V);
|
||||
const FFMS_TrackTimeBase *TB = FFMS_GetTimeBase(T);
|
||||
Env->SetVar(Env->Sprintf("%s%s", this->VarPrefix, "FFVFR_TIME"), static_cast<int>(FFMS_GetFrameInfo(T, n)->PTS * static_cast<double>(TB->Num) / TB->Den));
|
||||
if (has_at_least_v8) {
|
||||
int64_t num;
|
||||
if (n + 1 < VI.num_frames)
|
||||
num = FFMS_GetFrameInfo(T, n + 1)->PTS - FFMS_GetFrameInfo(T, n)->PTS;
|
||||
else if (n > 0) // simply use the second to last frame's duration for the last one, should be good enough
|
||||
num = FFMS_GetFrameInfo(T, n)->PTS - FFMS_GetFrameInfo(T, n - 1)->PTS;
|
||||
else // just make it one timebase if it's a single frame clip
|
||||
num = 1;
|
||||
int64_t DurNum = TB->Num * num;
|
||||
int64_t DurDen = TB->Den * 1000;
|
||||
vsh::muldivRational(&DurNum, &DurDen, 1, 1);
|
||||
Env->propSetInt(props, "_DurationNum", DurNum, 0);
|
||||
Env->propSetInt(props, "_DurationDen", DurDen, 0);
|
||||
Env->propSetFloat(props, "_AbsoluteTime", ((static_cast<double>(TB->Num) / 1000) * FFMS_GetFrameInfo(T, n)->PTS) / TB->Den, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (Frame == nullptr)
|
||||
|
@ -598,58 +564,6 @@ PVideoFrame AvisynthVideoSource::GetFrame(int n, IScriptEnvironment *Env) {
|
|||
OutputFrame(Frame, Dst, Env);
|
||||
}
|
||||
|
||||
if (has_at_least_v8) {
|
||||
const FFMS_VideoProperties *VP = FFMS_GetVideoProperties(V);
|
||||
if (VP->SARNum > 0 && VP->SARDen > 0) {
|
||||
Env->propSetInt(props, "_SARNum", VP->SARNum, 0);
|
||||
Env->propSetInt(props, "_SARDen", VP->SARDen, 0);
|
||||
}
|
||||
|
||||
Env->propSetInt(props, "_Matrix", Frame->ColorSpace, 0);
|
||||
Env->propSetInt(props, "_Primaries", Frame->ColorPrimaries, 0);
|
||||
Env->propSetInt(props, "_Transfer", Frame->TransferCharateristics, 0);
|
||||
if (Frame->ChromaLocation > 0)
|
||||
Env->propSetInt(props, "_ChromaLocation", Frame->ChromaLocation - 1, 0);
|
||||
|
||||
if (Frame->ColorRange == FFMS_CR_MPEG)
|
||||
Env->propSetInt(props, "_ColorRange", 1, 0);
|
||||
else if (Frame->ColorRange == FFMS_CR_JPEG)
|
||||
Env->propSetInt(props, "_ColorRange", 0, 0);
|
||||
if (RFFMode == 0)
|
||||
Env->propSetData(props, "_PictType", &Frame->PictType, 1, 0);
|
||||
|
||||
// Set field information
|
||||
int FieldBased = 0;
|
||||
if (Frame->InterlacedFrame)
|
||||
FieldBased = (Frame->TopFieldFirst ? 2 : 1);
|
||||
Env->propSetInt(props, "_FieldBased", FieldBased, 0);
|
||||
|
||||
if (Frame->HasMasteringDisplayPrimaries) {
|
||||
Env->propSetFloatArray(props, "MasteringDisplayPrimariesX", Frame->MasteringDisplayPrimariesX, 3);
|
||||
Env->propSetFloatArray(props, "MasteringDisplayPrimariesY", Frame->MasteringDisplayPrimariesY, 3);
|
||||
Env->propSetFloat(props, "MasteringDisplayWhitePointX", Frame->MasteringDisplayWhitePointX, 0);
|
||||
Env->propSetFloat(props, "MasteringDisplayWhitePointY", Frame->MasteringDisplayWhitePointY, 0);
|
||||
}
|
||||
|
||||
if (Frame->HasMasteringDisplayLuminance) {
|
||||
Env->propSetFloat(props, "MasteringDisplayMinLuminance", Frame->MasteringDisplayMinLuminance, 0);
|
||||
Env->propSetFloat(props, "MasteringDisplayMaxLuminance", Frame->MasteringDisplayMaxLuminance, 0);
|
||||
}
|
||||
|
||||
if (Frame->HasContentLightLevel) {
|
||||
Env->propSetFloat(props, "ContentLightLevelMax", Frame->ContentLightLevelMax, 0);
|
||||
Env->propSetFloat(props, "ContentLightLevelAverage", Frame->ContentLightLevelAverage, 0);
|
||||
}
|
||||
|
||||
if (Frame->DolbyVisionRPU && Frame->DolbyVisionRPUSize > 0) {
|
||||
Env->propSetData(props, "DolbyVisionRPU", reinterpret_cast<const char *>(Frame->DolbyVisionRPU), Frame->DolbyVisionRPUSize, 0);
|
||||
}
|
||||
|
||||
if (Frame->HDR10Plus && Frame->HDR10PlusSize > 0) {
|
||||
Env->propSetData(props, "HDR10Plus", reinterpret_cast<const char *>(Frame->HDR10Plus), Frame->HDR10PlusSize, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return Dst;
|
||||
}
|
||||
|
||||
|
@ -658,11 +572,11 @@ bool AvisynthVideoSource::GetParity(int n) {
|
|||
}
|
||||
|
||||
AvisynthAudioSource::AvisynthAudioSource(const char *SourceFile, int Track, FFMS_Index *Index,
|
||||
int AdjustDelay, int FillGaps, double DrcScale, const char *VarPrefix, IScriptEnvironment* Env) {
|
||||
int AdjustDelay, const char *VarPrefix, IScriptEnvironment* Env) {
|
||||
VI = {};
|
||||
|
||||
ErrorInfo E;
|
||||
A = FFMS_CreateAudioSource2(SourceFile, Track, Index, AdjustDelay, FillGaps, DrcScale, &E);
|
||||
A = FFMS_CreateAudioSource(SourceFile, Track, Index, AdjustDelay, &E);
|
||||
if (!A)
|
||||
Env->ThrowError("FFAudioSource: %s", E.Buffer);
|
||||
|
||||
|
@ -670,8 +584,8 @@ AvisynthAudioSource::AvisynthAudioSource(const char *SourceFile, int Track, FFMS
|
|||
VI.nchannels = AP->Channels;
|
||||
VI.num_audio_samples = AP->NumSamples;
|
||||
VI.audio_samples_per_second = AP->SampleRate;
|
||||
VI.SetChannelMask(true, AP->ChannelLayout);
|
||||
|
||||
// casting to int should be safe; none of the channel constants are greater than INT_MAX
|
||||
Env->SetVar(Env->Sprintf("%s%s", VarPrefix, "FFCHANNEL_LAYOUT"), static_cast<int>(AP->ChannelLayout));
|
||||
|
||||
Env->SetGlobalVar("FFVAR_PREFIX", VarPrefix);
|
||||
|
@ -689,7 +603,7 @@ AvisynthAudioSource::~AvisynthAudioSource() {
|
|||
FFMS_DestroyAudioSource(A);
|
||||
}
|
||||
|
||||
void AvisynthAudioSource::GetAudio(void* Buf, int64_t Start, int64_t Count, IScriptEnvironment *Env) {
|
||||
void AvisynthAudioSource::GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env) {
|
||||
ErrorInfo E;
|
||||
if (FFMS_GetAudio(A, Buf, Start, Count, &E))
|
||||
Env->ThrowError("FFAudioSource: %s", E.Buffer);
|
|
@ -22,9 +22,7 @@
|
|||
#define FFAVSSOURCES_H
|
||||
|
||||
#include <vector>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <avisynth.h>
|
||||
#include "ffms.h"
|
||||
|
||||
|
@ -50,7 +48,6 @@ class AvisynthVideoSource : public IClip {
|
|||
int RFFMode;
|
||||
std::vector<FrameFields> FieldList;
|
||||
const char *VarPrefix;
|
||||
bool has_at_least_v8;
|
||||
|
||||
void InitOutputFormat(int ResizeToWidth, int ResizeToHeight,
|
||||
const char *ResizerName, const char *ConvertToFormatName, IScriptEnvironment *Env);
|
||||
|
@ -65,7 +62,7 @@ public:
|
|||
bool __stdcall GetParity(int n);
|
||||
int __stdcall SetCacheHints(int cachehints, int frame_range) { return 0; }
|
||||
const VideoInfo& __stdcall GetVideoInfo() { return VI; }
|
||||
void __stdcall GetAudio(void* Buf, int64_t Start, int64_t Count, IScriptEnvironment *Env) {}
|
||||
void __stdcall GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env) {}
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env);
|
||||
};
|
||||
|
||||
|
@ -74,12 +71,12 @@ class AvisynthAudioSource : public IClip {
|
|||
FFMS_AudioSource *A;
|
||||
public:
|
||||
AvisynthAudioSource(const char *SourceFile, int Track, FFMS_Index *Index,
|
||||
int AdjustDelay, int FillGaps, double DrcScale, const char *VarPrefix, IScriptEnvironment* Env);
|
||||
int AdjustDelay, const char *VarPrefix, IScriptEnvironment* Env);
|
||||
~AvisynthAudioSource();
|
||||
bool __stdcall GetParity(int n) { return false; }
|
||||
int __stdcall SetCacheHints(int cachehints, int frame_range) { return 0; }
|
||||
const VideoInfo& __stdcall GetVideoInfo() { return VI; }
|
||||
void __stdcall GetAudio(void* Buf, int64_t Start, int64_t Count, IScriptEnvironment *Env);
|
||||
void __stdcall GetAudio(void* Buf, __int64 Start, __int64 Count, IScriptEnvironment *Env);
|
||||
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *Env) { return nullptr; };
|
||||
};
|
||||
|
61
ffms2/src/config/config.h.in
Normal file
61
ffms2/src/config/config.h.in
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* src/config/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to the sub-directory where libtool stores uninstalled libraries. */
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
|
@ -53,13 +53,9 @@ namespace {
|
|||
#undef MAPPER
|
||||
}
|
||||
|
||||
FFMS_AudioSource::FFMS_AudioSource(const char *SourceFile, FFMS_Index &Index, int Track, int DelayMode, int FillGaps, double DrcScale)
|
||||
: DrcScale(DrcScale), LastValidTS(AV_NOPTS_VALUE), SourceFile(SourceFile), ResampleContext{ swr_alloc() }, TrackNumber(Track) {
|
||||
FFMS_AudioSource::FFMS_AudioSource(const char *SourceFile, FFMS_Index &Index, int Track, int DelayMode)
|
||||
: LastValidTS(AV_NOPTS_VALUE), SourceFile(SourceFile), ResampleContext{ swr_alloc() }, TrackNumber(Track) {
|
||||
try {
|
||||
if (FillGaps < -1 || FillGaps > 1)
|
||||
throw FFMS_Exception(FFMS_ERROR_INDEX, FFMS_ERROR_INVALID_ARGUMENT,
|
||||
"Invalid gap fill mode");
|
||||
|
||||
if (Track < 0 || Track >= static_cast<int>(Index.size()))
|
||||
throw FFMS_Exception(FFMS_ERROR_INDEX, FFMS_ERROR_INVALID_ARGUMENT,
|
||||
"Out of bounds track index selected");
|
||||
|
@ -77,7 +73,6 @@ FFMS_AudioSource::FFMS_AudioSource(const char *SourceFile, FFMS_Index &Index, in
|
|||
"The index does not match the source file");
|
||||
|
||||
Frames = Index[Track];
|
||||
LAVFOpts = Index.LAVFOpts;
|
||||
|
||||
DecodeFrame = av_frame_alloc();
|
||||
if (!DecodeFrame)
|
||||
|
@ -85,9 +80,6 @@ FFMS_AudioSource::FFMS_AudioSource(const char *SourceFile, FFMS_Index &Index, in
|
|||
"Couldn't allocate frame");
|
||||
OpenFile();
|
||||
|
||||
if (FillGaps == 1 || (FillGaps == -1 && (!strcmp(FormatContext->iformat->name, "flv"))))
|
||||
Frames.FillAudioGaps();
|
||||
|
||||
if (Frames.back().PTS == Frames.front().PTS)
|
||||
SeekOffset = -1;
|
||||
else
|
||||
|
@ -203,16 +195,6 @@ void FFMS_AudioSource::CacheBeginning() {
|
|||
--CacheNoDelete;
|
||||
}
|
||||
|
||||
static int PopCount(int64_t v) {
|
||||
int c = 0;
|
||||
for (size_t i = 0; i < 64; i++) {
|
||||
if (v & 1)
|
||||
c++;
|
||||
v >>= 1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void FFMS_AudioSource::SetOutputFormat(FFMS_ResampleOptions const& opt) {
|
||||
if (opt.SampleRate != AP.SampleRate)
|
||||
throw FFMS_Exception(FFMS_ERROR_RESAMPLING, FFMS_ERROR_UNSUPPORTED,
|
||||
|
@ -224,7 +206,7 @@ void FFMS_AudioSource::SetOutputFormat(FFMS_ResampleOptions const& opt) {
|
|||
OpenFile();
|
||||
avcodec_flush_buffers(CodecContext);
|
||||
|
||||
BytesPerSample = av_get_bytes_per_sample(static_cast<AVSampleFormat>(opt.SampleFormat)) * PopCount(opt.ChannelLayout);
|
||||
BytesPerSample = av_get_bytes_per_sample(static_cast<AVSampleFormat>(opt.SampleFormat)) * av_get_channel_layout_nb_channels(opt.ChannelLayout);
|
||||
NeedsResample =
|
||||
opt.SampleFormat != (int)CodecContext->sample_fmt ||
|
||||
opt.SampleRate != AP.SampleRate ||
|
||||
|
@ -233,15 +215,15 @@ void FFMS_AudioSource::SetOutputFormat(FFMS_ResampleOptions const& opt) {
|
|||
|
||||
if (!NeedsResample) return;
|
||||
|
||||
SwrContext *rawCtx = swr_alloc();
|
||||
|
||||
AVChannelLayout ChLayoutOut = { AV_CHANNEL_ORDER_NATIVE, PopCount(opt.ChannelLayout), static_cast<uint64_t>(opt.ChannelLayout), nullptr };
|
||||
AVChannelLayout ChLayoutIn = { AV_CHANNEL_ORDER_NATIVE, PopCount(AP.ChannelLayout), static_cast<uint64_t>(AP.ChannelLayout), nullptr };
|
||||
swr_alloc_set_opts2(&rawCtx, &ChLayoutOut, (AVSampleFormat)opt.SampleFormat, opt.SampleRate, &ChLayoutIn, CodecContext->sample_fmt, AP.SampleRate, 0, nullptr);
|
||||
|
||||
FFResampleContext newContext{ rawCtx };
|
||||
|
||||
FFResampleContext newContext{ swr_alloc() };
|
||||
SetOptions(opt, newContext.get(), resample_options);
|
||||
av_opt_set_int(newContext.get(), "in_sample_rate", AP.SampleRate, 0);
|
||||
av_opt_set_int(newContext.get(), "in_sample_fmt", CodecContext->sample_fmt, 0);
|
||||
av_opt_set_int(newContext.get(), "in_channel_layout", AP.ChannelLayout, 0);
|
||||
|
||||
av_opt_set_int(newContext.get(), "out_sample_rate", opt.SampleRate, 0);
|
||||
av_opt_set_channel_layout(newContext.get(), "out_channel_layout", opt.ChannelLayout, 0);
|
||||
av_opt_set_sample_fmt(newContext.get(), "out_sample_fmt", (AVSampleFormat)opt.SampleFormat, 0);
|
||||
|
||||
if (swr_init(newContext.get()))
|
||||
throw FFMS_Exception(FFMS_ERROR_RESAMPLING, FFMS_ERROR_UNKNOWN,
|
||||
|
@ -301,51 +283,34 @@ FFMS_AudioSource::AudioBlock *FFMS_AudioSource::CacheBlock(CacheIterator &pos) {
|
|||
}
|
||||
|
||||
int FFMS_AudioSource::DecodeNextBlock(CacheIterator *pos) {
|
||||
AVPacket *Packet = av_packet_alloc();
|
||||
if (!Packet)
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_ALLOCATION_FAILED,
|
||||
"Could not allocate packet.");
|
||||
if (!ReadPacket(Packet)) {
|
||||
av_packet_free(&Packet);
|
||||
CurrentFrame = &Frames[PacketNumber];
|
||||
|
||||
AVPacket Packet;
|
||||
if (!ReadPacket(&Packet))
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_UNKNOWN,
|
||||
"ReadPacket unexpectedly failed to read a packet");
|
||||
}
|
||||
|
||||
// ReadPacket may have changed the packet number
|
||||
CurrentFrame = &Frames[PacketNumber];
|
||||
CurrentSample = CurrentFrame->SampleStart;
|
||||
|
||||
// Value code intentionally ignored, combined with the checks when indexing this mostly gives the expected behavior
|
||||
avcodec_send_packet(CodecContext, Packet);
|
||||
|
||||
int NumberOfSamples = 0;
|
||||
AudioBlock *CachedBlock = nullptr;
|
||||
|
||||
int Ret = avcodec_send_packet(CodecContext, &Packet);
|
||||
av_packet_unref(&Packet);
|
||||
|
||||
while (true) {
|
||||
av_frame_unref(DecodeFrame);
|
||||
int Ret = avcodec_receive_frame(CodecContext, DecodeFrame);
|
||||
if (Ret == 0) {
|
||||
NumberOfSamples += DecodeFrame->nb_samples;
|
||||
if (DecodeFrame->nb_samples > 0) {
|
||||
if (pos)
|
||||
CachedBlock = CacheBlock(*pos);
|
||||
}
|
||||
break;
|
||||
} else if (Ret == AVERROR(EAGAIN)) {
|
||||
if (!ReadPacket(Packet)) {
|
||||
av_packet_free(&Packet);
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_UNKNOWN,
|
||||
"ReadPacket unexpectedly failed to read a packet");
|
||||
}
|
||||
avcodec_send_packet(CodecContext, Packet);
|
||||
} else if (Ret == AVERROR_EOF) {
|
||||
break;
|
||||
} else {
|
||||
throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_DECODING, "Audio decoding error");
|
||||
av_frame_unref(DecodeFrame);
|
||||
Ret = avcodec_receive_frame(CodecContext, DecodeFrame);
|
||||
if (Ret == 0) {
|
||||
//FIXME, is DecodeFrame->nb_samples > 0 always true for decoded frames? I can't be bothered to find out
|
||||
NumberOfSamples += DecodeFrame->nb_samples;
|
||||
if (DecodeFrame->nb_samples > 0) {
|
||||
if (pos)
|
||||
CachedBlock = CacheBlock(*pos);
|
||||
}
|
||||
}
|
||||
|
||||
av_packet_free(&Packet);
|
||||
|
||||
// Zero sample packets aren't included in the index
|
||||
if (!NumberOfSamples)
|
||||
return NumberOfSamples;
|
||||
|
@ -496,9 +461,9 @@ void FFMS_AudioSource::OpenFile() {
|
|||
avcodec_free_context(&CodecContext);
|
||||
avformat_close_input(&FormatContext);
|
||||
|
||||
LAVFOpenFile(SourceFile.c_str(), FormatContext, TrackNumber, LAVFOpts);
|
||||
LAVFOpenFile(SourceFile.c_str(), FormatContext, TrackNumber);
|
||||
|
||||
auto *Codec = avcodec_find_decoder(FormatContext->streams[TrackNumber]->codecpar->codec_id);
|
||||
AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[TrackNumber]->codecpar->codec_id);
|
||||
if (Codec == nullptr)
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
|
||||
"Audio codec not found");
|
||||
|
@ -512,15 +477,9 @@ void FFMS_AudioSource::OpenFile() {
|
|||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
|
||||
"Could not copy audio codec parameters");
|
||||
|
||||
AVDictionary *CodecDict = nullptr;
|
||||
if (Codec->id == AV_CODEC_ID_AC3 || Codec->id == AV_CODEC_ID_EAC3)
|
||||
av_dict_set(&CodecDict, "drc_scale", std::to_string(DrcScale).c_str(), 0);
|
||||
|
||||
if (avcodec_open2(CodecContext, Codec, &CodecDict) < 0)
|
||||
if (avcodec_open2(CodecContext, Codec, nullptr) < 0)
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
|
||||
"Could not open audio codec");
|
||||
|
||||
av_dict_free(&CodecDict);
|
||||
}
|
||||
|
||||
void FFMS_AudioSource::Free() {
|
||||
|
@ -554,6 +513,8 @@ void FFMS_AudioSource::Seek() {
|
|||
}
|
||||
|
||||
bool FFMS_AudioSource::ReadPacket(AVPacket *Packet) {
|
||||
InitNullPacket(*Packet);
|
||||
|
||||
while (av_read_frame(FormatContext, Packet) >= 0) {
|
||||
if (Packet->stream_index == TrackNumber) {
|
||||
// Required because not all audio packets, especially in ogg, have a pts. Use the previous valid packet's pts instead.
|
|
@ -62,8 +62,6 @@ struct FFMS_AudioSource {
|
|||
typedef std::list<AudioBlock>::iterator CacheIterator;
|
||||
|
||||
AVFormatContext *FormatContext = nullptr;
|
||||
std::map<std::string, std::string> LAVFOpts;
|
||||
double DrcScale;
|
||||
int64_t LastValidTS;
|
||||
std::string SourceFile;
|
||||
|
||||
|
@ -135,7 +133,7 @@ struct FFMS_AudioSource {
|
|||
|
||||
void Free();
|
||||
public:
|
||||
FFMS_AudioSource(const char *SourceFile, FFMS_Index &Index, int Track, int DelayMode, int FillGaps, double DrcScale);
|
||||
FFMS_AudioSource(const char *SourceFile, FFMS_Index &Index, int Track, int DelayMode);
|
||||
~FFMS_AudioSource();
|
||||
FFMS_Track *GetTrack() { return &Frames; }
|
||||
const FFMS_AudioProperties& GetAudioProperties() const { return AP; }
|
|
@ -39,6 +39,8 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
static std::once_flag FFmpegOnce;
|
||||
static std::mutex FFmpegNetwork;
|
||||
static bool FFmpegNetworkInited = false;
|
||||
|
||||
#ifdef FFMS_WIN_DEBUG
|
||||
|
||||
|
@ -78,6 +80,7 @@ static void av_log_windebug_callback(void* ptr, int level, const char* fmt, va_l
|
|||
|
||||
FFMS_API(void) FFMS_Init(int, int) {
|
||||
std::call_once(FFmpegOnce, []() {
|
||||
FFMS_REGISTER();
|
||||
#ifdef FFMS_WIN_DEBUG
|
||||
av_log_set_callback(av_log_windebug_callback);
|
||||
av_log_set_level(AV_LOG_INFO);
|
||||
|
@ -85,10 +88,21 @@ FFMS_API(void) FFMS_Init(int, int) {
|
|||
av_log_set_level(AV_LOG_QUIET);
|
||||
#endif
|
||||
});
|
||||
FFmpegNetwork.lock();
|
||||
if (!FFmpegNetworkInited) {
|
||||
avformat_network_init();
|
||||
FFmpegNetworkInited = true;
|
||||
}
|
||||
FFmpegNetwork.unlock();
|
||||
}
|
||||
|
||||
FFMS_API(void) FFMS_Deinit() {
|
||||
|
||||
FFmpegNetwork.lock();
|
||||
if (FFmpegNetworkInited) {
|
||||
avformat_network_deinit();
|
||||
FFmpegNetworkInited = false;
|
||||
}
|
||||
FFmpegNetwork.unlock();
|
||||
}
|
||||
|
||||
FFMS_API(int) FFMS_GetVersion() {
|
||||
|
@ -113,12 +127,8 @@ FFMS_API(FFMS_VideoSource *) FFMS_CreateVideoSource(const char *SourceFile, int
|
|||
}
|
||||
|
||||
FFMS_API(FFMS_AudioSource *) FFMS_CreateAudioSource(const char *SourceFile, int Track, FFMS_Index *Index, int DelayMode, FFMS_ErrorInfo *ErrorInfo) {
|
||||
return FFMS_CreateAudioSource2(SourceFile, Track, Index, DelayMode, -1, 0, ErrorInfo);
|
||||
}
|
||||
|
||||
FFMS_API(FFMS_AudioSource *) FFMS_CreateAudioSource2(const char *SourceFile, int Track, FFMS_Index *Index, int DelayMode, int FillGaps, double DrcScale, FFMS_ErrorInfo *ErrorInfo) {
|
||||
try {
|
||||
return new FFMS_AudioSource(SourceFile, *Index, Track, DelayMode, FillGaps, DrcScale);
|
||||
return new FFMS_AudioSource(SourceFile, *Index, Track, DelayMode);
|
||||
} catch (FFMS_Exception &e) {
|
||||
e.CopyOut(ErrorInfo);
|
||||
return nullptr;
|
||||
|
@ -309,13 +319,9 @@ FFMS_API(int) FFMS_WriteTimecodes(FFMS_Track *T, const char *TimecodeFile, FFMS_
|
|||
}
|
||||
|
||||
FFMS_API(FFMS_Indexer *) FFMS_CreateIndexer(const char *SourceFile, FFMS_ErrorInfo *ErrorInfo) {
|
||||
return FFMS_CreateIndexer2(SourceFile, nullptr, 0, ErrorInfo);
|
||||
}
|
||||
|
||||
FFMS_API(FFMS_Indexer *) FFMS_CreateIndexer2(const char *SourceFile, const FFMS_KeyValuePair *DemuxerOptions, int NumOptions, FFMS_ErrorInfo *ErrorInfo) {
|
||||
ClearErrorInfo(ErrorInfo);
|
||||
try {
|
||||
return new FFMS_Indexer(SourceFile, DemuxerOptions, NumOptions);
|
||||
return new FFMS_Indexer(SourceFile);
|
||||
} catch (FFMS_Exception &e) {
|
||||
e.CopyOut(ErrorInfo);
|
||||
return nullptr;
|
|
@ -35,7 +35,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
#define INDEXID 0x53920873
|
||||
#define INDEX_VERSION 7
|
||||
#define INDEX_VERSION 5
|
||||
|
||||
SharedAVContext::~SharedAVContext() {
|
||||
avcodec_free_context(&CodecContext);
|
||||
|
@ -70,15 +70,6 @@ void FFMS_Index::CalculateFileSignature(const char *Filename, int64_t *Filesize,
|
|||
void FFMS_Index::Finalize(std::vector<SharedAVContext> const& video_contexts, const char *Format) {
|
||||
for (size_t i = 0, end = size(); i != end; ++i) {
|
||||
FFMS_Track& track = (*this)[i];
|
||||
|
||||
// Some audio tracks are simply insane junk (seen with als) and will have a single(?) super long packet and
|
||||
// apart from that look legit and be chosen instead of usable audio. This hopefully rejects some of it.
|
||||
// Caused by sample in https://github.com/FFMS/ffms2/issues/351
|
||||
if (track.TT == FFMS_TYPE_AUDIO) {
|
||||
if (track.size() <= 10 && track.size() > 0 && track[0].SampleCount > 1000000)
|
||||
track.clear();
|
||||
}
|
||||
|
||||
// H.264 PAFF needs to have some frames hidden
|
||||
//
|
||||
// Don't send any WMV/ASF files, since they (as far as we know) cannot contain PAFF,
|
||||
|
@ -127,14 +118,6 @@ void FFMS_Index::WriteIndex(ZipFile &zf) {
|
|||
zf.Write<int64_t>(Filesize);
|
||||
zf.Write(Digest);
|
||||
|
||||
zf.Write<uint32_t>(LAVFOpts.size());
|
||||
for (const auto &iter : LAVFOpts) {
|
||||
zf.Write<uint32_t>(iter.first.length());
|
||||
zf.Write(iter.first.data(), iter.first.length());
|
||||
zf.Write<uint32_t>(iter.second.length());
|
||||
zf.Write(iter.second.data(), iter.second.length());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < size(); ++i)
|
||||
at(i).Write(zf);
|
||||
|
||||
|
@ -182,21 +165,6 @@ void FFMS_Index::ReadIndex(ZipFile &zf, const char *IndexFile) {
|
|||
Filesize = zf.Read<int64_t>();
|
||||
zf.Read(Digest, sizeof(Digest));
|
||||
|
||||
uint32_t NumOptions = zf.Read<uint32_t>();
|
||||
std::vector<char> KeyBuffer;
|
||||
std::vector<char> ValueBuffer;
|
||||
for (uint32_t i = 0; i < NumOptions; i++) {
|
||||
uint32_t KeyLength = zf.Read<uint32_t>();
|
||||
KeyBuffer.resize(KeyLength);
|
||||
zf.Read(KeyBuffer.data(), KeyLength);
|
||||
|
||||
uint32_t ValueLength = zf.Read<uint32_t>();
|
||||
ValueBuffer.resize(ValueLength);
|
||||
zf.Read(ValueBuffer.data(), ValueLength);
|
||||
|
||||
LAVFOpts[std::string(KeyBuffer.data(), KeyLength)] = std::string(ValueBuffer.data(), ValueLength);
|
||||
}
|
||||
|
||||
reserve(Tracks);
|
||||
try {
|
||||
for (size_t i = 0; i < Tracks; ++i)
|
||||
|
@ -221,9 +189,9 @@ FFMS_Index::FFMS_Index(const uint8_t *Buffer, size_t Size) {
|
|||
ReadIndex(zf, "User supplied buffer");
|
||||
}
|
||||
|
||||
FFMS_Index::FFMS_Index(int64_t Filesize, uint8_t Digest[20], int ErrorHandling, const std::map<std::string, std::string> &LAVFOpts)
|
||||
FFMS_Index::FFMS_Index(int64_t Filesize, uint8_t Digest[20], int ErrorHandling)
|
||||
: ErrorHandling(ErrorHandling)
|
||||
, Filesize(Filesize), LAVFOpts(LAVFOpts) {
|
||||
, Filesize(Filesize) {
|
||||
memcpy(this->Digest, Digest, sizeof(this->Digest));
|
||||
}
|
||||
|
||||
|
@ -260,24 +228,17 @@ void FFMS_Indexer::SetProgressCallback(TIndexCallback IC_, void *ICPrivate_) {
|
|||
ICPrivate = ICPrivate_;
|
||||
}
|
||||
|
||||
FFMS_Indexer::FFMS_Indexer(const char *Filename, const FFMS_KeyValuePair *DemuxerOptions, int NumOptions)
|
||||
FFMS_Indexer *CreateIndexer(const char *Filename) {
|
||||
return new FFMS_Indexer(Filename);
|
||||
}
|
||||
|
||||
FFMS_Indexer::FFMS_Indexer(const char *Filename)
|
||||
: SourceFile(Filename) {
|
||||
try {
|
||||
AVDictionary *Dict = nullptr;
|
||||
for (int i = 0; i < NumOptions; i++) {
|
||||
if (!DemuxerOptions[i].Key && !DemuxerOptions[i].Value)
|
||||
throw FFMS_Exception(FFMS_ERROR_INDEX, FFMS_ERROR_INVALID_ARGUMENT,
|
||||
"Demuxer key-value pairs can't have NULL strings");
|
||||
LAVFOpts[DemuxerOptions[i].Key] = DemuxerOptions[i].Value;
|
||||
av_dict_set(&Dict, DemuxerOptions[i].Key, DemuxerOptions[i].Value, 0);
|
||||
}
|
||||
|
||||
if (avformat_open_input(&FormatContext, Filename, nullptr, &Dict) != 0)
|
||||
if (avformat_open_input(&FormatContext, Filename, nullptr, nullptr) != 0)
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ,
|
||||
std::string("Can't open '") + Filename + "'");
|
||||
|
||||
av_dict_free(&Dict);
|
||||
|
||||
FFMS_Index::CalculateFileSignature(Filename, &Filesize, Digest);
|
||||
|
||||
if (avformat_find_stream_info(FormatContext, nullptr) < 0) {
|
||||
|
@ -344,14 +305,14 @@ void FFMS_Indexer::CheckAudioProperties(int Track, AVCodecContext *Context) {
|
|||
FFMS_AudioProperties &AP = LastAudioProperties[Track];
|
||||
AP.SampleRate = Context->sample_rate;
|
||||
AP.SampleFormat = Context->sample_fmt;
|
||||
AP.Channels = Context->ch_layout.nb_channels;
|
||||
AP.Channels = Context->channels;
|
||||
} else if (it->second.SampleRate != Context->sample_rate ||
|
||||
it->second.SampleFormat != Context->sample_fmt ||
|
||||
it->second.Channels != Context->ch_layout.nb_channels) {
|
||||
std::ostringstream buf; // fixme, dodgy comparison and maybe wrong since it skips layout comp
|
||||
it->second.Channels != Context->channels) {
|
||||
std::ostringstream buf;
|
||||
buf <<
|
||||
"Audio format change detected. This is currently unsupported."
|
||||
<< " Channels: " << it->second.Channels << " -> " << Context->ch_layout.nb_channels << ";"
|
||||
<< " Channels: " << it->second.Channels << " -> " << Context->channels << ";"
|
||||
<< " Sample rate: " << it->second.SampleRate << " -> " << Context->sample_rate << ";"
|
||||
<< " Sample format: " << av_get_sample_fmt_name((AVSampleFormat)it->second.SampleFormat) << " -> "
|
||||
<< av_get_sample_fmt_name(Context->sample_fmt);
|
||||
|
@ -359,7 +320,7 @@ void FFMS_Indexer::CheckAudioProperties(int Track, AVCodecContext *Context) {
|
|||
}
|
||||
}
|
||||
|
||||
void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt, int *RepeatPict,
|
||||
void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt, int *RepeatPict,
|
||||
int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct) {
|
||||
if (VideoContext.Parser) {
|
||||
uint8_t *OB;
|
||||
|
@ -369,8 +330,8 @@ void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt
|
|||
av_parser_parse2(VideoContext.Parser,
|
||||
VideoContext.CodecContext,
|
||||
&OB, &OBSize,
|
||||
pkt->data, pkt->size,
|
||||
pkt->pts, pkt->dts, pkt->pos);
|
||||
pkt.data, pkt.size,
|
||||
pkt.pts, pkt.dts, pkt.pos);
|
||||
|
||||
// H.264 (PAFF) and HEVC may have one field per packet, so we need to track
|
||||
// when we have a full or half frame available, and mark one of them as
|
||||
|
@ -390,15 +351,15 @@ void FFMS_Indexer::ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt
|
|||
|
||||
*RepeatPict = VideoContext.Parser->repeat_pict;
|
||||
*FrameType = VideoContext.Parser->pict_type;
|
||||
*Invisible = (IncompleteFrame || VideoContext.Parser->repeat_pict < 0 || (pkt->flags & AV_PKT_FLAG_DISCARD));
|
||||
*Invisible = (IncompleteFrame || VideoContext.Parser->repeat_pict < 0 || (pkt.flags & AV_PKT_FLAG_DISCARD));
|
||||
} else {
|
||||
*Invisible = !!(pkt->flags & AV_PKT_FLAG_DISCARD);
|
||||
*Invisible = !!(pkt.flags & AV_PKT_FLAG_DISCARD);
|
||||
}
|
||||
|
||||
if (VideoContext.CodecContext->codec_id == AV_CODEC_ID_VP8)
|
||||
ParseVP8(pkt->data[0], Invisible, FrameType);
|
||||
ParseVP8(pkt.data[0], Invisible, FrameType);
|
||||
else if (VideoContext.CodecContext->codec_id == AV_CODEC_ID_VP9)
|
||||
ParseVP9(pkt->data[0], FrameType);
|
||||
ParseVP9(pkt.data[0], Invisible, FrameType);
|
||||
}
|
||||
|
||||
void FFMS_Indexer::Free() {
|
||||
|
@ -423,14 +384,14 @@ FFMS_TrackType FFMS_Indexer::GetTrackType(int Track) {
|
|||
}
|
||||
|
||||
const char *FFMS_Indexer::GetTrackCodec(int Track) {
|
||||
auto *codec = avcodec_find_decoder(FormatContext->streams[Track]->codecpar->codec_id);
|
||||
AVCodec *codec = avcodec_find_decoder(FormatContext->streams[Track]->codecpar->codec_id);
|
||||
return codec ? codec->name : nullptr;
|
||||
}
|
||||
|
||||
FFMS_Index *FFMS_Indexer::DoIndexing() {
|
||||
std::vector<SharedAVContext> AVContexts(FormatContext->nb_streams);
|
||||
|
||||
auto TrackIndices = std::unique_ptr<FFMS_Index>(new FFMS_Index(Filesize, Digest, ErrorHandling, LAVFOpts));
|
||||
auto TrackIndices = make_unique<FFMS_Index>(Filesize, Digest, ErrorHandling);
|
||||
bool UseDTS = !strcmp(FormatContext->iformat->name, "mpeg") || !strcmp(FormatContext->iformat->name, "mpegts") || !strcmp(FormatContext->iformat->name, "mpegtsraw") || !strcmp(FormatContext->iformat->name, "nuv");
|
||||
|
||||
for (unsigned int i = 0; i < FormatContext->nb_streams; i++) {
|
||||
|
@ -441,7 +402,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() {
|
|||
UseDTS);
|
||||
|
||||
if (IndexMask.count(i) && FormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
auto *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id);
|
||||
AVCodec *VideoCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id);
|
||||
if (!VideoCodec) {
|
||||
FormatContext->streams[i]->discard = AVDISCARD_ALL;
|
||||
IndexMask.erase(i);
|
||||
|
@ -472,7 +433,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() {
|
|||
IndexMask.insert(i);
|
||||
}
|
||||
} else if (IndexMask.count(i) && FormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
auto *AudioCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id);
|
||||
AVCodec *AudioCodec = avcodec_find_decoder(FormatContext->streams[i]->codecpar->codec_id);
|
||||
if (AudioCodec == nullptr)
|
||||
throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_UNSUPPORTED,
|
||||
"Audio codec not found");
|
||||
|
@ -497,37 +458,32 @@ FFMS_Index *FFMS_Indexer::DoIndexing() {
|
|||
}
|
||||
}
|
||||
|
||||
AVPacket *Packet = av_packet_alloc();
|
||||
if (!Packet)
|
||||
throw FFMS_Exception(FFMS_ERROR_CODEC, FFMS_ERROR_ALLOCATION_FAILED,
|
||||
"Could not allocate packet.");
|
||||
AVPacket Packet;
|
||||
InitNullPacket(Packet);
|
||||
std::vector<int64_t> LastValidTS(FormatContext->nb_streams, AV_NOPTS_VALUE);
|
||||
|
||||
int64_t filesize = avio_size(FormatContext->pb);
|
||||
enum AVPictureStructure LastPicStruct = AV_PICTURE_STRUCTURE_UNKNOWN;
|
||||
int ret;
|
||||
while ((ret = av_read_frame(FormatContext, Packet)) >= 0) {
|
||||
while (av_read_frame(FormatContext, &Packet) >= 0) {
|
||||
// Update progress
|
||||
// FormatContext->pb can apparently be NULL when opening images.
|
||||
if (IC && FormatContext->pb) {
|
||||
if ((*IC)(FormatContext->pb->pos, filesize, ICPrivate)) {
|
||||
av_packet_free(&Packet);
|
||||
if ((*IC)(FormatContext->pb->pos, filesize, ICPrivate))
|
||||
throw FFMS_Exception(FFMS_ERROR_CANCELLED, FFMS_ERROR_USER,
|
||||
"Cancelled by user");
|
||||
}
|
||||
}
|
||||
if (!IndexMask.count(Packet->stream_index)) {
|
||||
av_packet_unref(Packet);
|
||||
if (!IndexMask.count(Packet.stream_index)) {
|
||||
av_packet_unref(&Packet);
|
||||
continue;
|
||||
}
|
||||
|
||||
int Track = Packet->stream_index;
|
||||
int Track = Packet.stream_index;
|
||||
FFMS_Track &TrackInfo = (*TrackIndices)[Track];
|
||||
bool KeyFrame = !!(Packet->flags & AV_PKT_FLAG_KEY);
|
||||
bool KeyFrame = !!(Packet.flags & AV_PKT_FLAG_KEY);
|
||||
ReadTS(Packet, LastValidTS[Track], (*TrackIndices)[Track].UseDTS);
|
||||
|
||||
if (FormatContext->streams[Track]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
|
||||
int64_t PTS = TrackInfo.UseDTS ? Packet->dts : Packet->pts;
|
||||
int64_t PTS = TrackInfo.UseDTS ? Packet.dts : Packet.pts;
|
||||
if (PTS == AV_NOPTS_VALUE) {
|
||||
// VPx alt-refs are output as packets which lack timestmps or durations, since
|
||||
// they are invisible. Currently, the timestamp mangling code in libavformat
|
||||
|
@ -539,11 +495,9 @@ FFMS_Index *FFMS_Indexer::DoIndexing() {
|
|||
// FFMS2 currently sorts packets by PTS, which will break decoding, otherwise.
|
||||
bool HasAltRefs = (FormatContext->streams[Track]->codecpar->codec_id == AV_CODEC_ID_VP8 ||
|
||||
FormatContext->streams[Track]->codecpar->codec_id == AV_CODEC_ID_VP9);
|
||||
if (Packet->duration == 0 && !HasAltRefs) {
|
||||
av_packet_free(&Packet);
|
||||
if (Packet.duration == 0 && !HasAltRefs)
|
||||
throw FFMS_Exception(FFMS_ERROR_INDEXING, FFMS_ERROR_PARSER,
|
||||
"Invalid packet pts, dts, and duration");
|
||||
}
|
||||
|
||||
if (TrackInfo.empty())
|
||||
PTS = 0;
|
||||
|
@ -559,7 +513,7 @@ FFMS_Index *FFMS_Indexer::DoIndexing() {
|
|||
ParseVideoPacket(AVContexts[Track], Packet, &RepeatPict, &FrameType, &Invisible, &LastPicStruct);
|
||||
|
||||
TrackInfo.AddVideoFrame(PTS, RepeatPict, KeyFrame,
|
||||
FrameType, Packet->pos, Invisible);
|
||||
FrameType, Packet.pos, Invisible);
|
||||
} else if (FormatContext->streams[Track]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
// For video seeking timestamps are used only if all packets have
|
||||
// timestamps, while for audio they're used if any have timestamps,
|
||||
|
@ -568,36 +522,28 @@ FFMS_Index *FFMS_Indexer::DoIndexing() {
|
|||
TrackInfo.HasTS = true;
|
||||
|
||||
int64_t StartSample = AVContexts[Track].CurrentSample;
|
||||
uint32_t SampleCount = IndexAudioPacket(Track, Packet, AVContexts[Track], *TrackIndices);
|
||||
uint32_t SampleCount = IndexAudioPacket(Track, &Packet, AVContexts[Track], *TrackIndices);
|
||||
TrackInfo.SampleRate = AVContexts[Track].CodecContext->sample_rate;
|
||||
|
||||
TrackInfo.AddAudioFrame(LastValidTS[Track],
|
||||
StartSample, SampleCount, KeyFrame, Packet->pos, Packet->flags & AV_PKT_FLAG_DISCARD);
|
||||
StartSample, SampleCount, KeyFrame, Packet.pos, Packet.flags & AV_PKT_FLAG_DISCARD);
|
||||
}
|
||||
|
||||
if (!(Packet->flags & AV_PKT_FLAG_DISCARD))
|
||||
TrackInfo.LastDuration = Packet->duration;
|
||||
if (!(Packet.flags & AV_PKT_FLAG_DISCARD))
|
||||
TrackInfo.LastDuration = Packet.duration;
|
||||
|
||||
av_packet_unref(Packet);
|
||||
}
|
||||
av_packet_free(&Packet);
|
||||
if (IsIOError(ret)) {
|
||||
char error[1024];
|
||||
av_strerror(ret, error, 1024);
|
||||
std::string cerr(error);
|
||||
throw FFMS_Exception(FFMS_ERROR_INDEXING, FFMS_ERROR_FILE_READ,
|
||||
"Indexing failed: " + cerr);
|
||||
av_packet_unref(&Packet);
|
||||
}
|
||||
|
||||
TrackIndices->Finalize(AVContexts, FormatContext->iformat->name);
|
||||
return TrackIndices.release();
|
||||
}
|
||||
|
||||
void FFMS_Indexer::ReadTS(const AVPacket *Packet, int64_t &TS, bool &UseDTS) {
|
||||
if (!UseDTS && Packet->pts != AV_NOPTS_VALUE)
|
||||
TS = Packet->pts;
|
||||
void FFMS_Indexer::ReadTS(const AVPacket &Packet, int64_t &TS, bool &UseDTS) {
|
||||
if (!UseDTS && Packet.pts != AV_NOPTS_VALUE)
|
||||
TS = Packet.pts;
|
||||
if (TS == AV_NOPTS_VALUE)
|
||||
UseDTS = true;
|
||||
if (UseDTS && Packet->dts != AV_NOPTS_VALUE)
|
||||
TS = Packet->dts;
|
||||
if (UseDTS && Packet.dts != AV_NOPTS_VALUE)
|
||||
TS = Packet.dts;
|
||||
}
|
|
@ -53,7 +53,6 @@ public:
|
|||
int ErrorHandling;
|
||||
int64_t Filesize;
|
||||
uint8_t Digest[20];
|
||||
std::map<std::string, std::string> LAVFOpts;
|
||||
|
||||
void Finalize(std::vector<SharedAVContext> const& video_contexts, const char *Format);
|
||||
bool CompareFileSignature(const char *Filename);
|
||||
|
@ -62,7 +61,7 @@ public:
|
|||
|
||||
FFMS_Index(const char *IndexFile);
|
||||
FFMS_Index(const uint8_t *Buffer, size_t Size);
|
||||
FFMS_Index(int64_t Filesize, uint8_t Digest[20], int ErrorHandling, const std::map<std::string, std::string> &LAVFOpts);
|
||||
FFMS_Index(int64_t Filesize, uint8_t Digest[20], int ErrorHandling);
|
||||
};
|
||||
|
||||
struct FFMS_Indexer {
|
||||
|
@ -72,7 +71,6 @@ private:
|
|||
FFMS_Indexer& operator=(FFMS_Indexer const&) = delete;
|
||||
AVFormatContext *FormatContext = nullptr;
|
||||
std::set<int> IndexMask;
|
||||
std::map<std::string, std::string> LAVFOpts;
|
||||
int ErrorHandling = FFMS_IEH_CLEAR_TRACK;
|
||||
TIndexCallback IC = nullptr;
|
||||
void *ICPrivate = nullptr;
|
||||
|
@ -82,13 +80,13 @@ private:
|
|||
int64_t Filesize;
|
||||
uint8_t Digest[20];
|
||||
|
||||
void ReadTS(const AVPacket *Packet, int64_t &TS, bool &UseDTS);
|
||||
void ReadTS(const AVPacket &Packet, int64_t &TS, bool &UseDTS);
|
||||
void CheckAudioProperties(int Track, AVCodecContext *Context);
|
||||
uint32_t IndexAudioPacket(int Track, AVPacket *Packet, SharedAVContext &Context, FFMS_Index &TrackIndices);
|
||||
void ParseVideoPacket(SharedAVContext &VideoContext, AVPacket *pkt, int *RepeatPict, int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct);
|
||||
void ParseVideoPacket(SharedAVContext &VideoContext, AVPacket &pkt, int *RepeatPict, int *FrameType, bool *Invisible, enum AVPictureStructure *LastPicStruct);
|
||||
void Free();
|
||||
public:
|
||||
FFMS_Indexer(const char *Filename, const FFMS_KeyValuePair *DemuxerOptions, int NumOptions);
|
||||
FFMS_Indexer(const char *Filename);
|
||||
~FFMS_Indexer();
|
||||
|
||||
void SetIndexTrack(int Track, bool Index);
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/avutil.h>
|
||||
|
@ -94,7 +93,6 @@ FFMS_Track::FFMS_Track(ZipFile &stream)
|
|||
MaxBFrames = stream.Read<int32_t>();
|
||||
UseDTS = !!stream.Read<uint8_t>();
|
||||
HasTS = !!stream.Read<uint8_t>();
|
||||
HasDiscontTS = !!stream.Read<uint8_t>();
|
||||
size_t FrameCount = static_cast<size_t>(stream.Read<uint64_t>());
|
||||
|
||||
if (!FrameCount) return;
|
||||
|
@ -117,7 +115,6 @@ void FFMS_Track::Write(ZipFile &stream) const {
|
|||
stream.Write<int32_t>(MaxBFrames);
|
||||
stream.Write<uint8_t>(UseDTS);
|
||||
stream.Write<uint8_t>(HasTS);
|
||||
stream.Write<uint8_t>(HasDiscontTS);
|
||||
stream.Write<uint64_t>(size());
|
||||
|
||||
if (empty()) return;
|
||||
|
@ -333,6 +330,11 @@ void FFMS_Track::FinalizeTrack() {
|
|||
if (size() > 2 && front().PTS >= back().PTS)
|
||||
Frames.pop_back();
|
||||
|
||||
if (TT == FFMS_TYPE_AUDIO) {
|
||||
FillAudioGaps();
|
||||
return;
|
||||
}
|
||||
|
||||
if (TT != FFMS_TYPE_VIDEO)
|
||||
return;
|
||||
|
||||
|
@ -387,14 +389,6 @@ void FFMS_Track::FinalizeTrack() {
|
|||
Frames[ReorderTemp[i]].OriginalPos = i;
|
||||
|
||||
GeneratePublicInfo();
|
||||
|
||||
// If the last packet in the file did not have a duration set,
|
||||
// fudge one based on the previous frame's duration.
|
||||
if (LastDuration == 0) {
|
||||
size_t InfoSize = Data->PublicFrameInfo.size();
|
||||
if (InfoSize >= 2)
|
||||
LastDuration = Data->PublicFrameInfo[InfoSize - 1].PTS - Data->PublicFrameInfo[InfoSize - 2].PTS;
|
||||
}
|
||||
}
|
||||
|
||||
void FFMS_Track::GeneratePublicInfo() {
|
|
@ -54,6 +54,7 @@ private:
|
|||
std::shared_ptr<TrackData> Data;
|
||||
|
||||
void MaybeReorderFrames();
|
||||
void FillAudioGaps();
|
||||
void GeneratePublicInfo();
|
||||
|
||||
public:
|
||||
|
@ -71,7 +72,6 @@ public:
|
|||
|
||||
void MaybeHideFrames();
|
||||
void FinalizeTrack();
|
||||
void FillAudioGaps();
|
||||
|
||||
int FindClosestVideoKeyFrame(int Frame) const;
|
||||
int FrameFromPTS(int64_t PTS) const;
|
|
@ -62,21 +62,17 @@ void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
void InitNullPacket(AVPacket &pkt) {
|
||||
av_init_packet(&pkt);
|
||||
pkt.data = nullptr;
|
||||
pkt.size = 0;
|
||||
}
|
||||
|
||||
void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames) {
|
||||
AP.SampleFormat = static_cast<FFMS_SampleFormat>(av_get_packed_sample_fmt(CTX->sample_fmt));
|
||||
AP.BitsPerSample = av_get_bytes_per_sample(CTX->sample_fmt) * 8;
|
||||
AP.Channels = CTX->ch_layout.nb_channels;
|
||||
|
||||
if (CTX->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
|
||||
AP.ChannelLayout = CTX->ch_layout.u.mask;
|
||||
} else if (CTX->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) {
|
||||
AVChannelLayout ch = {};
|
||||
av_channel_layout_default(&ch, CTX->ch_layout.nb_channels);
|
||||
AP.ChannelLayout = ch.u.mask;
|
||||
} else {
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_UNSUPPORTED, "Ambisonics and custom channel orders not supported");
|
||||
}
|
||||
|
||||
AP.Channels = CTX->channels;
|
||||
AP.ChannelLayout = CTX->channel_layout;
|
||||
AP.SampleRate = CTX->sample_rate;
|
||||
if (!Frames.empty()) {
|
||||
AP.NumSamples = (Frames.back()).SampleStart + (Frames.back()).SampleCount;
|
||||
|
@ -84,19 +80,16 @@ void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames) {
|
|||
AP.LastTime = ((Frames.back().PTS * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
|
||||
AP.LastEndTime = (((Frames.back().PTS + Frames.LastDuration) * Frames.TB.Num) / (double)Frames.TB.Den) / 1000;
|
||||
}
|
||||
|
||||
if (AP.ChannelLayout == 0)
|
||||
AP.ChannelLayout = av_get_default_channel_layout(AP.Channels);
|
||||
}
|
||||
|
||||
void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext, int Track, const std::map<std::string, std::string> &LAVFOpts) {
|
||||
AVDictionary *Dict = nullptr;
|
||||
for (const auto &iter : LAVFOpts)
|
||||
av_dict_set(&Dict, iter.first.c_str(), iter.second.c_str(), 0);
|
||||
|
||||
if (avformat_open_input(&FormatContext, SourceFile, nullptr, &Dict) != 0)
|
||||
void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext, int Track) {
|
||||
if (avformat_open_input(&FormatContext, SourceFile, nullptr, nullptr) != 0)
|
||||
throw FFMS_Exception(FFMS_ERROR_PARSER, FFMS_ERROR_FILE_READ,
|
||||
std::string("Couldn't open '") + SourceFile + "'");
|
||||
|
||||
av_dict_free(&Dict);
|
||||
|
||||
if (avformat_find_stream_info(FormatContext, nullptr) < 0) {
|
||||
avformat_close_input(&FormatContext);
|
||||
FormatContext = nullptr;
|
||||
|
@ -147,27 +140,3 @@ bool IsSamePath(const char *p1, const char *p2) {
|
|||
return !_stricmp(p1, p2);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsIOError(int error) {
|
||||
switch (error) {
|
||||
case AVERROR(EIO):
|
||||
case AVERROR(ETIMEDOUT):
|
||||
case AVERROR(EPROTO):
|
||||
case AVERROR(EADDRINUSE):
|
||||
case AVERROR(EADDRNOTAVAIL):
|
||||
case AVERROR(ENETDOWN):
|
||||
case AVERROR(ENETUNREACH):
|
||||
case AVERROR(ENETRESET):
|
||||
case AVERROR(ECONNABORTED):
|
||||
case AVERROR(ECONNRESET):
|
||||
case AVERROR(ECONNREFUSED):
|
||||
case AVERROR(EHOSTUNREACH):
|
||||
#ifndef _WIN32
|
||||
case AVERROR(ESHUTDOWN):
|
||||
case AVERROR(EHOSTDOWN):
|
||||
#endif
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
138
ffms2/src/core/utils.h
Normal file
138
ffms2/src/core/utils.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
// Copyright (c) 2007-2011 Fredrik Mellbin
|
||||
//
|
||||
// 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 UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include "ffms.h"
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/mem.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libswresample/swresample.h>
|
||||
}
|
||||
|
||||
// must be included after ffmpeg headers
|
||||
#include "ffmscompat.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class FFMS_Exception {
|
||||
std::string _Message;
|
||||
int _ErrorType;
|
||||
int _SubType;
|
||||
|
||||
public:
|
||||
FFMS_Exception(int ErrorType, int SubType, const char *Message = "");
|
||||
FFMS_Exception(int ErrorType, int SubType, const std::string &Message);
|
||||
const std::string &GetErrorMessage() const { return _Message; }
|
||||
int CopyOut(FFMS_ErrorInfo *ErrorInfo) const;
|
||||
};
|
||||
|
||||
template<typename T, typename... Args>
|
||||
std::unique_ptr<T> make_unique(Args&&... args) {
|
||||
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
void ClearErrorInfo(FFMS_ErrorInfo *ErrorInfo);
|
||||
void InitNullPacket(AVPacket &pkt);
|
||||
void FillAP(FFMS_AudioProperties &AP, AVCodecContext *CTX, FFMS_Track &Frames);
|
||||
|
||||
void LAVFOpenFile(const char *SourceFile, AVFormatContext *&FormatContext, int Track);
|
||||
|
||||
namespace optdetail {
|
||||
template<typename T>
|
||||
T get_av_opt(void *v, const char *name) {
|
||||
int64_t value = 0;
|
||||
av_opt_get_int(v, name, 0, &value);
|
||||
return static_cast<T>(value);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline double get_av_opt<double>(void *v, const char *name) {
|
||||
double value = 0.0;
|
||||
av_opt_get_double(v, name, 0, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void set_av_opt(void *v, const char *name, T value) {
|
||||
av_opt_set_int(v, name, value, 0);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline void set_av_opt<double>(void *v, const char *name, double value) {
|
||||
av_opt_set_double(v, name, value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename FFMS_Struct>
|
||||
class OptionMapper {
|
||||
struct OptionMapperBase {
|
||||
virtual void ToOpt(FFMS_Struct const& src, void *dst) const = 0;
|
||||
virtual void FromOpt(FFMS_Struct &dst, void *src) const = 0;
|
||||
virtual ~OptionMapperBase() = default;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class OptionMapperImpl : public OptionMapperBase {
|
||||
T(FFMS_Struct::*ptr);
|
||||
const char *name;
|
||||
|
||||
public:
|
||||
OptionMapperImpl(T(FFMS_Struct::*ptr), const char *name) : ptr(ptr), name(name) {}
|
||||
void ToOpt(FFMS_Struct const& src, void *dst) const { optdetail::set_av_opt(dst, name, src.*ptr); }
|
||||
void FromOpt(FFMS_Struct &dst, void *src) const { dst.*ptr = optdetail::get_av_opt<T>(src, name); }
|
||||
};
|
||||
|
||||
std::unique_ptr<OptionMapperBase> impl;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
OptionMapper(const char *opt_name, T(FFMS_Struct::*member)) : impl(new OptionMapperImpl<T>(member, opt_name)) {}
|
||||
|
||||
void ToOpt(FFMS_Struct const& src, void *dst) const { impl->ToOpt(src, dst); }
|
||||
void FromOpt(FFMS_Struct &dst, void *src) const { impl->FromOpt(dst, src); }
|
||||
};
|
||||
|
||||
template<typename T, int N>
|
||||
std::unique_ptr<T> ReadOptions(void *opt, OptionMapper<T>(&options)[N]) {
|
||||
auto ret = make_unique<T>();
|
||||
for (int i = 0; i < N; ++i)
|
||||
options[i].FromOpt(*ret, opt);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename T, int N>
|
||||
void SetOptions(T const& src, void *opt, OptionMapper<T>(&options)[N]) {
|
||||
for (int i = 0; i < N; ++i)
|
||||
options[i].ToOpt(src, opt);
|
||||
}
|
||||
|
||||
int ResizerNameToSWSResizer(const char *ResizerName);
|
||||
bool IsSamePath(const char *p1, const char *p2);
|
||||
|
||||
#endif
|
|
@ -81,7 +81,7 @@ FFMS_Frame *FFMS_VideoSource::OutputFrame(AVFrame *Frame) {
|
|||
LocalFrame.PictType = av_get_picture_type_char(Frame->pict_type);
|
||||
LocalFrame.RepeatPict = Frame->repeat_pict;
|
||||
LocalFrame.InterlacedFrame = Frame->interlaced_frame;
|
||||
LocalFrame.TopFieldFirst = Frame->top_field_first;
|
||||
LocalFrame.TopFieldFirst = Frame->top_field_first;
|
||||
LocalFrame.ColorSpace = OutputColorSpaceSet ? OutputColorSpace : Frame->colorspace;
|
||||
LocalFrame.ColorRange = OutputColorRangeSet ? OutputColorRange : Frame->color_range;
|
||||
LocalFrame.ColorPrimaries = (OutputColorPrimaries >= 0) ? OutputColorPrimaries : Frame->color_primaries;
|
||||
|
@ -113,49 +113,6 @@ FFMS_Frame *FFMS_VideoSource::OutputFrame(AVFrame *Frame) {
|
|||
/* MasteringDisplayMinLuminance can be 0 */
|
||||
LocalFrame.HasMasteringDisplayLuminance = !!LocalFrame.MasteringDisplayMaxLuminance;
|
||||
|
||||
const AVFrameSideData *DolbyVisionRPUSideData = av_frame_get_side_data(Frame, AV_FRAME_DATA_DOVI_RPU_BUFFER);
|
||||
if (DolbyVisionRPUSideData) {
|
||||
if (DolbyVisionRPUSideData->size > RPUBufferSize) {
|
||||
void *tmp = av_realloc(RPUBuffer, DolbyVisionRPUSideData->size);
|
||||
if (!tmp)
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED,
|
||||
"Could not allocate RPU buffer.");
|
||||
RPUBuffer = reinterpret_cast<uint8_t *>(tmp);
|
||||
RPUBufferSize = DolbyVisionRPUSideData->size;
|
||||
}
|
||||
|
||||
memcpy(RPUBuffer, DolbyVisionRPUSideData->data, DolbyVisionRPUSideData->size);
|
||||
|
||||
LocalFrame.DolbyVisionRPU = RPUBuffer;
|
||||
LocalFrame.DolbyVisionRPUSize = DolbyVisionRPUSideData->size;
|
||||
}
|
||||
|
||||
#if VERSION_CHECK(LIBAVUTIL_VERSION_INT, >=, 58, 5, 100)
|
||||
AVFrameSideData *HDR10PlusSideData = av_frame_get_side_data(Frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS);
|
||||
if (HDR10PlusSideData) {
|
||||
uint8_t *T35Buffer = nullptr;
|
||||
size_t T35Size;
|
||||
int ret = av_dynamic_hdr_plus_to_t35(reinterpret_cast<const AVDynamicHDRPlus *>(HDR10PlusSideData->data), &T35Buffer, &T35Size);
|
||||
if (ret < 0)
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_INVALID_ARGUMENT,
|
||||
"HDR10+ dynamic metadata could not be serialized.");
|
||||
if (T35Size > HDR10PlusBufferSize) {
|
||||
void *tmp = av_realloc(HDR10PlusBuffer, T35Size);
|
||||
if (!tmp)
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED,
|
||||
"Could not allocate HDR10+ buffer.");
|
||||
HDR10PlusBuffer = reinterpret_cast<uint8_t *>(tmp);
|
||||
HDR10PlusBufferSize = T35Size;
|
||||
}
|
||||
|
||||
memcpy(HDR10PlusBuffer, T35Buffer, T35Size);
|
||||
av_free(T35Buffer);
|
||||
|
||||
LocalFrame.HDR10Plus = HDR10PlusBuffer;
|
||||
LocalFrame.HDR10PlusSize = T35Size;
|
||||
}
|
||||
#endif
|
||||
|
||||
const AVFrameSideData *ContentLightSideData = av_frame_get_side_data(Frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
|
||||
if (ContentLightSideData) {
|
||||
const AVContentLightMetadata *ContentLightLevel = reinterpret_cast<const AVContentLightMetadata *>(ContentLightSideData->data);
|
||||
|
@ -212,9 +169,9 @@ FFMS_VideoSource::FFMS_VideoSource(const char *SourceFile, FFMS_Index &Index, in
|
|||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED,
|
||||
"Could not allocate dummy frame.");
|
||||
|
||||
LAVFOpenFile(SourceFile, FormatContext, VideoTrack, Index.LAVFOpts);
|
||||
LAVFOpenFile(SourceFile, FormatContext, VideoTrack);
|
||||
|
||||
auto *Codec = avcodec_find_decoder(FormatContext->streams[VideoTrack]->codecpar->codec_id);
|
||||
AVCodec *Codec = avcodec_find_decoder(FormatContext->streams[VideoTrack]->codecpar->codec_id);
|
||||
if (Codec == nullptr)
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_CODEC,
|
||||
"Video codec not found");
|
||||
|
@ -653,16 +610,14 @@ bool FFMS_VideoSource::DecodePacket(AVPacket *Packet) {
|
|||
// H.264 (PAFF) and HEVC can have one field per packet, and decoding delay needs
|
||||
// to be adjusted accordingly.
|
||||
if (CodecContext->codec_id == AV_CODEC_ID_H264 || CodecContext->codec_id == AV_CODEC_ID_HEVC) {
|
||||
if (LastDecodedFrame->interlaced_frame == 1)
|
||||
HaveSeenInterlacedFrame = true;
|
||||
if (!PAFFAdjusted && DelayCounter > Delay && HaveSeenInterlacedFrame && LastDecodedFrame->repeat_pict == 0 && Ret != 0) {
|
||||
if (!PAFFAdjusted && DelayCounter > Delay && LastDecodedFrame->repeat_pict == 0 && Ret != 0) {
|
||||
int OldBFrameDelay = Delay - (CodecContext->thread_count - 1);
|
||||
Delay = 1 + OldBFrameDelay * 2 + (CodecContext->thread_count - 1);
|
||||
PAFFAdjusted = true;
|
||||
}
|
||||
}
|
||||
|
||||
return (Ret == 0) || (DelayCounter > Delay && !InitialDecode);
|
||||
return (Ret == 0) || (DelayCounter > Delay && !InitialDecode);;
|
||||
}
|
||||
|
||||
int FFMS_VideoSource::Seek(int n) {
|
||||
|
@ -703,8 +658,6 @@ int FFMS_VideoSource::ReadFrame(AVPacket *pkt) {
|
|||
}
|
||||
|
||||
void FFMS_VideoSource::Free() {
|
||||
av_freep(&RPUBuffer);
|
||||
av_freep(&HDR10PlusBuffer);
|
||||
avcodec_free_context(&CodecContext);
|
||||
avformat_close_input(&FormatContext);
|
||||
if (SWS)
|
||||
|
@ -720,42 +673,30 @@ void FFMS_VideoSource::DecodeNextFrame(int64_t &AStartTime, int64_t &Pos) {
|
|||
if (HasPendingDelayedFrames())
|
||||
return;
|
||||
|
||||
AVPacket *Packet = av_packet_alloc();
|
||||
if (!Packet)
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_ALLOCATION_FAILED,
|
||||
"Could not allocate packet.");
|
||||
AVPacket Packet;
|
||||
InitNullPacket(Packet);
|
||||
|
||||
int ret;
|
||||
while ((ret = ReadFrame(Packet)) >= 0) {
|
||||
if (Packet->stream_index != VideoTrack) {
|
||||
av_packet_unref(Packet);
|
||||
while (ReadFrame(&Packet) >= 0) {
|
||||
if (Packet.stream_index != VideoTrack) {
|
||||
av_packet_unref(&Packet);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AStartTime < 0)
|
||||
AStartTime = Frames.UseDTS ? Packet->dts : Packet->pts;
|
||||
AStartTime = Frames.UseDTS ? Packet.dts : Packet.pts;
|
||||
|
||||
if (Pos < 0)
|
||||
Pos = Packet->pos;
|
||||
Pos = Packet.pos;
|
||||
|
||||
bool FrameFinished = DecodePacket(Packet);
|
||||
av_packet_unref(Packet);
|
||||
if (FrameFinished) {
|
||||
av_packet_free(&Packet);
|
||||
bool FrameFinished = DecodePacket(&Packet);
|
||||
av_packet_unref(&Packet);
|
||||
if (FrameFinished)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (IsIOError(ret)) {
|
||||
char err[1024];
|
||||
av_strerror(ret, err, 1024);
|
||||
std::string serr(err);
|
||||
throw FFMS_Exception(FFMS_ERROR_DECODING, FFMS_ERROR_FILE_READ,
|
||||
"Failed to read packet: " + serr);
|
||||
}
|
||||
|
||||
// Flush final frames
|
||||
DecodePacket(Packet);
|
||||
av_packet_free(&Packet);
|
||||
InitNullPacket(Packet);
|
||||
DecodePacket(&Packet);
|
||||
}
|
||||
|
||||
bool FFMS_VideoSource::SeekTo(int n, int SeekOffset) {
|
||||
|
@ -808,7 +749,7 @@ FFMS_Frame *FFMS_VideoSource::GetFrame(int n) {
|
|||
|
||||
int64_t StartTime = AV_NOPTS_VALUE, FilePos = -1;
|
||||
bool Hidden = (((unsigned) CurrentFrame < Frames.size()) && Frames[CurrentFrame].Hidden);
|
||||
if (HasSeeked || !Hidden || PAFFAdjusted)
|
||||
if (HasSeeked || !Hidden)
|
||||
DecodeNextFrame(StartTime, FilePos);
|
||||
|
||||
if (!HasSeeked)
|
|
@ -29,11 +29,6 @@ extern "C" {
|
|||
#include <libavutil/stereo3d.h>
|
||||
#include <libavutil/display.h>
|
||||
#include <libavutil/mastering_display_metadata.h>
|
||||
|
||||
#include "ffmscompat.h"
|
||||
#if VERSION_CHECK(LIBAVUTIL_VERSION_INT, >=, 58, 5, 100)
|
||||
#include <libavutil/hdr_dynamic_metadata.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
#include <vector>
|
||||
|
@ -82,10 +77,6 @@ private:
|
|||
|
||||
FFMS_VideoProperties VP = {};
|
||||
FFMS_Frame LocalFrame = {};
|
||||
uint8_t *RPUBuffer = nullptr;
|
||||
size_t RPUBufferSize = 0;
|
||||
uint8_t *HDR10PlusBuffer = nullptr;
|
||||
size_t HDR10PlusBufferSize = 0;
|
||||
AVFrame *DecodeFrame = nullptr;
|
||||
AVFrame *LastDecodedFrame = nullptr;
|
||||
int LastFrameNum = 0;
|
||||
|
@ -99,7 +90,6 @@ private:
|
|||
int SeekMode;
|
||||
bool SeekByPos = false;
|
||||
int PosOffset = 0;
|
||||
bool HaveSeenInterlacedFrame = false;
|
||||
|
||||
void ReAdjustOutputFormat(AVFrame *Frame);
|
||||
FFMS_Frame *OutputFrame(AVFrame *Frame);
|
|
@ -153,7 +153,7 @@ static LossAttributes CalculateLoss(AVPixelFormat Dst, AVPixelFormat Src) {
|
|||
|
||||
LossAttributes Loss;
|
||||
Loss.Format = Dst;
|
||||
Loss.DepthDifference = GetPseudoDepth(DstDesc) - GetPseudoDepth(SrcDesc);
|
||||
Loss.DepthDifference = GetPseudoDepth(DstDesc) - GetPseudoDepth(SrcDesc);;
|
||||
Loss.ChromaOversampling = FFMAX(0, SrcDesc.log2_chroma_h - DstDesc.log2_chroma_h) + FFMAX(0, SrcDesc.log2_chroma_w - DstDesc.log2_chroma_w);
|
||||
Loss.ChromaUndersampling = FFMAX(0, DstDesc.log2_chroma_h - SrcDesc.log2_chroma_h) + FFMAX(0, DstDesc.log2_chroma_w - SrcDesc.log2_chroma_w);
|
||||
Loss.CSGain = 0;
|
||||
|
@ -248,13 +248,16 @@ void ParseVP8(const uint8_t Buf, bool *Invisible, int *PictType) {
|
|||
*Invisible = (*Invisible || !(Buf & 0x10));
|
||||
}
|
||||
|
||||
void ParseVP9(const uint8_t Buf, int *PictType)
|
||||
void ParseVP9(const uint8_t Buf, bool *Invisible, int *PictType)
|
||||
{
|
||||
int profile = ((Buf & 0x20) >> 5) | ((Buf & 0x10) >> 3);
|
||||
int shift = (profile == 3);
|
||||
|
||||
if (Buf & (0x8 >> shift))
|
||||
if (Buf & (0x8 >> shift)) {
|
||||
*Invisible = false;
|
||||
*PictType = AV_PICTURE_TYPE_P;
|
||||
else
|
||||
} else {
|
||||
*PictType = (Buf & (0x4 >> shift)) ? AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_I;
|
||||
*Invisible = !(Buf & (0x2 >> shift));
|
||||
}
|
||||
}
|
|
@ -52,4 +52,4 @@ AVPixelFormat FindBestPixelFormat(const std::vector<AVPixelFormat> &Dsts, AVPixe
|
|||
|
||||
// handling of alt-refs in VP8 and VP9
|
||||
void ParseVP8(const uint8_t Buf, bool *Invisible, int *PictType);
|
||||
void ParseVP9(const uint8_t Buf, int *PictType);
|
||||
void ParseVP9(const uint8_t Buf, bool *Invisible, int *PictType);
|
285
ffms2/src/index/ffmsindex.cpp
Normal file
285
ffms2/src/index/ffmsindex.cpp
Normal file
|
@ -0,0 +1,285 @@
|
|||
// Copyright (c) 2008-2009 Karl Blomster
|
||||
//
|
||||
// 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 "ffms.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "vsutf16.h"
|
||||
#endif
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace {
|
||||
|
||||
long long IndexMask = 0;
|
||||
int Verbose = 0;
|
||||
int IgnoreErrors = 0;
|
||||
bool Overwrite = false;
|
||||
bool PrintProgress = true;
|
||||
bool WriteTC = false;
|
||||
bool WriteKF = false;
|
||||
std::string InputFile;
|
||||
std::string CacheFile;
|
||||
|
||||
struct Error {
|
||||
std::string msg;
|
||||
Error(const char *msg) : msg(msg) {}
|
||||
Error(const char *msg, FFMS_ErrorInfo const& e) : msg(msg) {
|
||||
this->msg.append(e.Buffer);
|
||||
}
|
||||
};
|
||||
|
||||
void PrintUsage() {
|
||||
std::cout <<
|
||||
"FFmpegSource2 indexing app\n"
|
||||
"Usage: ffmsindex [options] inputfile [outputfile]\n"
|
||||
"If no output filename is specified, inputfile.ffindex will be used.\n"
|
||||
"\n"
|
||||
"Options:\n"
|
||||
"-f Force overwriting of existing index file, if any (default: no)\n"
|
||||
"-v Set FFmpeg verbosity level. Can be repeated for more verbosity. (default: no messages printed)\n"
|
||||
"-p Disable progress reporting. (default: progress reporting on)\n"
|
||||
"-c Write timecodes for all video tracks to outputfile_track00.tc.txt (default: no)\n"
|
||||
"-k Write keyframes for all video tracks to outputfile_track00.kf.txt (default: no)\n"
|
||||
"-t N Set the audio indexing mask to N (-1 means index all tracks, 0 means index none, default: 0)\n"
|
||||
"-s N Set audio decoding error handling. See the documentation for details. (default: 0)\n"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
void ParseCMDLine(int argc, const char *argv[]) {
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
const char *Option = argv[i];
|
||||
#define OPTION_ARG(dst, flag, parse) try { dst = parse(i + 1 < argc ? argv[i+1] : throw Error("Error: missing argument for -" flag)); i++; } catch (std::logic_error &) { throw Error("Error: invalid argument specified for -" flag); }
|
||||
|
||||
if (!strcmp(Option, "-f")) {
|
||||
Overwrite = true;
|
||||
} else if (!strcmp(Option, "-v")) {
|
||||
Verbose++;
|
||||
} else if (!strcmp(Option, "-p")) {
|
||||
PrintProgress = false;
|
||||
} else if (!strcmp(Option, "-c")) {
|
||||
WriteTC = true;
|
||||
} else if (!strcmp(Option, "-k")) {
|
||||
WriteKF = true;
|
||||
} else if (!strcmp(Option, "-t")) {
|
||||
OPTION_ARG(IndexMask, "t", std::stoll);
|
||||
} else if (!strcmp(Option, "-s")) {
|
||||
OPTION_ARG(IgnoreErrors, "s", std::stoi);
|
||||
} else if (InputFile.empty()) {
|
||||
InputFile = Option;
|
||||
} else if (CacheFile.empty()) {
|
||||
CacheFile = Option;
|
||||
} else {
|
||||
std::cout << "Warning: ignoring unknown option " << Option << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (IgnoreErrors < 0 || IgnoreErrors > 3)
|
||||
throw Error("Error: invalid error handling mode");
|
||||
if (InputFile.empty())
|
||||
throw Error("Error: no input file specified");
|
||||
|
||||
if (CacheFile.empty()) {
|
||||
CacheFile = InputFile;
|
||||
CacheFile.append(".ffindex");
|
||||
}
|
||||
}
|
||||
|
||||
int FFMS_CC UpdateProgress(int64_t Current, int64_t Total, void *Private) {
|
||||
if (!PrintProgress)
|
||||
return 0;
|
||||
|
||||
int Percentage = int((double(Current) / double(Total)) * 100);
|
||||
|
||||
if (Private) {
|
||||
int *LastPercentage = (int *)Private;
|
||||
if (Percentage <= *LastPercentage)
|
||||
return 0;
|
||||
*LastPercentage = Percentage;
|
||||
}
|
||||
|
||||
std::cout << "Indexing, please wait... " << Percentage << "% \r" << std::flush;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string DumpFilename(FFMS_Track *Track, int TrackNum, const char *Suffix) {
|
||||
if (FFMS_GetTrackType(Track) != FFMS_TYPE_VIDEO || !FFMS_GetNumFrames(Track))
|
||||
return "";
|
||||
|
||||
char tn[11];
|
||||
snprintf(tn, 11, "%02" PRIu32"", (uint32_t) TrackNum);
|
||||
return CacheFile + "_track" + tn + Suffix;
|
||||
}
|
||||
|
||||
void DoIndexing() {
|
||||
char ErrorMsg[1024];
|
||||
FFMS_ErrorInfo E;
|
||||
E.Buffer = ErrorMsg;
|
||||
E.BufferSize = sizeof(ErrorMsg);
|
||||
|
||||
int Progress = 0;
|
||||
|
||||
FFMS_Index *Index = FFMS_ReadIndex(CacheFile.c_str(), &E);
|
||||
if (Index) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
if (!Overwrite)
|
||||
throw Error("Error: index file already exists, use -f if you are sure you want to overwrite it.");
|
||||
}
|
||||
|
||||
UpdateProgress(0, 100, nullptr);
|
||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(InputFile.c_str(), &E);
|
||||
if (Indexer == nullptr)
|
||||
throw Error("\nFailed to initialize indexing: ", E);
|
||||
|
||||
FFMS_SetProgressCallback(Indexer, UpdateProgress, &Progress);
|
||||
|
||||
// Treat -1 as meaning track numbers above sizeof(long long) * 8 too, dumping implies indexing
|
||||
if (IndexMask == -1)
|
||||
FFMS_TrackTypeIndexSettings(Indexer, FFMS_TYPE_AUDIO, 1, 0);
|
||||
|
||||
// Apply attributes to remaining tracks (will set the attributes again on some tracks)
|
||||
for (int i = 0; i < static_cast<int>(sizeof(IndexMask) * 8); i++) {
|
||||
if ((IndexMask >> i) & 1)
|
||||
FFMS_TrackIndexSettings(Indexer, i, 1, 0);
|
||||
}
|
||||
|
||||
Index = FFMS_DoIndexing2(Indexer, IgnoreErrors, &E);
|
||||
|
||||
// The indexer is always freed
|
||||
Indexer = nullptr;
|
||||
|
||||
if (Index == nullptr)
|
||||
throw Error("\nIndexing error: ", E);
|
||||
|
||||
UpdateProgress(100, 100, nullptr);
|
||||
|
||||
std::cout << std::endl;
|
||||
|
||||
if (WriteTC) {
|
||||
if (PrintProgress)
|
||||
std::cout << "Writing timecodes... ";
|
||||
int NumTracks = FFMS_GetNumTracks(Index);
|
||||
for (int t = 0; t < NumTracks; t++) {
|
||||
FFMS_Track *Track = FFMS_GetTrackFromIndex(Index, t);
|
||||
std::string Filename = DumpFilename(Track, t, ".tc.txt");
|
||||
if (!Filename.empty()) {
|
||||
if (FFMS_WriteTimecodes(Track, Filename.c_str(), &E))
|
||||
std::cout << std::endl << "Failed to write timecodes file "
|
||||
<< Filename << ": " << E.Buffer << std::endl;
|
||||
}
|
||||
}
|
||||
if (PrintProgress)
|
||||
std::cout << "done." << std::endl;
|
||||
}
|
||||
|
||||
if (WriteKF) {
|
||||
if (PrintProgress)
|
||||
std::cout << "Writing keyframes... ";
|
||||
int NumTracks = FFMS_GetNumTracks(Index);
|
||||
for (int t = 0; t < NumTracks; t++) {
|
||||
FFMS_Track *Track = FFMS_GetTrackFromIndex(Index, t);
|
||||
std::string Filename = DumpFilename(Track, t, ".kf.txt");
|
||||
if (!Filename.empty()) {
|
||||
std::ofstream kf(Filename.c_str());
|
||||
kf << "# keyframe format v1\n"
|
||||
"fps 0\n";
|
||||
|
||||
int FrameCount = FFMS_GetNumFrames(Track);
|
||||
for (int CurFrameNum = 0; CurFrameNum < FrameCount; CurFrameNum++) {
|
||||
if (FFMS_GetFrameInfo(Track, CurFrameNum)->KeyFrame)
|
||||
kf << CurFrameNum << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (PrintProgress)
|
||||
std::cout << "done. " << std::endl;
|
||||
}
|
||||
|
||||
if (PrintProgress)
|
||||
std::cout << "Writing index... ";
|
||||
|
||||
int error = FFMS_WriteIndex(CacheFile.c_str(), Index, &E);
|
||||
FFMS_DestroyIndex(Index);
|
||||
if (error)
|
||||
throw Error("Error writing index: ", E);
|
||||
|
||||
if (PrintProgress)
|
||||
std::cout << "done." << std::endl;
|
||||
}
|
||||
|
||||
} // namespace {
|
||||
|
||||
#ifdef _WIN32
|
||||
int wmain(int argc, const wchar_t *_argv[]) {
|
||||
std::vector<const char *> StringPtrs(argc);
|
||||
std::vector<std::string> StringStorage(argc);
|
||||
|
||||
for (int i = 0; i < argc; i++) {
|
||||
StringStorage[i] = utf16_to_utf8(_argv[i]);
|
||||
StringPtrs[i] = StringStorage[i].c_str();
|
||||
}
|
||||
|
||||
const char **argv = StringPtrs.data();
|
||||
#else
|
||||
int main(int argc, const char *argv[]) {
|
||||
#endif
|
||||
try {
|
||||
if (argc <= 1) {
|
||||
PrintUsage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ParseCMDLine(argc, argv);
|
||||
} catch (Error const& e) {
|
||||
std::cout << e.msg << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
FFMS_Init(0, 0);
|
||||
|
||||
switch (Verbose) {
|
||||
case 0: FFMS_SetLogLevel(FFMS_LOG_QUIET); break;
|
||||
case 1: FFMS_SetLogLevel(FFMS_LOG_WARNING); break;
|
||||
case 2: FFMS_SetLogLevel(FFMS_LOG_INFO); break;
|
||||
case 3: FFMS_SetLogLevel(FFMS_LOG_VERBOSE); break;
|
||||
default: FFMS_SetLogLevel(FFMS_LOG_DEBUG); // if user used -v 4 or more times, he deserves the spam
|
||||
}
|
||||
|
||||
try {
|
||||
DoIndexing();
|
||||
} catch (Error const& e) {
|
||||
std::cout << e.msg << std::endl;
|
||||
FFMS_Deinit();
|
||||
return 1;
|
||||
}
|
||||
|
||||
FFMS_Deinit();
|
||||
return 0;
|
||||
}
|
174
ffms2/src/vapoursynth/VSHelper.h
Normal file
174
ffms2/src/vapoursynth/VSHelper.h
Normal file
|
@ -0,0 +1,174 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2012-2015 Fredrik Mellbin
|
||||
* --- Legal stuff ---
|
||||
* This program is free software. It comes without any warranty, to
|
||||
* the extent permitted by applicable law. You can redistribute it
|
||||
* and/or modify it under the terms of the Do What The Fuck You Want
|
||||
* To Public License, Version 2, as published by Sam Hocevar. See
|
||||
* http://sam.zoy.org/wtfpl/COPYING for more details.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef VSHELPER_H
|
||||
#define VSHELPER_H
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#ifdef _WIN32
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
#include "VapourSynth.h"
|
||||
|
||||
/* Visual Studio doesn't recognize inline in c mode */
|
||||
#if defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define inline _inline
|
||||
#endif
|
||||
|
||||
/* A kinda portable definition of the C99 restrict keyword (or its inofficial C++ equivalent) */
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* Available in C99 */
|
||||
#define VS_RESTRICT restrict
|
||||
#elif defined(__cplusplus) || defined(_MSC_VER) /* Almost all relevant C++ compilers support it so just assume it works */
|
||||
#define VS_RESTRICT __restrict
|
||||
#else /* Not supported */
|
||||
#define VS_RESTRICT
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define VS_ALIGNED_MALLOC(pptr, size, alignment) do { *(pptr) = _aligned_malloc((size), (alignment)); } while (0)
|
||||
#define VS_ALIGNED_FREE(ptr) do { _aligned_free((ptr)); } while (0)
|
||||
#else
|
||||
#define VS_ALIGNED_MALLOC(pptr, size, alignment) do { if(posix_memalign((void**)(pptr), (alignment), (size))) *((void**)pptr) = NULL; } while (0)
|
||||
#define VS_ALIGNED_FREE(ptr) do { free((ptr)); } while (0)
|
||||
#endif
|
||||
|
||||
#define VSMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define VSMIN(a,b) ((a) > (b) ? (b) : (a))
|
||||
|
||||
#ifdef __cplusplus
|
||||
/* A nicer templated malloc for all the C++ users out there */
|
||||
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
|
||||
template<typename T=void>
|
||||
#else
|
||||
template<typename T>
|
||||
#endif
|
||||
static inline T* vs_aligned_malloc(size_t size, size_t alignment) {
|
||||
#ifdef _WIN32
|
||||
return (T*)_aligned_malloc(size, alignment);
|
||||
#else
|
||||
void *tmp = NULL;
|
||||
if (posix_memalign(&tmp, alignment, size))
|
||||
tmp = 0;
|
||||
return (T*)tmp;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void vs_aligned_free(void *ptr) {
|
||||
VS_ALIGNED_FREE(ptr);
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* convenience function for checking if the format never changes between frames */
|
||||
static inline int isConstantFormat(const VSVideoInfo *vi) {
|
||||
return vi->height > 0 && vi->width > 0 && vi->format;
|
||||
}
|
||||
|
||||
/* convenience function to check for if two clips have the same format (unknown/changeable will be considered the same too) */
|
||||
static inline int isSameFormat(const VSVideoInfo *v1, const VSVideoInfo *v2) {
|
||||
return v1->height == v2->height && v1->width == v2->width && v1->format == v2->format;
|
||||
}
|
||||
|
||||
/* multiplies and divides a rational number, such as a frame duration, in place and reduces the result */
|
||||
static inline void muldivRational(int64_t *num, int64_t *den, int64_t mul, int64_t div) {
|
||||
/* do nothing if the rational number is invalid */
|
||||
if (!*den)
|
||||
return;
|
||||
|
||||
/* nobody wants to accidentally divide by zero */
|
||||
assert(div);
|
||||
|
||||
int64_t a, b;
|
||||
*num *= mul;
|
||||
*den *= div;
|
||||
a = *num;
|
||||
b = *den;
|
||||
while (b != 0) {
|
||||
int64_t t = a;
|
||||
a = b;
|
||||
b = t % b;
|
||||
}
|
||||
if (a < 0)
|
||||
a = -a;
|
||||
*num /= a;
|
||||
*den /= a;
|
||||
}
|
||||
|
||||
/* reduces a rational number */
|
||||
static inline void vs_normalizeRational(int64_t *num, int64_t *den) {
|
||||
muldivRational(num, den, 1, 1);
|
||||
}
|
||||
|
||||
/* add two rational numbers and reduces the result */
|
||||
static inline void vs_addRational(int64_t *num, int64_t *den, int64_t addnum, int64_t addden) {
|
||||
/* do nothing if the rational number is invalid */
|
||||
if (!*den)
|
||||
return;
|
||||
|
||||
/* nobody wants to accidentally add an invalid rational number */
|
||||
assert(addden);
|
||||
|
||||
if (*den == addden) {
|
||||
*num += addnum;
|
||||
} else {
|
||||
int64_t temp = addden;
|
||||
addnum *= *den;
|
||||
addden *= *den;
|
||||
*num *= temp;
|
||||
*den *= temp;
|
||||
|
||||
*num += addnum;
|
||||
|
||||
vs_normalizeRational(num, den);
|
||||
}
|
||||
}
|
||||
|
||||
/* converts an int64 to int with saturation, useful to silence warnings when reading int properties among other things */
|
||||
static inline int int64ToIntS(int64_t i) {
|
||||
if (i > INT_MAX)
|
||||
return INT_MAX;
|
||||
else if (i < INT_MIN)
|
||||
return INT_MIN;
|
||||
else return (int)i;
|
||||
}
|
||||
|
||||
static inline void vs_bitblt(void *dstp, int dst_stride, const void *srcp, int src_stride, size_t row_size, size_t height) {
|
||||
if (height) {
|
||||
if (src_stride == dst_stride && src_stride == (int)row_size) {
|
||||
memcpy(dstp, srcp, row_size * height);
|
||||
} else {
|
||||
const uint8_t *srcp8 = (const uint8_t *)srcp;
|
||||
uint8_t *dstp8 = (uint8_t *)dstp;
|
||||
size_t i;
|
||||
for (i = 0; i < height; i++) {
|
||||
memcpy(dstp8, srcp8, row_size);
|
||||
srcp8 += src_stride;
|
||||
dstp8 += dst_stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check if the frame dimensions are valid for a given format */
|
||||
/* returns non-zero for valid width and height */
|
||||
static inline int areValidDimensions(const VSFormat *fi, int width, int height) {
|
||||
return !(width % (1 << fi->subSamplingW) || height % (1 << fi->subSamplingH));
|
||||
}
|
||||
|
||||
/* Visual Studio doesn't recognize inline in c mode */
|
||||
#if defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#undef inline
|
||||
#endif
|
||||
|
||||
#endif
|
342
ffms2/src/vapoursynth/VapourSynth.h
Normal file
342
ffms2/src/vapoursynth/VapourSynth.h
Normal file
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* Copyright (c) 2012-2017 Fredrik Mellbin
|
||||
*
|
||||
* This file is part of VapourSynth.
|
||||
*
|
||||
* VapourSynth is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* VapourSynth is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with VapourSynth; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef VAPOURSYNTH_H
|
||||
#define VAPOURSYNTH_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define VAPOURSYNTH_API_MAJOR 3
|
||||
#define VAPOURSYNTH_API_MINOR 5
|
||||
#define VAPOURSYNTH_API_VERSION ((VAPOURSYNTH_API_MAJOR << 16) | (VAPOURSYNTH_API_MINOR))
|
||||
|
||||
/* Convenience for C++ users. */
|
||||
#ifdef __cplusplus
|
||||
# define VS_EXTERN_C extern "C"
|
||||
# if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
|
||||
# define VS_NOEXCEPT noexcept
|
||||
# else
|
||||
# define VS_NOEXCEPT
|
||||
# endif
|
||||
#else
|
||||
# define VS_EXTERN_C
|
||||
# define VS_NOEXCEPT
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(_WIN64)
|
||||
# define VS_CC __stdcall
|
||||
#else
|
||||
# define VS_CC
|
||||
#endif
|
||||
|
||||
/* And now for some symbol hide-and-seek... */
|
||||
#if defined(_WIN32) /* Windows being special */
|
||||
# define VS_EXTERNAL_API(ret) VS_EXTERN_C __declspec(dllexport) ret VS_CC
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
# define VS_EXTERNAL_API(ret) VS_EXTERN_C __attribute__((visibility("default"))) ret VS_CC
|
||||
#else
|
||||
# define VS_EXTERNAL_API(ret) VS_EXTERN_C ret VS_CC
|
||||
#endif
|
||||
|
||||
#if !defined(VS_CORE_EXPORTS) && defined(_WIN32)
|
||||
# define VS_API(ret) VS_EXTERN_C __declspec(dllimport) ret VS_CC
|
||||
#else
|
||||
# define VS_API(ret) VS_EXTERNAL_API(ret)
|
||||
#endif
|
||||
|
||||
typedef struct VSFrameRef VSFrameRef;
|
||||
typedef struct VSNodeRef VSNodeRef;
|
||||
typedef struct VSCore VSCore;
|
||||
typedef struct VSPlugin VSPlugin;
|
||||
typedef struct VSNode VSNode;
|
||||
typedef struct VSFuncRef VSFuncRef;
|
||||
typedef struct VSMap VSMap;
|
||||
typedef struct VSAPI VSAPI;
|
||||
typedef struct VSFrameContext VSFrameContext;
|
||||
|
||||
typedef enum VSColorFamily {
|
||||
/* all planar formats */
|
||||
cmGray = 1000000,
|
||||
cmRGB = 2000000,
|
||||
cmYUV = 3000000,
|
||||
cmYCoCg = 4000000,
|
||||
/* special for compatibility */
|
||||
cmCompat = 9000000
|
||||
} VSColorFamily;
|
||||
|
||||
typedef enum VSSampleType {
|
||||
stInteger = 0,
|
||||
stFloat = 1
|
||||
} VSSampleType;
|
||||
|
||||
/* The +10 is so people won't be using the constants interchangably "by accident" */
|
||||
typedef enum VSPresetFormat {
|
||||
pfNone = 0,
|
||||
|
||||
pfGray8 = cmGray + 10,
|
||||
pfGray16,
|
||||
|
||||
pfGrayH,
|
||||
pfGrayS,
|
||||
|
||||
pfYUV420P8 = cmYUV + 10,
|
||||
pfYUV422P8,
|
||||
pfYUV444P8,
|
||||
pfYUV410P8,
|
||||
pfYUV411P8,
|
||||
pfYUV440P8,
|
||||
|
||||
pfYUV420P9,
|
||||
pfYUV422P9,
|
||||
pfYUV444P9,
|
||||
|
||||
pfYUV420P10,
|
||||
pfYUV422P10,
|
||||
pfYUV444P10,
|
||||
|
||||
pfYUV420P16,
|
||||
pfYUV422P16,
|
||||
pfYUV444P16,
|
||||
|
||||
pfYUV444PH,
|
||||
pfYUV444PS,
|
||||
|
||||
pfYUV420P12,
|
||||
pfYUV422P12,
|
||||
pfYUV444P12,
|
||||
|
||||
pfYUV420P14,
|
||||
pfYUV422P14,
|
||||
pfYUV444P14,
|
||||
|
||||
pfRGB24 = cmRGB + 10,
|
||||
pfRGB27,
|
||||
pfRGB30,
|
||||
pfRGB48,
|
||||
|
||||
pfRGBH,
|
||||
pfRGBS,
|
||||
|
||||
/* special for compatibility, if you implement these in any filter I'll personally kill you */
|
||||
/* I'll also change their ids around to break your stuff regularly */
|
||||
pfCompatBGR32 = cmCompat + 10,
|
||||
pfCompatYUY2
|
||||
} VSPresetFormat;
|
||||
|
||||
typedef enum VSFilterMode {
|
||||
fmParallel = 100, /* completely parallel execution */
|
||||
fmParallelRequests = 200, /* for filters that are serial in nature but can request one or more frames they need in advance */
|
||||
fmUnordered = 300, /* for filters that modify their internal state every request */
|
||||
fmSerial = 400 /* for source filters and compatibility with other filtering architectures */
|
||||
} VSFilterMode;
|
||||
|
||||
typedef struct VSFormat {
|
||||
char name[32];
|
||||
int id;
|
||||
int colorFamily; /* see VSColorFamily */
|
||||
int sampleType; /* see VSSampleType */
|
||||
int bitsPerSample; /* number of significant bits */
|
||||
int bytesPerSample; /* actual storage is always in a power of 2 and the smallest possible that can fit the number of bits used per sample */
|
||||
|
||||
int subSamplingW; /* log2 subsampling factor, applied to second and third plane */
|
||||
int subSamplingH;
|
||||
|
||||
int numPlanes; /* implicit from colorFamily */
|
||||
} VSFormat;
|
||||
|
||||
typedef enum VSNodeFlags {
|
||||
nfNoCache = 1,
|
||||
nfIsCache = 2,
|
||||
nfMakeLinear = 4 /* api 3.3 */
|
||||
} VSNodeFlags;
|
||||
|
||||
typedef enum VSPropTypes {
|
||||
ptUnset = 'u',
|
||||
ptInt = 'i',
|
||||
ptFloat = 'f',
|
||||
ptData = 's',
|
||||
ptNode = 'c',
|
||||
ptFrame = 'v',
|
||||
ptFunction = 'm'
|
||||
} VSPropTypes;
|
||||
|
||||
typedef enum VSGetPropErrors {
|
||||
peUnset = 1,
|
||||
peType = 2,
|
||||
peIndex = 4
|
||||
} VSGetPropErrors;
|
||||
|
||||
typedef enum VSPropAppendMode {
|
||||
paReplace = 0,
|
||||
paAppend = 1,
|
||||
paTouch = 2
|
||||
} VSPropAppendMode;
|
||||
|
||||
typedef struct VSCoreInfo {
|
||||
const char *versionString;
|
||||
int core;
|
||||
int api;
|
||||
int numThreads;
|
||||
int64_t maxFramebufferSize;
|
||||
int64_t usedFramebufferSize;
|
||||
} VSCoreInfo;
|
||||
|
||||
typedef struct VSVideoInfo {
|
||||
const VSFormat *format;
|
||||
int64_t fpsNum;
|
||||
int64_t fpsDen;
|
||||
int width;
|
||||
int height;
|
||||
int numFrames; /* api 3.2 - no longer allowed to be 0 */
|
||||
int flags;
|
||||
} VSVideoInfo;
|
||||
|
||||
typedef enum VSActivationReason {
|
||||
arInitial = 0,
|
||||
arFrameReady = 1,
|
||||
arAllFramesReady = 2,
|
||||
arError = -1
|
||||
} VSActivationReason;
|
||||
|
||||
typedef enum VSMessageType {
|
||||
mtDebug = 0,
|
||||
mtWarning = 1,
|
||||
mtCritical = 2,
|
||||
mtFatal = 3
|
||||
} VSMessageType;
|
||||
|
||||
/* core entry point */
|
||||
typedef const VSAPI *(VS_CC *VSGetVapourSynthAPI)(int version);
|
||||
|
||||
/* plugin function and filter typedefs */
|
||||
typedef void (VS_CC *VSPublicFunction)(const VSMap *in, VSMap *out, void *userData, VSCore *core, const VSAPI *vsapi);
|
||||
typedef void (VS_CC *VSRegisterFunction)(const char *name, const char *args, VSPublicFunction argsFunc, void *functionData, VSPlugin *plugin);
|
||||
typedef void (VS_CC *VSConfigPlugin)(const char *identifier, const char *defaultNamespace, const char *name, int apiVersion, int readonly, VSPlugin *plugin);
|
||||
typedef void (VS_CC *VSInitPlugin)(VSConfigPlugin configFunc, VSRegisterFunction registerFunc, VSPlugin *plugin);
|
||||
typedef void (VS_CC *VSFreeFuncData)(void *userData);
|
||||
typedef void (VS_CC *VSFilterInit)(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi);
|
||||
typedef const VSFrameRef *(VS_CC *VSFilterGetFrame)(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi);
|
||||
typedef void (VS_CC *VSFilterFree)(void *instanceData, VSCore *core, const VSAPI *vsapi);
|
||||
|
||||
/* other */
|
||||
typedef void (VS_CC *VSFrameDoneCallback)(void *userData, const VSFrameRef *f, int n, VSNodeRef *, const char *errorMsg);
|
||||
typedef void (VS_CC *VSMessageHandler)(int msgType, const char *msg, void *userData);
|
||||
|
||||
struct VSAPI {
|
||||
VSCore *(VS_CC *createCore)(int threads) VS_NOEXCEPT;
|
||||
void (VS_CC *freeCore)(VSCore *core) VS_NOEXCEPT;
|
||||
const VSCoreInfo *(VS_CC *getCoreInfo)(VSCore *core) VS_NOEXCEPT;
|
||||
|
||||
const VSFrameRef *(VS_CC *cloneFrameRef)(const VSFrameRef *f) VS_NOEXCEPT;
|
||||
VSNodeRef *(VS_CC *cloneNodeRef)(VSNodeRef *node) VS_NOEXCEPT;
|
||||
VSFuncRef *(VS_CC *cloneFuncRef)(VSFuncRef *f) VS_NOEXCEPT;
|
||||
|
||||
void (VS_CC *freeFrame)(const VSFrameRef *f) VS_NOEXCEPT;
|
||||
void (VS_CC *freeNode)(VSNodeRef *node) VS_NOEXCEPT;
|
||||
void (VS_CC *freeFunc)(VSFuncRef *f) VS_NOEXCEPT;
|
||||
|
||||
VSFrameRef *(VS_CC *newVideoFrame)(const VSFormat *format, int width, int height, const VSFrameRef *propSrc, VSCore *core) VS_NOEXCEPT;
|
||||
VSFrameRef *(VS_CC *copyFrame)(const VSFrameRef *f, VSCore *core) VS_NOEXCEPT;
|
||||
void (VS_CC *copyFrameProps)(const VSFrameRef *src, VSFrameRef *dst, VSCore *core) VS_NOEXCEPT;
|
||||
|
||||
void (VS_CC *registerFunction)(const char *name, const char *args, VSPublicFunction argsFunc, void *functionData, VSPlugin *plugin) VS_NOEXCEPT;
|
||||
VSPlugin *(VS_CC *getPluginById)(const char *identifier, VSCore *core) VS_NOEXCEPT;
|
||||
VSPlugin *(VS_CC *getPluginByNs)(const char *ns, VSCore *core) VS_NOEXCEPT;
|
||||
VSMap *(VS_CC *getPlugins)(VSCore *core) VS_NOEXCEPT;
|
||||
VSMap *(VS_CC *getFunctions)(VSPlugin *plugin) VS_NOEXCEPT;
|
||||
void (VS_CC *createFilter)(const VSMap *in, VSMap *out, const char *name, VSFilterInit init, VSFilterGetFrame getFrame, VSFilterFree free, int filterMode, int flags, void *instanceData, VSCore *core) VS_NOEXCEPT;
|
||||
void (VS_CC *setError)(VSMap *map, const char *errorMessage) VS_NOEXCEPT; /* use to signal errors outside filter getframe functions */
|
||||
const char *(VS_CC *getError)(const VSMap *map) VS_NOEXCEPT; /* use to query errors, returns 0 if no error */
|
||||
void (VS_CC *setFilterError)(const char *errorMessage, VSFrameContext *frameCtx) VS_NOEXCEPT; /* use to signal errors in the filter getframe function */
|
||||
VSMap *(VS_CC *invoke)(VSPlugin *plugin, const char *name, const VSMap *args) VS_NOEXCEPT;
|
||||
|
||||
const VSFormat *(VS_CC *getFormatPreset)(int id, VSCore *core) VS_NOEXCEPT;
|
||||
const VSFormat *(VS_CC *registerFormat)(int colorFamily, int sampleType, int bitsPerSample, int subSamplingW, int subSamplingH, VSCore *core) VS_NOEXCEPT;
|
||||
|
||||
const VSFrameRef *(VS_CC *getFrame)(int n, VSNodeRef *node, char *errorMsg, int bufSize) VS_NOEXCEPT; /* do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor */
|
||||
void (VS_CC *getFrameAsync)(int n, VSNodeRef *node, VSFrameDoneCallback callback, void *userData) VS_NOEXCEPT; /* do never use inside a filter's getframe function, for external applications using the core as a library or for requesting frames in a filter constructor */
|
||||
const VSFrameRef *(VS_CC *getFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */
|
||||
void (VS_CC *requestFrameFilter)(int n, VSNodeRef *node, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */
|
||||
void (VS_CC *queryCompletedFrame)(VSNodeRef **node, int *n, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */
|
||||
void (VS_CC *releaseFrameEarly)(VSNodeRef *node, int n, VSFrameContext *frameCtx) VS_NOEXCEPT; /* only use inside a filter's getframe function */
|
||||
|
||||
int (VS_CC *getStride)(const VSFrameRef *f, int plane) VS_NOEXCEPT;
|
||||
const uint8_t *(VS_CC *getReadPtr)(const VSFrameRef *f, int plane) VS_NOEXCEPT;
|
||||
uint8_t *(VS_CC *getWritePtr)(VSFrameRef *f, int plane) VS_NOEXCEPT;
|
||||
|
||||
VSFuncRef *(VS_CC *createFunc)(VSPublicFunction func, void *userData, VSFreeFuncData free, VSCore *core, const VSAPI *vsapi) VS_NOEXCEPT;
|
||||
void (VS_CC *callFunc)(VSFuncRef *func, const VSMap *in, VSMap *out, VSCore *core, const VSAPI *vsapi) VS_NOEXCEPT; /* core and vsapi arguments are completely ignored, they only remain to preserve ABI */
|
||||
|
||||
/* property access functions */
|
||||
VSMap *(VS_CC *createMap)(void) VS_NOEXCEPT;
|
||||
void (VS_CC *freeMap)(VSMap *map) VS_NOEXCEPT;
|
||||
void (VS_CC *clearMap)(VSMap *map) VS_NOEXCEPT;
|
||||
|
||||
const VSVideoInfo *(VS_CC *getVideoInfo)(VSNodeRef *node) VS_NOEXCEPT;
|
||||
void (VS_CC *setVideoInfo)(const VSVideoInfo *vi, int numOutputs, VSNode *node) VS_NOEXCEPT;
|
||||
const VSFormat *(VS_CC *getFrameFormat)(const VSFrameRef *f) VS_NOEXCEPT;
|
||||
int (VS_CC *getFrameWidth)(const VSFrameRef *f, int plane) VS_NOEXCEPT;
|
||||
int (VS_CC *getFrameHeight)(const VSFrameRef *f, int plane) VS_NOEXCEPT;
|
||||
const VSMap *(VS_CC *getFramePropsRO)(const VSFrameRef *f) VS_NOEXCEPT;
|
||||
VSMap *(VS_CC *getFramePropsRW)(VSFrameRef *f) VS_NOEXCEPT;
|
||||
|
||||
int (VS_CC *propNumKeys)(const VSMap *map) VS_NOEXCEPT;
|
||||
const char *(VS_CC *propGetKey)(const VSMap *map, int index) VS_NOEXCEPT;
|
||||
int (VS_CC *propNumElements)(const VSMap *map, const char *key) VS_NOEXCEPT;
|
||||
char (VS_CC *propGetType)(const VSMap *map, const char *key) VS_NOEXCEPT;
|
||||
|
||||
int64_t(VS_CC *propGetInt)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
||||
double(VS_CC *propGetFloat)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
||||
const char *(VS_CC *propGetData)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
||||
int (VS_CC *propGetDataSize)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
||||
VSNodeRef *(VS_CC *propGetNode)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
||||
const VSFrameRef *(VS_CC *propGetFrame)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
||||
VSFuncRef *(VS_CC *propGetFunc)(const VSMap *map, const char *key, int index, int *error) VS_NOEXCEPT;
|
||||
|
||||
int (VS_CC *propDeleteKey)(VSMap *map, const char *key) VS_NOEXCEPT;
|
||||
int (VS_CC *propSetInt)(VSMap *map, const char *key, int64_t i, int append) VS_NOEXCEPT;
|
||||
int (VS_CC *propSetFloat)(VSMap *map, const char *key, double d, int append) VS_NOEXCEPT;
|
||||
int (VS_CC *propSetData)(VSMap *map, const char *key, const char *data, int size, int append) VS_NOEXCEPT;
|
||||
int (VS_CC *propSetNode)(VSMap *map, const char *key, VSNodeRef *node, int append) VS_NOEXCEPT;
|
||||
int (VS_CC *propSetFrame)(VSMap *map, const char *key, const VSFrameRef *f, int append) VS_NOEXCEPT;
|
||||
int (VS_CC *propSetFunc)(VSMap *map, const char *key, VSFuncRef *func, int append) VS_NOEXCEPT;
|
||||
|
||||
int64_t (VS_CC *setMaxCacheSize)(int64_t bytes, VSCore *core) VS_NOEXCEPT;
|
||||
int (VS_CC *getOutputIndex)(VSFrameContext *frameCtx) VS_NOEXCEPT;
|
||||
VSFrameRef *(VS_CC *newVideoFrame2)(const VSFormat *format, int width, int height, const VSFrameRef **planeSrc, const int *planes, const VSFrameRef *propSrc, VSCore *core) VS_NOEXCEPT;
|
||||
void (VS_CC *setMessageHandler)(VSMessageHandler handler, void *userData) VS_NOEXCEPT;
|
||||
int (VS_CC *setThreadCount)(int threads, VSCore *core) VS_NOEXCEPT;
|
||||
|
||||
const char *(VS_CC *getPluginPath)(const VSPlugin *plugin) VS_NOEXCEPT;
|
||||
|
||||
/* api 3.1 */
|
||||
const int64_t *(VS_CC *propGetIntArray)(const VSMap *map, const char *key, int *error) VS_NOEXCEPT;
|
||||
const double *(VS_CC *propGetFloatArray)(const VSMap *map, const char *key, int *error) VS_NOEXCEPT;
|
||||
|
||||
int (VS_CC *propSetIntArray)(VSMap *map, const char *key, const int64_t *i, int size) VS_NOEXCEPT;
|
||||
int (VS_CC *propSetFloatArray)(VSMap *map, const char *key, const double *d, int size) VS_NOEXCEPT;
|
||||
|
||||
/* api 3.4 */
|
||||
void (VS_CC *logMessage)(int msgType, const char *msg) VS_NOEXCEPT;
|
||||
};
|
||||
|
||||
VS_API(const VSAPI *) getVapourSynthAPI(int version) VS_NOEXCEPT;
|
||||
|
||||
#endif /* VAPOURSYNTH_H */
|
373
ffms2/src/vapoursynth/vapoursource.cpp
Normal file
373
ffms2/src/vapoursynth/vapoursource.cpp
Normal file
|
@ -0,0 +1,373 @@
|
|||
// Copyright (c) 2012-2018 Fredrik Mellbin
|
||||
//
|
||||
// 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 "vapoursource.h"
|
||||
#include "../core/utils.h"
|
||||
#include "VSHelper.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
static int GetNumPixFmts() {
|
||||
int n = 0;
|
||||
while (av_get_pix_fmt_name((AVPixelFormat)n))
|
||||
n++;
|
||||
return n;
|
||||
}
|
||||
|
||||
static bool IsRealNativeEndianPlanar(const AVPixFmtDescriptor &desc) {
|
||||
// reject all special flags
|
||||
if (desc.flags & (AV_PIX_FMT_FLAG_PAL | AV_PIX_FMT_FLAG_BAYER | AV_PIX_FMT_FLAG_HWACCEL | AV_PIX_FMT_FLAG_BITSTREAM))
|
||||
return false;
|
||||
int used_planes = 0;
|
||||
for (int i = 0; i < desc.nb_components; i++)
|
||||
used_planes = std::max(used_planes, (int)desc.comp[i].plane + 1);
|
||||
bool temp = (used_planes == desc.nb_components) && (desc.comp[0].depth >= 8);
|
||||
if (!temp)
|
||||
return false;
|
||||
else if (desc.comp[0].depth == 8)
|
||||
return temp;
|
||||
else
|
||||
return (AV_PIX_FMT_YUV420P10 == AV_PIX_FMT_YUV420P10BE ? !!(desc.flags & AV_PIX_FMT_FLAG_BE) : !(desc.flags & AV_PIX_FMT_FLAG_BE));
|
||||
}
|
||||
|
||||
static int GetSampleType(const AVPixFmtDescriptor &desc) {
|
||||
return (desc.flags & AV_PIX_FMT_FLAG_FLOAT) ? stFloat : stInteger;
|
||||
}
|
||||
|
||||
static bool HasAlpha(const AVPixFmtDescriptor &desc) {
|
||||
return !!(desc.flags & AV_PIX_FMT_FLAG_ALPHA);
|
||||
}
|
||||
|
||||
static int GetColorFamily(const AVPixFmtDescriptor &desc) {
|
||||
if (desc.nb_components <= 2)
|
||||
return cmGray;
|
||||
else if (desc.flags & AV_PIX_FMT_FLAG_RGB)
|
||||
return cmRGB;
|
||||
else
|
||||
return cmYUV;
|
||||
}
|
||||
|
||||
static int FormatConversionToPixelFormat(int id, bool alpha, VSCore *core, const VSAPI *vsapi) {
|
||||
const VSFormat *f = vsapi->getFormatPreset(id, core);
|
||||
int npixfmt = GetNumPixFmts();
|
||||
// Look for a suitable format without alpha first to not waste memory
|
||||
if (!alpha) {
|
||||
for (int i = 0; i < npixfmt; i++) {
|
||||
const AVPixFmtDescriptor &desc = *av_pix_fmt_desc_get((AVPixelFormat)i);
|
||||
if (IsRealNativeEndianPlanar(desc) && !HasAlpha(desc)
|
||||
&& GetColorFamily(desc) == f->colorFamily
|
||||
&& desc.comp[0].depth == f->bitsPerSample
|
||||
&& desc.log2_chroma_w == f->subSamplingW
|
||||
&& desc.log2_chroma_h == f->subSamplingH
|
||||
&& GetSampleType(desc) == f->sampleType)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// Try all remaining formats
|
||||
for (int i = 0; i < npixfmt; i++) {
|
||||
const AVPixFmtDescriptor &desc = *av_pix_fmt_desc_get((AVPixelFormat)i);
|
||||
if (IsRealNativeEndianPlanar(desc) && HasAlpha(desc)
|
||||
&& GetColorFamily(desc) == f->colorFamily
|
||||
&& desc.comp[0].depth == f->bitsPerSample
|
||||
&& desc.log2_chroma_w == f->subSamplingW
|
||||
&& desc.log2_chroma_h == f->subSamplingH
|
||||
&& GetSampleType(desc) == f->sampleType)
|
||||
return i;
|
||||
}
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
static const VSFormat *FormatConversionToVS(int id, VSCore *core, const VSAPI *vsapi) {
|
||||
const AVPixFmtDescriptor &desc = *av_pix_fmt_desc_get((AVPixelFormat)id);
|
||||
return vsapi->registerFormat(
|
||||
GetColorFamily(desc),
|
||||
GetSampleType(desc),
|
||||
desc.comp[0].depth,
|
||||
desc.log2_chroma_w,
|
||||
desc.log2_chroma_h, core);
|
||||
}
|
||||
|
||||
void VS_CC VSVideoSource::Init(VSMap *, VSMap *, void **instanceData, VSNode *node, VSCore *, const VSAPI *vsapi) {
|
||||
VSVideoSource *Source = static_cast<VSVideoSource *>(*instanceData);
|
||||
vsapi->setVideoInfo(Source->VI, Source->OutputAlpha ? 2 : 1, node);
|
||||
}
|
||||
|
||||
const VSFrameRef *VS_CC VSVideoSource::GetFrame(int n, int activationReason, void **instanceData, void **, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) {
|
||||
VSVideoSource *vs = static_cast<VSVideoSource *>(*instanceData);
|
||||
if (activationReason == arInitial) {
|
||||
|
||||
char ErrorMsg[1024];
|
||||
FFMS_ErrorInfo E;
|
||||
E.Buffer = ErrorMsg;
|
||||
E.BufferSize = sizeof(ErrorMsg);
|
||||
std::string buf = "Source: ";
|
||||
|
||||
int OutputIndex = vs->OutputAlpha ? vsapi->getOutputIndex(frameCtx) : 0;
|
||||
|
||||
VSFrameRef *Dst = vsapi->newVideoFrame(vs->VI[OutputIndex].format, vs->VI[OutputIndex].width, vs->VI[OutputIndex].height, nullptr, core);
|
||||
VSMap *Props = vsapi->getFramePropsRW(Dst);
|
||||
|
||||
const FFMS_Frame *Frame = nullptr;
|
||||
|
||||
if (vs->FPSNum > 0 && vs->FPSDen > 0) {
|
||||
double currentTime = FFMS_GetVideoProperties(vs->V)->FirstTime +
|
||||
(double)(n * (int64_t)vs->FPSDen) / vs->FPSNum;
|
||||
Frame = FFMS_GetFrameByTime(vs->V, currentTime, &E);
|
||||
vsapi->propSetInt(Props, "_DurationNum", vs->FPSDen, paReplace);
|
||||
vsapi->propSetInt(Props, "_DurationDen", vs->FPSNum, paReplace);
|
||||
vsapi->propSetFloat(Props, "_AbsoluteTime", currentTime, paReplace);
|
||||
} else {
|
||||
Frame = FFMS_GetFrame(vs->V, n, &E);
|
||||
FFMS_Track *T = FFMS_GetTrackFromVideo(vs->V);
|
||||
const FFMS_TrackTimeBase *TB = FFMS_GetTimeBase(T);
|
||||
int64_t num;
|
||||
if (n + 1 < vs->VI[0].numFrames)
|
||||
num = FFMS_GetFrameInfo(T, n + 1)->PTS - FFMS_GetFrameInfo(T, n)->PTS;
|
||||
else if (n > 0) // simply use the second to last frame's duration for the last one, should be good enough
|
||||
num = FFMS_GetFrameInfo(T, n)->PTS - FFMS_GetFrameInfo(T, n - 1)->PTS;
|
||||
else // just make it one timebase if it's a single frame clip
|
||||
num = 1;
|
||||
int64_t DurNum = TB->Num * num;
|
||||
int64_t DurDen = TB->Den * 1000;
|
||||
muldivRational(&DurNum, &DurDen, 1, 1);
|
||||
vsapi->propSetInt(Props, "_DurationNum", DurNum, paReplace);
|
||||
vsapi->propSetInt(Props, "_DurationDen", DurDen, paReplace);
|
||||
vsapi->propSetFloat(Props, "_AbsoluteTime", ((static_cast<double>(TB->Num) / 1000) * FFMS_GetFrameInfo(T, n)->PTS) / TB->Den, paReplace);
|
||||
}
|
||||
|
||||
if (Frame == nullptr) {
|
||||
buf += E.Buffer;
|
||||
vsapi->setFilterError(buf.c_str(), frameCtx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Set AR variables
|
||||
if (vs->SARNum > 0 && vs->SARDen > 0) {
|
||||
vsapi->propSetInt(Props, "_SARNum", vs->SARNum, paReplace);
|
||||
vsapi->propSetInt(Props, "_SARDen", vs->SARDen, paReplace);
|
||||
}
|
||||
|
||||
vsapi->propSetInt(Props, "_Matrix", Frame->ColorSpace, paReplace);
|
||||
vsapi->propSetInt(Props, "_Primaries", Frame->ColorPrimaries, paReplace);
|
||||
vsapi->propSetInt(Props, "_Transfer", Frame->TransferCharateristics, paReplace);
|
||||
if (Frame->ChromaLocation > 0)
|
||||
vsapi->propSetInt(Props, "_ChromaLocation", Frame->ChromaLocation - 1, paReplace);
|
||||
|
||||
if (Frame->ColorRange == FFMS_CR_MPEG)
|
||||
vsapi->propSetInt(Props, "_ColorRange", 1, paReplace);
|
||||
else if (Frame->ColorRange == FFMS_CR_JPEG)
|
||||
vsapi->propSetInt(Props, "_ColorRange", 0, paReplace);
|
||||
vsapi->propSetData(Props, "_PictType", &Frame->PictType, 1, paReplace);
|
||||
|
||||
// Set field information
|
||||
int FieldBased = 0;
|
||||
if (Frame->InterlacedFrame)
|
||||
FieldBased = (Frame->TopFieldFirst ? 2 : 1);
|
||||
vsapi->propSetInt(Props, "_FieldBased", FieldBased, paReplace);
|
||||
|
||||
if (Frame->HasMasteringDisplayPrimaries) {
|
||||
vsapi->propSetFloatArray(Props, "MasteringDisplayPrimariesX", Frame->MasteringDisplayPrimariesX, 3);
|
||||
vsapi->propSetFloatArray(Props, "MasteringDisplayPrimariesY", Frame->MasteringDisplayPrimariesY, 3);
|
||||
vsapi->propSetFloat(Props, "MasteringDisplayWhitePointX", Frame->MasteringDisplayWhitePointX, paReplace);
|
||||
vsapi->propSetFloat(Props, "MasteringDisplayWhitePointY", Frame->MasteringDisplayWhitePointY, paReplace);
|
||||
}
|
||||
|
||||
if (Frame->HasMasteringDisplayLuminance) {
|
||||
vsapi->propSetFloat(Props, "MasteringDisplayMinLuminance", Frame->MasteringDisplayMinLuminance, paReplace);
|
||||
vsapi->propSetFloat(Props, "MasteringDisplayMaxLuminance", Frame->MasteringDisplayMaxLuminance, paReplace);
|
||||
}
|
||||
|
||||
if (Frame->HasContentLightLevel) {
|
||||
vsapi->propSetFloat(Props, "ContentLightLevelMax", Frame->ContentLightLevelMax, paReplace);
|
||||
vsapi->propSetFloat(Props, "ContentLightLevelAverage", Frame->ContentLightLevelAverage, paReplace);
|
||||
}
|
||||
|
||||
if (OutputIndex == 0)
|
||||
OutputFrame(Frame, Dst, vsapi);
|
||||
else
|
||||
OutputAlphaFrame(Frame, vs->VI[0].format->numPlanes, Dst, vsapi);
|
||||
|
||||
return Dst;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void VS_CC VSVideoSource::Free(void *instanceData, VSCore *, const VSAPI *) {
|
||||
FFMS_Deinit();
|
||||
delete static_cast<VSVideoSource *>(instanceData);
|
||||
}
|
||||
|
||||
VSVideoSource::VSVideoSource(const char *SourceFile, int Track, FFMS_Index *Index,
|
||||
int AFPSNum, int AFPSDen, int Threads, int SeekMode, int /*RFFMode*/,
|
||||
int ResizeToWidth, int ResizeToHeight, const char *ResizerName,
|
||||
int Format, bool OutputAlpha, const VSAPI *vsapi, VSCore *core)
|
||||
: FPSNum(AFPSNum), FPSDen(AFPSDen), OutputAlpha(OutputAlpha) {
|
||||
|
||||
VI[0] = {};
|
||||
VI[1] = {};
|
||||
|
||||
char ErrorMsg[1024];
|
||||
FFMS_ErrorInfo E;
|
||||
E.Buffer = ErrorMsg;
|
||||
E.BufferSize = sizeof(ErrorMsg);
|
||||
|
||||
V = FFMS_CreateVideoSource(SourceFile, Track, Index, Threads, SeekMode, &E);
|
||||
if (!V) {
|
||||
throw std::runtime_error(std::string("Source: ") + E.Buffer);
|
||||
}
|
||||
try {
|
||||
InitOutputFormat(ResizeToWidth, ResizeToHeight, ResizerName, Format, vsapi, core);
|
||||
} catch (std::exception &) {
|
||||
FFMS_DestroyVideoSource(V);
|
||||
throw;
|
||||
}
|
||||
|
||||
const FFMS_VideoProperties *VP = FFMS_GetVideoProperties(V);
|
||||
|
||||
if (FPSNum > 0 && FPSDen > 0) {
|
||||
muldivRational(&FPSNum, &FPSDen, 1, 1);
|
||||
VI[0].fpsDen = FPSDen;
|
||||
VI[0].fpsNum = FPSNum;
|
||||
if (VP->NumFrames > 1) {
|
||||
VI[0].numFrames = static_cast<int>((VP->LastTime - VP->FirstTime) * (1 + 1. / (VP->NumFrames - 1)) * FPSNum / FPSDen + 0.5);
|
||||
if (VI[0].numFrames < 1)
|
||||
VI[0].numFrames = 1;
|
||||
} else {
|
||||
VI[0].numFrames = 1;
|
||||
}
|
||||
} else {
|
||||
VI[0].fpsDen = VP->FPSDenominator;
|
||||
VI[0].fpsNum = VP->FPSNumerator;
|
||||
VI[0].numFrames = VP->NumFrames;
|
||||
muldivRational(&VI[0].fpsNum, &VI[0].fpsDen, 1, 1);
|
||||
}
|
||||
|
||||
if (OutputAlpha) {
|
||||
VI[1] = VI[0];
|
||||
VI[1].format = vsapi->registerFormat(cmGray, VI[0].format->sampleType, VI[0].format->bitsPerSample, VI[0].format->subSamplingW, VI[0].format->subSamplingH, core);
|
||||
}
|
||||
|
||||
SARNum = VP->SARNum;
|
||||
SARDen = VP->SARDen;
|
||||
}
|
||||
|
||||
VSVideoSource::~VSVideoSource() {
|
||||
FFMS_DestroyVideoSource(V);
|
||||
}
|
||||
|
||||
void VSVideoSource::InitOutputFormat(int ResizeToWidth, int ResizeToHeight,
|
||||
const char *ResizerName, int ConvertToFormat, const VSAPI *vsapi, VSCore *core) {
|
||||
|
||||
char ErrorMsg[1024];
|
||||
FFMS_ErrorInfo E;
|
||||
E.Buffer = ErrorMsg;
|
||||
E.BufferSize = sizeof(ErrorMsg);
|
||||
|
||||
const FFMS_Frame *F = FFMS_GetFrame(V, 0, &E);
|
||||
if (!F) {
|
||||
std::string buf = "Source: ";
|
||||
buf += E.Buffer;
|
||||
throw std::runtime_error(buf);
|
||||
}
|
||||
|
||||
std::vector<int> TargetFormats;
|
||||
int npixfmt = GetNumPixFmts();
|
||||
for (int i = 0; i < npixfmt; i++)
|
||||
if (IsRealNativeEndianPlanar(*av_pix_fmt_desc_get((AVPixelFormat)i)))
|
||||
TargetFormats.push_back(i);
|
||||
TargetFormats.push_back(AV_PIX_FMT_NONE);
|
||||
|
||||
int TargetPixelFormat = AV_PIX_FMT_NONE;
|
||||
if (ConvertToFormat != pfNone) {
|
||||
TargetPixelFormat = FormatConversionToPixelFormat(ConvertToFormat, OutputAlpha, core, vsapi);
|
||||
if (TargetPixelFormat == AV_PIX_FMT_NONE)
|
||||
throw std::runtime_error(std::string("Source: Invalid output colorspace specified"));
|
||||
|
||||
TargetFormats.clear();
|
||||
TargetFormats.push_back(TargetPixelFormat);
|
||||
TargetFormats.push_back(-1);
|
||||
}
|
||||
|
||||
if (ResizeToWidth <= 0)
|
||||
ResizeToWidth = F->EncodedWidth;
|
||||
|
||||
if (ResizeToHeight <= 0)
|
||||
ResizeToHeight = F->EncodedHeight;
|
||||
|
||||
int Resizer = ResizerNameToSWSResizer(ResizerName);
|
||||
if (Resizer == 0)
|
||||
throw std::runtime_error(std::string("Source: Invalid resizer name specified"));
|
||||
|
||||
if (FFMS_SetOutputFormatV2(V, &TargetFormats[0],
|
||||
ResizeToWidth, ResizeToHeight, Resizer, &E))
|
||||
throw std::runtime_error(std::string("Source: No suitable output format found"));
|
||||
|
||||
F = FFMS_GetFrame(V, 0, &E);
|
||||
TargetFormats.clear();
|
||||
TargetFormats.push_back(F->ConvertedPixelFormat);
|
||||
TargetFormats.push_back(-1);
|
||||
|
||||
// This trick is required to first get the "best" default format and then set only that format as the output
|
||||
if (FFMS_SetOutputFormatV2(V, TargetFormats.data(), ResizeToWidth, ResizeToHeight, Resizer, &E))
|
||||
throw std::runtime_error(std::string("Source: No suitable output format found"));
|
||||
|
||||
F = FFMS_GetFrame(V, 0, &E);
|
||||
|
||||
// Don't output alpha if the clip doesn't have it
|
||||
if (!HasAlpha(*av_pix_fmt_desc_get((AVPixelFormat)F->ConvertedPixelFormat)))
|
||||
OutputAlpha = false;
|
||||
|
||||
VI[0].format = FormatConversionToVS(F->ConvertedPixelFormat, core, vsapi);
|
||||
if (!VI[0].format)
|
||||
throw std::runtime_error(std::string("Source: No suitable output format found"));
|
||||
|
||||
VI[0].width = F->ScaledWidth;
|
||||
VI[0].height = F->ScaledHeight;
|
||||
|
||||
// Crop to obey subsampling width/height requirements
|
||||
VI[0].width -= VI[0].width % (1 << VI[0].format->subSamplingW);
|
||||
VI[0].height -= VI[0].height % (1 << VI[0].format->subSamplingH);
|
||||
}
|
||||
|
||||
void VSVideoSource::OutputFrame(const FFMS_Frame *Frame, VSFrameRef *Dst, const VSAPI *vsapi) {
|
||||
const int RGBPlaneOrder[3] = { 2, 0, 1 };
|
||||
const VSFormat *fi = vsapi->getFrameFormat(Dst);
|
||||
if (fi->colorFamily == cmRGB) {
|
||||
for (int i = 0; i < fi->numPlanes; i++)
|
||||
vs_bitblt(vsapi->getWritePtr(Dst, i), vsapi->getStride(Dst, i), Frame->Data[RGBPlaneOrder[i]], Frame->Linesize[RGBPlaneOrder[i]],
|
||||
vsapi->getFrameWidth(Dst, i) * fi->bytesPerSample, vsapi->getFrameHeight(Dst, i));
|
||||
} else {
|
||||
for (int i = 0; i < fi->numPlanes; i++)
|
||||
vs_bitblt(vsapi->getWritePtr(Dst, i), vsapi->getStride(Dst, i), Frame->Data[i], Frame->Linesize[i],
|
||||
vsapi->getFrameWidth(Dst, i) * fi->bytesPerSample, vsapi->getFrameHeight(Dst, i));
|
||||
}
|
||||
}
|
||||
|
||||
void VSVideoSource::OutputAlphaFrame(const FFMS_Frame *Frame, int Plane, VSFrameRef *Dst, const VSAPI *vsapi) {
|
||||
const VSFormat *fi = vsapi->getFrameFormat(Dst);
|
||||
vs_bitblt(vsapi->getWritePtr(Dst, 0), vsapi->getStride(Dst, 0), Frame->Data[Plane], Frame->Linesize[Plane],
|
||||
vsapi->getFrameWidth(Dst, 0) * fi->bytesPerSample, vsapi->getFrameHeight(Dst, 0));
|
||||
}
|
63
ffms2/src/vapoursynth/vapoursource.h
Normal file
63
ffms2/src/vapoursynth/vapoursource.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
// Copyright (c) 2012-2017 Fredrik Mellbin
|
||||
//
|
||||
// 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 FFVAPOURSOURCES_H
|
||||
#define FFVAPOURSOURCES_H
|
||||
|
||||
extern "C" {
|
||||
#include <libavutil/avutil.h>
|
||||
#include <libavutil/common.h>
|
||||
#include <libavutil/pixdesc.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
|
||||
#include "VapourSynth.h"
|
||||
#include "ffms.h"
|
||||
#include "ffmscompat.h"
|
||||
|
||||
struct VSVideoSource {
|
||||
private:
|
||||
VSVideoInfo VI[2];
|
||||
FFMS_VideoSource *V;
|
||||
int64_t FPSNum;
|
||||
int64_t FPSDen;
|
||||
int SARNum;
|
||||
int SARDen;
|
||||
bool OutputAlpha;
|
||||
|
||||
void InitOutputFormat(int ResizeToWidth, int ResizeToHeight,
|
||||
const char *ResizerName, int ConvertToFormat, const VSAPI *vsapi, VSCore *core);
|
||||
static void OutputFrame(const FFMS_Frame *Frame, VSFrameRef *Dst, const VSAPI *vsapi);
|
||||
static void OutputAlphaFrame(const FFMS_Frame *Frame, int Plane, VSFrameRef *Dst, const VSAPI *vsapi);
|
||||
public:
|
||||
VSVideoSource(const char *SourceFile, int Track, FFMS_Index *Index,
|
||||
int AFPSNum, int AFPSDen, int Threads, int SeekMode, int RFFMode,
|
||||
int ResizeToWidth, int ResizeToHeight, const char *ResizerName,
|
||||
int Format, bool OutputAlpha, const VSAPI *vsapi, VSCore *core);
|
||||
~VSVideoSource();
|
||||
|
||||
static void VS_CC Init(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi);
|
||||
static const VSFrameRef *VS_CC GetFrame(int n, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi);
|
||||
static void VS_CC Free(void *instanceData, VSCore *core, const VSAPI *vsapi);
|
||||
};
|
||||
|
||||
#endif
|
239
ffms2/src/vapoursynth/vapoursynth.cpp
Normal file
239
ffms2/src/vapoursynth/vapoursynth.cpp
Normal file
|
@ -0,0 +1,239 @@
|
|||
// Copyright (c) 2012-2017 Fredrik Mellbin
|
||||
//
|
||||
// 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 "ffms.h"
|
||||
#include "vapoursource.h"
|
||||
#include "VSHelper.h"
|
||||
#include "../core/utils.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
static void VS_CC CreateIndex(const VSMap *in, VSMap *out, void *, VSCore *, const VSAPI *vsapi) {
|
||||
FFMS_Init(0, 0);
|
||||
|
||||
char ErrorMsg[1024];
|
||||
FFMS_ErrorInfo E;
|
||||
E.Buffer = ErrorMsg;
|
||||
E.BufferSize = sizeof(ErrorMsg);
|
||||
int err;
|
||||
|
||||
std::set<int> IndexTracks;
|
||||
|
||||
const char *Source = vsapi->propGetData(in, "source", 0, nullptr);
|
||||
const char *CacheFile = vsapi->propGetData(in, "cachefile", 0, &err);
|
||||
|
||||
int NumIndexTracks = vsapi->propNumElements(in, "indextracks");
|
||||
bool IndexAllTracks = (NumIndexTracks == 1) && (int64ToIntS(vsapi->propGetInt(in, "indextracks", 0, nullptr)) == -1);
|
||||
if (!IndexAllTracks) {
|
||||
for (int i = 0; i < NumIndexTracks; i++) {
|
||||
int Track = int64ToIntS(vsapi->propGetInt(in, "indextracks", i, nullptr));
|
||||
IndexTracks.insert(Track);
|
||||
}
|
||||
}
|
||||
|
||||
int ErrorHandling = int64ToIntS(vsapi->propGetInt(in, "errorhandling", 0, &err));
|
||||
if (err)
|
||||
ErrorHandling = FFMS_IEH_IGNORE;
|
||||
bool OverWrite = !!vsapi->propGetInt(in, "overwrite", 0, &err);
|
||||
|
||||
std::string DefaultCache(Source);
|
||||
if (!CacheFile || !strcmp(CacheFile, "")) {
|
||||
DefaultCache.append(".ffindex");
|
||||
CacheFile = DefaultCache.c_str();
|
||||
}
|
||||
|
||||
FFMS_Index *Index = FFMS_ReadIndex(CacheFile, &E);
|
||||
if (OverWrite || !Index || (Index && FFMS_IndexBelongsToFile(Index, Source, nullptr) != FFMS_ERROR_SUCCESS)) {
|
||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(Source, &E);
|
||||
if (!Indexer) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
return vsapi->setError(out, (std::string("Index: ") + E.Buffer).c_str());
|
||||
}
|
||||
|
||||
if (IndexAllTracks) {
|
||||
FFMS_TrackTypeIndexSettings(Indexer, FFMS_TYPE_AUDIO, 1, 0);
|
||||
} else {
|
||||
for (int i : IndexTracks)
|
||||
FFMS_TrackIndexSettings(Indexer, i, 1, 0);
|
||||
}
|
||||
|
||||
Index = FFMS_DoIndexing2(Indexer, ErrorHandling, &E);
|
||||
if (!Index)
|
||||
return vsapi->setError(out, (std::string("Index: ") + E.Buffer).c_str());
|
||||
if (FFMS_WriteIndex(CacheFile, Index, &E)) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
return vsapi->setError(out, (std::string("Index: ") + E.Buffer).c_str());
|
||||
}
|
||||
FFMS_DestroyIndex(Index);
|
||||
if (!OverWrite)
|
||||
vsapi->propSetData(out, "result", "Index generated", -1, paReplace);
|
||||
else
|
||||
vsapi->propSetData(out, "result", "Index generated (forced overwrite)", -1, paReplace);
|
||||
} else {
|
||||
FFMS_DestroyIndex(Index);
|
||||
vsapi->propSetData(out, "result", "Valid index already exists", -1, paReplace);
|
||||
}
|
||||
FFMS_Deinit();
|
||||
}
|
||||
|
||||
static void VS_CC CreateSource(const VSMap *in, VSMap *out, void *, VSCore *core, const VSAPI *vsapi) {
|
||||
FFMS_Init(0, 0);
|
||||
|
||||
char ErrorMsg[1024];
|
||||
FFMS_ErrorInfo E;
|
||||
E.Buffer = ErrorMsg;
|
||||
E.BufferSize = sizeof(ErrorMsg);
|
||||
int err;
|
||||
|
||||
const char *Source = vsapi->propGetData(in, "source", 0, nullptr);
|
||||
int Track = int64ToIntS(vsapi->propGetInt(in, "track", 0, &err));
|
||||
if (err)
|
||||
Track = -1;
|
||||
bool Cache = !!vsapi->propGetInt(in, "cache", 0, &err);
|
||||
if (err)
|
||||
Cache = true;
|
||||
const char *CacheFile = vsapi->propGetData(in, "cachefile", 0, &err);
|
||||
int FPSNum = int64ToIntS(vsapi->propGetInt(in, "fpsnum", 0, &err));
|
||||
if (err)
|
||||
FPSNum = -1;
|
||||
int FPSDen = int64ToIntS(vsapi->propGetInt(in, "fpsden", 0, &err));
|
||||
if (err)
|
||||
FPSDen = 1;
|
||||
int Threads = int64ToIntS(vsapi->propGetInt(in, "threads", 0, &err));
|
||||
const char *Timecodes = vsapi->propGetData(in, "timecodes", 0, &err);
|
||||
int SeekMode = int64ToIntS(vsapi->propGetInt(in, "seekmode", 0, &err));
|
||||
if (err)
|
||||
SeekMode = FFMS_SEEK_NORMAL;
|
||||
int RFFMode = int64ToIntS(vsapi->propGetInt(in, "rffmode", 0, &err));
|
||||
int Width = int64ToIntS(vsapi->propGetInt(in, "width", 0, &err));
|
||||
int Height = int64ToIntS(vsapi->propGetInt(in, "height", 0, &err));
|
||||
const char *Resizer = vsapi->propGetData(in, "resizer", 0, &err);
|
||||
if (err)
|
||||
Resizer = "BICUBIC";
|
||||
int Format = int64ToIntS(vsapi->propGetInt(in, "format", 0, &err));
|
||||
|
||||
bool OutputAlpha = !!vsapi->propGetInt(in, "alpha", 0, &err);
|
||||
if (err)
|
||||
OutputAlpha = false;
|
||||
|
||||
if (FPSDen < 1)
|
||||
return vsapi->setError(out, "Source: FPS denominator needs to be 1 or higher");
|
||||
if (Track <= -2)
|
||||
return vsapi->setError(out, "Source: No video track selected");
|
||||
if (SeekMode < -1 || SeekMode > 3)
|
||||
return vsapi->setError(out, "Source: Invalid seekmode selected");
|
||||
if (RFFMode < 0 || RFFMode > 2)
|
||||
return vsapi->setError(out, "Source: Invalid RFF mode selected");
|
||||
if (RFFMode > 0 && FPSNum > 0)
|
||||
return vsapi->setError(out, "Source: RFF modes may not be combined with CFR conversion");
|
||||
if (Timecodes && IsSamePath(Source, Timecodes))
|
||||
return vsapi->setError(out, "Source: Timecodes will overwrite the source");
|
||||
|
||||
FFMS_Index *Index = nullptr;
|
||||
std::string DefaultCache;
|
||||
if (Cache) {
|
||||
if (CacheFile && *CacheFile) {
|
||||
if (IsSamePath(Source, CacheFile))
|
||||
return vsapi->setError(out, "Source: Cache will overwrite the source");
|
||||
Index = FFMS_ReadIndex(CacheFile, &E);
|
||||
} else {
|
||||
DefaultCache = Source;
|
||||
DefaultCache += ".ffindex";
|
||||
CacheFile = DefaultCache.c_str();
|
||||
Index = FFMS_ReadIndex(CacheFile, &E);
|
||||
// Reindex if the index doesn't match the file and its name wasn't
|
||||
// explicitly given
|
||||
if (Index && FFMS_IndexBelongsToFile(Index, Source, nullptr) != FFMS_ERROR_SUCCESS) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
Index = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!Index) {
|
||||
FFMS_Indexer *Indexer = FFMS_CreateIndexer(Source, &E);
|
||||
if (!Indexer)
|
||||
return vsapi->setError(out, (std::string("Index: ") + E.Buffer).c_str());
|
||||
|
||||
Index = FFMS_DoIndexing2(Indexer, FFMS_IEH_CLEAR_TRACK, &E);
|
||||
if (!Index)
|
||||
return vsapi->setError(out, (std::string("Index: ") + E.Buffer).c_str());
|
||||
|
||||
if (Cache)
|
||||
if (FFMS_WriteIndex(CacheFile, Index, &E)) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
return vsapi->setError(out, (std::string("Index: ") + E.Buffer).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (Track == -1)
|
||||
Track = FFMS_GetFirstIndexedTrackOfType(Index, FFMS_TYPE_VIDEO, &E);
|
||||
if (Track < 0) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
return vsapi->setError(out, "Source: No video track found");
|
||||
}
|
||||
|
||||
if (Timecodes && strcmp(Timecodes, "")) {
|
||||
if (FFMS_WriteTimecodes(FFMS_GetTrackFromIndex(Index, Track), Timecodes, &E)) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
return vsapi->setError(out, (std::string("Index: ") + E.Buffer).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
VSVideoSource *vs;
|
||||
try {
|
||||
vs = new VSVideoSource(Source, Track, Index, FPSNum, FPSDen, Threads, SeekMode, RFFMode, Width, Height, Resizer, Format, OutputAlpha, vsapi, core);
|
||||
} catch (std::exception const& e) {
|
||||
FFMS_DestroyIndex(Index);
|
||||
return vsapi->setError(out, e.what());
|
||||
}
|
||||
|
||||
vsapi->createFilter(in, out, "Source", VSVideoSource::Init, VSVideoSource::GetFrame, VSVideoSource::Free, fmUnordered, nfMakeLinear, vs, core);
|
||||
|
||||
FFMS_DestroyIndex(Index);
|
||||
}
|
||||
|
||||
static void VS_CC GetLogLevel(const VSMap *, VSMap *out, void *, VSCore *, const VSAPI *vsapi) {
|
||||
vsapi->propSetInt(out, "level", FFMS_GetLogLevel(), paReplace);
|
||||
}
|
||||
|
||||
static void VS_CC SetLogLevel(const VSMap *in, VSMap *out, void *, VSCore *, const VSAPI *vsapi) {
|
||||
FFMS_SetLogLevel((int)vsapi->propGetInt(in, "level", 0, nullptr));
|
||||
vsapi->propSetInt(out, "level", FFMS_GetLogLevel(), paReplace);
|
||||
}
|
||||
|
||||
static void VS_CC GetVersion(const VSMap *, VSMap *out, void *, VSCore *, const VSAPI *vsapi) {
|
||||
int Version = FFMS_GetVersion();
|
||||
char buf[100];
|
||||
sprintf(buf, "%d.%d.%d.%d", Version >> 24, (Version & 0xFF0000) >> 16, (Version & 0xFF00) >> 8, Version & 0xFF);
|
||||
vsapi->propSetData(out, "version", buf, -1, paReplace);
|
||||
}
|
||||
|
||||
VS_EXTERNAL_API(void) VapourSynthPluginInit(VSConfigPlugin configFunc, VSRegisterFunction registerFunc, VSPlugin *plugin) {
|
||||
configFunc("com.vapoursynth.ffms2", "ffms2", "FFmpegSource 2 for VapourSynth", VAPOURSYNTH_API_VERSION, 1, plugin);
|
||||
registerFunc("Index", "source:data;cachefile:data:opt;indextracks:int[]:opt;errorhandling:int:opt;overwrite:int:opt;", CreateIndex, nullptr, plugin);
|
||||
registerFunc("Source", "source:data;track:int:opt;cache:int:opt;cachefile:data:opt;fpsnum:int:opt;fpsden:int:opt;threads:int:opt;timecodes:data:opt;seekmode:int:opt;width:int:opt;height:int:opt;resizer:data:opt;format:int:opt;alpha:int:opt;", CreateSource, nullptr, plugin);
|
||||
registerFunc("GetLogLevel", "", GetLogLevel, nullptr, plugin);
|
||||
registerFunc("SetLogLevel", "level:int;", SetLogLevel, nullptr, plugin);
|
||||
registerFunc("Version", "", GetVersion, nullptr, plugin);
|
||||
}
|
115
ffms2/test/Makefile
Normal file
115
ffms2/test/Makefile
Normal file
|
@ -0,0 +1,115 @@
|
|||
# Where to find user code.
|
||||
USER_DIR = ..
|
||||
|
||||
# Points to the root of Google Test, relative to where this file is.
|
||||
# Remember to tweak this if you move this file.
|
||||
GTEST_DIR = $(USER_DIR)/test/googletest/googletest
|
||||
|
||||
# Where to find sample files
|
||||
SAMPLES_DIR =
|
||||
|
||||
# URL to sync samples from
|
||||
SAMPLES_URL =
|
||||
|
||||
# Flags passed to the preprocessor.
|
||||
# Set Google Test's header directory as a system directory, such that
|
||||
# the compiler doesn't generate warnings in Google Test headers.
|
||||
CPPFLAGS += -isystem $(GTEST_DIR)/include \
|
||||
-I$(USER_DIR)/include \
|
||||
-D_FILE_OFFSET_BITS=64 \
|
||||
-DFFMS_EXPORTS \
|
||||
-D__STDC_CONSTANT_MACROS \
|
||||
-DSAMPLES_DIR=$(SAMPLES_DIR)
|
||||
|
||||
# Flags passed to the C++ compiler.
|
||||
CXXFLAGS += -g -Wall -Wextra -pthread -std=c++11 -fvisibility=hidden
|
||||
|
||||
# All tests produced by this Makefile. Remember to add new tests you
|
||||
# created to the list.
|
||||
TESTS = indexer \
|
||||
hdr \
|
||||
display_matrix
|
||||
|
||||
RUNTESTS = $(subst $() $(),-run$() $(),$(TESTS))-run
|
||||
|
||||
# All the sample files we need to sync
|
||||
SAMPLES = test.mp4 \
|
||||
hdr10tags-both.mkv \
|
||||
hdr10tags-container.mkv \
|
||||
hdr10tags-stream.mp4 \
|
||||
qrvideo_hflip_90.mov \
|
||||
qrvideo_hflip_270.mov \
|
||||
qrvideo_vflip.mov
|
||||
|
||||
# All Google Test headers. Usually you shouldn't change this
|
||||
# definition.
|
||||
GTEST_HEADERS = $(GTEST_DIR)/include/gtest/*.h $(GTEST_DIR)/include/gtest/internal/*.h
|
||||
|
||||
# House-keeping build targets.
|
||||
|
||||
all: $(TESTS)
|
||||
|
||||
run: all $(RUNTESTS)
|
||||
|
||||
sync:
|
||||
@for i in $(SAMPLES); do \
|
||||
if [ ! -f "$(SAMPLES_DIR)/$$i" ]; then \
|
||||
wget -O $(SAMPLES_DIR)/$$i $(SAMPLES_URL)/$$i; \
|
||||
fi \
|
||||
done
|
||||
|
||||
clean:
|
||||
rm -f $(TESTS) gtest.a gtest_main.a *.o
|
||||
rm -rf .libs
|
||||
|
||||
# Builds gtest.a and gtest_main.a.
|
||||
|
||||
# Usually you shouldn't tweak such internal variables, indicated by a
|
||||
# trailing _.
|
||||
GTEST_SRCS_ = $(GTEST_DIR)/src/*.cc $(GTEST_DIR)/src/*.h $(GTEST_HEADERS)
|
||||
|
||||
# For simplicity and to avoid depending on Google Test's
|
||||
# implementation details, the dependencies specified below are
|
||||
# conservative and not optimized. This is fine as Google Test
|
||||
# compiles fast and for ordinary users its source rarely changes.
|
||||
gtest-all.o: $(GTEST_SRCS_)
|
||||
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest-all.cc
|
||||
|
||||
gtest_main.o: $(GTEST_SRCS_)
|
||||
$(CXX) $(CPPFLAGS) -I$(GTEST_DIR) $(CXXFLAGS) -c $(GTEST_DIR)/src/gtest_main.cc
|
||||
|
||||
gtest.a: gtest-all.o
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
gtest_main.a: gtest-all.o gtest_main.o
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
tests.o: $(USER_DIR)/test/tests.cpp $(USER_DIR)/include/ffms.h $(GTEST_HEADERS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/test/tests.cpp
|
||||
|
||||
hdr.o: $(USER_DIR)/test/hdr.cpp $(USER_DIR)/include/ffms.h $(GTEST_HEADERS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/test/hdr.cpp
|
||||
|
||||
display_matrix.o: $(USER_DIR)/test/display_matrix.cpp $(USER_DIR)/include/ffms.h $(GTEST_HEADERS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/test/display_matrix.cpp
|
||||
|
||||
indexer.o: $(USER_DIR)/test/indexer.cpp $(USER_DIR)/include/ffms.h $(GTEST_HEADERS)
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/test/indexer.cpp
|
||||
|
||||
indexer: indexer.o tests.o gtest_main.a ../src/core/libffms2.la
|
||||
../libtool --tag=CXX --mode=link $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o indexer indexer.o tests.o gtest_main.a -lavutil ../src/core/libffms2.la
|
||||
|
||||
indexer-run:
|
||||
@./indexer
|
||||
|
||||
hdr: hdr.o gtest_main.a ../src/core/libffms2.la
|
||||
../libtool --tag=CXX --mode=link $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o hdr hdr.o gtest_main.a -lavutil ../src/core/libffms2.la
|
||||
|
||||
hdr-run:
|
||||
@./hdr
|
||||
|
||||
display_matrix: display_matrix.o gtest_main.a ../src/core/libffms2.la
|
||||
../libtool --tag=CXX --mode=link $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o display_matrix display_matrix.o gtest_main.a -lavutil ../src/core/libffms2.la
|
||||
|
||||
display_matrix-run:
|
||||
@./display_matrix
|
|
@ -18,9 +18,7 @@ typedef struct HDR10Data {
|
|||
double MasteringDisplayMaxLuminance;
|
||||
} HDR10Data;
|
||||
|
||||
// Tests relative error with an error of 1e-5, given the accuracy of
|
||||
// the hardcoded test values, and how it would affect HDR.
|
||||
#define TEST_DOUBLE(A, B) (fabs((A / B) - 1) < (double) 1e-5)
|
||||
#define TEST_DOUBLE(A, B) ((A == B) || (fabs(A - B) < DBL_EPSILON))
|
||||
|
||||
const HDR10Data StreamHDR10Data = {
|
||||
{ 35400.0 / 50000.0, 8500.0 / 50000.0, 6550.0 / 50000.0 },
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue