Bring CSRI into the repository fully, I'm not an advocate of this! but it's the

best 'solution' for now.

Originally committed to SVN as r1915.
This commit is contained in:
Amar Takhar 2008-03-06 16:59:48 +00:00
parent 20f0f52cec
commit cdd49b02b4
43 changed files with 5074 additions and 0 deletions

22
csri/Doxyfile Normal file
View file

@ -0,0 +1,22 @@
PROJECT_NAME = CSRI
PROJECT_NUMBER = 0.1
OUTPUT_DIRECTORY = doc
JAVADOC_AUTOBRIEF = YES
OPTIMIZE_OUTPUT_FOR_C = YES
PREDEFINED = DOXYGEN
ENUM_VALUES_PER_LINE = 1
EXPAND_AS_DEFINED = _CSRI_H _CSRI_HELPER_H
INPUT = include/csri include/subhelp.h
FILE_PATTERNS = *.h
RECURSIVE = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO

31
csri/LICENSE Normal file
View file

@ -0,0 +1,31 @@
Copyright (c) 2007, David Lamparter
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE

12
csri/Makefile.am Normal file
View file

@ -0,0 +1,12 @@
AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = csri.pc.in acinclude.m4
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = csri.pc
SUBDIRS = ac \
include \
subhelp \
lib \
backends \
frontends

3
csri/ac/Makefile.am Normal file
View file

@ -0,0 +1,3 @@
EXTRA_DIST = \
csri.sln \
subhelp.vcproj

20
csri/ac/csri.sln Normal file
View file

@ -0,0 +1,20 @@
Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "subhelp", "subhelp.vcproj", "{870552FE-7B73-41AB-A7D9-475440F4731C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{870552FE-7B73-41AB-A7D9-475440F4731C}.Debug|Win32.ActiveCfg = Debug|Win32
{870552FE-7B73-41AB-A7D9-475440F4731C}.Debug|Win32.Build.0 = Debug|Win32
{870552FE-7B73-41AB-A7D9-475440F4731C}.Release|Win32.ActiveCfg = Release|Win32
{870552FE-7B73-41AB-A7D9-475440F4731C}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

179
csri/ac/subhelp.vcproj Normal file
View file

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="subhelp"
ProjectGUID="{870552FE-7B73-41AB-A7D9-475440F4731C}"
RootNamespace="subhelp"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\include"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="..\include"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Quelldateien"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath="..\subhelp\win32\openfile.c"
>
</File>
<File
RelativePath="..\subhelp\logging.c"
>
</File>
</Filter>
<Filter
Name="Headerdateien"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath="..\include\subhelp.h"
>
</File>
</Filter>
<Filter
Name="Ressourcendateien"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

67
csri/acinclude.m4 Normal file
View file

@ -0,0 +1,67 @@
dnl AC_CPP_PRAGMA_ONCE
dnl - check for #pragma once
AC_DEFUN([AC_CPP_PRAGMA_ONCE], [{
AC_MSG_CHECKING([[whether $CPP supports #pragma once]])
AC_PREPROC_IFELSE(
[AC_LANG_PROGRAM([[#pragma once]])],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_PRAGMA_ONCE], [1], [Preprocessor support for #pragma once])
],
[AC_MSG_RESULT([no])])
}])
dnl AC_C_FLAG([-flag])
dnl - check for CFLAG support in CC
AC_DEFUN([AC_C_FLAG], [{
AC_LANG_PUSH(C)
ac_c_flag_save="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_MSG_CHECKING([[whether $CC supports $1]])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[]])],
[
AC_MSG_RESULT([yes])
m4_if([$3], [], [], [
CFLAGS="$ac_c_flag_save"
$3
])
], [
CFLAGS="$ac_c_flag_save"
AC_MSG_RESULT([no])
$2
])
AC_LANG_POP(C)
}])
dnl AC_C_FLAG([-flag])
dnl - check for CFLAG support in CC
AC_DEFUN([AC_GCC_VISIBILITY], [{
AC_MSG_CHECKING([[whether $CC supports GCC visibility]])
# always use Werror since visibility is sensitive
# doesn't work on anything other than gcc either way, so Werror is fine...
vis_type="$1"
save_cflags="$CFLAGS"
CFLAGS="$CFLAGS -fvisibility=$vis_type -Werror"
AC_LINK_IFELSE(
[AC_LANG_SOURCE([[
int a() __attribute__((visibility("default")));
int b() __attribute__((visibility("hidden")));
int c() __attribute__((visibility("internal")));
int a() { return 1; }
int b() { return 2; }
int c() { return 3; }
int main() { return a()+b()+c(); }
]])],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_GCC_VISIBILITY], [1], [Compiler support for GCC visibility attributes])
save_cflags="$save_cflags -fvisibility=$vis_type"
],
[AC_MSG_RESULT([no])]
)
CFLAGS="$save_cflags"
}])

View file

@ -0,0 +1,4 @@
if BUILD_LIBASS
LIBASS_DIR = libass
endif
SUBDIRS = $(LIBASS_DIR)

View file

@ -0,0 +1,6 @@
csrilib_LTLIBRARIES = libass_csri.la
libass_csri_la_SOURCES = libass_csri.c
libass_csri_la_LDFLAGS = -avoid-version -no-undefined
libass_csri_la_LIBADD = ../../subhelp/libsubhelp_la-openfile.lo $(LIBASS_LIBS)
libass_csri_la_CFLAGS = -I$(top_srcdir)/include $(LIBASS_CFLAGS)

View file

@ -0,0 +1,258 @@
/*****************************************************************************
* csri: common subtitle renderer interface
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
/** libass csri wrapper.
* Indirectly based on code from aegisub,
* (c) 2006-2007, Rodrigo Braz Monteiro, Evgeniy Stepanov
*/
#ifdef HAVE_CONFIG_H
#include "acconf.h"
#endif
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <ass/ass.h>
#ifdef _WIN32
# define CSRIAPI __declspec(dllexport)
#else
# ifdef HAVE_GCC_VISIBILITY
# define CSRIAPI __attribute__((visibility ("default")))
# else
# define CSRIAPI
# endif
#endif
#define CSRI_OWN_HANDLES
typedef struct csri_libass_rend {
ass_library_t* ass_library;
} csri_rend;
typedef struct csri_asa_inst {
ass_renderer_t* ass_renderer;
ass_track_t* ass_track;
} csri_inst;
#include <csri/csri.h>
#include <csri/stream.h>
#include <subhelp.h>
static struct csri_libass_rend csri_libass = { NULL };
csri_inst *csri_open_file(csri_rend *renderer,
const char *filename, struct csri_openflag *flags)
{
return subhelp_open_file(renderer, csri_open_mem, filename, flags);
}
csri_inst *csri_open_mem(csri_rend *renderer,
const void *data, size_t length, struct csri_openflag *flags)
{
csri_inst *rv;
if (renderer != &csri_libass)
return NULL;
rv = (csri_inst *)malloc(sizeof(csri_inst));
if (!rv)
return NULL;
rv->ass_renderer = ass_renderer_init(renderer->ass_library);
if (!rv->ass_renderer) {
free(rv);
return NULL;
}
ass_set_font_scale(rv->ass_renderer, 1.);
ass_set_fonts(rv->ass_renderer, NULL, "Sans");
rv->ass_track = ass_read_memory(csri_libass.ass_library,
(void *)data, length, "UTF-8");
if (!rv->ass_track) {
ass_renderer_done(rv->ass_renderer);
free(rv);
return NULL;
}
return rv;
}
void csri_close(csri_inst *inst)
{
ass_free_track(inst->ass_track);
ass_renderer_done(inst->ass_renderer);
free(inst);
}
int csri_request_fmt(csri_inst *inst, const struct csri_fmt *fmt)
{
if (!csri_is_rgb(fmt->pixfmt) || csri_has_alpha(fmt->pixfmt))
return -1;
ass_set_frame_size(inst->ass_renderer, fmt->width, fmt->height);
return 0;
}
void csri_render(csri_inst *inst, struct csri_frame *frame, double time)
{
ass_image_t *img = ass_render_frame(inst->ass_renderer,
inst->ass_track, (int)(time * 1000), NULL);
while (img) {
unsigned bpp, alpha = 256 - (img->color && 0xFF);
int src_d, dst_d;
unsigned char *src, *dst, *endy, *endx;
unsigned char c[3] = {
(img->color >> 8) & 0xFF, /* B */
(img->color >> 16) & 0xFF, /* G */
img->color >> 24 /* R */
};
if ((frame->pixfmt | 1) == CSRI_F__RGB
|| frame->pixfmt == CSRI_F_RGB) {
unsigned char tmp = c[2];
c[2] = c[0];
c[0] = tmp;
}
bpp = frame->pixfmt >= 0x200 ? 3 : 4;
dst = frame->planes[0]
+ img->dst_y * frame->strides[0]
+ img->dst_x * bpp;
if (frame->pixfmt & 1)
dst++;
src = img->bitmap;
src_d = img->stride - img->w;
dst_d = frame->strides[0] - img->w * bpp;
endy = src + img->h * img->stride;
while (src != endy) {
endx = src + img->w;
while (src != endx) {
/* src[x]: 0..255, alpha: 1..256 (see above)
* -> src[x]*alpha: 0<<8..255<<8
* -> need 1..256 for mult => +1
*/
unsigned s = ((*src++ * alpha) >> 8) + 1;
unsigned d = 257 - s;
/* c[0]: 0.255, s/d: 1..256 */
dst[0] = (s*c[0] + d*dst[0]) >> 8;
dst[1] = (s*c[1] + d*dst[1]) >> 8;
dst[2] = (s*c[2] + d*dst[2]) >> 8;
dst += bpp;
}
dst += dst_d;
src += src_d;
}
img = img->next;
}
}
static csri_inst *libass_init_stream(csri_rend *renderer,
const void *header, size_t headerlen,
struct csri_openflag *flags)
{
csri_inst *rv;
if (renderer != &csri_libass)
return NULL;
rv = (csri_inst *)malloc(sizeof(csri_inst));
if (!rv)
return NULL;
rv->ass_renderer = ass_renderer_init(renderer->ass_library);
if (!rv->ass_renderer) {
free(rv);
return NULL;
}
ass_set_font_scale(rv->ass_renderer, 1.);
ass_set_fonts(rv->ass_renderer, NULL, "Sans");
rv->ass_track = ass_new_track(csri_libass.ass_library);
if (!rv->ass_track) {
ass_renderer_done(rv->ass_renderer);
free(rv);
return NULL;
}
ass_process_codec_private(rv->ass_track, (void *)header, headerlen);
return rv;
}
static void libass_push_packet(csri_inst *inst,
const void *packet, size_t packetlen,
double pts_start, double pts_end)
{
ass_process_chunk(inst->ass_track, (void *)packet, packetlen,
(int)(pts_start * 1000), (int)((pts_end - pts_start) * 1000));
}
static struct csri_stream_ext streamext = {
libass_init_stream,
libass_push_packet,
NULL
};
void *csri_query_ext(csri_rend *rend, csri_ext_id extname)
{
if (!rend)
return NULL;
if (!strcmp(extname, CSRI_EXT_STREAM_ASS))
return &streamext;
return NULL;
}
static struct csri_info csri_libass_info = {
"libass",
"0.9.x",
"libass (the MPlayer SSA/ASS renderer, 0.9.x API)",
"Evgeniy Stepanov",
"Copyright (c) 2006, 2007 by Evgeniy Stepanov"
};
struct csri_info *csri_renderer_info(csri_rend *rend)
{
return &csri_libass_info;
}
csri_rend *csri_renderer_byname(const char *name,
const char *specific)
{
if (strcmp(name, csri_libass_info.name))
return NULL;
if (specific && strcmp(specific, csri_libass_info.specific))
return NULL;
return &csri_libass;
}
csri_rend *csri_renderer_default()
{
csri_libass.ass_library = ass_library_init();
if (!csri_libass.ass_library)
return NULL;
ass_set_fonts_dir(csri_libass.ass_library, "");
ass_set_extract_fonts(csri_libass.ass_library, 0);
ass_set_style_overrides(csri_libass.ass_library, NULL);
return &csri_libass;
}
csri_rend *csri_renderer_next(csri_rend *prev)
{
return NULL;
}

4
csri/bootstrap Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash -x
autoreconf -f -i -s

135
csri/configure.ac Normal file
View file

@ -0,0 +1,135 @@
AC_PREREQ(2.57)
AC_INIT(csri, 0.1.0)
AC_CONFIG_AUX_DIR(ac)
AM_INIT_AUTOMAKE
AC_CONFIG_HEADER([include/acconf.h])
# Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL
AC_C_CONST
AC_C_INLINE
AC_C_VOLATILE
AC_PROG_INSTALL
AC_CHECK_HEADERS([png.h])
AC_CHECK_LIB([z], [inflate])
AC_CHECK_LIB([m], [pow])
AC_CHECK_LIB([png], [png_init_io])
AC_CPP_PRAGMA_ONCE
AC_C_FLAG([-Wall])
AC_C_FLAG([-Wextra],[AC_C_FLAG([-W])])
AC_C_FLAG([-Wno-unused-parameter])
AC_C_FLAG([-Winvalid-pch])
AC_C_FLAG([-pedantic])
AC_C_FLAG([-std=c99],[AC_C_FLAG([-c99])])
AC_ARG_ENABLE([werror],
AC_HELP_STRING([--enable-werror], [compile with -Werror (for developers)]),
[ if test "$enableval" == "yes"
then AC_C_FLAG([-Werror])
fi])
AC_GCC_VISIBILITY([internal])
AC_PATH_XTRA
platform=""
case $host_os in
mingw*) # LoadLibraryEx + GetProcAddress
platform="win32"
;;
*) AC_SEARCH_LIBS([dlopen], [dl], [], [
AC_MSG_FAILURE([dlopen not found - unsupported dynamic loader architecture / operating system])
])
esac
AM_CONDITIONAL([BUILD_MINGW], [test "$platform" == "win32" ])
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_STDBOOL
AC_CHECK_HEADERS([stdlib.h string.h sys/ioctl.h sys/time.h sys/wait.h sys/mman.h unistd.h libgen.h getopt.h])
AC_CHECK_FUNCS([getopt_long])
#
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
#AC_FUNC_FORK
#AC_PROG_GCC_TRADITIONAL
AC_TYPE_PID_T
AC_TYPE_SIZE_T
AC_TYPE_SIGNAL
AC_FUNC_MEMCMP
AC_CHECK_FUNCS([memset strdup strerror strtoul])
AC_ARG_WITH([libass],[
AS_HELP_STRING([--with-libass],[build libass backend @<:@default=auto@:>@])
],[],[ with_libass=auto
])
libass=no
AS_IF([test "$with_libass" != no],[
ac_cflags_save="$CFLAGS"
ac_ldflags_save="$LDFLAGS"
if test "$with_libass" != auto -a "$with_libass" != yes
then LIBASS_CFLAGS="-I$with_libass/include"
LIBASS_LIBS="-L$with_libass/lib -lass"
else PKG_CHECK_MODULES([LIBASS], libass >= 0.9.1,[],[
AC_MSG_WARN([libass not found via pkg-config])
LIBASS_LIBS="-lass"
])
fi
CFLAGS="$CFLAGS $LIBASS_CFLAGS"
LDFLAGS="$LDFLAGS $LIBASS_LIBS"
AC_CHECK_LIB([ass], [ass_library_init], [libass_lib="yes"])
AC_CHECK_HEADER([ass/ass.h], [libass_hdr="yes"])
if test "$libass_lib" == yes -a "$libass_hdr" == yes
then libass=yes
else if "$with_libass" != auto
then AC_MSG_FAILURE([libass requested but not found])
fi
fi
CFLAGS="$ac_cflags_save"
LDFLAGS="$ac_ldflags_save"
])
AM_CONDITIONAL([BUILD_LIBASS], [test "$libass" == "yes" ])
AC_SUBST([LIBASS_CFLAGS])
AC_SUBST([LIBASS_LIBS])
csrilibdir="${libdir}/csri"
AC_SUBST([csrilibdir])
csri_path="${csrilibdir}:/usr/lib/csri:/usr/local/lib/csri:~/.csri/lib"
AC_ARG_WITH(csri-libpath,
AC_HELP_STRING([--with-csri-libpath=PATH1:PATH2],
[Look for CSRI renderers in the specified directories. Separate directory names with colons. Tildes are expanded at run-time. [[$csri_path]]]),
[
if test "$withval" != "yes" -a "$withval" != "" -a "$withval" != "no"
then csri_path="$withval"
fi
])
AC_SUBST([csri_path], ["$csri_path"])
AC_CONFIG_FILES([csri.pc])
echo ""
echo " using search path: ${csri_path}"
echo "building libass wrapper: ${libass}"
echo ""
AC_OUTPUT([
ac/Makefile
include/Makefile
subhelp/Makefile
lib/Makefile
frontends/Makefile
frontends/avisynth25/Makefile
frontends/cmdline/Makefile
backends/Makefile
backends/libass/Makefile
Makefile
])

10
csri/csri.pc.in Normal file
View file

@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: csri
Description: csri - common subtitle renderer interface
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lcsri
Cflags: -I${includedir}

328
csri/csri.vcproj Normal file
View file

@ -0,0 +1,328 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="csri"
ProjectGUID="{4294BC27-91AC-4642-B5E1-042288478C2A}"
RootNamespace="csri"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="../lib/csri_d.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
AdditionalOptions="/machine:x64"
OutputFile="../lib/csri_d_x64.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="../lib/csri.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
AdditionalOptions="/machine:x64"
OutputFile="../lib/csri_x64.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\lib\win32\enumerate.c"
>
</File>
<File
RelativePath=".\lib\list.c"
>
</File>
<File
RelativePath=".\subhelp\logging.c"
>
</File>
<File
RelativePath=".\lib\wrap.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\include\csri\csri.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

327
csri/csri_2008.vcproj Normal file
View file

@ -0,0 +1,327 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="9.00"
Name="csri_2008"
ProjectGUID="{4294BC27-91AC-4642-B5E1-042288478C2A}"
RootNamespace="csri"
Keyword="Win32Proj"
TargetFrameworkVersion="131072"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="x64"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="../lib/csri_d_x64.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
CompileAs="1"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="../lib/csri_d_x64.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="../lib/csri.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|x64"
OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
ConfigurationType="4"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="lib;lib/win32;include;../aegisub/win32"
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLibrarianTool"
OutputFile="../lib/csri_x64.lib"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\lib\win32\enumerate.c"
>
</File>
<File
RelativePath=".\lib\list.c"
>
</File>
<File
RelativePath=".\subhelp\logging.c"
>
</File>
<File
RelativePath=".\lib\wrap.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\include\csri\csri.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View file

@ -0,0 +1,4 @@
SUBDIRS = \
avisynth25 \
cmdline

View file

@ -0,0 +1,15 @@
if BUILD_MINGW
AM_CPPFLAGS = \
-I$(top_srcdir)/include
lib_LTLIBRARIES = csri_avs.la
csri_avs_la_SOURCES = avisynth.cpp
csri_avs_la_LIBADD = \
../../lib/libcsri_la-enumerate.lo \
../../lib/libcsri_la-list.lo \
../../lib/libcsri_la-wrap.lo \
../../subhelp/libsubhelp_la-logging.lo
csri_avs_la_LDFLAGS = -avoid-version -no-undefined -module
endif
noinst_HEADERS = avisynth.h
EXTRA_DIST = avisynth.cpp

View file

@ -0,0 +1,155 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2006 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <windows.h>
#include "avisynth.h"
#include <stdio.h>
#include <csri/csri.h>
class CSRIAviSynth : public GenericVideoFilter {
csri_inst *inst;
double spf;
public:
CSRIAviSynth(PClip _child, IScriptEnvironment *env, const char *file,
const char *rendname, const char *rendver);
~CSRIAviSynth();
enum csri_pixfmt GetPixfmt();
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment *env);
static AVSValue __cdecl Create(AVSValue args, void* user_data,
IScriptEnvironment* env);
};
CSRIAviSynth::CSRIAviSynth(PClip _child, IScriptEnvironment *env,
const char *file, const char *rendname, const char *rendver)
: GenericVideoFilter(_child)
{
csri_rend *r = csri_renderer_byname(rendname, rendver);
if (!r) {
if (rendver)
env->ThrowError("Failed to load renderer \"%s\""
" version \"%s\"", rendname, rendver);
else if (rendname)
env->ThrowError("Failed to load renderer \"%s\"",
rendname);
else
env->ThrowError("Failed to load default renderer");
}
struct csri_fmt fmt;
fmt.pixfmt = GetPixfmt();
if (fmt.pixfmt == -1)
env->ThrowError("Pixel format not supported by "
"AviSynth interface");
inst = csri_open_file(r, file, NULL);
if (!inst)
env->ThrowError("Failed to load \"%s\"", file);
fmt.width = vi.width;
fmt.height = vi.height;
if (csri_request_fmt(inst, &fmt)) {
csri_close(inst);
env->ThrowError("Selected pixel format or size not supported "
"by selected subtitle renderer", file);
}
spf = (double)vi.fps_denominator / (double)vi.fps_numerator;
}
CSRIAviSynth::~CSRIAviSynth()
{
csri_close(inst);
}
enum csri_pixfmt CSRIAviSynth::GetPixfmt()
{
switch (vi.pixel_type) {
case VideoInfo::CS_BGR24: return CSRI_F_BGR;
case VideoInfo::CS_BGR32: return CSRI_F_BGR_;
case VideoInfo::CS_YUY2: return CSRI_F_YUY2;
case VideoInfo::CS_YV12: return CSRI_F_YV12;
}
return (enum csri_pixfmt)-1;
}
PVideoFrame __stdcall CSRIAviSynth::GetFrame(int n, IScriptEnvironment *env)
{
PVideoFrame avsframe = child->GetFrame(n, env);
struct csri_frame frame;
env->MakeWritable(&avsframe);
frame.pixfmt = GetPixfmt();
frame.planes[0] = avsframe->GetWritePtr();
frame.strides[0] = avsframe->GetPitch();
if (csri_is_yuv_planar(frame.pixfmt)) {
frame.planes[1] = avsframe->GetWritePtr(PLANAR_U);
frame.strides[1] = avsframe->GetPitch(PLANAR_U);
frame.planes[2] = avsframe->GetWritePtr(PLANAR_V);
frame.strides[2] = avsframe->GetPitch(PLANAR_V);
}
if (csri_is_rgb(frame.pixfmt)) {
frame.planes[0] += (vi.height - 1) * frame.strides[0];
frame.strides[0] = -frame.strides[0];
}
csri_render(inst, &frame, n * spf);
return avsframe;
}
AVSValue __cdecl CSRIAviSynth::Create(AVSValue args, void* user_data,
IScriptEnvironment* env)
{
const char *rname = args.ArraySize() >= 2 ? args[2].AsString() : NULL,
*rver = args.ArraySize() >= 3 ? args[3].AsString() : NULL;
return new CSRIAviSynth(args[0].AsClip(), env, args[1].AsString(),
rname, rver);
}
extern "C" __declspec(dllexport) const char* __stdcall AvisynthPluginInit2(
IScriptEnvironment* env)
{
static char avs_name_f[2048];
const char *avs_cmdname = (const char *)csri_query_ext(NULL,
"csri.avisynth25.command_name");
const char *avs_name = (const char *)csri_query_ext(NULL,
"csri.avisynth25.name");
if (!csri_renderer_default())
return NULL;
if (!avs_cmdname)
avs_cmdname = "CSRI";
if (!avs_name)
avs_name = "Common Subtitle Renderer Interface";
env->AddFunction(avs_cmdname, "cs", CSRIAviSynth::Create, 0);
env->AddFunction(avs_cmdname, "css", CSRIAviSynth::Create, 0);
env->AddFunction(avs_cmdname, "csss", CSRIAviSynth::Create, 0);
snprintf(avs_name_f, sizeof(avs_name_f),
"%s [AviSynth 2.5 front-end]", avs_name);
return avs_name_f;
}

View file

@ -0,0 +1,754 @@
// Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
// http://www.avisynth.org
// 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 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., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
// http://www.gnu.org/copyleft/gpl.html .
//
// Linking Avisynth statically or dynamically with other modules is making a
// combined work based on Avisynth. Thus, the terms and conditions of the GNU
// General Public License cover the whole combination.
//
// As a special exception, the copyright holders of Avisynth give you
// permission to link Avisynth with independent modules that communicate with
// Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
// terms of these independent modules, and to copy and distribute the
// resulting combined work under terms of your choice, provided that
// every copy of the combined work is accompanied by a complete copy of
// the source code of Avisynth (the version of Avisynth used to produce the
// combined work), being distributed under the terms of the GNU General
// Public License plus this exception. An independent module is a module
// which is not derived from or based on Avisynth, such as 3rd-party filters,
// import and export plugins, or graphical user interfaces.
#ifndef __AVISYNTH_H__
#define __AVISYNTH_H__
enum { AVISYNTH_INTERFACE_VERSION = 3 };
/* Define all types necessary for interfacing with avisynth.dll
Moved from internal.h */
// Win32 API macros, notably the types BYTE, DWORD, ULONG, etc.
#include <windef.h>
// COM interface macros
#include <objbase.h>
// Raster types used by VirtualDub & Avisynth
#define in64 (__int64)(unsigned short)
typedef unsigned long Pixel; // this will break on 64-bit machines!
typedef unsigned long Pixel32;
typedef unsigned char Pixel8;
typedef long PixCoord;
typedef long PixDim;
typedef long PixOffset;
/* Compiler-specific crap */
// Tell MSVC to stop precompiling here
#ifdef _MSC_VER
#pragma hdrstop
#endif
// Set up debugging macros for MS compilers; for others, step down to the
// standard <assert.h> interface
#ifdef _MSC_VER
#include <crtdbg.h>
#else
#define _RPT0(a,b) ((void)0)
#define _RPT1(a,b,c) ((void)0)
#define _RPT2(a,b,c,d) ((void)0)
#define _RPT3(a,b,c,d,e) ((void)0)
#define _RPT4(a,b,c,d,e,f) ((void)0)
#define _ASSERTE(x) assert(x)
#define _ASSERT(x) assert(x)
#include <assert.h>
#endif
// I had problems with Premiere wanting 1-byte alignment for its structures,
// so I now set the Avisynth struct alignment explicitly here.
#pragma pack(push,8)
#define FRAME_ALIGN 16
// Default frame alignment is 16 bytes, to help P4, when using SSE2
// The VideoInfo struct holds global information about a clip (i.e.
// information that does not depend on the frame number). The GetVideoInfo
// method in IClip returns this struct.
// Audio Sample information
typedef float SFLOAT;
enum {SAMPLE_INT8 = 1<<0,
SAMPLE_INT16 = 1<<1,
SAMPLE_INT24 = 1<<2, // Int24 is a very stupid thing to code, but it's supported by some hardware.
SAMPLE_INT32 = 1<<3,
SAMPLE_FLOAT = 1<<4};
enum {
PLANAR_Y=1<<0,
PLANAR_U=1<<1,
PLANAR_V=1<<2,
PLANAR_ALIGNED=1<<3,
PLANAR_Y_ALIGNED=PLANAR_Y|PLANAR_ALIGNED,
PLANAR_U_ALIGNED=PLANAR_U|PLANAR_ALIGNED,
PLANAR_V_ALIGNED=PLANAR_V|PLANAR_ALIGNED,
};
struct VideoInfo {
int width, height; // width=0 means no video
unsigned fps_numerator, fps_denominator;
int num_frames;
// This is more extensible than previous versions. More properties can be added seeminglesly.
// Colorspace properties.
enum {
CS_BGR = 1<<28,
CS_YUV = 1<<29,
CS_INTERLEAVED = 1<<30,
CS_PLANAR = 1<<31
};
// Specific colorformats
enum { CS_UNKNOWN = 0,
CS_BGR24 = 1<<0 | CS_BGR | CS_INTERLEAVED,
CS_BGR32 = 1<<1 | CS_BGR | CS_INTERLEAVED,
CS_YUY2 = 1<<2 | CS_YUV | CS_INTERLEAVED,
CS_YV12 = 1<<3 | CS_YUV | CS_PLANAR, // y-v-u, planar
CS_I420 = 1<<4 | CS_YUV | CS_PLANAR, // y-u-v, planar
CS_IYUV = 1<<4 | CS_YUV | CS_PLANAR // same as above
};
int pixel_type; // changed to int as of 2.5
int audio_samples_per_second; // 0 means no audio
int sample_type; // as of 2.5
__int64 num_audio_samples; // changed as of 2.5
int nchannels; // as of 2.5
// Imagetype properties
int image_type;
enum {
IT_BFF = 1<<0,
IT_TFF = 1<<1,
IT_FIELDBASED = 1<<2
};
// useful functions of the above
bool HasVideo() const { return (width!=0); }
bool HasAudio() const { return (audio_samples_per_second!=0); }
bool IsRGB() const { return !!(pixel_type&CS_BGR); }
bool IsRGB24() const { return (pixel_type&CS_BGR24)==CS_BGR24; } // Clear out additional properties
bool IsRGB32() const { return (pixel_type & CS_BGR32) == CS_BGR32 ; }
bool IsYUV() const { return !!(pixel_type&CS_YUV ); }
bool IsYUY2() const { return (pixel_type & CS_YUY2) == CS_YUY2; }
bool IsYV12() const { return ((pixel_type & CS_YV12) == CS_YV12)||((pixel_type & CS_I420) == CS_I420); }
bool IsColorSpace(int c_space) const { return ((pixel_type & c_space) == c_space); }
bool Is(int property) const { return ((pixel_type & property)==property ); }
bool IsPlanar() const { return !!(pixel_type & CS_PLANAR); }
bool IsFieldBased() const { return !!(image_type & IT_FIELDBASED); }
bool IsParityKnown() const { return ((image_type & IT_FIELDBASED)&&(image_type & (IT_BFF|IT_TFF))); }
bool IsBFF() const { return !!(image_type & IT_BFF); }
bool IsTFF() const { return !!(image_type & IT_TFF); }
bool IsVPlaneFirst() const {return ((pixel_type & CS_YV12) == CS_YV12); } // Don't use this
int BytesFromPixels(int pixels) const { return pixels * (BitsPerPixel()>>3); } // Will not work on planar images, but will return only luma planes
int RowSize() const { return BytesFromPixels(width); } // Also only returns first plane on planar images
int BMPSize() const { if (IsPlanar()) {int p = height * ((RowSize()+3) & ~3); p+=p>>1; return p; } return height * ((RowSize()+3) & ~3); }
__int64 AudioSamplesFromFrames(__int64 frames) const { return (fps_numerator && HasVideo()) ? ((__int64)(frames) * audio_samples_per_second * fps_denominator / fps_numerator) : 0; }
int FramesFromAudioSamples(__int64 samples) const { return (fps_denominator && HasAudio()) ? (int)((samples * (__int64)fps_numerator)/((__int64)fps_denominator * (__int64)audio_samples_per_second)) : 0; }
__int64 AudioSamplesFromBytes(__int64 bytes) const { return HasAudio() ? bytes / BytesPerAudioSample() : 0; }
__int64 BytesFromAudioSamples(__int64 samples) const { return samples * BytesPerAudioSample(); }
int AudioChannels() const { return nchannels; }
int SampleType() const{ return sample_type;}
bool IsSampleType(int testtype) const{ return !!(sample_type&testtype);}
int SamplesPerSecond() const { return audio_samples_per_second; }
int BytesPerAudioSample() const { return nchannels*BytesPerChannelSample();}
void SetFieldBased(bool isfieldbased) { if (isfieldbased) image_type|=IT_FIELDBASED; else image_type&=~IT_FIELDBASED; }
void Set(int property) { image_type|=property; }
void Clear(int property) { image_type&=~property; }
int BitsPerPixel() const {
switch (pixel_type) {
case CS_BGR24:
return 24;
case CS_BGR32:
return 32;
case CS_YUY2:
return 16;
case CS_YV12:
case CS_I420:
return 12;
default:
return 0;
}
}
int BytesPerChannelSample() const {
switch (sample_type) {
case SAMPLE_INT8:
return sizeof(signed char);
case SAMPLE_INT16:
return sizeof(signed short);
case SAMPLE_INT24:
return 3;
case SAMPLE_INT32:
return sizeof(signed int);
case SAMPLE_FLOAT:
return sizeof(SFLOAT);
default:
_ASSERTE("Sample type not recognized!");
return 0;
}
}
// useful mutator
void SetFPS(unsigned numerator, unsigned denominator) {
if ((numerator == 0) || (denominator == 0)) {
fps_numerator = 0;
fps_denominator = 1;
}
else {
unsigned x=numerator, y=denominator;
while (y) { // find gcd
unsigned t = x%y; x = y; y = t;
}
fps_numerator = numerator/x;
fps_denominator = denominator/x;
}
}
// Range protected multiply-divide of FPS
void MulDivFPS(unsigned multiplier, unsigned divisor) {
unsigned __int64 numerator = UInt32x32To64(fps_numerator, multiplier);
unsigned __int64 denominator = UInt32x32To64(fps_denominator, divisor);
unsigned __int64 x=numerator, y=denominator;
while (y) { // find gcd
unsigned __int64 t = x%y; x = y; y = t;
}
numerator /= x; // normalize
denominator /= x;
unsigned __int64 temp = numerator | denominator; // Just looking top bit
unsigned u = 0;
#ifdef __GNUC__
while (temp & 0xffffffff80000000LL) { // or perhaps > 16777216*2
#else
while (temp & 0xffffffff80000000) { // or perhaps > 16777216*2
#endif
temp = Int64ShrlMod32(temp, 1);
u++;
}
if (u) { // Scale to fit
const unsigned round = 1 << (u-1);
SetFPS( (unsigned)Int64ShrlMod32(numerator + round, u),
(unsigned)Int64ShrlMod32(denominator + round, u) );
}
else {
fps_numerator = (unsigned)numerator;
fps_denominator = (unsigned)denominator;
}
}
// Test for same colorspace
bool IsSameColorspace(const VideoInfo& vi) const {
if (vi.pixel_type == pixel_type) return TRUE;
if (IsYV12() && vi.IsYV12()) return TRUE;
return FALSE;
}
};
// VideoFrameBuffer holds information about a memory block which is used
// for video data. For efficiency, instances of this class are not deleted
// when the refcount reaches zero; instead they're stored in a linked list
// to be reused. The instances are deleted when the corresponding AVS
// file is closed.
class VideoFrameBuffer {
BYTE* const data;
const int data_size;
// sequence_number is incremented every time the buffer is changed, so
// that stale views can tell they're no longer valid.
long sequence_number;
friend class VideoFrame;
friend class Cache;
friend class ScriptEnvironment;
long refcount;
public:
VideoFrameBuffer(int size);
VideoFrameBuffer();
~VideoFrameBuffer();
const BYTE* GetReadPtr() const { return data; }
BYTE* GetWritePtr() { ++sequence_number; return data; }
int GetDataSize() { return data_size; }
int GetSequenceNumber() { return sequence_number; }
int GetRefcount() { return refcount; }
};
class IClip;
class PClip;
class PVideoFrame;
class IScriptEnvironment;
class AVSValue;
// VideoFrame holds a "window" into a VideoFrameBuffer. Operator new
// is overloaded to recycle class instances.
class VideoFrame {
int refcount;
VideoFrameBuffer* const vfb;
const int offset, pitch, row_size, height, offsetU, offsetV, pitchUV; // U&V offsets are from top of picture.
friend class PVideoFrame;
void AddRef() { InterlockedIncrement((long *)&refcount); }
void Release() { if (refcount==1) InterlockedDecrement(&vfb->refcount); InterlockedDecrement((long *)&refcount); }
friend class ScriptEnvironment;
friend class Cache;
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height);
VideoFrame(VideoFrameBuffer* _vfb, int _offset, int _pitch, int _row_size, int _height, int _offsetU, int _offsetV, int _pitchUV);
void* operator new(size_t size);
// TESTME: OFFSET U/V may be switched to what could be expected from AVI standard!
public:
int GetPitch() const { return pitch; }
int GetPitch(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: return pitchUV;} return pitch; }
int GetRowSize() const { return row_size; }
int GetRowSize(int plane) const {
switch (plane) {
case PLANAR_U: case PLANAR_V: if (pitchUV) return row_size>>1; else return 0;
case PLANAR_U_ALIGNED: case PLANAR_V_ALIGNED:
if (pitchUV) {
int r = ((row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)) )>>1; // Aligned rowsize
if (r<=pitchUV)
return r;
return row_size>>1;
} else return 0;
case PLANAR_Y_ALIGNED:
int r = (row_size+FRAME_ALIGN-1)&(~(FRAME_ALIGN-1)); // Aligned rowsize
if (r<=pitch)
return r;
return row_size;
}
return row_size; }
int GetHeight() const { return height; }
int GetHeight(int plane) const { switch (plane) {case PLANAR_U: case PLANAR_V: if (pitchUV) return height>>1; return 0;} return height; }
// generally you shouldn't use these three
VideoFrameBuffer* GetFrameBuffer() const { return vfb; }
int GetOffset() const { return offset; }
int GetOffset(int plane) const { switch (plane) {case PLANAR_U: return offsetU;case PLANAR_V: return offsetV;default: return offset;}; }
// in plugins use env->SubFrame()
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height) const;
VideoFrame* Subframe(int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int pitchUV) const;
const BYTE* GetReadPtr() const { return vfb->GetReadPtr() + offset; }
const BYTE* GetReadPtr(int plane) const { return vfb->GetReadPtr() + GetOffset(plane); }
bool IsWritable() const { return (refcount == 1 && vfb->refcount == 1); }
BYTE* GetWritePtr() const {
if (vfb->GetRefcount()>1) {
_ASSERT(FALSE);
//throw AvisynthError("Internal Error - refcount was more than one!");
}
return IsWritable() ? (vfb->GetWritePtr() + offset) : 0;
}
BYTE* GetWritePtr(int plane) const {
if (plane==PLANAR_Y) {
if (vfb->GetRefcount()>1) {
_ASSERT(FALSE);
// throw AvisynthError("Internal Error - refcount was more than one!");
}
return IsWritable() ? vfb->GetWritePtr() + GetOffset(plane) : 0;
}
return vfb->data + GetOffset(plane);
}
~VideoFrame() { InterlockedDecrement(&vfb->refcount); }
};
enum {
CACHE_NOTHING=0,
CACHE_RANGE=1,
CACHE_ALL=2,
CACHE_AUDIO=3,
CACHE_AUDIO_NONE=4
};
// Base class for all filters.
class IClip {
friend class PClip;
friend class AVSValue;
int refcnt;
void AddRef() { InterlockedIncrement((long *)&refcnt); }
void Release() { InterlockedDecrement((long *)&refcnt); if (!refcnt) delete this; }
public:
IClip() : refcnt(0) {}
virtual int __stdcall GetVersion() { return AVISYNTH_INTERFACE_VERSION; }
virtual PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) = 0;
virtual bool __stdcall GetParity(int n) = 0; // return field parity if field_based, else parity of first field in frame
virtual void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) = 0; // start and count are in samples
virtual void __stdcall SetCacheHints(int cachehints,int frame_range) = 0 ; // We do not pass cache requests upwards, only to the next filter.
virtual const VideoInfo& __stdcall GetVideoInfo() = 0;
virtual __stdcall ~IClip() {}
};
// smart pointer to IClip
class PClip {
IClip* p;
IClip* GetPointerWithAddRef() const { if (p) p->AddRef(); return p; }
friend class AVSValue;
friend class VideoFrame;
void Init(IClip* x) {
if (x) x->AddRef();
p=x;
}
void Set(IClip* x) {
if (x) x->AddRef();
if (p) p->Release();
p=x;
}
public:
PClip() { p = 0; }
PClip(const PClip& x) { Init(x.p); }
PClip(IClip* x) { Init(x); }
void operator=(IClip* x) { Set(x); }
void operator=(const PClip& x) { Set(x.p); }
IClip* operator->() const { return p; }
// useful in conditional expressions
operator void*() const { return p; }
bool operator!() const { return !p; }
~PClip() { if (p) p->Release(); }
};
// smart pointer to VideoFrame
class PVideoFrame {
VideoFrame* p;
void Init(VideoFrame* x) {
if (x) x->AddRef();
p=x;
}
void Set(VideoFrame* x) {
if (x) x->AddRef();
if (p) p->Release();
p=x;
}
public:
PVideoFrame() { p = 0; }
PVideoFrame(const PVideoFrame& x) { Init(x.p); }
PVideoFrame(VideoFrame* x) { Init(x); }
void operator=(VideoFrame* x) { Set(x); }
void operator=(const PVideoFrame& x) { Set(x.p); }
VideoFrame* operator->() const { return p; }
// for conditional expressions
operator void*() const { return p; }
bool operator!() const { return !p; }
~PVideoFrame() { if (p) p->Release();}
};
class AVSValue {
public:
AVSValue() { type = 'v'; }
AVSValue(IClip* c) { type = 'c'; clip = c; if (c) c->AddRef(); }
AVSValue(const PClip& c) { type = 'c'; clip = c.GetPointerWithAddRef(); }
AVSValue(bool b) { type = 'b'; boolean = b; }
AVSValue(int i) { type = 'i'; integer = i; }
// AVSValue(__int64 l) { type = 'l'; longlong = l; }
AVSValue(float f) { type = 'f'; floating_pt = f; }
AVSValue(double f) { type = 'f'; floating_pt = float(f); }
AVSValue(const char* s) { type = 's'; string = s; }
AVSValue(const AVSValue* a, int size) { type = 'a'; array = a; array_size = size; }
AVSValue(const AVSValue& v) { Assign(&v, true); }
~AVSValue() { if (IsClip() && clip) clip->Release(); }
AVSValue& operator=(const AVSValue& v) { Assign(&v, false); return *this; }
// Note that we transparently allow 'int' to be treated as 'float'.
// There are no int<->bool conversions, though.
bool Defined() const { return type != 'v'; }
bool IsClip() const { return type == 'c'; }
bool IsBool() const { return type == 'b'; }
bool IsInt() const { return type == 'i'; }
// bool IsLong() const { return (type == 'l'|| type == 'i'); }
bool IsFloat() const { return type == 'f' || type == 'i'; }
bool IsString() const { return type == 's'; }
bool IsArray() const { return type == 'a'; }
PClip AsClip() const { _ASSERTE(IsClip()); return IsClip()?clip:0; }
bool AsBool() const { _ASSERTE(IsBool()); return boolean; }
int AsInt() const { _ASSERTE(IsInt()); return integer; }
// int AsLong() const { _ASSERTE(IsLong()); return longlong; }
const char* AsString() const { _ASSERTE(IsString()); return IsString()?string:0; }
double AsFloat() const { _ASSERTE(IsFloat()); return IsInt()?integer:floating_pt; }
bool AsBool(bool def) const { _ASSERTE(IsBool()||!Defined()); return IsBool() ? boolean : def; }
int AsInt(int def) const { _ASSERTE(IsInt()||!Defined()); return IsInt() ? integer : def; }
double AsFloat(double def) const { _ASSERTE(IsFloat()||!Defined()); return IsInt() ? integer : type=='f' ? floating_pt : def; }
const char* AsString(const char* def) const { _ASSERTE(IsString()||!Defined()); return IsString() ? string : def; }
int ArraySize() const { _ASSERTE(IsArray()); return IsArray()?array_size:1; }
const AVSValue& operator[](int index) const {
_ASSERTE(IsArray() && index>=0 && index<array_size);
return (IsArray() && index>=0 && index<array_size) ? array[index] : *this;
}
private:
short type; // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong
short array_size;
union {
IClip* clip;
bool boolean;
int integer;
float floating_pt;
const char* string;
const AVSValue* array;
// __int64 longlong;
};
void Assign(const AVSValue* src, bool init) {
if (src->IsClip() && src->clip)
src->clip->AddRef();
if (!init && IsClip() && clip)
clip->Release();
// make sure this copies the whole struct!
((__int32*)this)[0] = ((__int32*)src)[0];
((__int32*)this)[1] = ((__int32*)src)[1];
}
};
// instantiable null filter
class GenericVideoFilter : public IClip {
protected:
PClip child;
VideoInfo vi;
public:
GenericVideoFilter(PClip _child) : child(_child) { vi = child->GetVideoInfo(); }
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env) { return child->GetFrame(n, env); }
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env) { child->GetAudio(buf, start, count, env); }
const VideoInfo& __stdcall GetVideoInfo() { return vi; }
bool __stdcall GetParity(int n) { return child->GetParity(n); }
void __stdcall SetCacheHints(int cachehints,int frame_range) { } ; // We do not pass cache requests upwards, only to the next filter.
};
class AvisynthError /* exception */ {
public:
const char* const msg;
AvisynthError(const char* _msg) : msg(_msg) {}
};
/* Helper classes useful to plugin authors */
class AlignPlanar : public GenericVideoFilter
{
public:
AlignPlanar(PClip _clip);
static PClip Create(PClip clip);
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};
class FillBorder : public GenericVideoFilter
{
public:
FillBorder(PClip _clip);
static PClip Create(PClip clip);
PVideoFrame __stdcall GetFrame(int n, IScriptEnvironment* env);
};
class ConvertAudio : public GenericVideoFilter
/**
* Helper class to convert audio to any format
**/
{
public:
ConvertAudio(PClip _clip, int prefered_format);
void __stdcall GetAudio(void* buf, __int64 start, __int64 count, IScriptEnvironment* env);
void __stdcall SetCacheHints(int cachehints,int frame_range); // We do pass cache requests upwards, to the cache!
static PClip Create(PClip clip, int sample_type, int prefered_type);
static AVSValue __cdecl Create_float(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_32bit(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_24bit(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_16bit(AVSValue args, void*, IScriptEnvironment*);
static AVSValue __cdecl Create_8bit(AVSValue args, void*, IScriptEnvironment*);
virtual ~ConvertAudio();
private:
void convertToFloat(char* inbuf, float* outbuf, char sample_type, int count);
void convertToFloat_3DN(char* inbuf, float* outbuf, char sample_type, int count);
void convertToFloat_SSE(char* inbuf, float* outbuf, char sample_type, int count);
void convertToFloat_SSE2(char* inbuf, float* outbuf, char sample_type, int count);
void convertFromFloat(float* inbuf, void* outbuf, char sample_type, int count);
void convertFromFloat_3DN(float* inbuf, void* outbuf, char sample_type, int count);
void convertFromFloat_SSE(float* inbuf, void* outbuf, char sample_type, int count);
void convertFromFloat_SSE2(float* inbuf, void* outbuf, char sample_type, int count);
__inline int Saturate_int8(float n);
__inline short Saturate_int16(float n);
__inline int Saturate_int24(float n);
__inline int Saturate_int32(float n);
char src_format;
char dst_format;
int src_bps;
char *tempbuffer;
SFLOAT *floatbuffer;
int tempbuffer_size;
};
// For GetCPUFlags. These are backwards-compatible with those in VirtualDub.
enum {
/* slowest CPU to support extension */
CPUF_FORCE = 0x01, // N/A
CPUF_FPU = 0x02, // 386/486DX
CPUF_MMX = 0x04, // P55C, K6, PII
CPUF_INTEGER_SSE = 0x08, // PIII, Athlon
CPUF_SSE = 0x10, // PIII, Athlon XP/MP
CPUF_SSE2 = 0x20, // PIV, Hammer
CPUF_3DNOW = 0x40, // K6-2
CPUF_3DNOW_EXT = 0x80, // Athlon
CPUF_X86_64 = 0xA0, // Hammer (note: equiv. to 3DNow + SSE2, which only Hammer
// will have anyway)
CPUF_SSE3 = 0x100, // Some P4 & Athlon 64.
};
#define MAX_INT 0x7fffffff
#define MIN_INT -0x7fffffff
class IScriptEnvironment {
public:
virtual __stdcall ~IScriptEnvironment() {}
virtual /*static*/ long __stdcall GetCPUFlags() = 0;
virtual char* __stdcall SaveString(const char* s, int length = -1) = 0;
virtual char* __stdcall Sprintf(const char* fmt, ...) = 0;
// note: val is really a va_list; I hope everyone typedefs va_list to a pointer
virtual char* __stdcall VSprintf(const char* fmt, void* val) = 0;
__declspec(noreturn) virtual void __stdcall ThrowError(const char* fmt, ...) = 0;
class NotFound /*exception*/ {}; // thrown by Invoke and GetVar
typedef AVSValue (__cdecl *ApplyFunc)(AVSValue args, void* user_data, IScriptEnvironment* env);
virtual void __stdcall AddFunction(const char* name, const char* params, ApplyFunc apply, void* user_data) = 0;
virtual bool __stdcall FunctionExists(const char* name) = 0;
virtual AVSValue __stdcall Invoke(const char* name, const AVSValue args, const char** arg_names=0) = 0;
virtual AVSValue __stdcall GetVar(const char* name) = 0;
virtual bool __stdcall SetVar(const char* name, const AVSValue& val) = 0;
virtual bool __stdcall SetGlobalVar(const char* name, const AVSValue& val) = 0;
virtual void __stdcall PushContext(int level=0) = 0;
virtual void __stdcall PopContext() = 0;
// align should be 4 or 8
virtual PVideoFrame __stdcall NewVideoFrame(const VideoInfo& vi, int align=FRAME_ALIGN) = 0;
virtual bool __stdcall MakeWritable(PVideoFrame* pvf) = 0;
virtual /*static*/ void __stdcall BitBlt(BYTE* dstp, int dst_pitch, const BYTE* srcp, int src_pitch, int row_size, int height) = 0;
typedef void (__cdecl *ShutdownFunc)(void* user_data, IScriptEnvironment* env);
virtual void __stdcall AtExit(ShutdownFunc function, void* user_data) = 0;
virtual void __stdcall CheckVersion(int version = AVISYNTH_INTERFACE_VERSION) = 0;
virtual PVideoFrame __stdcall Subframe(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height) = 0;
virtual int __stdcall SetMemoryMax(int mem) = 0;
virtual int __stdcall SetWorkingDir(const char * newdir) = 0;
virtual void* __stdcall ManageCache(int key, void* data) = 0;
enum PlanarChromaAlignmentMode {
PlanarChromaAlignmentOff,
PlanarChromaAlignmentOn,
PlanarChromaAlignmentTest };
virtual bool __stdcall PlanarChromaAlignment(PlanarChromaAlignmentMode key) = 0;
virtual PVideoFrame __stdcall SubframePlanar(PVideoFrame src, int rel_offset, int new_pitch, int new_row_size, int new_height, int rel_offsetU, int rel_offsetV, int new_pitchUV) = 0;
};
// avisynth.dll exports this; it's a way to use it as a library, without
// writing an AVS script or without going through AVIFile.
IScriptEnvironment* __stdcall CreateScriptEnvironment(int version = AVISYNTH_INTERFACE_VERSION);
#pragma pack(pop)
#endif //__AVISYNTH_H__

View file

@ -0,0 +1,6 @@
bin_PROGRAMS = csri
AM_CPPFLAGS = -I$(top_srcdir)/include
csri_SOURCES = cmdmain.c render.c
csri_LDADD = ../../lib/libcsri.la
noinst_HEADERS = render.h

View file

@ -0,0 +1,473 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "acconf.h"
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <math.h>
#include <csri/csri.h>
#include <csri/logging.h>
#include <csri/openerr.h>
#include <csri/stream.h>
#include "render.h"
csri_rend *r;
static int do_usage(FILE *fd)
{
fprintf(fd, "usage: csri [COMMON-OPTIONS] COMMAND [COMMAND-OPTIONS]\n"
"\n"
"common options: [-r renderer [-s specific]]\n"
"\t-r\tselect a renderer, by name\n"
"\t-s\tselect a renderer version, by specific name\n"
"\n"
"commands:\n"
"\tlist\tshow installed renderers\n"
"\tinfo\tshow detailed renderer information\n"
"\trender\trender subtitle output\n"
#ifdef HAVE_LIBPNG
"\t\t-i FILE\t\tread background from PNG file\n"
"\t\t-o PREFIX\twrite output to PREFIX_nnnn.png\n"
#endif
"\t\t-A\t\tkeep alpha\n"
"\t\t-t [start][:[end][:[step]]]\tspecify timestamps to be rendered\n"
"\t\tSUBFILE\t\tsubtitle file to load\n"
"\n");
return 2;
}
static int do_list(int argc, char **argv)
{
unsigned num = 0;
if (argc)
return do_usage(stderr);
while (r) {
struct csri_info *info = csri_renderer_info(r);
if (!info)
continue;
printf("%s:%s %s, %s, %s\n", info->name, info->specific,
info->longname, info->author, info->copyright);
r = csri_renderer_next(r);
num++;
}
fprintf(stderr, "%u renderers found\n", num);
return num > 0 ? 0 : 1;
}
static csri_ext_id known_exts[] = {
CSRI_EXT_OPENERR,
CSRI_EXT_LOGGING,
CSRI_EXT_STREAM,
CSRI_EXT_STREAM_ASS,
CSRI_EXT_STREAM_TEXT,
CSRI_EXT_STREAM_DISCARD,
NULL
};
static const char *dummy_script = "[Script Info]\r\n"
"ScriptType: v4.00\r\n"
"[V4 Styles]\r\n"
"Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, "
"TertiaryColour, BackColour, Bold, Italic, BorderStyle, "
"Outline, Shadow, Alignment, MarginL, MarginR, MarginV, "
"AlphaLevel, Encoding\r\n"
"Style: Default,Arial,20,&HFFFFFF&,&H00FFFF&,&H000000&,&H000000&,"
"0,0,1,2,2,2,10,10,10,0,0\r\n"
"[Events]\r\n"
"Format: Marked, Start, End, Style, Name, "
"MarginL, MarginR, MarginV, Effect, Text\r\n"
"Dialogue: Marked=0,0:00:01.00,0:00:02.00,Default,,0000,0000,0000,,"
"test\r\n";
static const char *dummy_stream = "1,0,Default,,0000,0000,0000,,stream\r\n";
#define e(x) { #x, CSRI_F_ ## x }
#define ree(x) e(RGB ## x), e(x ## RGB), e(BGR ## x), e(x ## BGR)
static struct csri_fmtlistent {
const char *label;
enum csri_pixfmt fmt;
} csri_fmts[] = {
ree(A), ree(_),
e(RGB), e(BGR),
e(AYUV), e(YUVA), e(YVUA), e(YUY2), e(YV12A), e(YV12),
{ NULL, 0 }
};
static void listfmts()
{
csri_inst *i;
struct csri_fmtlistent *fmt;
struct csri_fmt f;
printf("\ntrying to get list of supported colorspaces:\n");
fflush(stdout);
i = csri_open_mem(r, dummy_script, strlen(dummy_script), NULL);
f.width = f.height = 256;
for (fmt = csri_fmts; fmt->label; fmt++) {
f.pixfmt = fmt->fmt;
if (!csri_request_fmt(i, &f))
printf("\t[%04x] %s\n", fmt->fmt, fmt->label);
}
csri_close(i);
}
static int do_info(int argc, char **argv)
{
struct csri_info *info;
csri_ext_id *id;
if (argc)
return do_usage(stderr);
info = csri_renderer_info(r);
if (!info)
return 1;
printf("%s:%s\n\t%s\n\t%s\n\t%s\n", info->name, info->specific,
info->longname, info->author, info->copyright);
printf("supported CSRI extensions:\n");
for (id = known_exts; *id; id++) {
void *rext = csri_query_ext(r, *id);
void *lext = csri_query_ext(NULL, *id);
if (lext || rext) {
printf("\t%s ", *id);
if (!lext)
printf("\n");
else if (!rext)
printf("[library only]\n");
else if (rext == lext)
printf("[emulated by library]\n");
else
printf("\n");
}
}
listfmts();
return 0;
}
static void logfunc(void *appdata, enum csri_logging_severity sev,
const char *message)
{
char severity[32];
switch (sev) {
case CSRI_LOG_DEBUG: strcpy(severity, "[debug]"); break;
case CSRI_LOG_INFO: strcpy(severity, "[info]"); break;
case CSRI_LOG_NOTICE: strcpy(severity, "[notice]"); break;
case CSRI_LOG_WARNING: strcpy(severity, "[warning]"); break;
case CSRI_LOG_ERROR: strcpy(severity, "[error]"); break;
default: snprintf(severity, 32, "[%d?]", (int)sev);
}
fprintf(stderr, "%-10s %s\n", severity, message);
}
static int real_render(double *times, const char *infile, const char *outfile,
const char *script, enum csri_pixfmt pfmt)
{
struct csri_frame *bg, *a;
csri_inst *inst;
struct csri_fmt fmt;
double now;
int idx;
uint32_t width = 640, height = 480;
bg = infile ? png_load(infile, &width, &height, pfmt)
: frame_alloc(width, height, pfmt);
a = frame_alloc(width, height, pfmt);
if (!bg || !a) {
fprintf(stderr, "failed to allocate frame\n");
if (!bg)
fprintf(stderr, "\t- problem with background.\n");
return 2;
}
inst = csri_open_file(r, script, NULL);
if (!inst) {
fprintf(stderr, "failed to open script \"%s\"\n", script);
return 2;
}
fmt.pixfmt = pfmt;
fmt.width = width;
fmt.height = height;
if (csri_request_fmt(inst, &fmt)) {
fprintf(stderr, "format not supported by renderer\n");
return 2;
}
idx = 0;
for (now = times[0]; now <= times[1]; now += times[2]) {
frame_copy(a, bg, width, height);
csri_render(inst, a, now);
if (outfile) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
"%s_%04d.png", outfile, idx);
printf("%s\n", buffer);
png_store(a, buffer, width, height);
}
idx++;
}
csri_close(inst);
inst = NULL;
frame_free(bg);
frame_free(a);
return 0;
}
static int do_render(int argc, char **argv)
{
double times[3] = {0.0, 0.0, 1.0};
const char *outfile = NULL, *infile = NULL;
struct csri_fmtlistent *fmte;
int keepalpha = 0;
enum csri_pixfmt fmt = ~0U;
argv--, argc++;
while (1) {
int c, i;
const char *short_options = "t:o:i:F:A";
char *arg, *end, *err;
struct option long_options[] = {
{"time", 1, 0, 't'},
{"output", 1, 0, 'o'},
{"input", 1, 0, 'i'},
{"format", 0, 0, 'F'},
{"alpha", 0, 0, 'A'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, short_options, long_options, NULL);
if (c == -1)
break;
switch (c) {
case 't':
arg = optarg;
for (i = 0; i < 3; i++) {
end = strchr(arg, ':');
if (end)
*end = '\0';
if (*arg) {
times[i] = strtod(arg, &err);
if (*err) {
fprintf(stderr,
"invalid time: %s\n",
arg);
return do_usage(stderr);
}
}
if (!end)
break;
arg = end + 1;
}
break;
case 'i':
infile = optarg;
break;
case 'o':
outfile = optarg;
break;
case 'A':
if (fmt != ~0U)
return do_usage(stderr);
keepalpha = 1;
break;
case 'F':
if (keepalpha || fmt != ~0U)
return do_usage(stderr);
for (fmte = csri_fmts; fmte->label; fmte++)
if (!strcmp(fmte->label, optarg))
break;
if (!fmte->label)
return do_usage(stderr);
fmt = fmte->fmt;
break;
default:
return do_usage(stderr);
};
}
if (fmt == ~0U)
fmt = keepalpha ? CSRI_F_RGBA : CSRI_F_RGB_;
if (!isfinite(times[0])) {
fprintf(stderr, "invalid start time\n");
return do_usage(stderr);
}
if (!isfinite(times[1]) || times[1] < times[0]) {
fprintf(stderr, "invalid end time\n");
return do_usage(stderr);
}
if (!isnormal(times[2]) || times[2] < 0.0) {
fprintf(stderr, "invalid end time\n");
return do_usage(stderr);
}
if (argc - optind != 1) {
fprintf(stderr, "script name missing\n");
return do_usage(stderr);
}
return real_render(times, infile, outfile, argv[optind], fmt);
}
static int do_streamtest(int argc, char **argv)
{
const char *outfile = NULL;
struct csri_fmtlistent *fmte;
enum csri_pixfmt pfmt = ~0U;
struct csri_frame *bg, *a;
csri_inst *inst;
struct csri_fmt fmt;
uint32_t width = 640, height = 480;
struct csri_stream_ext *sext;
argv--, argc++;
while (1) {
int c;
const char *short_options = "o:F:";
struct option long_options[] = {
{"output", 1, 0, 'o'},
{"format", 0, 0, 'F'},
{0, 0, 0, 0}
};
c = getopt_long(argc, argv, short_options, long_options, NULL);
if (c == -1)
break;
switch (c) {
case 'o':
outfile = optarg;
break;
case 'F':
if (pfmt != ~0U)
return do_usage(stderr);
for (fmte = csri_fmts; fmte->label; fmte++)
if (!strcmp(fmte->label, optarg))
break;
if (!fmte->label)
return do_usage(stderr);
pfmt = fmte->fmt;
break;
default:
return do_usage(stderr);
};
}
if (pfmt == ~0U)
pfmt = CSRI_F_RGB_;
sext = (struct csri_stream_ext *)csri_query_ext(r,
CSRI_EXT_STREAM_ASS);
if (!sext) {
fprintf(stderr, "renderer does not support ASS streaming\n");
return 2;
}
bg = frame_alloc(width, height, pfmt);
a = frame_alloc(width, height, pfmt);
if (!bg || !a) {
fprintf(stderr, "failed to allocate frame\n");
return 2;
}
inst = sext->init_stream(r, dummy_script, strlen(dummy_script), NULL);
if (!inst) {
fprintf(stderr, "failed to initialize stream\n");
return 2;
}
fmt.pixfmt = pfmt;
fmt.width = width;
fmt.height = height;
if (csri_request_fmt(inst, &fmt)) {
fprintf(stderr, "format not supported by renderer\n");
return 2;
}
frame_copy(a, bg, width, height);
csri_render(inst, a, 1.75);
if (outfile) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
"%s_nstream.png", outfile);
printf("%s\n", buffer);
png_store(a, buffer, width, height);
}
frame_copy(a, bg, width, height);
sext->push_packet(inst, dummy_stream, strlen(dummy_stream),
1.5, 2.0);
csri_render(inst, a, 1.75);
if (outfile) {
char buffer[256];
snprintf(buffer, sizeof(buffer),
"%s_stream.png", outfile);
printf("%s\n", buffer);
png_store(a, buffer, width, height);
}
csri_close(inst);
inst = NULL;
frame_free(bg);
frame_free(a);
return 0;
}
int main(int argc, char **argv)
{
struct csri_logging_ext *logext;
if (argc < 2)
return do_usage(stderr);
logext = (struct csri_logging_ext *)csri_query_ext(NULL,
CSRI_EXT_LOGGING);
if (logext && logext->set_logcallback)
logext->set_logcallback(logfunc, NULL);
else
fprintf(stderr, "warning: unable to set log callback\n");
r = csri_renderer_default();
argc--, argv++;
if (!strcmp(argv[0], "list"))
return do_list(argc - 1, argv + 1);
if (!strcmp(argv[0], "-r")) {
const char *name = NULL, *spec = NULL;
if (argc < 2)
return do_usage(stderr);
name = argv[1];
argc -= 2, argv += 2;
if (!strcmp(argv[0], "-s")) {
if (argc < 2)
return do_usage(stderr);
spec = argv[1];
}
r = csri_renderer_byname(name, spec);
if (!r) {
fprintf(stderr, "renderer %s:%s not found.\n",
name, spec ? spec : "*");
return 2;
}
}
if (!strcmp(argv[0], "info"))
return do_info(argc - 1, argv + 1);
if (!strcmp(argv[0], "render"))
return do_render(argc - 1, argv + 1);
if (!strcmp(argv[0], "streamtest"))
return do_streamtest(argc - 1, argv + 1);
return do_usage(stderr);
}

View file

@ -0,0 +1,240 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "acconf.h"
#endif
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <csri/csri.h>
#include <csri/logging.h>
#include "render.h"
extern csri_rend *r;
#ifdef HAVE_LIBPNG
#include <png.h>
struct csri_frame *png_load(const char *filename,
uint32_t *width, uint32_t *height, enum csri_pixfmt fmt)
{
struct csri_frame *frame;
int bit_depth, color_type;
png_structp png_ptr;
png_infop info_ptr;
png_bytep *rows;
unsigned char *imgdata;
FILE *fp;
if (!csri_is_rgb(fmt)) {
fprintf(stderr, "PNG loader: can't load non-RGB.\n");
return NULL;
}
frame = (struct csri_frame *)malloc(sizeof(struct csri_frame));
if (!frame)
return NULL;
memset(frame, 0, sizeof(*frame));
frame->pixfmt = fmt;
fp = fopen(filename, "rb");
if (!fp) {
fprintf(stderr, "Error opening \"%s\": %s (%d)\n",
filename, strerror(errno), errno);
return NULL;
}
assert(png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL));
assert(info_ptr = png_create_info_struct(png_ptr));
//keepalpha ? CSRI_F_RGBA : CSRI_F_RGB_;
png_init_io(png_ptr, fp);
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr,
(png_uint_32 *)width, (png_uint_32 *)height,
&bit_depth, &color_type, NULL, NULL, NULL);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_palette_to_rgb(png_ptr);
if (bit_depth < 8)
png_set_packing(png_ptr);
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_tRNS_to_alpha(png_ptr);
if (bit_depth == 16)
png_set_strip_16(png_ptr);
if ((fmt < 0x200 && (fmt & 2)) || fmt == CSRI_F_BGR)
png_set_bgr(png_ptr);
if (csri_has_alpha(fmt)) {
int before = fmt == CSRI_F_ARGB || fmt == CSRI_F_ABGR;
if (color_type == PNG_COLOR_TYPE_RGB)
png_set_filler(png_ptr, 0xff, before
? PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
else {
png_set_invert_alpha(png_ptr);
if (before)
png_set_swap_alpha(png_ptr);
}
} else {
if (color_type & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(png_ptr);
if (fmt != CSRI_F_RGB && fmt != CSRI_F_BGR) {
int before = fmt == CSRI_F__RGB || fmt == CSRI_F__BGR;
png_set_filler(png_ptr, 0xff, before
? PNG_FILLER_BEFORE : PNG_FILLER_AFTER);
}
}
rows = (png_bytep *)malloc(sizeof(png_bytep) * *height);
assert(rows);
imgdata = (unsigned char *)malloc(4 * *height * *width);
assert(imgdata);
for (uint32_t y = 0; y < *height; y++)
rows[y] = imgdata + 4 * *width * y;
png_read_image(png_ptr, rows);
png_read_end(png_ptr, NULL);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
free(rows);
frame->planes[0] = imgdata;
frame->strides[0] = *width * 4;
printf("\033[32;1mloaded %ux%u\033[m\n", *width, *height);
return frame;
}
void png_store(struct csri_frame *frame, const char *filename,
uint32_t width, uint32_t height)
{
enum csri_pixfmt fmt = frame->pixfmt;
int xforms = 0, before = 0, after = 0;
png_structp png_ptr;
png_infop info_ptr;
png_bytep *rows;
FILE *fp;
fp = fopen(filename, "wb");
if (!fp) {
fprintf(stderr, "Error opening \"%s\": %s (%d)\n",
filename, strerror(errno), errno);
return;
}
rows = (png_bytep *)malloc(sizeof(png_bytep) * height);
assert(rows);
after = fmt == CSRI_F_RGB_ || fmt == CSRI_F_BGR_;
before = fmt == CSRI_F__RGB || fmt == CSRI_F__BGR;
for (uint32_t y = 0; y < height; y++) {
rows[y] = frame->planes[0] + frame->strides[0] * y;
if (before || after) {
unsigned char *d = rows[y], *s = rows[y],
*e = d + frame->strides[0];
if (before)
s++;
while (d < e) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
s++;
}
}
}
assert(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL, NULL));
assert(info_ptr = png_create_info_struct(png_ptr));
png_init_io(png_ptr, fp);
if (csri_has_alpha(fmt)
&& (fmt == CSRI_F_ARGB || fmt == CSRI_F_ABGR))
xforms |= PNG_TRANSFORM_SWAP_ALPHA;
if ((fmt < 0x200 && (fmt & 2)) || fmt == CSRI_F_BGR)
xforms |= PNG_TRANSFORM_BGR;
png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
png_set_IHDR(png_ptr, info_ptr, width, height, 8, csri_has_alpha(fmt)
? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_set_rows(png_ptr, info_ptr, rows);
png_write_png(png_ptr, info_ptr, xforms, NULL);
fflush(fp);
png_destroy_write_struct(&png_ptr, &info_ptr);
}
#else
struct csri_frame *png_load(const char *filename,
uint32_t *width, uint32_t *height, enum csri_pixfmt fmt)
{
fprintf(stderr, "PNG support not compiled in.\n");
return NULL;
}
void png_store(struct csri_frame *frame, const char *filename,
uint32_t width, uint32_t height)
{
fprintf(stderr, "PNG support not compiled in.\n");
return;
}
#endif
struct csri_frame *frame_alloc(uint32_t width, uint32_t height,
enum csri_pixfmt fmt)
{
int bpp;
unsigned char *d;
struct csri_frame *frame;
if (!csri_is_rgb(fmt))
return NULL;
bpp = fmt < CSRI_F_RGB ? 4 : 3;
d = (unsigned char *)malloc(width * height * bpp);
frame = (struct csri_frame *)malloc(sizeof(struct csri_frame));
if (!frame || !d)
return NULL;
memset(frame, 0, sizeof(*frame));
frame->pixfmt = fmt;
frame->strides[0] = width * bpp;
memset(d, csri_has_alpha(fmt) ? 0x00 : 0x80, width * height * bpp);
frame->planes[0] = d;
return frame;
}
void frame_free(struct csri_frame *frame)
{
int c;
for (c = 0; c < 4; c++)
if (frame->planes[c])
free(frame->planes[c]);
free(frame);
}
void frame_copy(struct csri_frame *dst, struct csri_frame *src,
uint32_t width, uint32_t height)
{
memcpy(dst->planes[0], src->planes[0], height * src->strides[0]);
}

View file

@ -0,0 +1,34 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifndef _RENDER_H
#define _RENDER_H
extern struct csri_frame *png_load(const char *filename,
uint32_t *width, uint32_t *height, enum csri_pixfmt fmt);
extern void png_store(struct csri_frame *frame, const char *filename,
uint32_t width, uint32_t height);
extern struct csri_frame *frame_alloc(uint32_t width, uint32_t height,
enum csri_pixfmt fmt);
extern void frame_free(struct csri_frame *frame);
extern void frame_copy(struct csri_frame *dst, struct csri_frame *src,
uint32_t width, uint32_t height);
#endif

2
csri/include/Makefile.am Normal file
View file

@ -0,0 +1,2 @@
noinst_HEADERS = subhelp.h visibility.h
pkginclude_HEADERS = csri/csri.h csri/openerr.h csri/logging.h csri/stream.h

348
csri/include/csri/csri.h Normal file
View file

@ -0,0 +1,348 @@
/*****************************************************************************
* csri: common subtitle renderer interface
*****************************************************************************
* Copyright (C) 2007 David Lamparter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
****************************************************************************/
/** \file csri.h - main CSRI (common subtitle renderer interface) include.
* $Id: csri.h 45 2007-06-20 01:00:40Z equinox $ */
#ifndef _CSRI_H
/** \cond */
#define _CSRI_H 20070119
/** \endcond */
#include <stddef.h> /* ptrdiff_t */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef CSRIAPI
/** CSRI API attributes.
* defaults to \c extern.
*/
#define CSRIAPI extern
#endif
/** \defgroup base CSRI base API. */
/*@{*/
/** pixel format specification for frames */
enum csri_pixfmt {
CSRI_F_RGBA = 0,
CSRI_F_ARGB,
CSRI_F_BGRA,
CSRI_F_ABGR,
CSRI_F_RGB_ = 0x100,
CSRI_F__RGB,
CSRI_F_BGR_, /**< Windows "RGB32" */
CSRI_F__BGR,
CSRI_F_RGB = 0x200,
CSRI_F_BGR, /**< Windows "RGB24" */
CSRI_F_AYUV = 0x1000,
CSRI_F_YUVA,
CSRI_F_YVUA,
CSRI_F_YUY2 = 0x1100,
CSRI_F_YV12A = 0x2011, /**< planar YUV 2x2 + alpha plane */
CSRI_F_YV12 = 0x2111 /**< planar YUV 2x2 */
};
#define csri_is_rgb(x) ((x) < 0x1000)
#define csri_is_yuv(x) ((x) >= 0x1000)
#define csri_is_yuv_planar(x) ((x) >= 0x2000)
#define csri_get_yuv_planar_xred(x) (0xf & (x))
#define csri_get_yuv_planar_yred(x) (0xf & ((x) >> 4))
#define csri_is_yuv_packed(x) ((x) >= 0x1000 && (x) < 0x2000)
#define csri_has_alpha(x) (((x) & 0xfff) < 0x100)
/** frame/image format specification pre-fed to the renderer */
struct csri_fmt {
/** format to be used */
enum csri_pixfmt pixfmt;
/** image width, full frame.
*
* This should specify the full size of the frame.
* Specifying the video sub-size (in case of added black
* borders) is left to an extension.
*/
unsigned width;
/** image height */
unsigned height;
};
/** single frame to be fed to the renderer. */
struct csri_frame {
/** frame format.
* It is an application bug if this differs from the one
* passed in struct #csri_fmt to csri_query_fmt()
*/
enum csri_pixfmt pixfmt;
/** the frame's data.
* Packed formats only use planes[0]; planar formats
* have the data ordered as Y, U, V[, A].
*
* Also note that the topmost line always comes first.
* The Windows biHeight strange-ity is \a NOT duplicated.
*/
unsigned char *planes[4];
/** strides for the individual planes.
* Stride means full byte offset, i.e. do \a not add
* frame width
*/
ptrdiff_t strides[4];
};
#ifndef CSRI_OWN_HANDLES
/** opaque renderer data */
typedef void csri_rend;
/** opaque instance data */
typedef void csri_inst;
#endif
#ifdef DOXYGEN
/** disable the emission of the csri_rend and csri_inst typedefs.
* define this if you are in a renderer and are typedef'ing
* csri_rend and csri_inst to your own structs.
*/
#define CSRI_OWN_HANDLES
#endif
/** renderer description.
* \ingroup loader
*/
struct csri_info {
/** an identifier for the renderer.
* - MUST match the regular expression
* \code ^[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])? \endcode
* i.e. consists only of letters, numbers and underscores;
* must start with a letter and doesnt have an underscore
* as the last character.
*/
const char *name;
/** an identifier to the exact version of the renderer.
* most likely a version number or revision identifier.
*
* The helper library does a strcmp over this field in order
* to order multiple instances of the same renderer. Use
* higher-byte-value strings for newer renderers.
*/
const char *specific;
/** a nice name to be presented to the user */
const char *longname;
/** the renderer's author */
const char *author;
/** a copyright string. Copyright (c) 2042 by Mr. Nice Guy */
const char *copyright;
};
/** data of extension-dependent type.
* The field to be used MUST be specified in the extension where it is used.
*/
union csri_vardata {
long lval;
double dval;
const char *utf8val;
void *otherval;
};
/** extension identifier.
* This follows reverse DNS syntax, i.e.:
* \code root.branch.leaf \endcode
* you can either reverse a registered domain name, e.g.
* \code com.microsoft.csri.usegdiplus \endcode
* or ask the CSRI maintainers to assign a namespace to you.
*
* currently registered namespaces are:
*
* \code
* csri.* - official extensions
* asa.* - custom extensions of the asa renderer
* \endcode
*/
typedef const char *csri_ext_id;
/** script loading parameters.
* each flag MUST have an associated extension, which can be queried
* with csri_query_ext(). If the open flag constitutes an extension on its
* sole own, csri_query_ext() can return a meaningless non-NULL value for
* it.
*
* The data field used must be specified.
*
* An extension can have multiple flags. In that case, the flags should have
* the extension name as common prefix, separated with a dot.
*
* A renderer MUST ignore unknown open flags. It MUST NOT return an error
* just because it does not support a particular flag.
*/
struct csri_openflag {
/** flag name */
csri_ext_id name;
/** flag data argument */
union csri_vardata data;
/** link to next flag */
struct csri_openflag *next;
};
/** load a script from a file.
* \param renderer the handle to the renderer
* \param filename the path to the file to be loaded. \n
* The filename should be encoded as UTF-8. Windows renderers are
* expected to convert it to UTF-16 and use the Unicode Windows API
* functions.
* \param flags a linked list of open flags. \n
* The caller manages memory allocation, i.e. static allocation is OK.
* \return the renderer instance handle, or NULL on error.
*/
CSRIAPI csri_inst *csri_open_file(csri_rend *renderer,
const char *filename, struct csri_openflag *flags);
/** load a script from memory.
* \param renderer the handle to the renderer
* \param data pointer to the first data byte. \n
* The caller manages memory allocation and should free the data after
* calling csri_open_mem(). If the renderer needs to keep the data, it
* must copy it. \n
* The renderer is not allowed to write to the data.
* \param length length, in bytes, of the data
* \param flags see csri_open_file()
* \return the render instance handle, or NULL on error.
*/
CSRIAPI csri_inst *csri_open_mem(csri_rend *renderer,
const void *data, size_t length, struct csri_openflag *flags);
/** close a renderer instance.
* \param inst the instance handle.
*/
CSRIAPI void csri_close(csri_inst *inst);
/** query / set the image format and size.
* \param inst the renderer instance handle
* \param fmt the format and image size to be used
* \return 0 if the format was successfully set,
* any other value in case of error.
*/
CSRIAPI int csri_request_fmt(csri_inst *inst, const struct csri_fmt *fmt);
/** render a single frame
* \param inst the renderer instance handle
* \param frame frame data to render to
* \param time associated timestamp of the frame
*/
CSRIAPI void csri_render(csri_inst *inst, struct csri_frame *frame,
double time);
/** query for an extension.
* \param rend the renderer handle
* \param extname the extension's identifier
* \return NULL if the extension is not supported,
* a pointer to extension-specific data otherwise
*
* The data pointed to by the return value does not neccessarily need to
* have any meaning; An extension that does not need to return data
* can return a pointer to whatever it wants, as long as that pointer is
* not NULL.
*
* In the usual case, the pointer is supposed to point to a struct with
* function pointers and other information as needed.
*/
CSRIAPI void *csri_query_ext(csri_rend *rend, csri_ext_id extname);
/*@}*/
/** \defgroup loader CSRI loader API.
*
* These functions locate renderers based on given parameters.
*
* <b>Renderers must implement these functions as well.</b>
*
* They are used by the library to grab renderer information
* from a shared object; and also this way a single renderer
* can be linked directly into an appliaction.
*/
/*@{*/
/** get renderer information
* \param rend the renderer handle
* \return information about the renderer, or NULL in case the renderer
* encountered an internal error.
*/
CSRIAPI struct csri_info *csri_renderer_info(csri_rend *rend);
/** try to load a given renderer
* \param name the name of the renderer, as in csri_info.name
* \param specific the specific version of the renderer,
* as in csri_info.specific;\n
* alternatively NULL if any version of the renderer is ok.
* \return a handle to the renderer if it was successfully loaded,
* NULL otherwise.
*/
CSRIAPI csri_rend *csri_renderer_byname(const char *name,
const char *specific);
/** try to find an implementation of the given extensions.
* \param next number of extensions pointed to by ext
* \param ext array of extensions to search for
* \return a handle to a renderer supporting ALL of the
* extensions, NULL if none was found.
*/
CSRIAPI csri_rend *csri_renderer_byext(unsigned n_ext, csri_ext_id *ext);
/** get the default (highest priority) renderer
* \return a handle to the default renderer, or NULL if
* no renderer is installed.
*
* Together with csri_renderer_next(), this can be used
* to enumerate all installed renderers.
*/
CSRIAPI csri_rend *csri_renderer_default();
/** get the next lower priority renderer
* \param prev the current renderer
* \return the renderer with the next lower priority than
* the one named in prev, or NULL if prev is the last
* renderer installed.
*/
CSRIAPI csri_rend *csri_renderer_next(csri_rend *prev);
/*@}*/
#ifdef __cplusplus
}
#endif
#endif /* _CSRI_H */

View file

@ -0,0 +1,65 @@
/*****************************************************************************
* csri: common subtitle renderer interface
*****************************************************************************
* Copyright (C) 2007 David Lamparter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
****************************************************************************/
/** \file fmtids.h - csri.format - extension identifiers for subtitle formats.
* $Id$ */
#ifndef _CSRI_FMTIDS_H
/** \cond */
#define _CSRI_FMTIDS_H 20070119
/** \endcond */
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup fmtids csri.format identifiers.
* only includes the most important ones for now, more to be added. */
/*@{*/
/** SSA / ASS. Sub Station Alpha - versions 2, 3, 4, 4+ and 4++ */
#define CSRI_EXT_FMT_SSA (csri_ext_id)"csri.format.ssa"
/** SRT. SubRip Text, SubRip Titles or something similar. */
#define CSRI_EXT_FMT_SRT (csri_ext_id)"csri.format.srt"
/** MicroDVD */
#define CSRI_EXT_FMT_MICRODVD (csri_ext_id)"csri.format.microdvd"
/** SAMI. Microsoft Synchronized Accessible Media Interchange */
#define CSRI_EXT_FMT_SAMI (csri_ext_id)"csri.format.sami"
/** SMIL. W3C Synchronized Multimedia Integration Language.
* NB: this format uses separate files for text streams */
#define CSRI_EXT_FMT_SMIL (csri_ext_id)"csri.format.smil"
/*@}*/
#ifdef __cplusplus
}
#endif
#endif /* _CSRI_OPENERR_H */

View file

@ -0,0 +1,79 @@
/*****************************************************************************
* csri: common subtitle renderer interface
*****************************************************************************
* Copyright (C) 2007 David Lamparter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
****************************************************************************/
/** \file logging.h - csri.logging - logging for renderers via callback.
* $Id$
*
* <b>THE SPECIFICATION OF THIS EXTENSION IS TENTATIVE
* AND NOT FINALIZED YET</b>
*/
#ifndef _CSRI_LOGGING_H
/** \cond */
#define _CSRI_LOGGING_H 20070119
/** \endcond */
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup logging csri.logging extension.
* <b>THE SPECIFICATION OF THIS EXTENSION IS TENTATIVE
* AND NOT FINALIZED YET</b>
*/
/*@{*/
/** extension identifier */
#define CSRI_EXT_LOGGING (csri_ext_id)"csri.logging"
/** -. TODO: add scope? */
enum csri_logging_severity {
CSRI_LOG_DEBUG = 0,
CSRI_LOG_INFO,
CSRI_LOG_NOTICE,
CSRI_LOG_WARNING,
CSRI_LOG_ERROR
};
typedef void csri_logging_func(void *appdata,
enum csri_logging_severity sev,
const char *message);
struct csri_logging_ext {
void (*set_logcallback)(csri_logging_func *func, void *appdata);
};
/*@}*/
#ifdef __cplusplus
}
#endif
#endif /* _CSRI_LOGGING_H */

124
csri/include/csri/openerr.h Normal file
View file

@ -0,0 +1,124 @@
/*****************************************************************************
* csri: common subtitle renderer interface
*****************************************************************************
* Copyright (C) 2007 David Lamparter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
****************************************************************************/
/** \file openerr.h - csri.openerr - error return extension.
* $Id$ */
#ifndef _CSRI_OPENERR_H
/** \cond */
#define _CSRI_OPENERR_H 20070119
/** \endcond */
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup openerr csri.openerr extension. */
/*@{*/
/** extension identifier */
#define CSRI_EXT_OPENERR (csri_ext_id)"csri.openerr"
/** flag field describing which fields of #csri_openerr_flag are valid */
enum csri_openerr_flags {
/** support indicator.
* set if the structure was filled with any meaningful data
*/
CSRI_OPENERR_FILLED = (1 << 0),
/** csri_openerr_flag.posixerrno valid */
CSRI_OPENERR_ERRNO = (1 << 1),
/** csri_openerr_flag.winerr valid */
CSRI_OPENERR_WINERR = (1 << 2),
/** csri_openerr_flag.custerr valid */
CSRI_OPENERR_CUSTERR = (1 << 3),
/** csri_openerr_flag.warncount valid */
CSRI_OPENERR_WARNCOUNT = (1 << 4)
};
/** returned error information.
* to be passed via csri_vardata.otherval as an openflag with
* extension ID #CSRI_EXT_OPENERR.
*
* Memory management by caller.
*
* The three error fields should only be filled when csri_open_file()
* / csri_open_mem() returned NULL. The warning counter can indicate
* information on successfully loaded scripts.
*/
struct csri_openerr_flag {
/** bitfield of valid information */
enum csri_openerr_flags flags;
/** posix errno value indicating the error occured */
int posixerrno;
/** Windows GetLastError value */
unsigned winerr;
/** renderer-specific custom error value.
* should be string-lookupable via csri_openerr_ext.strerror
* (csri_query_ext())
*/
union csri_vardata custerr;
/** warning count.
* The number of (renderer-specific) warnings that occured
* during loading the script. The content of these warnings
* should be retrievable via a renderer-specific extension.
*/
unsigned warncount;
};
/** openerr extension information structure */
struct csri_openerr_ext {
/** csri_openerr_flag.custerr to string lookup.
* \param renderer the renderer handle.
* \param custerr renderer-specific error
* \param buffer buffer to fill with an UTF-8 error message.
* may be NULL; in that case only size is filled in
* \param size buffer size.\n
* in: maximum bytes to write to buffer, in bytes,
* including terminating \\0.\nthe renderer MUST always
* zero-terminate this, even when the space is not sufficient
* \n\n
* out: number of bytes (including terminating \\0) needed
* to return the full error message
*
* This function pointer may be NULL if the renderer does not
* return custom error codes. #CSRI_OPENERR_CUSTERR must not be
* used in that case.
*/
void (*strerror)(csri_rend *renderer, union csri_vardata custerr,
char *buffer, size_t *size);
};
/*@}*/
#ifdef __cplusplus
}
#endif
#endif /* _CSRI_OPENERR_H */

143
csri/include/csri/stream.h Normal file
View file

@ -0,0 +1,143 @@
/*****************************************************************************
* csri: common subtitle renderer interface
*****************************************************************************
* Copyright (C) 2007 David Lamparter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
****************************************************************************/
/** \file stream.h - subtitle streaming (MKV & co).
* $Id$
*
* <b>THE SPECIFICATION OF THIS EXTENSION IS TENTATIVE
* AND NOT FINALIZED YET</b>
*/
#ifndef _CSRI_STREAM_H
/** \cond */
#define _CSRI_STREAM_H 20070119
/** \endcond */
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup stream csri.stream.* extensions. */
/*@{*/
/** stream extension group.
* note: you cannot query for csri.stream, you need
* to query for one of the streaming formats instead,
* which will return a csri_stream_ext pointer.
*/
#define CSRI_EXT_STREAM (csri_ext_id)"csri.stream"
/** Matroska-style ASS streaming.
* header contains standard SSA stuff, packet contains
* ReadOrder,Layer,Style,Speaker,MarginL,R,V,Effect,Text
*/
#define CSRI_EXT_STREAM_ASS CSRI_EXT_STREAM ".ass"
/** Simple text + timestamp streams */
#define CSRI_EXT_STREAM_TEXT CSRI_EXT_STREAM ".text"
/* missing: USF, MPEG-4 TT */
/** stream extension information structure */
struct csri_stream_ext {
/** create streaming renderer instance.
* \param renderer the renderer handle.
* \param header codec-private stream header.
* \param headerlen byte length of header data.
* \param flags openflags.
*
* not NULL if this extension is supported.
* may take various flags like csri_openerr_flag.
*
* the returned instance can be used with
* csri_request_fmt, csri_render and csri_close.
*/
csri_inst *(*init_stream)(csri_rend *renderer,
const void *header, size_t headerlen,
struct csri_openflag *flags);
/** process a streamed packet.
* \param inst instance created with init_stream.
* \param packet stream packet data.
* \param packetlen byte length of packet.
* \param pts_start start timestamp from container.
* \param pts_end end timestamp from container.
*
* add a single packet to the renderer instance.
*/
void (*push_packet)(csri_inst *inst,
const void *packet, size_t packetlen,
double pts_start, double pts_end);
/** discard processed packets.
* \param inst instance created with init_stream.
* \param all discard possibly-active packets too.\n
* a possibly-active packet is a packet which
* has not seen a csri_render call with a pts
* beyond its end timestamp yet.
*
* frees up memory, or can force a clean renderer.
* may be NULL if unsupported, check before calling!
*/
void (*discard)(csri_inst *inst, int all);
};
/** streaming openflag ext for controlling subtitle lifetime */
#define CSRI_EXT_STREAM_DISCARD CSRI_EXT_STREAM ".discard"
/** subtitle packet lifetime */
enum csri_stream_discard {
/** lifetime: timestamp expiry.
* delete packets from csri_render if the current
* timestamp is beyond the packet's end timestamp.
* this should be the default
*/
CSRI_STREAM_DISCARD_TSEXPIRE = 0,
/** lifetime: discard immediately.
* discard all packets on returning from csri_render.
*/
CSRI_STREAM_DISCARD_IMMEDIATELY,
/** lifetime: discard explicitly.
* never discard packets, use csri_stream_ext.discard
*/
CSRI_STREAM_DISCARD_EXPLICIT
};
/** openflag for csri_stream_ext.init_stream */
struct csri_stream_discard_flag {
/** the lifetime to be used for subtitle packets */
enum csri_stream_discard lifetime;
};
/*@}*/
#ifdef __cplusplus
}
#endif
#endif /* _CSRI_STREAM_H */

114
csri/include/subhelp.h Normal file
View file

@ -0,0 +1,114 @@
/*****************************************************************************
* csri: common subtitle renderer interface
*****************************************************************************
* Copyright (C) 2007 David Lamparter
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
****************************************************************************/
/** \file subhelp.h - subtitle helper API.
* $Id$ */
#ifndef _SUBHELP_H
#define _SUBHELP_H
#include <stdarg.h>
#include <csri/csri.h>
#include <csri/logging.h>
/** \defgroup subhelp subtitle filter helper API. */
/*@{*/
/** file opening wrapper.
* can be used to implement csri_open_file() by using csri_open_mem().
* \param renderer the renderer handle
* \param memopenfunc function pointer to a csri_open_mem() implementation
* \param filename name of file to open
* \param flags pointer #csri_openflag.\n
* subhelp_open_file will fill in csri.openerr if present
* \return return value from memopenfunc or NULL on fs error
*/
extern csri_inst *subhelp_open_file(csri_rend *renderer,
csri_inst *(*memopenfunc)(csri_rend *renderer, const void *data,
size_t length, struct csri_openflag *flags),
const char *filename, struct csri_openflag *flags);
/** logging extension query function.
* call from csri_query_ext BEFORE checking whether the renderer.
* \code
* void *csri_query_ext(csri_rend *rend, csri_ext_id extname) {
* void *rv;
* if ((rv = subhelp_query_ext_logging(extname)))
* return rv;
* if (!rend)
* return NULL;
* ...
* \endcode
* \param extname the extension name. compared to "csri.logging" by
* this function.
* \return logging extension pointer, if the extension name matched.
* NULL otherwise.
*/
extern void *subhelp_query_ext_logging(csri_ext_id extname);
/** configure other renderer with our settings.
* \param logext csri.logging from configuree.
*/
extern void subhelp_logging_pass(struct csri_logging_ext *logext);
/** logging function.
* \param severity severity of this message, as defined by csri.logging
* \param msg log message, one line, without \\n at the end.
*/
extern void subhelp_log(enum csri_logging_severity severity,
const char *msg, ...)
#ifdef __GNUC__
__attribute__((format(printf, 2, 3)))
#endif
;
/** logging function, varargs version.
* \param severity severity of this message, as defined by csri.logging
* \param msg log message, one line, without \\n at the end.
* \param args argument list
*/
extern void subhelp_vlog(enum csri_logging_severity severity,
const char *msg, va_list args)
#ifdef __GNUC__
__attribute__((format(printf, 2, 0)))
#endif
;
/** logging function, fixed string version.
* \param severity severity of this message, as defined by csri.logging
* \param msg log message, one line, without \\n at the end.
*/
extern void subhelp_slog(enum csri_logging_severity severity, const char *msg);
/*@}*/
#endif /* _SUBHELP_H */

43
csri/include/visibility.h Normal file
View file

@ -0,0 +1,43 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifndef _VISIBILITY_H
#define _VISIBILITY_H
#ifdef HAVE_CONFIG_H
#include "acconf.h"
#endif
#ifdef _WIN32
#define export __declspec(dllexport)
#define internal
#define hidden
#elif HAVE_GCC_VISIBILITY
#define export __attribute__((visibility ("default")))
#define internal __attribute__((visibility ("internal")))
#define hidden __attribute__((visibility ("hidden")))
#else
#define export
#define internal
#define hidden
#endif
#endif /* _VISIBILITY_H */

14
csri/lib/Makefile.am Normal file
View file

@ -0,0 +1,14 @@
if BUILD_MINGW
PLATF = win32
else
PLATF = posix
AM_CPPFLAGS = -DCSRI_PATH="\"$(csri_path)\""
endif
lib_LTLIBRARIES = libcsri.la
noinst_HEADERS = csrilib.h posix/csrilib_os.h win32/csrilib_os.h
libcsri_la_SOURCES = list.c wrap.c $(PLATF)/enumerate.c
libcsri_la_CFLAGS = -I$(top_srcdir)/lib/posix -I$(top_srcdir)/include
libcsri_la_LIBADD = ../subhelp/libsubhelp_la-logging.lo
libcsri_la_LDFLAGS = -static
EXTRA_DIST = posix/enumerate.c win32/enumerate.c

85
csri/lib/csrilib.h Normal file
View file

@ -0,0 +1,85 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifndef _CSRILIB_H
#define _CSRILIB_H
#ifdef HAVE_CONFIG_H
#include "acconf.h"
#endif
#include "visibility.h"
#define CSRIAPI export
#include <csri/csri.h>
#include <csri/stream.h>
#include "csrilib_os.h"
struct csri_wrap_rend {
struct csri_wrap_rend *next;
csri_rend *rend;
csri_inst *(*open_file)(csri_rend *renderer,
const char *filename, struct csri_openflag *flags);
csri_inst *(*open_mem)(csri_rend *renderer,
const void *data, size_t length,
struct csri_openflag *flags);
void (*close)(csri_inst *inst);
int (*request_fmt)(csri_inst *inst, const struct csri_fmt *fmt);
void (*render)(csri_inst *inst, struct csri_frame *frame,
double time);
void *(*query_ext)(csri_rend *rend, csri_ext_id extname);
struct csri_stream_ext stream_ass, stream_text;
csri_inst *(*init_stream_ass)(csri_rend *renderer,
const void *header, size_t headerlen,
struct csri_openflag *flags);
csri_inst *(*init_stream_text)(csri_rend *renderer,
const void *header, size_t headerlen,
struct csri_openflag *flags);
struct csri_info *info;
struct csrilib_os os;
};
struct csri_wrap_inst {
struct csri_wrap_inst *next;
csri_inst *inst;
struct csri_wrap_rend *wrend;
void (*close)(csri_inst *inst);
int (*request_fmt)(csri_inst *inst, const struct csri_fmt *fmt);
void (*render)(csri_inst *inst, struct csri_frame *frame,
double time);
};
extern struct csri_wrap_rend *wraprends;
extern struct csri_wrap_rend *csrilib_rend_lookup(csri_rend *rend);
extern void csrilib_rend_initadd(struct csri_wrap_rend *wrend);
extern struct csri_wrap_inst *csrilib_inst_lookup(csri_inst *inst);
extern csri_inst *csrilib_inst_initadd(struct csri_wrap_rend *wrend,
csri_inst *inst);
extern void csrilib_inst_remove(struct csri_wrap_inst *winst);
extern void csrilib_os_init();
#endif /*_CSRILIB_H */

148
csri/lib/list.c Normal file
View file

@ -0,0 +1,148 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "csrilib.h"
struct csri_wrap_rend *wraprends = NULL;
struct csri_wrap_rend *csrilib_rend_lookup(csri_rend *rend)
{
struct csri_wrap_rend *wrap = wraprends;
for (; wrap; wrap = wrap->next)
if (wrap->rend == rend)
return wrap;
return NULL;
}
#define INSTHASHSZ 256
#define HASH(x) (((intptr_t)(x) & 0xff00) >> 8)
static struct csri_wrap_inst *wrapinsts[INSTHASHSZ];
struct csri_wrap_inst *csrilib_inst_lookup(csri_inst *inst)
{
struct csri_wrap_inst *ent = wrapinsts[HASH(inst)];
while (ent && ent->inst != inst)
ent = ent->next;
return ent;
}
csri_inst *csrilib_inst_initadd(struct csri_wrap_rend *wrend,
csri_inst *inst)
{
struct csri_wrap_inst *winst = (struct csri_wrap_inst *)
malloc(sizeof(struct csri_wrap_inst)),
**pnext;
if (!winst) {
wrend->close(inst);
return NULL;
}
winst->wrend = wrend;
winst->inst = inst;
winst->close = wrend->close;
winst->request_fmt = wrend->request_fmt;
winst->render = wrend->render;
winst->next = NULL;
pnext = &wrapinsts[HASH(inst)];
while (*pnext)
pnext = &(*pnext)->next;
*pnext = winst;
return inst;
}
void csrilib_inst_remove(struct csri_wrap_inst *winst)
{
struct csri_wrap_inst **pnext = &wrapinsts[HASH(winst->inst)];
while (*pnext && *pnext != winst)
pnext = &(*pnext)->next;
if (!*pnext)
return;
*pnext = (*pnext)->next;
}
void csrilib_rend_initadd(struct csri_wrap_rend *wrend)
{
wrend->next = wraprends;
wraprends = wrend;
}
static int initialized = 0;
csri_rend *csri_renderer_default()
{
if (!initialized) {
csrilib_os_init();
initialized = 1;
}
if (!wraprends)
return NULL;
return wraprends->rend;
}
csri_rend *csri_renderer_next(csri_rend *prev)
{
struct csri_wrap_rend *wrend = csrilib_rend_lookup(prev);
if (!wrend || !wrend->next)
return NULL;
return wrend->next->rend;
}
csri_rend *csri_renderer_byname(const char *name, const char *specific)
{
struct csri_wrap_rend *wrend;
if (!initialized) {
csrilib_os_init();
initialized = 1;
}
if (!name)
return NULL;
for (wrend = wraprends; wrend; wrend = wrend->next) {
if (strcmp(wrend->info->name, name))
continue;
if (specific && strcmp(wrend->info->specific, specific))
continue;
return wrend->rend;
}
return NULL;
}
csri_rend *csri_renderer_byext(unsigned n_ext, csri_ext_id *ext)
{
struct csri_wrap_rend *wrend;
unsigned i;
if (!initialized) {
csrilib_os_init();
initialized = 1;
}
for (wrend = wraprends; wrend; wrend = wrend->next) {
for (i = 0; i < n_ext; i++) {
if (!wrend->query_ext(wrend->rend, ext[i]))
break;
}
if (i == n_ext)
return wrend->rend;
}
return NULL;
}

View file

@ -0,0 +1,27 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <sys/types.h>
struct csrilib_os {
void *dlhandle;
dev_t device;
ino_t inode;
};

199
csri/lib/posix/enumerate.c Normal file
View file

@ -0,0 +1,199 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#define _POSIX_C_SOURCE 200112L /* for PATH_MAX */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
#include <dlfcn.h>
#include "../csrilib.h"
#include "subhelp.h"
static const char csri_path[] = CSRI_PATH;
static void csrilib_enum_dir(const char *dir);
static void csrilib_add(csri_rend *rend,
const struct csri_wrap_rend *tmp, struct csri_info *info)
{
struct csri_wrap_rend *wrend = (struct csri_wrap_rend *)
malloc(sizeof(struct csri_wrap_rend));
if (!wrend)
return;
memcpy(wrend, tmp, sizeof(struct csri_wrap_rend));
wrend->rend = rend;
wrend->info = info;
csrilib_rend_initadd(wrend);
}
static void csrilib_do_load(const char *filename, dev_t device, ino_t inode)
{
void *dlhandle = dlopen(filename, RTLD_NOW);
struct csri_wrap_rend tmp;
csri_rend *rend;
struct csri_info *(*renderer_info)(csri_rend *rend);
csri_rend *(*renderer_default)();
csri_rend *(*renderer_next)(csri_rend *prev);
const char *sym;
if (!dlhandle) {
subhelp_log(CSRI_LOG_WARNING, "dlopen(\"%s\") says: %s",
filename, dlerror());
return;
}
if (dlsym(dlhandle, "csri_library")) {
subhelp_log(CSRI_LOG_WARNING, "ignoring library %s",
filename);
return;
}
subhelp_log(CSRI_LOG_INFO, "loading %s", filename);
tmp.os.dlhandle = dlhandle;
tmp.os.device = device;
tmp.os.inode = inode;
/* okay, this is uber-ugly. either I end up casting from void *
* to a fptr (which yields a cast warning), or I do a *(void **)&tmp.x
* (which yields a strict-aliasing warning).
* casting via char* works because char* can alias anything.
*/
#define _dl_map_function(x, dst) do { \
char *t1 = (char *)&dst; \
union x { void *ptr; } *ptr = (union x *)t1; \
sym = "csri_" # x; \
ptr->ptr = dlsym(dlhandle, sym);\
if (!ptr->ptr) goto out_dlfail; } while (0)
#define dl_map_function(x) _dl_map_function(x, tmp.x)
dl_map_function(query_ext);
subhelp_logging_pass((struct csri_logging_ext *)
tmp.query_ext(NULL, CSRI_EXT_LOGGING));
dl_map_function(open_file);
dl_map_function(open_mem);
dl_map_function(close);
dl_map_function(request_fmt);
dl_map_function(render);
#define dl_map_local(x) _dl_map_function(x, x)
dl_map_local(renderer_info);
dl_map_local(renderer_default);
dl_map_local(renderer_next);
rend = renderer_default();
while (rend) {
csrilib_add(rend, &tmp, renderer_info(rend));
rend = renderer_next(rend);
}
return;
out_dlfail:
subhelp_log(CSRI_LOG_WARNING, "%s: symbol %s not found (%s)",
filename, sym, dlerror());
dlclose(dlhandle);
}
static void csrilib_load(const char *filename)
{
struct csri_wrap_rend *rend;
struct stat st;
if (stat(filename, &st))
return;
if (S_ISDIR(st.st_mode)) {
csrilib_enum_dir(filename);
return;
}
if (!S_ISREG(st.st_mode))
return;
if (access(filename, X_OK))
return;
for (rend = wraprends; rend; rend = rend->next)
if (rend->os.device == st.st_dev
&& rend->os.inode == st.st_ino)
return;
csrilib_do_load(filename, st.st_dev, st.st_ino);
}
static void csrilib_enum_dir(const char *dir)
{
DIR *dirh;
struct dirent *e;
char buf[PATH_MAX];
dirh = opendir(dir);
if (!dirh) {
subhelp_log(CSRI_LOG_WARNING, "ignoring directory \"%s\":"
" %s (%d)", dir, strerror(errno), errno);
return;
}
subhelp_log(CSRI_LOG_INFO, "scanning directory \"%s\"", dir);
while ((e = readdir(dirh))) {
if (e->d_name[0] == '.')
continue;
snprintf(buf, sizeof(buf), "%s/%s", dir, e->d_name);
csrilib_load(buf);
}
closedir(dirh);
}
static void csrilib_expand_enum_dir(const char *dir)
{
if (dir[0] == '~' && (dir[1] == '\0' || dir[1] == '/')) {
char buf[PATH_MAX], *home = getenv("HOME");
if (!home)
home = "";
snprintf(buf, sizeof(buf), "%s%s", home, dir + 1);
csrilib_enum_dir(buf);
} else
csrilib_enum_dir(dir);
}
void csrilib_os_init()
{
char buf[4096];
char *envpath = getenv("CSRI_PATH");
char *pos, *next = buf;
if (envpath)
snprintf(buf, sizeof(buf), "%s:%s", csri_path, envpath);
else {
strncpy(buf, csri_path, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
}
do {
pos = next;
next = strchr(pos, ':');
if (next)
*next++ = '\0';
csrilib_expand_enum_dir(pos);
} while (next);
}

View file

@ -0,0 +1,25 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <windows.h>
struct csrilib_os {
HMODULE dlhandle;
};

175
csri/lib/win32/enumerate.c Normal file
View file

@ -0,0 +1,175 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../csrilib.h"
#include "subhelp.h"
static void csrilib_enum_dir(const wchar_t *dir);
static const char *get_errstr()
{
static char msg[2048];
DWORD err = GetLastError();
if (!FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, err, 0, msg, sizeof(msg), NULL))
strcpy(msg, "Unknown Error");
else {
int msglen = strlen(msg) - 1;
if (msg[msglen] == '\n')
msg[msglen] = '\0';
}
return msg;
}
static void csrilib_add(csri_rend *rend,
const struct csri_wrap_rend *tmp, struct csri_info *info)
{
struct csri_wrap_rend *wrend = (struct csri_wrap_rend *)
malloc(sizeof(struct csri_wrap_rend));
if (!wrend)
return;
memcpy(wrend, tmp, sizeof(struct csri_wrap_rend));
wrend->rend = rend;
wrend->info = info;
csrilib_rend_initadd(wrend);
}
static void csrilib_do_load(const wchar_t *filename)
{
HMODULE dlhandle = LoadLibraryExW(filename, NULL,
LOAD_WITH_ALTERED_SEARCH_PATH);
struct csri_wrap_rend tmp;
csri_rend *rend;
struct csri_info *(*renderer_info)(csri_rend *rend);
csri_rend *(*renderer_default)();
csri_rend *(*renderer_next)(csri_rend *prev);
const char *sym;
if (!dlhandle) {
subhelp_log(CSRI_LOG_WARNING, "LoadLibraryEx(\"%ls\") failed: "
"%s", filename, get_errstr());
return;
}
if (GetProcAddress(dlhandle, "csri_library")) {
subhelp_log(CSRI_LOG_WARNING, "ignoring library %ls",
filename);
goto out_freelib;
}
subhelp_log(CSRI_LOG_INFO, "loading %ls", filename);
tmp.os.dlhandle = dlhandle;
/* okay, this is uber-ugly. either I end up casting from void *
* to a fptr (which yields a cast warning), or I do a *(void **)&tmp.x
* (which yields a strict-aliasing warning).
* casting via char* works because char* can alias anything.
*/
#define _dl_map_function(x, dst) do { \
char *t1 = (char *)&dst; \
union x { FARPROC ptr; } *ptr = (union x *)t1; \
sym = "csri_" # x; \
ptr->ptr = GetProcAddress(dlhandle, sym);\
if (!ptr->ptr) goto out_dlfail; } while (0)
#define dl_map_function(x) _dl_map_function(x, tmp.x)
dl_map_function(query_ext);
subhelp_logging_pass((struct csri_logging_ext *)
tmp.query_ext(NULL, CSRI_EXT_LOGGING));
dl_map_function(open_file);
dl_map_function(open_mem);
dl_map_function(close);
dl_map_function(request_fmt);
dl_map_function(render);
#define dl_map_local(x) _dl_map_function(x, x)
dl_map_local(renderer_info);
dl_map_local(renderer_default);
dl_map_local(renderer_next);
rend = renderer_default();
while (rend) {
csrilib_add(rend, &tmp, renderer_info(rend));
rend = renderer_next(rend);
}
return;
out_dlfail:
subhelp_log(CSRI_LOG_WARNING, "%ls: symbol %s not found (%s)",
filename, sym, get_errstr());
out_freelib:
FreeLibrary(dlhandle);
}
static void csrilib_load(const wchar_t *filename)
{
DWORD attr = GetFileAttributesW(filename);
if (attr == INVALID_FILE_ATTRIBUTES)
return;
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
csrilib_enum_dir(filename);
return;
}
csrilib_do_load(filename);
}
static void csrilib_enum_dir(const wchar_t *dir)
{
WIN32_FIND_DATAW data;
HANDLE res;
wchar_t buf[MAX_PATH];
_snwprintf(buf, sizeof(buf) / sizeof(buf[0]), L"%ls\\*", dir);
res = FindFirstFileW(buf, &data);
if (res == INVALID_HANDLE_VALUE) {
subhelp_log(CSRI_LOG_WARNING, "ignoring directory \"%ls\": %s",
dir, get_errstr());
return;
}
subhelp_log(CSRI_LOG_INFO, "scanning directory \"%ls\"", dir);
do {
if (data.cFileName[0] == '.')
continue;
_snwprintf(buf, sizeof(buf) / sizeof(buf[0]),
L"%ls\\%ls", dir, data.cFileName);
csrilib_load(buf);
} while (FindNextFileW(res, &data));
FindClose(res);
}
void csrilib_os_init()
{
wchar_t filename[MAX_PATH], *slash;
DWORD rv = GetModuleFileNameW(NULL, filename, MAX_PATH);
if (!rv)
*filename = L'\0';
slash = wcsrchr(filename, L'\\');
slash = slash ? slash + 1 : filename;
*slash = L'\0';
wcsncpy(slash, L"csri", filename + MAX_PATH - slash);
csrilib_enum_dir(filename);
}

118
csri/lib/wrap.c Normal file
View file

@ -0,0 +1,118 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include "csrilib.h"
#include "subhelp.h"
#include <string.h>
csri_inst *csri_open_file(csri_rend *rend,
const char *filename, struct csri_openflag *flags)
{
struct csri_wrap_rend *wrend = csrilib_rend_lookup(rend);
if (!wrend)
return NULL;
return csrilib_inst_initadd(wrend,
wrend->open_file(rend, filename, flags));
}
#define instance_wrapper(wrapname, funcname) \
csri_inst *wrapname(csri_rend *rend, \
const void *data, size_t length, struct csri_openflag *flags) \
{ \
struct csri_wrap_rend *wrend = csrilib_rend_lookup(rend); \
if (!wrend) \
return NULL; \
return csrilib_inst_initadd(wrend, \
wrend->funcname(rend, data, length, flags)); \
}
instance_wrapper(csri_open_mem, open_mem)
static instance_wrapper(wrap_init_stream_ass, init_stream_ass)
static instance_wrapper(wrap_init_stream_text, init_stream_text)
void *csri_query_ext(csri_rend *rend, csri_ext_id extname)
{
struct csri_wrap_rend *wrend;
void *rv;
if (!rend && (rv = subhelp_query_ext_logging(extname)))
return rv;
wrend = csrilib_rend_lookup(rend);
if (!wrend)
return NULL;
rv = wrend->query_ext(rend, extname);
if (rv && !strcmp(extname, CSRI_EXT_STREAM_ASS)) {
struct csri_stream_ext *e = (struct csri_stream_ext *)rv;
memcpy(&wrend->stream_ass, e, sizeof(*e));
wrend->init_stream_ass = e->init_stream;
wrend->stream_ass.init_stream = wrap_init_stream_ass;
return &wrend->stream_ass;
}
if (rv && !strcmp(extname, CSRI_EXT_STREAM_TEXT)) {
struct csri_stream_ext *e = (struct csri_stream_ext *)rv;
memcpy(&wrend->stream_text, e, sizeof(*e));
wrend->init_stream_text = e->init_stream;
wrend->stream_text.init_stream = wrap_init_stream_text;
return &wrend->stream_text;
}
return rv;
}
struct csri_info *csri_renderer_info(csri_rend *rend)
{
struct csri_wrap_rend *wrend = csrilib_rend_lookup(rend);
if (!wrend)
return NULL;
return wrend->info;
}
void csri_close(csri_inst *inst)
{
struct csri_wrap_inst *winst = csrilib_inst_lookup(inst);
if (!winst)
return;
winst->close(inst);
csrilib_inst_remove(winst);
}
int csri_request_fmt(csri_inst *inst, const struct csri_fmt *fmt)
{
struct csri_wrap_inst *winst = csrilib_inst_lookup(inst);
if (!winst)
return 0;
return winst->request_fmt(inst, fmt);
}
void csri_render(csri_inst *inst, struct csri_frame *frame,
double time)
{
struct csri_wrap_inst *winst = csrilib_inst_lookup(inst);
if (!winst)
return;
winst->render(inst, frame, time);
}
const char *csri_library()
{
return "DEV";
}

10
csri/subhelp/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
if BUILD_MINGW
PLATF = win32
else
PLATF = posix
endif
noinst_LTLIBRARIES = libsubhelp.la
libsubhelp_la_SOURCES = $(PLATF)/openfile.c logging.c
libsubhelp_la_CFLAGS = -I$(top_srcdir)/include
EXTRA_DIST = win32/openfile.c posix/openfile.c

102
csri/subhelp/logging.c Normal file
View file

@ -0,0 +1,102 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "acconf.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "visibility.h"
#include "subhelp.h"
#include <csri/logging.h>
static void *appdata = NULL;
static csri_logging_func *logfunc = NULL;
void setlogcallback(csri_logging_func *_logfunc, void *_appdata) hidden;
void setlogcallback(csri_logging_func *_logfunc, void *_appdata)
{
logfunc = _logfunc;
appdata = _appdata;
}
static struct csri_logging_ext logext = {
setlogcallback
};
void subhelp_logging_pass(struct csri_logging_ext *nlogext)
{
if (!nlogext || !nlogext->set_logcallback)
return;
nlogext->set_logcallback(logfunc, appdata);
}
void *subhelp_query_ext_logging(csri_ext_id extname)
{
if (strcmp(extname, CSRI_EXT_LOGGING))
return NULL;
return &logext;
}
void subhelp_log(enum csri_logging_severity severity, const char *msg, ...)
{
va_list args;
va_start(args, msg);
subhelp_vlog(severity, msg, args);
va_end(args);
}
void subhelp_vlog(enum csri_logging_severity severity,
const char *msg, va_list args)
{
char *buffer;
const char *final;
size_t size = 256;
int n;
buffer = (char *)malloc(256);
while (buffer) {
n = vsnprintf(buffer, size, msg, args);
if (n >= 0 && (unsigned)n < size)
break;
size = n > 0 ? (unsigned)n + 1 : size * 2;
buffer = (char *)realloc(buffer, size);
}
final = buffer ? buffer : "<out of memory in logging function>";
subhelp_slog(severity, final);
if (buffer)
free(buffer);
}
void subhelp_slog(enum csri_logging_severity severity, const char *msg)
{
if (logfunc)
logfunc(appdata, severity, msg);
else {
fprintf(stderr, msg);
fprintf(stderr, "\n");
}
}

View file

@ -0,0 +1,82 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#ifdef HAVE_CONFIG_H
#include "acconf.h"
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "subhelp.h"
#include <csri/openerr.h>
csri_inst *subhelp_open_file(csri_rend *renderer,
csri_inst *(*memopenfunc)(csri_rend *renderer, const void *data,
size_t length, struct csri_openflag *flags),
const char *filename, struct csri_openflag *flags)
{
csri_inst *rv = NULL;
void *data;
int fd;
struct stat st;
struct csri_openflag *err;
fd = open(filename, O_RDONLY);
if (fd == -1)
goto out_err;
if (fstat(fd, &st)
|| !(data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE,
fd, 0))) {
close(fd);
goto out_err;
}
rv = memopenfunc(renderer, data, st.st_size, flags);
munmap(data, st.st_size);
close(fd);
return rv;
out_err:
for (err = flags; err; err = err->next)
if (!strcmp(err->name, CSRI_EXT_OPENERR))
break;
if (err) {
struct csri_openerr_flag *errd = (struct csri_openerr_flag *)
err->data.otherval;
errd->flags = CSRI_OPENERR_FILLED | CSRI_OPENERR_ERRNO;
errd->posixerrno = errno;
}
return NULL;
}

View file

@ -0,0 +1,84 @@
/*****************************************************************************
* asa: portable digital subtitle renderer
*****************************************************************************
* Copyright (C) 2007 David Lamparter
*
* 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA
****************************************************************************/
#include <windows.h>
#include <string.h>
#include "subhelp.h"
#include <csri/openerr.h>
csri_inst *subhelp_open_file(csri_rend *renderer,
csri_inst *(*memopenfunc)(csri_rend *renderer, const void *data,
size_t length, struct csri_openflag *flags),
const char *filename, struct csri_openflag *flags)
{
csri_inst *rv = NULL;
void *data;
struct csri_openflag *err;
HANDLE file, mapping;
DWORD size;
int namesize;
wchar_t *namebuf;
namesize = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
if (!namesize)
goto out_err;
namesize++;
namebuf = malloc(sizeof(wchar_t) * namesize);
MultiByteToWideChar(CP_UTF8, 0, filename, -1, namebuf, namesize);
file = CreateFileW(namebuf, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
free(namebuf);
if (file == INVALID_HANDLE_VALUE)
goto out_err;
size = GetFileSize(file, NULL);
if (size == INVALID_FILE_SIZE || !size)
goto out_closefile;
mapping = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL);
if (!mapping)
goto out_closefile;
data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, size);
if (!data)
goto out_closemap;
rv = memopenfunc(renderer, data, size, flags);
UnmapViewOfFile(data);
CloseHandle(mapping);
CloseHandle(file);
return rv;
out_closemap:
CloseHandle(mapping);
out_closefile:
CloseHandle(file);
out_err:
for (err = flags; err; err = err->next)
if (!strcmp(err->name, CSRI_EXT_OPENERR))
break;
if (err) {
struct csri_openerr_flag *errd = err->data.otherval;
errd->flags = CSRI_OPENERR_FILLED | CSRI_OPENERR_WINERR;
errd->winerr = GetLastError();
}
return NULL;
}