server-2.2.0-stable/000077500000000000000000000000001341175263200142755ustar00rootroot00000000000000server-2.2.0-stable/.clang-format000066400000000000000000000056221341175263200166550ustar00rootroot00000000000000--- # TODO BreakBeforeLambdaBody # TODO IncludeBlocks Language: Cpp AccessModifierOffset: -2 AlignAfterOpenBracket: Align AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: true AlignEscapedNewlines: Right AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false AlwaysBreakTemplateDeclarations: true BinPackArguments: false BinPackParameters: false BreakBeforeBraces: Custom BraceWrapping: AfterClass: true AfterControlStatement: false AfterEnum: true AfterFunction: true AfterNamespace: false AfterObjCDeclaration: false AfterStruct: true AfterUnion: true #AfterExternBlock: true BeforeCatch: false BeforeElse: false IndentBraces: false SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true BreakBeforeBinaryOperators: None BreakBeforeInheritanceComma: true BreakBeforeTernaryOperators: true BreakConstructorInitializersBeforeComma: true BreakConstructorInitializers: BeforeColon BreakAfterJavaFieldAnnotations: false BreakStringLiterals: true ColumnLimit: 120 CommentPragmas: '^ IWYU pragma:' CompactNamespaces: true ConstructorInitializerAllOnOneLineOrOnePerLine: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true DerivePointerAlignment: false DisableFormat: false ExperimentalAutoDetectBinPacking: false FixNamespaceComments: true ForEachMacros: - foreach - Q_FOREACH - BOOST_FOREACH IncludeCategories: - Regex: '^"(llvm|llvm-c|clang|clang-c)/' Priority: 2 - Regex: '^(<|"(gtest|gmock|isl|json)/)' Priority: 3 - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' IndentCaseLabels: true #IndentPPDirectives: None IndentWidth: 4 IndentWrappedFunctionNames: false KeepEmptyLinesAtTheStartOfBlocks: false MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 NamespaceIndentation: None PenaltyBreakAssignment: 2 PenaltyBreakBeforeFirstCallParameter: 19 PenaltyBreakComment: 300 PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left #RawStringFormats: # - Delimiter: pb # Language: TextProto # BasedOnStyle: google ReflowComments: true SortIncludes: true SortUsingDeclarations: true SpaceAfterCStyleCast: false SpaceAfterTemplateKeyword: true SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: false SpacesInContainerLiterals: true SpacesInCStyleCastParentheses: false SpacesInParentheses: false SpacesInSquareBrackets: false Standard: Cpp11 UseTab: Never ... server-2.2.0-stable/.dockerignore000066400000000000000000000001451341175263200167510ustar00rootroot00000000000000src/packages src/cmake-build-* build-scripts build resources .git .vscode CMakeFiles casparcg_server server-2.2.0-stable/.editorconfig000066400000000000000000000002231341175263200167470ustar00rootroot00000000000000root = true [*] charset = utf-8 indent_style = space indent_size = 4 end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true server-2.2.0-stable/.github/000077500000000000000000000000001341175263200156355ustar00rootroot00000000000000server-2.2.0-stable/.github/ISSUE_TEMPLATE/000077500000000000000000000000001341175263200200205ustar00rootroot00000000000000server-2.2.0-stable/.github/ISSUE_TEMPLATE/bug_report.md000066400000000000000000000007411341175263200225140ustar00rootroot00000000000000--- name: Bug report about: Create a report to help us improve --- ### Expected behaviour A clear and concise description of what you expected to happen. ### Current behaviour A clear and concise description of what the current behaviour is. ---- ### Steps to reproduce 1. 2. 3. ... ### Environment * Commit: [e.g. ab1234c] * Server version: [e.g. v2.2] * Operating system: [e.g. Windows 10] --- ### Screenshots If applicable, add screenshots as complementary information. server-2.2.0-stable/.github/ISSUE_TEMPLATE/feature_request.md000066400000000000000000000005631341175263200235510ustar00rootroot00000000000000--- name: Feature request about: Suggest an idea for this project --- ### Description A clear and concise description describing to us how your feature/enhancement request should work. ### Solution suggestion A clear and concise description if you have an idea about a solution. --- ### Additional information If you have some additional information or attachments. server-2.2.0-stable/.gitignore000066400000000000000000000002031341175263200162600ustar00rootroot00000000000000*.dir *.vcxproj *.vcxproj.filters *.tlog *.sln .settings .vscode .vs build CMakeFiles casparcg_server src/cmake-build-* src/.idea server-2.2.0-stable/BUILDING.md000066400000000000000000000056011341175263200160160ustar00rootroot00000000000000Building the CasparCG Server ============================ The CasparCG Server source code uses the CMake build system in order to easily generate build systems for multiple platforms. CMake is basically a build system for generating build systems. On Windows we can use CMake to generate a .sln file and .vcproj files. On Linux CMake can generate make files or ninja files. Qt Creator has support for loading CMakeLists.txt files directly. Windows ======= Development using Visual Studio ------------------------------- 1. Install Visual Studio 2017. 2. Install CMake (http://www.cmake.org/download/). 3. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master` 4. `cd casparcg-server-master` 5. `mkdir build` 6. `cd build` 7. `cmake -G "Visual Studio 15 2017" -A x64 ../src` 8. Open `CasparCG Server.sln` Linux ===== Building inside Docker ---------------------- 1. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master` 2. `cd casparcg-server-master` 3. `./tools/linux/build-in-docker` If all goes to plan, a docker image `casparcg/server` has been created containing CasparCG Server. Extracting CasparCG Server from Docker -------------------------------------- 1. `./tools/linux/extract-from-docker` You will then find a folder called `casparcg_server` which should contain everything you need to run CasparCG Server. _Note: if you ran docker with sudo, CasparCG server will not be able to run without sudo out of the box. For security reasons we do not recommend to run CasparCG with sudo. Instead you can use chown to change the ownership of the CasparCG Server folder._ Development ----------- 1. Install dependencies `apt-get install git cmake build-essential g++ libglew-dev libfreeimage-dev libtbb-dev libsndfile1-dev libopenal-dev libjpeg-dev libfreetype6-dev libglfw3-dev libxcursor-dev libxinerama-dev libxi-dev libsfml-dev libvpx-dev libwebp-dev liblzma-dev libfdk-aac-dev libmp3lame-dev libopus-dev libtheora-dev libx264-dev libx265-dev libbz2-dev libssl-dev libcrypto++-dev librtmp-dev libgmp-dev libxcb-shm0-dev libass-dev libgconf2-dev` 2. Install Docker by following installation instructions from [Docker Docs][1] 3. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master` 4. `cd casparcg-server-master` 5. Extract Boost, FFmpeg and CEF from the docker images via `sudo ./tools/linux/extract-deps-from-docker`. Alternatively these can be prepared manually by following the steps laid out in each Dockerfile 6. `mkdir build && cd build` 7. `cmake ../src` 8. `make -j8` If all goes to plan, a folder called 'staging' has been created with everything you need to run CasparCG server. [1]: https://docs.docker.com/install/linux/docker-ce/ubuntu/ Build options ------------- -DENABLE_HTML=OFF - useful if you lack CEF, and would like to build without that module. server-2.2.0-stable/CHANGELOG.md000066400000000000000000001452261341175263200161200ustar00rootroot00000000000000CasparCG 2.2.0 Beta ========================================== General ------- * C++14 * Major refactoring, cleanup, optimization and stability improvements. * Removed unmaintained documentation API. * Removed unmaintained program options API. * Removed unused frame age API. * Removed misc unused and/or unmaintained APIs. * Removed TCP logger. * Fixed memory leak in transition producer. * Removed PSD Producer (moved to 3.0.0). * Removed Text Producer (moved to 3.0.0). * Removed SyncTo consumer. * Removed channel layout in favor of 8 channel passthrough and FFMPEG audio filters. * Major stability and performance improvements of GPU code. * Requires OpenGL 4.5. * Repo cleanup (>2GB => <100MB when cloning). * Misc cleanup and fixes. Build ----- * Linux build re done with Docker. * Windows build re done with Nuget. HTML ---- * Updated to Chromium 63 (Julusian). * Allow running templates from arbitrary urls (Julusian). DECKLINK -------- * Fixed broken Linux. * Misc cleanup and fixes. * Complex FFMPEG filters (VF, AF). MIXER ----- * Performance improvements. * Removed straight output (moved to 3.0.0). * Proper OpenGL pipelining. * Blend modes are always enabled. * Misc cleanup and fixes. * Removed CPU mixer. * Mixer always runs in progressive mode. Consumers are expected to convert to interlaced if required. IMAGE ----- * Correctly apply alpha to base64 encoded pngs from AMCP (Julusian). * Unmultiply frame before writing to png (Julusian). * Removed scroll producer (moved to 3.0.0) ROUTE ----- * Reimplemented, simplified. * Cross channel routing will render full stage instead of simply copying channel output. * Reduced overhead and latency. FFMPEG ------ * Rewritten from scratch for better accuracy, stability and performance. * Update freezed frame during seeking. * FFMPEG 3.4.1. * Reduce blocking during initialization. * Fixed timestamp handling. * Fixed V/A sync. * Fixed interlacing. * Fixed framerate handling. * Fixed looping. * Fixed seeking. * Fixed duration. * Audio resampling to match timestamps. * Fixed invalid interlaced YUV (411, 420) handling. * Added YUV(A)444. * Added IO timeout. * Added HTTP reconnect. * FFMPEG video filter support. * FFMPEG audio filter support. * Complex FFMPEG filters (VF, AF). * CALL SEEK return actually seeked value. * All AMCP options are based on channel format. * Misc improvements, cleanup and fixes. Bluefish -------- * Bluefish Consumer removed (moved to 3.0.0). OAL ------------ * Added audio sample compensation to avoid audio distortions during time drift. * Misc cleanup and fixes. Screen --------------- * Proper OpenGL pipelining. * Misc cleanup and fixes. AMCP ---- * Added PING command (Julusian). * Removed INFO commands in favor of OSC. * Moved CLS, CINF, TLS, FLS, TLS, THUMBNAIL implementations into a separate NodeJS service which is proxied through an HTTP API. * Misc cleanup and fixes. CasparCG 2.1.0 Next (w.r.t 2.1.0 Beta 2) ========================================== General ------- * Removed asmlib dependency in favor of using standard library std::memcpy and std::memset, because of better performance. CasparCG 2.1.0 Beta 2 (w.r.t 2.1.0 Beta 1) ========================================== General ------- * Fail early with clear error message if configured paths are not creatable/writable. * Added backwards compatibility (with deprecation warning) for using thumbnails-path instead of thumbnail-path in casparcg.config. * Suppress the logging of full path names in stack traces so that only the relative path within the source tree is visible. * General stability improvements. * Native thread id is now logged in Linux as well. Finally they are mappable against INFO THREADS, ps and top. * Created automatically generated build number, so that it is easier to see whether a build is newer or older than an other. * Changed configuration element mipmapping_default_on to mipmapping-default-on for consistency with the rest of the configuration (Jesper Stærkær). * Handle stdin EOF as EXIT. * Added support for RESTART in Linux startup script run.sh. * Copy casparcg_auto_restart.bat into Windows releases. * Fixed bug with thumbnail generation when there are .-files in the media folder. * Removed CMake platform specification in Linux build script (Krzysztof Pyrkosz). * Build script for building FFmpeg for Linux now part of the repository. Contributions during development (not w.r.t 2.1.0 Beta 1): * Fix ffmpeg build dependencies on clean Ubuntu desktop amd64 14.04.3 or higher (Walter Sonius). * Added support for video modes 2160p5000, 2160p5994 and 2160p6000 (Antonio Ruano Cuesta). * Fixed serious buffer overrun in FFmpeg logging code. Consumers --------- * FFmpeg consumer: * Fixed long overdue bug where HD material was always recorded using the BT.601 color matrix instead of the BT.709 color matrix. RGB codecs like qtrle was never affected but all the YCbCr based codecs were. * Fixed bug in parsing of paths containing -. * Fixed bugs where previously effective arguments like -pix_fmt were ignored. * Fixed bug where interlaced channels where not recorded correctly for some codecs. * DeckLink consumer: * Rewrote the frame hand-off between send() and ScheduledFrameCompleted() in a way that hopefully resolves all dead-lock scenarios previously possible. * Bluefish consumer: * Largely rewritten against newest SDK Driver 5.11.0.47 (Satchit Nambiar and James Wise sponsored by Bluefish444): * Added support for Epoch Neutron and Supernova CG. All current Epoch cards are now supported. * Added support for for multiple SDI channels per card. 1 to 4 channels per Bluefish444 card depending on model and firmware. * Added support for single SDI output, complementing existing external key output support. * Added support for internal key using the Bluefish444 hardware keyer. * Screen consumer: * Fixed full screen mode. Producers --------- * FFmpeg producer: * Increased the max number of frames that audio/video can be badly interleaved with (Dimitry Ishenko). * Fixed bug where decoders sometimes requires more than one video packet to decode the first frame. * Added support for IN and OUT parameters (Dimitry Ishenko). * Added DV/HDV video device support under Linux (Walter Sonius). * Remove unused flags variable in queued_seek (Dimitry Ishenko). * Now recognizes .ts files without probing contents (Ovidijus Striaukas). * Fixed uninitialized value causing initial log printout to usually say that clips are interlaced when they are not. * Destroy producer proxy: * Created workaround for bug in FFmpeg where every new thread used to cleanup caused handles to leak (not sure why). Reduced the effect by using only one thread for all producer destructions. * Framerate producer: * Fixed bug when INFO was used on a not yet playing framerate producer. * HTML producer: * Fixed bug where only URL:s with . in them where recognized. * Image producer: * Added LENGTH parameter to allow for queueing with LOADBG AUTO. * Fixed inconsistency in what file extensions are supported vs listed in CLS/CINF. * Layer producer: * Fixed serious bug where a circular reference of layer producers caused a stack overflow and server crash. * Can now route from layer on a channel with an incompatible framerate. * Channel producer: * Can now route from channel with an incompatible framerate. * Deinterlaces interlaced content from source channel. * Added optional NO_AUTO_DEINTERLACE parameter to opt out of the mentioned deinterlacing. * Scene producer: * Added abs(), floor(), to_lower(), to_upper() and length() functions to the expression language. * Created XML Schema for the *.scene XML format. Allows for IDE-like auto- completion, API documentation and validation. * Added possibility to specify the width and height of a layer instead of letting the producer on the layer decide. * Added global variables scene_width, scene_height and fps. * Made it possible to use expressions in keyframe values. * Fixed serious bug where uninitialized values were used. * Created more example scenes. * Can now forward CALL, CG PLAY, CG STOP, CG NEXT and CG INVOKE to the producer on a layer. * CG proxy wrapper producer: * New in 2.1.0. * Allows all CG producers to be used as an ordinary producer inside a layer in a scene. * Allows the Scene producer to know what variables are available in a template. * Color producer: * Now has support for gradients. * PSD producer: * Added support for centered and right justified text. * Text producer: * Fixed bug where tracking contributed to the overall text width on the last character. Mixer ----- * Fixed bug in the contrast/saturation/brightness code where the wrong luma coefficients was used. * Rewrote the chroma key code to support variable hue, instead of fixed green or blue. Threshold setting was removed in favour of separate hue width, minimum saturation and minimum brightness constraints. Also a much more effective spill suppression method was implemented. * Fixed bug where glReadPixels() was done from the last drawn to texture instead of always from the target texture. This means that for example a MIXER KEYER layer without a layer above to key, as well as a separate alpha file with MIXER OPACITY 0 now works as expected. * Fixed bug where already drawn GL_QUADS were not composited against, causing for example italic texts to be rendered incorrectly in the text_producer. AMCP ---- * INFO PATHS now adds all the path elements even if they are using the default values. * MIXER CHROMA syntax deprecated (still supported) in favour of the more advanced syntax required by the rewritten chroma key code. * Added special command REQ that can be prepended before any command to identify the response with a client specified request id, allowing a client to know exactly what asynchronous response matched a specific request. * Added support for listing contents of a specific directory for CLS, TLS, DATA LIST and THUMBNAIL LIST. * Fixed bug where CINF only returned the first match. * Fixed bug where a client closing the connection after BYE instead of letting the server close the connection caused an exception to be logged. CasparCG 2.1.0 Beta 1 (w.r.t 2.0.7 Stable) ========================================== General ------- * 64 bit! * Linux support! * Moved to CMake build system for better platform independence. * Contributions before build system switch (not w.r.t 2.0.7 Stable): * gitrev.bat adaptions for 2.1 (Thomas Kaltz III). * Thanks to our already heavy use of the pimpl idiom, abstracting platform specifics was easily done by having different versions of the .cpp files included in the build depending on target platform. No #ifdef necessary, except for in header only platform specific code. * Flash, Bluefish and NewTek modules are not ported to the Linux build. * Contributions during development (not w.r.t 2.0.7 Stable): * Fixed compilation problems in Linux build (Dimitry Ishenko). * Fixed compilation problem in GCC 5 (Krzysztof Pyrkosz). * Fixed thumbnail image saving on Linux (Krzysztof Pyrkosz). * Fixed compilation problem in PSD module (Krzysztof Pyrkosz). * Major code refactoring: * Mixer abstraction so different implementations can be created. Currently CPU mixer and GPU mixer (previously the usage of the GPU was mandatory) exists. * Flattened folder structure for easier inclusion of header files. * Many classes renamed to better describe the abstractions they provide. * Sink parameters usually taken by value and moved into place instead of taken by const reference as previously done. * Old Windows specific AsyncEventServer class has been replaced by platform independent implementation based on Boost.Asio. * Pimpl classes are now stack allocated with internal shared_ptr to implementation, instead of both handle and body being dynamically allocated. This means that objects are now often passed by value instead of via safe_ptr/shared_ptr, because they are internally reference counted. * Protocol strategies are now easier to implement correctly, because of separation of state between different client connections. * Complete AMCP command refactoring. * On-line help system that forces the developer to document AMCP commands, producer syntaxes and consumer syntaxes making the documentation coupled to the code, which is great. * Added missing help for VERSION command (Jesper Stærkær). * Upgraded Windows build to target Visual Studio 2015 making it possible to use the C++11 features also supported by GCC 4.8 which is targeted on Linux. * Fixed compilation problems in Visual Studio 2015 Update 1 (Roman Tarasov) * Created abstraction of the different forms of templates (flash, html, psd and scene). Each module registers itself as a CG producer provides. All CG commands transparently works with all of them. * Audio mixer now uses double samples instead of float samples to fully accommodate all int32 samples. * Reduced coupling between core and modules (and modules and modules): * Modules can register system info providers to contribute to INFO SYSTEM. * XML configuration factories for adding support for new consumer elements in casparcg.config. * Server startup hooks can be registered (used by HTML producer to fork its sub process). * Version providers can contribute content to the VERSION command. * Refactored multichannel audio support to use FFmpeg's PAN filter and simplified the configuration a lot. * Upgraded most third party libraries we depend on. * Some unit tests have been created. * Renamed README.txt to README, CHANGES.txt to CHANGELOG and LICENSE.txt to LICENSE * Created README.md for github front page in addition to README which is distributed with builds. * README file updates (Jonas Hummelstrand). * Created BUILDING file describing how to build the server on Windows and Linux. * Diagnostics: * Now also sent over OSC. * Diag window is now scrollable and without squeezing of graphs. * Contextual information such as video channel and video layer now included in graphs. * Logging: * Implemented a TCP server, simply sending every log line to each connected client. Default port is 3250. * Changed default log level to info and moved debug statements that are interesting in a production system to info. * Try to not log full stack traces when user error is the cause. Stacktraces should ideally only be logged when a system error or a programming error has occurred. * More contextual information about an error added to exceptions. An example of this is that XML configuration errors now cause the XPath of the error is logged. * Improved the readability of the log format. * Added optional calltrace.log for logging method calls. Allows for trace logging to be enabled while calltracing is disabled etc. OSC --- * Improved message formatting performance. * Added possibility to disable sending OSC to connected AMCP clients. * Fixed inconsistent element name predefined_client to predefined-client in casparcg.config (Krzysztof Pyrkosz). Consumers --------- * System audio consumer: * Pushes data to openal instead of being callbacked by SFML when data is needed. * Added possibility to specify the expected delay in the sound card. Might help get better consumer synchronization. * Screen consumer: * Added mouse interaction support, usable by the producers running on the video channel. * FFmpeg consumer: * Replaced by Streaming Consumer after it was adapted to support everything that FFmpeg Consumer did. * Added support for recording all audio channels into separate mono audio streams. * Now sends recording progress via OSC. * SyncTo consumer: * New in 2.1.0. * Allows the pace of a channel to follow another channel. This is useful for virtual "precomp" channels without a DeckLink consumer to pace it. * DeckLink consumer: * Added workaround for timescale bug found in Decklink SDK 10.7. * Now ScheduledFrameCompleted is no longer only used for video scheduling but for audio as well, simplifying the code a lot. * iVGA consumer: * No longer provides sync to the video channel. * Supports NewTek NDI out of the box just by upgrading the Processing.AirSend library. Producers --------- * Scene producer: * New in 2.1.0. * Utilizes CasparCG concepts such as producers, mixer transforms and uses them in a nested way to form infinite number of sub layers. Think movie clip in Flash. * A scene consists of variables, layers, timelines and marks (intro and outro for example). * Mostly for use by other producers but comes with a XML based producer that is a registered CG producer and shows up in TLS. * Enables frame accurate compositions and animations. * Has a powerful variable binding system (think expressions in After Effects or JavaFX Bindings). * PSD producer: * New in 2.1.0. * Parses PSD files and sets up a scene for the Scene producer to display. * Text layers based on CG parameters. * Supports Photoshop timeline. * Uses Photoshop comment key-frames to describe where intro and outro (CG PLAY and CG STOP) should be in the timeline. * Shows up as regular templates in TLS. * Text producer: * New in 2.1.0. * Renders text using FreeType library. * Is used by the PSD producer for dynamic text layers. * Image scroll producer: * Speed can be changed while running using a CALL. The speed change can be tweened. * Added support for an absolute end time so that the duration is calculated based on when PLAY is called for shows when an exact end time is important. * Image producer: * Fixed bug where too large (OpenGL limit) images were accepted, causing problems during thumbnail generation. * Framerate producer: * New in 2.1.0. * Wraps a producer with one framerate and converts it to another. It is not usable on its own but is utilized in the FFmpeg producer and the DeckLink consumer. * Supports different interpolation algorithms. Currently a no-op drop-and-repeat mode and a two different frame blending modes. * It also supports changing the speed on demand with tweening support. * FFmpeg producer: * Supports decoding all audio streams from a clip. Useful with .mxf files which usually have separate mono streams for every audio channel. * No longer do framerate conversion (half or double), but delegates that task to the Framerate producer. * Added support for v4l2 devices. * Added relative and "from end" seeking (Dimitry Ishenko). * Contributions during development (not w.r.t 2.0.7 Stable): * Fixed 100% CPU problem on clip EOF (Peter Keuter, Robert Nagy). * Constrained SEEK within the length of a clip (Dimitry Ishenko). * Fixed a regular expression (Dimitry Ishenko). * DeckLink producer: * No longer do framerate conversion (half or double), but delegates that task to the Framerate producer. * Route producer: * Added possibility to delay frames routed from a layer or a channel. * HTML Producer: * Disabled web security in HTML Producer (Robert Nagy). * Reimplemented requestAnimationFrame handling in Javascript instead of C++. * Implemented cancelAnimationFrame. * Increased animation smoothness in HTML Producer with interlaced video modes. * Added remote debugging support. * Added mouse interaction support by utilizing the Screen consumer's new interaction support. * Flash Producer: * Contributions during development (not w.r.t 2.0.7 Stable): * Workaround for flickering with high CPU usage and CPU accelerator (Robert Nagy) AMCP ---- * TLS has a new column for "template type" for clients that want to differentiate between html and flash for example. * SET CHANNEL_LAYOUT added to be able to change the audio channel layout of a video channel at runtime. * HELP command added for accessing the new on-line help system. * FLS added to list the fonts usable by the Text producer. * LOCK command added for controlling/gaining exclusive access to a video channel. * LOG CATEGORY command added to enable/disable the new log categories. * SWAP command now optionally supports swapping the transforms as well as the layers. * VERSION command can now provide CEF version. CasparCG Server 2.0.7 Stable (as compared to CasparCG Server 2.0.7 Beta 2) ========================================================================== General ------- * Added support for using a different configuration file at startup than the default casparcg.config by simply adding the name of the file to use as the first command line argument to casparcg.exe. * Upgraded FFmpeg to latest stable. * Created build script. * Fixed bug where both layer_producer and channel_producer display:s and empty/late first frame when the producer is called before the consumer in the other end has received the first frame. * Added rudimentary support for audio for layer_producer and channel_producer. * Upgraded DeckLink SDK to 10.1.4, bringing new 2K and 4K DCI video modes. New template hosts also available for those modes. * General bug fixes (mostly memory and resource leaks, some serious). * Updated Boost to version 1.57 * Frontend no longer maintained and therefore not included in the release. Mixer ----- * Added support for rotation. * Added support for changing the anchor point around which fill_translation, fill_scale and rotation will be done from. * Added support for perspective correct corner pinning. * Added support for mipmapped textures with anisotropic filtering for increased downscaling quality. Whether to enable by default can be configured in casparcg.config. * Added support for cropping a layer. Not the same as clipping. AMCP ---- * Added RESUME command to complement PAUSE. (Peter Keuter) * To support the new mixer features the following commands has been added: * MIXER ANCHOR -- will return or modify the anchor point for a layer (default is 0 0 for backwards compatibility). Example: MIXER 1-10 ANCHOR 0.5 0.5 ...for changing the anchor to the middle of the layer (a MIXER 1-10 FILL 0.5 0.5 1 1 will be necessary to place the layer at the same place on screen as it was before). * MIXER ROTATION -- will return or modify the angle of which a layer is rotated by (clockwise degrees) around the point specified by ANCHOR. * MIXER PERSPECTIVE -- will return or modify the corners of the perspective transformation of a layer. One X Y pair for each corner (order upper left, upper right, lower right and lower left). Example: MIXER 1-10 PERSPECTIVE 0.4 0.4 0.6 0.4 1 1 0 1 * MIXER MIPMAP -- will return or modify whether to enable mipmapping of textures produced on a layer. Only frames produced after a change will be affected. So for example image_producer will not be affected while the image is displayed. * MIXER CROP -- will return or modify how textures on a layer will be cropped. One X Y pair each for the upper left corner and for the lower right corner. * Added INFO QUEUES command for debugging AMCP command queues. Useful for debugging command queue overflows, where a command is deadlocked. Hopefully always accessible via console, even though the TCP command queue may be full. * Added GL command: - GL INFO prints information about device buffers and host buffers. - GL GC garbage collects pooled but unused GL resources. * Added INFO THREADS command listing the known threads and their descriptive names. Can be matched against the thread id column of log entries. Consumers --------- * Removed blocking_decklink_consumer. It was more like an experiment at best and its usefulness was questionable. * Added a 10 second time-out for consumer sends, to detect/recover from blocked consumers. * Some consumers which are usually added and removed during playout (for example ffmpeg_consumer, streaming_consumer and channel_consumer) no longer affect the presentation time on other consumers. Previously a lag on the SDI output could be seen when adding such consumers. HTML producer ------------- * No longer tries to play all files with a . in their name. (Georgi Chorbadzhiyski) * Reimplemented using CEF3 instead of Berkelium, which enables use of WebGL and more. CEF3 is actively maintained, which Berkelium is not. (Robert Nagy) * Implements a custom version of window.requestAnimationFrame which will follow the pace of the channel, for perfectly smooth animations. * No longer manually interlaces frames, to allow for mixer fill transforms without artifacts. * Now uses CEF3 event loop to avoid 100% CPU core usage. CasparCG Server 2.0.7 Beta 2 (as compared to CasparCG Server 2.0.7 Beta 1) ========================================================================== General ------- * Added sending of OSC messages for channel_grid channel in addition to regular channels. Producers --------- * FFmpeg: Reports correct nb_frames() when using SEEK (Thomas Kaltz III) * Flash: Fixed bug where CG PLAY, CG INVOKE did not work. Consumers --------- * channel_consumer: Added support for more than one channel_consumer per channel. * decklink_consumer: Added support for a single instance of the consumer to manage a separate key output for use with DeckLink Duo/Quad cards: 1 2 external_separate_device ...in the configuration will enable the feature. The value of defaults to the value of + 1. * synchronizing_consumer: Removed in favour of a single decklink_consumer managing both fill and key device. * streaming_consumer: A new implementation of ffmpeg_consumer with added support for streaming and other PTS dependent protocols. Examples: udp://localhost:5004 -vcodec libx264 -tune zerolatency -preset ultrafast -crf 25 -format mpegts -vf scale=240:180 ...in configuration or: ADD 1 STREAM udp://localhost:5004 -vcodec libx264 -tune zerolatency -preset ultrafast -crf 25 -format mpegts -vf scale=240:180 ...via AMCP. (Robert Nagy sponsored by Ericsson Broadcasting Services) * newtek_ivga_consumer: Added support for iVGA consumer to not provide channel sync even though connected. Useful for iVGA clients that downloads as fast as possible instead of in frame-rate pace, like Wirecast. To enable: false ...in config to not provide channel sync when connected. The default is true. AMCP ---- * Added support in ADD and REMOVE for a placeholder which will resolve to the connected AMCP client's IPV4 address. * Fixed bug where AMCP commands split into multiple TCP packets where not correctly parsed (http://casparcg.com/forum/viewtopic.php?f=3&t=2480) CasparCG Server 2.0.7 Beta 1 (as compared to 2.0.6 Stable) ========================================================== General ------- * FFmpeg: Upgraded to master and adapted CasparCG to FFmpeg API changes (Robert Nagy sponsored by SVT) * FFmpeg: Fixed problem with frame count calculation (Thomas Kaltz III) * Fixed broken CG UPDATE. Producers --------- * New HTML producer has been created (Robert Nagy sponsored by Flemish Radio and Television Broadcasting Organization, VRT) CasparCG Server 2.0.6 Stable (as compared to 2.0.4 Stable) ========================================================== General ------- * iVGA: Allow for the server to work without Processing.AirSend.x86.dll to prevent a possible GPL violation. It is available as a separate optional download. * iVGA: Only provide sync to channel while connected, to prevent channel ticking too fast. * FFmpeg: Fixed bug during deinterlace-bob-reinterlace where output fields were offset by one field in relation to input fields. * FFmpeg: Fixed bug in ffmpeg_consumer where an access violation occurred during destruction. * FFmpeg: Improved seeking. (Robert Nagy and Thomas Kaltz III) * Frontend: Only writes elements to casparcg.config which overrides a default value to keep the file as compact as possible. * System audio: Patched sfml-audio to work better with oal-consumer and therefore removed PortAudio as the system audio implementation and went back to oal. * Flash: Changed so that the initial buffer fill of frames is rendered at a frame-duration pace instead of as fast as possible. Otherwise time based animations render incorrectly. During buffer recovery, a higher paced rendering takes place, but still not as fast as possible, which can cause animations to be somewhat incorrectly rendered. This is the only way though if we want the buffer to be able to recover after depletion. * Fixed race condition during server shutdown. * OSC: outgoing audio levels from the audio mixer for each audio channel is now transmitted (pFS and dBFS). (Thomas Kaltz III) * Stage: Fixed bug where tweened transforms were only ticked when a corresponding layer existed. * Screen consumer: Added borderless option and correct handling of name option. (Thomas Kaltz III) * AMCP: CLS now reports duration and framerate for MOVIE files were information is possible to extract. (Robert Nagy) * Version bump to keep up with CasparCG Client version. CasparCG Server 2.0.4 Stable (as compared to 2.0.4 Beta 1) ========================================================== General ------- * Can now open media with file names that only consist of digits. (Cambell Prince) * Miscellaneous stability and performance improvements. Video mixer ----------- * Conditional compilation of chroma key support and straight alpha output support in shader (just like with blend-modes) because of performance impact even when not in use on a layer or on a channel. New element added to configuration for turning on mixer features that not everybody would want to pay for (performance-wise.) blend-modes also moved into this element. * Fixed bug where MIXER LEVELS interpreted arguments in the wrong order, so that gamma was interpreted as max_input and vice versa. Consumers --------- * Added support for NewTek iVGA, which enables the use of CasparCG Server fill+key output(s) as input source(s) to a NewTek TriCaster without requiring video card(s) in the CasparCG Server machine, or taking up inputs in the TriCaster. element in config enables iVGA on a channel. (Robert Nagy sponsored by NewTek) * DeckLink: Created custom decklink allocator to reduce the memory footprint. * Replaced usage of SFML for with PortAudio, because of problems with SFML since change to static linkage. Also PortAudio seems to give lower latency. Producers --------- * FFmpeg: Added support for arbitrary FFmpeg options/parameters in ffmpeg_producer. (Cambell Prince) * Flash: Flash Player 11.8 now tested and fully supported. * Flash: No longer starts a Flash Player to service CG commands that mean nothing without an already running Flash Player. * Flash: globally serialize initialization and destruction of Flash Players, to avoid race conditions in Flash. * Flash: changed so that the Flash buffer is filled with Flash Player generated content at initialization instead of empty frames. OSC --- * Performance improvements. (Robert Nagy sponsored by Boffins Technologies) * Never sends old values to OSC receivers. Collects the latest value of each path logged since last UDP send, and sends the new UDP packet (to each subscribing OSC receiver) with the values collected. (Robert Nagy sponsored by Boffins Technologies) * Batches as many OSC messages as possible in an OSC bundle to reduce the number of UDP packets sent. Breakup into separate packages if necessary to avoid fragmentation. (Robert Nagy sponsored by Boffins Technologies) * Removed usage of Microsoft Agents library (Server ran out of memory after a while) in favour of direct synchronous invocations. CasparCG Server 2.0.4 Beta 1 (as compared to 2.0.3 Stable) ========================================================== General ------- * Front-end GUI for simplified configuration and easy access to common tasks. (Thomas Kaltz III and Jeff Lafforgue) * Added support for video and images file thumbnail generation. By default the media directory is scanned every 5 seconds for new/modified/removed files and thumbnails are generated/regenerated/removed accordingly. * Support for new video modes: 1556p2398, 1556p2400, 1556p2500, 2160p2398, 2160p2400, 2160p2500, 2160p2997 and 2160p3000. * Experimental ATI graphics card support by using static linking against SFML instead of dynamic. Should improve ATI GPU support, but needs testing. * Added support for playback and pass-through of up to 16 audio channels. See http://casparcg.com/forum/viewtopic.php?f=3&t=1453 for more information. * Optimizations in AMCP protocol implementations for large incoming messages, for example base64 encoded PNG images. * Logging output now includes milliseconds and has modified format: YYYY-MM-DD hh:mm:ss.zzz * Improved audio playback with 720p5994 and 720p6000 channels. * An attempt to improve output synchronization of consumers has been made. Use for example: 1 true 2 true ...to instruct the server to keep both DeckLink consumers in sync with each other. Consider this experimental, so don't wrap everything in unless synchronization of consumer outputs is needed. For synchronization to be effective all synchronized cards must have genlock reference signal connected. * Transfer of source code and issue tracker to github. (Thomas Kaltz III) Layer ----- * Fixed a problem where the first frame was not always shown on LOAD. (Robert Nagy) Stage ----- * Support for layer consumers for listening to frames coming out of producers. (Cambell Prince) Audio mixer ----------- * Added support for a master volume mixer setting for each channel. Video mixer ----------- * Added support for chroma keying. (Cambell Prince) * Fixed bug where MIXER CONTRAST set to < 1 can cause transparency issues. * Experimental support for straight alpha output. Consumers --------- * Avoid that the FFmpeg consumer blocks the channel output when it can't keep up with the frame rate (drops frames instead). * Added support for to create a separate key and fill file when recording with the FFmpeg consumer. Add the SEPARATE_KEY parameter to the FFmpeg consumer parameter list. The key file will get the _A file name suffix to be picked up by the separated_producer when doing playback. * The Image consumer now writes to the media folder instead of the data folder. * Fixed bug in DeckLink consumer where we submit too few audio samples to the driver when the video format has a frame rate > 50. * Added another experimental DeckLink consumer implementation where scheduled playback is not used, but a similar approach as in the bluefish consumer where we wait for a frame to be displayed and then display the next frame. It is configured via a consumer element. The benefits of this consumer is lower latency and more deterministic synchronization between multiple instances (should not need to be wrapped in a element when separated key/fill is used). Producers --------- * Added support for playing .swf files using the Flash producer. (Robert Nagy) * Image producer premultiplies PNG images with their alpha. * Image producer can load a PNG image encoded as base64 via: PLAY 1-0 [PNG_BASE64] * FFmpeg producer can now use a directshow input filters: PLAY 1-10 "dshow://video=Some Camera" (Cambell Prince, Julian Waller and Robert Nagy) * New layer producer which directs the output of a layer to another layer via a layer consumer. (Cambell Prince) AMCP ---- * The master volume feature is controlled via the MASTERVOLUME MIXER parameter. Example: MIXER 1 MASTERVOLUME 0.5 * THUMBNAIL LIST/RETRIEVE/GENERATE/GENERATE_ALL command was added to support the thumbnail feature. * ADD 1 FILE output.mov SEPARATE_KEY activates the separate key feature of the FFmpeg consumer creating an additional output_a.mov containing only the key. * Added KILL command for shutting down the server without console access. * Added RESTART command for shutting down the server in the same way as KILL except that the return code from CasparCG Server is 5 instead of 0, which can be used by parent process to take other actions. The 'casparcg_auto_restart.bat' script restarts the server if the return code is 5. * DATA RETRIEVE now returns linefeeds encoded as an actual linefeed (the single character 0x0a) instead of the previous two characters: \ followed by n. * MIXER CHROMA command added to control the chroma keying. Example: MIXER 1-1 CHROMA GREEN|BLUE 0.10 0.04 (Cambell Prince) * Fixed bug where MIXER FILL overrides any previous MIXER CLIP on the same layer. The bug-fix also has the side effect of supporting negative scale on MIXER FILL, causing the image to be flipped. * MIXER STRAIGHT_ALPHA_OUTPUT added to control whether to output straight alpha or not. * Added INFO DELAY and INFO - DELAY commands for showing some delay measurements. * PLAY 1-1 2-10 creates a layer producer on 1-1 redirecting the output of 2-10. (Cambell Prince) OSC --- * Support for sending OSC messages over UDP to either a predefined set of clients (servers in the OSC sense) or dynamically to the ip addresses of the currently connected AMCP clients. (Robert Nagy sponsored by Boffins Technologies) * /channel/[1-9]/stage/layer/[0-9] * always /paused [paused or not] * color producer /color [color string] * ffmpeg producer /profiler/time [render time] [frame duration] * ffmpeg producer /file/time [elapsed seconds] [total seconds] * ffmpeg producer /file/frame [frame] [total frames] * ffmpeg producer /file/fps [fps] * ffmpeg producer /file/path [file path] * ffmpeg producer /loop [looping or not] * during transitions /transition/frame [current frame] [total frames] * during transitions /transition/type [transition type] * flash producer /host/path [filename] * flash producer /host/width [width] * flash producer /host/height [height] * flash producer /host/fps [fps] * flash producer /buffer [buffered] [buffer size] * image producer /file/path [file path] CasparCG Server 2.0.3 Stable (as compared to 2.0.3 Alpha) ========================================================= Stage ----- * Fixed dead-lock that can occur with multiple mixer tweens. (Robert Nagy) AMCP ---- * DATA STORE now supports creating folders of path specified if they does not exist. (Jeff Lafforgue) * DATA REMOVE command was added. (Jeff Lafforgue) CasparCG Server 2.0.3 Alpha (as compared to 2.0 Stable) ======================================================= General ------- * Data files are now stored in UTF-8 with BOM. Latin1 files are still supported for backwards compatibility. * Commands written in UTF-8 to log file but only ASCII characters to console. * Added supported video formats: * 720p2398 (not supported by DeckLink) * 720p2400 (not supported by DeckLink) * 1080p5994 * 1080p6000 * 720p30 (not supported by DeckLink) * 720p29.976 (not supported by DeckLink) CLK --- * CLK protocol implementation can now serve more than one connection at a time safely. * Added timeline support to the CLK protocol. * Refactored parts of the CLK parser implementation. Consumers --------- * Consumers on same channel now invoked asynchronously to allow for proper sync of multiple consumers. * System audio consumer: * no longer provides sync to the video channel. * Screen consumer: * Support for multiple screen consumers on the same channel * No longer spin-waits for vsync. * Now deinterlaces to two separate frames so for example 50i will no longer be converted to 25p but instead to 50p for smooth playback of interlaced content. * DeckLink consumer now logs whether a reference signal is detected or not. Producers --------- * Image scroll producer: * Field-rate motion instead of frame-rate motion with interlaced video formats. This can be overridden by giving the PROGRESSIVE parameter. * SPEED parameter now defines pixels per frame/field instead of half pixels per frame. The scrolling direction is also reversed so SPEED 0.5 is the previous equivalent of SPEED -1. Movements are done with sub-pixel accuracy. * Fixed incorrect starting position of image. * Rounding error fixes to allow for more exact scrolling. * Added support for motion blur via a new BLUR parameter * Added PREMULTIPLY parameter to support images stored with straight alpha. CasparCG Server 2.0 Stable (as compared to Beta 3) ================================================== General ------- * Misc stability and performance fixes. Consumers --------- * File Consumer * Changed semantics to more closely follow FFmpeg (see forums). * Added options, -r, -acodec, -s, -pix_fmt, -f and more. * Screen Consumer * Added vsync support. CasparCG Server 2.0 Beta 3 (as compared to Beta 1) ================================================== Formats ------- * ProRes Support * Both encoding and decoding. * NTSC Support * Updated audio-pipeline for native NTSC support. Previous implementation did not fully support NTSC audio and could cause incorrect behaviour or even crashes. Consumers --------- * File Consumer added * See updated wiki or ask in forum for more information. * Should support anything FFmpeg supports. However, we will work mainly with DNxHD, PRORES and H264. - Key-only is not supported. * Bluefish Consumer * 24 bit audio support. - Embedded-audio does not work with Epoch cards. * DeckLink Consumer * Low latency enabled by default. * Added graphs for driver buffers. * Screen Consumer * Changed screen consumer square PAL to the more common wide-square PAL. * Can now be closed. * Fixed interpolation artifacts when running non-square video-modes. * Automatically deinterlace interlaced input. Producers --------- * DeckLink Producer * Improved color quality be avoiding unnecessary conversion to BGRA. * FFMPEG Producer * Fixed missing alpha for (RGB)A formats when deinterlacing. * Updated buffering to work better with files with long audio/video interleaving. * Seekable while running and after reaching EOF. CALL 1-1 SEEK 200. * Enable/disable/query looping while running. CALL 1-1 LOOP 1. * Fixed bug with duration calculation. * Fixed bug with fps calculation. * Improved auto-transcode accuracy. * Improved seeking accuracy. * Fixed bug with looping and LENGTH. * Updated to newer FFmpeg version. * Fixed incorrect scaling of NTSC DV files. * Optimized color conversion when using YADIF filters. * Flash Producer * Release Flash Player when empty. * Use native resolution TemplateHost. * TemplateHosts are now chosen automatically if not configured. The TemplateHost with the corresponding video-mode name is now chosen. * Use square pixel dimensions. AMCP ---- * When possible, commands will no longer wait for rendering pipeline. This reduces command execution latencies, especially when sending a lot of commands in a short timespan. * Fixed CINF command. * ADD/REMOVE no longer require subindex, e.g. "ADD 1 SCREEN" / "REMOVE 1 SCREEN" instead of "ADD 1-1 SCREEN" / ... * PARAM is renamed to CALL. * STATUS command is replaced by INFO. * INFO command has been extended: * INFO (lists channels). * INFO 1 (channel info). * INFO 1-1 (layer info). * INFO 1-1 F (foreground producer info). * INFO 1-1 B (background producer info). * INFO TEMPLATE mytemplate (template meta-data info, e.g. field names). * CG INFO command has been extended. * CG INFO 1 (template-host information, e.g. what layers are occupied). Mixer ----- * Fixed alpha with blend modes. * Automatically deinterlace for MIXER FILL commands. Channel ------- * SET MODE now reverts back to old video-mode on failure. Diagnostics ----------- * Improved graphs and added more status information. * Print configuration into log at startup. * Use the same log file for the entire day, instead of one per startup as previously. * Diagnostics window is now closable. CasparCG Server 2.0 Beta 1 (as compared to Alpha) ================================================= * Blending Modes (needs to be explicitly enabled) * overlay * screen * multiply * and many more. * Added additive keyer in addition to linear keyer. * Image adjustments * saturation * brightness * contrast * min input-level * max input-level * min output-level * max output-level * gamma * Support for FFmpeg-filters such as (ee http://ffmpeg.org/libavfilter.html) * yadif deinterlacer (optimized in CasparCG for full multi-core support) * de-noising * dithering * box blur * and many more * 32-bit SSE optimized audio pipeline. * DeckLink-Consumer uses external-key by default. * DeckLink-Consumer has 24 bit embedded-audio support. * DeckLink-Producer has 24 bit embedded-audio support. * LOADBG with AUTO feature which automatically plays queued clip when foreground clip has ended. * STATUS command for layers. * LOG LEVEL command for log filtering. * MIX transition works with transparent clips. * Freeze on last frame. * Producer buffering is now configurable. * Consumer buffering is now configurable. * Now possible to configure template-hosts for different video-modes. * Added auto transcoder for FFmpeg producer which automatically transcodes input video into compatible video format for the channel. * interlacing (50p -> 50i) * deinterlacing (50i -> 25p) * bob-deinterlacing (50i -> 50p) * bob-deinterlacing and reinterlacing (w1xh150i -> w2xh250i) * doubling (25p -> 50p) * halfing (50p -> 25p) * field-order swap (upper <-> lower) * Screen consumer now automatically deinterlaces when receiving interlaced content. * Optimized renderer. * Renderer can now be run asynchronously with producer by using a producer-buffer size greater than 0. * Improved error and crash recovery. * Improved logging. * Added Image-Scroll-Producer. * Key-only has now near zero performance overhead. * Reduced memory requirements. * Removed "warm up lag" which occurred when playing the first media clip after the server has started. * Added read-back fence for OpenGL device for improved multi-channel performance. * Memory support increased from standard 2 GB to 4 GB on 64 bit Win 7 OS. * Added support for 2* DeckLink cards in Full HD. * Misc bugs fixes and performance improvements. * Color producer now support some color codes in addition to color codes, e.g. EMPTY, BLACK, RED etc... * Alpha value in color codes is now optional. * More than 2 DeckLink cards might be possible but have not yet been tested. CasparCG Server 2.0 Alpha (as compared to 1.8) ============================================== General ------- * Mayor refactoring for improved readability and maintainability. * Some work towards platform-independence. Currently the greatest challenge for full platform-independence is flash-producer. * Misc improved scalability. * XML-configuration. * DeckLink * Support for multiple DeckLink cards. Core ---- * Multiple producers per video_channel. * Multiple consumers per video_channel. * Swap producers between layers and channels during run-time. * Support for upper-field and lower-field interlacing. * Add and remove consumers during run-time. * Preliminary support for NTSC. AMCP ---- * Query flash and template-host version. * Recursive media-folder listing. * Misc changes. Mixer ----- * Animated tween transforms. * Image-Mixer * Fully GPU accelerated (all features listed below are done on the GPU), * Layer composition. * Color spaces (rgba, bgra, argb, yuv, yuva, yuv-hd, yuva-hd). * Interlacing. * Per-layer image transforms: * Opacity * Gain * Scaling * Clipping * Translation * Audio Mixer * Per-layer and per-sample audio transforms: * Gain * Fully internal audio mixing. Single output video_channel. Consumers --------- * DeckLink Consumer * Embedded audio. * HD support. * Hardware clock. * Bluefish Consumer * Drivers are loaded on-demand (server now runs on computers without installed Bluefish drivers). * Embedded audio. * Allocated frames are no longer leaked. Producers --------- * Decklink Producer * Embedded audio. * HD support. * Color Producer * GPU accelerated. * FFMPEG Producer * Asynchronous file IO. * Parallel decoding of audio and video. * Color space transform are moved to GPU. * Transition Producer * Fully interlaced transition (previously only progressive, even when running in interlaced mode). * Per-sample mixing between source and destination clips. * Tween transitions. * Flash Producer * DirectDraw access (slightly improved performance). * Improved time-sync. Smoother animations and proper interlacing. * Image Producer * Support for various image formats through FreeImage library. Diagnostics ----------- * Graphs for monitoring performance and events. * Misc logging improvements. * Separate log file for every run of the server. * Error logging provides full exception details, instead of only printing that an error has occurred. * Console with real-time logging output. * Console with AMCP input. Removed ------- * Registry configuration (replaced by XML Configuration). * TGA Producer (replaced by Image Producer). * TGA Scroll Producer server-2.2.0-stable/CODE_OF_CONDUCT.MD000066400000000000000000000043051341175263200167760ustar00rootroot00000000000000# CasparCG Code of Conduct > CasparCG is all about showing respect and professionalism one to another. ## Community We want a positive and inspiring community that welcomes and embraces new ideas with respect and professionalism. CasparCG community has arisen through hard work and tremendous enthusiasm of hundreds of people around the world. This Code of Conduct is about how we behave, act and cooperate in this positive and inspiring community. Contributors and users who engage in the CasparCG project in one way or another share this Code of Conduct. ## We strive to: ### Be considerate CasparCG is used by other people and in various environments such as production. Your actions will affect other community members and therefore we expect you to take those consequences into account when making decisions. ### Be respectful In a community there will always be some form of disagreement, but that is no excuse for poor behavior and poor manners. Treat one another with respect and professionalism to make community members feel comfortable. We work together, as a union, to resolve conflicts and to maintain the positive and inspiring atmosphere in our community. We do not tolerate personal attacks, racism, sexism or any other form of discrimination or abuses. Maintainers of the project have right to suspend the person who persistently breaks to our Code of Conduct. ### Be collaborative Collaboration helps to reduce redundancy while improving the quality of the project and the software produced. To avoid misunderstanding, try to be clear when requesting for help, giving help or asking for feedback. If something is unclear ask for clarification. ### Be supportive CasparCG community is made up by mutual respect, collaboration and professional behavior. If you witness others being discriminated or abused, think about how you can be supportive. If the identified situation is beyond your ability, ask the victim privately if some form of official intervention is needed to solve the uncomfortable situation. ### Ask for help By asking questions early we can avoid many problems that can arise later on. We encourage you to ask questions. Those who are asked should be helpful and answer with professionalism in mind. server-2.2.0-stable/LICENSE.md000066400000000000000000001045131341175263200157050ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . server-2.2.0-stable/README.md000066400000000000000000000105421341175263200155560ustar00rootroot00000000000000CasparCG Server =============== Thank you for your interest in CasparCG Server, a professional software used to play out and record professional graphics, audio and video to multiple outputs. CasparCG Server has been in 24/7 broadcast production since 2006. The CasparCG Server works on Windows and Linux. Development ----------- ```bash git clone --single-branch --branch master https://github.com/CasparCG/server ``` See [BUILDING](BUILDING.md) for instructions on how to build the CasparCG Server from source manually. License ------- CasparCG Server is distributed under the GNU General Public License GPLv3 or higher, see [LICENSE](LICENSE.md) for details. More information about CasparCG is available at http://casparcg.com/ and in the forum at https://casparcgforum.org/ COMMON SYSTEM REQUIREMENTS FOR WINDOWS AND LINUX ------------------------------------------------ - A graphics card (GPU) capable of OpenGL 4.5 is required. SYSTEM REQUIREMENTS FOR WINDOWS ------------------------------- SYSTEM REQUIREMENTS FOR LINUX ----------------------------- INSTALLATION ON WINDOWS ----------------------- INSTALLATION ON LINUX --------------------- RESOLVING COMMON ISSUES ON LINUX -------------------------------- Common problems you may encounter when running on newer and unsupported Ubuntu editions: 1. HTML producer freezes and/or throws "Fontconfig error" message Add below line to run.sh script: export FONTCONFIG_PATH=/etc/fonts 2. HTML producer throws "GTK theme error" message Install gnome-themes-standard package: sudo apt install gnome-themes-standard 3. Error while loading libgcrypt.so.11 Extract libgcrypt.so.11 and libgcrypt.so.11.8.2 to CasparCG lib/ directory. You can get it from: https://launchpad.net/ubuntu/+archive/primary/+files/libgcrypt11_1.5.3-2ubuntu4.2_amd64.deb 4. Error while loading libcgmanager.so.0 Install central cgroup manager daemon (client library): sudo apt install libcgmanager0 5. Error while loading shared libraries: libgconf-2.so.4 Install GNOME configuration database system: sudo apt -y install libgconf2-4 6. lib/libz.so.1: version `ZLIB_1.2.9' not found cd your_casparcg_directory/lib/ sudo mv libz.so.1 libz.so.1.old sudo ln -s /lib/x86_64-linux-gnu/libz.so.1 INSTALLATION OF ADDITIONAL NON-GPL SOFTWARE ------------------------------------------- - For Flash template support (Windows only): 1. Uninstall any previous version of the Adobe Flash Player using this file: http://download.macromedia.com/get/flashplayer/current/support/uninstall_flash_player.exe 2. Download and unpack http://download.macromedia.com/pub/flashplayer/installers/archive/fp_11.8.800.94_archive.zip 3. Install Adobe Flash Player 11.8.800.94 from the unpacked archive: fp_11.8.800.94_archive\11_8_r800_94\flashplayer11_8r800_94_winax.exe - For NewTek iVGA support (Windows only), please download and install the following driver: http://new.tk/NetworkSendRedist CONFIGURATION ------------- 1. Configure the server by editing the self-documented "casparcg.config" file in a text editor. 2. 1. Windows: start `casparcg_auto_restart.bat`, or `casparcg.exe` and `scanner.exe` separately. 1. Linux: start the `run.sh` program. 3. Connect to the Server from a client software, such as the "CasparCG Client" which is available as a separate download. DOCUMENTATION ------------- The most up-to-date documentation is always available at https://github.com/CasparCG/help/wiki Ask questions in the forum: https://casparcgforum.org/ LICENSING --------- CasparCG is distributed under the GNU General Public License GPLv3 or higher, see the file LICENSE.txt for details. More information, samples and documentation at: http://casparcg.com/ https://casparcgforum.org/ https://github.com/CasparCG/help/wiki CasparCG Server uses FFmpeg (http://ffmpeg.org/) under the GPLv2 Licence. FFmpeg is a trademark of Fabrice Bellard, originator of the FFmpeg project. CasparCG Server uses the Threading Building Blocks (http://www.threadingbuildingblocks.org/) library under the GPLv2 Licence. CasparCG Server uses FreeImage (http://freeimage.sourceforge.net/) under the GPLv2 License. CasparCG Server uses SFML (http://www.sfml-dev.org/) under the zlib/libpng License. CasparCG Server uses GLEW (http://glew.sourceforge.net) under the modified BSD License. CasparCG Server uses boost (http://www.boost.org/) under the Boost Software License, version 1.0. server-2.2.0-stable/resources/000077500000000000000000000000001341175263200163075ustar00rootroot00000000000000server-2.2.0-stable/resources/windows/000077500000000000000000000000001341175263200200015ustar00rootroot00000000000000server-2.2.0-stable/src/000077500000000000000000000000001341175263200150645ustar00rootroot00000000000000server-2.2.0-stable/src/CMakeLists.txt000066400000000000000000000025311341175263200176250ustar00rootroot00000000000000CMAKE_MINIMUM_REQUIRED (VERSION 3.0) # Project settings PROJECT ("CasparCG Server") SET (CONFIG_VERSION_MAJOR 2) SET (CONFIG_VERSION_MINOR 2) SET (CONFIG_VERSION_BUG 0) SET (CONFIG_VERSION_TAG "Stable") option(ENABLE_HTML "Enable HTML module, require CEF" ON) # Add custom cmake modules path LIST (APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules) if (MSVC) INCLUDE (Bootstrap_Windows) else () INCLUDE (Bootstrap_Linux) # Output build settings IF (SUPPORTED_PLATFORM) MESSAGE (STATUS "Supported target platform: ${SUPPORTED_PLATFORM}") ELSE () MESSAGE (STATUS "Unsupported target platform, will still attempt build!") ENDIF () MESSAGE (STATUS "Target platform: ${CONFIG_PLATFORM}") MESSAGE (STATUS "Target architecture: ${CONFIG_ARCH}") MESSAGE (STATUS "CPU Count: ${CONFIG_CPU_COUNT}") MESSAGE (STATUS "Target build type: ${CMAKE_BUILD_TYPE}") MESSAGE (STATUS "Build Version: ${CONFIG_VERSION_MAJOR}.${CONFIG_VERSION_MINOR}.${CONFIG_VERSION_BUG} ${CONFIG_VERSION_TAG} (Revision: ${CONFIG_VERSION_GIT_HASH})") CONFIGURE_FILE ("${PROJECT_SOURCE_DIR}/version.tmpl" "${CMAKE_BINARY_DIR}/generated/version.h") INCLUDE_DIRECTORIES ("${CMAKE_BINARY_DIR}/generated") ADD_SUBDIRECTORY (accelerator) ADD_SUBDIRECTORY (common) ADD_SUBDIRECTORY (core) ADD_SUBDIRECTORY (modules) ADD_SUBDIRECTORY (protocol) ADD_SUBDIRECTORY (shell) endif () server-2.2.0-stable/src/CMakeModules/000077500000000000000000000000001341175263200173755ustar00rootroot00000000000000server-2.2.0-stable/src/CMakeModules/Bootstrap_Linux.cmake000066400000000000000000000130621341175263200235350ustar00rootroot00000000000000# Determine build (target) platform INCLUDE (PlatformIntrospection) TEST_FOR_SUPPORTED_PLATFORM (SUPPORTED_PLATFORM) _DETERMINE_PLATFORM (CONFIG_PLATFORM) _DETERMINE_ARCH (CONFIG_ARCH) _DETERMINE_CPU_COUNT (CONFIG_CPU_COUNT) SET (PLATFORM_FOLDER_NAME "linux") IF (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) MESSAGE (STATUS "Setting build type to 'Release' as none was specified.") SET (CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) SET_PROPERTY (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") ENDIF () MARK_AS_ADVANCED (CMAKE_INSTALL_PREFIX) FIND_PACKAGE (Git) SET (CONFIG_VERSION_GIT_HASH "N/A") IF (DEFINED ENV{GIT_HASH} AND NOT $ENV{GIT_HASH} STREQUAL "") SET (CONFIG_VERSION_GIT_HASH "$ENV{GIT_HASH}") ELSEIF (GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/../.git") EXEC_PROGRAM ("${GIT_EXECUTABLE}" "${PROJECT_SOURCE_DIR}/../" ARGS rev-parse --verify --short HEAD OUTPUT_VARIABLE CONFIG_VERSION_GIT_HASH) ENDIF () SET (BOOST_ROOT_PATH "/opt/boost" CACHE STRING "Path to Boost") SET (ENV{BOOST_ROOT} "${BOOST_ROOT_PATH}") SET (Boost_USE_DEBUG_LIBS ON) SET (Boost_USE_RELEASE_LIBS OFF) SET (Boost_USE_STATIC_LIBS ON) FIND_PACKAGE (Boost 1.66.0 COMPONENTS system thread chrono filesystem log locale regex date_time coroutine REQUIRED) SET (FFMPEG_ROOT_PATH "/opt/ffmpeg/lib/pkgconfig" CACHE STRING "Path to FFMPEG") SET (ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:${FFMPEG_ROOT_PATH}") FIND_PACKAGE (FFmpeg REQUIRED) LINK_DIRECTORIES( ${FFMPEG_LIBRARY_DIRS} ) FIND_PACKAGE (OpenGL REQUIRED) FIND_PACKAGE (JPEG REQUIRED) FIND_PACKAGE (FreeImage REQUIRED) FIND_PACKAGE (Freetype REQUIRED) FIND_PACKAGE (GLEW REQUIRED) FIND_PACKAGE (TBB REQUIRED) FIND_PACKAGE (SndFile REQUIRED) FIND_PACKAGE (OpenAL REQUIRED) FIND_PACKAGE (GLFW REQUIRED) FIND_PACKAGE (SFML 2 COMPONENTS graphics window system REQUIRED) if (ENABLE_HTML) SET(CEF_ROOT_DIR "/opt/cef" CACHE STRING "Path to CEF") FIND_PACKAGE (CEF REQUIRED) endif () SET (BOOST_INCLUDE_PATH "${Boost_INCLUDE_DIRS}") SET (TBB_INCLUDE_PATH "${TBB_INCLUDE_DIRS}") SET (GLEW_INCLUDE_PATH "${GLEW_INCLUDE_DIRS}") SET (SFML_INCLUDE_PATH "${SFML_INCLUDE_DIR}") SET (FREETYPE_INCLUDE_PATH "${FREETYPE_INCLUDE_DIRS}") SET (FFMPEG_INCLUDE_PATH "${FFMPEG_INCLUDE_DIRS}") SET (ASMLIB_INCLUDE_PATH "${EXTERNAL_INCLUDE_PATH}") SET (FREEIMAGE_INCLUDE_PATH "${FreeImage_INCLUDE_DIRS}") set(CEF_INCLUDE_PATH "${CEF_ROOT_DIR}") set(CEF_BIN_PATH "${CEF_ROOT_DIR}/Release") set(CEF_RESOURCE_PATH "${CEF_ROOT_DIR}/Resources") SET_PROPERTY (GLOBAL PROPERTY USE_FOLDERS ON) ADD_DEFINITIONS (-DSFML_STATIC) ADD_DEFINITIONS (-DUNICODE) ADD_DEFINITIONS (-D_UNICODE) ADD_DEFINITIONS (-DGLEW_NO_GLU) ADD_DEFINITIONS (-D__NO_INLINE__) # Needed for precompiled headers to work ADD_DEFINITIONS (-DBOOST_NO_SWPRINTF) # swprintf on Linux seems to always use , as decimal point regardless of C-locale or C++-locale ADD_DEFINITIONS (-DTBB_USE_CAPTURED_EXCEPTION=1) ADD_DEFINITIONS (-DNDEBUG) # Needed for precompiled headers to work ADD_COMPILE_OPTIONS (-std=c++14) # Needed for precompiled headers to work ADD_COMPILE_OPTIONS (-O3) # Needed for precompiled headers to work ADD_COMPILE_OPTIONS (-Wno-deprecated-declarations -Wno-write-strings -Wno-terminate -Wno-multichar -Wno-cpp) ADD_COMPILE_OPTIONS (-msse3) ADD_COMPILE_OPTIONS (-mssse3) ADD_COMPILE_OPTIONS (-msse4.1) ADD_COMPILE_OPTIONS (-fnon-call-exceptions) # Allow signal handler to throw exception IF (POLICY CMP0045) CMAKE_POLICY (SET CMP0045 OLD) ENDIF () SET (CASPARCG_MODULE_INCLUDE_STATEMENTS "" CACHE INTERNAL "") SET (CASPARCG_MODULE_INIT_STATEMENTS "" CACHE INTERNAL "") SET (CASPARCG_MODULE_UNINIT_STATEMENTS "" CACHE INTERNAL "") SET (CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS "" CACHE INTERNAL "") SET (CASPARCG_MODULE_PROJECTS "" CACHE INTERNAL "") SET (CASPARCG_RUNTIME_DEPENDENCIES "" CACHE INTERNAL "") INCLUDE (PrecompiledHeader) FUNCTION (casparcg_add_include_statement HEADER_FILE_TO_INCLUDE) SET (CASPARCG_MODULE_INCLUDE_STATEMENTS "${CASPARCG_MODULE_INCLUDE_STATEMENTS}" "#include <${HEADER_FILE_TO_INCLUDE}>" CACHE INTERNAL "" ) ENDFUNCTION () FUNCTION (casparcg_add_init_statement INIT_FUNCTION_NAME NAME_TO_LOG) SET (CASPARCG_MODULE_INIT_STATEMENTS "${CASPARCG_MODULE_INIT_STATEMENTS}" " ${INIT_FUNCTION_NAME}(dependencies)\;" " CASPAR_LOG(info) << L\"Initialized ${NAME_TO_LOG} module.\"\;" "" CACHE INTERNAL "" ) ENDFUNCTION () FUNCTION (casparcg_add_uninit_statement UNINIT_FUNCTION_NAME) SET (CASPARCG_MODULE_UNINIT_STATEMENTS " ${UNINIT_FUNCTION_NAME}()\;" "${CASPARCG_MODULE_UNINIT_STATEMENTS}" CACHE INTERNAL "" ) ENDFUNCTION () FUNCTION (casparcg_add_command_line_arg_interceptor INTERCEPTOR_FUNCTION_NAME) set(CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS "${CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS}" " if (${INTERCEPTOR_FUNCTION_NAME}(argc, argv))" " return true\;" "" CACHE INTERNAL "" ) ENDFUNCTION () FUNCTION (casparcg_add_module_project PROJECT) SET (CASPARCG_MODULE_PROJECTS "${CASPARCG_MODULE_PROJECTS}" "${PROJECT}" CACHE INTERNAL "") ENDFUNCTION () # http://stackoverflow.com/questions/7172670/best-shortest-way-to-join-a-list-in-cmake FUNCTION (join_list VALUES GLUE OUTPUT) STRING (REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}") STRING (REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping SET (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) ENDFUNCTION () FUNCTION (casparcg_add_runtime_dependency FILE_TO_COPY) SET (CASPARCG_RUNTIME_DEPENDENCIES "${CASPARCG_RUNTIME_DEPENDENCIES}" "${FILE_TO_COPY}" CACHE INTERNAL "") ENDFUNCTION () server-2.2.0-stable/src/CMakeModules/Bootstrap_Windows.cmake000066400000000000000000000246241341175263200240760ustar00rootroot00000000000000find_package(Git) set(CONFIG_VERSION_GIT_HASH "N/A") if (GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/../.git") exec_program("${GIT_EXECUTABLE}" "${PROJECT_SOURCE_DIR}" ARGS rev-parse --verify --short HEAD OUTPUT_VARIABLE CONFIG_VERSION_GIT_HASH) endif () CONFIGURE_FILE ("${PROJECT_SOURCE_DIR}/version.tmpl" "${CMAKE_BINARY_DIR}/generated/version.h") INCLUDE_DIRECTORIES ("${CMAKE_BINARY_DIR}/generated") set(CASPARCG_MODULE_INCLUDE_STATEMENTS "" CACHE INTERNAL "") set(CASPARCG_MODULE_INIT_STATEMENTS "" CACHE INTERNAL "") set(CASPARCG_MODULE_UNINIT_STATEMENTS "" CACHE INTERNAL "") set(CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS "" CACHE INTERNAL "") set(CASPARCG_MODULE_PROJECTS "" CACHE INTERNAL "") set(CASPARCG_RUNTIME_DEPENDENCIES "" CACHE INTERNAL "") function(casparcg_add_include_statement HEADER_FILE_TO_INCLUDE) set(CASPARCG_MODULE_INCLUDE_STATEMENTS "${CASPARCG_MODULE_INCLUDE_STATEMENTS}" "#include <${HEADER_FILE_TO_INCLUDE}>" CACHE INTERNAL "") endfunction() function(casparcg_add_init_statement INIT_FUNCTION_NAME NAME_TO_LOG) set(CASPARCG_MODULE_INIT_STATEMENTS "${CASPARCG_MODULE_INIT_STATEMENTS}" " ${INIT_FUNCTION_NAME}(dependencies)\;" " CASPAR_LOG(info) << L\"Initialized ${NAME_TO_LOG} module.\"\;" "" CACHE INTERNAL "") endfunction() function(casparcg_add_uninit_statement UNINIT_FUNCTION_NAME) set(CASPARCG_MODULE_UNINIT_STATEMENTS " ${UNINIT_FUNCTION_NAME}()\;" "${CASPARCG_MODULE_UNINIT_STATEMENTS}" CACHE INTERNAL "") endfunction() function(casparcg_add_command_line_arg_interceptor INTERCEPTOR_FUNCTION_NAME) set(CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS "${CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS}" " if (${INTERCEPTOR_FUNCTION_NAME}(argc, argv))" " return true\;" "" CACHE INTERNAL "") endfunction() function(casparcg_add_module_project PROJECT) set(CASPARCG_MODULE_PROJECTS "${CASPARCG_MODULE_PROJECTS}" "${PROJECT}" CACHE INTERNAL "") endfunction() # http://stackoverflow.com/questions/7172670/best-shortest-way-to-join-a-list-in-cmake function(join_list VALUES GLUE OUTPUT) string (REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}") string (REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping set (${OUTPUT} "${_TMP_STR}" PARENT_SCOPE) endfunction() function(casparcg_add_runtime_dependency FILE_TO_COPY) set(CASPARCG_RUNTIME_DEPENDENCIES "${CASPARCG_RUNTIME_DEPENDENCIES}" "${FILE_TO_COPY}" CACHE INTERNAL "") endfunction() set(PACKAGES_FOLDER "${PROJECT_SOURCE_DIR}/packages") set(NUGET_PACKAGES_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/packages") casparcg_add_runtime_dependency("${PROJECT_SOURCE_DIR}/shell/casparcg.config") # BOOST set(BOOST_INCLUDE_PATH "${NUGET_PACKAGES_FOLDER}/boost.1.66.0.0/lib/native/include") link_directories("${NUGET_PACKAGES_FOLDER}/boost_atomic-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_chrono-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_context-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_coroutine-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_date_time-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_filesystem-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_locale-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_log-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_log_setup-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_regex-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_system-vc141.1.66.0.0/lib/native") link_directories("${NUGET_PACKAGES_FOLDER}/boost_thread-vc141.1.66.0.0/lib/native") add_definitions( -DBOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE ) add_definitions( -DBOOST_COROUTINES_NO_DEPRECATION_WARNING ) # FFMPEG set(FFMPEG_INCLUDE_PATH "${NUGET_PACKAGES_FOLDER}/FFmpeg.Nightly.20180711.0.0/build/native/include") set(FFMPEG_BIN_PATH "${NUGET_PACKAGES_FOLDER}/FFmpeg.Nightly.20180711.0.0/build/native/bin/x64") link_directories("${NUGET_PACKAGES_FOLDER}/FFmpeg.Nightly.20180711.0.0/build/native/lib/x64") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/avcodec-58.dll") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/avdevice-58.dll") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/avfilter-7.dll") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/avformat-58.dll") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/avutil-56.dll") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/postproc-55.dll") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/swresample-3.dll") casparcg_add_runtime_dependency("${FFMPEG_BIN_PATH}/swscale-5.dll") # TBB set(TBB_INCLUDE_PATH "${PACKAGES_FOLDER}/tbb/include") set(TBB_BIN_PATH "${PACKAGES_FOLDER}/tbb/bin/win32") link_directories("${PACKAGES_FOLDER}/tbb/lib/win32") casparcg_add_runtime_dependency("${TBB_BIN_PATH}/tbb.dll") casparcg_add_runtime_dependency("${TBB_BIN_PATH}/tbb_debug.dll") casparcg_add_runtime_dependency("${TBB_BIN_PATH}/tbbmalloc.dll") casparcg_add_runtime_dependency("${TBB_BIN_PATH}/tbbmalloc_debug.dll") casparcg_add_runtime_dependency("${TBB_BIN_PATH}/tbbmalloc_proxy.dll") casparcg_add_runtime_dependency("${TBB_BIN_PATH}/tbbmalloc_proxy_debug.dll") # GLEW set(GLEW_INCLUDE_PATH "${PACKAGES_FOLDER}/glew/include") set(GLEW_BIN_PATH "${PACKAGES_FOLDER}/glew/bin/win32") link_directories("${PACKAGES_FOLDER}/glew/lib/win32") add_definitions( -DGLEW_NO_GLU ) casparcg_add_runtime_dependency("${GLEW_BIN_PATH}/glew32.dll") # SFML set(SFML_INCLUDE_PATH "${NUGET_PACKAGES_FOLDER}/sfml-system.2.4.2.0/build/native/include") link_directories("${NUGET_PACKAGES_FOLDER}/sfml-graphics.2.4.2.0/build/native/lib/x64/v140/Debug/dynamic") link_directories("${NUGET_PACKAGES_FOLDER}/sfml-graphics.2.4.2.0/build/native/lib/x64/v140/Release/dynamic") link_directories("${NUGET_PACKAGES_FOLDER}/sfml-window.2.4.2.0/build/native/lib/x64/v140/Debug/dynamic") link_directories("${NUGET_PACKAGES_FOLDER}/sfml-window.2.4.2.0/build/native/lib/x64/v140/Release/dynamic") link_directories("${NUGET_PACKAGES_FOLDER}/sfml-system.2.4.2.0/build/native/lib/x64/v140/Debug/dynamic") link_directories("${NUGET_PACKAGES_FOLDER}/sfml-system.2.4.2.0/build/native/lib/x64/v140/Release/dynamic") casparcg_add_runtime_dependency("${NUGET_PACKAGES_FOLDER}/sfml-graphics.redist.2.4.2.0/build/native/bin/x64/v140/Debug/dynamic/sfml-graphics-d-2.dll") casparcg_add_runtime_dependency("${NUGET_PACKAGES_FOLDER}/sfml-graphics.redist.2.4.2.0/build/native/bin/x64/v140/Release/dynamic/sfml-graphics-2.dll") casparcg_add_runtime_dependency("${NUGET_PACKAGES_FOLDER}/sfml-window.redist.2.4.2.0/build/native/bin/x64/v140/Debug/dynamic/sfml-window-d-2.dll") casparcg_add_runtime_dependency("${NUGET_PACKAGES_FOLDER}/sfml-window.redist.2.4.2.0/build/native/bin/x64/v140/Release/dynamic/sfml-window-2.dll") casparcg_add_runtime_dependency("${NUGET_PACKAGES_FOLDER}/sfml-system.redist.2.4.2.0/build/native/bin/x64/v140/Debug/dynamic/sfml-system-d-2.dll") casparcg_add_runtime_dependency("${NUGET_PACKAGES_FOLDER}/sfml-system.redist.2.4.2.0/build/native/bin/x64/v140/Release/dynamic/sfml-system-2.dll") # FREEIMAGE set(FREEIMAGE_INCLUDE_PATH "${NUGET_PACKAGES_FOLDER}/native.freeimage.vc140.3.17.0/build/native/include") set(FREEIMAGE_BIN_PATH "${NUGET_PACKAGES_FOLDER}/native.freeimage.vc140.redist.3.17.0/build/native/bin/x64/dynamic") link_directories("${NUGET_PACKAGES_FOLDER}/native.freeimage.vc140.3.17.0/build/native/lib/x64") casparcg_add_runtime_dependency("${FREEIMAGE_BIN_PATH}/FreeImage.dll") casparcg_add_runtime_dependency("${FREEIMAGE_BIN_PATH}/FreeImaged.dll") #ZLIB set(ZLIB_INCLUDE_PATH "${NUGET_PACKAGES_FOLDER}/zlib-msvc-x64.1.2.11.8900/build/native/include") link_directories("${NUGET_PACKAGES_FOLDER}/zlib-msvc-x64.1.2.11.8900/build/native/lib_release") link_directories("${NUGET_PACKAGES_FOLDER}/zlib-msvc-x64.1.2.11.8900/build/native/lib_debug") # OPENAL set(OPENAL_INCLUDE_PATH "${PACKAGES_FOLDER}/openal/include") set(OPENAL_BIN_PATH "${PACKAGES_FOLDER}/openal/bin/win32") link_directories("${PACKAGES_FOLDER}/openal/lib/win32") casparcg_add_runtime_dependency("${OPENAL_BIN_PATH}/OpenAL32.dll") # LIBERATION_FONTS set(LIBERATION_FONTS_BIN_PATH "${PROJECT_SOURCE_DIR}/shell/liberation-fonts") casparcg_add_runtime_dependency("${LIBERATION_FONTS_BIN_PATH}/LiberationMono-Regular.ttf") # CEF if (ENABLE_HTML) set(CEF_INCLUDE_PATH "${NUGET_PACKAGES_FOLDER}/cef.sdk.3.3239.1723/CEF") set(CEF_BIN_PATH "${NUGET_PACKAGES_FOLDER}/cef.redist.x64.3.3239.1723/CEF") set(CEF_RESOURCE_PATH "${NUGET_PACKAGES_FOLDER}/cef.redist.x64.3.3239.1723/CEF") link_directories("${NUGET_PACKAGES_FOLDER}/cef.sdk.3.3239.1723/CEF/x64") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/locales") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/swiftshader") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/cef.pak") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/cef_100_percent.pak") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/cef_200_percent.pak") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/cef_extensions.pak") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/devtools_resources.pak") casparcg_add_runtime_dependency("${CEF_RESOURCE_PATH}/icudtl.dat") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/natives_blob.bin") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/snapshot_blob.bin") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/libcef.dll") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/chrome_elf.dll") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/d3dcompiler_47.dll") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/libEGL.dll") casparcg_add_runtime_dependency("${CEF_BIN_PATH}/libGLESv2.dll") endif () set_property(GLOBAL PROPERTY USE_FOLDERS ON) add_definitions(-DUNICODE) add_definitions(-D_UNICODE) add_definitions(-DCASPAR_SOURCE_PREFIX="${CMAKE_CURRENT_SOURCE_DIR}") add_definitions(-D_WIN32_WINNT=0x601) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHa /Zi /W4 /WX /MP /fp:fast /Zm192 /FIcommon/compiler/vs/disable_silly_warnings.h") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D TBB_USE_ASSERT=1 /D TBB_USE_DEBUG /bigobj") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /Ot /Gy /bigobj") if (POLICY CMP0045) cmake_policy(SET CMP0045 OLD) endif () include(CMakeModules/PrecompiledHeader.cmake) add_subdirectory(accelerator) add_subdirectory(common) add_subdirectory(core) add_subdirectory(modules) add_subdirectory(protocol) add_subdirectory(shell) server-2.2.0-stable/src/CMakeModules/FindBoost.cmake000066400000000000000000002641761341175263200223060ustar00rootroot00000000000000# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #.rst: # FindBoost # --------- # # Find Boost include dirs and libraries # # Use this module by invoking find_package with the form:: # # find_package(Boost # [version] [EXACT] # Minimum or EXACT version e.g. 1.36.0 # [REQUIRED] # Fail with error if Boost is not found # [COMPONENTS ...] # Boost libraries by their canonical name # # e.g. "date_time" for "libboost_date_time" # [OPTIONAL_COMPONENTS ...] # # Optional Boost libraries by their canonical name) # ) # e.g. "date_time" for "libboost_date_time" # # This module finds headers and requested component libraries OR a CMake # package configuration file provided by a "Boost CMake" build. For the # latter case skip to the "Boost CMake" section below. For the former # case results are reported in variables:: # # Boost_FOUND - True if headers and requested libraries were found # Boost_INCLUDE_DIRS - Boost include directories # Boost_LIBRARY_DIRS - Link directories for Boost libraries # Boost_LIBRARIES - Boost component libraries to be linked # Boost__FOUND - True if component was found ( is upper-case) # Boost__LIBRARY - Libraries to link for component (may include # target_link_libraries debug/optimized keywords) # Boost_VERSION - BOOST_VERSION value from boost/version.hpp # Boost_LIB_VERSION - Version string appended to library filenames # Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) # Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) # Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) # Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) # - Pass to add_definitions() to have diagnostic # information about Boost's automatic linking # displayed during compilation # # This module reads hints about search locations from variables:: # # BOOST_ROOT - Preferred installation prefix # (or BOOSTROOT) # BOOST_INCLUDEDIR - Preferred include directory e.g. /include # BOOST_LIBRARYDIR - Preferred library directory e.g. /lib # Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not # specified by these hint variables. Default is OFF. # Boost_ADDITIONAL_VERSIONS # - List of Boost versions not known to this module # (Boost install locations may contain the version) # # and saves search results persistently in CMake cache entries:: # # Boost_INCLUDE_DIR - Directory containing Boost headers # Boost_LIBRARY_DIR_RELEASE - Directory containing release Boost libraries # Boost_LIBRARY_DIR_DEBUG - Directory containing debug Boost libraries # Boost__LIBRARY_DEBUG - Component library debug variant # Boost__LIBRARY_RELEASE - Component library release variant # # The following :prop_tgt:`IMPORTED` targets are also defined:: # # Boost::boost - Target for header-only dependencies # (Boost include directory) # Boost:: - Target for specific component dependency # (shared or static library); is lower- # case # Boost::diagnostic_definitions - interface target to enable diagnostic # information about Boost's automatic linking # during compilation (adds BOOST_LIB_DIAGNOSTIC) # Boost::disable_autolinking - interface target to disable automatic # linking with MSVC (adds BOOST_ALL_NO_LIB) # Boost::dynamic_linking - interface target to enable dynamic linking # linking with MSVC (adds BOOST_ALL_DYN_LINK) # # Implicit dependencies such as Boost::filesystem requiring # Boost::system will be automatically detected and satisfied, even # if system is not specified when using find_package and if # Boost::system is not added to target_link_libraries. If using # Boost::thread, then Threads::Threads will also be added automatically. # # It is important to note that the imported targets behave differently # than variables created by this module: multiple calls to # find_package(Boost) in the same directory or sub-directories with # different options (e.g. static or shared) will not override the # values of the targets created by the first call. # # Users may set these hints or results as cache entries. Projects # should not read these entries directly but instead use the above # result variables. Note that some hint names start in upper-case # "BOOST". One may specify these as environment variables if they are # not specified as CMake variables or cache entries. # # This module first searches for the Boost header files using the above # hint variables (excluding BOOST_LIBRARYDIR) and saves the result in # Boost_INCLUDE_DIR. Then it searches for requested component libraries # using the above hints (excluding BOOST_INCLUDEDIR and # Boost_ADDITIONAL_VERSIONS), "lib" directories near Boost_INCLUDE_DIR, # and the library name configuration settings below. It saves the # library directories in Boost_LIBRARY_DIR_DEBUG and # Boost_LIBRARY_DIR_RELEASE and individual library # locations in Boost__LIBRARY_DEBUG and Boost__LIBRARY_RELEASE. # When one changes settings used by previous searches in the same build # tree (excluding environment variables) this module discards previous # search results affected by the changes and searches again. # # Boost libraries come in many variants encoded in their file name. # Users or projects may tell this module which variant to find by # setting variables:: # # Boost_USE_DEBUG_LIBS - Set to ON or OFF to specify whether to search # and use the debug libraries. Default is ON. # Boost_USE_RELEASE_LIBS - Set to ON or OFF to specify whether to search # and use the release libraries. Default is ON. # Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded # libraries ('mt' tag). Default is ON. # Boost_USE_STATIC_LIBS - Set to ON to force the use of the static # libraries. Default is OFF. # Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use # libraries linked statically to the C++ runtime # ('s' tag). Default is platform dependent. # Boost_USE_DEBUG_RUNTIME - Set to ON or OFF to specify whether to use # libraries linked to the MS debug C++ runtime # ('g' tag). Default is ON. # Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a # debug Python build ('y' tag). Default is OFF. # Boost_USE_STLPORT - Set to ON to use libraries compiled with # STLPort ('p' tag). Default is OFF. # Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS # - Set to ON to use libraries compiled with # STLPort deprecated "native iostreams" # ('n' tag). Default is OFF. # Boost_COMPILER - Set to the compiler-specific library suffix # (e.g. "-gcc43"). Default is auto-computed # for the C++ compiler in use. A list may be # used if multiple compatible suffixes should # be tested for, in decreasing order of # preference. # Boost_THREADAPI - Suffix for "thread" component library name, # such as "pthread" or "win32". Names with # and without this suffix will both be tried. # Boost_NAMESPACE - Alternate namespace used to build boost with # e.g. if set to "myboost", will search for # myboost_thread instead of boost_thread. # # Other variables one may set to control this module are:: # # Boost_DEBUG - Set to ON to enable debug output from FindBoost. # Please enable this before filing any bug report. # Boost_DETAILED_FAILURE_MSG # - Set to ON to add detailed information to the # failure message even when the REQUIRED option # is not given to the find_package call. # Boost_REALPATH - Set to ON to resolve symlinks for discovered # libraries to assist with packaging. For example, # the "system" component library may be resolved to # "/usr/lib/libboost_system.so.1.42.0" instead of # "/usr/lib/libboost_system.so". This does not # affect linking and should not be enabled unless # the user needs this information. # Boost_LIBRARY_DIR - Default value for Boost_LIBRARY_DIR_RELEASE and # Boost_LIBRARY_DIR_DEBUG. # # On Visual Studio and Borland compilers Boost headers request automatic # linking to corresponding libraries. This requires matching libraries # to be linked explicitly or available in the link library search path. # In this case setting Boost_USE_STATIC_LIBS to OFF may not achieve # dynamic linking. Boost automatic linking typically requests static # libraries with a few exceptions (such as Boost.Python). Use:: # # add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) # # to ask Boost to report information about automatic linking requests. # # Example to find Boost headers only:: # # find_package(Boost 1.36.0) # if(Boost_FOUND) # include_directories(${Boost_INCLUDE_DIRS}) # add_executable(foo foo.cc) # endif() # # Example to find Boost libraries and use imported targets:: # # find_package(Boost 1.56 REQUIRED COMPONENTS # date_time filesystem iostreams) # add_executable(foo foo.cc) # target_link_libraries(foo Boost::date_time Boost::filesystem # Boost::iostreams) # # Example to find Boost headers and some *static* (release only) libraries:: # # set(Boost_USE_STATIC_LIBS ON) # only find static libs # set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and # set(Boost_USE_RELEASE_LIBS ON) # only find release libs # set(Boost_USE_MULTITHREADED ON) # set(Boost_USE_STATIC_RUNTIME OFF) # find_package(Boost 1.36.0 COMPONENTS date_time filesystem system ...) # if(Boost_FOUND) # include_directories(${Boost_INCLUDE_DIRS}) # add_executable(foo foo.cc) # target_link_libraries(foo ${Boost_LIBRARIES}) # endif() # # Boost CMake # ^^^^^^^^^^^ # # If Boost was built using the boost-cmake project it provides a package # configuration file for use with find_package's Config mode. This # module looks for the package configuration file called # BoostConfig.cmake or boost-config.cmake and stores the result in cache # entry "Boost_DIR". If found, the package configuration file is loaded # and this module returns with no further action. See documentation of # the Boost CMake package configuration for details on what it provides. # # Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. # Save project's policies cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST #------------------------------------------------------------------------------- # Before we go searching, check whether boost-cmake is available, unless the # user specifically asked NOT to search for boost-cmake. # # If Boost_DIR is set, this behaves as any find_package call would. If not, # it looks at BOOST_ROOT and BOOSTROOT to find Boost. # if (NOT Boost_NO_BOOST_CMAKE) # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, # since these are more conventional for Boost. if ("$ENV{Boost_DIR}" STREQUAL "") if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") set(ENV{Boost_DIR} $ENV{BOOSTROOT}) endif() endif() # Do the same find_package call but look specifically for the CMake version. # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no # need to delegate them to this find_package call. find_package(Boost QUIET NO_MODULE) mark_as_advanced(Boost_DIR) # If we found boost-cmake, then we're done. Print out what we found. # Otherwise let the rest of the module try to find it. if (Boost_FOUND) message(STATUS "Boost ${Boost_FIND_VERSION} found.") if (Boost_FIND_COMPONENTS) message(STATUS "Found Boost components:\n ${Boost_FIND_COMPONENTS}") endif() # Restore project's policies cmake_policy(POP) return() endif() endif() #------------------------------------------------------------------------------- # FindBoost functions & macros # ############################################ # # Check the existence of the libraries. # ############################################ # This macro was taken directly from the FindQt4.cmake file that is included # with the CMake distribution. This is NOT my work. All work was done by the # original authors of the FindQt4.cmake file. Only minor modifications were # made to remove references to Qt and make this file more generally applicable # And ELSE/ENDIF pairs were removed for readability. ######################################################################### macro(_Boost_ADJUST_LIB_VARS basename) if(Boost_INCLUDE_DIR ) if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for # single-config generators, set optimized and debug libraries get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if(_isMultiConfig OR CMAKE_BUILD_TYPE) set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) else() # For single-config generators where CMAKE_BUILD_TYPE has no value, # just use the release libraries set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) endif() # FIXME: This probably should be set for both cases set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) endif() # if only the release version was found, set the debug variable also to the release version if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) endif() # if only the debug version was found, set the release variable also to the debug version if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) endif() # If the debug & release library ends up being the same, omit the keywords if("${Boost_${basename}_LIBRARY_RELEASE}" STREQUAL "${Boost_${basename}_LIBRARY_DEBUG}") set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) endif() if(Boost_${basename}_LIBRARY AND Boost_${basename}_HEADER) set(Boost_${basename}_FOUND ON) if("x${basename}" STREQUAL "xTHREAD" AND NOT TARGET Threads::Threads) string(APPEND Boost_ERROR_REASON_THREAD " (missing dependency: Threads)") set(Boost_THREAD_FOUND OFF) endif() endif() endif() # Make variables changeable to the advanced user mark_as_advanced( Boost_${basename}_LIBRARY_RELEASE Boost_${basename}_LIBRARY_DEBUG ) endmacro() # Detect changes in used variables. # Compares the current variable value with the last one. # In short form: # v != v_LAST -> CHANGED = 1 # v is defined, v_LAST not -> CHANGED = 1 # v is not defined, but v_LAST is -> CHANGED = 1 # otherwise -> CHANGED = 0 # CHANGED is returned in variable named ${changed_var} macro(_Boost_CHANGE_DETECT changed_var) set(${changed_var} 0) foreach(v ${ARGN}) if(DEFINED _Boost_COMPONENTS_SEARCHED) if(${v}) if(_${v}_LAST) string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) else() set(_${v}_CHANGED 1) endif() elseif(_${v}_LAST) set(_${v}_CHANGED 1) endif() if(_${v}_CHANGED) set(${changed_var} 1) endif() else() set(_${v}_CHANGED 0) endif() endforeach() endmacro() # # Find the given library (var). # Use 'build_type' to support different lib paths for RELEASE or DEBUG builds # macro(_Boost_FIND_LIBRARY var build_type) find_library(${var} ${ARGN}) if(${var}) # If this is the first library found then save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. if(NOT Boost_LIBRARY_DIR_${build_type}) get_filename_component(_dir "${${var}}" PATH) set(Boost_LIBRARY_DIR_${build_type} "${_dir}" CACHE PATH "Boost library directory ${build_type}" FORCE) endif() elseif(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) # Try component-specific hints but do not save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. find_library(${var} HINTS ${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT} ${ARGN}) endif() # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is known then search only there. if(Boost_LIBRARY_DIR_${build_type}) set(_boost_LIBRARY_SEARCH_DIRS_${build_type} ${Boost_LIBRARY_DIR_${build_type}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " Boost_LIBRARY_DIR_${build_type} = ${Boost_LIBRARY_DIR_${build_type}}" " _boost_LIBRARY_SEARCH_DIRS_${build_type} = ${_boost_LIBRARY_SEARCH_DIRS_${build_type}}") endif() endif() endmacro() #------------------------------------------------------------------------------- # # Runs compiler with "-dumpversion" and parses major/minor # version with a regex. # function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION) string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\1\\2" _boost_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}) set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) endfunction() # # Take a list of libraries with "thread" in it # and prepend duplicates with "thread_${Boost_THREADAPI}" # at the front of the list # function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) set(_orig_libnames ${ARGN}) string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) endfunction() # # If a library is found, replace its cache entry with its REALPATH # function(_Boost_SWAP_WITH_REALPATH _library _docstring) if(${_library}) get_filename_component(_boost_filepathreal ${${_library}} REALPATH) unset(${_library} CACHE) set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") endif() endfunction() function(_Boost_CHECK_SPELLING _var) if(${_var}) string(TOUPPER ${_var} _var_UC) message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") endif() endfunction() # Guesses Boost's compiler prefix used in built library names # Returns the guess by setting the variable pointed to by _ret function(_Boost_GUESS_COMPILER_PREFIX _ret) if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") if(WIN32) set (_boost_COMPILER "-iw") else() set (_boost_COMPILER "-il") endif() elseif (GHSMULTI) set(_boost_COMPILER "-ghs") elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) set(_boost_COMPILER "-vc141;-vc140") elseif (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) set(_boost_COMPILER "-vc140") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18) set(_boost_COMPILER "-vc120") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17) set(_boost_COMPILER "-vc110") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) set(_boost_COMPILER "-vc100") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15) set(_boost_COMPILER "-vc90") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) set(_boost_COMPILER "-vc80") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10) set(_boost_COMPILER "-vc71") elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) # Good luck! set(_boost_COMPILER "-vc7") # yes, this is correct else() # VS 6.0 Good luck! set(_boost_COMPILER "-vc6") # yes, this is correct endif() elseif (BORLAND) set(_boost_COMPILER "-bcb") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") set(_boost_COMPILER "-sw") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "XL") set(_boost_COMPILER "-xlc") elseif (MINGW) if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 else() _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") endif() elseif (UNIX) if (CMAKE_COMPILER_IS_GNUCXX) if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 else() _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION) # Determine which version of GCC we have. if(APPLE) if(Boost_MINOR_VERSION) if(${Boost_MINOR_VERSION} GREATER 35) # In Boost 1.36.0 and newer, the mangled compiler name used # on Mac OS X/Darwin is "xgcc". set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") else() # In Boost <= 1.35.0, there is no mangled compiler name for # the Mac OS X/Darwin version of GCC. set(_boost_COMPILER "") endif() else() # We don't know the Boost version, so assume it's # pre-1.36.0. set(_boost_COMPILER "") endif() else() set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") endif() endif() endif () else() # TODO at least Boost_DEBUG here? set(_boost_COMPILER "") endif() set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) endfunction() # # Get component dependencies. Requires the dependencies to have been # defined for the Boost release version. # # component - the component to check # _ret - list of library dependencies # function(_Boost_COMPONENT_DEPENDENCIES component _ret) # Note: to add a new Boost release, run # # % cmake -DBOOST_DIR=/path/to/boost/source -P Utilities/Scripts/BoostScanDeps.cmake # # The output may be added in a new block below. If it's the same as # the previous release, simply update the version range of the block # for the previous release. Also check if any new components have # been added, and add any new components to # _Boost_COMPONENT_HEADERS. # # This information was originally generated by running # BoostScanDeps.cmake against every boost release to date supported # by FindBoost: # # % for version in /path/to/boost/sources/* # do # cmake -DBOOST_DIR=$version -P Utilities/Scripts/BoostScanDeps.cmake # done # # The output was then updated by search and replace with these regexes: # # - Strip message(STATUS) prefix dashes # s;^-- ;; # - Indent # s;^set(; set(;; # - Add conditionals # s;Scanning /path/to/boost/sources/boost_\(.*\)_\(.*\)_\(.*); elseif(NOT Boost_VERSION VERSION_LESS \10\20\3 AND Boost_VERSION VERSION_LESS xxxx); # # This results in the logic seen below, but will require the xxxx # replacing with the following Boost release version (or the next # minor version to be released, e.g. 1.59 was the latest at the time # of writing, making 1.60 the next, so 106000 is the needed version # number). Identical consecutive releases were then merged together # by updating the end range of the first block and removing the # following redundant blocks. # # Running the script against all historical releases should be # required only if the BoostScanDeps.cmake script logic is changed. # The addition of a new release should only require it to be run # against the new release. set(_Boost_IMPORTED_TARGETS TRUE) if(Boost_VERSION VERSION_LESS 103300) message(WARNING "Imported targets and dependency information not available for Boost version ${Boost_VERSION} (all versions older than 1.33)") set(_Boost_IMPORTED_TARGETS FALSE) elseif(NOT Boost_VERSION VERSION_LESS 103300 AND Boost_VERSION VERSION_LESS 103500) set(_Boost_IOSTREAMS_DEPENDENCIES regex thread) set(_Boost_REGEX_DEPENDENCIES thread) set(_Boost_WAVE_DEPENDENCIES filesystem thread) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 103500 AND Boost_VERSION VERSION_LESS 103600) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_WAVE_DEPENDENCIES filesystem system thread) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 103600 AND Boost_VERSION VERSION_LESS 103800) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_WAVE_DEPENDENCIES filesystem system thread) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 103800 AND Boost_VERSION VERSION_LESS 104300) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES date_time) set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 104300 AND Boost_VERSION VERSION_LESS 104400) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES date_time) set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 104400 AND Boost_VERSION VERSION_LESS 104500) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random serialization) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES date_time) set(_Boost_WAVE_DEPENDENCIES serialization filesystem system thread date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 104500 AND Boost_VERSION VERSION_LESS 104700) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES date_time) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 104700 AND Boost_VERSION VERSION_LESS 104800) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES date_time) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 104800 AND Boost_VERSION VERSION_LESS 105000) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES date_time) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 105000 AND Boost_VERSION VERSION_LESS 105300) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES chrono system date_time) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 105300 AND Boost_VERSION VERSION_LESS 105400) set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 105400 AND Boost_VERSION VERSION_LESS 105500) set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 105500 AND Boost_VERSION VERSION_LESS 105600) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 105600 AND Boost_VERSION VERSION_LESS 105900) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_RANDOM_DEPENDENCIES system) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 105900 AND Boost_VERSION VERSION_LESS 106000) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono atomic) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_RANDOM_DEPENDENCIES system) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 106000 AND Boost_VERSION VERSION_LESS 106100) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_RANDOM_DEPENDENCIES system) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_TIMER_DEPENDENCIES chrono system) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 106100 AND Boost_VERSION VERSION_LESS 106200) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_RANDOM_DEPENDENCIES system) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106300) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_RANDOM_DEPENDENCIES system) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) elseif(NOT Boost_VERSION VERSION_LESS 106300 AND Boost_VERSION VERSION_LESS 106500) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_COROUTINE2_DEPENDENCIES context fiber thread chrono system date_time) set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_RANDOM_DEPENDENCIES system) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) else() if(NOT Boost_VERSION VERSION_LESS 106500) set(_Boost_CHRONO_DEPENDENCIES system) set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) set(_Boost_COROUTINE_DEPENDENCIES context system) set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) set(_Boost_FILESYSTEM_DEPENDENCIES system) set(_Boost_IOSTREAMS_DEPENDENCIES regex) set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) set(_Boost_MPI_DEPENDENCIES serialization) set(_Boost_MPI_PYTHON_DEPENDENCIES python mpi serialization) set(_Boost_NUMPY_DEPENDENCIES python) set(_Boost_RANDOM_DEPENDENCIES system) set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) endif() if(NOT Boost_VERSION VERSION_LESS 106700) message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") endif() endif() string(TOUPPER ${component} uppercomponent) set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) string(REGEX REPLACE ";" " " _boost_DEPS_STRING "${_Boost_${uppercomponent}_DEPENDENCIES}") if (NOT _boost_DEPS_STRING) set(_boost_DEPS_STRING "(none)") endif() # message(STATUS "Dependencies for Boost::${component}: ${_boost_DEPS_STRING}") endfunction() # # Get component headers. This is the primary header (or headers) for # a given component, and is used to check that the headers are present # as well as the library itself as an extra sanity check of the build # environment. # # component - the component to check # _hdrs # function(_Boost_COMPONENT_HEADERS component _hdrs) # Note: new boost components will require adding here. The header # must be present in all versions of Boost providing a library. set(_Boost_ATOMIC_HEADERS "boost/atomic.hpp") set(_Boost_CHRONO_HEADERS "boost/chrono.hpp") set(_Boost_CONTAINER_HEADERS "boost/container/container_fwd.hpp") set(_Boost_CONTEXT_HEADERS "boost/context/all.hpp") set(_Boost_COROUTINE_HEADERS "boost/coroutine/all.hpp") set(_Boost_DATE_TIME_HEADERS "boost/date_time/date.hpp") set(_Boost_EXCEPTION_HEADERS "boost/exception/exception.hpp") set(_Boost_FIBER_HEADERS "boost/fiber/all.hpp") set(_Boost_FILESYSTEM_HEADERS "boost/filesystem/path.hpp") set(_Boost_GRAPH_HEADERS "boost/graph/adjacency_list.hpp") set(_Boost_GRAPH_PARALLEL_HEADERS "boost/graph/adjacency_list.hpp") set(_Boost_IOSTREAMS_HEADERS "boost/iostreams/stream.hpp") set(_Boost_LOCALE_HEADERS "boost/locale.hpp") set(_Boost_LOG_HEADERS "boost/log/core.hpp") set(_Boost_LOG_SETUP_HEADERS "boost/log/detail/setup_config.hpp") set(_Boost_MATH_HEADERS "boost/math_fwd.hpp") set(_Boost_MATH_C99_HEADERS "boost/math/tr1.hpp") set(_Boost_MATH_C99F_HEADERS "boost/math/tr1.hpp") set(_Boost_MATH_C99L_HEADERS "boost/math/tr1.hpp") set(_Boost_MATH_TR1_HEADERS "boost/math/tr1.hpp") set(_Boost_MATH_TR1F_HEADERS "boost/math/tr1.hpp") set(_Boost_MATH_TR1L_HEADERS "boost/math/tr1.hpp") set(_Boost_MPI_HEADERS "boost/mpi.hpp") set(_Boost_MPI_PYTHON_HEADERS "boost/mpi/python/config.hpp") set(_Boost_NUMPY_HEADERS "boost/python/numpy.hpp") set(_Boost_PRG_EXEC_MONITOR_HEADERS "boost/test/prg_exec_monitor.hpp") set(_Boost_PROGRAM_OPTIONS_HEADERS "boost/program_options.hpp") set(_Boost_PYTHON_HEADERS "boost/python.hpp") set(_Boost_RANDOM_HEADERS "boost/random.hpp") set(_Boost_REGEX_HEADERS "boost/regex.hpp") set(_Boost_SERIALIZATION_HEADERS "boost/serialization/serialization.hpp") set(_Boost_SIGNALS_HEADERS "boost/signals.hpp") set(_Boost_SYSTEM_HEADERS "boost/system/config.hpp") set(_Boost_TEST_EXEC_MONITOR_HEADERS "boost/test/test_exec_monitor.hpp") set(_Boost_THREAD_HEADERS "boost/thread.hpp") set(_Boost_TIMER_HEADERS "boost/timer.hpp") set(_Boost_TYPE_ERASURE_HEADERS "boost/type_erasure/config.hpp") set(_Boost_UNIT_TEST_FRAMEWORK_HEADERS "boost/test/framework.hpp") set(_Boost_WAVE_HEADERS "boost/wave.hpp") set(_Boost_WSERIALIZATION_HEADERS "boost/archive/text_wiarchive.hpp") if(WIN32) set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") endif() string(TOUPPER ${component} uppercomponent) set(${_hdrs} ${_Boost_${uppercomponent}_HEADERS} PARENT_SCOPE) string(REGEX REPLACE ";" " " _boost_HDRS_STRING "${_Boost_${uppercomponent}_HEADERS}") if (NOT _boost_HDRS_STRING) set(_boost_HDRS_STRING "(none)") endif() # message(STATUS "Headers for Boost::${component}: ${_boost_HDRS_STRING}") endfunction() # # Determine if any missing dependencies require adding to the component list. # # Sets _Boost_${COMPONENT}_DEPENDENCIES for each required component, # plus _Boost_IMPORTED_TARGETS (TRUE if imported targets should be # defined; FALSE if dependency information is unavailable). # # componentvar - the component list variable name # extravar - the indirect dependency list variable name # # function(_Boost_MISSING_DEPENDENCIES componentvar extravar) # _boost_unprocessed_components - list of components requiring processing # _boost_processed_components - components already processed (or currently being processed) # _boost_new_components - new components discovered for future processing # list(APPEND _boost_unprocessed_components ${${componentvar}}) while(_boost_unprocessed_components) list(APPEND _boost_processed_components ${_boost_unprocessed_components}) foreach(component ${_boost_unprocessed_components}) string(TOUPPER ${component} uppercomponent) set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) _Boost_COMPONENT_DEPENDENCIES("${component}" _Boost_${uppercomponent}_DEPENDENCIES) set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES}) if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components)) list(APPEND _boost_new_components ${componentdep}) endif() endforeach() endforeach() set(_boost_unprocessed_components ${_boost_new_components}) unset(_boost_new_components) endwhile() set(_boost_extra_components ${_boost_processed_components}) if(_boost_extra_components AND ${componentvar}) list(REMOVE_ITEM _boost_extra_components ${${componentvar}}) endif() set(${componentvar} ${_boost_processed_components} PARENT_SCOPE) set(${extravar} ${_boost_extra_components} PARENT_SCOPE) endfunction() # # Some boost libraries may require particular set of compler features. # The very first one was `boost::fiber` introduced in Boost 1.62. # One can check required compiler features of it in # `${Boost_ROOT}/libs/fiber/build/Jamfile.v2`. # function(_Boost_COMPILER_FEATURES component _ret) # Boost >= 1.62 and < 1.67 if(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106700) set(_Boost_FIBER_COMPILER_FEATURES cxx_alias_templates cxx_auto_type cxx_constexpr cxx_defaulted_functions cxx_final cxx_lambdas cxx_noexcept cxx_nullptr cxx_rvalue_references cxx_thread_local cxx_variadic_templates ) endif() string(TOUPPER ${component} uppercomponent) set(${_ret} ${_Boost_${uppercomponent}_COMPILER_FEATURES} PARENT_SCOPE) endfunction() # # Update library search directory hint variable with paths used by prebuilt boost binaries. # # Prebuilt windows binaries (https://sourceforge.net/projects/boost/files/boost-binaries/) # have library directories named using MSVC compiler version and architecture. # This function would append corresponding directories if MSVC is a current compiler, # so having `BOOST_ROOT` would be enough to specify to find everything. # function(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") if(CMAKE_SIZEOF_VOID_P EQUAL 8) set(_arch_suffix 64) else() set(_arch_suffix 32) endif() if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.10) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.1) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 18) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-12.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 17) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-11.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-10.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-9.0) elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14) list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-8.0) endif() set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE) endif() endfunction() # # End functions/macros # #------------------------------------------------------------------------------- #------------------------------------------------------------------------------- # main. #------------------------------------------------------------------------------- # If the user sets Boost_LIBRARY_DIR, use it as the default for both # configurations. if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR) set(Boost_LIBRARY_DIR_RELEASE "${Boost_LIBRARY_DIR}") endif() if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR) set(Boost_LIBRARY_DIR_DEBUG "${Boost_LIBRARY_DIR}") endif() if(NOT DEFINED Boost_USE_DEBUG_LIBS) set(Boost_USE_DEBUG_LIBS TRUE) endif() if(NOT DEFINED Boost_USE_RELEASE_LIBS) set(Boost_USE_RELEASE_LIBS TRUE) endif() if(NOT DEFINED Boost_USE_MULTITHREADED) set(Boost_USE_MULTITHREADED TRUE) endif() if(NOT DEFINED Boost_USE_DEBUG_RUNTIME) set(Boost_USE_DEBUG_RUNTIME TRUE) endif() # Check the version of Boost against the requested version. if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") endif() if(Boost_FIND_VERSION_EXACT) # The version may appear in a directory with or without the patch # level, even when the patch level is non-zero. set(_boost_TEST_VERSIONS "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") else() # The user has not requested an exact version. Among known # versions, find those that are acceptable to the user request. # # Note: When adding a new Boost release, also update the dependency # information in _Boost_COMPONENT_DEPENDENCIES and # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" "1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" "1.34" "1.33.1" "1.33.0" "1.33") set(_boost_TEST_VERSIONS) if(Boost_FIND_VERSION) set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") # Select acceptable versions. foreach(version ${_Boost_KNOWN_VERSIONS}) if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") # This version is high enough. list(APPEND _boost_TEST_VERSIONS "${version}") elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") # This version is a short-form for the requested version with # the patch level dropped. list(APPEND _boost_TEST_VERSIONS "${version}") endif() endforeach() else() # Any version is acceptable. set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") endif() endif() # The reason that we failed to find Boost. This will be set to a # user-friendly message when we fail to find some necessary piece of # Boost. set(Boost_ERROR_REASON) if(Boost_DEBUG) # Output some of their choices message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") endif() # Supply Boost_LIB_DIAGNOSTIC_DEFINITIONS as a convenience target. It # will only contain any interface definitions on WIN32, but is created # on all platforms to keep end user code free from platform dependent # code. Also provide convenience targets to disable autolinking and # enable dynamic linking. if(NOT TARGET Boost::diagnostic_definitions) add_library(Boost::diagnostic_definitions INTERFACE IMPORTED) add_library(Boost::disable_autolinking INTERFACE IMPORTED) add_library(Boost::dynamic_linking INTERFACE IMPORTED) endif() if(WIN32) # In windows, automatic linking is performed, so you do not have # to specify the libraries. If you are linking to a dynamic # runtime, then you can choose to link to either a static or a # dynamic Boost library, the default is to do a static link. You # can alter this for a specific library "whatever" by defining # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be # linked dynamically. Alternatively you can force all Boost # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. # This feature can be disabled for Boost library "whatever" by # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining # BOOST_ALL_NO_LIB. # If you want to observe which libraries are being linked against # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking # code to emit a #pragma message each time a library is selected # for linking. set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") set_target_properties(Boost::diagnostic_definitions PROPERTIES INTERFACE_COMPILE_DEFINITIONS "BOOST_LIB_DIAGNOSTIC") set_target_properties(Boost::disable_autolinking PROPERTIES INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_NO_LIB") set_target_properties(Boost::dynamic_linking PROPERTIES INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_DYN_LINK") endif() _Boost_CHECK_SPELLING(Boost_ROOT) _Boost_CHECK_SPELLING(Boost_LIBRARYDIR) _Boost_CHECK_SPELLING(Boost_INCLUDEDIR) # Collect environment variable inputs as hints. Do not consider changes. foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) set(_env $ENV{${v}}) if(_env) file(TO_CMAKE_PATH "${_env}" _ENV_${v}) else() set(_ENV_${v} "") endif() endforeach() if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") endif() # Collect inputs and cached results. Detect changes since the last run. if(NOT BOOST_ROOT AND BOOSTROOT) set(BOOST_ROOT "${BOOSTROOT}") endif() set(_Boost_VARS_DIR BOOST_ROOT Boost_NO_SYSTEM_PATHS ) if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Declared as CMake or Environmental Variables:") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " BOOST_ROOT = ${BOOST_ROOT}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") endif() # ------------------------------------------------------------------------ # Search for Boost include DIR # ------------------------------------------------------------------------ set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) _Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) # Clear Boost_INCLUDE_DIR if it did not change but other input affecting the # location did. We will find a new one based on the new inputs. if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) unset(Boost_INCLUDE_DIR CACHE) endif() if(NOT Boost_INCLUDE_DIR) set(_boost_INCLUDE_SEARCH_DIRS "") if(BOOST_INCLUDEDIR) list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) elseif(_ENV_BOOST_INCLUDEDIR) list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) endif() if( BOOST_ROOT ) list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) elseif( _ENV_BOOST_ROOT ) list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) endif() if( Boost_NO_SYSTEM_PATHS) list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) else() if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") foreach(ver ${_Boost_KNOWN_VERSIONS}) string(REPLACE "." "_" ver "${ver}") list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS "C:/local/boost_${ver}") endforeach() endif() list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS C:/boost/include C:/boost /sw/local/include ) endif() # Try to find Boost by stepping backwards through the Boost versions # we know about. # Build a list of path suffixes for each version. set(_boost_PATH_SUFFIXES) foreach(_boost_VER ${_boost_TEST_VERSIONS}) # Add in a path suffix, based on the required version, ideally # we could read this from version.hpp, but for that to work we'd # need to know the include dir already set(_boost_BOOSTIFIED_VERSION) # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 if(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)") set(_boost_BOOSTIFIED_VERSION "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}_${CMAKE_MATCH_3}") elseif(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)") set(_boost_BOOSTIFIED_VERSION "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}") endif() list(APPEND _boost_PATH_SUFFIXES "boost-${_boost_BOOSTIFIED_VERSION}" "boost_${_boost_BOOSTIFIED_VERSION}" "boost/boost-${_boost_BOOSTIFIED_VERSION}" "boost/boost_${_boost_BOOSTIFIED_VERSION}" ) endforeach() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Include debugging info:") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") endif() # Look for a standard boost header file. find_path(Boost_INCLUDE_DIR NAMES boost/config.hpp HINTS ${_boost_INCLUDE_SEARCH_DIRS} PATH_SUFFIXES ${_boost_PATH_SUFFIXES} ) endif() # ------------------------------------------------------------------------ # Extract version information from version.hpp # ------------------------------------------------------------------------ # Set Boost_FOUND based only on header location and version. # It will be updated below for component libraries. if(Boost_INCLUDE_DIR) if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") endif() # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp set(Boost_VERSION 0) set(Boost_LIB_VERSION "") file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") set(_Boost_VERSION_REGEX "([0-9]+)") set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") foreach(v VERSION LIB_VERSION) if("${_boost_VERSION_HPP_CONTENTS}" MATCHES "#define BOOST_${v} ${_Boost_${v}_REGEX}") set(Boost_${v} "${CMAKE_MATCH_1}") endif() endforeach() unset(_boost_VERSION_HPP_CONTENTS) math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") string(APPEND Boost_ERROR_REASON "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "version.hpp reveals boost " "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") endif() if(Boost_FIND_VERSION) # Set Boost_FOUND based on requested version. set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") set(Boost_FOUND 0) set(_Boost_VERSION_AGE "old") elseif(Boost_FIND_VERSION_EXACT AND NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") set(Boost_FOUND 0) set(_Boost_VERSION_AGE "new") else() set(Boost_FOUND 1) endif() if(NOT Boost_FOUND) # State that we found a version of Boost that is too new or too old. string(APPEND Boost_ERROR_REASON "\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") if (Boost_FIND_VERSION_PATCH) string(APPEND Boost_ERROR_REASON ".${Boost_FIND_VERSION_PATCH}") endif () if (NOT Boost_FIND_VERSION_EXACT) string(APPEND Boost_ERROR_REASON " (or newer)") endif () string(APPEND Boost_ERROR_REASON ".") endif () else() # Caller will accept any Boost version. set(Boost_FOUND 1) endif() else() set(Boost_FOUND 0) string(APPEND Boost_ERROR_REASON "Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") endif() # ------------------------------------------------------------------------ # Prefix initialization # ------------------------------------------------------------------------ set(Boost_LIB_PREFIX "") if ( (GHSMULTI AND Boost_USE_STATIC_LIBS) OR (WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) ) set(Boost_LIB_PREFIX "lib") endif() if ( NOT Boost_NAMESPACE ) set(Boost_NAMESPACE "boost") endif() # ------------------------------------------------------------------------ # Suffix initialization and compiler suffix detection. # ------------------------------------------------------------------------ set(_Boost_VARS_NAME Boost_NAMESPACE Boost_COMPILER Boost_THREADAPI Boost_USE_DEBUG_PYTHON Boost_USE_MULTITHREADED Boost_USE_STATIC_LIBS Boost_USE_STATIC_RUNTIME Boost_USE_STLPORT Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS ) _Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) # Setting some more suffixes for the library if (Boost_COMPILER) set(_boost_COMPILER ${Boost_COMPILER}) if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "using user-specified Boost_COMPILER = ${_boost_COMPILER}") endif() else() # Attempt to guess the compiler suffix # NOTE: this is not perfect yet, if you experience any issues # please report them and use the Boost_COMPILER variable # to work around the problems. _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "guessed _boost_COMPILER = ${_boost_COMPILER}") endif() endif() set (_boost_MULTITHREADED "-mt") if( NOT Boost_USE_MULTITHREADED ) set (_boost_MULTITHREADED "") endif() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") endif() #====================== # Systematically build up the Boost ABI tag for the 'tagged' and 'versioned' layouts # http://boost.org/doc/libs/1_66_0/more/getting_started/windows.html#library-naming # http://boost.org/doc/libs/1_66_0/boost/config/auto_link.hpp # http://boost.org/doc/libs/1_66_0/tools/build/src/tools/common.jam # http://boost.org/doc/libs/1_66_0/boostcpp.jam set( _boost_RELEASE_ABI_TAG "-") set( _boost_DEBUG_ABI_TAG "-") # Key Use this library when: # s linking statically to the C++ standard library and # compiler runtime support libraries. if(Boost_USE_STATIC_RUNTIME) set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") endif() # g using debug versions of the standard and runtime # support libraries if(WIN32 AND Boost_USE_DEBUG_RUNTIME) if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang" OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") string(APPEND _boost_DEBUG_ABI_TAG "g") endif() endif() # y using special debug build of python if(Boost_USE_DEBUG_PYTHON) string(APPEND _boost_DEBUG_ABI_TAG "y") endif() # d using a debug version of your code string(APPEND _boost_DEBUG_ABI_TAG "d") # p using the STLport standard library rather than the # default one supplied with your compiler if(Boost_USE_STLPORT) string(APPEND _boost_RELEASE_ABI_TAG "p") string(APPEND _boost_DEBUG_ABI_TAG "p") endif() # n using the STLport deprecated "native iostreams" feature # removed from the documentation in 1.43.0 but still present in # boost/config/auto_link.hpp if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) string(APPEND _boost_RELEASE_ABI_TAG "n") string(APPEND _boost_DEBUG_ABI_TAG "n") endif() # -x86 Architecture and address model tag # First character is the architecture, then word-size, either 32 or 64 # Only used in 'versioned' layout, added in Boost 1.66.0 set(_boost_ARCHITECTURE_TAG "") # {CMAKE_CXX_COMPILER_ARCHITECTURE_ID} is not currently set for all compilers if(NOT "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "x" AND NOT Boost_VERSION VERSION_LESS 106600) string(APPEND _boost_ARCHITECTURE_TAG "-") # This needs to be kept in-sync with the section of CMakePlatformId.h.in # inside 'defined(_WIN32) && defined(_MSC_VER)' if(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "IA64") string(APPEND _boost_ARCHITECTURE_TAG "i") elseif(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "X86" OR ${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "x64") string(APPEND _boost_ARCHITECTURE_TAG "x") elseif(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} MATCHES "^ARM") string(APPEND _boost_ARCHITECTURE_TAG "a") elseif(${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} STREQUAL "MIPS") string(APPEND _boost_ARCHITECTURE_TAG "m") endif() if(CMAKE_SIZEOF_VOID_P EQUAL 8) string(APPEND _boost_ARCHITECTURE_TAG "64") else() string(APPEND _boost_ARCHITECTURE_TAG "32") endif() endif() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") endif() # ------------------------------------------------------------------------ # Begin finding boost libraries # ------------------------------------------------------------------------ set(_Boost_VARS_LIB "") foreach(c DEBUG RELEASE) set(_Boost_VARS_LIB_${c} BOOST_LIBRARYDIR Boost_LIBRARY_DIR_${c}) list(APPEND _Boost_VARS_LIB ${_Boost_VARS_LIB_${c}}) _Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR_${c} ${_Boost_VARS_DIR} ${_Boost_VARS_LIB_${c}} Boost_INCLUDE_DIR) # Clear Boost_LIBRARY_DIR_${c} if it did not change but other input affecting the # location did. We will find a new one based on the new inputs. if(_Boost_CHANGE_LIBDIR_${c} AND NOT _Boost_LIBRARY_DIR_${c}_CHANGED) unset(Boost_LIBRARY_DIR_${c} CACHE) endif() # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is set, prefer its value. if(Boost_LIBRARY_DIR_${c}) set(_boost_LIBRARY_SEARCH_DIRS_${c} ${Boost_LIBRARY_DIR_${c}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) else() set(_boost_LIBRARY_SEARCH_DIRS_${c} "") if(BOOST_LIBRARYDIR) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_LIBRARYDIR}) elseif(_ENV_BOOST_LIBRARYDIR) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_LIBRARYDIR}) endif() if(BOOST_ROOT) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${BOOST_ROOT}") elseif(_ENV_BOOST_ROOT) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${_ENV_BOOST_ROOT}") endif() list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${Boost_INCLUDE_DIR}/lib ${Boost_INCLUDE_DIR}/../lib ${Boost_INCLUDE_DIR}/stage/lib ) _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}/..") _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}") if( Boost_NO_SYSTEM_PATHS ) list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) else() foreach(ver ${_Boost_KNOWN_VERSIONS}) string(REPLACE "." "_" ver "${ver}") _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/local/boost_${ver}") endforeach() _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS C:/boost/lib C:/boost /sw/local/lib ) endif() endif() endforeach() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "_boost_LIBRARY_SEARCH_DIRS_RELEASE = ${_boost_LIBRARY_SEARCH_DIRS_RELEASE}" "_boost_LIBRARY_SEARCH_DIRS_DEBUG = ${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") endif() # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES if( Boost_USE_STATIC_LIBS ) set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) if(WIN32) list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a) else() set(CMAKE_FIND_LIBRARY_SUFFIXES .a) endif() endif() # We want to use the tag inline below without risking double dashes if(_boost_RELEASE_ABI_TAG) if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") set(_boost_RELEASE_ABI_TAG "") endif() endif() if(_boost_DEBUG_ABI_TAG) if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") set(_boost_DEBUG_ABI_TAG "") endif() endif() # The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled # on WIN32 was to: # 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) # 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) # We maintain this behavior since changing it could break people's builds. # To disable the ambiguous behavior, the user need only # set Boost_USE_STATIC_RUNTIME either ON or OFF. set(_boost_STATIC_RUNTIME_WORKAROUND false) if(WIN32 AND Boost_USE_STATIC_LIBS) if(NOT DEFINED Boost_USE_STATIC_RUNTIME) set(_boost_STATIC_RUNTIME_WORKAROUND TRUE) endif() endif() # On versions < 1.35, remove the System library from the considered list # since it wasn't added until 1.35. if(Boost_VERSION AND Boost_FIND_COMPONENTS) if(Boost_VERSION LESS 103500) list(REMOVE_ITEM Boost_FIND_COMPONENTS system) endif() endif() # Additional components may be required via component dependencies. # Add any missing components to the list. _Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS) # If thread is required, get the thread libs as a dependency if("thread" IN_LIST Boost_FIND_COMPONENTS) if(Boost_FIND_QUIETLY) set(_Boost_find_quiet QUIET) else() set(_Boost_find_quiet "") endif() find_package(Threads ${_Boost_find_quiet}) unset(_Boost_find_quiet) endif() # If the user changed any of our control inputs flush previous results. if(_Boost_CHANGE_LIBDIR_DEBUG OR _Boost_CHANGE_LIBDIR_RELEASE OR _Boost_CHANGE_LIBNAME) foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) string(TOUPPER ${COMPONENT} UPPERCOMPONENT) foreach(c DEBUG RELEASE) set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) unset(${_var} CACHE) set(${_var} "${_var}-NOTFOUND") endforeach() endforeach() set(_Boost_COMPONENTS_SEARCHED "") endif() foreach(COMPONENT ${Boost_FIND_COMPONENTS}) string(TOUPPER ${COMPONENT} UPPERCOMPONENT) set( _boost_docstring_release "Boost ${COMPONENT} library (release)") set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") # Compute component-specific hints. set(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT "") if(${COMPONENT} STREQUAL "mpi" OR ${COMPONENT} STREQUAL "mpi_python" OR ${COMPONENT} STREQUAL "graph_parallel") foreach(lib ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES}) if(IS_ABSOLUTE "${lib}") get_filename_component(libdir "${lib}" PATH) string(REPLACE "\\" "/" libdir "${libdir}") list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT ${libdir}) endif() endforeach() endif() # Consolidate and report component-specific hints. if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Component-specific library search paths for ${COMPONENT}: " "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT}") endif() endif() # # Find headers # _Boost_COMPONENT_HEADERS("${COMPONENT}" Boost_${UPPERCOMPONENT}_HEADER_NAME) # Look for a standard boost header file. if(Boost_${UPPERCOMPONENT}_HEADER_NAME) if(EXISTS "${Boost_INCLUDE_DIR}/${Boost_${UPPERCOMPONENT}_HEADER_NAME}") set(Boost_${UPPERCOMPONENT}_HEADER ON) else() set(Boost_${UPPERCOMPONENT}_HEADER OFF) endif() else() set(Boost_${UPPERCOMPONENT}_HEADER ON) message(WARNING "No header defined for ${COMPONENT}; skipping header check") endif() # # Find RELEASE libraries # unset(_boost_RELEASE_NAMES) foreach(compiler IN LISTS _boost_COMPILER) list(APPEND _boost_RELEASE_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ) endforeach() list(APPEND _boost_RELEASE_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) if(_boost_STATIC_RUNTIME_WORKAROUND) set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") foreach(compiler IN LISTS _boost_COMPILER) list(APPEND _boost_RELEASE_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) endforeach() list(APPEND _boost_RELEASE_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) endif() if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) endif() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") endif() # if Boost_LIBRARY_DIR_RELEASE is not defined, # but Boost_LIBRARY_DIR_DEBUG is, look there first for RELEASE libs if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR_DEBUG) list(INSERT _boost_LIBRARY_SEARCH_DIRS_RELEASE 0 ${Boost_LIBRARY_DIR_DEBUG}) endif() # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_RELEASE}") if(Boost_USE_RELEASE_LIBS) _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE RELEASE NAMES ${_boost_RELEASE_NAMES} HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} NAMES_PER_DIR DOC "${_boost_docstring_release}" ) endif() # # Find DEBUG libraries # unset(_boost_DEBUG_NAMES) foreach(compiler IN LISTS _boost_COMPILER) list(APPEND _boost_DEBUG_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ) endforeach() list(APPEND _boost_DEBUG_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT} ) if(_boost_STATIC_RUNTIME_WORKAROUND) set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") foreach(compiler IN LISTS _boost_COMPILER) list(APPEND _boost_DEBUG_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) endforeach() list(APPEND _boost_DEBUG_NAMES ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${COMPONENT}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) endif() if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) endif() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") endif() # if Boost_LIBRARY_DIR_DEBUG is not defined, # but Boost_LIBRARY_DIR_RELEASE is, look there first for DEBUG libs if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR_RELEASE) list(INSERT _boost_LIBRARY_SEARCH_DIRS_DEBUG 0 ${Boost_LIBRARY_DIR_RELEASE}) endif() # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") if(Boost_USE_DEBUG_LIBS) _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG DEBUG NAMES ${_boost_DEBUG_NAMES} HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} NAMES_PER_DIR DOC "${_boost_docstring_debug}" ) endif () if(Boost_REALPATH) _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) endif() _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) # Check if component requires some compiler features _Boost_COMPILER_FEATURES(${COMPONENT} _Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) endforeach() # Restore the original find library ordering if( Boost_USE_STATIC_LIBS ) set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) endif() # ------------------------------------------------------------------------ # End finding boost libraries # ------------------------------------------------------------------------ set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) set(Boost_LIBRARY_DIRS) if(Boost_LIBRARY_DIR_RELEASE) list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_RELEASE}) endif() if(Boost_LIBRARY_DIR_DEBUG) list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_DEBUG}) endif() if(Boost_LIBRARY_DIRS) list(REMOVE_DUPLICATES Boost_LIBRARY_DIRS) endif() # The above setting of Boost_FOUND was based only on the header files. # Update it for the requested component libraries. if(Boost_FOUND) # The headers were found. Check for requested component libs. set(_boost_CHECKED_COMPONENT FALSE) set(_Boost_MISSING_COMPONENTS "") foreach(COMPONENT ${Boost_FIND_COMPONENTS}) string(TOUPPER ${COMPONENT} UPPERCOMPONENT) set(_boost_CHECKED_COMPONENT TRUE) if(NOT Boost_${UPPERCOMPONENT}_FOUND AND Boost_FIND_REQUIRED_${COMPONENT}) list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) endif() endforeach() if(_Boost_MISSING_COMPONENTS AND _Boost_EXTRA_FIND_COMPONENTS) # Optional indirect dependencies are not counted as missing. list(REMOVE_ITEM _Boost_MISSING_COMPONENTS ${_Boost_EXTRA_FIND_COMPONENTS}) endif() if(Boost_DEBUG) message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") endif() if (_Boost_MISSING_COMPONENTS) set(Boost_FOUND 0) # We were unable to find some libraries, so generate a sensible # error message that lists the libraries we were unable to find. string(APPEND Boost_ERROR_REASON "\nCould not find the following") if(Boost_USE_STATIC_LIBS) string(APPEND Boost_ERROR_REASON " static") endif() string(APPEND Boost_ERROR_REASON " Boost libraries:\n") foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) string(TOUPPER ${COMPONENT} UPPERCOMPONENT) string(APPEND Boost_ERROR_REASON " ${Boost_NAMESPACE}_${COMPONENT}${Boost_ERROR_REASON_${UPPERCOMPONENT}}\n") endforeach() list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) string(APPEND Boost_ERROR_REASON "No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") else () string(APPEND Boost_ERROR_REASON "Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") endif () endif () if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) # Compatibility Code for backwards compatibility with CMake # 2.4's FindBoost module. # Look for the boost library path. # Note that the user may not have installed any libraries # so it is quite possible the Boost_LIBRARY_DIRS may not exist. set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) endif() if("${_boost_LIB_DIR}" MATCHES "/include$") # Strip off the trailing "/include" in the path. get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) endif() if(EXISTS "${_boost_LIB_DIR}/lib") string(APPEND _boost_LIB_DIR /lib) elseif(EXISTS "${_boost_LIB_DIR}/stage/lib") string(APPEND _boost_LIB_DIR "/stage/lib") else() set(_boost_LIB_DIR "") endif() if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) endif() endif() else() # Boost headers were not found so no components were found. foreach(COMPONENT ${Boost_FIND_COMPONENTS}) string(TOUPPER ${COMPONENT} UPPERCOMPONENT) set(Boost_${UPPERCOMPONENT}_FOUND 0) endforeach() endif() # ------------------------------------------------------------------------ # Add imported targets # ------------------------------------------------------------------------ if(Boost_FOUND) # For header-only libraries if(NOT TARGET Boost::boost) add_library(Boost::boost INTERFACE IMPORTED) if(Boost_INCLUDE_DIRS) set_target_properties(Boost::boost PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") endif() endif() foreach(COMPONENT ${Boost_FIND_COMPONENTS}) if(_Boost_IMPORTED_TARGETS AND NOT TARGET Boost::${COMPONENT}) string(TOUPPER ${COMPONENT} UPPERCOMPONENT) if(Boost_${UPPERCOMPONENT}_FOUND) if(Boost_USE_STATIC_LIBS) add_library(Boost::${COMPONENT} STATIC IMPORTED) else() # Even if Boost_USE_STATIC_LIBS is OFF, we might have static # libraries as a result. add_library(Boost::${COMPONENT} UNKNOWN IMPORTED) endif() if(Boost_INCLUDE_DIRS) set_target_properties(Boost::${COMPONENT} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") endif() if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY}") set_target_properties(Boost::${COMPONENT} PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" IMPORTED_LOCATION "${Boost_${UPPERCOMPONENT}_LIBRARY}") endif() if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(Boost::${COMPONENT} PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" IMPORTED_LOCATION_RELEASE "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") endif() if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG) set_target_properties(Boost::${COMPONENT} PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" IMPORTED_LOCATION_DEBUG "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") endif() if(_Boost_${UPPERCOMPONENT}_DEPENDENCIES) unset(_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES) foreach(dep ${_Boost_${UPPERCOMPONENT}_DEPENDENCIES}) list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Boost::${dep}) endforeach() if(COMPONENT STREQUAL "thread") list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Threads::Threads) endif() set_target_properties(Boost::${COMPONENT} PROPERTIES INTERFACE_LINK_LIBRARIES "${_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES}") endif() if(_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) set_target_properties(Boost::${COMPONENT} PROPERTIES INTERFACE_COMPILE_FEATURES "${_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES}") endif() endif() endif() endforeach() endif() # ------------------------------------------------------------------------ # Notification to end user about what was found # ------------------------------------------------------------------------ set(Boost_LIBRARIES "") if(Boost_FOUND) if(NOT Boost_FIND_QUIETLY) message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") if(Boost_FIND_COMPONENTS) message(STATUS "Found the following Boost libraries:") endif() endif() foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) if( Boost_${UPPERCOMPONENT}_FOUND ) if(NOT Boost_FIND_QUIETLY) message (STATUS " ${COMPONENT}") endif() list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) endif() endforeach() else() if(Boost_FIND_REQUIRED) message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") else() if(NOT Boost_FIND_QUIETLY) # we opt not to automatically output Boost_ERROR_REASON here as # it could be quite lengthy and somewhat imposing in its requests # Since Boost is not always a required dependency we'll leave this # up to the end-user. if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") else() message(STATUS "Could NOT find Boost") endif() endif() endif() endif() # Configure display of cache entries in GUI. foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) get_property(_type CACHE ${v} PROPERTY TYPE) if(_type) set_property(CACHE ${v} PROPERTY ADVANCED 1) if("x${_type}" STREQUAL "xUNINITIALIZED") if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") set_property(CACHE ${v} PROPERTY TYPE STRING) else() set_property(CACHE ${v} PROPERTY TYPE PATH) endif() endif() endif() endforeach() # Record last used values of input variables so we can # detect on the next run if the user changed them. foreach(v ${_Boost_VARS_INC} ${_Boost_VARS_LIB} ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} ) if(DEFINED ${v}) set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") else() unset(_${v}_LAST CACHE) endif() endforeach() # Maintain a persistent list of components requested anywhere since # the last flush. set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) list(SORT _Boost_COMPONENTS_SEARCHED) set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" CACHE INTERNAL "Components requested for this build tree.") # Restore project's policies cmake_policy(POP) server-2.2.0-stable/src/CMakeModules/FindCEF.cmake000066400000000000000000000040111341175263200215710ustar00rootroot00000000000000include(FindPackageHandleStandardArgs) SET(CEF_ROOT_DIR "" CACHE PATH "Path to a CEF distributed build") message(STATUS "Looking for Chromium Embedded Framework in ${CEF_ROOT_DIR}") find_path(CEF_INCLUDE_DIR "include/cef_version.h" HINTS ${CEF_ROOT_DIR}) if(APPLE) find_library(CEF_LIBRARY NAMES cef libcef cef.lib libcef.o "Chromium Embedded Framework" NO_DEFAULT_PATH PATHS ${CEF_ROOT_DIR} ${CEF_ROOT_DIR}/Release) find_library(CEFWRAPPER_LIBRARY NAMES cef_dll_wrapper libcef_dll_wrapper NO_DEFAULT_PATH PATHS ${CEF_ROOT_DIR}/build/libcef_dll/Release ${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Release ${CEF_ROOT_DIR}/build/libcef_dll ${CEF_ROOT_DIR}/build/libcef_dll_wrapper) else() find_library(CEF_LIBRARY NAMES cef libcef cef.lib libcef.o "Chromium Embedded Framework" PATHS ${CEF_ROOT_DIR} ${CEF_ROOT_DIR}/Release) find_library(CEFWRAPPER_LIBRARY NAMES cef_dll_wrapper libcef_dll_wrapper PATHS ${CEF_ROOT_DIR}/build/libcef_dll/Release ${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Release ${CEF_ROOT_DIR}/build/libcef_dll ${CEF_ROOT_DIR}/build/libcef_dll_wrapper ${CEF_ROOT_DIR}/Release) if(WIN32) find_library(CEFWRAPPER_LIBRARY_DEBUG NAMES cef_dll_wrapper libcef_dll_wrapper PATHS ${CEF_ROOT_DIR}/build/libcef_dll/Debug ${CEF_ROOT_DIR}/build/libcef_dll_wrapper/Debug) endif() endif() if(NOT CEF_LIBRARY) set(CEF_FOUND FALSE) message(FATAL_ERROR "Could not find the CEF shared library" ) return() endif() if(NOT CEFWRAPPER_LIBRARY) set(CEF_FOUND FALSE) message(FATAL_ERROR "Could not find the CEF wrapper library" ) return() endif() if(WIN32) set(CEF_LIBRARIES ${CEF_LIBRARY} optimized ${CEFWRAPPER_LIBRARY}) if (CEFWRAPPER_LIBRARY_DEBUG) list(APPEND CEF_LIBRARIES debug ${CEFWRAPPER_LIBRARY_DEBUG}) endif() else() set(CEF_LIBRARIES ${CEF_LIBRARY} ${CEFWRAPPER_LIBRARY}) endif() find_package_handle_standard_args(CEF DEFAULT_MSG CEF_LIBRARY CEFWRAPPER_LIBRARY CEF_INCLUDE_DIR) mark_as_advanced(CEF_LIBRARY CEF_WRAPPER_LIBRARY CEF_LIBRARIES CEF_INCLUDE_DIR) server-2.2.0-stable/src/CMakeModules/FindFFmpeg.cmake000066400000000000000000000136051341175263200223510ustar00rootroot00000000000000# vim: ts=2 sw=2 # - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) # # Once done this will define # FFMPEG_FOUND - System has the all required components. # FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. # FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. # FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. # # For each of the components it will additionally set. # - AVCODEC # - AVDEVICE # - AVFORMAT # - AVFILTER # - AVUTIL # - POSTPROC # - SWSCALE # the following variables will be defined # _FOUND - System has # _INCLUDE_DIRS - Include directory necessary for using the headers # _LIBRARIES - Link these to use # _DEFINITIONS - Compiler switches required for using # _VERSION - The components version # # Copyright (c) 2006, Matthias Kretz, # Copyright (c) 2008, Alexander Neundorf, # Copyright (c) 2011, Michael Jansen, # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. include(FindPackageHandleStandardArgs) # The default components were taken from a survey over other FindFFMPEG.cmake files if (NOT FFmpeg_FIND_COMPONENTS) set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL AVDEVICE AVFILTER POSTPROC SWSCALE SWRESAMPLE) endif () # ### Macro: set_component_found # # Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. # macro(set_component_found _component ) if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) # message(STATUS " - ${_component} found.") set(${_component}_FOUND TRUE) else () # message(STATUS " - ${_component} not found.") endif () endmacro() # ### Macro: find_component # # Checks for the given component by invoking pkgconfig and then looking up the libraries and # include directories. # macro(find_component _component _pkgconfig _library _header) if (NOT WIN32) # use pkg-config to get the directories and then use these values # in the FIND_PATH() and FIND_LIBRARY() calls find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(${_component} ${_pkgconfig}) endif () endif (NOT WIN32) find_path(${_component}_INCLUDE_DIRS ${_header} HINTS ${PC_LIB${_component}_INCLUDEDIR} ${PC_LIB${_component}_INCLUDE_DIRS} PATH_SUFFIXES ffmpeg ) find_library(${_component}_LIBRARIES NAMES ${_library} HINTS ${PC_LIB${_component}_LIBDIR} ${PC_LIB${_component}_LIBRARY_DIRS} ) set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") set_component_found(${_component}) mark_as_advanced( ${_component}_LIBRARY_DIRS ${_component}_INCLUDE_DIRS ${_component}_LIBRARIES ${_component}_DEFINITIONS ${_component}_VERSION ) endmacro() # Check for cached results. If there are skip the costly part. if (NOT FFMPEG_LIBRARIES) # Check for all possible component. find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) find_component(AVFORMAT libavformat avformat libavformat/avformat.h) find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) find_component(AVUTIL libavutil avutil libavutil/avutil.h) find_component(AVFILTER libavfilter avfilter libavfilter/avfilter.h) find_component(SWSCALE libswscale swscale libswscale/swscale.h) find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) # Check if the required components were found and add their stuff to the FFMPEG_* vars. foreach (_component ${FFmpeg_FIND_COMPONENTS}) if (${_component}_FOUND) # message(STATUS "Required component ${_component} present.") set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS}) list(APPEND FFMPEG_LIBRARY_DIRS ${${_component}_LIBRARY_DIRS}) list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) else () # message(STATUS "Required component ${_component} missing.") endif () endforeach () # Build the include path with duplicates removed. if (FFMPEG_INCLUDE_DIRS) list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) endif () # Build the lib path with duplicates removed. if (FFMPEG_LIBRARY_DIRS) list(REMOVE_DUPLICATES FFMPEG_LIBRARY_DIRS) endif () # cache the vars. set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) set(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBRARY_DIRS} CACHE STRING "The FFmpeg lib directories." FORCE) set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) mark_as_advanced( FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARY_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS ) endif () # Now set the noncached _FOUND vars for the components. foreach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWSCALE) set_component_found(${_component}) endforeach () # Compile the list of required vars set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) foreach (_component ${FFmpeg_FIND_COMPONENTS}) list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) endforeach () # Give a nice error message if some of the required vars are missing. find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) server-2.2.0-stable/src/CMakeModules/FindFreeImage.cmake000066400000000000000000000041771341175263200230350ustar00rootroot00000000000000# Find FreeImage includes and library # # This module defines # FreeImage_INCLUDE_DIRS # FreeImage_LIBRARIES, the libraries to link against to use FreeImage. # FreeImage_LIBRARY_DIRS, the location of the libraries # FreeImage_FOUND, If false, do not try to use FreeImage # # Copyright © 2007, Matt Williams # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. IF (FreeImage_LIBRARIES AND FreeImage_INCLUDE_DIRS) SET(FreeImage_FIND_QUIETLY TRUE) # Already in cache, be silent ELSE(FreeImage_LIBRARIES AND FreeImage_INCLUDE_DIRS) MESSAGE(STATUS "Looking for FreeImage") ENDIF (FreeImage_LIBRARIES AND FreeImage_INCLUDE_DIRS) SET(FreeImage_INCLUDE_SEARCH_DIRS ${FreeImage_LIBRARY_SEARCH_DIRS} ${CMAKE_LIBRARY_PATH} /opt/freeimage/lib ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) SET(FreeImage_LIBRARY_SEARCH_DIRS ${FreeImage_LIBRARY_SEARCH_DIRS} ${CMAKE_LIBRARY_PATH} /opt/freeimage/lib ~/Library/Frameworks /Library/Frameworks /usr/local/lib /usr/local/lib64 /usr/lib /usr/lib64 /sw/lib /opt/local/lib /opt/csw/lib /opt/lib /usr/freeware/lib64 ) FIND_PATH(FreeImage_INCLUDE_DIRS FreeImage.h ${FreeImage_INCLUDE_SEARCH_DIRS}) FIND_LIBRARY(FreeImage_LIBRARIES freeimage PATHS ${FreeImage_LIBRARY_SEARCH_DIRS}) #Do some preparation SEPARATE_ARGUMENTS(FreeImage_INCLUDE_DIRS) SEPARATE_ARGUMENTS(FreeImage_LIBRARIES) MARK_AS_ADVANCED(FreeImage_INCLUDE_DIRS FreeImage_LIBRARIES FreeImage_LIBRARY_DIRS) IF (FreeImage_INCLUDE_DIRS AND FreeImage_LIBRARIES) SET(FreeImage_FOUND TRUE) ENDIF (FreeImage_INCLUDE_DIRS AND FreeImage_LIBRARIES) IF (FreeImage_FOUND) IF (NOT FreeImage_FIND_QUIETLY) MESSAGE(STATUS " libraries : ${FreeImage_LIBRARIES} from ${FreeImage_LIBRARY_DIRS}") MESSAGE(STATUS " includes : ${FreeImage_INCLUDE_DIRS}") ENDIF (NOT FreeImage_FIND_QUIETLY) ELSE (FreeImage_FOUND) IF (FreeImage_FIND_REQUIRED) MESSAGE(FATAL_ERROR "Could not find FreeImage") ENDIF (FreeImage_FIND_REQUIRED) ENDIF (FreeImage_FOUND) server-2.2.0-stable/src/CMakeModules/FindGLFW.cmake000066400000000000000000000171451341175263200217470ustar00rootroot00000000000000# # Copyright 2013 Pixar # # Licensed under the Apache License, Version 2.0 (the "Apache License") # with the following modification; you may not use this file except in # compliance with the Apache License and the following modification to it: # Section 6. Trademarks. is deleted and replaced with: # # 6. Trademarks. This License does not grant permission to use the trade # names, trademarks, service marks, or product names of the Licensor # and its affiliates, except as required to comply with Section 4(c) of # the License and to reproduce the content of the NOTICE file. # # You may obtain a copy of the Apache License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the Apache License with the above modification is # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the Apache License for the specific # language governing permissions and limitations under the Apache License. # # Try to find GLFW library and include path. # Once done this will define # # GLFW_FOUND # GLFW_INCLUDE_DIR # GLFW_LIBRARIES # find_path( GLFW_INCLUDE_DIR NAMES GLFW/glfw3.h HINTS "${GLFW_LOCATION}/include" "$ENV{GLFW_LOCATION}/include" PATHS "$ENV{PROGRAMFILES}/GLFW/include" "${OPENGL_INCLUDE_DIR}" /usr/openwin/share/include /usr/openwin/include /usr/X11R6/include /usr/include/X11 /opt/graphics/OpenGL/include /opt/graphics/OpenGL/contrib/libglfw /usr/local/include /usr/include/GL /usr/include DOC "The directory where GLFW/glfw3.h resides" ) # # XXX: Do we still need to search for GL/glfw.h? # find_path( GLFW_INCLUDE_DIR NAMES GL/glfw.h HINTS "${GLFW_LOCATION}/include" "$ENV{GLFW_LOCATION}/include" PATHS "$ENV{PROGRAMFILES}/GLFW/include" "${OPENGL_INCLUDE_DIR}" /usr/openwin/share/include /usr/openwin/include /usr/X11R6/include /usr/include/X11 /opt/graphics/OpenGL/include /opt/graphics/OpenGL/contrib/libglfw /usr/local/include /usr/include/GL /usr/include DOC "The directory where GL/glfw.h resides" ) if (WIN32) if(CYGWIN) find_library( GLFW_glfw_LIBRARY NAMES glfw32 HINTS "${GLFW_LOCATION}/lib" "${GLFW_LOCATION}/lib/x64" "$ENV{GLFW_LOCATION}/lib" PATHS "${OPENGL_LIBRARY_DIR}" /usr/lib /usr/lib/w32api /usr/local/lib /usr/X11R6/lib DOC "The GLFW library" ) else() find_library( GLFW_glfw_LIBRARY NAMES glfw32 glfw32s glfw glfw3 HINTS "${GLFW_LOCATION}/lib" "${GLFW_LOCATION}/lib/x64" "${GLFW_LOCATION}/lib-msvc110" "${GLFW_LOCATION}/lib-vc2012" "$ENV{GLFW_LOCATION}/lib" "$ENV{GLFW_LOCATION}/lib/x64" "$ENV{GLFW_LOCATION}/lib-msvc110" "$ENV{GLFW_LOCATION}/lib-vc2012" PATHS "$ENV{PROGRAMFILES}/GLFW/lib" "${OPENGL_LIBRARY_DIR}" DOC "The GLFW library" ) endif() else () if (APPLE) find_library( GLFW_glfw_LIBRARY glfw NAMES glfw glfw3 HINTS "${GLFW_LOCATION}/lib" "${GLFW_LOCATION}/lib/cocoa" "$ENV{GLFW_LOCATION}/lib" "$ENV{GLFW_LOCATION}/lib/cocoa" PATHS /usr/local/lib ) set(GLFW_cocoa_LIBRARY "-framework Cocoa" CACHE STRING "Cocoa framework for OSX") set(GLFW_corevideo_LIBRARY "-framework CoreVideo" CACHE STRING "CoreVideo framework for OSX") set(GLFW_iokit_LIBRARY "-framework IOKit" CACHE STRING "IOKit framework for OSX") else () # (*)NIX find_package(Threads REQUIRED) find_package(X11 REQUIRED) if(NOT X11_Xrandr_FOUND) message(FATAL_ERROR "Xrandr library not found - required for GLFW") endif() if(NOT X11_xf86vmode_FOUND) message(FATAL_ERROR "xf86vmode library not found - required for GLFW") endif() if(NOT X11_Xcursor_FOUND) message(FATAL_ERROR "Xcursor library not found - required for GLFW") endif() if(NOT X11_Xinerama_FOUND) message(FATAL_ERROR "Xinerama library not found - required for GLFW") endif() if(NOT X11_Xi_FOUND) message(FATAL_ERROR "Xi library not found - required for GLFW") endif() list(APPEND GLFW_x11_LIBRARY "${X11_Xrandr_LIB}" "${X11_Xxf86vm_LIB}" "${X11_Xcursor_LIB}" "${X11_Xinerama_LIB}" "${X11_Xi_LIB}" "${X11_LIBRARIES}" "${CMAKE_THREAD_LIBS_INIT}" -lrt -ldl) find_library( GLFW_glfw_LIBRARY NAMES glfw glfw3 HINTS "${GLFW_LOCATION}/lib" "$ENV{GLFW_LOCATION}/lib" "${GLFW_LOCATION}/lib/x11" "$ENV{GLFW_LOCATION}/lib/x11" PATHS /usr/lib64 /usr/lib /usr/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/local/lib64 /usr/local/lib /usr/local/lib/${CMAKE_LIBRARY_ARCHITECTURE} /usr/openwin/lib /usr/X11R6/lib DOC "The GLFW library" ) endif (APPLE) endif (WIN32) set( GLFW_FOUND "NO" ) if(GLFW_INCLUDE_DIR) if(GLFW_glfw_LIBRARY) set( GLFW_LIBRARIES "${GLFW_glfw_LIBRARY}" "${GLFW_x11_LIBRARY}" "${GLFW_cocoa_LIBRARY}" "${GLFW_iokit_LIBRARY}" "${GLFW_corevideo_LIBRARY}" ) set( GLFW_FOUND "YES" ) set (GLFW_LIBRARY "${GLFW_LIBRARIES}") set (GLFW_INCLUDE_PATH "${GLFW_INCLUDE_DIR}") endif(GLFW_glfw_LIBRARY) # Tease the GLFW_VERSION numbers from the lib headers function(parseVersion FILENAME VARNAME) set(PATTERN "^#define ${VARNAME}.*$") file(STRINGS "${GLFW_INCLUDE_DIR}/${FILENAME}" TMP REGEX ${PATTERN}) string(REGEX MATCHALL "[0-9]+" TMP ${TMP}) set(${VARNAME} ${TMP} PARENT_SCOPE) endfunction() if(EXISTS "${GLFW_INCLUDE_DIR}/GL/glfw.h") parseVersion(GL/glfw.h GLFW_VERSION_MAJOR) parseVersion(GL/glfw.h GLFW_VERSION_MINOR) parseVersion(GL/glfw.h GLFW_VERSION_REVISION) elseif(EXISTS "${GLFW_INCLUDE_DIR}/GLFW/glfw3.h") parseVersion(GLFW/glfw3.h GLFW_VERSION_MAJOR) parseVersion(GLFW/glfw3.h GLFW_VERSION_MINOR) parseVersion(GLFW/glfw3.h GLFW_VERSION_REVISION) endif() if("${GLFW_VERSION_MAJOR}" OR "${GLFW_VERSION_MINOR}" OR "${GLFW_VERSION_REVISION}") set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}.${GLFW_VERSION_REVISION}") set(GLFW_VERSION_STRING "${GLFW_VERSION}") mark_as_advanced(GLFW_VERSION) endif() endif(GLFW_INCLUDE_DIR) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(GLFW REQUIRED_VARS GLFW_INCLUDE_DIR GLFW_LIBRARIES VERSION_VAR GLFW_VERSION ) mark_as_advanced( GLFW_INCLUDE_DIR GLFW_LIBRARIES GLFW_glfw_LIBRARY GLFW_cocoa_LIBRARY ) server-2.2.0-stable/src/CMakeModules/FindSFML.cmake000066400000000000000000000413441341175263200217470ustar00rootroot00000000000000# This script locates the SFML library # ------------------------------------ # # Usage # ----- # # When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main). # If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing. # example: # find_package(SFML COMPONENTS graphics window system) # find the graphics, window and system modules # # You can enforce a specific version, either MAJOR.MINOR or only MAJOR. # If nothing is specified, the version won't be checked (i.e. any version will be accepted). # example: # find_package(SFML COMPONENTS ...) # no specific version required # find_package(SFML 2 COMPONENTS ...) # any 2.x version # find_package(SFML 2.4 COMPONENTS ...) # version 2.4 or greater # # By default, the dynamic libraries of SFML will be found. To find the static ones instead, # you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...). # Since you have to link yourself all the SFML dependencies when you link it statically, the following # additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed # description below). # In case of static linking, the SFML_STATIC macro will also be defined by this script. # example: # set(SFML_STATIC_LIBRARIES TRUE) # find_package(SFML 2 COMPONENTS network system) # # On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless # CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details. # Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which # are available for both release and debug modes. # # If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable # to tell CMake where SFML is. # # Output # ------ # # This script defines the following variables: # - For each specified module XXX (system, window, graphics, network, audio, main): # - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found) # - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found) # - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary) # - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found # - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking # - SFML_LIBRARIES: the list of all libraries corresponding to the required modules # - SFML_FOUND: true if all the required modules are found # - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file) # - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking # # example: # find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED) # include_directories(${SFML_INCLUDE_DIR}) # add_executable(myapp ...) # target_link_libraries(myapp ${SFML_LIBRARIES}) # define the SFML_STATIC macro if static build was chosen if(SFML_STATIC_LIBRARIES) add_definitions(-DSFML_STATIC) endif() # define the list of search paths for headers and libraries set(FIND_SFML_PATHS ${SFML_ROOT} $ENV{SFML_ROOT} ~/Library/Frameworks /Library/Frameworks /usr/local /usr /sw /opt/local /opt/csw /opt) # find the SFML include directory find_path(SFML_INCLUDE_DIR SFML/Config.hpp PATH_SUFFIXES include PATHS ${FIND_SFML_PATHS}) # check the version number set(SFML_VERSION_OK TRUE) if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR) # extract the major and minor version numbers from SFML/Config.hpp # we have to handle framework a little bit differently: if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework") set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp") else() set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp") endif() FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS) STRING(REGEX REPLACE ".*#define SFML_VERSION_MAJOR ([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}") STRING(REGEX REPLACE ".*#define SFML_VERSION_MINOR ([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}") STRING(REGEX REPLACE ".*#define SFML_VERSION_PATCH ([0-9]+).*" "\\1" SFML_VERSION_PATCH "${SFML_CONFIG_HPP_CONTENTS}") if (NOT "${SFML_VERSION_PATCH}" MATCHES "^[0-9]+$") set(SFML_VERSION_PATCH 0) endif() math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10000 + ${SFML_FIND_VERSION_MINOR} * 100 + ${SFML_FIND_VERSION_PATCH}") # if we could extract them, compare with the requested version number if (SFML_VERSION_MAJOR) # transform version numbers to an integer math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10000 + ${SFML_VERSION_MINOR} * 100 + ${SFML_VERSION_PATCH}") # compare them if(SFML_VERSION LESS SFML_REQUESTED_VERSION) set(SFML_VERSION_OK FALSE) endif() else() # SFML version is < 2.0 if (SFML_REQUESTED_VERSION GREATER 10900) set(SFML_VERSION_OK FALSE) set(SFML_VERSION_MAJOR 1) set(SFML_VERSION_MINOR x) set(SFML_VERSION_PATCH x) endif() endif() endif() # find the requested modules set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS}) string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER) string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER) set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER}) # no suffix for sfml-main, it is always a static library if(FIND_SFML_COMPONENT_LOWER STREQUAL "main") # release library find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE NAMES ${FIND_SFML_COMPONENT_NAME} PATH_SUFFIXES lib64 lib PATHS ${FIND_SFML_PATHS}) # debug library find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG NAMES ${FIND_SFML_COMPONENT_NAME}-d PATH_SUFFIXES lib64 lib PATHS ${FIND_SFML_PATHS}) else() # static release library find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE NAMES ${FIND_SFML_COMPONENT_NAME}-s PATH_SUFFIXES lib64 lib PATHS ${FIND_SFML_PATHS}) # static debug library find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG NAMES ${FIND_SFML_COMPONENT_NAME}-s-d PATH_SUFFIXES lib64 lib PATHS ${FIND_SFML_PATHS}) # dynamic release library find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE NAMES ${FIND_SFML_COMPONENT_NAME} PATH_SUFFIXES lib64 lib PATHS ${FIND_SFML_PATHS}) # dynamic debug library find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG NAMES ${FIND_SFML_COMPONENT_NAME}-d PATH_SUFFIXES lib64 lib PATHS ${FIND_SFML_PATHS}) # choose the entries that fit the requested link type if(SFML_STATIC_LIBRARIES) if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE}) endif() if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG}) endif() else() if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE}) endif() if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG}) endif() endif() endif() if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) # library found set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE) # if both are found, set SFML_XXX_LIBRARY to contain both if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG} optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) endif() # if only one debug/release variant is found, set the other to be equal to the found one if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE) # debug and not release set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}) endif() if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG) # release and not debug set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE}) endif() else() # library not found set(SFML_FOUND FALSE) set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE) set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "") set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY") endif() # mark as advanced MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG) # add to the global list of libraries set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}") endforeach() # in case of static linking, we must also define the list of all the dependencies of SFML libraries if(SFML_STATIC_LIBRARIES) # detect the OS if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(FIND_SFML_OS_WINDOWS 1) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(FIND_SFML_OS_LINUX 1) elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(FIND_SFML_OS_FREEBSD 1) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(FIND_SFML_OS_MACOSX 1) endif() # start with an empty list set(SFML_DEPENDENCIES) set(FIND_SFML_DEPENDENCIES_NOTFOUND) # macro that searches for a 3rd-party library macro(find_sfml_dependency output friendlyname) # No lookup in environment variables (PATH on Windows), as they may contain wrong library versions find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib NO_SYSTEM_ENVIRONMENT_PATH) if(${${output}} STREQUAL "${output}-NOTFOUND") unset(output) set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}") endif() endmacro() # sfml-system list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT) if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1) # update the list -- these are only system libraries, no need to find them if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX) set(SFML_SYSTEM_DEPENDENCIES "pthread") endif() if(FIND_SFML_OS_LINUX) set(SFML_SYSTEM_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} "rt") endif() if(FIND_SFML_OS_WINDOWS) set(SFML_SYSTEM_DEPENDENCIES "winmm") endif() set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES}) endif() # sfml-network list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT) if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1) # update the list -- these are only system libraries, no need to find them if(FIND_SFML_OS_WINDOWS) set(SFML_NETWORK_DEPENDENCIES "ws2_32") endif() set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES}) endif() # sfml-window list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT) if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1) # find libraries if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD) find_sfml_dependency(X11_LIBRARY "X11" X11) find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr) endif() if(FIND_SFML_OS_LINUX) find_sfml_dependency(UDEV_LIBRARIES "UDev" udev libudev) endif() # update the list if(FIND_SFML_OS_WINDOWS) set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32") elseif(FIND_SFML_OS_LINUX) set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} ${UDEV_LIBRARIES}) elseif(FIND_SFML_OS_FREEBSD) set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} "usbhid") elseif(FIND_SFML_OS_MACOSX) set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon") endif() set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES}) endif() # sfml-graphics list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT) if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1) # find libraries find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype) find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg) # update the list set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${JPEG_LIBRARY}) set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES}) endif() # sfml-audio list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT) if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1) # find libraries find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32) find_sfml_dependency(OGG_LIBRARY "Ogg" ogg) find_sfml_dependency(VORBIS_LIBRARY "Vorbis" vorbis) find_sfml_dependency(VORBISFILE_LIBRARY "VorbisFile" vorbisfile) find_sfml_dependency(VORBISENC_LIBRARY "VorbisEnc" vorbisenc) find_sfml_dependency(FLAC_LIBRARY "FLAC" FLAC) # update the list set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${FLAC_LIBRARY} ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY}) set(SFML_DEPENDENCIES ${SFML_DEPENDENCIES} ${SFML_AUDIO_DEPENDENCIES}) endif() endif() # handle errors if(NOT SFML_VERSION_OK) # SFML version not ok set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH})") set(SFML_FOUND FALSE) elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND) set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})") set(SFML_FOUND FALSE) elseif(NOT SFML_FOUND) # include directory or library not found set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})") endif() if (NOT SFML_FOUND) if(SFML_FIND_REQUIRED) # fatal error message(FATAL_ERROR ${FIND_SFML_ERROR}) elseif(NOT SFML_FIND_QUIETLY) # error but continue message("${FIND_SFML_ERROR}") endif() endif() # handle success if(SFML_FOUND AND NOT SFML_FIND_QUIETLY) MARK_AS_ADVANCED (SFML_INCLUDE_DIR) message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH} in ${SFML_INCLUDE_DIR}") endif() server-2.2.0-stable/src/CMakeModules/FindSndFile.cmake000066400000000000000000000032231341175263200225240ustar00rootroot00000000000000# Found on http://hg.kvats.net # # - Try to find libsndfile # # Once done this will define # # SNDFILE_FOUND - system has libsndfile # SNDFILE_INCLUDE_DIRS - the libsndfile include directory # SNDFILE_LIBRARIES - Link these to use libsndfile # # Copyright (C) 2006 Wengo # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (SNDFILE_LIBRARIES AND SNDFILE_INCLUDE_DIRS) # in cache already set(SNDFILE_FOUND TRUE) else (SNDFILE_LIBRARIES AND SNDFILE_INCLUDE_DIRS) find_path(SNDFILE_INCLUDE_DIR NAMES sndfile.h PATHS /usr/include /usr/local/include /opt/local/include /sw/include ) find_library(SNDFILE_LIBRARY NAMES sndfile PATHS /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(SNDFILE_INCLUDE_DIRS ${SNDFILE_INCLUDE_DIR} ) set(SNDFILE_LIBRARIES ${SNDFILE_LIBRARY} ) if (SNDFILE_INCLUDE_DIRS AND SNDFILE_LIBRARIES) set(SNDFILE_FOUND TRUE) endif (SNDFILE_INCLUDE_DIRS AND SNDFILE_LIBRARIES) if (SNDFILE_FOUND) if (NOT SndFile_FIND_QUIETLY) message(STATUS "Found libsndfile: ${SNDFILE_LIBRARIES}") endif (NOT SndFile_FIND_QUIETLY) else (SNDFILE_FOUND) if (SndFile_FIND_REQUIRED) message(FATAL_ERROR "Could not find libsndfile") endif (SndFile_FIND_REQUIRED) endif (SNDFILE_FOUND) # show the SNDFILE_INCLUDE_DIRS and SNDFILE_LIBRARIES variables only in the advanced view mark_as_advanced(SNDFILE_INCLUDE_DIRS SNDFILE_LIBRARIES SNDFILE_INCLUDE_DIR SNDFILE_LIBRARY) endif (SNDFILE_LIBRARIES AND SNDFILE_INCLUDE_DIRS) server-2.2.0-stable/src/CMakeModules/FindTBB.cmake000066400000000000000000000310571341175263200216150ustar00rootroot00000000000000# - Find ThreadingBuildingBlocks include dirs and libraries # Use this module by invoking find_package with the form: # find_package(TBB # [REQUIRED] # Fail with error if TBB is not found # ) # # Once done, this will define # # TBB_FOUND - system has TBB # TBB_INCLUDE_DIRS - the TBB include directories # TBB_LIBRARIES - TBB libraries to be lined, doesn't include malloc or # malloc proxy # # TBB_VERSION_MAJOR - Major Product Version Number # TBB_VERSION_MINOR - Minor Product Version Number # TBB_INTERFACE_VERSION - Engineering Focused Version Number # TBB_COMPATIBLE_INTERFACE_VERSION - The oldest major interface version # still supported. This uses the engineering # focused interface version numbers. # # TBB_MALLOC_FOUND - system has TBB malloc library # TBB_MALLOC_INCLUDE_DIRS - the TBB malloc include directories # TBB_MALLOC_LIBRARIES - The TBB malloc libraries to be lined # # TBB_MALLOC_PROXY_FOUND - system has TBB malloc proxy library # TBB_MALLOC_PROXY_INCLUDE_DIRS = the TBB malloc proxy include directories # TBB_MALLOC_PROXY_LIBRARIES - The TBB malloc proxy libraries to be lined # # # This module reads hints about search locations from variables: # ENV TBB_ARCH_PLATFORM - for eg. set it to "mic" for Xeon Phi builds # ENV TBB_ROOT or just TBB_ROOT - root directory of tbb installation # ENV TBB_BUILD_PREFIX - specifies the build prefix for user built tbb # libraries. Should be specified with ENV TBB_ROOT # and optionally... # ENV TBB_BUILD_DIR - if build directory is different than ${TBB_ROOT}/build # # # Modified by Robert Maynard from the original OGRE source # #------------------------------------------------------------------- # This file is part of the CMake build system for OGRE # (Object-oriented Graphics Rendering Engine) # For the latest info, see http://www.ogre3d.org/ # # The contents of this file are placed in the public domain. Feel # free to make use of it in any way you like. #------------------------------------------------------------------- # #============================================================================= # Copyright 2010-2012 Kitware, Inc. # Copyright 2012 Rolf Eike Beer # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) #============================================================================= # FindTBB helper functions and macros # #=============================================== # Do the final processing for the package find. #=============================================== macro(findpkg_finish PREFIX) # skip if already processed during this run if (NOT ${PREFIX}_FOUND) if (${PREFIX}_INCLUDE_DIR AND ${PREFIX}_LIBRARY) set(${PREFIX}_FOUND TRUE) set (${PREFIX}_INCLUDE_DIRS ${${PREFIX}_INCLUDE_DIR}) set (${PREFIX}_LIBRARIES ${${PREFIX}_LIBRARY}) else () if (${PREFIX}_FIND_REQUIRED AND NOT ${PREFIX}_FIND_QUIETLY) message(FATAL_ERROR "Required library ${PREFIX} not found.") endif () endif () #mark the following variables as internal variables mark_as_advanced(${PREFIX}_INCLUDE_DIR ${PREFIX}_LIBRARY ${PREFIX}_LIBRARY_DEBUG ${PREFIX}_LIBRARY_RELEASE) endif () endmacro() #=============================================== # Generate debug names from given release names #=============================================== macro(get_debug_names PREFIX) foreach(i ${${PREFIX}}) set(${PREFIX}_DEBUG ${${PREFIX}_DEBUG} ${i}d ${i}D ${i}_d ${i}_D ${i}_debug ${i}) endforeach() endmacro() #=============================================== # See if we have env vars to help us find tbb #=============================================== macro(getenv_path VAR) set(ENV_${VAR} $ENV{${VAR}}) # replace won't work if var is blank if (ENV_${VAR}) string( REGEX REPLACE "\\\\" "/" ENV_${VAR} ${ENV_${VAR}} ) endif () endmacro() #=============================================== # Couple a set of release AND debug libraries #=============================================== macro(make_library_set PREFIX) if (${PREFIX}_RELEASE AND ${PREFIX}_DEBUG) set(${PREFIX} optimized ${${PREFIX}_RELEASE} debug ${${PREFIX}_DEBUG}) elseif (${PREFIX}_RELEASE) set(${PREFIX} ${${PREFIX}_RELEASE}) elseif (${PREFIX}_DEBUG) set(${PREFIX} ${${PREFIX}_DEBUG}) endif () endmacro() #============================================================================= # Now to actually find TBB # # Get path, convert backslashes as ${ENV_${var}} getenv_path(TBB_ROOT) # initialize search paths set(TBB_PREFIX_PATH ${TBB_ROOT} ${ENV_TBB_ROOT}) set(TBB_INC_SEARCH_PATH "") set(TBB_LIB_SEARCH_PATH "") # If user built from sources set(TBB_BUILD_PREFIX $ENV{TBB_BUILD_PREFIX}) if (TBB_BUILD_PREFIX AND ENV_TBB_ROOT) getenv_path(TBB_BUILD_DIR) if (NOT ENV_TBB_BUILD_DIR) set(ENV_TBB_BUILD_DIR ${ENV_TBB_ROOT}/build) endif () # include directory under ${ENV_TBB_ROOT}/include list(APPEND TBB_LIB_SEARCH_PATH ${ENV_TBB_BUILD_DIR}/${TBB_BUILD_PREFIX}_release ${ENV_TBB_BUILD_DIR}/${TBB_BUILD_PREFIX}_debug) endif () # For Windows, let's assume that the user might be using the precompiled # TBB packages from the main website. These use a rather awkward directory # structure (at least for automatically finding the right files) depending # on platform and compiler, but we'll do our best to accommodate it. # Not adding the same effort for the precompiled linux builds, though. Those # have different versions for CC compiler versions and linux kernels which # will never adequately match the user's setup, so there is no feasible way # to detect the "best" version to use. The user will have to manually # select the right files. (Chances are the distributions are shipping their # custom version of tbb, anyway, so the problem is probably nonexistent.) if (WIN32 AND MSVC) set(COMPILER_PREFIX "vc7.1") if (MSVC_VERSION EQUAL 1400) set(COMPILER_PREFIX "vc8") elseif(MSVC_VERSION EQUAL 1500) set(COMPILER_PREFIX "vc9") elseif(MSVC_VERSION EQUAL 1600) set(COMPILER_PREFIX "vc10") elseif(MSVC_VERSION EQUAL 1700) set(COMPILER_PREFIX "vc11") elseif(MSVC_VERSION EQUAL 1800) set(COMPILER_PREFIX "vc12") elseif(MSVC_VERSION EQUAL 1900) set(COMPILER_PREFIX "vc14") endif () # for each prefix path, add ia32/64\${COMPILER_PREFIX}\lib to the lib search path foreach (dir IN LISTS TBB_PREFIX_PATH) if (CMAKE_CL_64) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia64/${COMPILER_PREFIX}/lib) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia64/${COMPILER_PREFIX}) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/intel64/${COMPILER_PREFIX}/lib) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/intel64/${COMPILER_PREFIX}) else () list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia32/${COMPILER_PREFIX}/lib) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia32/${COMPILER_PREFIX}) endif () endforeach () endif () # For OS X binary distribution, choose libc++ based libraries for Mavericks (10.9) # and above and AppleClang if (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND NOT CMAKE_SYSTEM_VERSION VERSION_LESS 13.0) set (USE_LIBCXX OFF) cmake_policy(GET CMP0025 POLICY_VAR) if (POLICY_VAR STREQUAL "NEW") if (CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") set (USE_LIBCXX ON) endif () else () if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set (USE_LIBCXX ON) endif () endif () if (USE_LIBCXX) foreach (dir IN LISTS TBB_PREFIX_PATH) list (APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/libc++ ${dir}/libc++/lib) endforeach () endif () endif () # check compiler ABI if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") set(COMPILER_PREFIX) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) list(APPEND COMPILER_PREFIX "gcc4.7") endif() if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.4) list(APPEND COMPILER_PREFIX "gcc4.4") endif() list(APPEND COMPILER_PREFIX "gcc4.1") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(COMPILER_PREFIX) if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.6) list(APPEND COMPILER_PREFIX "gcc4.7") endif() list(APPEND COMPILER_PREFIX "gcc4.4") else() # Assume compatibility with 4.4 for other compilers list(APPEND COMPILER_PREFIX "gcc4.4") endif () # if platform architecture is explicitly specified set(TBB_ARCH_PLATFORM $ENV{TBB_ARCH_PLATFORM}) if (TBB_ARCH_PLATFORM) foreach (dir IN LISTS TBB_PREFIX_PATH) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/${TBB_ARCH_PLATFORM}/lib) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/${TBB_ARCH_PLATFORM}) endforeach () endif () foreach (dir IN LISTS TBB_PREFIX_PATH) foreach (prefix IN LISTS COMPILER_PREFIX) if (CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/intel64) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/intel64/${prefix}) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/intel64/lib) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/intel64/${prefix}/lib) else () list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia32) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib/ia32/${prefix}) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia32/lib) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/ia32/${prefix}/lib) endif () endforeach() endforeach () # add general search paths foreach (dir IN LISTS TBB_PREFIX_PATH) list(APPEND TBB_LIB_SEARCH_PATH ${dir}/lib ${dir}/Lib ${dir}/lib/tbb ${dir}/Libs) list(APPEND TBB_INC_SEARCH_PATH ${dir}/include ${dir}/Include ${dir}/include/tbb) endforeach () set(TBB_LIBRARY_NAMES tbb) get_debug_names(TBB_LIBRARY_NAMES) find_path(TBB_INCLUDE_DIR NAMES tbb/tbb.h PATHS ${TBB_INC_SEARCH_PATH}) find_library(TBB_LIBRARY_RELEASE NAMES ${TBB_LIBRARY_NAMES} PATHS ${TBB_LIB_SEARCH_PATH}) find_library(TBB_LIBRARY_DEBUG NAMES ${TBB_LIBRARY_NAMES_DEBUG} PATHS ${TBB_LIB_SEARCH_PATH}) make_library_set(TBB_LIBRARY) findpkg_finish(TBB) #if we haven't found TBB no point on going any further if (NOT TBB_FOUND) return() endif () #============================================================================= # Look for TBB's malloc package set(TBB_MALLOC_LIBRARY_NAMES tbbmalloc) get_debug_names(TBB_MALLOC_LIBRARY_NAMES) find_path(TBB_MALLOC_INCLUDE_DIR NAMES tbb/tbb.h PATHS ${TBB_INC_SEARCH_PATH}) find_library(TBB_MALLOC_LIBRARY_RELEASE NAMES ${TBB_MALLOC_LIBRARY_NAMES} PATHS ${TBB_LIB_SEARCH_PATH}) find_library(TBB_MALLOC_LIBRARY_DEBUG NAMES ${TBB_MALLOC_LIBRARY_NAMES_DEBUG} PATHS ${TBB_LIB_SEARCH_PATH}) make_library_set(TBB_MALLOC_LIBRARY) findpkg_finish(TBB_MALLOC) #============================================================================= # Look for TBB's malloc proxy package set(TBB_MALLOC_PROXY_LIBRARY_NAMES tbbmalloc_proxy) get_debug_names(TBB_MALLOC_PROXY_LIBRARY_NAMES) find_path(TBB_MALLOC_PROXY_INCLUDE_DIR NAMES tbb/tbbmalloc_proxy.h PATHS ${TBB_INC_SEARCH_PATH}) find_library(TBB_MALLOC_PROXY_LIBRARY_RELEASE NAMES ${TBB_MALLOC_PROXY_LIBRARY_NAMES} PATHS ${TBB_LIB_SEARCH_PATH}) find_library(TBB_MALLOC_PROXY_LIBRARY_DEBUG NAMES ${TBB_MALLOC_PROXY_LIBRARY_NAMES_DEBUG} PATHS ${TBB_LIB_SEARCH_PATH}) make_library_set(TBB_MALLOC_PROXY_LIBRARY) findpkg_finish(TBB_MALLOC_PROXY) #============================================================================= #parse all the version numbers from tbb if(NOT TBB_VERSION) #only read the start of the file file(READ "${TBB_INCLUDE_DIR}/tbb/tbb_stddef.h" TBB_VERSION_CONTENTS LIMIT 2048) string(REGEX REPLACE ".*#define TBB_VERSION_MAJOR ([0-9]+).*" "\\1" TBB_VERSION_MAJOR "${TBB_VERSION_CONTENTS}") string(REGEX REPLACE ".*#define TBB_VERSION_MINOR ([0-9]+).*" "\\1" TBB_VERSION_MINOR "${TBB_VERSION_CONTENTS}") string(REGEX REPLACE ".*#define TBB_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_INTERFACE_VERSION "${TBB_VERSION_CONTENTS}") string(REGEX REPLACE ".*#define TBB_COMPATIBLE_INTERFACE_VERSION ([0-9]+).*" "\\1" TBB_COMPATIBLE_INTERFACE_VERSION "${TBB_VERSION_CONTENTS}") endif() server-2.2.0-stable/src/CMakeModules/PlatformIntrospection.cmake000066400000000000000000000147471341175263200247610ustar00rootroot00000000000000include(ProcessorCount) # Returns a simple string describing the current architecture. Possible # return values currently include: amd64, x86_64, x86. MACRO (_DETERMINE_ARCH var) IF (DEFINED CB_DOWNLOAD_DEPS_ARCH) SET (_arch ${CB_DOWNLOAD_DEPS_ARCH}) ELSEIF (DEFINED ENV{target_arch}) # target_arch is used by environment.bat to represent the desired # target architecture, so use that value first if set. STRING (TOLOWER "$ENV{target_arch}" _arch) ELSE (DEFINED CB_DOWNLOAD_DEPS_ARCH) # We tweak MacOS, which for some reason claims to be i386 IF (CMAKE_SYSTEM_NAME STREQUAL "Darwin") # QQQ MacOS 10.7 could be 32-bit; we should catch and abort SET (_arch x86_64) ELSEIF (CMAKE_SYSTEM_NAME STREQUAL "SunOS") EXECUTE_PROCESS (COMMAND isainfo -k COMMAND tr -d '\n' OUTPUT_VARIABLE _arch) ELSEIF (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") # If user didn't specify the arch via target_arch or # CB_DOWNLOAD_DEPS_ARCH, assume that the target is the same as # the current host architecture and derive that from # Windows-provided environment variables. IF (DEFINED ENV{PROCESSOR_ARCHITEW6432}) STRING (TOLOWER "$ENV{PROCESSOR_ARCHITEW6432}" _arch) ELSE () STRING (TOLOWER "$ENV{PROCESSOR_ARCHITECTURE}" _arch) ENDIF () ELSE (CMAKE_SYSTEM_NAME STREQUAL "Darwin") STRING (TOLOWER ${CMAKE_SYSTEM_PROCESSOR} _arch) ENDIF (CMAKE_SYSTEM_NAME STREQUAL "Darwin") SET (CB_DOWNLOAD_DEPS_ARCH ${_arch} CACHE STRING "Architecture for downloaded dependencies") MARK_AS_ADVANCED (CB_DOWNLOAD_DEPS_ARCH) ENDIF (DEFINED CB_DOWNLOAD_DEPS_ARCH) SET (${var} ${_arch}) ENDMACRO (_DETERMINE_ARCH) # Returns a lowercased version of a given lsb_release field. MACRO (_LSB_RELEASE field retval) EXECUTE_PROCESS (COMMAND lsb_release "--${field}" OUTPUT_VARIABLE _output ERROR_VARIABLE _output RESULT_VARIABLE _result) IF (_result) MESSAGE (FATAL_ERROR "Cannot determine Linux revision! Output from " "lsb_release --${field}: ${_output}") ENDIF (_result) STRING (REGEX REPLACE "^[^:]*:" "" _output "${_output}") STRING (TOLOWER "${_output}" _output) STRING (STRIP "${_output}" ${retval}) ENDMACRO (_LSB_RELEASE) # Returns a simple string describing the current platform. Possible # return values currently include: windows_msvc2015; windows_msvc (implies # MSVC 2013); macosx; or any value from _DETERMINE_LINUX_DISTRO. MACRO (_DETERMINE_PLATFORM var) IF (DEFINED CB_DOWNLOAD_DEPS_PLATFORM) SET (_plat ${CB_DOWNLOAD_DEPS_PLATFORM}) ELSE (DEFINED CB_DOWNLOAD_DEPS_PLATFORM) SET (_plat ${CMAKE_SYSTEM_NAME}) IF (_plat STREQUAL "Windows") if (${MSVC_VERSION} LESS 1900) SET (_plat "windows_msvc") elseif (${MSVC_VERSION} LESS 1910) SET (_plat "windows_msvc2015") elseif (${MSVC_VERSION} EQUAL 1910) SET (_plat "windows_msvc2017") ELSE() MESSAGE(FATAL_ERROR "Unsupported MSVC version: ${MSVC_VERSION}") ENDIF () ELSEIF (_plat STREQUAL "Darwin") SET (_plat "macosx") ELSEIF (_plat STREQUAL "Linux") FIND_PROGRAM(LSB_RELEASE lsb_release) MARK_AS_ADVANCED(LSB_RELEASE) IF (LSB_RELEASE) _DETERMINE_LINUX_DISTRO (_plat) ELSE (LSB_RELEASE) MESSAGE (WARNING "Can't determine Linux platform without lsb_release") SET (_plat "unknown") ENDIF (LSB_RELEASE) ELSEIF (_plat STREQUAL "SunOS") SET (_plat "sunos") ELSEIF (_plat STREQUAL "FreeBSD") SET (_plat "freebsd") ELSE (_plat STREQUAL "Windows") MESSAGE (WARNING "Sorry, don't recognize your system ${_plat}. ") SET (_plat "unknown") ENDIF (_plat STREQUAL "Windows") SET (CB_DOWNLOAD_DEPS_PLATFORM ${_plat} CACHE STRING "Platform for downloaded dependencies") MARK_AS_ADVANCED (CB_DOWNLOAD_DEPS_PLATFORM) ENDIF (DEFINED CB_DOWNLOAD_DEPS_PLATFORM) SET (${var} ${_plat}) ENDMACRO (_DETERMINE_PLATFORM) # Returns a simple string describing the current Linux distribution # compatibility. Possible return values currently include: # ubuntu14.04, ubuntu12.04, ubuntu10.04, centos5, centos6, debian7, debian8. MACRO (_DETERMINE_LINUX_DISTRO _distro) _LSB_RELEASE (id _id) _LSB_RELEASE (release _rel) IF (_id STREQUAL "linuxmint") # Linux Mint is an Ubuntu derivative; estimate nearest Ubuntu equivalent SET (_id "ubuntu") IF (_rel VERSION_LESS 13) SET (_rel 10.04) ELSEIF (_rel VERSION_LESS 17) SET (_rel 12.04) ELSEIF (_rel VERSION_LESS 18) SET (_rel 14.04) ELSE () SET (_rel 16.04) ENDIF () ELSEIF (_id STREQUAL "debian" OR _id STREQUAL "centos" ) # Just use the major version from the CentOS/Debian identifier - we don't # need different builds for different minor versions. STRING (REGEX MATCH "[0-9]+" _rel "${_rel}") ELSEIF (_id STREQUAL "fedora" AND _rel VERSION_LESS 26) SET (_id "centos") SET (_rel "7") ELSEIF (_id STREQUAL "opensuse project" OR _id STREQUAL "suse linux") SET(_id "suse") ENDIF (_id STREQUAL "linuxmint") SET (${_distro} "${_id}${_rel}") ENDMACRO (_DETERMINE_LINUX_DISTRO) # Returns number of CPUs the system has. The value can be overwritten by the # CB_CPU_COUNT environment variable. If neither of these work, return some # (hopefully) reasonable default. MACRO (_DETERMINE_CPU_COUNT _var) SET(_count 0) IF (DEFINED $ENV{CB_CPU_COUNT}) SET(_count $ENV{CB_CPU_COUNT}) ENDIF (DEFINED $ENV{CB_CPU_COUNT}) IF (_count EQUAL 0) ProcessorCount(_count) ENDIF (_count EQUAL 0) IF (_count EQUAL 0) MESSAGE(WARNING "Couldn't determine number of CPUs to use. Using default.") SET(_count 4) ENDIF (_count EQUAL 0) SET(${_var} ${_count}) ENDMACRO (_DETERMINE_CPU_COUNT) # Sets _platform to the name of the current platform if it is a supported # platform, or a False value otherwise. # "Supported" means that we produce and distribute builds to # customers on that platform. # QQQ This list should come from manifest/product-config.json ultimately. # _platform is in the same format as _DETERMINE_PLATFORM(). MACRO (TEST_FOR_SUPPORTED_PLATFORM _supported_platform) SET (${_supported_platform} 0) # First get the current platform _DETERMINE_PLATFORM(_platform) # .. and check it against the list, returning it if found. SET (_supported_platforms "ubuntu14.04" "ubuntu16.04" "windows_msvc2015") LIST (FIND _supported_platforms ${_platform} _index) IF (_index GREATER "-1") SET(${_supported_platform} ${_platform}) ENDIF (_index GREATER "-1") ENDMACRO (TEST_FOR_SUPPORTED_PLATFORM) server-2.2.0-stable/src/CMakeModules/PrecompiledHeader.cmake000066400000000000000000000206761341175263200237660ustar00rootroot00000000000000# Function for setting up precompiled headers. Usage: # # add_library/executable(target # pchheader.c pchheader.cpp pchheader.h) # # add_precompiled_header(target pchheader.h # [FORCEINCLUDE] # [SOURCE_C pchheader.c] # [SOURCE_CXX pchheader.cpp]) # # Options: # # FORCEINCLUDE: Add compiler flags to automatically include the # pchheader.h from every source file. Works with both GCC and # MSVC. This is recommended. # # SOURCE_C/CXX: Specifies the .c/.cpp source file that includes # pchheader.h for generating the pre-compiled header # output. Defaults to pchheader.c. Only required for MSVC. # # Caveats: # # * Its not currently possible to use the same precompiled-header in # more than a single target in the same directory (No way to set # the source file properties differently for each target). # # * MSVC: A source file with the same name as the header must exist # and be included in the target (E.g. header.cpp). Name of file # can be changed using the SOURCE_CXX/SOURCE_C options. # # License: # # Copyright (C) 2009-2013 Lars Christensen # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation files # (the 'Software') deal in the Software without restriction, # including without limitation the rights to use, copy, modify, merge, # publish, distribute, sublicense, and/or sell copies of the Software, # and to permit persons to whom the Software is furnished to do so, # subject to the following conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. include(CMakeParseArguments) macro(combine_arguments _variable) set(_result "") foreach(_element ${${_variable}}) set(_result "${_result} \"${_element}\"") endforeach() string(STRIP "${_result}" _result) set(${_variable} "${_result}") endmacro() function(export_all_flags _filename) set(_include_directories "$") set(_compile_definitions "$") set(_compile_flags "$") set(_compile_options "$") set(_include_directories "$<$:-I$\n>") set(_compile_definitions "$<$:-D$\n>") set(_compile_flags "$<$:$\n>") set(_compile_options "$<$:$\n>") file(GENERATE OUTPUT "${_filename}" CONTENT "${_compile_definitions}${_include_directories}${_compile_flags}${_compile_options}\n") endfunction() function(add_precompiled_header _target _input) cmake_parse_arguments(_PCH "FORCEINCLUDE" "SOURCE_CXX:SOURCE_C" "" ${ARGN}) get_filename_component(_input_we ${_input} NAME_WE) if(NOT _PCH_SOURCE_CXX) set(_PCH_SOURCE_CXX "${_input_we}.cpp") endif() if(NOT _PCH_SOURCE_C) set(_PCH_SOURCE_C "${_input_we}.c") endif() if(MSVC) set(_cxx_path "${CMAKE_CFG_INTDIR}/${_target}_cxx_pch") set(_c_path "${CMAKE_CFG_INTDIR}/${_target}_c_pch") make_directory("${_cxx_path}") make_directory("${_c_path}") set(_pch_cxx_header "${_cxx_path}/${_input}") set(_pch_cxx_pch "${_cxx_path}/${_input_we}.pch") set(_pch_c_header "${_c_path}/${_input}") set(_pch_c_pch "${_c_path}/${_input_we}.pch") get_target_property(sources ${_target} SOURCES) foreach(_source ${sources}) set(_pch_compile_flags "") if(_source MATCHES \\.\(cc|cxx|cpp|c\)$) if(_source MATCHES \\.\(cpp|cxx|cc\)$) set(_pch_header "${_input}") set(_pch "${_pch_cxx_pch}") else() set(_pch_header "${_input}") set(_pch "${_pch_c_pch}") endif() if(_source STREQUAL "${_PCH_SOURCE_CXX}") set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" /Yc${_input}") set(_pch_source_cxx_found TRUE) elseif(_source STREQUAL "${_PCH_SOURCE_C}") set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" /Yc${_input}") set(_pch_source_c_found TRUE) else() if(_source MATCHES \\.\(cpp|cxx|cc\)$) set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_cxx_pch}\" /Yu${_input}") set(_pch_source_cxx_needed TRUE) else() set(_pch_compile_flags "${_pch_compile_flags} \"/Fp${_pch_c_pch}\" /Yu${_input}") set(_pch_source_c_needed TRUE) endif() if(_PCH_FORCEINCLUDE) set(_pch_compile_flags "${_pch_compile_flags} /FI${_input}") endif(_PCH_FORCEINCLUDE) endif() get_source_file_property(_object_depends "${_source}" OBJECT_DEPENDS) if(NOT _object_depends) set(_object_depends) endif() if(_PCH_FORCEINCLUDE) if(_source MATCHES \\.\(cc|cxx|cpp\)$) list(APPEND _object_depends "${_pch_header}") else() list(APPEND _object_depends "${_pch_header}") endif() endif() set_source_files_properties(${_source} PROPERTIES COMPILE_FLAGS "${_pch_compile_flags}" OBJECT_DEPENDS "${_object_depends}") endif() endforeach() if(_pch_source_cxx_needed AND NOT _pch_source_cxx_found) message(FATAL_ERROR "A source file ${_PCH_SOURCE_CXX} for ${_input} is required for MSVC builds. Can be set with the SOURCE_CXX option.") endif() if(_pch_source_c_needed AND NOT _pch_source_c_found) message(FATAL_ERROR "A source file ${_PCH_SOURCE_C} for ${_input} is required for MSVC builds. Can be set with the SOURCE_C option.") endif() endif(MSVC) if(CMAKE_COMPILER_IS_GNUCXX) get_filename_component(_name ${_input} NAME) set(_pch_header "${CMAKE_CURRENT_SOURCE_DIR}/${_input}") set(_pch_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${_target}_pch") set(_pchfile "${_pch_binary_dir}/${_input}") set(_outdir "${CMAKE_CURRENT_BINARY_DIR}/${_target}_pch/${_name}.gch") make_directory(${_outdir}) set(_output_cxx "${_outdir}/.c++") set(_output_c "${_outdir}/.c") set(_pch_flags_file "${_pch_binary_dir}/compile_flags.rsp") export_all_flags("${_pch_flags_file}") set(_compiler_FLAGS "@${_pch_flags_file}") add_custom_command( OUTPUT "${_pchfile}" COMMAND "${CMAKE_COMMAND}" -E copy "${_pch_header}" "${_pchfile}" DEPENDS "${_pch_header}" COMMENT "Updating ${_name}") add_custom_command( OUTPUT "${_output_cxx}" COMMAND "${CMAKE_CXX_COMPILER}" ${_compiler_FLAGS} -x c++-header -o "${_output_cxx}" "${_pchfile}" DEPENDS "${_pchfile}" "${_pch_flags_file}" COMMENT "Precompiling ${_name} for ${_target} (C++)") add_custom_command( OUTPUT "${_output_c}" COMMAND "${CMAKE_C_COMPILER}" ${_compiler_FLAGS} -x c-header -o "${_output_c}" "${_pchfile}" DEPENDS "${_pchfile}" "${_pch_flags_file}" COMMENT "Precompiling ${_name} for ${_target} (C)") get_property(_sources TARGET ${_target} PROPERTY SOURCES) foreach(_source ${_sources}) set(_pch_compile_flags "") if(_source MATCHES \\.\(cc|cxx|cpp|c\)$) get_source_file_property(_pch_compile_flags "${_source}" COMPILE_FLAGS) if(NOT _pch_compile_flags) set(_pch_compile_flags) endif() separate_arguments(_pch_compile_flags) list(APPEND _pch_compile_flags -Winvalid-pch) if(_PCH_FORCEINCLUDE) list(APPEND _pch_compile_flags -include "${_pchfile}") else(_PCH_FORCEINCLUDE) list(APPEND _pch_compile_flags "-I${_pch_binary_dir}") endif(_PCH_FORCEINCLUDE) get_source_file_property(_object_depends "${_source}" OBJECT_DEPENDS) if(NOT _object_depends) set(_object_depends) endif() list(APPEND _object_depends "${_pchfile}") if(_source MATCHES \\.\(cc|cxx|cpp\)$) list(APPEND _object_depends "${_output_cxx}") else() list(APPEND _object_depends "${_output_c}") endif() combine_arguments(_pch_compile_flags) message("${_source}" ${_pch_compile_flags}) set_source_files_properties(${_source} PROPERTIES COMPILE_FLAGS "${_pch_compile_flags}" OBJECT_DEPENDS "${_object_depends}") endif() endforeach() endif(CMAKE_COMPILER_IS_GNUCXX) endfunction() server-2.2.0-stable/src/accelerator/000077500000000000000000000000001341175263200173505ustar00rootroot00000000000000server-2.2.0-stable/src/accelerator/CMakeLists.txt000066400000000000000000000021741341175263200221140ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (accelerator) set(SOURCES ogl/image/image_kernel.cpp ogl/image/image_mixer.cpp ogl/image/image_shader.cpp ogl/util/buffer.cpp ogl/util/device.cpp ogl/util/shader.cpp ogl/util/texture.cpp accelerator.cpp StdAfx.cpp ) set(HEADERS ogl/image/blending_glsl.h ogl/image/image_kernel.h ogl/image/image_mixer.h ogl/image/image_shader.h ogl/util/buffer.h ogl/util/device.h ogl/util/shader.h ogl/util/texture.h accelerator.h StdAfx.h ) add_library(accelerator ${SOURCES} ${HEADERS} ${OS_SPECIFIC_SOURCES}) add_precompiled_header(accelerator StdAfx.h FORCEINCLUDE) include_directories(..) include_directories(${BOOST_INCLUDE_PATH}) include_directories(${TBB_INCLUDE_PATH}) include_directories(${GLEW_INCLUDE_PATH}) include_directories(${FFMPEG_INCLUDE_PATH}) include_directories(${SFML_INCLUDE_PATH}) source_group(sources ./.*) source_group(sources\\cpu\\image cpu/image/.*) source_group(sources\\cpu\\util cpu/util/.*) source_group(sources\\ogl\\image ogl/image/.*) source_group(sources\\ogl\\util ogl/util/.*) target_link_libraries(accelerator common core ffmpeg) server-2.2.0-stable/src/accelerator/StdAfx.cpp000066400000000000000000000014761341175263200212550ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "StdAfx.h" server-2.2.0-stable/src/accelerator/StdAfx.h000066400000000000000000000026341341175263200207170ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include server-2.2.0-stable/src/accelerator/accelerator.cpp000066400000000000000000000020551341175263200223420ustar00rootroot00000000000000#include "accelerator.h" #include "ogl/image/image_mixer.h" #include "ogl/util/device.h" #include #include #include #include namespace caspar { namespace accelerator { struct accelerator::impl { const std::wstring path_; std::mutex mutex_; std::shared_ptr ogl_device_; impl(const std::wstring& path) : path_(path) { } std::unique_ptr create_image_mixer(int channel_id) { if (!ogl_device_) { ogl_device_.reset(new ogl::device()); } return std::make_unique(spl::make_shared_ptr(ogl_device_), channel_id); } }; accelerator::accelerator(const std::wstring& path) : impl_(std::make_unique(path)) { } accelerator::~accelerator() {} std::unique_ptr accelerator::create_image_mixer(int channel_id) { return impl_->create_image_mixer(channel_id); } }} // namespace caspar::accelerator server-2.2.0-stable/src/accelerator/accelerator.h000066400000000000000000000007111341175263200220040ustar00rootroot00000000000000#pragma once #include #include namespace caspar { namespace accelerator { class accelerator { public: accelerator(const std::wstring& path); accelerator(accelerator&) = delete; ~accelerator(); accelerator& operator=(accelerator&) = delete; std::unique_ptr create_image_mixer(int channel_id); private: struct impl; std::unique_ptr impl_; }; }} // namespace caspar::acceleratorserver-2.2.0-stable/src/accelerator/ogl/000077500000000000000000000000001341175263200201315ustar00rootroot00000000000000server-2.2.0-stable/src/accelerator/ogl/image/000077500000000000000000000000001341175263200212135ustar00rootroot00000000000000server-2.2.0-stable/src/accelerator/ogl/image/blending_glsl.h000066400000000000000000000301601341175263200241670ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once static std::string get_adjustement_glsl() { return R"shader( /* ** Contrast, saturation, brightness ** Code of this function is from TGM's shader pack ** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057 */ vec3 ContrastSaturationBrightness(vec4 color, float brt, float sat, float con) { const float AvgLumR = 0.5; const float AvgLumG = 0.5; const float AvgLumB = 0.5; vec3 LumCoeff = is_hd ? vec3(0.0722, 0.7152, 0.2126) : vec3(0.114, 0.587, 0.299); if (color.a > 0.0) color.rgb /= color.a; vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB); vec3 brtColor = color.rgb * brt; vec3 intensity = vec3(dot(brtColor, LumCoeff)); vec3 satColor = mix(intensity, brtColor, sat); vec3 conColor = mix(AvgLumin, satColor, con); conColor.rgb *= color.a; return conColor; } /* ** Gamma correction ** Details: http://blog.mouaif.org/2009/01/22/photoshop-gamma-correction-shader/ */ #define GammaCorrection(color, gamma) pow(color, vec3(1.0 / gamma)) /* ** Levels control (input (+gamma), output) ** Details: http://blog.mouaif.org/2009/01/28/levels-control-shader/ */ #define LevelsControlInputRange(color, minInput, maxInput) min(max(color - vec3(minInput), vec3(0.0)) / (vec3(maxInput) - vec3(minInput)), vec3(1.0)) #define LevelsControlInput(color, minInput, gamma, maxInput) GammaCorrection(LevelsControlInputRange(color, minInput, maxInput), gamma) #define LevelsControlOutputRange(color, minOutput, maxOutput) mix(vec3(minOutput), vec3(maxOutput), color) #define LevelsControl(color, minInput, gamma, maxInput, minOutput, maxOutput) LevelsControlOutputRange(LevelsControlInput(color, minInput, gamma, maxInput), minOutput, maxOutput) )shader"; } static std::string get_blend_glsl() { static std::string glsl = R"shader( /* ** Photoshop & misc math ** Blending modes, RGB/HSL/Contrast/Desaturate, levels control ** ** Romain Dura | Romz ** Blog: http://blog.mouaif.org ** Post: http://blog.mouaif.org/?p=94 */ /* ** Desaturation */ vec4 Desaturate(vec3 color, float Desaturation) { vec3 grayXfer = vec3(0.3, 0.59, 0.11); vec3 gray = vec3(dot(grayXfer, color)); return vec4(mix(color, gray, Desaturation), 1.0); } /* ** Hue, saturation, luminance */ vec3 RGBToHSL(vec3 color) { vec3 hsl; float fmin = min(min(color.r, color.g), color.b); float fmax = max(max(color.r, color.g), color.b); float delta = fmax - fmin; hsl.z = (fmax + fmin) / 2.0; if (delta == 0.0) { hsl.x = 0.0; hsl.y = 0.0; } else { if (hsl.z < 0.5) hsl.y = delta / (fmax + fmin); else hsl.y = delta / (2.0 - fmax - fmin); float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta; float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta; float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta; if (color.r == fmax ) hsl.x = deltaB - deltaG; else if (color.g == fmax) hsl.x = (1.0 / 3.0) + deltaR - deltaB; else if (color.b == fmax) hsl.x = (2.0 / 3.0) + deltaG - deltaR; if (hsl.x < 0.0) hsl.x += 1.0; else if (hsl.x > 1.0) hsl.x -= 1.0; } return hsl; } float HueToRGB(float f1, float f2, float hue) { if (hue < 0.0) hue += 1.0; else if (hue > 1.0) hue -= 1.0; float res; if ((6.0 * hue) < 1.0) res = f1 + (f2 - f1) * 6.0 * hue; else if ((2.0 * hue) < 1.0) res = f2; else if ((3.0 * hue) < 2.0) res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0; else res = f1; return res; } vec3 HSLToRGB(vec3 hsl) { vec3 rgb; if (hsl.y == 0.0) rgb = vec3(hsl.z); else { float f2; if (hsl.z < 0.5) f2 = hsl.z * (1.0 + hsl.y); else f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z); float f1 = 2.0 * hsl.z - f2; rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0)); rgb.g = HueToRGB(f1, f2, hsl.x); rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0)); } return rgb; } /* ** Float blending modes ** Adapted from here: http://www.nathanm.com/photoshop-blending-math/ ** But I modified the HardMix (wrong condition), Overlay, SoftLight, ColorDodge, ColorBurn, VividLight, PinLight (inverted layers) ones to have correct results */ #define BlendLinearDodgef BlendAddf #define BlendLinearBurnf BlendSubstractf #define BlendAddf(base, blend) min(base + blend, 1.0) #define BlendSubstractf(base, blend) max(base + blend - 1.0, 0.0) #define BlendLightenf(base, blend) max(blend, base) #define BlendDarkenf(base, blend) min(blend, base) #define BlendLinearLightf(base, blend) (blend < 0.5 ? BlendLinearBurnf(base, (2.0 * blend)) : BlendLinearDodgef(base, (2.0 * (blend - 0.5)))) #define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend))) #define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend))) #define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend))) #define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0)) #define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0)) #define BlendVividLightf(base, blend) ((blend < 0.5) ? BlendColorBurnf(base, (2.0 * blend)) : BlendColorDodgef(base, (2.0 * (blend - 0.5)))) #define BlendPinLightf(base, blend) ((blend < 0.5) ? BlendDarkenf(base, (2.0 * blend)) : BlendLightenf(base, (2.0 *(blend - 0.5)))) #define BlendHardMixf(base, blend) ((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0) #define BlendReflectf(base, blend) ((blend == 1.0) ? blend : min(base * base / (1.0 - blend), 1.0)) /* ** Vector3 blending modes */ #define Blend(base, blend, funcf) vec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b)) #define BlendNormal(base, blend) (blend) #define BlendLighten BlendLightenf #define BlendDarken BlendDarkenf #define BlendMultiply(base, blend) (base * blend) #define BlendAverage(base, blend) ((base + blend) / 2.0) #define BlendAdd(base, blend) min(base + blend, vec3(1.0)) #define BlendSubstract(base, blend) max(base + blend - vec3(1.0), vec3(0.0)) #define BlendDifference(base, blend) abs(base - blend) #define BlendNegation(base, blend) (vec3(1.0) - abs(vec3(1.0) - base - blend)) #define BlendExclusion(base, blend) (base + blend - 2.0 * base * blend) #define BlendScreen(base, blend) Blend(base, blend, BlendScreenf) #define BlendOverlay(base, blend) Blend(base, blend, BlendOverlayf) #define BlendSoftLight(base, blend) Blend(base, blend, BlendSoftLightf) #define BlendHardLight(base, blend) BlendOverlay(blend, base) #define BlendColorDodge(base, blend) Blend(base, blend, BlendColorDodgef) #define BlendColorBurn(base, blend) Blend(base, blend, BlendColorBurnf) #define BlendLinearDodge BlendAdd #define BlendLinearBurn BlendSubstract #define BlendLinearLight(base, blend) Blend(base, blend, BlendLinearLightf) #define BlendVividLight(base, blend) Blend(base, blend, BlendVividLightf) #define BlendPinLight(base, blend) Blend(base, blend, BlendPinLightf) #define BlendHardMix(base, blend) Blend(base, blend, BlendHardMixf) #define BlendReflect(base, blend) Blend(base, blend, BlendReflectf) #define BlendGlow(base, blend) BlendReflect(blend, base) #define BlendPhoenix(base, blend) (min(base, blend) - max(base, blend) + vec3(1.0)) #define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O)) vec3 BlendHue(vec3 base, vec3 blend) { vec3 baseHSL = RGBToHSL(base); return HSLToRGB(vec3(RGBToHSL(blend).r, baseHSL.g, baseHSL.b)); } vec3 BlendSaturation(vec3 base, vec3 blend) { vec3 baseHSL = RGBToHSL(base); return HSLToRGB(vec3(baseHSL.r, RGBToHSL(blend).g, baseHSL.b)); } vec3 BlendColor(vec3 base, vec3 blend) { vec3 blendHSL = RGBToHSL(blend); return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b)); } vec3 BlendLuminosity(vec3 base, vec3 blend) { vec3 baseHSL = RGBToHSL(base); return HSLToRGB(vec3(baseHSL.r, baseHSL.g, RGBToHSL(blend).b)); } )shader"; return glsl; } static std::string get_chroma_glsl() { static std::string glsl = R"shader( // Chroma keying // Author: Tim Eves // // This implements the Chroma key algorithm described in the paper: // 'Software Chroma Keying in an Imersive Virtual Environment' // by F. van den Bergh & V. Lalioti // but as a pixel shader algorithm. // vec4 grey_xfer = is_hd ? vec4(0.2126, 0.7152, 0.0722, 0) : vec4(0.299, 0.587, 0.114, 0); // This allows us to implement the paper's alphaMap curve in software // rather than a largeish array float alpha_map(float d) { return 1.0 - smoothstep(1.0, chroma_softness, d); } // http://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl vec3 rgb2hsv(vec3 c) { vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g)); vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r)); float d = q.x - min(q.w, q.y); float e = 1.0e-10; return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); } // From the same page vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } float AngleDiff(float angle1, float angle2) { return 0.5 - abs(abs(angle1 - angle2) - 0.5); } float AngleDiffDirectional(float angle1, float angle2) { float diff = angle1 - angle2; return diff < -0.5 ? diff + 1.0 : (diff > 0.5 ? diff - 1.0 : diff); } float Distance(float actual, float target) { return min(0.0, target - actual); } float ColorDistance(vec3 hsv) { float hueDiff = AngleDiff(hsv.x, chroma_target_hue) * 2; float saturationDiff = Distance(hsv.y, chroma_min_saturation); float brightnessDiff = Distance(hsv.z, chroma_min_brightness); float saturationBrightnessScore = max(brightnessDiff, saturationDiff); float hueScore = hueDiff - chroma_hue_width; return -hueScore * saturationBrightnessScore; } vec3 supress_spill(vec3 c) { float hue = c.x; float diff = AngleDiffDirectional(hue, chroma_target_hue); float distance = abs(diff) / chroma_spill_suppress; if (distance < 1) { c.x = diff < 0 ? chroma_target_hue - chroma_spill_suppress : chroma_target_hue + chroma_spill_suppress; c.y *= min(1.0, distance + chroma_spill_suppress_saturation); } return c; } // Key on any color vec4 ChromaOnCustomColor(vec4 c) { vec3 hsv = rgb2hsv(c.rgb); float distance = ColorDistance(hsv); float d = distance * -2.0 + 1.0; vec4 suppressed = vec4(hsv2rgb(supress_spill(hsv)), 1.0); float alpha = alpha_map(d); suppressed *= alpha; return chroma_show_mask ? vec4(suppressed.a, suppressed.a, suppressed.a, 1) : suppressed; } )shader"; return glsl; } server-2.2.0-stable/src/accelerator/ogl/image/image_kernel.cpp000066400000000000000000000377131341175263200243540ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "image_kernel.h" #include "blending_glsl.h" #include "image_shader.h" #include "../util/device.h" #include "../util/shader.h" #include "../util/texture.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace accelerator { namespace ogl { // http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect bool get_line_intersection(double p0_x, double p0_y, double p1_x, double p1_y, double p2_x, double p2_y, double p3_x, double p3_y, double& result_x, double& result_y) { double s1_x = p1_x - p0_x; double s1_y = p1_y - p0_y; double s2_x = p3_x - p2_x; double s2_y = p3_y - p2_y; double s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y); double t = (s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y); if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { // Collision detected result_x = p0_x + (t * s1_x); result_y = p0_y + (t * s1_y); return true; } return false; // No collision } double hypotenuse(double x1, double y1, double x2, double y2) { auto x = x2 - x1; auto y = y2 - y1; return std::sqrt(x * x + y * y); } double calc_q(double close_diagonal, double distant_diagonal) { return (close_diagonal + distant_diagonal) / distant_diagonal; } bool is_above_screen(double y) { return y < 0.0; } bool is_below_screen(double y) { return y > 1.0; } bool is_left_of_screen(double x) { return x < 0.0; } bool is_right_of_screen(double x) { return x > 1.0; } bool is_outside_screen(const std::vector& coords) { auto x_coords = coords | boost::adaptors::transformed([](const core::frame_geometry::coord& c) { return c.vertex_x; }); auto y_coords = coords | boost::adaptors::transformed([](const core::frame_geometry::coord& c) { return c.vertex_y; }); return boost::algorithm::all_of(x_coords, &is_left_of_screen) || boost::algorithm::all_of(x_coords, &is_right_of_screen) || boost::algorithm::all_of(y_coords, &is_above_screen) || boost::algorithm::all_of(y_coords, &is_below_screen); } struct image_kernel::impl { spl::shared_ptr ogl_; spl::shared_ptr shader_; GLuint vao_; GLuint vbo_; impl(const spl::shared_ptr& ogl) : ogl_(ogl) , shader_(ogl_->dispatch_sync([&] { return get_image_shader(ogl); })) { ogl_->dispatch_sync([&] { GL(glGenVertexArrays(1, &vao_)); GL(glGenBuffers(1, &vbo_)); }); } ~impl() { ogl_->dispatch_sync([&] { GL(glDeleteVertexArrays(1, &vao_)); GL(glDeleteBuffers(1, &vbo_)); }); } void draw(draw_params params) { static const double epsilon = 0.001; CASPAR_ASSERT(params.pix_desc.planes.size() == params.textures.size()); if (params.textures.empty() || !params.background) { return; } if (params.transform.opacity < epsilon) { return; } auto coords = params.geometry.data(); if (coords.empty()) { return; } // Calculate transforms auto f_p = params.transform.fill_translation; auto f_s = params.transform.fill_scale; bool is_default_geometry = boost::equal(coords, core::frame_geometry::get_default().data()); auto aspect = params.aspect_ratio; auto angle = params.transform.angle; auto anchor = params.transform.anchor; auto crop = params.transform.crop; auto pers = params.transform.perspective; pers.ur[0] -= 1.0; pers.lr[0] -= 1.0; pers.lr[1] -= 1.0; pers.ll[1] -= 1.0; std::vector> pers_corners = {pers.ul, pers.ur, pers.lr, pers.ll}; auto do_crop = [&](core::frame_geometry::coord& coord) { if (!is_default_geometry) { // TODO implement support for non-default geometry. return; } coord.vertex_x = std::max(coord.vertex_x, crop.ul[0]); coord.vertex_x = std::min(coord.vertex_x, crop.lr[0]); coord.vertex_y = std::max(coord.vertex_y, crop.ul[1]); coord.vertex_y = std::min(coord.vertex_y, crop.lr[1]); coord.texture_x = std::max(coord.texture_x, crop.ul[0]); coord.texture_x = std::min(coord.texture_x, crop.lr[0]); coord.texture_y = std::max(coord.texture_y, crop.ul[1]); coord.texture_y = std::min(coord.texture_y, crop.lr[1]); }; auto do_perspective = [=](core::frame_geometry::coord& coord, const std::array& pers_corner) { if (!is_default_geometry) { // TODO implement support for non-default geometry. return; } coord.vertex_x += pers_corner[0]; coord.vertex_y += pers_corner[1]; }; auto rotate = [&](core::frame_geometry::coord& coord) { auto orig_x = (coord.vertex_x - anchor[0]) * f_s[0]; auto orig_y = (coord.vertex_y - anchor[1]) * f_s[1] / aspect; coord.vertex_x = orig_x * std::cos(angle) - orig_y * std::sin(angle); coord.vertex_y = orig_x * std::sin(angle) + orig_y * std::cos(angle); coord.vertex_y *= aspect; }; auto move = [&](core::frame_geometry::coord& coord) { coord.vertex_x += f_p[0]; coord.vertex_y += f_p[1]; }; int corner = 0; for (auto& coord : coords) { do_crop(coord); do_perspective(coord, pers_corners.at(corner)); rotate(coord); move(coord); if (++corner == 4) { corner = 0; } } // Skip drawing if all the coordinates will be outside the screen. if (is_outside_screen(coords)) { return; } // Bind textures for (int n = 0; n < params.textures.size(); ++n) { params.textures[n]->bind(n); } if (params.local_key) { params.local_key->bind(static_cast(texture_id::local_key)); } if (params.layer_key) { params.layer_key->bind(static_cast(texture_id::layer_key)); } // Setup shader shader_->use(); shader_->set("plane[0]", texture_id::plane0); shader_->set("plane[1]", texture_id::plane1); shader_->set("plane[2]", texture_id::plane2); shader_->set("plane[3]", texture_id::plane3); shader_->set("local_key", texture_id::local_key); shader_->set("layer_key", texture_id::layer_key); shader_->set("is_hd", params.pix_desc.planes.at(0).height > 700 ? 1 : 0); shader_->set("has_local_key", static_cast(params.local_key)); shader_->set("has_layer_key", static_cast(params.layer_key)); shader_->set("pixel_format", params.pix_desc.format); shader_->set("opacity", params.transform.is_key ? 1.0 : params.transform.opacity); if (params.transform.chroma.enable) { shader_->set("chroma", true); shader_->set("chroma_show_mask", params.transform.chroma.show_mask); shader_->set("chroma_target_hue", params.transform.chroma.target_hue / 360.0); shader_->set("chroma_hue_width", params.transform.chroma.hue_width); shader_->set("chroma_min_saturation", params.transform.chroma.min_saturation); shader_->set("chroma_min_brightness", params.transform.chroma.min_brightness); shader_->set("chroma_softness", 1.0 + params.transform.chroma.softness); shader_->set("chroma_spill_suppress", params.transform.chroma.spill_suppress / 360.0); shader_->set("chroma_spill_suppress_saturation", params.transform.chroma.spill_suppress_saturation); } else { shader_->set("chroma", false); } // Setup blend_func if (params.transform.is_key) { params.blend_mode = core::blend_mode::normal; } params.background->bind(static_cast(texture_id::background)); shader_->set("background", texture_id::background); shader_->set("blend_mode", params.blend_mode); shader_->set("keyer", params.keyer); // Setup image-adjustements if (params.transform.levels.min_input > epsilon || params.transform.levels.max_input < 1.0 - epsilon || params.transform.levels.min_output > epsilon || params.transform.levels.max_output < 1.0 - epsilon || std::abs(params.transform.levels.gamma - 1.0) > epsilon) { shader_->set("levels", true); shader_->set("min_input", params.transform.levels.min_input); shader_->set("max_input", params.transform.levels.max_input); shader_->set("min_output", params.transform.levels.min_output); shader_->set("max_output", params.transform.levels.max_output); shader_->set("gamma", params.transform.levels.gamma); } else { shader_->set("levels", false); } if (std::abs(params.transform.brightness - 1.0) > epsilon || std::abs(params.transform.saturation - 1.0) > epsilon || std::abs(params.transform.contrast - 1.0) > epsilon) { shader_->set("csb", true); shader_->set("brt", params.transform.brightness); shader_->set("sat", params.transform.saturation); shader_->set("con", params.transform.contrast); } else { shader_->set("csb", false); } // Setup drawing area GL(glViewport(0, 0, params.background->width(), params.background->height())); glDisable(GL_DEPTH_TEST); auto m_p = params.transform.clip_translation; auto m_s = params.transform.clip_scale; bool scissor = m_p[0] > std::numeric_limits::epsilon() || m_p[1] > std::numeric_limits::epsilon() || m_s[0] < (1.0 - std::numeric_limits::epsilon()) || m_s[1] < (1.0 - std::numeric_limits::epsilon()); if (scissor) { double w = static_cast(params.background->width()); double h = static_cast(params.background->height()); GL(glEnable(GL_SCISSOR_TEST)); GL(glScissor(static_cast(m_p[0] * w), static_cast(m_p[1] * h), std::max(0, static_cast(m_s[0] * w)), std::max(0, static_cast(m_s[1] * h)))); } // Set render target params.background->attach(); // Perspective correction double diagonal_intersection_x; double diagonal_intersection_y; if (get_line_intersection(pers.ul[0] + crop.ul[0], pers.ul[1] + crop.ul[1], pers.lr[0] + crop.lr[0], pers.lr[1] + crop.lr[1], pers.ur[0] + crop.lr[0], pers.ur[1] + crop.ul[1], pers.ll[0] + crop.ul[0], pers.ll[1] + crop.lr[1], diagonal_intersection_x, diagonal_intersection_y) && is_default_geometry) { // http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/ auto d0 = hypotenuse( pers.ll[0] + crop.ul[0], pers.ll[1] + crop.lr[1], diagonal_intersection_x, diagonal_intersection_y); auto d1 = hypotenuse( pers.lr[0] + crop.lr[0], pers.lr[1] + crop.lr[1], diagonal_intersection_x, diagonal_intersection_y); auto d2 = hypotenuse( pers.ur[0] + crop.lr[0], pers.ur[1] + crop.ul[1], diagonal_intersection_x, diagonal_intersection_y); auto d3 = hypotenuse( pers.ul[0] + crop.ul[0], pers.ul[1] + crop.ul[1], diagonal_intersection_x, diagonal_intersection_y); auto ulq = calc_q(d3, d1); auto urq = calc_q(d2, d0); auto lrq = calc_q(d1, d3); auto llq = calc_q(d0, d2); std::vector q_values = {ulq, urq, lrq, llq}; corner = 0; for (auto& coord : coords) { coord.texture_q = q_values[corner]; coord.texture_x *= q_values[corner]; coord.texture_y *= q_values[corner]; if (++corner == 4) corner = 0; } } // Draw switch (params.geometry.type()) { case core::frame_geometry::geometry_type::quad: { GL(glBindVertexArray(vao_)); GL(glBindBuffer(GL_ARRAY_BUFFER, vbo_)); std::vector coords_triangles{ coords[0], coords[1], coords[2], coords[0], coords[2], coords[3]}; GL(glBufferData(GL_ARRAY_BUFFER, static_cast(sizeof(core::frame_geometry::coord)) * coords_triangles.size(), coords_triangles.data(), GL_STATIC_DRAW)); auto stride = static_cast(sizeof(core::frame_geometry::coord)); auto vtx_loc = shader_->get_attrib_location("Position"); auto tex_loc = shader_->get_attrib_location("TexCoordIn"); GL(glEnableVertexAttribArray(vtx_loc)); GL(glEnableVertexAttribArray(tex_loc)); GL(glVertexAttribPointer(vtx_loc, 2, GL_DOUBLE, GL_FALSE, stride, nullptr)); GL(glVertexAttribPointer(tex_loc, 4, GL_DOUBLE, GL_FALSE, stride, (GLvoid*)(2 * sizeof(GLdouble)))); GL(glDrawArrays(GL_TRIANGLES, 0, static_cast(coords_triangles.size()))); GL(glTextureBarrier()); GL(glDisableVertexAttribArray(vtx_loc)); GL(glDisableVertexAttribArray(tex_loc)); GL(glBindVertexArray(0)); GL(glBindBuffer(GL_ARRAY_BUFFER, 0)); break; } default: break; } // Cleanup GL(glDisable(GL_SCISSOR_TEST)); GL(glDisable(GL_BLEND)); } }; image_kernel::image_kernel(const spl::shared_ptr& ogl) : impl_(new impl(ogl)) { } image_kernel::~image_kernel() {} void image_kernel::draw(const draw_params& params) { impl_->draw(params); } }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/image/image_kernel.h000066400000000000000000000042621341175263200240120ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include namespace caspar { namespace accelerator { namespace ogl { enum class keyer { linear = 0, additive, }; struct draw_params final { core::pixel_format_desc pix_desc = core::pixel_format::invalid; std::vector> textures; core::image_transform transform; core::frame_geometry geometry = core::frame_geometry::get_default(); core::blend_mode blend_mode = core::blend_mode::normal; ogl::keyer keyer = ogl::keyer::linear; std::shared_ptr background; std::shared_ptr local_key; std::shared_ptr layer_key; double aspect_ratio = 1.0; }; class image_kernel final { image_kernel(const image_kernel&); image_kernel& operator=(const image_kernel&); public: image_kernel(const spl::shared_ptr& ogl); ~image_kernel(); void draw(const draw_params& params); private: struct impl; spl::unique_ptr impl_; }; }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/image/image_mixer.cpp000066400000000000000000000305111341175263200242050ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "image_mixer.h" #include "image_kernel.h" #include "../util/buffer.h" #include "../util/device.h" #include "../util/texture.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace accelerator { namespace ogl { typedef std::shared_future> future_texture; struct item { core::pixel_format_desc pix_desc = core::pixel_format::invalid; std::vector textures; core::image_transform transform; core::frame_geometry geometry = core::frame_geometry::get_default(); }; struct layer { std::vector sublayers; std::vector items; core::blend_mode blend_mode; layer(core::blend_mode blend_mode) : blend_mode(blend_mode) { } }; class image_renderer { spl::shared_ptr ogl_; image_kernel kernel_; public: image_renderer(const spl::shared_ptr& ogl) : ogl_(ogl) , kernel_(ogl_) { } std::future> operator()(std::vector layers, const core::video_format_desc& format_desc) { if (layers.empty()) { // Bypass GPU with empty frame. static const std::vector buffer(4096 * 4096 * 4, 0); return make_ready_future(array(buffer.data(), format_desc.size, true)); } return flatten(ogl_->dispatch_async([=]() mutable -> std::shared_future> { auto target_texture = ogl_->create_texture(format_desc.width, format_desc.height, 4); draw(target_texture, std::move(layers), format_desc); return ogl_->copy_async(target_texture); })); } private: void draw(std::shared_ptr& target_texture, std::vector layers, const core::video_format_desc& format_desc) { std::shared_ptr layer_key_texture; for (auto& layer : layers) { draw(target_texture, layer.sublayers, format_desc); draw(target_texture, std::move(layer), layer_key_texture, format_desc); } } void draw(std::shared_ptr& target_texture, layer layer, std::shared_ptr& layer_key_texture, const core::video_format_desc& format_desc) { if (layer.items.empty()) return; std::shared_ptr local_key_texture; std::shared_ptr local_mix_texture; if (layer.blend_mode != core::blend_mode::normal) { auto layer_texture = ogl_->create_texture(target_texture->width(), target_texture->height(), 4); for (auto& item : layer.items) draw(layer_texture, std::move(item), layer_key_texture, local_key_texture, local_mix_texture, format_desc); draw(layer_texture, std::move(local_mix_texture), core::blend_mode::normal); draw(target_texture, std::move(layer_texture), layer.blend_mode); } else // fast path { for (auto& item : layer.items) draw(target_texture, std::move(item), layer_key_texture, local_key_texture, local_mix_texture, format_desc); draw(target_texture, std::move(local_mix_texture), core::blend_mode::normal); } layer_key_texture = std::move(local_key_texture); } void draw(std::shared_ptr& target_texture, item item, std::shared_ptr& layer_key_texture, std::shared_ptr& local_key_texture, std::shared_ptr& local_mix_texture, const core::video_format_desc& format_desc) { draw_params draw_params; draw_params.pix_desc = std::move(item.pix_desc); draw_params.transform = std::move(item.transform); draw_params.geometry = item.geometry; draw_params.aspect_ratio = static_cast(format_desc.square_width) / static_cast(format_desc.square_height); for (auto& future_texture : item.textures) { draw_params.textures.push_back(spl::make_shared_ptr(future_texture.get())); } if (item.transform.is_key) { local_key_texture = local_key_texture ? local_key_texture : ogl_->create_texture(target_texture->width(), target_texture->height(), 1); draw_params.background = local_key_texture; draw_params.local_key = nullptr; draw_params.layer_key = nullptr; kernel_.draw(std::move(draw_params)); } else if (item.transform.is_mix) { local_mix_texture = local_mix_texture ? local_mix_texture : ogl_->create_texture(target_texture->width(), target_texture->height(), 4); draw_params.background = local_mix_texture; draw_params.local_key = std::move(local_key_texture); draw_params.layer_key = layer_key_texture; draw_params.keyer = keyer::additive; kernel_.draw(std::move(draw_params)); } else { draw(target_texture, std::move(local_mix_texture), core::blend_mode::normal); draw_params.background = target_texture; draw_params.local_key = std::move(local_key_texture); draw_params.layer_key = layer_key_texture; kernel_.draw(std::move(draw_params)); } } void draw(std::shared_ptr& target_texture, std::shared_ptr&& source_buffer, core::blend_mode blend_mode = core::blend_mode::normal) { if (!source_buffer) return; draw_params draw_params; draw_params.pix_desc.format = core::pixel_format::bgra; draw_params.pix_desc.planes = { core::pixel_format_desc::plane(source_buffer->width(), source_buffer->height(), 4)}; draw_params.textures = {spl::make_shared_ptr(source_buffer)}; draw_params.transform = core::image_transform(); draw_params.blend_mode = blend_mode; draw_params.background = target_texture; draw_params.geometry = core::frame_geometry::get_default(); kernel_.draw(std::move(draw_params)); } }; struct image_mixer::impl : public core::frame_factory , public std::enable_shared_from_this { spl::shared_ptr ogl_; image_renderer renderer_; std::vector transform_stack_; std::vector layers_; // layer/stream/items std::vector layer_stack_; public: impl(const spl::shared_ptr& ogl, int channel_id) : ogl_(ogl) , renderer_(ogl) , transform_stack_(1) { CASPAR_LOG(info) << L"Initialized OpenGL Accelerated GPU Image Mixer for channel " << channel_id; } void push(const core::frame_transform& transform) { auto previous_layer_depth = transform_stack_.back().layer_depth; transform_stack_.push_back(transform_stack_.back() * transform.image_transform); auto new_layer_depth = transform_stack_.back().layer_depth; if (previous_layer_depth < new_layer_depth) { layer new_layer(transform_stack_.back().blend_mode); if (layer_stack_.empty()) { layers_.push_back(std::move(new_layer)); layer_stack_.push_back(&layers_.back()); } else { layer_stack_.back()->sublayers.push_back(std::move(new_layer)); layer_stack_.push_back(&layer_stack_.back()->sublayers.back()); } } } void visit(const core::const_frame& frame) { if (frame.pixel_format_desc().format == core::pixel_format::invalid) return; if (frame.pixel_format_desc().planes.empty()) return; item item; item.pix_desc = frame.pixel_format_desc(); item.transform = transform_stack_.back(); item.geometry = frame.geometry(); auto textures_ptr = boost::any_cast>>(frame.opaque()); if (textures_ptr) { item.textures = *textures_ptr; } else { for (int n = 0; n < static_cast(item.pix_desc.planes.size()); ++n) { item.textures.emplace_back(ogl_->copy_async(frame.image_data(n), item.pix_desc.planes[n].width, item.pix_desc.planes[n].height, item.pix_desc.planes[n].stride)); } } layer_stack_.back()->items.push_back(item); } void pop() { transform_stack_.pop_back(); layer_stack_.resize(transform_stack_.back().layer_depth); } std::future> render(const core::video_format_desc& format_desc) { return renderer_(std::move(layers_), format_desc); } core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override { std::vector> image_data; for (auto& plane : desc.planes) { image_data.push_back(ogl_->create_array(plane.size)); } std::weak_ptr weak_self = shared_from_this(); return core::mutable_frame( tag, std::move(image_data), array{}, desc, [weak_self, desc](std::vector> image_data) -> boost::any { auto self = weak_self.lock(); if (!self) { return boost::any{}; } std::vector textures; for (int n = 0; n < static_cast(desc.planes.size()); ++n) { textures.emplace_back(self->ogl_->copy_async( image_data[n], desc.planes[n].width, desc.planes[n].height, desc.planes[n].stride)); } return std::make_shared(std::move(textures)); }); } }; image_mixer::image_mixer(const spl::shared_ptr& ogl, int channel_id) : impl_(std::make_unique(ogl, channel_id)) { } image_mixer::~image_mixer() {} void image_mixer::push(const core::frame_transform& transform) { impl_->push(transform); } void image_mixer::visit(const core::const_frame& frame) { impl_->visit(frame); } void image_mixer::pop() { impl_->pop(); } std::future> image_mixer::operator()(const core::video_format_desc& format_desc) { return impl_->render(format_desc); } core::mutable_frame image_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc) { return impl_->create_frame(tag, desc); } }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/image/image_mixer.h000066400000000000000000000036201341175263200236530ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include #include #include #include #include namespace caspar { namespace accelerator { namespace ogl { class image_mixer final : public core::image_mixer { public: image_mixer(const spl::shared_ptr& ogl, int channel_id); image_mixer(const image_mixer&) = delete; ~image_mixer(); image_mixer& operator=(const image_mixer&) = delete; std::future> operator()(const core::video_format_desc& format_desc) override; core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override; // core::image_mixer void push(const core::frame_transform& frame) override; void visit(const core::const_frame& frame) override; void pop() override; private: struct impl; std::shared_ptr impl_; }; }}} // namespace caspar::accelerator::oglserver-2.2.0-stable/src/accelerator/ogl/image/image_shader.cpp000066400000000000000000000213041341175263200243270ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "image_shader.h" #include "../util/device.h" #include "../util/shader.h" #include "blending_glsl.h" #include #include #include namespace caspar { namespace accelerator { namespace ogl { std::weak_ptr g_shader; std::mutex g_shader_mutex; std::string get_blend_color_func() { return get_adjustement_glsl() + get_blend_glsl() + R"shader( vec3 get_blend_color(vec3 back, vec3 fore) { switch(blend_mode) { case 0: return BlendNormal(back, fore); case 1: return BlendLighten(back, fore); case 2: return BlendDarken(back, fore); case 3: return BlendMultiply(back, fore); case 4: return BlendAverage(back, fore); case 5: return BlendAdd(back, fore); case 6: return BlendSubstract(back, fore); case 7: return BlendDifference(back, fore); case 8: return BlendNegation(back, fore); case 9: return BlendExclusion(back, fore); case 10: return BlendScreen(back, fore); case 11: return BlendOverlay(back, fore); // case 12: return BlendSoftLight(back, fore); case 13: return BlendHardLight(back, fore); case 14: return BlendColorDodge(back, fore); case 15: return BlendColorBurn(back, fore); case 16: return BlendLinearDodge(back, fore); case 17: return BlendLinearBurn(back, fore); case 18: return BlendLinearLight(back, fore); case 19: return BlendVividLight(back, fore); case 20: return BlendPinLight(back, fore); case 21: return BlendHardMix(back, fore); case 22: return BlendReflect(back, fore); case 23: return BlendGlow(back, fore); case 24: return BlendPhoenix(back, fore); case 25: return BlendHue(back, fore); case 26: return BlendSaturation(back, fore); case 27: return BlendColor(back, fore); case 28: return BlendLuminosity(back, fore); } return BlendNormal(back, fore); } vec4 blend(vec4 fore) { vec4 back = texture(background, TexCoord2.st).bgra; if(blend_mode != 0) fore.rgb = get_blend_color(back.rgb/(back.a+0.0000001), fore.rgb/(fore.a+0.0000001))*fore.a; switch(keyer) { case 1: return fore + back; // additive default: return fore + (1.0-fore.a)*back; // linear } } )shader"; } std::string get_chroma_func() { return get_chroma_glsl() + R"shader( vec4 chroma_key(vec4 c) { return ChromaOnCustomColor(c.bgra).bgra; } )shader"; } std::string get_vertex() { return R"shader( #version 450 in vec4 TexCoordIn; in vec2 Position; out vec4 TexCoord; out vec4 TexCoord2; void main() { TexCoord = TexCoordIn; vec4 pos = vec4(Position, 0, 1); TexCoord2 = vec4(pos.xy, 0.0, 0.0); pos.x = pos.x*2.0 - 1.0; pos.y = pos.y*2.0 - 1.0; gl_Position = pos; } )shader"; } std::string get_fragment() { return R"shader( #version 450 in vec4 TexCoord; in vec4 TexCoord2; out vec4 fragColor; uniform sampler2D background; uniform sampler2D plane[4]; uniform sampler2D local_key; uniform sampler2D layer_key; uniform bool is_hd; uniform bool has_local_key; uniform bool has_layer_key; uniform int blend_mode; uniform int keyer; uniform int pixel_format; uniform float opacity; uniform bool levels; uniform float min_input; uniform float max_input; uniform float gamma; uniform float min_output; uniform float max_output; uniform bool csb; uniform float brt; uniform float sat; uniform float con; uniform bool chroma; uniform bool chroma_show_mask; uniform float chroma_target_hue; uniform float chroma_hue_width; uniform float chroma_min_saturation; uniform float chroma_min_brightness; uniform float chroma_softness; uniform float chroma_spill_suppress; uniform float chroma_spill_suppress_saturation; )shader" + get_blend_color_func() + get_chroma_func() + R"shader( vec4 ycbcra_to_rgba_sd(float Y, float Cb, float Cr, float A) { vec4 rgba; rgba.b = (1.164*(Y*255 - 16) + 1.596*(Cr*255 - 128))/255; rgba.g = (1.164*(Y*255 - 16) - 0.813*(Cr*255 - 128) - 0.391*(Cb*255 - 128))/255; rgba.r = (1.164*(Y*255 - 16) + 2.018*(Cb*255 - 128))/255; rgba.a = A; return rgba; } vec4 ycbcra_to_rgba_hd(float Y, float Cb, float Cr, float A) { vec4 rgba; rgba.b = (1.164*(Y*255 - 16) + 1.793*(Cr*255 - 128))/255; rgba.g = (1.164*(Y*255 - 16) - 0.534*(Cr*255 - 128) - 0.213*(Cb*255 - 128))/255; rgba.r = (1.164*(Y*255 - 16) + 2.115*(Cb*255 - 128))/255; rgba.a = A; return rgba; } vec4 ycbcra_to_rgba(float y, float cb, float cr, float a) { if(is_hd) return ycbcra_to_rgba_hd(y, cb, cr, a); else return ycbcra_to_rgba_sd(y, cb, cr, a); } vec4 get_sample(sampler2D sampler, vec2 coords) { return texture2D(sampler, coords); } vec4 get_rgba_color() { switch(pixel_format) { case 0: //gray return vec4(get_sample(plane[0], TexCoord.st / TexCoord.q).rrr, 1.0); case 1: //bgra, return get_sample(plane[0], TexCoord.st / TexCoord.q).bgra; case 2: //rgba, return get_sample(plane[0], TexCoord.st / TexCoord.q).rgba; case 3: //argb, return get_sample(plane[0], TexCoord.st / TexCoord.q).argb; case 4: //abgr, return get_sample(plane[0], TexCoord.st / TexCoord.q).gbar; case 5: //ycbcr, { float y = get_sample(plane[0], TexCoord.st / TexCoord.q).r; float cb = get_sample(plane[1], TexCoord.st / TexCoord.q).r; float cr = get_sample(plane[2], TexCoord.st / TexCoord.q).r; return ycbcra_to_rgba(y, cb, cr, 1.0); } case 6: //ycbcra { float y = get_sample(plane[0], TexCoord.st / TexCoord.q).r; float cb = get_sample(plane[1], TexCoord.st / TexCoord.q).r; float cr = get_sample(plane[2], TexCoord.st / TexCoord.q).r; float a = get_sample(plane[3], TexCoord.st / TexCoord.q).r; return ycbcra_to_rgba(y, cb, cr, a); } case 7: //luma { vec3 y3 = get_sample(plane[0], TexCoord.st / TexCoord.q).rrr; return vec4((y3-0.065)/0.859, 1.0); } case 8: //bgr, return vec4(get_sample(plane[0], TexCoord.st / TexCoord.q).bgr, 1.0); case 9: //rgb, return vec4(get_sample(plane[0], TexCoord.st / TexCoord.q).rgb, 1.0); } return vec4(0.0, 0.0, 0.0, 0.0); } void main() { vec4 color = get_rgba_color(); if (chroma) color = chroma_key(color); if(levels) color.rgb = LevelsControl(color.rgb, min_input, gamma, max_input, min_output, max_output); if(csb) color.rgb = ContrastSaturationBrightness(color, brt, sat, con); if(has_local_key) color *= texture(local_key, TexCoord2.st).r; if(has_layer_key) color *= texture(layer_key, TexCoord2.st).r; color *= opacity; if (blend_mode >= 0) color = blend(color); fragColor = color.bgra; } )shader"; } std::shared_ptr get_image_shader(const spl::shared_ptr& ogl) { std::lock_guard lock(g_shader_mutex); auto existing_shader = g_shader.lock(); if (existing_shader) { return existing_shader; } // The deleter is alive until the weak pointer is destroyed, so we have // to weakly reference ogl, to not keep it alive until atexit std::weak_ptr weak_ogl = ogl; auto deleter = [weak_ogl](shader* p) { auto ogl = weak_ogl.lock(); if (ogl) { ogl->dispatch_async([=] { delete p; }); } }; existing_shader.reset(new shader(get_vertex(), get_fragment()), deleter); g_shader = existing_shader; return existing_shader; } }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/image/image_shader.h000066400000000000000000000022431341175263200237750ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { namespace accelerator { namespace ogl { class shader; class device; enum class texture_id { plane0 = 0, plane1, plane2, plane3, local_key, layer_key, background }; std::shared_ptr get_image_shader(const spl::shared_ptr& ogl); }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/util/000077500000000000000000000000001341175263200211065ustar00rootroot00000000000000server-2.2.0-stable/src/accelerator/ogl/util/buffer.cpp000066400000000000000000000046001341175263200230630ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "buffer.h" #include #include namespace caspar { namespace accelerator { namespace ogl { struct buffer::impl : boost::noncopyable { GLuint id_ = 0; GLsizei size_ = 0; void* data_ = nullptr; bool write_ = false; GLenum target_ = 0; GLbitfield flags_ = 0; public: impl(int size, bool write) : size_(size) , write_(write) , target_(!write ? GL_PIXEL_PACK_BUFFER : GL_PIXEL_UNPACK_BUFFER) , flags_(GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | (write ? GL_MAP_WRITE_BIT : GL_MAP_READ_BIT)) { GL(glCreateBuffers(1, &id_)); GL(glNamedBufferStorage(id_, size_, nullptr, flags_)); data_ = GL2(glMapNamedBufferRange(id_, 0, size_, flags_)); } ~impl() { GL(glUnmapNamedBuffer(id_)); glDeleteBuffers(1, &id_); } void bind() { GL(glBindBuffer(target_, id_)); } void unbind() { GL(glBindBuffer(target_, 0)); } }; buffer::buffer(int size, bool write) : impl_(new impl(size, write)) { } buffer::buffer(buffer&& other) : impl_(std::move(other.impl_)) { } buffer::~buffer() {} buffer& buffer::operator=(buffer&& other) { impl_ = std::move(other.impl_); return *this; } void* buffer::data() { return impl_->data_; } bool buffer::write() const { return impl_->write_; } int buffer::size() const { return impl_->size_; } void buffer::bind() { return impl_->bind(); } void buffer::unbind() { return impl_->unbind(); } int buffer::id() const { return impl_->id_; } }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/util/buffer.h000066400000000000000000000025511341175263200225330ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { namespace accelerator { namespace ogl { class buffer final { public: buffer(int size, bool write); buffer(const buffer&) = delete; buffer(buffer&& other); ~buffer(); buffer& operator=(const buffer&) = delete; buffer& operator =(buffer&& other); void bind(); void unbind(); int id() const; void* data(); int size() const; bool write() const; private: struct impl; std::unique_ptr impl_; }; }}} // namespace caspar::accelerator::oglserver-2.2.0-stable/src/accelerator/ogl/util/device.cpp000066400000000000000000000226001341175263200230510ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "device.h" #include "buffer.h" #include "shader.h" #include "texture.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace accelerator { namespace ogl { using namespace boost::asio; struct device::impl : public std::enable_shared_from_this { typedef tbb::concurrent_bounded_queue> texture_queue_t; typedef tbb::concurrent_bounded_queue> buffer_queue_t; sf::Context device_; std::array, 4> device_pools_; std::array, 2> host_pools_; typedef tbb::concurrent_bounded_queue> sync_queue_t; sync_queue_t sync_queue_; GLuint fbo_; std::wstring version_; io_context service_; decltype(make_work_guard(service_)) work_; std::thread thread_; impl() : work_(make_work_guard(service_)) , device_(sf::ContextSettings(0, 0, 0, 4, 5, sf::ContextSettings::Attribute::Core), 1, 1) { CASPAR_LOG(info) << L"Initializing OpenGL Device."; device_.setActive(true); if (glewInit() != GLEW_OK) { CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info("Failed to initialize GLEW.")); } version_ = u16(reinterpret_cast(GL2(glGetString(GL_VERSION)))) + L" " + u16(reinterpret_cast(GL2(glGetString(GL_VENDOR)))); CASPAR_LOG(info) << L"Initialized OpenGL " << version(); if (!GLEW_VERSION_4_5 && !glewIsSupported("GL_ARB_sync GL_ARB_shader_objects GL_ARB_multitexture " "GL_ARB_direct_state_access GL_ARB_texture_barrier")) { CASPAR_THROW_EXCEPTION(not_supported() << msg_info("Your graphics card does not meet the minimum hardware requirements " "since it does not support OpenGL 4.5 or higher.")); } GL(glCreateFramebuffers(1, &fbo_)); GL(glBindFramebuffer(GL_FRAMEBUFFER, fbo_)); device_.setActive(false); thread_ = std::thread([&] { device_.setActive(true); set_thread_name(L"OpenGL Device"); service_.run(); device_.setActive(false); }); } ~impl() { work_.reset(); thread_.join(); device_.setActive(true); for (auto& pool : host_pools_) pool.clear(); for (auto& pool : device_pools_) pool.clear(); sync_queue_.clear(); GL(glDeleteFramebuffers(1, &fbo_)); } template auto spawn_async(Func&& func) { typedef decltype(func(std::declval())) result_type; typedef std::packaged_task task_type; auto task = task_type(std::forward(func)); auto future = task.get_future(); boost::asio::spawn(service_, std::move(task)); return future; } template auto dispatch_async(Func&& func) { typedef decltype(func()) result_type; typedef std::packaged_task task_type; auto task = task_type(std::forward(func)); auto future = task.get_future(); boost::asio::dispatch(service_, std::move(task)); return future; } template auto dispatch_sync(Func&& func) -> decltype(func()) { return dispatch_async(std::forward(func)).get(); } std::wstring version() { return version_; } std::shared_ptr create_texture(int width, int height, int stride, bool clear) { CASPAR_VERIFY(stride > 0 && stride < 5); CASPAR_VERIFY(width > 0 && height > 0); // TODO (perf) Shared pool. auto pool = &device_pools_[stride - 1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)]; std::shared_ptr tex; if (!pool->try_pop(tex)) { tex = std::make_shared(width, height, stride); } if (clear) { tex->clear(); } auto ptr = tex.get(); return std::shared_ptr( ptr, [tex = std::move(tex), pool, self = shared_from_this()](texture*) mutable { pool->push(tex); }); } std::shared_ptr create_buffer(int size, bool write) { CASPAR_VERIFY(size > 0); // TODO (perf) Shared pool. auto pool = &host_pools_[static_cast(write ? 1 : 0)][size]; std::shared_ptr buf; if (!pool->try_pop(buf)) { // TODO (perf) Avoid blocking in create_array. dispatch_sync([&] { buf = std::make_shared(size, write); }); } auto ptr = buf.get(); return std::shared_ptr(ptr, [buf = std::move(buf), self = shared_from_this()](buffer*) mutable { self->sync_queue_.emplace(std::move(buf)); }); } array create_array(int size) { auto buf = create_buffer(size, true); auto ptr = reinterpret_cast(buf->data()); return array(ptr, buf->size(), buf); } std::future> copy_async(const array& source, int width, int height, int stride) { return dispatch_async([=] { std::shared_ptr buf; auto tmp = source.template storage>(); if (tmp) { buf = *tmp; } else { buf = create_buffer(static_cast(source.size()), true); // TODO (perf) Copy inside a TBB worker. std::memcpy(buf->data(), source.data(), source.size()); } auto tex = create_texture(width, height, stride, false); tex->copy_from(*buf); // TODO (perf) save tex on source return tex; }); } std::future> copy_async(const std::shared_ptr& source) { return spawn_async([=](yield_context yield) { auto buf = create_buffer(source->size(), false); source->copy_to(*buf); sync_queue_.push(nullptr); auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); GL(glFlush()); deadline_timer timer(service_); for (auto n = 0; true; ++n) { // TODO (perf) Smarter non-polling solution? timer.expires_from_now(boost::posix_time::milliseconds(2)); timer.async_wait(yield); auto wait = glClientWaitSync(fence, 0, 1); if (wait == GL_ALREADY_SIGNALED || wait == GL_CONDITION_SATISFIED) { break; } } glDeleteSync(fence); { std::shared_ptr buf2; while (sync_queue_.try_pop(buf2) && buf2) { auto pool = &host_pools_[static_cast(buf2->write() ? 1 : 0)][buf2->size()]; pool->push(std::move(buf2)); } } auto ptr = reinterpret_cast(buf->data()); auto size = buf->size(); return array(ptr, size, std::move(buf)); }); } }; device::device() : impl_(new impl()) { } device::~device() {} std::shared_ptr device::create_texture(int width, int height, int stride) { return impl_->create_texture(width, height, stride, true); } array device::create_array(int size) { return impl_->create_array(size); } std::future> device::copy_async(const array& source, int width, int height, int stride) { return impl_->copy_async(source, width, height, stride); } std::future> device::copy_async(const std::shared_ptr& source) { return impl_->copy_async(source); } void device::dispatch(std::function func) { boost::asio::dispatch(impl_->service_, std::move(func)); } std::wstring device::version() const { return impl_->version(); } }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/util/device.h000066400000000000000000000043351341175263200225230ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include namespace caspar { namespace accelerator { namespace ogl { class device final : public std::enable_shared_from_this { public: device(); ~device(); device(const device&) = delete; device& operator=(const device&) = delete; std::shared_ptr create_texture(int width, int height, int stride); array create_array(int size); std::future> copy_async(const array& source, int width, int height, int stride); std::future> copy_async(const std::shared_ptr& source); template auto dispatch_async(Func&& func) { typedef decltype(func()) result_type; typedef std::packaged_task task_type; auto task = std::make_shared(std::forward(func)); auto future = task->get_future(); dispatch([=] { (*task)(); }); return future; } template auto dispatch_sync(Func&& func) { return dispatch_async(std::forward(func)).get(); } std::wstring version() const; private: void dispatch(std::function func); struct impl; std::shared_ptr impl_; }; }}} // namespace caspar::accelerator::oglserver-2.2.0-stable/src/accelerator/ogl/util/shader.cpp000066400000000000000000000134201341175263200230600ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "shader.h" #include #include #include namespace caspar { namespace accelerator { namespace ogl { struct shader::impl : boost::noncopyable { GLuint program_; std::unordered_map uniform_locations_; std::unordered_map attrib_locations_; public: impl(const std::string& vertex_source_str, const std::string& fragment_source_str) : program_(0) { GLint success; const char* vertex_source = vertex_source_str.c_str(); auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL)); GL(glCompileShaderARB(vertex_shader)); GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); if (success == GL_FALSE) { char info[2048]; GL(glGetInfoLogARB(vertex_shader, sizeof(info), 0, info)); GL(glDeleteObjectARB(vertex_shader)); std::stringstream str; str << "Failed to compile vertex shader:" << std::endl << info << std::endl; CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(str.str())); } const char* fragment_source = fragment_source_str.c_str(); auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL)); GL(glCompileShaderARB(fragmemt_shader)); GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success)); if (success == GL_FALSE) { char info[2048]; GL(glGetInfoLogARB(fragmemt_shader, sizeof(info), 0, info)); GL(glDeleteObjectARB(fragmemt_shader)); std::stringstream str; str << "Failed to compile fragment shader:" << std::endl << info << std::endl; CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(str.str())); } program_ = glCreateProgramObjectARB(); GL(glAttachObjectARB(program_, vertex_shader)); GL(glAttachObjectARB(program_, fragmemt_shader)); GL(glLinkProgramARB(program_)); GL(glDeleteObjectARB(vertex_shader)); GL(glDeleteObjectARB(fragmemt_shader)); GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success)); if (success == GL_FALSE) { char info[2048]; GL(glGetInfoLogARB(program_, sizeof(info), 0, info)); GL(glDeleteObjectARB(program_)); std::stringstream str; str << "Failed to link shader program:" << std::endl << info << std::endl; CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(str.str())); } GL(glUseProgramObjectARB(program_)); } ~impl() { glDeleteProgram(program_); } GLint get_uniform_location(const char* name) { auto it = uniform_locations_.find(name); if (it == uniform_locations_.end()) it = uniform_locations_.insert(std::make_pair(name, glGetUniformLocation(program_, name))).first; return it->second; } GLint get_attrib_location(const char* name) { auto it = attrib_locations_.find(name); if (it == attrib_locations_.end()) it = attrib_locations_.insert(std::make_pair(name, glGetAttribLocation(program_, name))).first; return it->second; } void set(const std::string& name, bool value) { set(name, value ? 1 : 0); } void set(const std::string& name, int value) { GL(glUniform1i(get_uniform_location(name.c_str()), value)); } void set(const std::string& name, float value) { GL(glUniform1f(get_uniform_location(name.c_str()), value)); } void set(const std::string& name, double value0, double value1) { GL(glUniform2f(get_uniform_location(name.c_str()), static_cast(value0), static_cast(value1))); } void set(const std::string& name, double value) { GL(glUniform1f(get_uniform_location(name.c_str()), static_cast(value))); } void use() { GL(glUseProgramObjectARB(program_)); } }; shader::shader(const std::string& vertex_source_str, const std::string& fragment_source_str) : impl_(new impl(vertex_source_str, fragment_source_str)) { } shader::~shader() {} void shader::set(const std::string& name, bool value) { impl_->set(name, value); } void shader::set(const std::string& name, int value) { impl_->set(name, value); } void shader::set(const std::string& name, float value) { impl_->set(name, value); } void shader::set(const std::string& name, double value0, double value1) { impl_->set(name, value0, value1); } void shader::set(const std::string& name, double value) { impl_->set(name, value); } GLint shader::get_attrib_location(const char* name) { return impl_->get_attrib_location(name); } int shader::id() const { return impl_->program_; } void shader::use() const { impl_->use(); } }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/util/shader.h000066400000000000000000000035111341175263200225250ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include namespace caspar { namespace accelerator { namespace ogl { class shader final { shader(const shader&); shader& operator=(const shader&); public: shader(const std::string& vertex_source_str, const std::string& fragment_source_str); ~shader(); void set(const std::string& name, bool value); void set(const std::string& name, int value); void set(const std::string& name, float value); void set(const std::string& name, double value0, double value1); void set(const std::string& name, double value); GLint get_attrib_location(const char* name); template typename std::enable_if::value, void>::type set(const std::string& name, E value) { set(name, static_cast::type>(value)); } void use() const; int id() const; private: struct impl; std::unique_ptr impl_; }; }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/util/texture.cpp000066400000000000000000000076071341175263200233240ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "texture.h" #include "buffer.h" #include #include namespace caspar { namespace accelerator { namespace ogl { static GLenum FORMAT[] = {0, GL_RED, GL_RG, GL_BGR, GL_BGRA}; static GLenum INTERNAL_FORMAT[] = {0, GL_R8, GL_RG8, GL_RGB8, GL_RGBA8}; static GLenum TYPE[] = {0, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT_8_8_8_8_REV}; struct texture::impl : boost::noncopyable { GLuint id_ = 0; GLsizei width_ = 0; GLsizei height_ = 0; GLsizei stride_ = 0; GLsizei size_ = 0; public: impl(int width, int height, int stride) : width_(width) , height_(height) , stride_(stride) , size_(width * height * stride) { GL(glCreateTextures(GL_TEXTURE_2D, 1, &id_)); GL(glTextureParameteri(id_, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); GL(glTextureParameteri(id_, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); GL(glTextureParameteri(id_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); GL(glTextureParameteri(id_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); GL(glTextureStorage2D(id_, 1, INTERNAL_FORMAT[stride_], width_, height_)); } ~impl() { glDeleteTextures(1, &id_); } void bind() { GL(glBindTexture(GL_TEXTURE_2D, id_)); } void bind(int index) { GL(glActiveTexture(GL_TEXTURE0 + index)); bind(); } void unbind() { GL(glBindTexture(GL_TEXTURE_2D, 0)); } void attach() { GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, id_, 0)); } void clear() { GL(glClearTexImage(id_, 0, FORMAT[stride_], TYPE[stride_], nullptr)); } void copy_from(buffer& src) { src.bind(); if (width_ % 16 > 0) { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); } else { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); } GL(glTextureSubImage2D(id_, 0, 0, 0, width_, height_, FORMAT[stride_], TYPE[stride_], nullptr)); src.unbind(); } void copy_to(buffer& dst) { dst.bind(); GL(glGetTextureImage(id_, 0, FORMAT[stride_], TYPE[stride_], size_, nullptr)); dst.unbind(); } }; texture::texture(int width, int height, int stride) : impl_(new impl(width, height, stride)) { } texture::texture(texture&& other) : impl_(std::move(other.impl_)) { } texture::~texture() {} texture& texture::operator=(texture&& other) { impl_ = std::move(other.impl_); return *this; } void texture::bind(int index) { impl_->bind(index); } void texture::unbind() { impl_->unbind(); } void texture::attach() { impl_->attach(); } void texture::clear() { impl_->clear(); } void texture::copy_from(buffer& source) { impl_->copy_from(source); } void texture::copy_to(buffer& dest) { impl_->copy_to(dest); } int texture::width() const { return impl_->width_; } int texture::height() const { return impl_->height_; } int texture::stride() const { return impl_->stride_; } int texture::size() const { return impl_->width_ * impl_->height_ * impl_->stride_; } int texture::id() const { return impl_->id_; } }}} // namespace caspar::accelerator::ogl server-2.2.0-stable/src/accelerator/ogl/util/texture.h000066400000000000000000000030311341175263200227540ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { namespace accelerator { namespace ogl { class texture final { public: texture(int width, int height, int stride); texture(const texture&) = delete; texture(texture&& other); ~texture(); texture& operator=(const texture&) = delete; texture& operator =(texture&& other); void copy_from(class buffer& source); void copy_to(class buffer& dest); void attach(); void clear(); void bind(int index); void unbind(); int width() const; int height() const; int stride() const; int size() const; int id() const; private: struct impl; std::unique_ptr impl_; }; }}} // namespace caspar::accelerator::oglserver-2.2.0-stable/src/accelerator/packages.config000066400000000000000000000006711341175263200223210ustar00rootroot00000000000000 server-2.2.0-stable/src/common/000077500000000000000000000000001341175263200163545ustar00rootroot00000000000000server-2.2.0-stable/src/common/CMakeLists.txt000066400000000000000000000026551341175263200211240ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (common) set(SOURCES diagnostics/graph.cpp gl/gl_check.cpp base64.cpp env.cpp filesystem.cpp log.cpp stdafx.cpp tweener.cpp utf.cpp ) if (MSVC) set(OS_SPECIFIC_SOURCES compiler/vs/disable_silly_warnings.h os/windows/filesystem.cpp os/windows/prec_timer.cpp os/windows/thread.cpp os/windows/windows.h ) else () set(OS_SPECIFIC_SOURCES os/linux/filesystem.cpp os/linux/prec_timer.cpp os/linux/thread.cpp ) endif () set(HEADERS diagnostics/graph.h gl/gl_check.h os/filesystem.h os/thread.h array.h assert.h base64.h endian.h enum_class.h env.h executor.h except.h filesystem.h forward.h future.h log.h memory.h memshfl.h param.h prec_timer.h ptree.h scope_exit.h stdafx.h timer.h tweener.h utf.h ) add_library(common ${SOURCES} ${HEADERS} ${OS_SPECIFIC_SOURCES}) add_precompiled_header(common stdafx.h FORCEINCLUDE) configure_file("${PROJECT_SOURCE_DIR}/packages.config" "${CMAKE_CURRENT_BINARY_DIR}/packages.config") include_directories(..) include_directories(${BOOST_INCLUDE_PATH}) include_directories(${TBB_INCLUDE_PATH}) include_directories(${GLEW_INCLUDE_PATH}) source_group(sources ./*) source_group(sources\\gl gl/*) source_group(sources\\diagnostics diagnostics/*) source_group(sources\\compiler\\vs compiler/vs/*) source_group(sources\\os\\windows os/windows/*) source_group(sources\\os os/*) server-2.2.0-stable/src/common/array.h000066400000000000000000000104641341175263200176500ustar00rootroot00000000000000#pragma once #include #include #include #include #include namespace caspar { template class array final { template friend class array; public: typedef T* iterator; typedef const T* const_iterator; array() = default; explicit array(std::size_t size) : size_(size) { if (size_ > 0) { auto storage = std::shared_ptr(std::malloc(size), std::free); ptr_ = reinterpret_cast(storage.get()); std::memset(ptr_, 0, size_); storage_ = std::make_shared(std::move(storage)); } } array(std::vector other) { auto storage = std::make_shared>(std::move(other)); ptr_ = storage->data(); size_ = storage->size(); storage_ = std::make_shared(std::move(storage)); } template explicit array(T* ptr, std::size_t size, S&& storage) : ptr_(ptr) , size_(size) , storage_(std::make_shared(std::forward(storage))) { } array(const array&) = delete; array(array&& other) : ptr_(other.ptr_) , size_(other.size_) , storage_(std::move(other.storage_)) { other.ptr_ = nullptr; other.size_ = 0; } array& operator=(const array&) = delete; array& operator=(array&& other) { ptr_ = std::move(other.ptr_); size_ = std::move(other.size_); storage_ = std::move(other.storage_); return *this; } T* begin() const { return ptr_; } T* data() const { return ptr_; } T* end() const { return ptr_ + size_; } std::size_t size() const { return size_; } explicit operator bool() const { return size_ > 0; }; template S* storage() const { return boost::any_cast(storage_.get()); } private: T* ptr_ = nullptr; std::size_t size_ = 0; std::shared_ptr storage_; }; template class array final { public: typedef const T* iterator; typedef const T* const_iterator; array() = default; array(std::size_t size) : size_(size) { if (size_ > 0) { auto storage = std::shared_ptr(std::malloc(size), std::free); ptr_ = reinterpret_cast(storage.get()); std::memset(ptr_, 0, size_); storage_ = std::make_shared(storage); } } array(const std::vector& other) { auto storage = std::make_shared>(std::move(other)); ptr_ = storage->data(); size_ = storage->size(); storage_ = std::make_shared(std::move(storage)); } template explicit array(const T* ptr, std::size_t size, S&& storage) : ptr_(ptr) , size_(size) , storage_(std::make_shared(std::forward(storage))) { } array(const array& other) : ptr_(other.ptr_) , size_(other.size_) , storage_(other.storage_) { } array(array&& other) : ptr_(other.ptr_) , size_(other.size_) , storage_(other.storage_) { other.ptr_ = nullptr; other.size_ = 0; other.storage_ = nullptr; } array& operator=(const array& other) { ptr_ = other.ptr_; size_ = other.size_; storage_ = other.storage_; return *this; } const T* begin() const { return ptr_; } const T* data() const { return ptr_; } const T* end() const { return ptr_ + size_; } std::size_t size() const { return size_; } explicit operator bool() const { return size_ > 0; } template S* storage() const { return boost::any_cast(storage_.get()); } private: const T* ptr_ = nullptr; std::size_t size_ = 0; std::shared_ptr storage_; }; } // namespace caspar namespace std { template void swap(caspar::array& lhs, caspar::array& rhs) { lhs.swap(rhs); } } // namespace std server-2.2.0-stable/src/common/assert.h000066400000000000000000000054221341175263200200310ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "except.h" #include "log.h" #ifdef _MSC_VER #define _CASPAR_DBG_BREAK _CrtDbgBreak() #else #define _CASPAR_DBG_BREAK #endif #define CASPAR_VERIFY_EXPR_STR(str) #str #define CASPAR_VERIFY(expr) \ do { \ if (!(expr)) { \ CASPAR_LOG(warning) << "Assertion Failed: " << CASPAR_VERIFY_EXPR_STR(expr) << " " \ << "file:" << __FILE__ << " " \ << "line:" << __LINE__ << " "; \ _CASPAR_DBG_BREAK; \ } \ } while (0); #define CASPAR_ENSURE(expr) \ do { \ if (!(expr)) { \ CASPAR_THROW_EXCEPTION(programming_error() \ << msg_info(std::string("Assertion Failed: ") + CASPAR_VERIFY_EXPR_STR(expr))); \ } \ } while (0); #ifdef _DEBUG #define CASPAR_ASSERT(expr) CASPAR_VERIFY(expr) #else #define CASPAR_ASSERT(expr) #endif server-2.2.0-stable/src/common/base64.cpp000066400000000000000000000106771341175263200201570ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #include "base64.h" #include #include #include #include #include #include #include #include #include #include #include "except.h" namespace caspar { std::string to_base64(const char* data, size_t length) { using namespace boost::archive::iterators; // From http://www.webbiscuit.co.uk/2012/04/02/base64-encoder-and-boost/ typedef insert_linebreaks< // insert line breaks every 76 characters base64_from_binary< // convert binary values to base64 characters transform_width< // retrieve 6 bit integers from a sequence of 8 bit bytes const unsigned char*, 6, 8>>, 76> base64_iterator; // compose all the above operations in to a new iterator std::vector bytes; bytes.resize(length); std::memcpy(bytes.data(), data, length); int padding = 0; while (bytes.size() % 3 != 0) { ++padding; bytes.push_back(0x00); } std::string result(base64_iterator(bytes.data()), base64_iterator(bytes.data() + length)); result.insert(result.end(), padding, '='); return std::move(result); } std::vector from_base64(const std::string& data) { // The boost base64 iterator will over-iterate the string if not a multiple // of 4, so we have to short circuit before. auto length = std::count_if(data.begin(), data.end(), [](char c) { return !std::isspace(static_cast(c)); }); if (length % 4 != 0) CASPAR_THROW_EXCEPTION(user_error() << msg_info("The length of a base64 sequence must be a multiple of 4")); int padding = 0; std::string zero_padding; // binary_from_base64 does not support padding characters so we have to append base64 0 -> 'A' and then remove it // after decoding if (data.length() >= 2) { if (data[data.length() - 1] == '=') { ++padding; zero_padding += 'A'; } if (data[data.length() - 2] == '=') { ++padding; zero_padding += 'A'; } } if (padding > 0) { auto concatenated = boost::join(data | boost::adaptors::sliced(0, data.length() - padding), boost::make_iterator_range(zero_padding.cbegin(), zero_padding.cend())); // From https://svn.boost.org/trac/boost/ticket/5624 typedef boost::archive::iterators::transform_width< boost::archive::iterators::binary_from_base64< boost::archive::iterators::remove_whitespace>, 8, 6> base64_iterator; std::vector result(base64_iterator(concatenated.begin()), base64_iterator(concatenated.end())); result.resize(result.size() - padding); return std::move(result); } else { // From https://svn.boost.org/trac/boost/ticket/5624 typedef boost::archive::iterators::transform_width< boost::archive::iterators::binary_from_base64< boost::archive::iterators::remove_whitespace>, 8, 6> base64_iterator; std::vector result(base64_iterator(data.begin()), base64_iterator(data.end())); return std::move(result); } } } // namespace caspar server-2.2.0-stable/src/common/base64.h000066400000000000000000000020241341175263200176070ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include #include namespace caspar { std::string to_base64(const char* data, size_t length); std::vector from_base64(const std::string& data); } // namespace casparserver-2.2.0-stable/src/common/compiler/000077500000000000000000000000001341175263200201665ustar00rootroot00000000000000server-2.2.0-stable/src/common/compiler/vs/000077500000000000000000000000001341175263200206165ustar00rootroot00000000000000server-2.2.0-stable/src/common/compiler/vs/disable_silly_warnings.h000066400000000000000000000042561341175263200255250ustar00rootroot00000000000000/* * copyright (c) 2010 Sveriges Television AB * * This file is part of CasparCG. * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * */ #pragma once #if defined(_MSC_VER) #pragma warning(disable : 4100) // unreferenced formal parameter #pragma warning(disable : 4127) // conditional expression is constant #pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored #pragma warning(disable : 4355) // 'this' : used in base member initializer list #pragma warning(disable : 4482) // nonstandard extension used: enum 'enum' used in qualified name #pragma warning(disable : 4503) // decorated name length exceeded, name was truncated #pragma warning(disable : 4512) // assignment operator could not be generated #pragma warning(disable : 4702) // unreachable code #pragma warning(disable : 4714) // marked as __forceinline not inlined #pragma warning(disable : 4505) // unreferenced local function has been #pragma warning(disable : 4481) // nonstandard extension used: override specifier 'override' #pragma warning(disable : 4996) // function call with parameters that may be unsafe #pragma warning( \ disable : 4334) // '<<': result of 32 - bit shift implicitly converted to 64 bits(was 64 - bit shift intended ?) #if (_MSC_VER > 1800 && _MSC_FULL_VER >= 190023506) #pragma warning(disable : 4592) // symbol will be dynamically initialized (implementation limitation). Bug in // VS2015 14.0.24720.00 Update 1 #endif #endif server-2.2.0-stable/src/common/diagnostics/000077500000000000000000000000001341175263200206635ustar00rootroot00000000000000server-2.2.0-stable/src/common/diagnostics/graph.cpp000066400000000000000000000073041341175263200224740ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "graph.h" #include #include namespace caspar { namespace diagnostics { int color(float r, float g, float b, float a) { int code = 0; code |= static_cast(r * 255.0f + 0.5f) << 24; code |= static_cast(g * 255.0f + 0.5f) << 16; code |= static_cast(b * 255.0f + 0.5f) << 8; code |= static_cast(a * 255.0f + 0.5f) << 0; return code; } std::tuple color(int code) { float r = static_cast((code >> 24) & 255) / 255.0f; float g = static_cast((code >> 16) & 255) / 255.0f; float b = static_cast((code >> 8) & 255) / 255.0f; float a = static_cast((code >> 0) & 255) / 255.0f; return std::make_tuple(r, g, b, a); } typedef std::vector sink_factories_t; static std::mutex g_sink_factories_mutex; static sink_factories_t g_sink_factories; std::vector> create_sinks() { std::lock_guard lock(g_sink_factories_mutex); std::vector> result; for (auto sink : g_sink_factories) { result.push_back(sink()); } return result; } struct graph::impl { std::vector> sinks_ = create_sinks(); public: impl() {} void activate() { for (auto& sink : sinks_) sink->activate(); } void set_text(const std::wstring& value) { for (auto& sink : sinks_) sink->set_text(value); } void set_value(const std::string& name, double value) { for (auto& sink : sinks_) sink->set_value(name, value); } void set_tag(tag_severity severity, const std::string& name) { for (auto& sink : sinks_) sink->set_tag(severity, name); } void set_color(const std::string& name, int color) { for (auto& sink : sinks_) sink->set_color(name, color); } void auto_reset() { for (auto& sink : sinks_) sink->auto_reset(); } private: impl(impl&); impl& operator=(impl&); }; graph::graph() : impl_(new impl) { } void graph::set_text(const std::wstring& value) { impl_->set_text(value); } void graph::set_value(const std::string& name, double value) { impl_->set_value(name, value); } void graph::set_color(const std::string& name, int color) { impl_->set_color(name, color); } void graph::set_tag(tag_severity severity, const std::string& name) { impl_->set_tag(severity, name); } void graph::auto_reset() { impl_->auto_reset(); } void register_graph(const spl::shared_ptr& graph) { graph->impl_->activate(); } namespace spi { void register_sink_factory(sink_factory_t factory) { std::lock_guard lock(g_sink_factories_mutex); g_sink_factories.push_back(std::move(factory)); } } // namespace spi }} // namespace caspar::diagnosticsserver-2.2.0-stable/src/common/diagnostics/graph.h000066400000000000000000000046731341175263200221470ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "../memory.h" #include #include #include #include namespace caspar { namespace diagnostics { int color(float r, float g, float b, float a = 1.0f); std::tuple color(int code); enum class tag_severity { WARNING, INFO, SILENT, }; class graph : boost::noncopyable { friend void register_graph(const spl::shared_ptr& graph); public: graph(); void set_text(const std::wstring& value); void set_value(const std::string& name, double value); void set_color(const std::string& name, int color); void set_tag(tag_severity severity, const std::string& name); void auto_reset(); private: struct impl; std::shared_ptr impl_; }; void register_graph(const spl::shared_ptr& graph); namespace spi { class graph_sink : boost::noncopyable { public: virtual ~graph_sink() {} virtual void activate() = 0; virtual void set_text(const std::wstring& value) = 0; virtual void set_value(const std::string& name, double value) = 0; virtual void set_color(const std::string& name, int color) = 0; virtual void set_tag(tag_severity severity, const std::string& name) = 0; virtual void auto_reset() = 0; }; typedef std::function()> sink_factory_t; void register_sink_factory(sink_factory_t factory); } // namespace spi }} // namespace caspar::diagnosticsserver-2.2.0-stable/src/common/endian.h000066400000000000000000000042031341175263200177620ustar00rootroot00000000000000/* * Copyright 2013 Sveriges Television AB http://casparcg.com/ * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #ifdef _MSC_VER #include #endif namespace caspar { template typename std::enable_if::type swap_byte_order(const T& value) { return value; } template typename std::enable_if::type swap_byte_order(const T& value) { #ifdef _MSC_VER auto swapped = _byteswap_ushort(reinterpret_cast(value)); #elif __GNUC__ auto swapped = __builtin_bswap16(value); #endif return reinterpret_cast(swapped); } template typename std::enable_if::type swap_byte_order(const T& value) { #ifdef _MSC_VER auto swapped = _byteswap_ulong(reinterpret_cast(value)); #elif __GNUC__ auto swapped = __builtin_bswap32(value); #endif return reinterpret_cast(swapped); } template typename std::enable_if::type swap_byte_order(const T& value) { #ifdef _MSC_VER auto swapped = _byteswap_uint64(reinterpret_cast(value)); #elif __GNUC__ auto swapped = __builtin_bswap64(value); #endif return reinterpret_cast(swapped); } } // namespace caspar server-2.2.0-stable/src/common/enum_class.h000066400000000000000000000107401341175263200206600ustar00rootroot00000000000000#pragma once #include #include #define ENUM_ENABLE_BITWISE(enum_class) \ static enum_class operator&(enum_class lhs, enum_class rhs) \ { \ return static_cast(static_cast::type>(lhs) & \ static_cast::type>(rhs)); \ }; \ static enum_class& operator&=(enum_class& lhs, enum_class rhs) \ { \ lhs = lhs & rhs; \ return lhs; \ }; \ static enum_class operator|(enum_class lhs, enum_class rhs) \ { \ return static_cast(static_cast::type>(lhs) | \ static_cast::type>(rhs)); \ }; \ static enum_class& operator|=(enum_class& lhs, enum_class rhs) \ { \ lhs = lhs | rhs; \ return lhs; \ }; \ static enum_class operator^(enum_class lhs, enum_class rhs) \ { \ return static_cast(static_cast::type>(lhs) ^ \ static_cast::type>(rhs)); \ }; \ static enum_class& operator^=(enum_class& lhs, enum_class rhs) \ { \ lhs = lhs ^ rhs; \ return lhs; \ }; \ static enum_class operator~(enum_class e) \ { \ return static_cast(~static_cast::type>(e)); \ }; namespace caspar { template const std::vector& enum_constants() { typedef typename std::underlying_type::type integer; static auto res = [] { std::vector result; for (auto n = 0; n < static_cast(E::count); ++n) { result.push_back(static_cast(n)); } return result; }(); return res; } } // namespace caspar server-2.2.0-stable/src/common/env.cpp000066400000000000000000000131671341175263200176600ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "env.h" #include "version.h" #include "except.h" #include "log.h" #include "os/filesystem.h" #include "string.h" #include #include #include #include #include #include #include #include namespace caspar { namespace env { std::wstring initial; std::wstring media; std::wstring log; std::wstring ftemplate; std::wstring data; std::wstring font; boost::property_tree::wptree pt; void check_is_configured() { if (pt.empty()) CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(L"Enviroment properties has not been configured")); } std::wstring clean_path(std::wstring path) { boost::replace_all(path, L"\\\\", L"/"); boost::replace_all(path, L"\\", L"/"); return path; } std::wstring ensure_trailing_slash(std::wstring folder) { if (folder.at(folder.length() - 1) != L'/') folder.append(L"/"); return folder; } std::wstring resolve_or_create(const std::wstring& folder) { auto found_path = find_case_insensitive(folder); if (found_path) return *found_path; else { boost::system::error_code ec; boost::filesystem::create_directories(folder, ec); if (ec) CASPAR_THROW_EXCEPTION(user_error() << msg_info("Failed to create directory " + u8(folder) + " (" + ec.message() + ")")); return folder; } } void ensure_writable(const std::wstring& folder) { static const std::wstring CREATE_FILE_TEST = L"casparcg_test_writable.empty"; boost::system::error_code ec; boost::filesystem::path test_file(folder + L"/" + CREATE_FILE_TEST); boost::filesystem::ofstream out(folder + L"/" + CREATE_FILE_TEST); if (out.fail()) { boost::filesystem::remove(test_file, ec); CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Directory " + folder + L" is not writable.")); } out.close(); boost::filesystem::remove(test_file, ec); } void configure(const std::wstring& filename) { try { initial = clean_path(boost::filesystem::initial_path().wstring()); boost::filesystem::wifstream file(initial + L"/" + filename); boost::property_tree::read_xml(file, pt, boost::property_tree::xml_parser::trim_whitespace | boost::property_tree::xml_parser::no_comments); auto paths = pt.get_child(L"configuration.paths"); media = clean_path(paths.get(L"media-path", initial + L"/media/")); log = clean_path(paths.get(L"log-path", initial + L"/log/")); ftemplate = clean_path(boost::filesystem::complete(paths.get(L"template-path", initial + L"/template/")).wstring()); data = clean_path(paths.get(L"data-path", initial + L"/data/")); font = clean_path(paths.get(L"font-path", initial + L"/font/")); } catch (...) { CASPAR_LOG(error) << L" ### Invalid configuration file. ###"; throw; } media = ensure_trailing_slash(resolve_or_create(media)); log = ensure_trailing_slash(resolve_or_create(log)); ftemplate = ensure_trailing_slash(resolve_or_create(ftemplate)); data = ensure_trailing_slash(resolve_or_create(data)); font = ensure_trailing_slash(resolve_or_create(font)); ensure_writable(log); ensure_writable(ftemplate); ensure_writable(data); } const std::wstring& initial_folder() { check_is_configured(); return initial; } const std::wstring& media_folder() { check_is_configured(); return media; } const std::wstring& log_folder() { check_is_configured(); return log; } const std::wstring& template_folder() { check_is_configured(); return ftemplate; } const std::wstring& data_folder() { check_is_configured(); return data; } const std::wstring& font_folder() { check_is_configured(); return font; } #define QUOTE(str) #str #define EXPAND_AND_QUOTE(str) QUOTE(str) const std::wstring& version() { static std::wstring ver = u16(EXPAND_AND_QUOTE(CASPAR_GEN) "." EXPAND_AND_QUOTE(CASPAR_MAJOR) "." EXPAND_AND_QUOTE( CASPAR_MINOR) " " CASPAR_HASH " " CASPAR_TAG); return ver; } const boost::property_tree::wptree& properties() { check_is_configured(); return pt; } void log_configuration_warnings() { if (pt.empty()) return; if (pt.get_optional(L"configuration.paths.thumbnails-path")) CASPAR_LOG(warning) << L"Element thumbnails-path in casparcg.config has been deprecated. Use thumbnail-path instead."; } }} // namespace caspar::env server-2.2.0-stable/src/common/env.h000066400000000000000000000024701341175263200173200ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include namespace caspar { namespace env { void configure(const std::wstring& filename); const std::wstring& initial_folder(); const std::wstring& media_folder(); const std::wstring& log_folder(); const std::wstring& template_folder(); const std::wstring& data_folder(); const std::wstring& font_folder(); const std::wstring& version(); const boost::property_tree::wptree& properties(); void log_configuration_warnings(); }} // namespace caspar::env server-2.2.0-stable/src/common/except.h000066400000000000000000000104141341175263200200150ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "utf.h" #include "log.h" #include #include #include #define NOMINMAX #define WIN32_LEAN_AND_MEAN #include namespace caspar { typedef boost::error_info arg_name_info_t; typedef boost::error_info arg_value_info_t; typedef boost::error_info msg_info_t; typedef boost::error_info error_info_t; typedef boost::error_info source_info_t; typedef boost::error_info file_name_info_t; typedef boost::error_info stacktrace_info_t; template inline arg_name_info_t arg_name_info(const T& str) { return arg_name_info_t(u8(str)); } template inline arg_value_info_t arg_value_info(const T& str) { return arg_value_info_t(u8(str)); } template inline msg_info_t msg_info(const T& str) { return msg_info_t(u8(str)); } template inline error_info_t error_info(const T& str) { return error_info_t(u8(str)); } template inline source_info_t source_info(const T& str) { return source_info_t(u8(str)); } template inline file_name_info_t file_name_info(const T& str) { return file_name_info_t(u8(str)); } inline stacktrace_info_t stacktrace_info() { return stacktrace_info_t(boost::stacktrace::stacktrace()); } typedef boost::error_info line_info; typedef boost::error_info nested_exception; struct caspar_exception : virtual boost::exception , virtual std::exception { caspar_exception() {} const char* what() const throw() override { return boost::diagnostic_information_what(*this); } }; struct io_error : virtual caspar_exception { }; struct directory_not_found : virtual io_error { }; struct file_not_found : virtual io_error { }; struct file_read_error : virtual io_error { }; struct file_write_error : virtual io_error { }; struct invalid_argument : virtual caspar_exception { }; struct null_argument : virtual invalid_argument { }; struct out_of_range : virtual invalid_argument { }; struct programming_error : virtual caspar_exception { }; struct bad_alloc : virtual caspar_exception { }; struct invalid_operation : virtual caspar_exception { }; struct operation_failed : virtual caspar_exception { }; struct timed_out : virtual caspar_exception { }; struct not_implemented : virtual caspar_exception { }; struct user_error : virtual caspar_exception { }; struct expected_user_error : virtual user_error { }; struct not_supported : virtual user_error { }; #define CASPAR_THROW_EXCEPTION(x) \ ::boost::throw_exception(::boost::enable_error_info(x) \ << ::boost::throw_function(BOOST_THROW_EXCEPTION_CURRENT_FUNCTION) \ << ::boost::throw_file(__FILE__) << ::boost::throw_line((int)__LINE__) \ << stacktrace_info()) } // namespace caspar server-2.2.0-stable/src/common/executor.h000066400000000000000000000071451341175263200203720ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "except.h" #include "log.h" #include "os/thread.h" #include #include #include #include namespace caspar { class executor final { executor(const executor&); executor& operator=(const executor&); typedef std::function task_t; typedef tbb::concurrent_bounded_queue queue_t; std::wstring name_; std::atomic is_running_{true}; queue_t queue_; std::thread thread_; public: executor(const std::wstring& name) : name_(name) , thread_(std::thread([this] { run(); })) { } ~executor() { stop(); thread_.join(); } template auto begin_invoke(Func&& func) { if (!is_running_) { CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info("executor not running.")); } typedef decltype(func()) result_type; auto task = std::make_shared>(std::forward(func)); queue_.push([=]() mutable { (*task)(); }); return task->get_future(); } template auto invoke(Func&& func) { if (is_current()) { // Avoids potential deadlock. return func(); } return begin_invoke(std::forward(func)).get(); } template typename std::enable_if())>::value, void>::type invoke(Func&& func) { if (is_current()) { // Avoids potential deadlock. func(); } begin_invoke(std::forward(func)).wait(); } void yield() {} void set_capacity(queue_t::size_type capacity) { queue_.set_capacity(capacity); } queue_t::size_type capacity() const { return queue_.capacity(); } void clear() { queue_.clear(); } void stop() { if (!is_running_) { return; } is_running_ = false; queue_.push(nullptr); } void wait() { invoke([] {}); } queue_t::size_type size() const { return queue_.size(); } bool is_running() const { return is_running_; } bool is_current() const { return std::this_thread::get_id() == thread_.get_id(); } const std::wstring& name() const { return name_; } private: void run() { set_thread_name(name_); task_t task; while (is_running_) { try { queue_.pop(task); do { if (!task) { return; } task(); } while (queue_.try_pop(task)); } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } } } }; } // namespace casparserver-2.2.0-stable/src/common/filesystem.cpp000066400000000000000000000037401341175263200212500ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #include "filesystem.h" #include "except.h" #include #include namespace caspar { boost::filesystem::path get_relative(const boost::filesystem::path& file, const boost::filesystem::path& relative_to) { auto result = file.filename(); auto current_path = file; if (boost::filesystem::equivalent(current_path, relative_to)) return L""; while (true) { current_path = current_path.parent_path(); if (boost::filesystem::equivalent(current_path, relative_to)) break; if (current_path.empty()) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("File " + file.string() + " not relative to folder " + relative_to.string())); result = current_path.filename() / result; } return result; } boost::filesystem::path get_relative_without_extension(const boost::filesystem::path& file, const boost::filesystem::path& relative_to) { return get_relative(file.parent_path() / file.stem(), relative_to); } } // namespace caspar server-2.2.0-stable/src/common/filesystem.h000066400000000000000000000023301341175263200207070ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include #include namespace caspar { boost::filesystem::path get_relative(const boost::filesystem::path& file, const boost::filesystem::path& relative_to); boost::filesystem::path get_relative_without_extension(const boost::filesystem::path& file, const boost::filesystem::path& relative_to); } // namespace caspar server-2.2.0-stable/src/common/forward.h000066400000000000000000000022001341175263200201630ustar00rootroot00000000000000#pragma once #define FORWARD0(expr) expr #define FORWARD1(a1, expr) \ namespace a1 { \ expr; \ } #define FORWARD2(a1, a2, expr) \ namespace a1 { namespace a2 { \ expr; \ }} #define FORWARD3(a1, a2, a3, expr) \ namespace a1 { namespace a2 { namespace a3 { \ expr; \ }}} server-2.2.0-stable/src/common/future.h000066400000000000000000000013271341175263200200420ustar00rootroot00000000000000#pragma once #include #include #include #include namespace caspar { template auto flatten(F&& f) { return std::async(std::launch::deferred, [f = std::forward(f)]() mutable { return f.get().get(); }); } template bool is_ready(const F& future) { return future.wait_for(std::chrono::seconds(0)) == std::future_status::ready; } template auto make_ready_future(T&& value) { std::promise::type> p; p.set_value(std::forward(value)); return p.get_future(); } static std::future make_ready_future() { std::promise p; p.set_value(); return p.get_future(); } } // namespace casparserver-2.2.0-stable/src/common/gl/000077500000000000000000000000001341175263200167565ustar00rootroot00000000000000server-2.2.0-stable/src/common/gl/gl_check.cpp000066400000000000000000000073071341175263200212300ustar00rootroot00000000000000/////////////////////////// // // SFML - Simple and Fast Multimedia Library // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it freely, // subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; // you must not claim that you wrote the original software. // If you use this software in a product, an acknowledgment // in the product documentation would be appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, // and must not be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source distribution. // /////////////////////////// #include "gl_check.h" #include "../except.h" #include "../log.h" #include namespace caspar { namespace gl { void SMFL_GLCheckError(const std::string&, const char* func, const char* file, unsigned int line) { // Get the last error GLenum LastErrorCode = GL_NO_ERROR; for (GLenum ErrorCode = glGetError(); ErrorCode != GL_NO_ERROR; ErrorCode = glGetError()) { std::string str(reinterpret_cast(glewGetErrorString(ErrorCode))); CASPAR_LOG(error) << "OpenGL Error: " << ErrorCode << L" " << str; LastErrorCode = ErrorCode; } if (LastErrorCode != GL_NO_ERROR) { // Decode the error code switch (LastErrorCode) { case GL_INVALID_ENUM: CASPAR_THROW_EXCEPTION(ogl_invalid_enum() << msg_info( "an unacceptable value has been specified for an enumerated argument") << error_info("GL_INVALID_ENUM")); case GL_INVALID_VALUE: CASPAR_THROW_EXCEPTION(ogl_invalid_value() << msg_info("a numeric argument is out of range") << error_info("GL_INVALID_VALUE")); case GL_INVALID_OPERATION: CASPAR_THROW_EXCEPTION(ogl_invalid_operation() << msg_info("the specified operation is not allowed in the current state") << error_info("GL_INVALID_OPERATION")); case GL_STACK_OVERFLOW: CASPAR_THROW_EXCEPTION(ogl_stack_overflow() << msg_info("this command would cause a stack overflow") << error_info("GL_STACK_OVERFLOW")); case GL_STACK_UNDERFLOW: CASPAR_THROW_EXCEPTION(ogl_stack_underflow() << msg_info("this command would cause a stack underflow") << error_info("GL_STACK_UNDERFLOW")); case GL_OUT_OF_MEMORY: CASPAR_THROW_EXCEPTION(ogl_out_of_memory() << msg_info("there is not enough memory left to execute the command") << error_info("GL_OUT_OF_MEMORY")); case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: CASPAR_THROW_EXCEPTION( ogl_invalid_framebuffer_operation_ext() << msg_info("the object bound to FRAMEBUFFER_BINDING_EXT is not \"framebuffer complete\"") << error_info("GL_INVALID_FRAMEBUFFER_OPERATION_EXT")); } } } }} // namespace caspar::gl server-2.2.0-stable/src/common/gl/gl_check.h000066400000000000000000000065641341175263200207010ustar00rootroot00000000000000/////////////////////////// // // SFML - Simple and Fast Multimedia Library // Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com) // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it freely, // subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; // you must not claim that you wrote the original software. // If you use this software in a product, an acknowledgment // in the product documentation would be appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, // and must not be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source distribution. // /////////////////////////// #pragma once #include "../except.h" namespace caspar { namespace gl { struct ogl_exception : virtual caspar_exception { }; struct ogl_invalid_enum : virtual ogl_exception { }; struct ogl_invalid_value : virtual ogl_exception { }; struct ogl_invalid_operation : virtual ogl_exception { }; struct ogl_stack_overflow : virtual ogl_exception { }; struct ogl_stack_underflow : virtual ogl_exception { }; struct ogl_out_of_memory : virtual ogl_exception { }; struct ogl_invalid_framebuffer_operation_ext : virtual ogl_exception { }; void SMFL_GLCheckError(const std::string& expr, const char* func, const char* file, unsigned int line); //#ifdef _DEBUG #define CASPAR_GL_EXPR_STR(expr) #expr #define GL(expr) \ if (false) { \ } else { \ (expr); \ caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FUNCTION__, __FILE__, __LINE__); \ } // TODO: decltype version does not play well with gcc #define GL2(expr) \ [&]() { \ auto ret = (expr); \ caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FUNCTION__, __FILE__, __LINE__); \ return ret; \ }() /*#define GL2(expr) \ [&]() -> decltype(expr) \ { \ auto ret = (expr); \ caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__); \ return ret; \ }()*/ //#define GL2(expr) [&]() -> decltype(expr) { auto ret = (expr); caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), //__FILE__, __LINE__); return ret; }() #else #define GL(expr) expr #endif }} // namespace caspar::gl server-2.2.0-stable/src/common/log.cpp000066400000000000000000000204701341175263200176440ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "log.h" #include "except.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace logging = boost::log; namespace src = boost::log::sources; namespace sinks = boost::log::sinks; namespace keywords = boost::log::keywords; namespace caspar { namespace log { std::string current_exception_diagnostic_information() { { auto e = boost::current_exception_cast(); if (e) { return std::string("[char *] = ") + *e + "\n"; } } { auto e = boost::current_exception_cast(); if (e) { return std::string("[char *] = ") + u8(*e) + "\n"; } } { auto e = boost::current_exception_cast(); if (e) { return std::string("[char *] = ") + *e + "\n"; } } { auto e = boost::current_exception_cast(); if (e) { return std::string("[char *] = ") + u8(*e) + "\n"; } } return boost::current_exception_diagnostic_information(true); } template void append_timestamp(Stream& stream, boost::posix_time::ptime timestamp) { auto date = timestamp.date(); auto time = timestamp.time_of_day(); auto milliseconds = time.fractional_seconds() / 1000; // microseconds to milliseconds std::wstringstream buffer; buffer << std::setfill(L'0') << L"[" << std::setw(4) << date.year() << L"-" << std::setw(2) << date.month().as_number() << "-" << std::setw(2) << date.day().as_number() << L" " << std::setw(2) << time.hours() << L":" << std::setw(2) << time.minutes() << L":" << std::setw(2) << time.seconds() << L"." << std::setw(3) << milliseconds << L"] "; stream << buffer.str(); } class column_writer { std::atomic column_width_; public: column_writer(int initial_width = 0) { column_width_ = initial_width; } template void write(Stream& out, const Val& value) { std::wstring to_string = boost::lexical_cast(value); int length = static_cast(to_string.size()); int read_width; while (true) { read_width = column_width_; if (read_width >= length || column_width_.compare_exchange_strong(length, read_width)) { break; } } read_width = column_width_; out << L"[" << to_string << L"] "; for (int n = 0; n < read_width - length; ++n) { out << L" "; } } }; template void my_formatter(bool print_all_characters, const boost::log::record_view& rec, Stream& strm) { static column_writer thread_id_column; static column_writer severity_column(7); namespace expr = boost::log::expressions; std::wstringstream pre_message_stream; append_timestamp(pre_message_stream, boost::log::extract("TimestampMillis", rec).get()); // thread_id_column.write(pre_message_stream, boost::log::extract("NativeThreadId", rec)); severity_column.write(pre_message_stream, boost::log::extract("Severity", rec)); auto pre_message = pre_message_stream.str(); strm << pre_message; auto line_break_replacement = L"\n" + pre_message; if (print_all_characters) { strm << boost::replace_all_copy(rec[expr::message].get(), "\n", line_break_replacement); } else { strm << boost::replace_all_copy( replace_nonprintable_copy(rec[expr::message].get(), L'?'), L"\n", line_break_replacement); } } void add_file_sink(const std::wstring& file) { typedef boost::log::sinks::synchronous_sink file_sink_type; try { if (!boost::filesystem::is_directory(boost::filesystem::path(file).parent_path())) { CASPAR_THROW_EXCEPTION(directory_not_found()); } auto file_sink = boost::make_shared( boost::log::keywords::file_name = (file + L"_%Y-%m-%d.log"), boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0), boost::log::keywords::auto_flush = true, boost::log::keywords::open_mode = std::ios::app); file_sink->set_formatter(boost::bind(&my_formatter, true, _1, _2)); boost::log::core::get()->add_sink(file_sink); } catch (...) { std::wcerr << L"Failed to Setup File Logging Sink" << std::endl << std::endl; } } void add_cout_sink() { boost::log::add_common_attributes(); // boost::log::core::get()->add_global_attribute("NativeThreadId", // boost::log::attributes::make_function(&std::this_thread::get_id)); boost::log::core::get()->add_global_attribute("TimestampMillis", boost::log::attributes::make_function([] { return boost::posix_time::microsec_clock::local_time(); })); typedef sinks::asynchronous_sink stream_sink_type; auto stream_backend = boost::make_shared(); stream_backend->add_stream(boost::shared_ptr(&std::wcout, boost::null_deleter())); stream_backend->auto_flush(true); auto stream_sink = boost::make_shared(stream_backend); stream_sink->set_formatter(boost::bind(&my_formatter, false, _1, _2)); logging::core::get()->add_sink(stream_sink); } std::wstring current_log_level; bool set_log_level(const std::wstring& lvl) { if (boost::iequals(lvl, L"trace")) logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::trace); else if (boost::iequals(lvl, L"debug")) logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::debug); else if (boost::iequals(lvl, L"info")) logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::info); else if (boost::iequals(lvl, L"warning")) logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::warning); else if (boost::iequals(lvl, L"error")) logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::error); else if (boost::iequals(lvl, L"fatal")) logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::fatal); else return false; current_log_level = lvl; return true; } std::wstring& get_log_level() { return current_log_level; } }} // namespace caspar::logserver-2.2.0-stable/src/common/log.h000066400000000000000000000065431341175263200173160ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "utf.h" #include #include #include #include #include #define NOMINMAX #define WIN32_LEAN_AND_MEAN #include #include namespace caspar { namespace log { template inline void replace_nonprintable(std::basic_string, std::allocator>& str, T with) { std::locale loc; std::replace_if( str.begin(), str.end(), [&](T c) -> bool { return (!std::isprint(c, loc) && c != '\r' && c != '\n') || c > static_cast(127); }, with); } template inline std::basic_string replace_nonprintable_copy(std::basic_string, std::allocator> str, T with) { replace_nonprintable(str, with); return str; } std::string current_exception_diagnostic_information(); typedef boost::log::sources::wseverity_logger_mt caspar_logger; BOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(logger, caspar_logger) #define CASPAR_LOG(lvl) BOOST_LOG_SEV(::caspar::log::logger::get(), boost::log::trivial::severity_level::lvl) void add_file_sink(const std::wstring& file); void add_cout_sink(); bool set_log_level(const std::wstring& lvl); std::wstring& get_log_level(); inline std::wstring get_stack_trace() { auto bt = boost::stacktrace::stacktrace(); if (bt) { return caspar::u16(boost::stacktrace::detail::to_string(&bt.as_vector()[0], bt.size())); } return L""; } #define CASPAR_LOG_CURRENT_EXCEPTION() \ try { \ CASPAR_LOG(error) << L"Exception: " << caspar::u16(::caspar::log::current_exception_diagnostic_information()) \ << L"\r\n" \ << caspar::log::get_stack_trace(); \ } catch (...) { \ } #define CASPAR_LOG_CURRENT_CALL_STACK() // TODO (fix) }} // namespace caspar::log server-2.2.0-stable/src/common/memory.h000066400000000000000000000571061341175263200200460ustar00rootroot00000000000000/* * Copyright (c) 2011,2018 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNu General public: License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include namespace caspar { namespace spl { // unique_ptr /** * A wrapper around std::unique_ptr ensuring that the pointer is never null * except in the case of a moved from instance. * * The default constructor will point the wrapped pointer to a default * contructed instance of T. * * Use the make_unique overloads for perfectly forwarding the contructor * arguments of T and creating a unique_ptr to the created T instance. */ template > class unique_ptr { unique_ptr(const unique_ptr&); unique_ptr& operator=(const unique_ptr&); template friend class unique_ptr; template friend class shared_ptr; public: typedef T element_type; typedef D deleter_type; unique_ptr() : p_(new T()) { } template unique_ptr(unique_ptr&& p, typename std::enable_if::value, void*>::type = 0) : p_(p.p_.release(), p.p_.get_deleter()) { } template explicit unique_ptr(std::unique_ptr&& p, typename std::enable_if::value, void*>::type = 0) : p_(std::move(p)) { if (!p_) throw std::invalid_argument("p"); } template explicit unique_ptr(T2* p, typename std::enable_if::value, void*>::type = 0) : p_(p) { if (!p_) throw std::invalid_argument("p"); } template explicit unique_ptr(T2* p, typename std::remove_reference::type&& d, typename std::enable_if::value, void*>::type = 0) : p_(p, d) { if (!p_) throw std::invalid_argument("p"); } unique_ptr& operator=(unique_ptr&& other) { other.swap(*this); return *this; } T& operator*() const { return *p_.get(); } T* operator->() const { return p_.get(); } T* get() const { return p_.get(); } void swap(unique_ptr& other) { p_.swap(other.p_); } D& get_deleter() { return p_.get_deleter(); } private: T* release() { return p_.release(); } std::unique_ptr p_; }; template bool operator==(const unique_ptr& a, const unique_ptr& b) { return a.get() == b.get(); } template bool operator==(const std::unique_ptr& a, const unique_ptr& b) { return a.get() == b.get(); } template bool operator==(const unique_ptr& a, const std::unique_ptr& b) { return a.get() == b.get(); } template bool operator!=(const unique_ptr& a, const unique_ptr& b) { return a.get() != b.get(); } template bool operator!=(const std::unique_ptr& a, const unique_ptr& b) { return a.get() != b.get(); } template bool operator!=(const unique_ptr& a, const std::unique_ptr& b) { return a.get() != b.get(); } template bool operator<(const unique_ptr& a, const unique_ptr& b) { return a.get() < b.get(); } template bool operator<(const std::unique_ptr& a, const unique_ptr& b) { return a.get() < b.get(); } template bool operator<(const unique_ptr& a, const std::unique_ptr& b) { return a.get() < b.get(); } template bool operator>(const unique_ptr& a, const unique_ptr& b) { return a.get() > b.get(); } template bool operator>(const std::unique_ptr& a, const unique_ptr& b) { return a.get() > b.get(); } template bool operator>(const unique_ptr& a, const std::unique_ptr& b) { return a.get() > b.get(); } template bool operator>=(const unique_ptr& a, const unique_ptr& b) { return a.get() >= b.get(); } template bool operator>=(const std::unique_ptr& a, const unique_ptr& b) { return a.get() >= b.get(); } template bool operator>=(const unique_ptr& a, const std::unique_ptr& b) { return a.get() >= b.get(); } template bool operator<=(const unique_ptr& a, const unique_ptr& b) { return a.get() <= b.get(); } template bool operator<=(const std::unique_ptr& a, const unique_ptr& b) { return a.get() <= b.get(); } template bool operator<=(const unique_ptr& a, const std::unique_ptr& b) { return a.get() <= b.get(); } template std::basic_ostream& operator<<(std::basic_ostream& oT2t, const unique_ptr& p) { return oT2t << p.get(); } template void swap(unique_ptr& a, unique_ptr& b) { a.swap(b); } template T* get_pointer(unique_ptr const& p) { return p.get(); } template unique_ptr static_pointer_cast(const unique_ptr& p) { return unique_ptr(std::static_pointer_cast(std::unique_ptr(p))); } template unique_ptr const_pointer_cast(const unique_ptr& p) { return unique_ptr(std::const_pointer_cast(std::unique_ptr(p))); } template unique_ptr dynamic_pointer_cast(const unique_ptr& p) { auto temp = std::dynamic_pointer_cast(std::unique_ptr(p)); if (!temp) throw std::bad_cast(); return unique_ptr(std::move(temp)); } template unique_ptr make_unique_ptr(std::unique_ptr&& ptr) { return unique_ptr(std::move(ptr)); } template unique_ptr make_unique() { return unique_ptr(new T()); } template unique_ptr make_unique(P0&& p0) { return unique_ptr(new T(std::forward(p0))); } template unique_ptr make_unique(P0&& p0, P1&& p1) { return unique_ptr(new T(std::forward(p0), std::forward(p1))); } template unique_ptr make_unique(P0&& p0, P1&& p1, P2&& p2) { return unique_ptr(new T(std::forward(p0), std::forward(p1), std::forward(p2))); } template unique_ptr make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3) { return unique_ptr(new T(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3))); } template unique_ptr make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4) { return unique_ptr(new T( std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4))); } template unique_ptr make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5) { return unique_ptr(new T(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5))); } // shared_ptr /** * A wrapper around std::shared_ptr ensuring that it never points to a null * pointer except in the case of a moved from instance. * * A default constructed shared_ptr will point to a default constructed T. * * Use the make_shared overloads for perfect forwarding of the constructor * arguments of T which will return a shared_ptr pointing to the constructed T. */ template class shared_ptr { template friend class shared_ptr; public: typedef T element_type; shared_ptr(); // will constrT2ct new T object T2sing make_shared() template shared_ptr(shared_ptr other, typename std::enable_if::value, void*>::type = 0) : p_(std::move(other.p_)) { } template explicit shared_ptr(std::unique_ptr&& p, typename std::enable_if::value, void*>::type = 0) : p_(std::move(p)) { if (!p_) throw std::invalid_argument("p"); } template explicit shared_ptr(spl::unique_ptr&& p, typename std::enable_if::value, void*>::type = 0) : p_(p.release(), p.get_deleter()) { if (!p_) throw std::invalid_argument("p"); } template explicit shared_ptr(std::shared_ptr p, typename std::enable_if::value, void*>::type = 0) : p_(std::move(p)) { if (!p_) throw std::invalid_argument("p"); } template explicit shared_ptr(T2* p, typename std::enable_if::value, void*>::type = 0) : p_(p) { if (!p_) throw std::invalid_argument("p"); } template explicit shared_ptr(T2* p, D d, typename std::enable_if::value, void*>::type = 0) : p_(p, d) { if (!p_) throw std::invalid_argument("p"); } shared_ptr operator=(shared_ptr other) { other.swap(*this); return *this; } T& operator*() const { return *p_.get(); } T* operator->() const { return p_.get(); } T* get() const { return p_.get(); } bool unique() const { return p_.unique(); } long use_count() const { return p_.use_count(); } void swap(shared_ptr& other) { p_.swap(other.p_); } template operator std::shared_ptr() const { return p_; } template operator std::weak_ptr() const { return std::weak_ptr(p_); } template bool owner_before(const shared_ptr& ptr) { return p_.owner_before(ptr.p_); } template bool owner_before(const std::shared_ptr& ptr) { return p_.owner_before(ptr); } private: std::shared_ptr p_; }; template D* get_deleter(shared_ptr const& ptr) { return ptr.get_deleter(); } template bool operator==(const shared_ptr& a, const shared_ptr& b) { return a.get() == b.get(); } template bool operator==(const std::shared_ptr& a, const shared_ptr& b) { return a.get() == b.get(); } template bool operator==(const shared_ptr& a, const std::shared_ptr& b) { return a.get() == b.get(); } template bool operator!=(const shared_ptr& a, const shared_ptr& b) { return a.get() != b.get(); } template bool operator!=(const std::shared_ptr& a, const shared_ptr& b) { return a.get() != b.get(); } template bool operator!=(const shared_ptr& a, const std::shared_ptr& b) { return a.get() != b.get(); } template bool operator<(const shared_ptr& a, const shared_ptr& b) { return a.get() < b.get(); } template bool operator<(const std::shared_ptr& a, const shared_ptr& b) { return a.get() < b.get(); } template bool operator<(const shared_ptr& a, const std::shared_ptr& b) { return a.get() < b.get(); } template bool operator>(const shared_ptr& a, const shared_ptr& b) { return a.get() > b.get(); } template bool operator>(const std::shared_ptr& a, const shared_ptr& b) { return a.get() > b.get(); } template bool operator>(const shared_ptr& a, const std::shared_ptr& b) { return a.get() > b.get(); } template bool operator>=(const shared_ptr& a, const shared_ptr& b) { return a.get() >= b.get(); } template bool operator>=(const std::shared_ptr& a, const shared_ptr& b) { return a.get() >= b.get(); } template bool operator>=(const shared_ptr& a, const std::shared_ptr& b) { return a.get() >= b.get(); } template bool operator<=(const shared_ptr& a, const shared_ptr& b) { return a.get() <= b.get(); } template bool operator<=(const std::shared_ptr& a, const shared_ptr& b) { return a.get() <= b.get(); } template bool operator<=(const shared_ptr& a, const std::shared_ptr& b) { return a.get() <= b.get(); } template std::basic_ostream& operator<<(std::basic_ostream& oT2t, const shared_ptr& p) { return oT2t << p.get(); } template void swap(shared_ptr& a, shared_ptr& b) { a.swap(b); } template T* get_pointer(shared_ptr const& p) { return p.get(); } template shared_ptr static_pointer_cast(const shared_ptr& p) { return shared_ptr(std::static_pointer_cast(std::shared_ptr(p))); } template shared_ptr const_pointer_cast(const shared_ptr& p) { return shared_ptr(std::const_pointer_cast(std::shared_ptr(p))); } template shared_ptr dynamic_pointer_cast(const shared_ptr& p) { auto temp = std::dynamic_pointer_cast(std::shared_ptr(p)); if (!temp) throw std::bad_cast(); return shared_ptr(std::move(temp)); } // // enable_safe_this // // A shared_ptr version of enable_shared_from_this. // So that an object may get shared_ptr objects to itself. // template class enable_shared_from_this : public std::enable_shared_from_this { public: shared_ptr shared_from_this() { return shared_ptr(std::enable_shared_from_this::shared_from_this()); } shared_ptr shared_from_this() const { return shared_ptr(std::enable_shared_from_this::shared_from_this()); } protected: enable_shared_from_this() {} enable_shared_from_this(const enable_shared_from_this&) {} enable_shared_from_this& operator=(const enable_shared_from_this&) { return *this; } ~enable_shared_from_this() {} }; // // make_shared // // shared_ptr eqT2ivalents to make_shared // template shared_ptr make_shared_ptr(std::unique_ptr&& ptr) { return shared_ptr(std::move(ptr)); } template shared_ptr make_shared_ptr(std::shared_ptr ptr) { return shared_ptr(std::move(ptr)); } template shared_ptr make_shared() { return shared_ptr(std::make_shared()); } template shared_ptr make_shared(P0&& p0) { return shared_ptr(std::make_shared(std::forward(p0))); } template shared_ptr make_shared(P0&& p0, P1&& p1) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3) { return shared_ptr( std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4) { return shared_ptr(std::make_shared( std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5), std::forward(p6))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5), std::forward(p6), std::forward(p7))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5), std::forward(p6), std::forward(p7), std::forward(p8))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8, P9&& p9) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5), std::forward(p6), std::forward(p7), std::forward(p8), std::forward(p9))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8, P9&& p9, P10&& p10) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5), std::forward(p6), std::forward(p7), std::forward(p8), std::forward(p9), std::forward(p10))); } template shared_ptr make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8, P9&& p9, P10&& p10, P11&& p11) { return shared_ptr(std::make_shared(std::forward(p0), std::forward(p1), std::forward(p2), std::forward(p3), std::forward(p4), std::forward(p5), std::forward(p6), std::forward(p7), std::forward(p8), std::forward(p9), std::forward(p10), std::forward(p11))); } template shared_ptr::shared_ptr() : p_(make_shared()) { } }} // namespace caspar::spl server-2.2.0-stable/src/common/memshfl.h000066400000000000000000000034601341175263200201630ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #ifdef _MSC_VER #include #else #include #endif namespace caspar { static void* aligned_memshfl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4) { __m128i* dest128 = reinterpret_cast<__m128i*>(dest); const __m128i* source128 = reinterpret_cast(source); count /= 16; // 128 bit __m128i xmm0, xmm1, xmm2, xmm3; const __m128i mask128 = _mm_set_epi32(m1, m2, m3, m4); for (size_t n = 0; n < count / 4; ++n) { xmm0 = _mm_load_si128(source128++); xmm1 = _mm_load_si128(source128++); xmm2 = _mm_load_si128(source128++); xmm3 = _mm_load_si128(source128++); _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm0, mask128)); _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm1, mask128)); _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm2, mask128)); _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm3, mask128)); } return dest; } } // namespace caspar server-2.2.0-stable/src/common/os/000077500000000000000000000000001341175263200167755ustar00rootroot00000000000000server-2.2.0-stable/src/common/os/filesystem.h000066400000000000000000000017401341175263200213340ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include #include namespace caspar { boost::optional find_case_insensitive(const std::wstring& case_insensitive); } server-2.2.0-stable/src/common/os/linux/000077500000000000000000000000001341175263200201345ustar00rootroot00000000000000server-2.2.0-stable/src/common/os/linux/filesystem.cpp000066400000000000000000000036001341175263200230230ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #include "../../stdafx.h" #include "../filesystem.h" #include #include #include using namespace boost::filesystem; namespace caspar { boost::optional find_case_insensitive(const std::wstring& case_insensitive) { path p(case_insensitive); if (exists(p)) return case_insensitive; p = absolute(p); path result; for (auto part : p) { auto concatenated = result / part; if (exists(concatenated)) { result = concatenated; } else { bool found = false; for (auto it = directory_iterator(absolute(result)); it != directory_iterator(); ++it) { auto leaf = it->path().leaf(); if (boost::algorithm::iequals(part.wstring(), leaf.wstring())) { result = result / leaf; found = true; break; } } if (!found) return boost::none; } } return result.wstring(); } } // namespace caspar server-2.2.0-stable/src/common/os/linux/prec_timer.cpp000066400000000000000000000037541341175263200230020ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../../stdafx.h" #include "../../prec_timer.h" #include #include using namespace std::chrono; namespace caspar { prec_timer::prec_timer() : time_(0) { } void prec_timer::tick_nanos(int64_t ticks_to_wait) { auto t = duration_cast(high_resolution_clock::now().time_since_epoch()).count(); if (time_ != 0) { bool done = 0; do { auto ticks_passed = t - time_; auto ticks_left = ticks_to_wait - ticks_passed; if (t < time_) // time wrap done = 1; if (ticks_passed >= ticks_to_wait) done = 1; if (!done) { timespec spec; if (ticks_left > 2000000) { spec.tv_sec = ticks_left / 1000000000; spec.tv_nsec = 1000000; } else { spec.tv_sec = 0; spec.tv_nsec = ticks_left / 100; } nanosleep(&spec, nullptr); } t = duration_cast(high_resolution_clock::now().time_since_epoch()).count(); } while (!done); } time_ = t; } } // namespace caspar server-2.2.0-stable/src/common/os/linux/thread.cpp000066400000000000000000000002741341175263200221120ustar00rootroot00000000000000#include "../thread.h" #include "../../utf.h" namespace caspar { void set_thread_name(std::wstring name) { pthread_setname_np(pthread_self(), u8(name).c_str()); } } // namespace caspar server-2.2.0-stable/src/common/os/thread.h000066400000000000000000000001371341175263200204160ustar00rootroot00000000000000#pragma once #include namespace caspar { void set_thread_name(std::wstring name); }server-2.2.0-stable/src/common/os/windows/000077500000000000000000000000001341175263200204675ustar00rootroot00000000000000server-2.2.0-stable/src/common/os/windows/filesystem.cpp000066400000000000000000000022131341175263200233550ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #include "../../stdafx.h" #include "../filesystem.h" #include namespace caspar { boost::optional find_case_insensitive(const std::wstring& case_insensitive) { if (boost::filesystem::exists(case_insensitive)) return case_insensitive; else return boost::none; } } // namespace caspar server-2.2.0-stable/src/common/os/windows/prec_timer.cpp000066400000000000000000000044101341175263200233230ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../../stdafx.h" #include "../../prec_timer.h" #include #include "windows.h" using namespace std::chrono; namespace caspar { prec_timer::prec_timer() : time_(0) { } void prec_timer::tick_nanos(int64_t ticks_to_wait) { auto t = duration_cast(high_resolution_clock::now().time_since_epoch()).count(); if (time_ != 0) { bool done = 0; do { auto ticks_passed = t - time_; auto ticks_left = ticks_to_wait - ticks_passed; if (t < time_) // time wrap done = 1; if (ticks_passed >= ticks_to_wait) done = 1; if (!done) { // if > 0.002s left, do Sleep(1), which will actually sleep some // steady amount, probably 1-2 ms, // and do so in a nice way (cpu meter drops; laptop battery spared). // otherwise, do a few Sleep(0)'s, which just give up the timeslice, // but don't really save cpu or battery, but do pass a tiny // amount of time. if (ticks_left > 2000000) Sleep(1); else for (int i = 0; i < 10; ++i) Sleep(0); // causes thread to give up its timeslice } t = duration_cast(high_resolution_clock::now().time_since_epoch()).count(); } while (!done); } time_ = t; } } // namespace caspar server-2.2.0-stable/src/common/os/windows/thread.cpp000066400000000000000000000016471341175263200224520ustar00rootroot00000000000000#include "../thread.h" #include #include #include #include "../../utf.h" namespace caspar { typedef struct tagTHREADNAME_INFO { DWORD dwType; // must be 0x1000 LPCSTR szName; // pointer to name (in user addr space) DWORD dwThreadID; // thread ID (-1=caller thread) DWORD dwFlags; // reserved for future use, must be zero } THREADNAME_INFO; inline void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName) { THREADNAME_INFO info; { info.dwType = 0x1000; info.szName = szThreadName; info.dwThreadID = dwThreadID; info.dwFlags = 0; } __try { RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info); } __except (EXCEPTION_CONTINUE_EXECUTION) { } } void set_thread_name(std::wstring name) { SetThreadName(GetCurrentThreadId(), u8(name).c_str()); } } // namespace casparserver-2.2.0-stable/src/common/os/windows/windows.h000066400000000000000000000005571341175263200223410ustar00rootroot00000000000000#pragma once #undef _UNICODE #define _UNICODE #undef UNICODE #define UNICODE #undef NOMINMAX #define NOMINMAX #undef NOSERVICE #define NOSERVICE #undef NOMCX #define NOMCX #ifdef _MSC_VER #include #endif #ifndef _WIN32_WINNT #define _WIN32_WINNT _WIN32_WINNT_WIN7 #endif #undef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #include server-2.2.0-stable/src/common/packages.config000066400000000000000000000002051341175263200213160ustar00rootroot00000000000000 server-2.2.0-stable/src/common/param.h000066400000000000000000000054401341175263200176300ustar00rootroot00000000000000#pragma once #include "except.h" #include #include #include #include namespace caspar { class param_comparer { const std::wstring& lhs; public: explicit param_comparer(const std::wstring& p) : lhs(p) { } bool operator()(const std::wstring& rhs) { return boost::iequals(lhs, rhs); } }; template bool contains_param(const std::wstring& name, C&& params) { return std::find_if(params.begin(), params.end(), param_comparer(name)) != params.end(); } template bool get_and_consume_flag(const std::wstring& flag_param, C& params) { auto flag_it = std::find_if(params.begin(), params.end(), param_comparer(flag_param)); bool flag = false; if (flag_it != params.end()) { flag = true; params.erase(flag_it); } return flag; } template void replace_placeholders(const std::wstring& placeholder, const std::wstring& replacement, C&& params) { for (auto& param : params) boost::ireplace_all(param, placeholder, replacement); } static std::vector protocol_split(const std::wstring& s) { std::vector result; size_t pos; if ((pos = s.find(L"://")) != std::wstring::npos) { result.push_back(s.substr(0, pos)); result.push_back(s.substr(pos + 3)); } else { result.push_back(L""); result.push_back(s); } return result; } template typename std::enable_if::value, typename std::decay::type>::type get_param(const std::wstring& name, C&& params, T fail_value = T()) { auto it = std::find_if(std::begin(params), std::end(params), param_comparer(name)); if (it == params.end()) return fail_value; try { if (++it == params.end()) throw std::out_of_range(""); return boost::lexical_cast::type>(*it); } catch (...) { CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Failed to parse param " + name) << nested_exception(std::current_exception())); } } template std::wstring get_param(const std::wstring& name, C&& params, const std::wstring& fail_value = L"") { auto it = std::find_if(std::begin(params), std::end(params), param_comparer(name)); if (it == params.end()) return fail_value; try { if (++it == params.end()) throw std::out_of_range(""); return *it; } catch (...) { CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Failed to parse param " + name) << nested_exception(std::current_exception())); } } } // namespace caspar server-2.2.0-stable/src/common/prec_timer.h000066400000000000000000000023571341175263200206650ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { class prec_timer { public: prec_timer(); void tick(double interval) { tick_nanos(static_cast(interval * 1000000000.0)); } void tick_millis(int64_t interval) { tick_nanos(interval * 1000000); } // Author: Ryan M. Geiss // http://www.geisswerks.com/ryan/FAQS/timing.html void tick_nanos(int64_t interval); private: int64_t time_; }; } // namespace caspar server-2.2.0-stable/src/common/ptree.h000066400000000000000000000122741341175263200176520ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include "except.h" #include "memory.h" #include #include #include #include #include #include namespace caspar { struct ptree_exception : virtual user_error { }; static std::string to_xpath(std::string path) { path.insert(path.begin(), '/'); boost::replace_all(path, ".", "@"); boost::replace_all(path, ".", "/"); return path; } template T ptree_get(const Ptree& ptree, const typename Ptree::key_type& path) { try { return ptree.template get(path); } catch (boost::property_tree::ptree_bad_path&) { CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info("No such element: " + to_xpath(u8(path)))); } catch (const boost::property_tree::ptree_bad_data& e) { CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info(e.what())); } } template T ptree_get_value(const Ptree& ptree) { try { return ptree.template get_value(); } catch (const boost::property_tree::ptree_bad_data& e) { CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info(e.what())); } } template const Ptree& ptree_get_child(const Ptree& ptree, const typename Ptree::key_type& path) { try { return ptree.get_child(path); } catch (boost::property_tree::ptree_bad_path&) { CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info("No such element: " + to_xpath(u8(path)))); } } template class scope_aware_ptree_child_range { const Ptree& child_; typedef std::pair type; public: class scoped_const_iterator : public boost::iterator_facade { typename Ptree::const_iterator wrapped_; public: scoped_const_iterator(typename Ptree::const_iterator it) : wrapped_(std::move(it)) { } void increment() { ++wrapped_; } bool equal(const scoped_const_iterator& other) const { return wrapped_ == other.wrapped_; } const type& dereference() const { return *wrapped_; } }; typedef scoped_const_iterator iterator; typedef scoped_const_iterator const_iterator; scope_aware_ptree_child_range(const Ptree& parent, const typename Ptree::key_type& path) : child_(ptree_get_child(parent, path)) { } scoped_const_iterator begin() const { return scoped_const_iterator(child_.begin()); } scoped_const_iterator end() const { return scoped_const_iterator(child_.end()); } }; template struct iterate_children_tag { Key val; iterate_children_tag(Key val_) : val(std::move(val_)) { } }; typedef iterate_children_tag witerate_children; typedef iterate_children_tag iterate_children; template scope_aware_ptree_child_range operator|(const Ptree& ptree, iterate_children_tag path) { return scope_aware_ptree_child_range(ptree, path.val); } template struct basic_scoped_element_translator { mutable std::map by_name; typedef const std::pair& result_type; result_type operator()(result_type pair) const { return pair; } }; template struct element_context_iteration_tag { }; static element_context_iteration_tag welement_context_iteration; static element_context_iteration_tag element_context_iteration; template auto operator|(const Range& rng, element_context_iteration_tag tag) -> decltype(rng | boost::adaptors::transformed(basic_scoped_element_translator())) { return rng | boost::adaptors::transformed(basic_scoped_element_translator()); } template void ptree_verify_element_name(const std::pair& elem, const Str& expected) { if (elem.first != expected) CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info("Expected element named " + u8(expected) + ". Was " + u8(elem.first))); } } // namespace caspar server-2.2.0-stable/src/common/scope_exit.h000066400000000000000000000033371341175263200206750ustar00rootroot00000000000000#pragma once #include "except.h" #include namespace caspar { namespace detail { template class scope_exit { scope_exit(const scope_exit&); scope_exit& operator=(const scope_exit&); public: template explicit scope_exit(T2&& func) : func_(std::forward(func)) , valid_(true) { } scope_exit(scope_exit&& other) : func_(std::move(other.func_)) , valid_(std::move(other.valid_)) { other.valid_ = false; } scope_exit& operator=(scope_exit&& other) { func_ = std::move(other.func_); valid_ = std::move(other.valid_); other.valid_ = false; return *this; } ~scope_exit() { try { if (valid_) func_(); } catch (...) { if (!std::uncaught_exception()) #pragma warning(push) #pragma warning(disable : 4297) throw; #pragma warning(pop) else CASPAR_LOG_CURRENT_EXCEPTION(); } } private: T func_; bool valid_; }; class scope_exit_helper { }; template scope_exit::type> operator+(scope_exit_helper, T&& exitScope) { return scope_exit::type>(std::forward(exitScope)); } } // namespace detail #define _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line) name##line #define _CASPAR_EXIT_SCOPE_LINENAME(name, line) _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line) #define CASPAR_SCOPE_EXIT \ auto _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__) = ::caspar::detail::scope_exit_helper() + [&]() mutable } // namespace casparserver-2.2.0-stable/src/common/stdafx.cpp000066400000000000000000000014761341175263200203610ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "stdafx.h" server-2.2.0-stable/src/common/stdafx.h000066400000000000000000000065171341175263200200270ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include //#include //#include //#include //#include //#include //#include //#include //#include #include #include #include #include #include #include #include #include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include server-2.2.0-stable/src/common/timer.h000066400000000000000000000024561341175263200176540ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include namespace caspar { class timer { std::int_least64_t start_time_; public: timer() { start_time_ = now(); } void restart() { start_time_ = now(); } double elapsed() const { return static_cast(now() - start_time_) / 1000.0; } private: static std::int_least64_t now() { using namespace std::chrono; return duration_cast(high_resolution_clock::now().time_since_epoch()).count(); } }; } // namespace caspar server-2.2.0-stable/src/common/tweener.cpp000066400000000000000000000472111341175263200205360ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ // The following code is based on Tweener for actionscript, http://code.google.com/p/tweener/ // // Disclaimer for Robert Penner's Easing Equations license: // // TERMS OF USE - EASING EQUATIONS // // Open source under the BSD License. // // Copyright � 2001 Robert Penner // 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. // * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. #include "tweener.h" #include "except.h" #include #include #include #include #include #include #include #include namespace caspar { typedef std::function tweener_t; static const double PI = std::atan(1.0) * 4.0; static const double H_PI = std::atan(1.0) * 2.0; double ease_none(double t, double b, double c, double d, const std::vector& params) { return c * t / d + b; } double ease_in_quad(double t, double b, double c, double d, const std::vector& params) { return c * (t /= d) * t + b; } double ease_out_quad(double t, double b, double c, double d, const std::vector& params) { return -c * (t /= d) * (t - 2) + b; } double ease_in_out_quad(double t, double b, double c, double d, const std::vector& params) { if ((t /= d / 2) < 1) return c / 2 * t * t + b; return -c / 2 * ((--t) * (t - 2) - 1) + b; } double ease_out_in_quad(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_quad(t * 2, b, c / 2, d, params); return ease_in_quad((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_cubic(double t, double b, double c, double d, const std::vector& params) { return c * (t /= d) * t * t + b; } double ease_out_cubic(double t, double b, double c, double d, const std::vector& params) { return c * ((t = t / d - 1) * t * t + 1) + b; } double ease_in_out_cubic(double t, double b, double c, double d, const std::vector& params) { if ((t /= d / 2) < 1) return c / 2 * t * t * t + b; return c / 2 * ((t -= 2) * t * t + 2) + b; } double ease_out_in_cubic(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_cubic(t * 2, b, c / 2, d, params); return ease_in_cubic((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_quart(double t, double b, double c, double d, const std::vector& params) { return c * (t /= d) * t * t * t + b; } double ease_out_quart(double t, double b, double c, double d, const std::vector& params) { return -c * ((t = t / d - 1) * t * t * t - 1) + b; } double ease_in_out_quart(double t, double b, double c, double d, const std::vector& params) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b; return -c / 2 * ((t -= 2) * t * t * t - 2) + b; } double ease_out_in_quart(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_quart(t * 2, b, c / 2, d, params); return ease_in_quart((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_quint(double t, double b, double c, double d, const std::vector& params) { return c * (t /= d) * t * t * t * t + b; } double ease_out_quint(double t, double b, double c, double d, const std::vector& params) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b; } double ease_in_out_quint(double t, double b, double c, double d, const std::vector& params) { if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b; return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; } double ease_out_in_quint(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_quint(t * 2, b, c / 2, d, params); return ease_in_quint((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_sine(double t, double b, double c, double d, const std::vector& params) { return -c * std::cos(t / d * (PI / 2)) + c + b; } double ease_out_sine(double t, double b, double c, double d, const std::vector& params) { return c * std::sin(t / d * (PI / 2)) + b; } double ease_in_out_sine(double t, double b, double c, double d, const std::vector& params) { return -c / 2 * (std::cos(PI * t / d) - 1) + b; } double ease_out_in_sine(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_sine(t * 2, b, c / 2, d, params); return ease_in_sine((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_expo(double t, double b, double c, double d, const std::vector& params) { return (t == 0) ? b : c * std::pow(2, 10 * (t / d - 1)) + b - c * 0.001; } double ease_out_expo(double t, double b, double c, double d, const std::vector& params) { return (t == d) ? b + c : c * 1.001 * (-std::pow(2, -10 * t / d) + 1) + b; } double ease_in_out_expo(double t, double b, double c, double d, const std::vector& params) { if (t == 0) return b; if (t == d) return b + c; if ((t /= d / 2) < 1) return c / 2 * std::pow(2, 10 * (t - 1)) + b - c * 0.0005; return c / 2 * 1.0005 * (-std::pow(2, -10 * --t) + 2) + b; } double ease_out_in_expo(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_expo(t * 2, b, c / 2, d, params); return ease_in_expo((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_circ(double t, double b, double c, double d, const std::vector& params) { return -c * (std::sqrt(1 - (t /= d) * t) - 1) + b; } double ease_out_circ(double t, double b, double c, double d, const std::vector& params) { return c * std::sqrt(1 - (t = t / d - 1) * t) + b; } double ease_in_out_circ(double t, double b, double c, double d, const std::vector& params) { if ((t /= d / 2) < 1) return -c / 2 * (std::sqrt(1 - t * t) - 1) + b; return c / 2 * (std::sqrt(1 - (t -= 2) * t) + 1) + b; } double ease_out_in_circ(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_circ(t * 2, b, c / 2, d, params); return ease_in_circ((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_elastic(double t, double b, double c, double d, const std::vector& params) { if (t == 0) return b; if ((t /= d) == 1) return b + c; // var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period; // var s:Number; // var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude; double p = params.size() > 0 ? params[0] : d * 0.3; double s; double a = params.size() > 1 ? params[1] : 0.0; if (a == 0.0 || a < std::abs(c)) { a = c; s = p / 4; } else s = p / (2 * PI) * std::asin(c / a); return -(a * std::pow(2, 10 * (t -= 1)) * std::sin((t * d - s) * (2 * PI) / p)) + b; } double ease_out_elastic(double t, double b, double c, double d, const std::vector& params) { if (t == 0) return b; if ((t /= d) == 1) return b + c; // var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period; // var s:Number; // var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude; double p = params.size() > 0 ? params[0] : d * 0.3; double s; double a = params.size() > 1 ? params[1] : 0.0; if (a == 0.0 || a < std::abs(c)) { a = c; s = p / 4; } else s = p / (2 * PI) * std::asin(c / a); return (a * std::pow(2, -10 * t) * std::sin((t * d - s) * (2 * PI) / p) + c + b); } double ease_in_out_elastic(double t, double b, double c, double d, const std::vector& params) { if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; // var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*(.3*1.5) : p_params.period; // var s:Number; // var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude; double p = params.size() > 0 ? params[0] : d * 0.3 * 1.5; double s; double a = params.size() > 1 ? params[1] : 0.0; if (a == 0.0 || a < std::abs(c)) { a = c; s = p / 4; } else s = p / (2 * PI) * std::asin(c / a); if (t < 1) return -.5 * (a * std::pow(2, 10 * (t -= 1)) * std::sin((t * d - s) * (2 * PI) / p)) + b; return a * std::pow(2, -10 * (t -= 1)) * std::sin((t * d - s) * (2 * PI) / p) * .5 + c + b; } double ease_out_in_elastic(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_elastic(t * 2, b, c / 2, d, params); return ease_in_elastic((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_in_back(double t, double b, double c, double d, const std::vector& params) { // var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot; double s = params.size() > 0 ? params[0] : 1.70158; return c * (t /= d) * t * ((s + 1) * t - s) + b; } double ease_out_back(double t, double b, double c, double d, const std::vector& params) { // var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot; double s = params.size() > 0 ? params[0] : 1.70158; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; } double ease_in_out_back(double t, double b, double c, double d, const std::vector& params) { // var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot; double s = params.size() > 0 ? params[0] : 1.70158; if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; } double ease_out_int_back(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_back(t * 2, b, c / 2, d, params); return ease_in_back((t * 2) - d, b + c / 2, c / 2, d, params); } double ease_out_bounce(double t, double b, double c, double d, const std::vector& params) { if ((t /= d) < (1 / 2.75)) return c * (7.5625 * t * t) + b; else if (t < (2 / 2.75)) return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b; else if (t < (2.5 / 2.75)) return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b; else return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b; } double ease_in_bounce(double t, double b, double c, double d, const std::vector& params) { return c - ease_out_bounce(d - t, 0, c, d, params) + b; } double ease_in_out_bounce(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_in_bounce(t * 2, 0, c, d, params) * .5 + b; else return ease_out_bounce(t * 2 - d, 0, c, d, params) * .5 + c * .5 + b; } double ease_out_in_bounce(double t, double b, double c, double d, const std::vector& params) { if (t < d / 2) return ease_out_bounce(t * 2, b, c / 2, d, params); return ease_in_bounce((t * 2) - d, b + c / 2, c / 2, d, params); } typedef std::function&)> tween_t; const std::unordered_map& get_tweens() { static const std::unordered_map tweens = {{L"", ease_none}, {L"linear", ease_none}, {L"easenone", ease_none}, {L"easeinquad", ease_in_quad}, {L"easeoutquad", ease_out_quad}, {L"easeinoutquad", ease_in_out_quad}, {L"easeoutinquad", ease_out_in_quad}, {L"easeincubic", ease_in_cubic}, {L"easeoutcubic", ease_out_cubic}, {L"easeinoutcubic", ease_in_out_cubic}, {L"easeoutincubic", ease_out_in_cubic}, {L"easeinquart", ease_in_quart}, {L"easeoutquart", ease_out_quart}, {L"easeinoutquart", ease_in_out_quart}, {L"easeoutinquart", ease_out_in_quart}, {L"easeinquint", ease_in_quint}, {L"easeoutquint", ease_out_quint}, {L"easeinoutquint", ease_in_out_quint}, {L"easeoutinquint", ease_out_in_quint}, {L"easeinsine", ease_in_sine}, {L"easeoutsine", ease_out_sine}, {L"easeinoutsine", ease_in_out_sine}, {L"easeoutinsine", ease_out_in_sine}, {L"easeinexpo", ease_in_expo}, {L"easeoutexpo", ease_out_expo}, {L"easeinoutexpo", ease_in_out_expo}, {L"easeoutinexpo", ease_out_in_expo}, {L"easeincirc", ease_in_circ}, {L"easeoutcirc", ease_out_circ}, {L"easeinoutcirc", ease_in_out_circ}, {L"easeoutincirc", ease_out_in_circ}, {L"easeinelastic", ease_in_elastic}, {L"easeoutelastic", ease_out_elastic}, {L"easeinoutelastic", ease_in_out_elastic}, {L"easeoutinelastic", ease_out_in_elastic}, {L"easeinback", ease_in_back}, {L"easeoutback", ease_out_back}, {L"easeinoutback", ease_in_out_back}, {L"easeoutintback", ease_out_int_back}, {L"easeoutbounce", ease_out_bounce}, {L"easeinbounce", ease_in_bounce}, {L"easeinoutbounce", ease_in_out_bounce}, {L"easeoutinbounce", ease_out_in_bounce}}; return tweens; } tweener_t get_tweener(std::wstring name) { std::transform(name.begin(), name.end(), name.begin(), std::towlower); if (name == L"linear") return [](double t, double b, double c, double d) { return ease_none(t, b, c, d, std::vector()); }; std::vector params; static const boost::wregex expr( LR"((?\w*)(:(?\d+\.?\d?))?(:(?\d+\.?\d?))?)"); // boost::regex has no repeated captures? boost::wsmatch what; if (boost::regex_match(name, what, expr)) { name = what["NAME"].str(); if (what["V0"].matched) params.push_back(boost::lexical_cast(what["V0"].str())); if (what["V1"].matched) params.push_back(boost::lexical_cast(what["V1"].str())); } auto it = get_tweens().find(name); if (it == get_tweens().end()) CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Could not find tween " + name)); auto tween = it->second; return [=](double t, double b, double c, double d) { return tween(t, b, c, d, params); }; }; tweener::tweener(const std::wstring& name) : func_(get_tweener(name)) , name_(name) { } double tweener::operator()(double t, double b, double c, double d) const { return func_(t, b, c, d); } bool tweener::operator==(const tweener& other) const { return name_ == other.name_; } bool tweener::operator!=(const tweener& other) const { return !(*this == other); } const std::vector& tweener::names() { static auto result = [] { std::vector tweens; for (auto& tween : get_tweens()) tweens.push_back(tween.first); return tweens; }(); return result; } } // namespace caspar server-2.2.0-stable/src/common/tweener.h000066400000000000000000000054201341175263200201770ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include namespace caspar { /** * A tweener can be used for creating any kind of (image position, image fade * in/out, audio volume etc) transition, by invoking it for each temporal * timepoint when a tweened value is needed. * * For audio the smoothest transitions will be generated by using the samplerate * as temporal resolution, but using the video frame/field rate is probably fine * most of the times and much less time consuming. */ class tweener { public: /** * Constructor. * * @param name The name of the tween function to use. */ tweener(const std::wstring& name = L"linear"); /** * @return The possible tween function names. Some of them may also support * additional parameters appended to the name. */ static const std::vector& names(); /** * Calculate a tweened value given a timepoint within the total duration * and the starting value and the destination delta value. * * Usually b, c and d remains constant during a transition, while t changes * for each temporal tweened value. * * @param t The timepoint within the total duration (0 <= n <= d). * @param b The starting value. * @param c The destination value delta from the starting value * (absolute destination value - b). * @param d The total duration (when t = d, the destination value should * have been reached). * * @return The tweened value for the given timepoint. Can sometimes be less * than b or greater than b + c for some tweener functions. */ double operator()(double t, double b, double c, double d) const; bool operator==(const tweener& other) const; bool operator!=(const tweener& other) const; private: std::function func_; std::wstring name_; }; } // namespace caspar server-2.2.0-stable/src/common/utf.cpp000066400000000000000000000024531341175263200176620ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "utf.h" #pragma warning(push, 1) #include namespace caspar { std::wstring u16(const std::string& str) { return boost::locale::conv::utf_to_utf(str); // std::wstring(str.begin(), str.end()); } std::wstring u16(const std::wstring& str) { return str; } std::string u8(const std::wstring& str) { return boost::locale::conv::utf_to_utf(str); // std::string(str.begin(), str.end()); } std::string u8(const std::string& str) { return str; } } // namespace casparserver-2.2.0-stable/src/common/utf.h000066400000000000000000000020351341175263200173230ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { std::wstring u16(const std::string& str); std::wstring u16(const std::wstring& str); std::string u8(const std::wstring& str); std::string u8(const std::string& str); } // namespace casparserver-2.2.0-stable/src/core/000077500000000000000000000000001341175263200160145ustar00rootroot00000000000000server-2.2.0-stable/src/core/CMakeLists.txt000066400000000000000000000047551341175263200205670ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (core) set(SOURCES consumer/frame_consumer.cpp consumer/output.cpp diagnostics/call_context.cpp diagnostics/osd_graph.cpp frame/draw_frame.cpp frame/frame.cpp frame/frame_transform.cpp frame/geometry.cpp mixer/audio/audio_mixer.cpp mixer/image/blend_modes.cpp mixer/mixer.cpp producer/color/color_producer.cpp producer/separated/separated_producer.cpp producer/transition/transition_producer.cpp producer/route/route_producer.cpp producer/cg_proxy.cpp producer/frame_producer.cpp producer/layer.cpp producer/stage.cpp StdAfx.cpp video_channel.cpp video_format.cpp ) set(HEADERS consumer/frame_consumer.h consumer/output.h diagnostics/call_context.h diagnostics/osd_graph.h frame/draw_frame.h frame/frame.h frame/frame_factory.h frame/frame_transform.h frame/frame_visitor.h frame/geometry.h frame/pixel_format.h mixer/audio/audio_mixer.h mixer/image/blend_modes.h mixer/image/image_mixer.h mixer/mixer.h monitor/monitor.h producer/color/color_producer.h producer/separated/separated_producer.h producer/transition/transition_producer.h producer/route/route_producer.h producer/cg_proxy.h producer/frame_producer.h producer/layer.h producer/stage.h fwd.h module_dependencies.h StdAfx.h video_channel.h video_format.h ) add_library(core ${SOURCES} ${HEADERS}) add_precompiled_header(core StdAfx.h FORCEINCLUDE) configure_file("${PROJECT_SOURCE_DIR}/packages.config" "${CMAKE_CURRENT_BINARY_DIR}/packages.config") include_directories(..) include_directories(${BOOST_INCLUDE_PATH}) include_directories(${TBB_INCLUDE_PATH}) include_directories(${SFML_INCLUDE_PATH}) include_directories(${FREETYPE_INCLUDE_PATH}) include_directories(${GLEW_INCLUDE_PATH}) source_group(sources ./*) source_group(sources\\consumer consumer/*) source_group(sources\\diagnostics diagnostics/*) source_group(sources\\producer producer/*) source_group(sources\\monitor monitor/*) source_group(sources\\frame frame/*) source_group(sources\\mixer mixer/*) source_group(sources\\mixer\\audio mixer/audio/*) source_group(sources\\mixer\\image mixer/image/*) source_group(sources\\producer\\color producer/color/*) source_group(sources\\producer\\route producer/route/*) source_group(sources\\producer\\transition producer/transition/*) source_group(sources\\producer\\separated producer/separated/*) if (MSVC) target_link_libraries(core common ) else() target_link_libraries(core common ) endif() server-2.2.0-stable/src/core/StdAfx.cpp000066400000000000000000000014761341175263200177210ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "StdAfx.h" server-2.2.0-stable/src/core/StdAfx.h000066400000000000000000000045171341175263200173650ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include server-2.2.0-stable/src/core/consumer/000077500000000000000000000000001341175263200176475ustar00rootroot00000000000000server-2.2.0-stable/src/core/consumer/frame_consumer.cpp000066400000000000000000000200671341175263200233650ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../StdAfx.h" #include "frame_consumer.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { struct frame_consumer_registry::impl { std::vector consumer_factories; std::map preconfigured_consumer_factories; }; frame_consumer_registry::frame_consumer_registry() : impl_(new impl()) { } void frame_consumer_registry::register_consumer_factory(const std::wstring& name, const consumer_factory_t& factory) { impl_->consumer_factories.push_back(factory); } void frame_consumer_registry::register_preconfigured_consumer_factory(const std::wstring& element_name, const preconfigured_consumer_factory_t& factory) { impl_->preconfigured_consumer_factories.insert(std::make_pair(element_name, factory)); } std::atomic& destroy_consumers_in_separate_thread() { static std::atomic state; return state; } void destroy_consumers_synchronously() { destroy_consumers_in_separate_thread() = false; } class destroy_consumer_proxy : public frame_consumer { std::shared_ptr consumer_; public: destroy_consumer_proxy(spl::shared_ptr&& consumer) : consumer_(std::move(consumer)) { destroy_consumers_in_separate_thread() = true; } ~destroy_consumer_proxy() { static std::atomic counter; static std::once_flag counter_init_once; std::call_once(counter_init_once, [] { counter = 0; }); if (!destroy_consumers_in_separate_thread()) return; ++counter; CASPAR_VERIFY(counter < 8); auto consumer = new std::shared_ptr(std::move(consumer_)); std::thread([=] { std::unique_ptr> pointer_guard(consumer); auto str = (*consumer)->print(); try { if (!consumer->unique()) CASPAR_LOG(debug) << str << L" Not destroyed on asynchronous destruction thread: " << consumer->use_count(); else CASPAR_LOG(debug) << str << L" Destroying on asynchronous destruction thread."; } catch (...) { } pointer_guard.reset(); }) .detach(); } std::future send(const_frame frame) override { return consumer_->send(std::move(frame)); } void initialize(const video_format_desc& format_desc, int channel_index) override { return consumer_->initialize(format_desc, channel_index); } std::wstring print() const override { return consumer_->print(); } std::wstring name() const override { return consumer_->name(); } bool has_synchronization_clock() const override { return consumer_->has_synchronization_clock(); } int index() const override { return consumer_->index(); } core::monitor::state state() const override { return consumer_->state(); } }; class print_consumer_proxy : public frame_consumer { std::shared_ptr consumer_; public: print_consumer_proxy(spl::shared_ptr&& consumer) : consumer_(std::move(consumer)) { } ~print_consumer_proxy() { auto str = consumer_->print(); CASPAR_LOG(debug) << str << L" Uninitializing."; consumer_.reset(); CASPAR_LOG(info) << str << L" Uninitialized."; } std::future send(const_frame frame) override { return consumer_->send(std::move(frame)); } void initialize(const video_format_desc& format_desc, int channel_index) override { consumer_->initialize(format_desc, channel_index); CASPAR_LOG(info) << consumer_->print() << L" Initialized."; } std::wstring print() const override { return consumer_->print(); } std::wstring name() const override { return consumer_->name(); } bool has_synchronization_clock() const override { return consumer_->has_synchronization_clock(); } int index() const override { return consumer_->index(); } core::monitor::state state() const override { return consumer_->state(); } }; spl::shared_ptr frame_consumer_registry::create_consumer(const std::vector& params, std::vector> channels) const { if (params.empty()) CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("params cannot be empty")); auto consumer = frame_consumer::empty(); auto& consumer_factories = impl_->consumer_factories; std::any_of(consumer_factories.begin(), consumer_factories.end(), [&](const consumer_factory_t& factory) -> bool { try { consumer = factory(params, channels); } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } return consumer != frame_consumer::empty(); }); if (consumer == frame_consumer::empty()) CASPAR_THROW_EXCEPTION(file_not_found() << msg_info("No match found for supplied commands. Check syntax.")); return spl::make_shared(spl::make_shared(std::move(consumer))); } spl::shared_ptr frame_consumer_registry::create_consumer(const std::wstring& element_name, const boost::property_tree::wptree& element, std::vector> channels) const { auto& preconfigured_consumer_factories = impl_->preconfigured_consumer_factories; auto found = preconfigured_consumer_factories.find(element_name); if (found == preconfigured_consumer_factories.end()) CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"No consumer factory registered for element name " + element_name)); return spl::make_shared( spl::make_shared(found->second(element, channels))); } const spl::shared_ptr& frame_consumer::empty() { class empty_frame_consumer : public frame_consumer { public: std::future send(const_frame) override { return make_ready_future(false); } void initialize(const video_format_desc&, int) override {} std::wstring print() const override { return L"empty"; } std::wstring name() const override { return L"empty"; } bool has_synchronization_clock() const override { return false; } int index() const override { return -1; } }; static spl::shared_ptr consumer = spl::make_shared(); return consumer; } }} // namespace caspar::core server-2.2.0-stable/src/core/consumer/frame_consumer.h000066400000000000000000000065621341175263200230360ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "../fwd.h" #include "../monitor/monitor.h" #include #include #include #include #include #include #include namespace caspar { namespace core { class frame_consumer { frame_consumer(const frame_consumer&); frame_consumer& operator=(const frame_consumer&); public: static const spl::shared_ptr& empty(); frame_consumer() {} virtual ~frame_consumer() {} virtual std::future send(const_frame frame) = 0; virtual void initialize(const video_format_desc& format_desc, int channel_index) = 0; virtual core::monitor::state state() const { static const monitor::state empty; return empty; } virtual std::wstring print() const = 0; virtual std::wstring name() const = 0; virtual bool has_synchronization_clock() const { return false; } virtual int index() const = 0; }; typedef std::function(const std::vector&, std::vector> channels)> consumer_factory_t; typedef std::function(const boost::property_tree::wptree& element, std::vector> channels)> preconfigured_consumer_factory_t; class frame_consumer_registry : boost::noncopyable { public: frame_consumer_registry(); void register_consumer_factory(const std::wstring& name, const consumer_factory_t& factory); void register_preconfigured_consumer_factory(const std::wstring& element_name, const preconfigured_consumer_factory_t& factory); spl::shared_ptr create_consumer(const std::vector& params, std::vector> channels) const; spl::shared_ptr create_consumer(const std::wstring& element_name, const boost::property_tree::wptree& element, std::vector> channels) const; private: struct impl; spl::shared_ptr impl_; }; void destroy_consumers_synchronously(); }} // namespace caspar::core server-2.2.0-stable/src/core/consumer/output.cpp000066400000000000000000000136501341175263200217200ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "output.h" #include "frame_consumer.h" #include "../frame/frame.h" #include "../monitor/monitor.h" #include "../video_format.h" #include #include #include #include #include #include #include namespace caspar { namespace core { typedef decltype(std::chrono::high_resolution_clock::now()) time_point_t; struct output::impl { monitor::state state_; spl::shared_ptr graph_; const int channel_index_; video_format_desc format_desc_; std::mutex consumers_mutex_; std::map> consumers_; boost::optional time_; public: impl(spl::shared_ptr graph, const video_format_desc& format_desc, int channel_index) : graph_(std::move(graph)) , channel_index_(channel_index) , format_desc_(format_desc) { } void add(int index, spl::shared_ptr consumer) { remove(index); consumer->initialize(format_desc_, channel_index_); std::lock_guard lock(consumers_mutex_); consumers_.emplace(index, std::move(consumer)); } void add(const spl::shared_ptr& consumer) { add(consumer->index(), consumer); } bool remove(int index) { std::lock_guard lock(consumers_mutex_); auto it = consumers_.find(index); if (it != consumers_.end()) { consumers_.erase(it); return true; } return false; } bool remove(const spl::shared_ptr& consumer) { return remove(consumer->index()); } void operator()(const_frame input_frame, const core::video_format_desc& format_desc) { if (!input_frame) { return; } if (input_frame.size() != format_desc_.size) { CASPAR_LOG(warning) << print() << L" Invalid input frame size."; return; } auto time = std::move(time_); if (format_desc_ != format_desc) { std::lock_guard lock(consumers_mutex_); for (auto it = consumers_.begin(); it != consumers_.end();) { try { it->second->initialize(format_desc, it->first); ++it; } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); it = consumers_.erase(it); } } format_desc_ = format_desc; time_ = boost::none; return; } decltype(consumers_) consumers; { std::lock_guard lock(consumers_mutex_); consumers = consumers_; } std::map> futures; for (auto it = consumers_.begin(); it != consumers_.end();) { try { futures.emplace(it->first, it->second->send(input_frame)); ++it; } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); it = consumers_.erase(it); } } for (auto& p : futures) { try { if (!p.second.get()) { consumers_.erase(p.first); } } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); consumers_.erase(p.first); } } monitor::state state; for (auto& p : consumers_) { state["port"][p.first] = p.second->state(); } state_ = std::move(state); const auto needs_sync = std::all_of( consumers_.begin(), consumers_.end(), [](auto& p) { return !p.second->has_synchronization_clock(); }); if (needs_sync) { if (!time) { time = std::chrono::high_resolution_clock::now(); } else { std::this_thread::sleep_until(*time); } time_ = *time + std::chrono::microseconds(static_cast(1e6 / format_desc_.fps)); } else { time_.reset(); } } std::wstring print() const { return L"output[" + boost::lexical_cast(channel_index_) + L"]"; } }; output::output(spl::shared_ptr graph, const video_format_desc& format_desc, int channel_index) : impl_(new impl(std::move(graph), format_desc, channel_index)) { } output::~output() {} void output::add(int index, const spl::shared_ptr& consumer) { impl_->add(index, consumer); } void output::add(const spl::shared_ptr& consumer) { impl_->add(consumer); } bool output::remove(int index) { return impl_->remove(index); } bool output::remove(const spl::shared_ptr& consumer) { return impl_->remove(consumer); } void output::operator()(const_frame frame, const video_format_desc& format_desc) { return (*impl_)(std::move(frame), format_desc); } core::monitor::state output::state() const { return impl_->state_; } }} // namespace caspar::core server-2.2.0-stable/src/core/consumer/output.h000066400000000000000000000033261341175263200213640ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "../fwd.h" #include "../monitor/monitor.h" #include #include #include #include FORWARD2(caspar, diagnostics, class graph); namespace caspar { namespace core { class output final { public: explicit output(spl::shared_ptr graph, const video_format_desc& format_desc, int channel_index); output(const output&) = delete; output& operator=(const output&) = delete; ~output(); void operator()(const_frame frame, const video_format_desc& format_desc); void add(const spl::shared_ptr& consumer); void add(int index, const spl::shared_ptr& consumer); bool remove(const spl::shared_ptr& consumer); bool remove(int index); core::monitor::state state() const; private: struct impl; std::unique_ptr impl_; }; }} // namespace caspar::core server-2.2.0-stable/src/core/diagnostics/000077500000000000000000000000001341175263200203235ustar00rootroot00000000000000server-2.2.0-stable/src/core/diagnostics/call_context.cpp000066400000000000000000000027031341175263200235100ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #include "../StdAfx.h" #include "call_context.h" #include namespace caspar { namespace core { namespace diagnostics { thread_local call_context context; call_context& call_context::for_thread() { return context; } std::wstring call_context::to_string() const { if (video_channel == -1) return L"[]"; else if (layer == -1) return L"[ch=" + boost::lexical_cast(video_channel) + L"]"; else return L"[ch=" + boost::lexical_cast(video_channel) + L"; layer=" + boost::lexical_cast(layer) + L"]"; } }}} // namespace caspar::core::diagnostics server-2.2.0-stable/src/core/diagnostics/call_context.h000066400000000000000000000024761341175263200231640ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include #include namespace caspar { namespace core { namespace diagnostics { struct call_context { int video_channel = -1; int layer = -1; static call_context& for_thread(); std::wstring to_string() const; }; class scoped_call_context : boost::noncopyable { call_context saved_ = call_context::for_thread(); public: ~scoped_call_context() { call_context::for_thread() = saved_; } }; }}} // namespace caspar::core::diagnostics server-2.2.0-stable/src/core/diagnostics/osd_graph.cpp000066400000000000000000000401541341175263200230010ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../StdAfx.h" #include "osd_graph.h" #pragma warning(disable : 4244) #include "call_context.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { namespace diagnostics { namespace osd { static const int PREFERRED_VERTICAL_GRAPHS = 8; static const int RENDERING_WIDTH = 1024; static const int RENDERING_HEIGHT = RENDERING_WIDTH / PREFERRED_VERTICAL_GRAPHS; sf::Color get_sfml_color(int color) { auto c = caspar::diagnostics::color(color); return {static_cast((color >> 24) & 255), static_cast((color >> 16) & 255), static_cast((color >> 8) & 255), static_cast((color >> 0) & 255)}; } sf::Font& get_default_font() { static sf::Font DEFAULT_FONT = []() { sf::Font font; if (!font.loadFromFile("LiberationMono-Regular.ttf")) CASPAR_THROW_EXCEPTION(file_not_found() << msg_info("LiberationMono-Regular.ttf not found")); return font; }(); return DEFAULT_FONT; } struct drawable : public sf::Drawable , public sf::Transformable { virtual ~drawable() {} virtual void render(sf::RenderTarget& target, sf::RenderStates states) = 0; virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const override { states.transform *= getTransform(); const_cast(this)->render(target, states); } }; class context : public drawable { std::unique_ptr window_; sf::View view_; std::list> drawables_; caspar::timer display_time_; bool calculate_view_ = true; int scroll_position_ = 0; bool dragging_ = false; int last_mouse_y_ = 0; executor executor_{L"diagnostics"}; public: static void register_drawable(const std::shared_ptr& drawable) { if (!drawable) return; get_instance()->executor_.begin_invoke([=] { get_instance()->do_register_drawable(drawable); }); } static void show(bool value) { get_instance()->executor_.begin_invoke([=] { get_instance()->do_show(value); }); } static void shutdown() { get_instance().reset(); } private: context() {} void do_show(bool value) { if (value) { if (!window_) { window_.reset( new sf::RenderWindow(sf::VideoMode(RENDERING_WIDTH, RENDERING_WIDTH), "CasparCG Diagnostics")); window_->setPosition(sf::Vector2i(0, 0)); window_->setActive(); window_->setVerticalSyncEnabled(true); calculate_view_ = true; glEnable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); tick(); } } else window_.reset(); } void tick() { if (!window_) return; sf::Event e; while (window_->pollEvent(e)) { switch (e.type) { case sf::Event::Closed: window_.reset(); return; case sf::Event::Resized: calculate_view_ = true; break; case sf::Event::MouseButtonPressed: dragging_ = true; last_mouse_y_ = e.mouseButton.y; break; case sf::Event::MouseButtonReleased: dragging_ = false; break; case sf::Event::MouseMoved: if (dragging_) { auto delta_y = e.mouseMove.y - last_mouse_y_; scroll_position_ += delta_y; last_mouse_y_ = e.mouseMove.y; calculate_view_ = true; } break; case sf::Event::MouseWheelMoved: scroll_position_ += e.mouseWheel.delta * 15; calculate_view_ = true; break; } } window_->clear(); if (calculate_view_) { int content_height = static_cast(RENDERING_HEIGHT * drawables_.size()); int window_height = static_cast(window_->getSize().y); int not_visible = std::max(0, content_height - window_height); int min_scroll_position = -not_visible; int max_scroll_position = 0; scroll_position_ = std::min(max_scroll_position, std::max(min_scroll_position, scroll_position_)); view_.setViewport(sf::FloatRect(0, 0, 1.0, 1.0)); view_.setSize(RENDERING_WIDTH, window_height); view_.setCenter(RENDERING_WIDTH / 2, window_height / 2 - scroll_position_); window_->setView(view_); calculate_view_ = false; } CASPAR_LOG(trace) << "osd_graph::tick()"; window_->draw(*this); window_->display(); display_time_.restart(); if (executor_.is_running()) { executor_.begin_invoke([this] { tick(); }); } std::this_thread::sleep_for(std::chrono::milliseconds(20)); } void render(sf::RenderTarget& target, sf::RenderStates states) { int n = 0; for (auto it = drawables_.begin(); it != drawables_.end(); ++n) { auto drawable = it->lock(); if (drawable) { float target_y = n * RENDERING_HEIGHT; drawable->setPosition(0.0f, target_y); target.draw(*drawable, states); ++it; } else it = drawables_.erase(it); } } void do_register_drawable(const std::shared_ptr& drawable) { drawables_.push_back(drawable); auto it = drawables_.begin(); while (it != drawables_.end()) { if (it->lock()) ++it; else it = drawables_.erase(it); } } static std::unique_ptr& get_instance() { static auto impl = std::unique_ptr(new context); return impl; } }; class line : public drawable { size_t res_; boost::circular_buffer line_data_{res_}; boost::circular_buffer> line_tags_{res_}; std::atomic tick_data_; std::atomic tick_tag_; std::atomic color_; double x_delta_ = 1.0 / (res_ - 1); public: line() : res_(1024) { tick_data_ = -1.0f; color_ = 0xFFFFFFFF; tick_tag_ = false; } line(const line& other) : res_(other.res_) , line_data_(other.line_data_) , line_tags_(other.line_tags_) , tick_data_(other.tick_data_.load()) , tick_tag_(other.tick_tag_.load()) , color_(other.color_.load()) , x_delta_(other.x_delta_) { } void set_value(float value) { tick_data_ = value; } void set_tag() { tick_tag_ = true; } void set_color(int color) { color_ = color; } int get_color() { return color_; } void render(sf::RenderTarget& target, sf::RenderStates states) { /*states.transform.translate(x_pos_, 0.f); if (line_data_.size() == res_) x_pos_ = -get_insertion_xcoord() + 1.0 - x_delta_; // Otherwise the graph will drift because of floating point precision else x_pos_ -= x_delta_;*/ for (auto& vertex : line_data_) vertex.position.x -= x_delta_; for (auto& tag : line_tags_) { if (tag) { (*tag)[0].position.x -= x_delta_; (*tag)[1].position.x -= x_delta_; } } auto color = get_sfml_color(color_); color.a = 255 * 0.8; line_data_.push_back(sf::Vertex( sf::Vector2f(get_insertion_xcoord(), std::max(0.1f, std::min(0.9f, (1.0f - tick_data_) * 0.8f + 0.1f))), color)); if (tick_tag_) { sf::VertexArray vertical_dash(sf::LinesStrip); vertical_dash.append(sf::Vertex(sf::Vector2f(get_insertion_xcoord() - x_delta_, 0.f), color)); vertical_dash.append(sf::Vertex(sf::Vector2f(get_insertion_xcoord() - x_delta_, 1.f), color)); line_tags_.push_back(vertical_dash); } else line_tags_.push_back(boost::none); tick_tag_ = false; if (tick_data_ > -0.5) { auto array_one = line_data_.array_one(); auto array_two = line_data_.array_two(); // since boost::circular_buffer guarantees two contigous views of the buffer we can provide raw access to // SFML, which can use glDrawArrays. target.draw(array_one.first, static_cast(array_one.second), sf::LinesStrip, states); target.draw(array_two.first, static_cast(array_two.second), sf::LinesStrip, states); if (array_one.second > 0 && array_two.second > 0) { // Connect the gap between the arrays sf::VertexArray connecting_line(sf::LinesStrip); connecting_line.append(*(array_one.first + array_one.second - 1)); connecting_line.append(*(array_two.first)); target.draw(connecting_line, states); } } else { glEnable(GL_LINE_STIPPLE); glLineStipple(3, 0xAAAA); for (size_t n = 0; n < line_tags_.size(); ++n) { if (line_tags_[n]) { target.draw(*line_tags_[n], states); } } glDisable(GL_LINE_STIPPLE); } } private: double get_insertion_xcoord() const { return line_data_.empty() ? 1.0 : line_data_.back().position.x + x_delta_; } }; struct graph : public drawable , public caspar::diagnostics::spi::graph_sink , public std::enable_shared_from_this { call_context context_ = call_context::for_thread(); tbb::concurrent_unordered_map lines_; std::mutex mutex_; std::wstring text_; bool auto_reset_ = false; graph() {} void activate() override { context::register_drawable(shared_from_this()); } void set_text(const std::wstring& value) override { auto temp = value; std::lock_guard lock(mutex_); text_ = std::move(temp); } void set_value(const std::string& name, double value) override { lines_[name].set_value(static_cast(value)); } void set_tag(caspar::diagnostics::tag_severity /*severity*/, const std::string& name) override { lines_[name].set_tag(); } void set_color(const std::string& name, int color) override { lines_[name].set_color(color); } void auto_reset() override { std::lock_guard lock(mutex_); auto_reset_ = true; } private: void render(sf::RenderTarget& target, sf::RenderStates states) override { const size_t text_size = 15; const size_t text_margin = 2; const size_t text_offset = (text_size + text_margin * 2) * 2; std::wstring text_str; bool auto_reset; { std::lock_guard lock(mutex_); text_str = text_; auto_reset = auto_reset_; } sf::Text text(text_str.c_str(), get_default_font(), text_size); text.setStyle(sf::Text::Italic); text.move(text_margin, text_margin); target.draw(text, states); if (context_.video_channel != -1) { auto ctx_str = boost::lexical_cast(context_.video_channel); if (context_.layer != -1) ctx_str += "-" + boost::lexical_cast(context_.layer); sf::Text context_text(ctx_str, get_default_font(), text_size); context_text.setStyle(sf::Text::Italic); context_text.move(RENDERING_WIDTH - text_margin - 5 - context_text.getLocalBounds().width, text_margin); target.draw(context_text, states); } float x_offset = text_margin; for (auto it = lines_.begin(); it != lines_.end(); ++it) { sf::Text line_text(it->first, get_default_font(), text_size); line_text.setPosition(x_offset, text_margin + text_offset / 2); line_text.setColor(get_sfml_color(it->second.get_color())); target.draw(line_text, states); x_offset += line_text.getLocalBounds().width + text_margin * 2; } static const auto rect = []() { sf::RectangleShape r(sf::Vector2f(RENDERING_WIDTH, RENDERING_HEIGHT - 2)); r.setFillColor(sf::Color(255, 255, 255, 51)); r.setOutlineThickness(0.00f); r.move(0, 1); return r; }(); target.draw(rect, states); states.transform.translate(0, text_offset) .scale(RENDERING_WIDTH, RENDERING_HEIGHT * (static_cast(RENDERING_HEIGHT - text_offset) / static_cast(RENDERING_HEIGHT))); static const sf::Color guide_color(255, 255, 255, 127); static const sf::VertexArray middle_guide = []() { sf::VertexArray result(sf::LinesStrip); result.append(sf::Vertex(sf::Vector2f(0.0f, 0.5f), guide_color)); result.append(sf::Vertex(sf::Vector2f(1.0f, 0.5f), guide_color)); return result; }(); static const sf::VertexArray bottom_guide = []() { sf::VertexArray result(sf::LinesStrip); result.append(sf::Vertex(sf::Vector2f(0.0f, 0.9f), guide_color)); result.append(sf::Vertex(sf::Vector2f(1.0f, 0.9f), guide_color)); return result; }(); static const sf::VertexArray top_guide = []() { sf::VertexArray result(sf::LinesStrip); result.append(sf::Vertex(sf::Vector2f(0.0f, 0.1f), guide_color)); result.append(sf::Vertex(sf::Vector2f(1.0f, 0.1f), guide_color)); return result; }(); glEnable(GL_LINE_STIPPLE); glLineStipple(3, 0xAAAA); target.draw(middle_guide, states); target.draw(bottom_guide, states); target.draw(top_guide, states); glDisable(GL_LINE_STIPPLE); for (auto it = lines_.begin(); it != lines_.end(); ++it) { target.draw(it->second, states); if (auto_reset) it->second.set_value(0.0f); } } }; void register_sink() { caspar::diagnostics::spi::register_sink_factory([] { return spl::make_shared(); }); } void show_graphs(bool value) { context::show(value); } void shutdown() { context::shutdown(); } }}}} // namespace caspar::core::diagnostics::osd server-2.2.0-stable/src/core/diagnostics/osd_graph.h000066400000000000000000000022321341175263200224410ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include #include namespace caspar { namespace core { namespace diagnostics { namespace osd { void register_sink(); void show_graphs(bool value); void shutdown(); }}}} // namespace caspar::core::diagnostics::osd server-2.2.0-stable/src/core/frame/000077500000000000000000000000001341175263200171065ustar00rootroot00000000000000server-2.2.0-stable/src/core/frame/draw_frame.cpp000066400000000000000000000114741341175263200217300ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "draw_frame.h" #include "frame.h" #include "frame_transform.h" #include "frame_visitor.h" #include namespace caspar { namespace core { typedef boost::variant> frame_t; struct draw_frame::impl { frame_t frame_; frame_transform transform_; public: impl() {} impl(frame_t frame) : frame_(std::move(frame)) { } void accept(frame_visitor& visitor) const { struct accept_visitor : public boost::static_visitor { frame_visitor& visitor; accept_visitor(frame_visitor& visitor) : visitor(visitor) { } void operator()(boost::blank) const {} void operator()(const const_frame& frame) const { visitor.visit(frame); } void operator()(const std::vector& frames) const { for (auto& frame : frames) { frame.accept(visitor); } } }; visitor.push(transform_); boost::apply_visitor(accept_visitor{visitor}, frame_); visitor.pop(); } bool operator==(const impl& other) { return frame_ == other.frame_ && transform_ == other.transform_; } }; draw_frame::draw_frame() : impl_(new impl()) { } draw_frame::draw_frame(const draw_frame& other) : impl_(new impl()) { impl_->frame_ = other.impl_->frame_; impl_->transform_ = other.impl_->transform_; } draw_frame::draw_frame(draw_frame&& other) : impl_(std::move(other.impl_)) { } draw_frame::draw_frame(const_frame frame) : impl_(new impl(std::move(frame))) { } draw_frame::draw_frame(mutable_frame&& frame) : impl_(new impl(std::move(frame))) { } draw_frame::draw_frame(std::vector frames) : impl_(new impl(std::move(frames))) { } draw_frame::~draw_frame() {} draw_frame& draw_frame::operator=(draw_frame other) { impl_ = std::move(other.impl_); return *this; } void draw_frame::swap(draw_frame& other) { impl_.swap(other.impl_); } const frame_transform& draw_frame::transform() const { return impl_->transform_; } frame_transform& draw_frame::transform() { return impl_->transform_; } void draw_frame::accept(frame_visitor& visitor) const { impl_->accept(visitor); } bool draw_frame::operator==(const draw_frame& other) const { return impl_ && *impl_ == *other.impl_; } bool draw_frame::operator!=(const draw_frame& other) const { return !(*this == other); } draw_frame draw_frame::over(draw_frame frame1, draw_frame frame2) { if (!frame1 && !frame2) { return draw_frame{}; } std::vector frames; frames.push_back(std::move(frame1)); frames.push_back(std::move(frame2)); return draw_frame(std::move(frames)); } draw_frame draw_frame::mask(draw_frame fill, draw_frame key) { if (!fill || !key) { return draw_frame{}; } std::vector frames; key.transform().image_transform.is_key = true; frames.push_back(std::move(key)); frames.push_back(std::move(fill)); return draw_frame(std::move(frames)); } draw_frame draw_frame::push(draw_frame frame) { std::vector frames; frames.push_back(std::move(frame)); return draw_frame(std::move(frames)); } draw_frame draw_frame::push(draw_frame frame, const frame_transform& transform) { std::vector frames; frames.push_back(std::move(frame)); auto result = draw_frame(std::move(frames)); result.transform() = std::move(transform); return result; } draw_frame draw_frame::pop(draw_frame frame) { draw_frame result; result.impl_->frame_ = frame.impl_->frame_; return result; } draw_frame draw_frame::still(draw_frame frame) { frame.transform().audio_transform.volume = 0.0; return frame; } draw_frame draw_frame::empty() { return draw_frame(std::vector{}); } draw_frame::operator bool() const { return impl_ && impl_->frame_.which() != 0; } }} // namespace caspar::core server-2.2.0-stable/src/core/frame/draw_frame.h000066400000000000000000000037661341175263200214020ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include namespace caspar { namespace core { class draw_frame final { public: static draw_frame over(draw_frame frame1, draw_frame frame2); static draw_frame mask(draw_frame fill, draw_frame key); static draw_frame still(draw_frame frame); static draw_frame push(draw_frame frame); static draw_frame push(draw_frame frame, const struct frame_transform& transform); static draw_frame pop(draw_frame frame); static draw_frame empty(); draw_frame(); draw_frame(const draw_frame& other); draw_frame(draw_frame&& other); draw_frame(class const_frame frame); draw_frame(class mutable_frame&& frame); draw_frame(std::vector frames); ~draw_frame(); draw_frame& operator=(draw_frame other); void swap(draw_frame& other); void accept(class frame_visitor& visitor) const; bool operator==(const draw_frame& other) const; bool operator!=(const draw_frame& other) const; const struct frame_transform& transform() const; struct frame_transform& transform(); explicit operator bool() const; private: struct impl; std::unique_ptr impl_; }; }} // namespace caspar::core server-2.2.0-stable/src/core/frame/frame.cpp000066400000000000000000000172231341175263200207110ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "frame.h" #include "geometry.h" #include "pixel_format.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { struct mutable_frame::impl : boost::noncopyable { std::vector> image_data_; array audio_data_; const core::pixel_format_desc desc_; const void* tag_; frame_geometry geometry_ = frame_geometry::get_default(); mutable_frame::commit_t commit_; impl(const void* tag, std::vector> image_data, array audio_data, const core::pixel_format_desc& desc, commit_t commit) : tag_(tag) , image_data_(std::move(image_data)) , audio_data_(std::move(audio_data)) , desc_(desc) , commit_(std::move(commit)) { } }; mutable_frame::mutable_frame(const void* tag, std::vector> image_data, array audio_data, const core::pixel_format_desc& desc, commit_t commit) : impl_(new impl(tag, std::move(image_data), std::move(audio_data), desc, std::move(commit))) { } mutable_frame::mutable_frame(mutable_frame&& other) : impl_(std::move(other.impl_)) { } mutable_frame::~mutable_frame() {} mutable_frame& mutable_frame::operator=(mutable_frame&& other) { impl_ = std::move(other.impl_); return *this; } void mutable_frame::swap(mutable_frame& other) { impl_.swap(other.impl_); } const core::pixel_format_desc& mutable_frame::pixel_format_desc() const { return impl_->desc_; } const array& mutable_frame::image_data(std::size_t index) const { return impl_->image_data_.at(index); } const array& mutable_frame::audio_data() const { return impl_->audio_data_; } array& mutable_frame::image_data(std::size_t index) { return impl_->image_data_.at(index); } array& mutable_frame::audio_data() { return impl_->audio_data_; } std::size_t mutable_frame::width() const { return impl_->desc_.planes.at(0).width; } std::size_t mutable_frame::height() const { return impl_->desc_.planes.at(0).height; } const frame_geometry& mutable_frame::geometry() const { return impl_->geometry_; } frame_geometry& mutable_frame::geometry() { return impl_->geometry_; } struct const_frame::impl { std::vector> image_data_; array audio_data_; core::pixel_format_desc desc_ = pixel_format::invalid; frame_geometry geometry_ = frame_geometry::get_default(); boost::any opaque_; impl(std::vector> image_data, array audio_data, const core::pixel_format_desc& desc) : image_data_(std::move(image_data)) , audio_data_(std::move(audio_data)) , desc_(desc) { if (desc_.planes.size() != image_data_.size()) { CASPAR_THROW_EXCEPTION(invalid_argument()); } } impl(std::vector>&& image_data, array audio_data, const core::pixel_format_desc& desc) : image_data_(std::make_move_iterator(image_data.begin()), std::make_move_iterator(image_data.end())) , audio_data_(std::move(audio_data)) , desc_(desc) { if (desc_.planes.size() != image_data_.size()) { CASPAR_THROW_EXCEPTION(invalid_argument()); } } impl(mutable_frame&& other) : image_data_(std::make_move_iterator(other.impl_->image_data_.begin()), std::make_move_iterator(other.impl_->image_data_.end())) , audio_data_(std::move(other.impl_->audio_data_)) , desc_(std::move(other.impl_->desc_)) , geometry_(std::move(other.impl_->geometry_)) { if (desc_.planes.size() != image_data_.size()) { CASPAR_THROW_EXCEPTION(invalid_argument()); } if (other.impl_->commit_) { opaque_ = other.impl_->commit_(image_data_); } } const array& image_data(std::size_t index) const { return image_data_.at(index); } std::size_t width() const { return desc_.planes.at(0).width; } std::size_t height() const { return desc_.planes.at(0).height; } std::size_t size() const { return desc_.planes.at(0).size; } }; const_frame::const_frame() {} const_frame::const_frame(std::vector> image_data, array audio_data, const core::pixel_format_desc& desc) : impl_(new impl(std::move(image_data), std::move(audio_data), desc)) { } const_frame::const_frame(mutable_frame&& other) : impl_(new impl(std::move(other))) { } const_frame::const_frame(const const_frame& other) : impl_(other.impl_) { } const_frame::~const_frame() {} const_frame& const_frame::operator=(const const_frame& other) { impl_ = other.impl_; return *this; } bool const_frame::operator==(const const_frame& other) const { return impl_ == other.impl_; } bool const_frame::operator!=(const const_frame& other) const { return !(*this == other); } bool const_frame::operator<(const const_frame& other) const { return impl_ < other.impl_; } bool const_frame:: operator>(const const_frame& other) const { return impl_ > other.impl_; } const pixel_format_desc& const_frame::pixel_format_desc() const { return impl_->desc_; } const array& const_frame::image_data(std::size_t index) const { return impl_->image_data(index); } const array& const_frame::audio_data() const { return impl_->audio_data_; } std::size_t const_frame::width() const { return impl_->width(); } std::size_t const_frame::height() const { return impl_->height(); } std::size_t const_frame::size() const { return impl_->size(); } const frame_geometry& const_frame::geometry() const { return impl_->geometry_; } const boost::any& const_frame::opaque() const { return impl_->opaque_; } const_frame::operator bool() const { return impl_ != nullptr && impl_->desc_.format != core::pixel_format::invalid; } }} // namespace caspar::core server-2.2.0-stable/src/core/frame/frame.h000066400000000000000000000051761341175263200203620ustar00rootroot00000000000000#pragma once #include #include #include #include #include #include #include namespace caspar { namespace core { class mutable_frame final { friend class const_frame; public: typedef std::function>)> commit_t; explicit mutable_frame(const void* tag, std::vector> image_data, array audio_data, const struct pixel_format_desc& desc, commit_t commit = nullptr); mutable_frame(const mutable_frame&) = delete; mutable_frame(mutable_frame&& other); ~mutable_frame(); mutable_frame& operator=(const mutable_frame&) = delete; mutable_frame& operator =(mutable_frame&& other); void swap(mutable_frame& other); const struct pixel_format_desc& pixel_format_desc() const; array& image_data(std::size_t index); const array& image_data(std::size_t index) const; array& audio_data(); const array& audio_data() const; std::size_t width() const; std::size_t height() const; class frame_geometry& geometry(); const class frame_geometry& geometry() const; private: struct impl; std::unique_ptr impl_; }; class const_frame final { public: const_frame(); explicit const_frame(std::vector> image_data, array audio_data, const struct pixel_format_desc& desc); const_frame(const const_frame& other); const_frame(mutable_frame&& other); ~const_frame(); const_frame& operator=(const const_frame& other); const struct pixel_format_desc& pixel_format_desc() const; const array& image_data(std::size_t index) const; const array& audio_data() const; std::size_t width() const; std::size_t height() const; std::size_t size() const; const boost::any& opaque() const; const class frame_geometry& geometry() const; bool operator==(const const_frame& other) const; bool operator!=(const const_frame& other) const; bool operator<(const const_frame& other) const; bool operator>(const const_frame& other) const; explicit operator bool() const; private: struct impl; std::shared_ptr impl_; }; }} // namespace caspar::core server-2.2.0-stable/src/core/frame/frame_factory.h000066400000000000000000000023501341175263200221000ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once namespace caspar { namespace core { class frame_factory { public: frame_factory() = default; frame_factory& operator=(const frame_factory&) = delete; virtual ~frame_factory() = default; frame_factory(const frame_factory&) = delete; virtual class mutable_frame create_frame(const void* video_stream_tag, const struct pixel_format_desc& desc) = 0; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/frame/frame_transform.cpp000066400000000000000000000352151341175263200230050ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "frame_transform.h" #include #include namespace caspar { namespace core { // image_transform template void transform_rect(Rect& self, const Rect& other) { self.ul[0] += other.ul[0]; self.ul[1] += other.ul[1]; self.lr[0] *= other.lr[0]; self.lr[1] *= other.lr[1]; } void transform_corners(corners& self, const corners& other) { transform_rect(self, other); self.ur[0] *= other.ur[0]; self.ur[1] += other.ur[1]; self.ll[0] += other.ll[0]; self.ll[1] *= other.ll[1]; // TODO (fix) figure out the math to compose perspective transforms correctly. } image_transform& image_transform::operator*=(const image_transform& other) { opacity *= other.opacity; brightness *= other.brightness; contrast *= other.contrast; saturation *= other.saturation; // TODO (fix) auto aspect_ratio = 1.0; std::array rotated; auto orig_x = other.fill_translation[0]; auto orig_y = other.fill_translation[1] / aspect_ratio; rotated[0] = orig_x * std::cos(angle) - orig_y * std::sin(angle); rotated[1] = orig_x * std::sin(angle) + orig_y * std::cos(angle); rotated[1] *= aspect_ratio; anchor[0] += other.anchor[0] * fill_scale[0]; anchor[1] += other.anchor[1] * fill_scale[1]; fill_translation[0] += rotated[0] * fill_scale[0]; fill_translation[1] += rotated[1] * fill_scale[1]; fill_scale[0] *= other.fill_scale[0]; fill_scale[1] *= other.fill_scale[1]; clip_translation[0] += other.clip_translation[0] * clip_scale[0]; clip_translation[1] += other.clip_translation[1] * clip_scale[1]; clip_scale[0] *= other.clip_scale[0]; clip_scale[1] *= other.clip_scale[1]; angle += other.angle; transform_rect(crop, other.crop); transform_corners(perspective, other.perspective); levels.min_input = std::max(levels.min_input, other.levels.min_input); levels.max_input = std::min(levels.max_input, other.levels.max_input); levels.min_output = std::max(levels.min_output, other.levels.min_output); levels.max_output = std::min(levels.max_output, other.levels.max_output); levels.gamma *= other.levels.gamma; chroma.enable |= other.chroma.enable; chroma.show_mask |= other.chroma.show_mask; chroma.target_hue = std::max(other.chroma.target_hue, chroma.target_hue); chroma.min_saturation = std::max(other.chroma.min_saturation, chroma.min_saturation); chroma.min_brightness = std::max(other.chroma.min_brightness, chroma.min_brightness); chroma.hue_width = std::max(other.chroma.hue_width, chroma.hue_width); chroma.softness = std::max(other.chroma.softness, chroma.softness); chroma.spill_suppress = std::max(other.chroma.spill_suppress, chroma.spill_suppress); chroma.spill_suppress_saturation = std::min(other.chroma.spill_suppress_saturation, chroma.spill_suppress_saturation); is_key |= other.is_key; is_mix |= other.is_mix; blend_mode = std::max(blend_mode, other.blend_mode); layer_depth += other.layer_depth; return *this; } image_transform image_transform::operator*(const image_transform& other) const { return image_transform(*this) *= other; } double do_tween(double time, double source, double dest, double duration, const tweener& tween) { return tween(time, source, dest - source, duration); }; template void do_tween_rectangle(const Rect& source, const Rect& dest, Rect& out, double time, double duration, const tweener& tweener) { out.ul[0] = do_tween(time, source.ul[0], dest.ul[0], duration, tweener); out.ul[1] = do_tween(time, source.ul[1], dest.ul[1], duration, tweener); out.lr[0] = do_tween(time, source.lr[0], dest.lr[0], duration, tweener); out.lr[1] = do_tween(time, source.lr[1], dest.lr[1], duration, tweener); } void do_tween_corners(const corners& source, const corners& dest, corners& out, double time, double duration, const tweener& tweener) { do_tween_rectangle(source, dest, out, time, duration, tweener); out.ur[0] = do_tween(time, source.ur[0], dest.ur[0], duration, tweener); out.ur[1] = do_tween(time, source.ur[1], dest.ur[1], duration, tweener); out.ll[0] = do_tween(time, source.ll[0], dest.ll[0], duration, tweener); out.ll[1] = do_tween(time, source.ll[1], dest.ll[1], duration, tweener); }; image_transform image_transform::tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener& tween) { image_transform result; result.brightness = do_tween(time, source.brightness, dest.brightness, duration, tween); result.contrast = do_tween(time, source.contrast, dest.contrast, duration, tween); result.saturation = do_tween(time, source.saturation, dest.saturation, duration, tween); result.opacity = do_tween(time, source.opacity, dest.opacity, duration, tween); result.anchor[0] = do_tween(time, source.anchor[0], dest.anchor[0], duration, tween); result.anchor[1] = do_tween(time, source.anchor[1], dest.anchor[1], duration, tween); result.fill_translation[0] = do_tween(time, source.fill_translation[0], dest.fill_translation[0], duration, tween); result.fill_translation[1] = do_tween(time, source.fill_translation[1], dest.fill_translation[1], duration, tween); result.fill_scale[0] = do_tween(time, source.fill_scale[0], dest.fill_scale[0], duration, tween); result.fill_scale[1] = do_tween(time, source.fill_scale[1], dest.fill_scale[1], duration, tween); result.clip_translation[0] = do_tween(time, source.clip_translation[0], dest.clip_translation[0], duration, tween); result.clip_translation[1] = do_tween(time, source.clip_translation[1], dest.clip_translation[1], duration, tween); result.clip_scale[0] = do_tween(time, source.clip_scale[0], dest.clip_scale[0], duration, tween); result.clip_scale[1] = do_tween(time, source.clip_scale[1], dest.clip_scale[1], duration, tween); result.angle = do_tween(time, source.angle, dest.angle, duration, tween); result.levels.max_input = do_tween(time, source.levels.max_input, dest.levels.max_input, duration, tween); result.levels.min_input = do_tween(time, source.levels.min_input, dest.levels.min_input, duration, tween); result.levels.max_output = do_tween(time, source.levels.max_output, dest.levels.max_output, duration, tween); result.levels.min_output = do_tween(time, source.levels.min_output, dest.levels.min_output, duration, tween); result.levels.gamma = do_tween(time, source.levels.gamma, dest.levels.gamma, duration, tween); result.chroma.target_hue = do_tween(time, source.chroma.target_hue, dest.chroma.target_hue, duration, tween); result.chroma.hue_width = do_tween(time, source.chroma.hue_width, dest.chroma.hue_width, duration, tween); result.chroma.min_saturation = do_tween(time, source.chroma.min_saturation, dest.chroma.min_saturation, duration, tween); result.chroma.min_brightness = do_tween(time, source.chroma.min_brightness, dest.chroma.min_brightness, duration, tween); result.chroma.softness = do_tween(time, source.chroma.softness, dest.chroma.softness, duration, tween); result.chroma.spill_suppress = do_tween(time, source.chroma.spill_suppress, dest.chroma.spill_suppress, duration, tween); result.chroma.spill_suppress_saturation = do_tween(time, source.chroma.spill_suppress_saturation, dest.chroma.spill_suppress_saturation, duration, tween); result.chroma.enable = dest.chroma.enable; result.chroma.show_mask = dest.chroma.show_mask; result.is_key = source.is_key | dest.is_key; result.is_mix = source.is_mix | dest.is_mix; result.blend_mode = std::max(source.blend_mode, dest.blend_mode); result.layer_depth = dest.layer_depth; do_tween_rectangle(source.crop, dest.crop, result.crop, time, duration, tween); do_tween_corners(source.perspective, dest.perspective, result.perspective, time, duration, tween); return result; } bool eq(double lhs, double rhs) { return std::abs(lhs - rhs) < 5e-8; }; bool operator==(const corners& lhs, const corners& rhs) { return boost::range::equal(lhs.ul, rhs.ul, eq) && boost::range::equal(lhs.ur, rhs.ur, eq) && boost::range::equal(lhs.lr, rhs.lr, eq) && boost::range::equal(lhs.ll, rhs.ll, eq); } bool operator==(const rectangle& lhs, const rectangle& rhs) { return boost::range::equal(lhs.ul, rhs.ul, eq) && boost::range::equal(lhs.lr, rhs.lr, eq); } bool operator==(const image_transform& lhs, const image_transform& rhs) { return eq(lhs.opacity, rhs.opacity) && eq(lhs.contrast, rhs.contrast) && eq(lhs.brightness, rhs.brightness) && eq(lhs.saturation, rhs.saturation) && boost::range::equal(lhs.anchor, rhs.anchor, eq) && boost::range::equal(lhs.fill_translation, rhs.fill_translation, eq) && boost::range::equal(lhs.fill_scale, rhs.fill_scale, eq) && boost::range::equal(lhs.clip_translation, rhs.clip_translation, eq) && boost::range::equal(lhs.clip_scale, rhs.clip_scale, eq) && eq(lhs.angle, rhs.angle) && lhs.is_key == rhs.is_key && lhs.is_mix == rhs.is_mix && lhs.blend_mode == rhs.blend_mode && lhs.layer_depth == rhs.layer_depth && lhs.chroma.enable == rhs.chroma.enable && lhs.chroma.show_mask == rhs.chroma.show_mask && eq(lhs.chroma.target_hue, rhs.chroma.target_hue) && eq(lhs.chroma.hue_width, rhs.chroma.hue_width) && eq(lhs.chroma.min_saturation, rhs.chroma.min_saturation) && eq(lhs.chroma.min_brightness, rhs.chroma.min_brightness) && eq(lhs.chroma.softness, rhs.chroma.softness) && eq(lhs.chroma.spill_suppress, rhs.chroma.spill_suppress) && eq(lhs.chroma.spill_suppress_saturation, rhs.chroma.spill_suppress_saturation) && lhs.crop == rhs.crop && lhs.perspective == rhs.perspective; } bool operator!=(const image_transform& lhs, const image_transform& rhs) { return !(lhs == rhs); } // audio_transform audio_transform& audio_transform::operator*=(const audio_transform& other) { volume *= other.volume; return *this; } audio_transform audio_transform::operator*(const audio_transform& other) const { return audio_transform(*this) *= other; } audio_transform audio_transform::tween(double time, const audio_transform& source, const audio_transform& dest, double duration, const tweener& tween) { audio_transform result; result.volume = do_tween(time, source.volume, dest.volume, duration, tween); return result; } bool operator==(const audio_transform& lhs, const audio_transform& rhs) { return eq(lhs.volume, rhs.volume); } bool operator!=(const audio_transform& lhs, const audio_transform& rhs) { return !(lhs == rhs); } // frame_transform frame_transform::frame_transform() {} frame_transform& frame_transform::operator*=(const frame_transform& other) { image_transform *= other.image_transform; audio_transform *= other.audio_transform; return *this; } frame_transform frame_transform::operator*(const frame_transform& other) const { return frame_transform(*this) *= other; } frame_transform frame_transform::tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener& tween) { frame_transform result; result.image_transform = image_transform::tween(time, source.image_transform, dest.image_transform, duration, tween); result.audio_transform = audio_transform::tween(time, source.audio_transform, dest.audio_transform, duration, tween); return result; } bool operator==(const frame_transform& lhs, const frame_transform& rhs) { return lhs.image_transform == rhs.image_transform && lhs.audio_transform == rhs.audio_transform; } bool operator!=(const frame_transform& lhs, const frame_transform& rhs) { return !(lhs == rhs); } tweened_transform::tweened_transform(const frame_transform& source, const frame_transform& dest, int duration, const tweener& tween) : source_(source) , dest_(dest) , duration_(duration) , tweener_(tween) { } const frame_transform& tweened_transform::dest() const { return dest_; } frame_transform tweened_transform::fetch() { return time_ == duration_ ? dest_ : frame_transform::tween( static_cast(time_), source_, dest_, static_cast(duration_), tweener_); } void tweened_transform::tick(int num) { time_ = std::min(time_ + num, duration_); } boost::optional get_chroma_mode(const std::wstring& str) { if (boost::iequals(str, L"none")) { return chroma::legacy_type::none; } else if (boost::iequals(str, L"green")) { return chroma::legacy_type::green; } else if (boost::iequals(str, L"blue")) { return chroma::legacy_type::blue; } else { return boost::none; } } }} // namespace caspar::core server-2.2.0-stable/src/core/frame/frame_transform.h000066400000000000000000000124361341175263200224520ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include #include namespace caspar { namespace core { struct chroma { enum class legacy_type { none, green, blue }; bool enable = false; bool show_mask = false; double target_hue = 0.0; double hue_width = 0.0; double min_saturation = 0.0; double min_brightness = 0.0; double softness = 0.0; double spill_suppress = 0.0; double spill_suppress_saturation = 1.0; }; struct levels final { double min_input = 0.0; double max_input = 1.0; double gamma = 1.0; double min_output = 0.0; double max_output = 1.0; }; struct corners final { std::array ul = {0.0, 0.0}; std::array ur = {1.0, 0.0}; std::array lr = {1.0, 1.0}; std::array ll = {0.0, 1.0}; }; struct rectangle final { std::array ul = {0.0, 0.0}; std::array lr = {1.0, 1.0}; }; struct image_transform final { double opacity = 1.0; double contrast = 1.0; double brightness = 1.0; double saturation = 1.0; std::array anchor = {0.0, 0.0}; std::array fill_translation = {0.0, 0.0}; std::array fill_scale = {1.0, 1.0}; std::array clip_translation = {0.0, 0.0}; std::array clip_scale = {1.0, 1.0}; double angle = 0.0; rectangle crop; corners perspective; core::levels levels; core::chroma chroma; bool is_key = false; bool is_mix = false; core::blend_mode blend_mode = blend_mode::normal; int layer_depth = 0; image_transform& operator*=(const image_transform& other); image_transform operator*(const image_transform& other) const; static image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener& tween); }; bool operator==(const image_transform& lhs, const image_transform& rhs); bool operator!=(const image_transform& lhs, const image_transform& rhs); struct audio_transform final { double volume = 1.0; audio_transform& operator*=(const audio_transform& other); audio_transform operator*(const audio_transform& other) const; static audio_transform tween(double time, const audio_transform& source, const audio_transform& dest, double duration, const tweener& tween); }; bool operator==(const audio_transform& lhs, const audio_transform& rhs); bool operator!=(const audio_transform& lhs, const audio_transform& rhs); struct frame_transform final { public: frame_transform(); core::image_transform image_transform; core::audio_transform audio_transform; frame_transform& operator*=(const frame_transform& other); frame_transform operator*(const frame_transform& other) const; static frame_transform tween(double time, const frame_transform& source, const frame_transform& dest, double duration, const tweener& tween); }; bool operator==(const frame_transform& lhs, const frame_transform& rhs); bool operator!=(const frame_transform& lhs, const frame_transform& rhs); class tweened_transform { frame_transform source_; frame_transform dest_; int duration_ = 0; int time_ = 0; tweener tweener_; public: tweened_transform() = default; tweened_transform(const frame_transform& source, const frame_transform& dest, int duration, const tweener& tween); const frame_transform& dest() const; frame_transform fetch(); void tick(int num); }; boost::optional get_chroma_mode(const std::wstring& str); }} // namespace caspar::core server-2.2.0-stable/src/core/frame/frame_visitor.h000066400000000000000000000025001341175263200221250ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once namespace caspar { namespace core { class frame_visitor { public: frame_visitor() = default; frame_visitor(const frame_visitor&) = delete; virtual ~frame_visitor() = default; frame_visitor& operator=(const frame_visitor&) = delete; virtual void push(const struct frame_transform& transform) = 0; virtual void visit(const class const_frame& frame) = 0; virtual void pop() = 0; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/frame/geometry.cpp000066400000000000000000000050631341175263200214510ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Niklas P Andersson, niklas.p.andersson@svt.se */ #include "geometry.h" #include namespace caspar { namespace core { frame_geometry::coord::coord(double vertex_x, double vertex_y, double texture_x, double texture_y) : vertex_x(vertex_x) , vertex_y(vertex_y) , texture_x(texture_x) , texture_y(texture_y) { } bool frame_geometry::coord::operator==(const frame_geometry::coord& other) const { return vertex_x == other.vertex_x && vertex_y == other.vertex_y && texture_x == other.texture_x && texture_y == other.texture_y && texture_r == other.texture_r && texture_q == other.texture_q; } struct frame_geometry::impl { impl(frame_geometry::geometry_type type, std::vector data) : type_(type) { if (type == geometry_type::quad && data.size() != 4) CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("The number of coordinates needs to be 4")); data_ = std::move(data); } frame_geometry::geometry_type type_; std::vector data_; }; frame_geometry::frame_geometry(geometry_type type, std::vector data) : impl_(new impl(type, std::move(data))) { } frame_geometry::geometry_type frame_geometry::type() const { return impl_->type_; } const std::vector& frame_geometry::data() const { return impl_->data_; } const frame_geometry& frame_geometry::get_default() { static std::vector data = { // vertex texture {0.0, 0.0, 0.0, 0.0}, // upper left {1.0, 0.0, 1.0, 0.0}, // upper right {1.0, 1.0, 1.0, 1.0}, // lower right {0.0, 1.0, 0.0, 1.0} // lower left }; static const frame_geometry g(frame_geometry::geometry_type::quad, data); return g; } }} // namespace caspar::core server-2.2.0-stable/src/core/frame/geometry.h000066400000000000000000000032421341175263200211130ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Niklas P Andersson, niklas.p.andersson@svt.se */ #pragma once #include #include namespace caspar { namespace core { class frame_geometry { public: enum class geometry_type { quad }; struct coord { double vertex_x = 0.0; double vertex_y = 0.0; double texture_x = 0.0; double texture_y = 0.0; double texture_r = 0.0; double texture_q = 1.0; coord() = default; coord(double vertex_x, double vertex_y, double texture_x, double texture_y); bool operator==(const coord& other) const; }; frame_geometry(geometry_type type, std::vector data); geometry_type type() const; const std::vector& data() const; static const frame_geometry& get_default(); private: struct impl; spl::shared_ptr impl_; }; }} // namespace caspar::core server-2.2.0-stable/src/core/frame/pixel_format.h000066400000000000000000000033061341175263200217520ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { namespace core { enum class pixel_format { gray = 0, bgra, rgba, argb, abgr, ycbcr, ycbcra, luma, bgr, rgb, count, invalid, }; struct pixel_format_desc final { struct plane { int linesize = 0; int width = 0; int height = 0; int size = 0; int stride = 0; plane() = default; plane(int width, int height, int stride) : linesize(width * stride) , width(width) , height(height) , size(width * height * stride) , stride(stride) { } }; pixel_format_desc() = default; pixel_format_desc(pixel_format format) : format(format) { } pixel_format format = pixel_format::invalid; std::vector planes; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/fwd.h000066400000000000000000000034551341175263200167540ustar00rootroot00000000000000/* * Copyright 2013 Sveriges Television AB http://casparcg.com/ * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include FORWARD2(caspar, accelerator, class accelerator); FORWARD3(caspar, accelerator, ogl, class device); FORWARD2(caspar, core, class stage); FORWARD2(caspar, core, class mixer); FORWARD2(caspar, core, class output); FORWARD2(caspar, core, class image_mixer); FORWARD2(caspar, core, struct video_format_desc); FORWARD2(caspar, core, class frame_factory); FORWARD2(caspar, core, class frame_producer); FORWARD2(caspar, core, class frame_consumer); FORWARD2(caspar, core, class draw_frame); FORWARD2(caspar, core, class mutable_frame); FORWARD2(caspar, core, class const_frame); FORWARD2(caspar, core, class video_channel); FORWARD2(caspar, core, struct pixel_format_desc); FORWARD2(caspar, core, class cg_producer_registry); FORWARD2(caspar, core, struct frame_transform); FORWARD2(caspar, core, struct write_frame_consumer); FORWARD2(caspar, core, struct frame_producer_dependencies); FORWARD2(caspar, core, struct module_dependencies); FORWARD2(caspar, core, class frame_producer_registry); server-2.2.0-stable/src/core/mixer/000077500000000000000000000000001341175263200171405ustar00rootroot00000000000000server-2.2.0-stable/src/core/mixer/audio/000077500000000000000000000000001341175263200202415ustar00rootroot00000000000000server-2.2.0-stable/src/core/mixer/audio/audio_mixer.cpp000066400000000000000000000124621341175263200232570ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../../StdAfx.h" #include "audio_mixer.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { using namespace boost::container; struct audio_item { audio_transform transform; array samples; }; typedef std::vector audio_buffer_ps; struct audio_mixer::impl : boost::noncopyable { monitor::state state_; std::stack transform_stack_; std::vector items_; std::atomic master_volume_{1.0f}; spl::shared_ptr graph_; public: impl(spl::shared_ptr graph) : graph_(std::move(graph)) { graph_->set_color("volume", diagnostics::color(1.0f, 0.8f, 0.1f)); graph_->set_color("audio-clipping", diagnostics::color(0.3f, 0.6f, 0.3f)); transform_stack_.push(core::audio_transform()); } void push(const frame_transform& transform) { transform_stack_.push(transform_stack_.top() * transform.audio_transform); } void visit(const const_frame& frame) { if (transform_stack_.top().volume < 0.002 || !frame.audio_data()) return; audio_item item; item.transform = transform_stack_.top(); item.samples = frame.audio_data(); items_.push_back(std::move(item)); } void pop() { transform_stack_.pop(); } void set_master_volume(float volume) { master_volume_ = volume; } float get_master_volume() { return master_volume_; } array mix(const video_format_desc& format_desc, int nb_samples) { auto channels = format_desc.audio_channels; auto items = std::move(items_); auto result = std::vector(nb_samples * channels, 0); auto mixed = std::vector(nb_samples * channels, 0.0f); for (auto& item : items) { auto ptr = item.samples.data(); auto size = std::min(item.samples.size(), result.size()); for (auto n = 0; n < size; ++n) { mixed[n] = static_cast(ptr[n]) * item.transform.volume + mixed[n]; } } auto master_volume = master_volume_.load(); for (auto n = 0; n < mixed.size(); ++n) { auto sample = mixed[n] * master_volume; if (sample > std::numeric_limits::max()) { result[n] = std::numeric_limits::max(); } else if (sample < std::numeric_limits::min()) { result[n] = std::numeric_limits::min(); } else { result[n] = static_cast(sample); } } auto max = std::vector(channels, std::numeric_limits::min()); for (size_t n = 0; n < result.size(); n += channels) { for (int ch = 0; ch < channels; ++ch) { max[ch] = std::max(max[ch], std::abs(result[n + ch])); } } if (boost::range::count_if(max, [](auto val) { return val >= std::numeric_limits::max(); }) > 0) { graph_->set_tag(diagnostics::tag_severity::WARNING, "audio-clipping"); } state_["volume"] = std::move(max); graph_->set_value("volume", static_cast(*boost::max_element(max)) / std::numeric_limits::max()); return std::move(result); } }; audio_mixer::audio_mixer(spl::shared_ptr graph) : impl_(new impl(std::move(graph))) { } void audio_mixer::push(const frame_transform& transform) { impl_->push(transform); } void audio_mixer::visit(const const_frame& frame) { impl_->visit(frame); } void audio_mixer::pop() { impl_->pop(); } void audio_mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); } float audio_mixer::get_master_volume() { return impl_->get_master_volume(); } array audio_mixer::operator()(const video_format_desc& format_desc, int nb_samples) { return impl_->mix(format_desc, nb_samples); } core::monitor::state audio_mixer::state() const { return impl_->state_; } }} // namespace caspar::core server-2.2.0-stable/src/core/mixer/audio/audio_mixer.h000066400000000000000000000034041341175263200227200ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include #include #include FORWARD2(caspar, diagnostics, class graph); namespace caspar { namespace core { class audio_mixer final : public frame_visitor { audio_mixer(const audio_mixer&); audio_mixer& operator=(const audio_mixer&); public: audio_mixer(spl::shared_ptr<::caspar::diagnostics::graph> graph); array operator()(const struct video_format_desc& format_desc, int nb_samples); void set_master_volume(float volume); float get_master_volume(); core::monitor::state state() const; virtual void push(const struct frame_transform& transform); virtual void visit(const class const_frame& frame); virtual void pop(); private: struct impl; spl::shared_ptr impl_; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/mixer/audio/audio_util.h000066400000000000000000000035131341175263200225520ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include namespace caspar { namespace core { template std::vector audio_32_to_24(const T& audio_data) { auto size = std::distance(std::begin(audio_data), std::end(audio_data)); auto input8 = reinterpret_cast(&(*std::begin(audio_data))); auto output8 = std::vector(); output8.reserve(size * 3); for (int n = 0; n < size; ++n) { output8.push_back(input8[n * 4 + 1]); output8.push_back(input8[n * 4 + 2]); output8.push_back(input8[n * 4 + 3]); } return output8; } template std::vector audio_32_to_16(const T& audio_data) { auto size = std::distance(std::begin(audio_data), std::end(audio_data)); auto input32 = &(*std::begin(audio_data)); auto output16 = std::vector(); output16.reserve(size); for (int n = 0; n < size; ++n) output16.push_back((input32[n] >> 16) & 0xFFFF); return output16; } }} // namespace caspar::coreserver-2.2.0-stable/src/core/mixer/image/000077500000000000000000000000001341175263200202225ustar00rootroot00000000000000server-2.2.0-stable/src/core/mixer/image/blend_modes.cpp000066400000000000000000000127211341175263200232040ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../../StdAfx.h" #include "blend_modes.h" #include namespace caspar { namespace core { blend_mode get_blend_mode(const std::wstring& str) { if (boost::iequals(str, L"normal")) return blend_mode::normal; else if (boost::iequals(str, L"lighten")) return blend_mode::lighten; else if (boost::iequals(str, L"darken")) return blend_mode::darken; else if (boost::iequals(str, L"multiply")) return blend_mode::multiply; else if (boost::iequals(str, L"average")) return blend_mode::average; else if (boost::iequals(str, L"add")) return blend_mode::add; else if (boost::iequals(str, L"subtract")) return blend_mode::subtract; else if (boost::iequals(str, L"difference")) return blend_mode::difference; else if (boost::iequals(str, L"negation")) return blend_mode::negation; else if (boost::iequals(str, L"exclusion")) return blend_mode::exclusion; else if (boost::iequals(str, L"screen")) return blend_mode::screen; else if (boost::iequals(str, L"overlay")) return blend_mode::overlay; else if (boost::iequals(str, L"soft_light")) return blend_mode::soft_light; else if (boost::iequals(str, L"hard_light")) return blend_mode::hard_light; else if (boost::iequals(str, L"color_dodge")) return blend_mode::color_dodge; else if (boost::iequals(str, L"color_burn")) return blend_mode::color_burn; else if (boost::iequals(str, L"linear_dodge")) return blend_mode::linear_dodge; else if (boost::iequals(str, L"linear_burn")) return blend_mode::linear_burn; else if (boost::iequals(str, L"linear_light")) return blend_mode::linear_light; else if (boost::iequals(str, L"vivid_light")) return blend_mode::vivid_light; else if (boost::iequals(str, L"pin_light")) return blend_mode::pin_light; else if (boost::iequals(str, L"hard_mix")) return blend_mode::hard_mix; else if (boost::iequals(str, L"reflect")) return blend_mode::reflect; else if (boost::iequals(str, L"glow")) return blend_mode::glow; else if (boost::iequals(str, L"phoenix")) return blend_mode::phoenix; else if (boost::iequals(str, L"contrast")) return blend_mode::contrast; else if (boost::iequals(str, L"saturation")) return blend_mode::saturation; else if (boost::iequals(str, L"color")) return blend_mode::color; else if (boost::iequals(str, L"luminosity")) return blend_mode::luminosity; return blend_mode::normal; } std::wstring get_blend_mode(blend_mode mode) { switch (mode) { case blend_mode::normal: return L"normal"; case blend_mode::lighten: return L"lighten"; case blend_mode::darken: return L"darken"; case blend_mode::multiply: return L"multiply"; case blend_mode::average: return L"average"; case blend_mode::add: return L"add"; case blend_mode::subtract: return L"subtract"; case blend_mode::difference: return L"difference"; case blend_mode::negation: return L"negation"; case blend_mode::exclusion: return L"exclusion"; case blend_mode::screen: return L"screen"; case blend_mode::overlay: return L"overlay"; case blend_mode::soft_light: return L"soft_light"; case blend_mode::hard_light: return L"hard_light"; case blend_mode::color_dodge: return L"color_dodge"; case blend_mode::color_burn: return L"color_burn"; case blend_mode::linear_dodge: return L"linear_dodge"; case blend_mode::linear_burn: return L"linear_burn"; case blend_mode::linear_light: return L"linear_light"; case blend_mode::vivid_light: return L"vivid_light"; case blend_mode::pin_light: return L"pin_light"; case blend_mode::hard_mix: return L"hard_mix"; case blend_mode::reflect: return L"reflect"; case blend_mode::glow: return L"glow"; case blend_mode::phoenix: return L"phoenix"; case blend_mode::contrast: return L"contrast"; case blend_mode::saturation: return L"saturation"; case blend_mode::color: return L"color"; case blend_mode::luminosity: return L"luminosity"; default: return L"normal"; } } }} // namespace caspar::core server-2.2.0-stable/src/core/mixer/image/blend_modes.h000066400000000000000000000027151341175263200226530ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { namespace core { enum class blend_mode { normal = 0, lighten, darken, multiply, average, add, subtract, difference, negation, exclusion, screen, overlay, soft_light, hard_light, color_dodge, color_burn, linear_dodge, linear_burn, linear_light, vivid_light, pin_light, hard_mix, reflect, glow, phoenix, contrast, saturation, color, luminosity, mix, blend_mode_count }; blend_mode get_blend_mode(const std::wstring& str); std::wstring get_blend_mode(blend_mode mode); }} // namespace caspar::coreserver-2.2.0-stable/src/core/mixer/image/image_mixer.h000066400000000000000000000032021341175263200226560ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include namespace caspar { namespace core { class image_mixer : public frame_visitor , public frame_factory { image_mixer(const image_mixer&); image_mixer& operator=(const image_mixer&); public: image_mixer() {} virtual ~image_mixer() {} virtual void push(const struct frame_transform& frame) = 0; virtual void visit(const class const_frame& frame) = 0; virtual void pop() = 0; virtual std::future> operator()(const struct video_format_desc& format_desc) = 0; virtual class mutable_frame create_frame(const void* tag, const struct pixel_format_desc& desc) = 0; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/mixer/mixer.cpp000066400000000000000000000103621341175263200207720ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../StdAfx.h" #include "mixer.h" #include "../frame/frame.h" #include "audio/audio_mixer.h" #include "image/image_mixer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { struct mixer::impl : boost::noncopyable { monitor::state state_; int channel_index_; spl::shared_ptr graph_; audio_mixer audio_mixer_{graph_}; spl::shared_ptr image_mixer_; std::queue> buffer_; public: impl(int channel_index, spl::shared_ptr graph, spl::shared_ptr image_mixer) : channel_index_(channel_index) , graph_(std::move(graph)) , image_mixer_(std::move(image_mixer)) { } const_frame operator()(std::map frames, const video_format_desc& format_desc, int nb_samples) { for (auto& frame : frames) { frame.second.accept(audio_mixer_); frame.second.transform().image_transform.layer_depth = 1; frame.second.accept(*image_mixer_); } auto image = (*image_mixer_)(format_desc); auto audio = audio_mixer_(format_desc, nb_samples); state_["audio"] = audio_mixer_.state(); buffer_.push(std::async( std::launch::deferred, [image = std::move(image), audio = std::move(audio), graph = graph_, format_desc, tag = this]() mutable { auto desc = pixel_format_desc(pixel_format::bgra); desc.planes.push_back(pixel_format_desc::plane(format_desc.width, format_desc.height, 4)); std::vector> image_data; image_data.emplace_back(std::move(image.get())); return const_frame(std::move(image_data), std::move(audio), desc); })); if (buffer_.size() < 2) { return const_frame{}; } auto frame = std::move(buffer_.front().get()); buffer_.pop(); return frame; } void set_master_volume(float volume) { audio_mixer_.set_master_volume(volume); } float get_master_volume() { return audio_mixer_.get_master_volume(); } }; mixer::mixer(int channel_index, spl::shared_ptr graph, spl::shared_ptr image_mixer) : impl_(new impl(channel_index, std::move(graph), std::move(image_mixer))) { } void mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); } float mixer::get_master_volume() { return impl_->get_master_volume(); } const_frame mixer::operator()(std::map frames, const video_format_desc& format_desc, int nb_samples) { return (*impl_)(std::move(frames), format_desc, nb_samples); } mutable_frame mixer::create_frame(const void* tag, const pixel_format_desc& desc) { return impl_->image_mixer_->create_frame(tag, desc); } core::monitor::state mixer::state() const { return impl_->state_; } }} // namespace caspar::core server-2.2.0-stable/src/core/mixer/mixer.h000066400000000000000000000035001341175263200204330ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "image/blend_modes.h" #include #include #include #include #include #include #include FORWARD2(caspar, diagnostics, class graph); namespace caspar { namespace core { class mixer final { mixer(const mixer&); mixer& operator=(const mixer&); public: explicit mixer(int channel_index, spl::shared_ptr graph, spl::shared_ptr image_mixer); const_frame operator()(std::map frames, const video_format_desc& format_desc, int nb_samples); void set_master_volume(float volume); float get_master_volume(); mutable_frame create_frame(const void* tag, const pixel_format_desc& desc); core::monitor::state state() const; private: struct impl; spl::shared_ptr impl_; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/module_dependencies.h000066400000000000000000000032271341175263200221640ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include #include "consumer/frame_consumer.h" #include "producer/cg_proxy.h" #include "producer/frame_producer.h" namespace caspar { namespace core { struct module_dependencies { const spl::shared_ptr cg_registry; const spl::shared_ptr producer_registry; const spl::shared_ptr consumer_registry; module_dependencies(spl::shared_ptr cg_registry, spl::shared_ptr producer_registry, spl::shared_ptr consumer_registry) : cg_registry(std::move(cg_registry)) , producer_registry(std::move(producer_registry)) , consumer_registry(std::move(consumer_registry)) { } }; }} // namespace caspar::core server-2.2.0-stable/src/core/monitor/000077500000000000000000000000001341175263200175035ustar00rootroot00000000000000server-2.2.0-stable/src/core/monitor/monitor.h000066400000000000000000000064131341175263200213470ustar00rootroot00000000000000/* * Copyright 2013 Sveriges Television AB http://casparcg.com/ * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include #include #include namespace caspar { namespace core { namespace monitor { typedef boost::variant data_t; typedef boost::container::small_vector vector_t; typedef boost::container::flat_map data_map_t; class state { data_map_t data_; class state_proxy { std::string key_; data_map_t& data_; public: state_proxy(const std::string& key, data_map_t& data) : key_(key) , data_(data) { } state_proxy& operator=(data_t data) { data_[key_] = {std::move(data)}; return *this; } state_proxy& operator=(vector_t data) { data_[key_] = std::move(data); return *this; } template state_proxy operator[](const T& key) { return state_proxy(key_ + "/" + boost::lexical_cast(key), data_); } template state_proxy& operator=(const std::vector& data) { data_[key_] = vector_t(data.begin(), data.end()); return *this; } state_proxy& operator=(std::initializer_list data) { data_[key_] = vector_t(std::move(data)); return *this; } state_proxy& operator=(const state& other) { for (auto& p : other) { data_[key_ + "/" + p.first] = std::move(p.second); } return *this; } }; public: state() = default; state(const state& other) : data_(other.data_) { } state(data_map_t data) : data_(std::move(data)) { } state& operator=(const state& other) { data_ = other.data_; return *this; } template state_proxy operator[](const T& key) { return state_proxy(boost::lexical_cast(key), data_); } data_map_t::const_iterator begin() const { return data_.begin(); } data_map_t::const_iterator end() const { return data_.end(); } }; }}} // namespace caspar::core::monitor server-2.2.0-stable/src/core/packages.config000066400000000000000000000011321341175263200207560ustar00rootroot00000000000000 server-2.2.0-stable/src/core/producer/000077500000000000000000000000001341175263200176375ustar00rootroot00000000000000server-2.2.0-stable/src/core/producer/cg_proxy.cpp000066400000000000000000000246541341175263200222100ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #include "../StdAfx.h" #include "cg_proxy.h" #include "../diagnostics/call_context.h" #include "../frame/draw_frame.h" #include "../module_dependencies.h" #include "../video_channel.h" #include "frame_producer.h" #include "stage.h" #include #include #include #include #include #include #include "common/param.h" #include #include #include namespace caspar { namespace core { const spl::shared_ptr& cg_proxy::empty() { class empty_proxy : public cg_proxy { void add(int, const std::wstring&, bool, const std::wstring&, const std::wstring&) override {} void remove(int) override {} void play(int) override {} void stop(int, unsigned int) override {} void next(int) override {} void update(int, const std::wstring&) override {} std::wstring invoke(int, const std::wstring&) override { return L""; } }; static spl::shared_ptr instance = spl::make_shared(); return instance; } struct cg_producer_registry::impl { private: struct record { std::wstring name; meta_info_extractor info_extractor; cg_proxy_factory proxy_factory; cg_producer_factory producer_factory; bool reusable_producer_instance; }; mutable std::mutex mutex_; std::map records_by_extension_; public: void register_cg_producer(std::wstring cg_producer_name, std::set file_extensions, meta_info_extractor info_extractor, cg_proxy_factory proxy_factory, cg_producer_factory producer_factory, bool reusable_producer_instance) { std::lock_guard lock(mutex_); record rec{std::move(cg_producer_name), std::move(info_extractor), std::move(proxy_factory), std::move(producer_factory), reusable_producer_instance}; for (auto& extension : file_extensions) { records_by_extension_.insert(std::make_pair(extension, rec)); } } spl::shared_ptr create_producer(const frame_producer_dependencies& dependencies, const std::wstring& filename) const { auto found = find_record(filename); if (!found) return frame_producer::empty(); return found->producer_factory(dependencies, filename); } spl::shared_ptr get_proxy(const spl::shared_ptr& producer) const { auto producer_name = producer->name(); std::lock_guard lock(mutex_); for (auto& elem : records_by_extension_) { if (elem.second.name == producer_name) return elem.second.proxy_factory(producer); } return cg_proxy::empty(); } spl::shared_ptr get_proxy(const spl::shared_ptr& video_channel, int render_layer) const { auto producer = spl::make_shared_ptr(video_channel->stage().foreground(render_layer).get()); return get_proxy(producer); } spl::shared_ptr get_or_create_proxy(const spl::shared_ptr& video_channel, const frame_producer_dependencies& dependencies, int render_layer, const std::wstring& filename) const { using namespace boost::filesystem; auto found = find_record(filename); if (!found) return cg_proxy::empty(); auto producer = spl::make_shared_ptr(video_channel->stage().foreground(render_layer).get()); auto current_producer_name = producer->name(); bool create_new = current_producer_name != found->name || !found->reusable_producer_instance; if (create_new) { diagnostics::scoped_call_context save; diagnostics::call_context::for_thread().video_channel = video_channel->index(); diagnostics::call_context::for_thread().layer = render_layer; producer = found->producer_factory(dependencies, filename); video_channel->stage().load(render_layer, producer); video_channel->stage().play(render_layer); } return found->proxy_factory(producer); } std::string read_meta_info(const std::wstring& filename) const { using namespace boost::filesystem; auto basepath = path(env::template_folder()) / path(filename); std::lock_guard lock(mutex_); for (auto& rec : records_by_extension_) { auto p = path(basepath.wstring() + rec.first); auto found = find_case_insensitive(p.wstring()); if (found) return rec.second.info_extractor(*found); } CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L"No meta info extractor for " + filename)); } bool is_cg_extension(const std::wstring& extension) const { std::lock_guard lock(mutex_); return records_by_extension_.find(extension) != records_by_extension_.end(); } std::wstring get_cg_producer_name(const std::wstring& filename) const { auto record = find_record(filename); if (!record) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(filename + L" is not a cg template.")); return record->name; } private: boost::optional find_record(const std::wstring& filename) const { using namespace boost::filesystem; auto basepath = path(env::template_folder()) / path(filename); std::lock_guard lock(mutex_); for (auto& rec : records_by_extension_) { auto p = path(basepath.wstring() + rec.first); if (find_case_insensitive(p.wstring())) return rec.second; } auto protocol = caspar::protocol_split(filename).at(0); if (!protocol.empty()) { auto ext = path(filename).extension().wstring(); for (auto& rec : records_by_extension_) { if (rec.first == ext) return rec.second; } } // TODO (fix): This is a hack to allow query params. for (auto& rec : records_by_extension_) { if (rec.first == L".html") return rec.second; } return boost::none; } }; cg_producer_registry::cg_producer_registry() : impl_(new impl) { } void cg_producer_registry::register_cg_producer(std::wstring cg_producer_name, std::set file_extensions, meta_info_extractor info_extractor, cg_proxy_factory proxy_factory, cg_producer_factory producer_factory, bool reusable_producer_instance) { impl_->register_cg_producer(std::move(cg_producer_name), std::move(file_extensions), std::move(info_extractor), std::move(proxy_factory), std::move(producer_factory), reusable_producer_instance); } spl::shared_ptr cg_producer_registry::create_producer(const frame_producer_dependencies& dependencies, const std::wstring& filename) const { return impl_->create_producer(dependencies, filename); } spl::shared_ptr cg_producer_registry::get_proxy(const spl::shared_ptr& producer) const { return impl_->get_proxy(producer); } spl::shared_ptr cg_producer_registry::get_proxy(const spl::shared_ptr& video_channel, int render_layer) const { return impl_->get_proxy(video_channel, render_layer); } spl::shared_ptr cg_producer_registry::get_or_create_proxy(const spl::shared_ptr& video_channel, const frame_producer_dependencies& dependencies, int render_layer, const std::wstring& filename) const { return impl_->get_or_create_proxy(video_channel, dependencies, render_layer, filename); } std::string cg_producer_registry::read_meta_info(const std::wstring& filename) const { return impl_->read_meta_info(filename); } bool cg_producer_registry::is_cg_extension(const std::wstring& extension) const { return impl_->is_cg_extension(extension); } std::wstring cg_producer_registry::get_cg_producer_name(const std::wstring& filename) const { return impl_->get_cg_producer_name(filename); } void init_cg_proxy_as_producer(core::module_dependencies dependencies) {} }} // namespace caspar::core server-2.2.0-stable/src/core/producer/cg_proxy.h000066400000000000000000000101621341175263200216420ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "frame_producer.h" #include #include #include #include #include namespace caspar { namespace core { class cg_proxy { public: static const unsigned int DEFAULT_LAYER = 9999; virtual ~cg_proxy() {} virtual void add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& start_from_label = L"", const std::wstring& data = L"") = 0; virtual void remove(int layer) = 0; virtual void play(int layer) = 0; virtual void stop(int layer, unsigned int mix_out_duration) = 0; virtual void next(int layer) = 0; virtual void update(int layer, const std::wstring& data) = 0; virtual std::wstring invoke(int layer, const std::wstring& label) = 0; static const spl::shared_ptr& empty(); }; typedef std::function(const spl::shared_ptr& producer)> cg_proxy_factory; typedef std::function(const frame_producer_dependencies& dependencies, const std::wstring& filename)> cg_producer_factory; typedef std::function meta_info_extractor; class cg_producer_registry : boost::noncopyable { public: cg_producer_registry(); void register_cg_producer(std::wstring cg_producer_name, std::set file_extensions, meta_info_extractor info_extractor, cg_proxy_factory proxy_factory, cg_producer_factory producer_factory, bool reusable_producer_instance); spl::shared_ptr create_producer(const frame_producer_dependencies& dependencies, const std::wstring& filename) const; spl::shared_ptr get_proxy(const spl::shared_ptr& producer) const; spl::shared_ptr get_proxy(const spl::shared_ptr& video_channel, int render_layer) const; spl::shared_ptr get_or_create_proxy(const spl::shared_ptr& video_channel, const frame_producer_dependencies& dependencies, int render_layer, const std::wstring& filename) const; std::string read_meta_info(const std::wstring& filename) const; bool is_cg_extension(const std::wstring& extension) const; std::wstring get_cg_producer_name(const std::wstring& filename) const; private: struct impl; spl::shared_ptr impl_; }; void init_cg_proxy_as_producer(core::module_dependencies dependencies); }} // namespace caspar::core server-2.2.0-stable/src/core/producer/color/000077500000000000000000000000001341175263200207555ustar00rootroot00000000000000server-2.2.0-stable/src/core/producer/color/color_producer.cpp000066400000000000000000000132201341175263200245000ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../../StdAfx.h" #include "color_producer.h" #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { draw_frame create_color_frame(void* tag, const spl::shared_ptr& frame_factory, const std::vector& values) { core::pixel_format_desc desc(pixel_format::bgra); desc.planes.push_back(core::pixel_format_desc::plane(static_cast(values.size()), 1, 4)); auto frame = frame_factory->create_frame(tag, desc); for (int i = 0; i < values.size(); ++i) *reinterpret_cast(frame.image_data(0).begin() + (i * 4)) = values.at(i); return core::draw_frame(std::move(frame)); } draw_frame create_color_frame(void* tag, const spl::shared_ptr& frame_factory, uint32_t value) { std::vector values = {value}; return create_color_frame(tag, frame_factory, values); } draw_frame create_color_frame(void* tag, const spl::shared_ptr& frame_factory, const std::vector& strs) { std::vector values(strs.size()); for (int i = 0; i < values.size(); ++i) { if (!try_get_color(strs.at(i), values.at(i))) CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"Invalid color: " + strs.at(i))); } return create_color_frame(tag, frame_factory, values); } class color_producer : public frame_producer { monitor::state state_; const std::wstring color_str_; draw_frame frame_; public: color_producer(const spl::shared_ptr& frame_factory, uint32_t value) : color_str_(L"") , frame_(create_color_frame(this, frame_factory, value)) { CASPAR_LOG(info) << print() << L" Initialized"; } color_producer(const spl::shared_ptr& frame_factory, const std::vector& colors) : color_str_(boost::join(colors, L", ")) , frame_(create_color_frame(this, frame_factory, colors)) { CASPAR_LOG(info) << print() << L" Initialized"; } // frame_producer draw_frame receive_impl(int nb_samples) override { CASPAR_SCOPE_EXIT { state_["color"] = color_str_; }; return frame_; } std::wstring print() const override { return L"color[" + color_str_ + L"]"; } std::wstring name() const override { return L"color"; } core::monitor::state state() const override { return state_; } }; std::wstring get_hex_color(const std::wstring& str) { if (str.at(0) == '#') return str.length() == 7 ? L"#FF" + str.substr(1) : str; std::wstring col_str = boost::to_upper_copy(str); if (col_str == L"EMPTY") return L"#00000000"; if (col_str == L"BLACK") return L"#FF000000"; if (col_str == L"WHITE") return L"#FFFFFFFF"; if (col_str == L"RED") return L"#FFFF0000"; if (col_str == L"GREEN") return L"#FF00FF00"; if (col_str == L"BLUE") return L"#FF0000FF"; if (col_str == L"ORANGE") return L"#FFFFA500"; if (col_str == L"YELLOW") return L"#FFFFFF00"; if (col_str == L"BROWN") return L"#FFA52A2A"; if (col_str == L"GRAY") return L"#FF808080"; if (col_str == L"TEAL") return L"#FF008080"; return str; } bool try_get_color(const std::wstring& str, uint32_t& value) { auto color_str = get_hex_color(str); if (color_str.length() != 9 || color_str[0] != '#') return false; std::wstringstream ss(color_str.substr(1)); if (!(ss >> std::hex >> value) || !ss.eof()) return false; return true; } spl::shared_ptr create_color_producer(const spl::shared_ptr& frame_factory, uint32_t value) { return spl::make_shared(frame_factory, value); } spl::shared_ptr create_color_producer(const spl::shared_ptr& frame_factory, const std::vector& params) { if (params.size() < 0) return core::frame_producer::empty(); uint32_t value = 0; if (!try_get_color(params.at(0), value)) return core::frame_producer::empty(); std::vector colors; for (auto& param : params) { if (try_get_color(param, value)) colors.push_back(param); } return spl::make_shared(frame_factory, colors); } }} // namespace caspar::core server-2.2.0-stable/src/core/producer/color/color_producer.h000066400000000000000000000032551341175263200241540ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include namespace caspar { namespace core { bool try_get_color(const std::wstring& str, uint32_t& value); spl::shared_ptr create_color_producer(const spl::shared_ptr& frame_factory, uint32_t value); spl::shared_ptr create_color_producer(const spl::shared_ptr& frame_factory, const std::vector& params); draw_frame create_color_frame(void* tag, const spl::shared_ptr& frame_factory, uint32_t value); draw_frame create_color_frame(void* tag, const spl::shared_ptr& frame_factory, const std::wstring& color); }} // namespace caspar::core server-2.2.0-stable/src/core/producer/frame_producer.cpp000066400000000000000000000236431341175263200233500ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../StdAfx.h" #include "cg_proxy.h" #include "frame_producer.h" #include "../frame/draw_frame.h" #include "../frame/frame_transform.h" #include "color/color_producer.h" #include "route/route_producer.h" #include "separated/separated_producer.h" #include #include #include #include #include #include namespace caspar { namespace core { struct frame_producer_registry::impl { std::vector producer_factories; }; frame_producer_registry::frame_producer_registry() : impl_(new impl()) { } void frame_producer_registry::register_producer_factory(std::wstring name, const producer_factory_t& factory) { impl_->producer_factories.push_back(factory); } frame_producer_dependencies::frame_producer_dependencies( const spl::shared_ptr& frame_factory, const std::vector>& channels, const video_format_desc& format_desc, const spl::shared_ptr producer_registry, const spl::shared_ptr cg_registry) : frame_factory(frame_factory) , channels(channels) , format_desc(format_desc) , producer_registry(producer_registry) , cg_registry(cg_registry) { } const spl::shared_ptr& frame_producer::empty() { class empty_frame_producer : public frame_producer { public: empty_frame_producer() {} draw_frame receive_impl(int nb_samples) override { return draw_frame{}; } uint32_t nb_frames() const override { return 0; } std::wstring print() const override { return L"empty"; } std::wstring name() const override { return L"empty"; } uint32_t frame_number() const override { return 0; } std::future call(const std::vector& params) override { CASPAR_LOG(warning) << L" Cannot call on empty frame_producer"; return make_ready_future(std::wstring(L"")); } draw_frame last_frame() { return draw_frame{}; } }; static spl::shared_ptr producer = spl::make_shared(); return producer; } std::shared_ptr& producer_destroyer() { static auto destroyer = [] { auto result = std::make_shared(L"Producer destroyer"); result->set_capacity(std::numeric_limits::max()); return result; }(); ; return destroyer; } std::atomic& destroy_producers_in_separate_thread() { static std::atomic state; return state; } void destroy_producers_synchronously() { destroy_producers_in_separate_thread() = false; // Join destroyer, executing rest of producers in queue synchronously. producer_destroyer().reset(); } class destroy_producer_proxy : public frame_producer { std::shared_ptr producer_; public: destroy_producer_proxy(spl::shared_ptr&& producer) : producer_(std::move(producer)) { destroy_producers_in_separate_thread() = true; } virtual ~destroy_producer_proxy() { if (producer_ == core::frame_producer::empty() || !destroy_producers_in_separate_thread()) return; auto destroyer = producer_destroyer(); if (!destroyer) return; CASPAR_VERIFY(destroyer->size() < 8); auto producer = new spl::shared_ptr(std::move(producer_)); destroyer->begin_invoke([=] { std::unique_ptr> pointer_guard(producer); auto str = (*producer)->print(); try { if (!producer->unique()) CASPAR_LOG(debug) << str << L" Not destroyed on asynchronous destruction thread: " << producer->use_count(); else CASPAR_LOG(debug) << str << L" Destroying on asynchronous destruction thread."; } catch (...) { } try { pointer_guard.reset(); CASPAR_LOG(info) << str << L" Destroyed."; } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } }); } draw_frame receive_impl(int nb_samples) override { return producer_->receive(nb_samples); } std::wstring print() const override { return producer_->print(); } std::wstring name() const override { return producer_->name(); } std::future call(const std::vector& params) override { return producer_->call(params); } void leading_producer(const spl::shared_ptr& producer) override { return producer_->leading_producer(producer); } uint32_t frame_number() const override { return producer_->frame_number(); } uint32_t nb_frames() const override { return producer_->nb_frames(); } draw_frame last_frame() override { return producer_->last_frame(); } core::monitor::state state() const override { return producer_->state(); } }; spl::shared_ptr create_destroy_proxy(spl::shared_ptr producer) { return spl::make_shared(std::move(producer)); } spl::shared_ptr do_create_producer(const frame_producer_dependencies& dependencies, const std::vector& params, const std::vector& factories, bool throw_on_fail = false) { if (params.empty()) { CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("params cannot be empty")); } auto producer = frame_producer::empty(); if (producer == frame_producer::empty()) { producer = create_color_producer(dependencies.frame_factory, params); } if (producer != frame_producer::empty()) { return producer; } if (producer == frame_producer::empty()) { producer = create_route_producer(dependencies, params); } if (producer != frame_producer::empty()) { return producer; } std::any_of(factories.begin(), factories.end(), [&](const producer_factory_t& factory) -> bool { try { producer = factory(dependencies, params); } catch (user_error&) { throw; } catch (...) { if (throw_on_fail) throw; else CASPAR_LOG_CURRENT_EXCEPTION(); } return producer != frame_producer::empty(); }); return producer; } spl::shared_ptr frame_producer_registry::create_producer(const frame_producer_dependencies& dependencies, const std::vector& params) const { auto& producer_factories = impl_->producer_factories; auto producer = do_create_producer(dependencies, params, producer_factories); auto key_producer = frame_producer::empty(); if (!params.empty() && !boost::contains(params.at(0), L"://")) { try // to find a key file. { auto params_copy = params; if (params_copy.size() > 0) { params_copy[0] += L"_A"; key_producer = do_create_producer(dependencies, params_copy, producer_factories); if (key_producer == frame_producer::empty()) { params_copy[0] += L"LPHA"; key_producer = do_create_producer(dependencies, params_copy, producer_factories); } } } catch (...) { } } if (producer != frame_producer::empty() && key_producer != frame_producer::empty()) return create_separated_producer(producer, key_producer); if (producer == frame_producer::empty()) { std::wstring str; for (auto& param : params) str += param + L" "; CASPAR_THROW_EXCEPTION(file_not_found() << msg_info("No match found for supplied commands. Check syntax.") << arg_value_info(u8(str))); } return producer; } spl::shared_ptr frame_producer_registry::create_producer(const frame_producer_dependencies& dependencies, const std::wstring& params) const { std::wstringstream iss(params); std::vector tokens; typedef std::istream_iterator> iterator; std::copy(iterator(iss), iterator(), std::back_inserter(tokens)); return create_producer(dependencies, tokens); } }} // namespace caspar::core server-2.2.0-stable/src/core/producer/frame_producer.h000066400000000000000000000113661341175263200230140ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "../fwd.h" #include "../monitor/monitor.h" #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { class frame_producer { frame_producer(const frame_producer&); frame_producer& operator=(const frame_producer&); uint32_t frame_number_ = 0; core::draw_frame frame_; public: static const spl::shared_ptr& empty(); frame_producer(core::draw_frame frame) : frame_(std::move(frame)) { } frame_producer() {} virtual ~frame_producer() {} draw_frame receive(int nb_samples) { auto frame = receive_impl(nb_samples); if (frame) { frame_number_ += 1; frame_ = frame; } return frame; } virtual draw_frame receive_impl(int nb_samples) { return core::draw_frame{}; }; virtual std::future call(const std::vector& params) { CASPAR_THROW_EXCEPTION(not_implemented()); } virtual core::monitor::state state() const { static const monitor::state empty; return empty; } virtual std::wstring print() const { return L"frame_producer"; } virtual std::wstring name() const { return L"frame_producer"; } virtual uint32_t frame_number() const { return frame_number_; } virtual uint32_t nb_frames() const { return std::numeric_limits::max(); } virtual draw_frame last_frame() { if (!frame_) { frame_ = receive_impl(0); } return core::draw_frame::still(frame_); } virtual void leading_producer(const spl::shared_ptr&) {} virtual spl::shared_ptr following_producer() const { return core::frame_producer::empty(); } }; class frame_producer_registry; struct frame_producer_dependencies { spl::shared_ptr frame_factory; std::vector> channels; video_format_desc format_desc; spl::shared_ptr producer_registry; spl::shared_ptr cg_registry; frame_producer_dependencies(const spl::shared_ptr& frame_factory, const std::vector>& channels, const video_format_desc& format_desc, const spl::shared_ptr producer_registry, const spl::shared_ptr cg_registry); }; typedef std::function(const frame_producer_dependencies&, const std::vector&)> producer_factory_t; class frame_producer_registry : boost::noncopyable { public: frame_producer_registry(); void register_producer_factory(std::wstring name, const producer_factory_t& factoryr); // Not thread-safe. spl::shared_ptr create_producer(const frame_producer_dependencies&, const std::vector& params) const; spl::shared_ptr create_producer(const frame_producer_dependencies&, const std::wstring& params) const; private: struct impl; spl::shared_ptr impl_; }; spl::shared_ptr create_destroy_proxy(spl::shared_ptr producer); void destroy_producers_synchronously(); }} // namespace caspar::core server-2.2.0-stable/src/core/producer/layer.cpp000066400000000000000000000120311341175263200214540ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../StdAfx.h" #include "layer.h" #include "frame_producer.h" #include "../frame/draw_frame.h" #include "../frame/frame_transform.h" #include "../video_format.h" #include #include #include namespace caspar { namespace core { struct layer::impl { monitor::state state_; spl::shared_ptr foreground_ = frame_producer::empty(); spl::shared_ptr background_ = frame_producer::empty(); boost::optional auto_play_delta_; bool paused_ = false; public: void pause() { paused_ = true; } void resume() { paused_ = false; } void load(spl::shared_ptr producer, bool preview, const boost::optional& auto_play_delta) { background_ = std::move(producer); auto_play_delta_ = auto_play_delta; if (auto_play_delta_ && foreground_ == frame_producer::empty()) { play(); } else if (preview) { foreground_ = std::move(background_); background_ = frame_producer::empty(); paused_ = true; } } void play() { if (background_ != frame_producer::empty()) { if (!paused_) { background_->leading_producer(foreground_); } else { background_->leading_producer(spl::make_shared(foreground_->last_frame())); } foreground_ = std::move(background_); background_ = frame_producer::empty(); auto_play_delta_.reset(); } paused_ = false; } void stop() { foreground_ = frame_producer::empty(); auto_play_delta_.reset(); } draw_frame receive(const video_format_desc& format_desc, int nb_samples) { try { if (foreground_->following_producer() != core::frame_producer::empty()) { foreground_ = foreground_->following_producer(); } if (auto_play_delta_) { auto time = static_cast(foreground_->frame_number()); auto duration = static_cast(foreground_->nb_frames()); auto frames_left = duration - time - static_cast(*auto_play_delta_); if (frames_left < 1) { play(); } } auto frame = paused_ ? core::draw_frame{} : foreground_->receive(nb_samples); if (!frame) { frame = foreground_->last_frame(); } state_ = {}; state_["foreground"] = foreground_->state(); state_["foreground"]["producer"] = foreground_->name(); state_["foreground"]["paused"] = paused_; state_["background"] = background_->state(); state_["background"]["producer"] = background_->name(); return frame; } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); stop(); return draw_frame{}; } } }; layer::layer() : impl_(new impl()) { } layer::layer(layer&& other) : impl_(std::move(other.impl_)) { } layer& layer::operator=(layer&& other) { impl_ = std::move(other.impl_); return *this; } void layer::swap(layer& other) { impl_.swap(other.impl_); } void layer::load(spl::shared_ptr frame_producer, bool preview, const boost::optional& auto_play_delta) { return impl_->load(std::move(frame_producer), preview, auto_play_delta); } void layer::play() { impl_->play(); } void layer::pause() { impl_->pause(); } void layer::resume() { impl_->resume(); } void layer::stop() { impl_->stop(); } draw_frame layer::receive(const video_format_desc& format_desc, int nb_samples) { return impl_->receive(format_desc, nb_samples); } spl::shared_ptr layer::foreground() const { return impl_->foreground_; } spl::shared_ptr layer::background() const { return impl_->background_; } core::monitor::state layer::state() const { return impl_->state_; } }} // namespace caspar::core server-2.2.0-stable/src/core/producer/layer.h000066400000000000000000000035041341175263200211260ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "frame_producer.h" #include "../fwd.h" #include "../monitor/monitor.h" #include #include #include #include namespace caspar { namespace core { class layer final { layer(const layer&); layer& operator=(const layer&); public: explicit layer(); layer(layer&& other); layer& operator=(layer&& other); void swap(layer& other); void load(spl::shared_ptr producer, bool preview, const boost::optional& auto_play_delta = boost::optional()); void play(); void pause(); void resume(); void stop(); draw_frame receive(const video_format_desc& format_desc, int nb_samples); core::monitor::state state() const; spl::shared_ptr foreground() const; spl::shared_ptr background() const; private: struct impl; spl::shared_ptr impl_; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/producer/route/000077500000000000000000000000001341175263200207755ustar00rootroot00000000000000server-2.2.0-stable/src/core/producer/route/route_producer.cpp000066400000000000000000000110571341175263200245460ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "route_producer.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { class route_producer : public frame_producer { spl::shared_ptr graph_; tbb::concurrent_bounded_queue buffer_; caspar::timer produce_timer_; caspar::timer consume_timer_; std::shared_ptr route_; boost::signals2::scoped_connection connection_; core::draw_frame frame_; public: route_producer(std::shared_ptr route, int buffer) : route_(route) , connection_(route_->signal.connect([this](const core::draw_frame& frame) { if (!buffer_.try_push(frame)) { graph_->set_tag(diagnostics::tag_severity::WARNING, "dropped-frame"); } graph_->set_value("produce-time", produce_timer_.elapsed() * route_->format_desc.fps * 0.5); produce_timer_.restart(); })) { buffer_.set_capacity(buffer > 0 ? buffer : route->format_desc.field_count); graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f)); graph_->set_color("produce-time", caspar::diagnostics::color(0.0f, 1.0f, 0.0f)); graph_->set_color("consume-time", caspar::diagnostics::color(1.0f, 0.4f, 0.0f, 0.8f)); graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f)); graph_->set_text(print()); diagnostics::register_graph(graph_); CASPAR_LOG(debug) << print() << L" Initialized"; } draw_frame last_frame() override { if (!frame_) { buffer_.try_pop(frame_); } return core::draw_frame::still(frame_); } draw_frame receive_impl(int nb_samples) override { core::draw_frame frame; if (!buffer_.try_pop(frame)) { graph_->set_tag(diagnostics::tag_severity::WARNING, "late-frame"); } else { frame_ = frame; } graph_->set_value("consume-time", consume_timer_.elapsed() * route_->format_desc.fps * 0.5); consume_timer_.restart(); return frame; } std::wstring print() const override { return L"route[" + route_->name + L"]"; } std::wstring name() const override { return L"route"; } }; spl::shared_ptr create_route_producer(const core::frame_producer_dependencies& dependencies, const std::vector& params) { static boost::wregex expr(L"route://(?\\d+)(-(?\\d+))?", boost::regex::icase); boost::wsmatch what; if (params.empty() || !boost::regex_match(params.at(0), what, expr)) { return core::frame_producer::empty(); } auto channel = boost::lexical_cast(what["CHANNEL"].str()); auto layer = what["LAYER"].matched ? boost::lexical_cast(what["LAYER"].str()) : -1; auto channel_it = boost::find_if(dependencies.channels, [=](spl::shared_ptr ch) { return ch->index() == channel; }); if (channel_it == dependencies.channels.end()) { CASPAR_THROW_EXCEPTION(user_error() << msg_info(L"No channel with id " + boost::lexical_cast(channel))); } auto buffer = get_param(L"BUFFER", params, 0); return spl::make_shared((*channel_it)->route(layer), buffer); } }} // namespace caspar::core server-2.2.0-stable/src/core/producer/route/route_producer.h000066400000000000000000000023141341175263200242070ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "../../video_format.h" #include #include #include namespace caspar { namespace core { spl::shared_ptr create_route_producer(const core::frame_producer_dependencies& dependencies, const std::vector& params); }} // namespace caspar::coreserver-2.2.0-stable/src/core/producer/separated/000077500000000000000000000000001341175263200216075ustar00rootroot00000000000000server-2.2.0-stable/src/core/producer/separated/separated_producer.cpp000066400000000000000000000064611341175263200261750ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../../StdAfx.h" #include "separated_producer.h" #include #include #include #include #include #include namespace caspar { namespace core { class separated_producer : public frame_producer { monitor::state state_; spl::shared_ptr fill_producer_; spl::shared_ptr key_producer_; draw_frame fill_; draw_frame key_; public: explicit separated_producer(const spl::shared_ptr& fill, const spl::shared_ptr& key) : fill_producer_(fill) , key_producer_(key) { CASPAR_LOG(debug) << print() << L" Initialized"; } // frame_producer draw_frame last_frame() override { return draw_frame::mask(fill_producer_->last_frame(), key_producer_->last_frame()); } draw_frame receive_impl(int nb_samples) override { CASPAR_SCOPE_EXIT { state_ = fill_producer_->state(); state_["keyer"] = key_producer_->state(); }; if (!fill_) { fill_ = fill_producer_->receive(nb_samples); } if (!key_) { key_ = key_producer_->receive(nb_samples); } if (!fill_ || !key_) { return core::draw_frame{}; } auto frame = draw_frame::mask(fill_, key_); fill_ = draw_frame{}; key_ = draw_frame{}; return frame; } uint32_t frame_number() const override { return fill_producer_->frame_number(); } uint32_t nb_frames() const override { return std::min(fill_producer_->nb_frames(), key_producer_->nb_frames()); } std::wstring print() const override { return L"separated[fill:" + fill_producer_->print() + L"|key[" + key_producer_->print() + L"]]"; } std::future call(const std::vector& params) override { key_producer_->call(params); return fill_producer_->call(params); } std::wstring name() const override { return L"separated"; } core::monitor::state state() const override { return state_; } }; spl::shared_ptr create_separated_producer(const spl::shared_ptr& fill, const spl::shared_ptr& key) { return spl::make_shared(fill, key); } }} // namespace caspar::core server-2.2.0-stable/src/core/producer/separated/separated_producer.h000066400000000000000000000022171341175263200256350ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include namespace caspar { namespace core { spl::shared_ptr create_separated_producer(const spl::shared_ptr& fill, const spl::shared_ptr& key); }} // namespace caspar::coreserver-2.2.0-stable/src/core/producer/stage.cpp000066400000000000000000000262651341175263200214610ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../StdAfx.h" #include "stage.h" #include "layer.h" #include "../frame/draw_frame.h" #include "../frame/frame_factory.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { struct stage::impl : public std::enable_shared_from_this { int channel_index_; spl::shared_ptr graph_; monitor::state state_; std::map layers_; std::map tweens_; executor executor_{L"stage " + boost::lexical_cast(channel_index_)}; public: impl(int channel_index, spl::shared_ptr graph) : channel_index_(channel_index) , graph_(std::move(graph)) { } std::map operator()(const video_format_desc& format_desc, int nb_samples) { return executor_.invoke([=] { std::map frames; try { for (auto& t : tweens_) t.second.tick(1); for (auto& p : layers_) { auto& layer = p.second; auto& tween = tweens_[p.first]; frames[p.first] = draw_frame::push(layer.receive(format_desc, nb_samples), tween.fetch()); } monitor::state state; for (auto& p : layers_) { state["layer"][p.first] = p.second.state(); } state_ = std::move(state); } catch (...) { layers_.clear(); CASPAR_LOG_CURRENT_EXCEPTION(); } return frames; }); } layer& get_layer(int index) { auto it = layers_.find(index); if (it == std::end(layers_)) { it = layers_.emplace(index, layer()).first; } return it->second; } std::future apply_transforms(const std::vector>& transforms) { return executor_.begin_invoke([=] { for (auto& transform : transforms) { auto& tween = tweens_[std::get<0>(transform)]; auto src = tween.fetch(); auto dst = std::get<1>(transform)(tween.dest()); tweens_[std::get<0>(transform)] = tweened_transform(src, dst, std::get<2>(transform), std::get<3>(transform)); } }); } std::future apply_transform(int index, const stage::transform_func_t& transform, unsigned int mix_duration, const tweener& tween) { return executor_.begin_invoke([=] { auto src = tweens_[index].fetch(); auto dst = transform(src); tweens_[index] = tweened_transform(src, dst, mix_duration, tween); }); } std::future clear_transforms(int index) { return executor_.begin_invoke([=] { tweens_.erase(index); }); } std::future clear_transforms() { return executor_.begin_invoke([=] { tweens_.clear(); }); } std::future get_current_transform(int index) { return executor_.begin_invoke([=] { return tweens_[index].fetch(); }); } std::future load(int index, const spl::shared_ptr& producer, bool preview, const boost::optional& auto_play_delta) { return executor_.begin_invoke([=] { get_layer(index).load(producer, preview, auto_play_delta); }); } std::future pause(int index) { return executor_.begin_invoke([=] { get_layer(index).pause(); }); } std::future resume(int index) { return executor_.begin_invoke([=] { get_layer(index).resume(); }); } std::future play(int index) { return executor_.begin_invoke([=] { get_layer(index).play(); }); } std::future stop(int index) { return executor_.begin_invoke([=] { get_layer(index).stop(); }); } std::future clear(int index) { return executor_.begin_invoke([=] { layers_.erase(index); }); } std::future clear() { return executor_.begin_invoke([=] { layers_.clear(); }); } std::future swap_layers(stage& other, bool swap_transforms) { auto other_impl = other.impl_; if (other_impl.get() == this) { return make_ready_future(); } auto func = [=] { auto layers = layers_ | boost::adaptors::map_values; auto other_layers = other_impl->layers_ | boost::adaptors::map_values; std::swap(layers_, other_impl->layers_); if (swap_transforms) std::swap(tweens_, other_impl->tweens_); }; return invoke_both(other, func); } std::future swap_layer(int index, int other_index, bool swap_transforms) { return executor_.begin_invoke([=] { std::swap(get_layer(index), get_layer(other_index)); if (swap_transforms) std::swap(tweens_[index], tweens_[other_index]); }); } std::future swap_layer(int index, int other_index, stage& other, bool swap_transforms) { auto other_impl = other.impl_; if (other_impl.get() == this) return swap_layer(index, other_index, swap_transforms); else { auto func = [=] { auto& my_layer = get_layer(index); auto& other_layer = other_impl->get_layer(other_index); std::swap(my_layer, other_layer); if (swap_transforms) { auto& my_tween = tweens_[index]; auto& other_tween = other_impl->tweens_[other_index]; std::swap(my_tween, other_tween); } }; return invoke_both(other, func); } } std::future invoke_both(stage& other, std::function func) { auto other_impl = other.impl_; if (other_impl->channel_index_ < channel_index_) { return other_impl->executor_.begin_invoke([=] { executor_.invoke(func); }); } return executor_.begin_invoke([=] { other_impl->executor_.invoke(func); }); } std::future> foreground(int index) { return executor_.begin_invoke( [=]() -> std::shared_ptr { return get_layer(index).foreground(); }); } std::future> background(int index) { return executor_.begin_invoke( [=]() -> std::shared_ptr { return get_layer(index).background(); }); } std::future call(int index, const std::vector& params) { return flatten(executor_.begin_invoke([=] { return get_layer(index).foreground()->call(params).share(); })); } }; stage::stage(int channel_index, spl::shared_ptr graph) : impl_(new impl(channel_index, std::move(graph))) { } std::future stage::call(int index, const std::vector& params) { return impl_->call(index, params); } std::future stage::apply_transforms(const std::vector& transforms) { return impl_->apply_transforms(transforms); } std::future stage::apply_transform(int index, const std::function& transform, unsigned int mix_duration, const tweener& tween) { return impl_->apply_transform(index, transform, mix_duration, tween); } std::future stage::clear_transforms(int index) { return impl_->clear_transforms(index); } std::future stage::clear_transforms() { return impl_->clear_transforms(); } std::future stage::get_current_transform(int index) { return impl_->get_current_transform(index); } std::future stage::load(int index, const spl::shared_ptr& producer, bool preview, const boost::optional& auto_play_delta) { return impl_->load(index, producer, preview, auto_play_delta); } std::future stage::pause(int index) { return impl_->pause(index); } std::future stage::resume(int index) { return impl_->resume(index); } std::future stage::play(int index) { return impl_->play(index); } std::future stage::stop(int index) { return impl_->stop(index); } std::future stage::clear(int index) { return impl_->clear(index); } std::future stage::clear() { return impl_->clear(); } std::future stage::swap_layers(stage& other, bool swap_transforms) { return impl_->swap_layers(other, swap_transforms); } std::future stage::swap_layer(int index, int other_index, bool swap_transforms) { return impl_->swap_layer(index, other_index, swap_transforms); } std::future stage::swap_layer(int index, int other_index, stage& other, bool swap_transforms) { return impl_->swap_layer(index, other_index, other, swap_transforms); } std::future> stage::foreground(int index) { return impl_->foreground(index); } std::future> stage::background(int index) { return impl_->background(index); } std::map stage::operator()(const video_format_desc& format_desc, int nb_samples) { return (*impl_)(format_desc, nb_samples); } core::monitor::state stage::state() const { return impl_->state_; } }} // namespace caspar::core server-2.2.0-stable/src/core/producer/stage.h000066400000000000000000000065341341175263200211230ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "../fwd.h" #include "../monitor/monitor.h" #include #include #include #include #include #include #include #include #include FORWARD2(caspar, diagnostics, class graph); namespace caspar { namespace core { class stage final { stage(const stage&); stage& operator=(const stage&); public: typedef std::function transform_func_t; typedef std::tuple transform_tuple_t; explicit stage(int channel_index, spl::shared_ptr graph); std::map operator()(const video_format_desc& format_desc, int nb_samples); std::future apply_transforms(const std::vector& transforms); std::future apply_transform(int index, const transform_func_t& transform, unsigned int mix_duration, const tweener& tween); std::future clear_transforms(int index); std::future clear_transforms(); std::future get_current_transform(int index); std::future load(int index, const spl::shared_ptr& producer, bool preview = false, const boost::optional& auto_play_delta = boost::optional()); std::future pause(int index); std::future resume(int index); std::future play(int index); std::future stop(int index); std::future call(int index, const std::vector& params); std::future clear(int index); std::future clear(); std::future swap_layers(stage& other, bool swap_transforms); std::future swap_layer(int index, int other_index, bool swap_transforms); std::future swap_layer(int index, int other_index, stage& other, bool swap_transforms); core::monitor::state state() const; std::future> foreground(int index); std::future> background(int index); private: struct impl; spl::shared_ptr impl_; }; }} // namespace caspar::coreserver-2.2.0-stable/src/core/producer/transition/000077500000000000000000000000001341175263200220315ustar00rootroot00000000000000server-2.2.0-stable/src/core/producer/transition/transition_producer.cpp000066400000000000000000000134431341175263200266370ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../../StdAfx.h" #include "transition_producer.h" #include "../../frame/draw_frame.h" #include "../../frame/frame_transform.h" #include "../../monitor/monitor.h" #include "../frame_producer.h" #include #include namespace caspar { namespace core { class transition_producer : public frame_producer { monitor::state state_; int current_frame_ = 0; core::draw_frame dst_; core::draw_frame src_; const transition_info info_; spl::shared_ptr dst_producer_ = frame_producer::empty(); spl::shared_ptr src_producer_ = frame_producer::empty(); public: transition_producer(const spl::shared_ptr& dest, const transition_info& info) : info_(info) , dst_producer_(dest) { update_state(); } // frame_producer core::draw_frame last_frame() override { CASPAR_SCOPE_EXIT { update_state(); }; auto src = src_producer_->last_frame(); auto dst = dst_producer_->last_frame(); return dst && current_frame_ >= info_.duration ? dst : src; } void leading_producer(const spl::shared_ptr& producer) override { src_producer_ = producer; } spl::shared_ptr following_producer() const override { return dst_ && current_frame_ >= info_.duration ? dst_producer_ : core::frame_producer::empty(); } void update_state() { state_ = dst_producer_->state(); state_["transition/frame"] = {current_frame_, info_.duration}; state_["transition/type"] = [&]() -> std::string { switch (info_.type) { case transition_type::mix: return "mix"; case transition_type::wipe: return "wipe"; case transition_type::slide: return "slide"; case transition_type::push: return "push"; case transition_type::cut: return "cut"; default: return "n/a"; } }(); } draw_frame receive_impl(int nb_samples) override { CASPAR_SCOPE_EXIT { update_state(); }; dst_ = dst_producer_->receive(nb_samples); if (!dst_) { dst_ = dst_producer_->last_frame(); } src_ = src_producer_->receive(nb_samples); if (!src_) { src_ = src_producer_->last_frame(); } if (!dst_) { return src_; } if (current_frame_ >= info_.duration) { return dst_; } current_frame_ += 1; return compose(dst_, src_); } uint32_t nb_frames() const override { return dst_producer_->nb_frames(); } uint32_t frame_number() const override { return dst_producer_->frame_number(); } std::wstring print() const override { return L"transition[" + src_producer_->print() + L"=>" + dst_producer_->print() + L"]"; } std::wstring name() const override { return L"transition"; } std::future call(const std::vector& params) override { return dst_producer_->call(params); } draw_frame compose(draw_frame dst_frame, draw_frame src_frame) const { if (info_.type == transition_type::cut) { return src_frame; } const double delta = info_.tweener(current_frame_, 0.0, 1.0, static_cast(info_.duration)); const double dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0; src_frame.transform().audio_transform.volume = 1.0 - delta; dst_frame.transform().audio_transform.volume = delta; if (info_.type == transition_type::mix) { dst_frame.transform().image_transform.opacity = delta; dst_frame.transform().image_transform.is_mix = true; src_frame.transform().image_transform.opacity = 1.0 - delta; src_frame.transform().image_transform.is_mix = true; } else if (info_.type == transition_type::slide) { dst_frame.transform().image_transform.fill_translation[0] = (-1.0 + delta) * dir; } else if (info_.type == transition_type::push) { dst_frame.transform().image_transform.fill_translation[0] = (-1.0 + delta) * dir; src_frame.transform().image_transform.fill_translation[0] = (0.0 + delta) * dir; } else if (info_.type == transition_type::wipe) { dst_frame.transform().image_transform.clip_scale[0] = delta; } return draw_frame::over(src_frame, dst_frame); } core::monitor::state state() const override { return state_; } }; spl::shared_ptr create_transition_producer(const spl::shared_ptr& destination, const transition_info& info) { return spl::make_shared(destination, info); } }} // namespace caspar::core server-2.2.0-stable/src/core/producer/transition/transition_producer.h000066400000000000000000000031641341175263200263030ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "../../fwd.h" #include "../../video_format.h" #include #include #include namespace caspar { namespace core { enum class transition_type { cut, mix, push, slide, wipe, count }; enum class transition_direction { from_left, from_right, count }; struct transition_info { int duration = 0; transition_direction direction = transition_direction::from_left; transition_type type = transition_type::cut; caspar::tweener tweener{L"linear"}; }; spl::shared_ptr create_transition_producer(const spl::shared_ptr& destination, const transition_info& info); }} // namespace caspar::core server-2.2.0-stable/src/core/video_channel.cpp000066400000000000000000000232111341175263200213150ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "StdAfx.h" #include "video_channel.h" #include "video_format.h" #include "consumer/output.h" #include "frame/draw_frame.h" #include "frame/frame.h" #include "frame/frame_factory.h" #include "frame/frame_transform.h" #include "mixer/mixer.h" #include "producer/stage.h" #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace core { struct video_channel::impl final { monitor::state state_; const int index_; mutable std::mutex format_desc_mutex_; core::video_format_desc format_desc_; const spl::shared_ptr graph_ = [](int index) { core::diagnostics::scoped_call_context save; core::diagnostics::call_context::for_thread().video_channel = index; return spl::make_shared(); }(index_); caspar::core::output output_; spl::shared_ptr image_mixer_; caspar::core::mixer mixer_; caspar::core::stage stage_; std::vector audio_cadence_ = format_desc_.audio_cadence; std::function tick_; std::map> routes_; std::mutex routes_mutex_; std::atomic abort_request_{false}; std::thread thread_; public: impl(int index, const core::video_format_desc& format_desc, std::unique_ptr image_mixer, std::function tick) : index_(index) , format_desc_(format_desc) , output_(graph_, format_desc, index) , image_mixer_(std::move(image_mixer)) , mixer_(index, graph_, image_mixer_) , stage_(index, graph_) , tick_(tick) { graph_->set_color("produce-time", caspar::diagnostics::color(0.0f, 1.0f, 0.0f)); graph_->set_color("mix-time", caspar::diagnostics::color(1.0f, 0.0f, 0.9f, 0.8f)); graph_->set_color("consume-time", caspar::diagnostics::color(1.0f, 0.4f, 0.0f, 0.8f)); graph_->set_color("frame-time", caspar::diagnostics::color(1.0f, 0.4f, 0.4f, 0.8f)); graph_->set_color("osc-time", caspar::diagnostics::color(0.3f, 0.4f, 0.0f, 0.8f)); graph_->set_text(print()); caspar::diagnostics::register_graph(graph_); CASPAR_LOG(info) << print() << " Successfully Initialized."; thread_ = std::thread([=] { #ifdef WIN32 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); #endif set_thread_name(L"channel-" + boost::lexical_cast(index_)); while (!abort_request_) { try { core::video_format_desc format_desc; int nb_samples; { std::lock_guard lock(format_desc_mutex_); format_desc = format_desc_; boost::range::rotate(audio_cadence_, std::end(audio_cadence_) - 1); nb_samples = audio_cadence_.front(); } caspar::timer frame_timer; // Produce caspar::timer produce_timer; auto stage_frames = stage_(format_desc, nb_samples); graph_->set_value("produce-time", produce_timer.elapsed() * format_desc.fps * 0.5); // Mix caspar::timer mix_timer; auto mixed_frame = mixer_(stage_frames, format_desc, format_desc.audio_cadence[0]); graph_->set_value("mix-time", mix_timer.elapsed() * format_desc.fps * 0.5); // Consume caspar::timer consume_timer; output_(std::move(mixed_frame), format_desc); graph_->set_value("consume-time", consume_timer.elapsed() * format_desc.fps * 0.5); graph_->set_value("frame-time", frame_timer.elapsed() * format_desc.fps * 0.5); { std::vector frames; std::lock_guard lock(routes_mutex_); for (auto& p : stage_frames) { frames.push_back(p.second); auto it = routes_.find(p.first); if (it != routes_.end()) { auto route = it->second.lock(); if (route) { route->signal(draw_frame::pop(p.second)); } } } auto it = routes_.find(-1); if (it != routes_.end()) { auto route = it->second.lock(); if (route) { route->signal(core::draw_frame(std::move(frames))); } } } monitor::state state = {}; state["stage"] = stage_.state(); state["mixer"] = mixer_.state(); state["output"] = output_.state(); state["framerate"] = {format_desc_.framerate.numerator(), format_desc_.framerate.denominator()}; state_ = state; caspar::timer osc_timer; tick_(state_); graph_->set_value("osc-time", osc_timer.elapsed() * format_desc.fps * 0.5); } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } } }); } ~impl() { CASPAR_LOG(info) << print() << " Uninitializing."; abort_request_ = true; thread_.join(); } std::shared_ptr route(int index = -1) { std::lock_guard lock(routes_mutex_); auto route = routes_[index].lock(); if (!route) { route = std::make_shared(); route->format_desc = format_desc_; route->name = boost::lexical_cast(index_); if (index != -1) { route->name += L"/" + boost::lexical_cast(index); } routes_[index] = route; } return route; } core::video_format_desc video_format_desc() const { std::lock_guard lock(format_desc_mutex_); return format_desc_; } void video_format_desc(const core::video_format_desc& format_desc) { std::lock_guard lock(format_desc_mutex_); format_desc_ = format_desc; audio_cadence_ = format_desc_.audio_cadence; stage_.clear(); } std::wstring print() const { return L"video_channel[" + boost::lexical_cast(index_) + L"|" + video_format_desc().name + L"]"; } int index() const { return index_; } }; video_channel::video_channel(int index, const core::video_format_desc& format_desc, std::unique_ptr image_mixer, std::function tick) : impl_(new impl(index, format_desc, std::move(image_mixer), tick)) { } video_channel::~video_channel() {} const stage& video_channel::stage() const { return impl_->stage_; } stage& video_channel::stage() { return impl_->stage_; } const mixer& video_channel::mixer() const { return impl_->mixer_; } mixer& video_channel::mixer() { return impl_->mixer_; } const output& video_channel::output() const { return impl_->output_; } output& video_channel::output() { return impl_->output_; } spl::shared_ptr video_channel::frame_factory() { return impl_->image_mixer_; } core::video_format_desc video_channel::video_format_desc() const { return impl_->video_format_desc(); } void core::video_channel::video_format_desc(const core::video_format_desc& format_desc) { impl_->video_format_desc(format_desc); } int video_channel::index() const { return impl_->index(); } core::monitor::state video_channel::state() const { return impl_->state_; } std::shared_ptr video_channel::route(int index) { return impl_->route(index); } }} // namespace caspar::core server-2.2.0-stable/src/core/video_channel.h000066400000000000000000000047721341175263200207750ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include "fwd.h" #include "video_format.h" #include "monitor/monitor.h" #include #include #include #include namespace caspar { namespace core { struct route { route() = default; route(const route&) = delete; route(route&&) = default; route& operator=(const route&) = delete; route& operator=(route&&) = default; boost::signals2::signal signal; video_format_desc format_desc; std::wstring name; }; class video_channel final { video_channel(const video_channel&); video_channel& operator=(const video_channel&); public: explicit video_channel(int index, const video_format_desc& format_desc, std::unique_ptr image_mixer, std::function on_tick); ~video_channel(); core::monitor::state state() const; const core::stage& stage() const; core::stage& stage(); const core::mixer& mixer() const; core::mixer& mixer(); const core::output& output() const; core::output& output(); core::video_format_desc video_format_desc() const; void video_format_desc(const core::video_format_desc& format_desc); spl::shared_ptr frame_factory(); int index() const; std::shared_ptr route(int index = -1); private: struct impl; spl::unique_ptr impl_; }; }} // namespace caspar::core server-2.2.0-stable/src/core/video_format.cpp000066400000000000000000000203271341175263200212020ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "StdAfx.h" #include "video_format.h" #include #include #include #include namespace caspar { namespace core { const std::vector format_descs = { {video_format::pal, 2, 720, 576, 1024, 576, 50000, 1000, L"PAL", {1920 / 2}}, {video_format::ntsc, 2, 720, 486, 720, 540, 60000, 1001, L"NTSC", {1602 / 2, 1601 / 2, 1602 / 2, 1601 / 2, 1602 / 2}}, {video_format::x576p2500, 1, 720, 576, 1024, 576, 25000, 1000, L"576p2500", {1920}}, {video_format::x720p2398, 1, 1280, 720, 1280, 720, 24000, 1001, L"720p2398", {2002}}, {video_format::x720p2400, 1, 1280, 720, 1280, 720, 24000, 1000, L"720p2400", {2000}}, {video_format::x720p2500, 1, 1280, 720, 1280, 720, 25000, 1000, L"720p2500", {1920}}, {video_format::x720p5000, 1, 1280, 720, 1280, 720, 50000, 1000, L"720p5000", {960}}, {video_format::x720p2997, 1, 1280, 720, 1280, 720, 30000, 1001, L"720p2997", {1602, 1601, 1602, 1601, 1602}}, {video_format::x720p5994, 1, 1280, 720, 1280, 720, 60000, 1001, L"720p5994", {801, 800, 801, 801, 801}}, {video_format::x720p3000, 1, 1280, 720, 1280, 720, 30000, 1000, L"720p3000", {1600}}, {video_format::x720p6000, 1, 1280, 720, 1280, 720, 60000, 1000, L"720p6000", {800}}, {video_format::x1080p2398, 1, 1920, 1080, 1920, 1080, 24000, 1001, L"1080p2398", {2002}}, {video_format::x1080p2400, 1, 1920, 1080, 1920, 1080, 24000, 1000, L"1080p2400", {2000}}, {video_format::x1080i5000, 2, 1920, 1080, 1920, 1080, 50000, 1000, L"1080i5000", {1920 / 2}}, {video_format::x1080i5994, 2, 1920, 1080, 1920, 1080, 60000, 1001, L"1080i5994", {1602 / 2, 1601 / 2, 1602 / 2, 1601 / 2, 1602 / 2}}, {video_format::x1080i6000, 2, 1920, 1080, 1920, 1080, 60000, 1000, L"1080i6000", {1600 / 2}}, {video_format::x1080p2500, 1, 1920, 1080, 1920, 1080, 25000, 1000, L"1080p2500", {1920}}, {video_format::x1080p2997, 1, 1920, 1080, 1920, 1080, 30000, 1001, L"1080p2997", {1602, 1601, 1602, 1601, 1602}}, {video_format::x1080p3000, 1, 1920, 1080, 1920, 1080, 30000, 1000, L"1080p3000", {1600}}, {video_format::x1080p5000, 1, 1920, 1080, 1920, 1080, 50000, 1000, L"1080p5000", {960}}, {video_format::x1080p5994, 1, 1920, 1080, 1920, 1080, 60000, 1001, L"1080p5994", {801, 800, 801, 801, 801}}, {video_format::x1080p6000, 1, 1920, 1080, 1920, 1080, 60000, 1000, L"1080p6000", {800}}, {video_format::x1556p2398, 1, 2048, 1556, 2048, 1556, 24000, 1001, L"1556p2398", {2002}}, {video_format::x1556p2400, 1, 2048, 1556, 2048, 1556, 24000, 1000, L"1556p2400", {2000}}, {video_format::x1556p2500, 1, 2048, 1556, 2048, 1556, 25000, 1000, L"1556p2500", {1920}}, {video_format::x2160p2398, 1, 3840, 2160, 3840, 2160, 24000, 1001, L"2160p2398", {2002}}, {video_format::x2160p2400, 1, 3840, 2160, 3840, 2160, 24000, 1000, L"2160p2400", {2000}}, {video_format::x2160p2500, 1, 3840, 2160, 3840, 2160, 25000, 1000, L"2160p2500", {1920}}, {video_format::x2160p2997, 1, 3840, 2160, 3840, 2160, 30000, 1001, L"2160p2997", {1602, 1601, 1602, 1601, 1602}}, {video_format::x2160p3000, 1, 3840, 2160, 3840, 2160, 30000, 1000, L"2160p3000", {1600}}, {video_format::x2160p5000, 1, 3840, 2160, 3840, 2160, 50000, 1000, L"2160p5000", {960}}, {video_format::x2160p5994, 1, 3840, 2160, 3840, 2160, 60000, 1001, L"2160p5994", {801, 800, 801, 801, 801}}, {video_format::x2160p6000, 1, 3840, 2160, 3840, 2160, 60000, 1000, L"2160p6000", {800}}, {video_format::invalid, 1, 0, 0, 0, 0, 1, 1, L"invalid", {1}}}; video_format_desc::video_format_desc(video_format format, int field_count, int width, int height, int square_width, int square_height, int time_scale, int duration, const std::wstring& name, const std::vector& audio_cadence) : format(format) , field_count(field_count) , width(width) , height(height) , square_width(square_width) , square_height(square_height) , fps(static_cast(time_scale) / static_cast(duration)) , framerate(time_scale, duration) , time_scale(time_scale) , duration(duration) , size(width * height * 4) , name(name) , audio_sample_rate(48000) , audio_cadence(audio_cadence) { } video_format_desc::video_format_desc(video_format format) : format(video_format::invalid) { *this = format_descs.at(static_cast(format)); } video_format_desc::video_format_desc(const std::wstring& name) : format(video_format::invalid) { *this = video_format_desc(video_format::invalid); for (auto it = std::begin(format_descs); it != std::end(format_descs) - 1; ++it) { if (boost::iequals(it->name, name)) { *this = *it; break; } } } bool operator==(const video_format_desc& lhs, const video_format_desc& rhs) { return lhs.format == rhs.format; } bool operator!=(const video_format_desc& lhs, const video_format_desc& rhs) { return !(lhs == rhs); } std::wostream& operator<<(std::wostream& out, const video_format_desc& format_desc) { out << format_desc.name.c_str(); return out; } std::vector find_audio_cadence(const boost::rational& framerate, bool log_quiet) { static std::map, std::vector> CADENCES_BY_FRAMERATE = [] { std::map, std::vector> result; for (core::video_format format : enum_constants()) { core::video_format_desc desc(format); boost::rational format_rate(desc.time_scale, desc.duration); result.insert(std::make_pair(format_rate, desc.audio_cadence)); } return result; }(); auto exact_match = CADENCES_BY_FRAMERATE.find(framerate); if (exact_match != CADENCES_BY_FRAMERATE.end()) return exact_match->second; boost::rational closest_framerate_diff = std::numeric_limits::max(); boost::rational closest_framerate = 0; for (auto format_framerate : CADENCES_BY_FRAMERATE | boost::adaptors::map_keys) { auto diff = boost::abs(framerate - format_framerate); if (diff < closest_framerate_diff) { closest_framerate_diff = diff; closest_framerate = format_framerate; } } if (log_quiet) CASPAR_LOG(debug) << "No exact audio cadence match found for framerate " << to_string(framerate) << "\nClosest match is " << to_string(closest_framerate) << "\nwhich is a " << to_string(closest_framerate_diff) << " difference."; else CASPAR_LOG(warning) << "No exact audio cadence match found for framerate " << to_string(framerate) << "\nClosest match is " << to_string(closest_framerate) << "\nwhich is a " << to_string(closest_framerate_diff) << " difference."; return CADENCES_BY_FRAMERATE[closest_framerate]; } }} // namespace caspar::core server-2.2.0-stable/src/core/video_format.h000066400000000000000000000064041341175263200206470ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include namespace caspar { namespace core { enum class video_format { pal, ntsc, x576p2500, x720p2500, x720p5000, x720p2398, x720p2400, x720p2997, x720p5994, x720p3000, x720p6000, x1080p2398, x1080p2400, x1080i5000, x1080i5994, x1080i6000, x1080p2500, x1080p2997, x1080p3000, x1080p5000, x1080p5994, x1080p6000, x1556p2398, x1556p2400, x1556p2500, x2160p2398, x2160p2400, x2160p2500, x2160p2997, x2160p3000, x2160p5000, x2160p5994, x2160p6000, invalid, count }; struct video_format_desc final { video_format format; int width; int height; int square_width; int square_height; int field_count; double fps; // actual framerate = duration/time_scale, e.g. i50 = 25 fps, p50 = 50 fps boost::rational framerate; int time_scale; int duration; std::size_t size; // frame size in bytes std::wstring name; // name of output format int audio_channels = 8; int audio_sample_rate; std::vector audio_cadence; // rotating optimal number of samples per frame video_format_desc(video_format format, int field_count, int width, int height, int square_width, int square_height, int time_scale, int duration, const std::wstring& name, const std::vector& audio_cadence); video_format_desc(video_format format = video_format::invalid); video_format_desc(const std::wstring& name); }; bool operator==(const video_format_desc& rhs, const video_format_desc& lhs); bool operator!=(const video_format_desc& rhs, const video_format_desc& lhs); std::wostream& operator<<(std::wostream& out, const video_format_desc& format_desc); std::vector find_audio_cadence(const boost::rational& framerate, bool log_quiet = false); }} // namespace caspar::core server-2.2.0-stable/src/modules/000077500000000000000000000000001341175263200165345ustar00rootroot00000000000000server-2.2.0-stable/src/modules/CMakeLists.txt000066400000000000000000000005321341175263200212740ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.6) project("modules") add_subdirectory(ffmpeg) add_subdirectory(oal) add_subdirectory(decklink) add_subdirectory(screen) if (ENABLE_HTML) add_subdirectory(html) endif () if (MSVC) add_subdirectory(flash) add_subdirectory(newtek) add_subdirectory(bluefish) endif() add_subdirectory(image) server-2.2.0-stable/src/modules/bluefish/000077500000000000000000000000001341175263200203355ustar00rootroot00000000000000server-2.2.0-stable/src/modules/bluefish/CMakeLists.txt000066400000000000000000000025431341175263200231010ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (bluefish) set(SOURCES consumer/bluefish_consumer.cpp producer/bluefish_producer.cpp util/blue_velvet.cpp bluefish.cpp StdAfx.cpp ) set(HEADERS consumer/bluefish_consumer.h producer/bluefish_producer.h interop/BlueVelvetC.h interop/BlueVelvetCUtils.h util/blue_velvet.h util/memory.h bluefish.h StdAfx.h ) add_library(bluefish ${SOURCES} ${HEADERS}) add_precompiled_header(bluefish StdAfx.h FORCEINCLUDE) configure_file("${PROJECT_SOURCE_DIR}/packages.config" "${CMAKE_CURRENT_BINARY_DIR}/packages.config") include_directories(..) include_directories(../..) include_directories(${BOOST_INCLUDE_PATH}) include_directories(${TBB_INCLUDE_PATH}) include_directories(${FFMPEG_INCLUDE_PATH}) set_target_properties(bluefish PROPERTIES FOLDER modules) source_group(sources ./*) source_group(sources\\consumer consumer/*) source_group(sources\\producer producer/*) source_group(sources\\util util/*) source_group(sources\\interop interop/*) target_link_libraries( bluefish common core ffmpeg) casparcg_add_include_statement("modules/bluefish/bluefish.h") casparcg_add_init_statement("bluefish::init" "bluefish") casparcg_add_module_project("bluefish") server-2.2.0-stable/src/modules/bluefish/StdAfx.cpp000066400000000000000000000021041341175263200222270ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ // stdafx.cpp : source file that includes just the standard includes // dma.pch will be the pre-compiled header // stdafx.obj will contain the pre-compiled type information #include "stdafx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file server-2.2.0-stable/src/modules/bluefish/StdAfx.h000066400000000000000000000024751341175263200217070ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #if defined _DEBUG && defined _MSC_VER #include #endif #define NOMINMAX #include #include #include #include #include #include #include #include #include #include #include #include //#include "../common/executor.h" // Can't include this due to MSVC lambda bug #include #include #include #include server-2.2.0-stable/src/modules/bluefish/bluefish.cpp000066400000000000000000000046411341175263200226470ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com * James Wise, james.wise@bluefish444.com */ #include "StdAfx.h" #include "bluefish.h" #include "consumer/bluefish_consumer.h" #include "producer/bluefish_producer.h" #include "util/blue_velvet.h" #include #include #include #include namespace caspar { namespace bluefish { std::wstring version() { try { bvc_wrapper blue; return u16(blue.get_version()); } catch (...) { return L"Not found"; } } std::vector device_list() { std::vector devices; try { bvc_wrapper blue; int numCards = 0; blue.enumerate(numCards); for (int n = 1; n < (numCards + 1); n++) { blue.attach(n); devices.push_back(std::wstring(get_card_desc(blue, n)) + L" [" + boost::lexical_cast(n) + L"] " + get_sdi_inputs(blue) + L"i" + get_sdi_outputs(blue) + L"o"); blue.detach(); } } catch (...) { } return devices; } void init(core::module_dependencies dependencies) { try { bvc_wrapper blue; int num_cards = 0; blue.enumerate(num_cards); } catch (...) { } dependencies.consumer_registry->register_consumer_factory(L"Bluefish Consumer", create_consumer); dependencies.consumer_registry->register_preconfigured_consumer_factory(L"bluefish", create_preconfigured_consumer); dependencies.producer_registry->register_producer_factory(L"Bluefish Producer", create_producer); } }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/bluefish.h000066400000000000000000000020011341175263200223000ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { namespace bluefish { std::wstring get_version(); void init(core::module_dependencies dependencies); }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/consumer/000077500000000000000000000000001341175263200221705ustar00rootroot00000000000000server-2.2.0-stable/src/modules/bluefish/consumer/bluefish_consumer.cpp000066400000000000000000001246611341175263200264220ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com * James Wise, james.wise@bluefish444.com */ #include "../StdAfx.h" #include "../util/blue_velvet.h" #include "../util/memory.h" #include "bluefish_consumer.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace bluefish { #define BLUEFISH_MAX_SOFTWARE_BUFFERS 4 #define SIZE_TEMP_AUDIO_BUFFER \ (2048 * 16) // max 2002 samples across 16 channels, use 2048 for safety cos sometimes caspar gives us too many... enum class hardware_downstream_keyer_mode { disable = 0, external = 1, internal = 2, // Bluefish dedicated HW keyer - only available on some models. }; enum class hardware_downstream_keyer_audio_source { SDIVideoInput = 1, VideoOutputChannel = 2 }; enum class bluefish_hardware_output_channel { channel_1 = 1, channel_2 = 2, channel_3 = 3, channel_4 = 4, }; struct configuration { unsigned int device_index = 1; bluefish_hardware_output_channel device_stream = bluefish_hardware_output_channel::channel_1; bool embedded_audio = true; hardware_downstream_keyer_mode hardware_keyer_value = hardware_downstream_keyer_mode::disable; hardware_downstream_keyer_audio_source keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel; unsigned int watchdog_timeout = 2; }; bool get_videooutput_channel_routing_info_from_streamid(bluefish_hardware_output_channel streamid, EEpochRoutingElements& channelSrcElement, EEpochRoutingElements& sdioutputDstElement) { switch (streamid) { case bluefish_hardware_output_channel::channel_1: channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA; sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_A; break; case bluefish_hardware_output_channel::channel_2: channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHB; sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_B; break; case bluefish_hardware_output_channel::channel_3: channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC; sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_C; break; case bluefish_hardware_output_channel::channel_4: channelSrcElement = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHD; sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_D; break; default: return false; } return true; } EBlueVideoChannel get_bluesdk_videochannel_from_streamid(bluefish_hardware_output_channel streamid) { /*This function would return the corresponding EBlueVideoChannel from the device output channel*/ switch (streamid) { case bluefish_hardware_output_channel::channel_1: return BLUE_VIDEO_OUTPUT_CHANNEL_A; case bluefish_hardware_output_channel::channel_2: return BLUE_VIDEO_OUTPUT_CHANNEL_B; case bluefish_hardware_output_channel::channel_3: return BLUE_VIDEO_OUTPUT_CHANNEL_C; case bluefish_hardware_output_channel::channel_4: return BLUE_VIDEO_OUTPUT_CHANNEL_D; default: return BLUE_VIDEO_OUTPUT_CHANNEL_A; } } struct bluefish_consumer : boost::noncopyable { const int channel_index_; const configuration config_; spl::shared_ptr blue_ = create_blue(config_.device_index); std::mutex exception_mutex_; std::exception_ptr exception_; std::wstring model_name_; const core::video_format_desc format_desc_; std::mutex buffer_mutex_; std::condition_variable buffer_cond_; std::atomic scheduled_frames_completed_{0}; int field_count_; std::atomic abort_request_{false}; unsigned int mode_; // ie bf video mode / format bool interlaced_ = false; std::array all_frames_; tbb::concurrent_bounded_queue reserved_frames_; tbb::concurrent_bounded_queue live_frames_; std::atomic audio_frames_filled_{0}; blue_dma_buffer_ptr last_field_buf_ = nullptr; std::vector tmp_audio_buf_; unsigned int tmp_audio_buf_contains_samples = 0; std::shared_ptr dma_present_thread_; std::shared_ptr hardware_watchdog_thread_; std::atomic end_hardware_watchdog_thread_; unsigned int interrupts_to_wait_ = config_.watchdog_timeout; spl::shared_ptr graph_; caspar::timer tick_timer_; caspar::timer sync_timer_; public: bluefish_consumer(const configuration& config, const core::video_format_desc& format_desc, int channel_index) : channel_index_(channel_index) , config_(config) , format_desc_(format_desc) { // OK this is the Guts of it, lets see what we can do to get a compile working, and then some actual // functionality eh? graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f)); graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f)); graph_->set_color("flushed-frame", diagnostics::color(0.4f, 0.3f, 0.8f)); graph_->set_color("buffered-audio", diagnostics::color(0.9f, 0.9f, 0.5f)); graph_->set_color("buffered-video", diagnostics::color(0.2f, 0.9f, 0.9f)); graph_->set_text(print()); diagnostics::register_graph(graph_); reserved_frames_.set_capacity(BLUEFISH_MAX_SOFTWARE_BUFFERS); live_frames_.set_capacity(BLUEFISH_MAX_SOFTWARE_BUFFERS); // get BF video mode mode_ = get_bluefish_video_format(format_desc_.format); if (mode_ == VID_FMT_1080I_5000 || mode_ == VID_FMT_1080I_5994 || mode_ == VID_FMT_1080I_6000 || mode_ == VID_FMT_PAL || mode_ == VID_FMT_NTSC) { interlaced_ = true; } // Specify the video channel setup_hardware_output_channel(); // ie stream id model_name_ = get_card_desc(*blue_.get(), (int)config_.device_index); configure_watchdog(); // disable the video output while we do all the config. disable_video_output(); // Setting output Video mode if (BLUE_FAIL(blue_->set_card_property32(VIDEO_MODE, mode_))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set videomode.")); // Select Update Mode for output if (BLUE_FAIL(blue_->set_card_property32(VIDEO_UPDATE_TYPE, UPD_FMT_FRAME))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set update type.")); setup_hardware_output_channel_routing(); // Select output memory format if (BLUE_FAIL(blue_->set_card_property32(VIDEO_MEMORY_FORMAT, MEM_FMT_ARGB_PC))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set memory format.")); // Select image orientation if (BLUE_FAIL(blue_->set_card_property32(VIDEO_IMAGE_ORIENTATION, ImageOrientation_Normal))) CASPAR_LOG(warning) << print() << L" Failed to set image orientation to normal."; // Select data range if (BLUE_FAIL(blue_->set_card_property32(VIDEO_RGB_DATA_RANGE, CGR_RANGE))) CASPAR_LOG(warning) << print() << L" Failed to set RGB data range to CGR."; // configure audio if (!config_.embedded_audio || (config_.hardware_keyer_value == hardware_downstream_keyer_mode::internal && config.keyer_audio_source == hardware_downstream_keyer_audio_source::SDIVideoInput)) { if (BLUE_FAIL(blue_->set_card_property32(EMBEDEDDED_AUDIO_OUTPUT, 0))) CASPAR_LOG(warning) << TEXT("BLUECARD ERROR: Failed to disable embedded audio."); CASPAR_LOG(info) << print() << TEXT(" Disabled embedded-audio."); } else { ULONG audio_value = blue_emb_audio_enable | blue_emb_audio_group1_enable; if (format_desc_.audio_channels > 4) audio_value |= blue_emb_audio_group2_enable; if (format_desc_.audio_channels > 8) audio_value |= blue_emb_audio_group3_enable; if (format_desc_.audio_channels > 12) audio_value |= blue_emb_audio_group4_enable; if (BLUE_FAIL(blue_->set_card_property32(EMBEDEDDED_AUDIO_OUTPUT, audio_value))) CASPAR_LOG(warning) << print() << TEXT(" Failed to enable embedded audio."); CASPAR_LOG(info) << print() << TEXT(" Enabled embedded-audio."); } if (BLUE_FAIL(blue_->set_card_property32(VIDEO_OUTPUT_ENGINE, VIDEO_ENGINE_PLAYBACK))) CASPAR_LOG(warning) << print() << TEXT(" Failed to set video engine."); if (is_epoch_card((*blue_))) setup_hardware_downstream_keyer(config.hardware_keyer_value, config.keyer_audio_source); // ok here we create a bunch of Bluefish buffers, that contain video and encoded hanc.... // this is the software Q. / software buffers int n = 0; boost::range::generate( all_frames_, [&] { return std::make_shared(static_cast(format_desc_.size), n++); }); for (size_t i = 0; i < all_frames_.size(); i++) reserved_frames_.push(all_frames_[i]); tmp_audio_buf_.reserve(SIZE_TEMP_AUDIO_BUFFER); // start the thread if required. if (dma_present_thread_ == 0) { dma_present_thread_ = std::make_shared([this] { dma_present_thread_actual(); }); #if defined(_WIN32) HANDLE handle = (HANDLE)dma_present_thread_->native_handle(); SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST); #endif } enable_video_output(); } ~bluefish_consumer() { try { abort_request_ = true; buffer_cond_.notify_all(); if (!end_hardware_watchdog_thread_) disable_watchdog(); disable_video_output(); blue_->detach(); if (dma_present_thread_) dma_present_thread_->join(); if (hardware_watchdog_thread_) hardware_watchdog_thread_->join(); } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } } void watchdog_thread_actual() { bvc_wrapper watchdog_bvc; watchdog_bvc.attach(config_.device_index); EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream); watchdog_bvc.set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel); unsigned long fc = 0; unsigned int blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_keepalive, config_.watchdog_timeout); while (!end_hardware_watchdog_thread_) { watchdog_bvc.wait_video_output_sync(UPD_FMT_FIELD, fc); blue_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop); } disable_watchdog(); watchdog_bvc.detach(); } void configure_watchdog() { // First test if we even want to enable the watchdog, only on Ch 1 and if user has not explicitly set count to // 0, and only if card has at least 1 input sdi, else dont do anything unsigned int val = 0; blue_->get_card_property32(CARD_FEATURE_STREAM_INFO, val); unsigned int num_input_streams = CARD_FEATURE_GET_SDI_INPUT_STREAM_COUNT(val); if (interrupts_to_wait_ && (config_.device_stream == bluefish_hardware_output_channel::channel_1) && num_input_streams) { // check if it is already running unsigned int blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_get_timer_activated_status, 0); blue_->get_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop); if (EPOCH_WATCHDOG_TIMER_GET_VALUE_MACRO(blue_prop)) { // watchdog timer is running already, switch it off. blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_start_stop, (unsigned int)0); blue_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop); } // Setting up the watchdog properties unsigned int watchdog_timer_gpo_port = 1; // GPO port to use: 0 = none, 1 = port A, 2 = port B blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_enable_gpo_on_active, watchdog_timer_gpo_port); blue_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop); if (interrupts_to_wait_ == 1) // using too low a value can cause instability on the watchdog so always make // sure we use a value of 2 or more... interrupts_to_wait_++; blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_start_stop, interrupts_to_wait_); blue_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop); // start the thread if required. if (hardware_watchdog_thread_ == 0) { end_hardware_watchdog_thread_ = false; hardware_watchdog_thread_ = std::make_shared([this] { watchdog_thread_actual(); }); } } } void disable_watchdog() { end_hardware_watchdog_thread_ = true; unsigned int stop_value = 0; unsigned int blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_start_stop, stop_value); blue_->get_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop); } void setup_hardware_output_channel() { // This function would be used to setup the logic video channel in the bluefish hardware EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream); if (is_epoch_card((*blue_))) { if (out_vid_channel != BLUE_VIDEOCHANNEL_INVALID) { if (BLUE_FAIL(blue_->set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to set video stream.")); blue_->video_playback_stop(0, 0); } } } void setup_hardware_output_channel_routing() { // This function would be used to setup the dual link and any other routing that would be required . if (is_epoch_card(*blue_)) { EBlueVideoChannel blue_video_output_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream); EEpochRoutingElements src_element = (EEpochRoutingElements)0; EEpochRoutingElements dst_element = (EEpochRoutingElements)0; get_videooutput_channel_routing_info_from_streamid(config_.device_stream, src_element, dst_element); bool duallink_4224_enabled = false; if ((config_.device_stream == bluefish_hardware_output_channel::channel_1 || config_.device_stream == bluefish_hardware_output_channel::channel_3) && (config_.hardware_keyer_value == hardware_downstream_keyer_mode::external) || (config_.hardware_keyer_value == hardware_downstream_keyer_mode::internal)) { duallink_4224_enabled = true; } // Enable/Disable dual link output if (BLUE_FAIL(blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT, duallink_4224_enabled))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to enable/disable dual link.")); if (!duallink_4224_enabled) { if (BLUE_FAIL(blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE, Signal_FormatType_Independent_422))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set dual link format type to 4:2:2.")); ULONG routingValue = EPOCH_SET_ROUTING(src_element, dst_element, BLUE_CONNECTOR_PROP_SINGLE_LINK); if (BLUE_FAIL(blue_->set_card_property32(MR2_ROUTING, routingValue))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to MR 2 routing.")); // If single link 422, but on second channel AND on Neutron we need to set Genlock to Aux. if (is_epoch_neutron_1i2o_card((*blue_))) { if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_B) { ULONG genlock_source = BlueGenlockAux; if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genlock_source))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input.")); } } if (is_epoch_neutron_3o_card((*blue_))) { if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_C) { ULONG genlock_source = BlueGenlockAux; if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genlock_source))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input.")); } } } else // dual Link IS enabled, ie. 4224 Fill and Key { if (BLUE_FAIL( blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE, Signal_FormatType_4224))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set dual link format type to 4:2:2:4.")); if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_A) { ULONG routing_value = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA, EPOCH_DEST_SDI_OUTPUT_A, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1); if (BLUE_FAIL(blue_->set_card_property32(MR2_ROUTING, routing_value))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to MR 2 routing.")); routing_value = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA, EPOCH_DEST_SDI_OUTPUT_B, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2); if (BLUE_FAIL(blue_->set_card_property32(MR2_ROUTING, routing_value))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to MR 2 routing.")); if (is_epoch_neutron_1i2o_card((*blue_))) // Neutron cards require setting the Genlock conector to // Aux to enable them to do Dual-Link { ULONG genLockSource = BlueGenlockAux; if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input.")); } else if (is_epoch_neutron_3o_card((*blue_))) { if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_C) { ULONG genLockSource = BlueGenlockAux; if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to set GenLock to Aux Input.")); } } } else { // using channel C for 4224 on other configurations requires explicit routing if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_C) { ULONG routingValue = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC, EPOCH_DEST_SDI_OUTPUT_C, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1); if (BLUE_FAIL(blue_->set_card_property32(MR2_ROUTING, routingValue))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to MR 2 routing.")); routingValue = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC, EPOCH_DEST_SDI_OUTPUT_D, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2); if (BLUE_FAIL(blue_->set_card_property32(MR2_ROUTING, routingValue))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to MR 2 routing.")); } } } } } void setup_hardware_downstream_keyer(hardware_downstream_keyer_mode keyer, hardware_downstream_keyer_audio_source audio_source) { unsigned int keyer_control_value = 0, card_feature_value = 0; unsigned int card_connector_value = 0; unsigned int output_streams = 0; unsigned int input_streams = 0; unsigned int input_connectors = 0; unsigned int output_connectors = 0; if (BLUE_OK(blue_->get_card_property32(CARD_FEATURE_STREAM_INFO, card_feature_value))) { output_streams = CARD_FEATURE_GET_SDI_OUTPUT_STREAM_COUNT(card_feature_value); input_streams = CARD_FEATURE_GET_SDI_INPUT_STREAM_COUNT(card_feature_value); } if (BLUE_OK(blue_->get_card_property32(CARD_FEATURE_CONNECTOR_INFO, card_connector_value))) { output_connectors = CARD_FEATURE_GET_SDI_OUTPUT_CONNECTOR_COUNT(card_connector_value); input_connectors = CARD_FEATURE_GET_SDI_INPUT_CONNECTOR_COUNT(card_connector_value); } if (output_connectors == 0 || input_streams == 0) return; if (keyer == hardware_downstream_keyer_mode::disable || keyer == hardware_downstream_keyer_mode::external) { keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLED(keyer_control_value); keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(keyer_control_value); } else if (keyer == hardware_downstream_keyer_mode::internal) { unsigned int invalid_video_mode = 0; unsigned int input_video_mode = 0; if (BLUE_FAIL(blue_->get_card_property32(INVALID_VIDEO_MODE_FLAG, invalid_video_mode))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to get invalid video mode flag")); // The bluefish HW keyer is NOT going to pre-multiply the RGB with the A. keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_PREMULTIPLIED(keyer_control_value); keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLED(keyer_control_value); if (BLUE_FAIL(blue_->get_card_property32(VIDEO_INPUT_SIGNAL_VIDEO_MODE, input_video_mode))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to get video input signal mode")); if (input_video_mode >= invalid_video_mode) keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLE_OVER_BLACK(keyer_control_value); else keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(keyer_control_value); // lock to input if (BLUE_FAIL(blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, BlueSDI_A_BNC))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(" Failed to set the genlock to the input for the HW keyer")); } if (audio_source == hardware_downstream_keyer_audio_source::SDIVideoInput && (keyer == hardware_downstream_keyer_mode::internal)) keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_USE_INPUT_ANCILLARY(keyer_control_value); else if (audio_source == hardware_downstream_keyer_audio_source::VideoOutputChannel) keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_USE_OUTPUT_ANCILLARY(keyer_control_value); if (BLUE_FAIL(blue_->set_card_property32(VIDEO_ONBOARD_KEYER, keyer_control_value))) CASPAR_LOG(error) << print() << TEXT(" Failed to set keyer control."); } void enable_video_output() { if (config_.device_stream == bluefish_hardware_output_channel::channel_1) blue_->set_card_property32(BYPASS_RELAY_A_ENABLE, 0); else if (config_.device_stream == bluefish_hardware_output_channel::channel_2) blue_->set_card_property32(BYPASS_RELAY_B_ENABLE, 0); if (BLUE_FAIL(blue_->set_card_property32(VIDEO_BLACKGENERATOR, 0))) CASPAR_LOG(error) << print() << TEXT(" Failed to disable video output."); } void disable_video_output() { blue_->video_playback_stop(0, 0); blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT, 0); if (BLUE_FAIL(blue_->set_card_property32(VIDEO_BLACKGENERATOR, 1))) CASPAR_LOG(error) << print() << TEXT(" Failed to disable video output."); if (BLUE_FAIL(blue_->set_card_property32(EMBEDEDDED_AUDIO_OUTPUT, 0))) CASPAR_LOG(error) << print() << TEXT(" Failed to disable audio output."); } bool send(core::const_frame frame) { { std::lock_guard lock(exception_mutex_); if (exception_ != nullptr) { std::rethrow_exception(exception_); } } if (!frame) { return !abort_request_; } try { std::unique_lock lock(buffer_mutex_); copy_frame(frame); graph_->set_value("tick-time", static_cast(tick_timer_.elapsed() * format_desc_.fps * 0.5)); tick_timer_.restart(); } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } return !abort_request_; } void dma_present_thread_actual() { bvc_wrapper wait_b; wait_b.attach(config_.device_index); EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream); wait_b.set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel); int frames_to_buffer = 1; unsigned long buffer_id = 0; unsigned long underrun = 0; while (!abort_request_) { blue_dma_buffer_ptr buf = nullptr; if (live_frames_.try_pop(buf) && BLUE_OK(blue_->video_playback_allocate(buffer_id, underrun))) { // Send and display if (config_.embedded_audio) { // Do video first, then do hanc DMA... blue_->system_buffer_write(const_cast(buf->image_data()), static_cast(buf->image_size()), BlueImage_HANC_DMABuffer(buffer_id, BLUE_DATA_IMAGE), 0); blue_->system_buffer_write(buf->hanc_data(), static_cast(buf->hanc_size()), BlueImage_HANC_DMABuffer(buffer_id, BLUE_DATA_HANC), 0); if (BLUE_FAIL(blue_->video_playback_present(BlueBuffer_Image_HANC(buffer_id), 1, 0, 0))) CASPAR_LOG(warning) << print() << TEXT(" video_playback_present failed."); } else { blue_->system_buffer_write(const_cast(buf->image_data()), static_cast(buf->image_size()), BlueImage_DMABuffer(buffer_id, BLUE_DATA_IMAGE), 0); if (BLUE_FAIL(blue_->video_playback_present(BlueBuffer_Image(buffer_id), 1, 0, 0))) CASPAR_LOG(warning) << print() << TEXT(" video_playback_present failed."); } scheduled_frames_completed_++; reserved_frames_.push(buf); } { // Sync and Update timer unsigned long n_field = 0; wait_b.wait_video_output_sync(UPD_FMT_FRAME, n_field); graph_->set_value("sync-time", sync_timer_.elapsed() * format_desc_.fps * 0.5); sync_timer_.restart(); } if (frames_to_buffer > 0) { frames_to_buffer--; if (frames_to_buffer == 0) { if (BLUE_FAIL(blue_->video_playback_start(0, 0))) CASPAR_LOG(warning) << print() << TEXT("Error video playback start failed"); } } } wait_b.detach(); blue_->video_playback_stop(0, 0); } void copy_frame(core::const_frame frame) { int audio_samples_for_next_frame = blue_->get_num_audio_samples_for_frame(mode_, static_cast(audio_frames_filled_)); if (interlaced_) { if (!last_field_buf_) // field 1 { if (reserved_frames_.try_pop(last_field_buf_)) { // copy video data into holding buf void* dest = last_field_buf_->image_data(); if (frame.image_data(0).size()) { std::memcpy(dest, frame.image_data(0).begin(), frame.image_data(0).size()); } else std::memset(dest, 0, last_field_buf_->image_size()); // now copy Some of the Audio bytes that we need if (config_.embedded_audio) { auto audio_size = frame.audio_data().size() * 4; if (audio_size) { tmp_audio_buf_.insert( tmp_audio_buf_.end(), frame.audio_data().begin(), frame.audio_data().end()); } } } } else // field 2 { // we have already done the video... just grab the last bit of audio, encode and push to Q. if (config_.embedded_audio) { auto audio_size = frame.audio_data().size() * 4; if (audio_size) { tmp_audio_buf_.insert( tmp_audio_buf_.end(), frame.audio_data().begin(), frame.audio_data().end()); encode_hanc(reinterpret_cast(last_field_buf_->hanc_data()), reinterpret_cast(tmp_audio_buf_.data()), (audio_samples_for_next_frame), static_cast(format_desc_.audio_channels)); audio_frames_filled_++; } } // push to in use Q. live_frames_.push(last_field_buf_); last_field_buf_ = nullptr; tmp_audio_buf_.clear(); } } else { blue_dma_buffer_ptr buf = nullptr; // Copy to local buffers if (reserved_frames_.try_pop(buf)) { void* dest = buf->image_data(); if (frame.image_data(0).size()) std::memcpy(dest, frame.image_data(0).begin(), frame.image_data(0).size()); else std::memset(dest, 0, buf->image_size()); // encode and copy hanc data if (config_.embedded_audio) { if (frame.audio_data().size()) { encode_hanc(reinterpret_cast(buf->hanc_data()), (void*)frame.audio_data().data(), (audio_samples_for_next_frame), static_cast(format_desc_.audio_channels)); audio_frames_filled_++; } } // push to in use Q. live_frames_.push(buf); } } // Sync unsigned long n_field = 0; if (interlaced_) blue_->wait_video_output_sync(UPD_FMT_FIELD, n_field); else blue_->wait_video_output_sync(UPD_FMT_FRAME, n_field); graph_->set_value("sync-time", sync_timer_.elapsed() * format_desc_.fps * 0.5); sync_timer_.restart(); } void encode_hanc(BLUE_UINT32* hanc_data, void* audio_data, int audio_samples, int audio_nchannels) { const auto sample_type = AUDIO_CHANNEL_LITTLEENDIAN; auto emb_audio_flag = blue_emb_audio_enable | blue_emb_audio_group1_enable; if (audio_nchannels > 4) emb_audio_flag |= blue_emb_audio_group2_enable; if (audio_nchannels > 8) emb_audio_flag |= blue_emb_audio_group3_enable; if (audio_nchannels > 12) emb_audio_flag |= blue_emb_audio_group4_enable; hanc_stream_info_struct hanc_stream_info; memset(&hanc_stream_info, 0, sizeof(hanc_stream_info)); hanc_stream_info.AudioDBNArray[0] = -1; hanc_stream_info.AudioDBNArray[1] = -1; hanc_stream_info.AudioDBNArray[2] = -1; hanc_stream_info.AudioDBNArray[3] = -1; hanc_stream_info.hanc_data_ptr = hanc_data; hanc_stream_info.video_mode = get_bluefish_video_format(format_desc_.format); int card_type = CRD_INVALID; blue_->query_card_type(card_type, config_.device_index); blue_->encode_hanc_frame( card_type, &hanc_stream_info, audio_data, audio_nchannels, audio_samples, sample_type, emb_audio_flag); } std::wstring print() const { return model_name_ + L" [" + boost::lexical_cast(channel_index_) + L"-" + boost::lexical_cast(config_.device_index) + L"Stream: " + boost::lexical_cast(static_cast(config_.device_stream)) + L"|" + format_desc_.name + L"]"; } int64_t presentation_delay_millis() const { return 0; } }; struct bluefish_consumer_proxy : public core::frame_consumer { const configuration config_; std::unique_ptr consumer_; core::video_format_desc format_desc_; executor executor_; public: bluefish_consumer_proxy(const configuration& config) : config_(config) , executor_(L"bluefish_consumer[" + boost::lexical_cast(config.device_index) + L"]") { } ~bluefish_consumer_proxy() { executor_.invoke([=] { consumer_.reset(); }); } // frame_consumer void initialize(const core::video_format_desc& format_desc, int channel_index) override { format_desc_ = format_desc; executor_.invoke([=] { consumer_.reset(); consumer_.reset(new bluefish_consumer(config_, format_desc, channel_index)); }); } std::future send(core::const_frame frame) override { return executor_.begin_invoke([=] { return consumer_->send(frame); }); } std::wstring print() const override { return consumer_ ? consumer_->print() : L"[bluefish_consumer]"; } std::wstring name() const override { return L"bluefish"; } int index() const override { return 400 + config_.device_index; } bool has_synchronization_clock() const override { return true; } }; spl::shared_ptr create_consumer(const std::vector& params, std::vector> channels) { if (params.size() < 1 || !boost::iequals(params.at(0), L"BLUEFISH")) { return core::frame_consumer::empty(); } configuration config; const auto device_index = params.size() > 1 ? boost::lexical_cast(params.at(1)) : 1; const auto device_stream = contains_param(L"SDI-STREAM", params); const auto embedded_audio = contains_param(L"EMBEDDED_AUDIO", params); const auto keyer_option = contains_param(L"KEYER", params); const auto keyer_audio_option = contains_param(L"INTERNAL-KEYER-AUDIO-SOURCE", params); config.device_stream = bluefish_hardware_output_channel::channel_1; if (contains_param(L"1", params)) config.device_stream = bluefish_hardware_output_channel::channel_1; else if (contains_param(L"2", params)) config.device_stream = bluefish_hardware_output_channel::channel_2; else if (contains_param(L"3", params)) config.device_stream = bluefish_hardware_output_channel::channel_3; else if (contains_param(L"4", params)) config.device_stream = bluefish_hardware_output_channel::channel_4; config.hardware_keyer_value = hardware_downstream_keyer_mode::disable; if (contains_param(L"DISABLED", params)) config.hardware_keyer_value = hardware_downstream_keyer_mode::disable; else if (contains_param(L"EXTERNAL", params)) config.hardware_keyer_value = hardware_downstream_keyer_mode::external; else if (contains_param(L"INTERNAL", params)) config.hardware_keyer_value = hardware_downstream_keyer_mode::internal; config.keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput; if (contains_param(L"SDIVIDEOINPUT", params)) config.keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput; else if (contains_param(L"VIDEOOUTPUTCHANNEL", params)) config.keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel; config.embedded_audio = contains_param(L"EMBEDDED_AUDIO", params); config.watchdog_timeout = 2; return spl::make_shared(config); } spl::shared_ptr create_preconfigured_consumer(const boost::property_tree::wptree& ptree, std::vector> channels) { configuration config; auto device_index = ptree.get(L"device", 1); config.device_index = device_index; auto device_stream = ptree.get(L"sdi-stream", L"1"); if (device_stream == L"1") config.device_stream = bluefish_hardware_output_channel::channel_1; else if (device_stream == L"2") config.device_stream = bluefish_hardware_output_channel::channel_2; else if (device_stream == L"3") config.device_stream = bluefish_hardware_output_channel::channel_3; else if (device_stream == L"4") config.device_stream = bluefish_hardware_output_channel::channel_4; auto embedded_audio = ptree.get(L"embedded-audio", false); config.embedded_audio = embedded_audio; auto hardware_keyer_value = ptree.get(L"keyer", L"disabled"); if (hardware_keyer_value == L"disabled") config.hardware_keyer_value = hardware_downstream_keyer_mode::disable; else if (hardware_keyer_value == L"external") config.hardware_keyer_value = hardware_downstream_keyer_mode::external; else if (hardware_keyer_value == L"internal") config.hardware_keyer_value = hardware_downstream_keyer_mode::internal; auto keyer_audio_source_value = ptree.get(L"internal-keyer-audio-source", L"videooutputchannel"); if (keyer_audio_source_value == L"videooutputchannel") config.keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel; else if (keyer_audio_source_value == L"sdivideoinput") config.keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput; auto watchdog_timeout = ptree.get(L"watchdog", 2); config.watchdog_timeout = watchdog_timeout; return spl::make_shared(config); } }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/consumer/bluefish_consumer.h000066400000000000000000000030351341175263200260560ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com * James Wise, james.wise@bluefish444.com */ #pragma once #include #include #include #include #include namespace caspar { namespace bluefish { spl::shared_ptr create_consumer(const std::vector& params, std::vector> channels); spl::shared_ptr create_preconfigured_consumer(const boost::property_tree::wptree& ptree, std::vector> channels); }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/interop/000077500000000000000000000000001341175263200220155ustar00rootroot00000000000000server-2.2.0-stable/src/modules/bluefish/interop/BlueDriver_p.h000066400000000000000000002520371341175263200245610ustar00rootroot00000000000000/* -LICENSE-START- ** Copyright (c) 2018 Bluefish Technologies ** ** Permission is hereby granted, free of charge, to any person or organization ** obtaining a copy of the software and accompanying documentation covered by ** this license (the "Software") to use, reproduce, display, distribute, ** execute, and transmit the Software, and to prepare derivative works of the ** Software, and to permit third-parties to whom the Software is furnished to ** do so, all subject to the following: ** ** The copyright notices in the Software and this entire statement, including ** the above license grant, this restriction and the following disclaimer, ** must be included in all copies of the Software, in whole or in part, and ** all derivative works of the Software, unless such copies or derivative ** works are solely in the form of machine-executable object code generated by ** a source language processor. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ** DEALINGS IN THE SOFTWARE. ** -LICENSE-END- */ #ifndef _BLUEDRIVER_P_H__ #define _BLUEDRIVER_P_H__ #define BLUE_UINT32 unsigned int #define BLUE_INT32 int #define BLUE_UINT8 unsigned char #define BLUE_INT8 char #define BLUE_UINT16 unsigned short #define BLUE_INT16 short #if defined __linux__ #define BLUE_UINT64 unsigned long long #define ULONG unsigned long #elif defined (__APPLE__) #define BLUE_UINT64 unsigned long long #define UINT32 BLUE_UINT32 #define INT32 BLUE_INT32 #define ULONG unsigned long #define BOOLEAN BOOL #elif defined (_WIN32) #define BLUE_UINT64 unsigned __int64 #endif /** * This contains the enumerators that can be used to set the cards \n * video output and also to determine the video mode of the incoming \n * video signal. */ typedef enum _EVideoMode { VID_FMT_PAL=0, VID_FMT_NTSC=1, VID_FMT_576I_5000=0, /**< 720 x 576 50 Interlaced */ VID_FMT_486I_5994=1, /**< 720 x 486 60/1.001 Interlaced */ VID_FMT_720P_5994, /**< 1280 x 720 60/1.001 Progressive */ VID_FMT_720P_6000, /**< 1280 x 720 60 Progressive */ VID_FMT_1080PSF_2397, /**< 1920 x 1080 24/1.001 Segment Frame */ VID_FMT_1080PSF_2400, /**< 1920 x 1080 24 Segment Frame */ VID_FMT_1080P_2397, /**< 1920 x 1080 24/1.001 Progressive */ VID_FMT_1080P_2400, /**< 1920 x 1080 24 Progressive */ VID_FMT_1080I_5000, /**< 1920 x 1080 50 Interlaced */ VID_FMT_1080I_5994, /**< 1920 x 1080 60/1.001 Interlaced */ VID_FMT_1080I_6000, /**< 1920 x 1080 60 Interlaced */ VID_FMT_1080P_2500, /**< 1920 x 1080 25 Progressive */ VID_FMT_1080P_2997, /**< 1920 x 1080 30/1.001 Progressive */ VID_FMT_1080P_3000, /**< 1920 x 1080 30 Progressive */ VID_FMT_HSDL_1498, /**< 2048 x 1556 15/1.0 Segment Frame */ VID_FMT_HSDL_1500, /**< 2048 x 1556 15 Segment Frame */ VID_FMT_720P_5000, /**< 1280 x 720 50 Progressive */ VID_FMT_720P_2398, /**< 1280 x 720 24/1.001 Progressive */ VID_FMT_720P_2400, /**< 1280 x 720 24 Progressive */ VID_FMT_2048_1080PSF_2397=19, /**< 2048 x 1080 24/1.001 Segment Frame */ VID_FMT_2048_1080PSF_2400=20, /**< 2048 x 1080 24 Segment Frame */ VID_FMT_2048_1080P_2397=21, /**< 2048 x 1080 24/1.001 progressive */ VID_FMT_2048_1080P_2400=22, /**< 2048 x 1080 24 progressive */ VID_FMT_1080PSF_2500=23, VID_FMT_1080PSF_2997=24, VID_FMT_1080PSF_3000=25, VID_FMT_1080P_5000=26, VID_FMT_1080P_5994=27, VID_FMT_1080P_6000=28, VID_FMT_720P_2500=29, VID_FMT_720P_2997=30, VID_FMT_720P_3000=31, VID_FMT_DVB_ASI=32, VID_FMT_2048_1080PSF_2500=33, VID_FMT_2048_1080PSF_2997=34, VID_FMT_2048_1080PSF_3000=35, VID_FMT_2048_1080P_2500=36, VID_FMT_2048_1080P_2997=37, VID_FMT_2048_1080P_3000=38, VID_FMT_2048_1080P_5000=39, VID_FMT_2048_1080P_5994=40, VID_FMT_2048_1080P_6000=41, VID_FMT_1080P_4800=42, VID_FMT_2048_1080P_4800=43, VID_FMT_INVALID=44 } EVideoMode; /** @brief Use these enumerators to set the pixel format that should be used by the video input and output framestores. */ typedef enum _EMemoryFormat { MEM_FMT_ARGB=0, /**< ARGB 4:4:4:4 */ MEM_FMT_BV10=1, MEM_FMT_BV8=2, MEM_FMT_YUVS=MEM_FMT_BV8, MEM_FMT_V210=3, // Iridium HD (BAG1) MEM_FMT_RGBA=4, MEM_FMT_CINEON_LITTLE_ENDIAN=5, MEM_FMT_ARGB_PC=6, MEM_FMT_BGRA=MEM_FMT_ARGB_PC, MEM_FMT_CINEON=7, MEM_FMT_2VUY=8, MEM_FMT_BGR=9, MEM_FMT_BGR_16_16_16=10, MEM_FMT_BGR_48 = MEM_FMT_BGR_16_16_16, MEM_FMT_BGRA_16_16_16_16=11, MEM_FMT_BGRA_64 = MEM_FMT_BGRA_16_16_16_16, MEM_FMT_VUYA_4444=12, MEM_FMT_V216=13, MEM_FMT_Y210=14, MEM_FMT_Y216=15, MEM_FMT_RGB=16, MEM_FMT_YUV_ALPHA=17, MEM_FMT_RGB_16_16_16=18, MEM_FMT_RGB_48 = MEM_FMT_RGB_16_16_16, MEM_FMT_RGBA_16_16_16_16=19, MEM_FMT_RGBA_64 = MEM_FMT_RGBA_16_16_16_16, MEM_FMT_YCA8 = 20, MEM_FMT_CYA8 = 21, MEM_FMT_YUV_ALPHA_10 = 22, MEM_FMT_YCA10 = 23, MEM_FMT_CYA10 = 24, MEM_FMT_YAC10 = 25, MEM_FMT_CAY10 = 26, MEM_FMT_INVALID = 27 } EMemoryFormat; /** @brief Used to control the video update type, whether the card should capture/playback a video frame or field. */ typedef enum _EUpdateMethod { UPD_FMT_FIELD=0, UPD_FMT_FRAME, UPD_FMT_FRAME_DISPLAY_FIELD1, UPD_FMT_FRAME_DISPLAY_FIELD2, UPD_FMT_INVALID, UPD_FMT_FLAG_RETURN_CURRENT_UNIQUEID=0x80000000,/**< if this flag is used on epoch cards, function would return the unique id of the current frame as the return value.*/ } EUpdateMethod; typedef enum _EResoFormat { RES_FMT_NORMAL=0, RES_FMT_HALF, RES_FMT_INVALID } EResoFormat; typedef enum _ECardType { CRD_BLUEDEEP_LT=0, // D64 Lite CRD_BLUEDEEP_SD, // Iridium SD CRD_BLUEDEEP_AV, // Iridium AV CRD_BLUEDEEP_IO, // D64 Full CRD_BLUEWILD_AV, // D64 AV CRD_IRIDIUM_HD, // * Iridium HD CRD_BLUEWILD_RT, // D64 RT CRD_BLUEWILD_HD, // * BadAss G2 CRD_REDDEVIL, // Iridium Full CRD_BLUEDEEP_HD, // * BadAss G2 variant, proposed, reserved CRD_BLUE_EPOCH_2K = CRD_BLUEDEEP_HD, CRD_BLUE_EPOCH_2K_HORIZON=CRD_BLUE_EPOCH_2K, CRD_BLUEDEEP_HDS, // * BadAss G2 variant, proposed, reserved CRD_BLUE_ENVY, // Mini Din CRD_BLUE_PRIDE, //Mini Din Output CRD_BLUE_GREED, CRD_BLUE_INGEST, CRD_BLUE_SD_DUALLINK, CRD_BLUE_CATALYST, CRD_BLUE_SD_DUALLINK_PRO, CRD_BLUE_SD_INGEST_PRO, CRD_BLUE_SD_DEEPBLUE_LITE_PRO, CRD_BLUE_SD_SINGLELINK_PRO, CRD_BLUE_SD_IRIDIUM_AV_PRO, CRD_BLUE_SD_FIDELITY, CRD_BLUE_SD_FOCUS, CRD_BLUE_SD_PRIME, CRD_BLUE_EPOCH_2K_CORE, CRD_BLUE_EPOCH_2K_ULTRA, CRD_BLUE_EPOCH_HORIZON, CRD_BLUE_EPOCH_CORE, CRD_BLUE_EPOCH_ULTRA, CRD_BLUE_CREATE_HD, CRD_BLUE_CREATE_2K, CRD_BLUE_CREATE_2K_ULTRA, CRD_BLUE_CREATE_3D = CRD_BLUE_CREATE_2K, CRD_BLUE_CREATE_3D_ULTRA = CRD_BLUE_CREATE_2K_ULTRA, CRD_BLUE_SUPER_NOVA, CRD_BLUE_SUPER_NOVA_S_PLUS, CRD_BLUE_SUPER_NOVA_MICRO, CRD_BLUE_NEUTRON = CRD_BLUE_SUPER_NOVA_MICRO, CRD_BLUE_EPOCH_CG, CRD_INVALID } ECardType; typedef enum _EHDCardSubType { CRD_HD_FURY=1, CRD_HD_VENGENCE=2, CRD_HD_IRIDIUM_XP=3, CRD_HD_IRIDIUM = 4, CRD_HD_LUST=5, CRD_HD_INVALID }EHDCardSubType; enum EEpochFirmwareProductID { ORAC_FILMPOST_FIRMWARE_PRODUCTID = (0x01), //Epoch (2K) Horizon/Core/Ultra, Create/Create3D/Create3D Ultra ORAC_BROADCAST_FIRMWARE_PRODUCTID = (0x02), //Epoch (2K) Horizon/Core/Ultra, Create/Create3D/Create3D Ultra ORAC_ASI_FIRMWARE_PRODUCTID = (0x03), //Epoch (2K) Horizon/Core/Ultra ORAC_4SDIINPUT_FIRMWARE_PRODUCTID = (0x04), //Epoch Supernova/Supernova S+ ORAC_4SDIOUTPUT_FIRMWARE_PRODUCTID = (0x05), //Epoch Supernova/Supernova S+ ORAC_2SDIINPUT_2SDIOUTPUT_FIRMWARE_PRODUCTID = (0x06), //Epoch Supernova/Supernova S+ ORAC_1SDIINPUT_3SDIOUTPUT_FIRMWARE_PRODUCTID = (0x08), //Epoch Supernova/Supernova S+, deprecated ORAC_INPUT_1SDI_1CHANNEL_OUTPUT_4SDI_3CHANNEL_FIRMWARE_PRODUCTID = (0x09), //Epoch Supernova/Supernova S+ ORAC_INPUT_2SDI_2CHANNEL_OUTPUT_3SDI_2CHANNEL_FIRMWARE_PRODUCTID = (0x0A), //Epoch Supernova/Supernova S+, deprecated ORAC_INPUT_3SDI_3CHANNEL_OUTPUT_1SDI_1CHANNEL_FIRMWARE_PRODUCTID = (0x0B), //Epoch Supernova/Supernova S+ ORAC_BNC_ASI_FIRMWARE_PRODUCTID = (0x0C), //Epoch Supernova/Supernova S+ ORAC_NEUTRON_2_IN_0_OUT_FIRMWARE_PRODUCTID = (0x0D), //Epoch Neutron ORAC_NEUTRON_0_IN_2_OUT_FIRMWARE_PRODUCTID = (0x0E), //Epoch Neutron ORAC_NEUTRON_1_IN_1_OUT_FIRMWARE_PRODUCTID = (0x0F), //Epoch Neutron ORAC_NEUTRON_2_IN_0_OUT_SCALER_FIRMWARE_PRODUCTID = (0x10), //Epoch Neutron ORAC_NEUTRON_0_IN_2_OUT_SCALER_FIRMWARE_PRODUCTID = (0x11), //Epoch Neutron ORAC_NEUTRON_1_IN_1_OUT_SCALER_FIRMWARE_PRODUCTID = (0x12), //Epoch Neutron ORAC_NEUTRON_ASI_FIRMWARE_PRODUCTID = (0x13), //Epoch Neutron ORAC_INPUT_1SDI_1CHANNEL_OUTPUT_3SDI_3CHANNEL_FIRMWARE_PRODUCTID = (0x14), //Epoch Supernova/Supernova S+ ORAC_NEUTRON_1_IN_2_OUT_FIRMWARE_PRODUCTID = (0x15), //Epoch Neutron ORAC_NEUTRON_3_IN_0_OUT_FIRMWARE_PRODUCTID = (0x16), //Epoch Neutron ORAC_NEUTRON_0_IN_3_OUT_FIRMWARE_PRODUCTID = (0x17), //Epoch Neutron ORAC_INPUT_1SDI_1CHANNEL_OUTPUT_3SDI_2CHANNEL_FIRMWARE_PRODUCTID = (0x18), //Epoch Supernova/Supernova S+ ORAC_NEUTRON_2_IN_1_OUT_FIRMWARE_PRODUCTID = (0x19), //Epoch Neutron }; /**< @brief Use this enumerator to select the audio channels that should be captured or played back. */ typedef enum _BlueAudioChannelDesc { MONO_FLAG = 0xC0000000, MONO_CHANNEL_1 = 0x00000001, MONO_CHANNEL_2 = 0x00000002, MONO_CHANNEL_3 = 0x00000004, MONO_CHANNEL_4 = 0x00000008, MONO_CHANNEL_5 = 0x00000010, MONO_CHANNEL_6 = 0x00000020, MONO_CHANNEL_7 = 0x00000040, MONO_CHANNEL_8 = 0x00000080, MONO_CHANNEL_9 = 0x00000100,// to be used by analog audio output channels MONO_CHANNEL_10 = 0x00000200,// to be used by analog audio output channels MONO_CHANNEL_11 = 0x00000400,//actual channel 9 MONO_CHANNEL_12 = 0x00000800,//actual channel 10 MONO_CHANNEL_13 = 0x00001000,//actual channel 11 MONO_CHANNEL_14 = 0x00002000,//actual channel 12 MONO_CHANNEL_15 = 0x00004000,//actual channel 13 MONO_CHANNEL_16 = 0x00008000,//actual channel 14 MONO_CHANNEL_17 = 0x00010000,//actual channel 15 MONO_CHANNEL_18 = 0x00020000 //actual channel 16 }BlueAudioChannelDesc; //---------------------------------------------------------------------------- /**< Use this enumeraotor to set the type of pcm audio data. */ typedef enum { AUDIO_CHANNEL_LOOPING_OFF = 0x00000000, /**< deprecated not used any more */ AUDIO_CHANNEL_LOOPING = 0x00000001,/**< deprecated not used any more */ AUDIO_CHANNEL_LITTLEENDIAN = 0x00000000, /**< if the audio data is little endian this flag must be set*/ AUDIO_CHANNEL_BIGENDIAN = 0x00000002,/**< if the audio data is big endian this flag must be set*/ AUDIO_CHANNEL_OFFSET_IN_BYTES = 0x00000004,/**< deprecated not used any more */ AUDIO_CHANNEL_16BIT = 0x00000008, /**< if the audio channel bit depth is 16 bits this flag must be set*/ AUDIO_CHANNEL_BLIP_PENDING = 0x00000010,/**< deprecated not used any more */ AUDIO_CHANNEL_BLIP_COMPLETE = 0x00000020,/**< deprecated not used any more */ AUDIO_CHANNEL_SELECT_CHANNEL = 0x00000040,/**< deprecated not used any more */ AUDIO_CHANNEL_24BIT = 0x00000080/**< if the audio channel bit depth is 24 bits this flag must be set*/ } EAudioFlags; /** @desc Used to select Audio input source on new generation SD cards @remarks This enumerator works only when used with ReadAudioSample function. */ typedef enum { BLUE_AUDIO_AES = 0, /** 8 channels of AES */ BLUE_AUDIO_ANALOG = 1, /** 2 channels of analog audio */ BLUE_AUDIO_SDIA = 2, /** deprecated, do not use */ BLUE_AUDIO_EMBEDDED = BLUE_AUDIO_SDIA, /** use BLUE_AUDIO_EMBEDDED for any embedded audio stream; the stream is associated with the SDK object (BlueVelvet4/BlueVelvetC) */ BLUE_AUDIO_SDIB = 3, /** deprecated, do not use */ BLUE_AUDIO_AES_PAIR0 = 4, /** deprecated, do not use */ BLUE_AUDIO_AES_PAIR1 = 5, /** deprecated, do not use */ BLUE_AUDIO_AES_PAIR2 = 6, /** deprecated, do not use */ BLUE_AUDIO_AES_PAIR3 = 7, /** deprecated, do not use */ BLUE_AUDIO_SDIC = 8, /** deprecated, do not use */ BLUE_AUDIO_SDID = 9, /** deprecated, do not use */ BLUE_AUDIO_INVALID = 10 } Blue_Audio_Connector_Type; typedef enum _EAudioRate { AUDIO_SAMPLE_RATE_48K=48000, AUDIO_SAMPLE_RATE_96K=96000, AUDIO_SAMPLE_RATE_UNKNOWN=-1 } EAudioRate; /**< @brief use this enumerator to define the color space of the video signal on the SDI cable */ typedef enum _EConnectorSignalColorSpace { RGB_ON_CONNECTOR=0x00400000, /**< Use this enumerator if the colorspace of video data on the SDI cable is RGB
When using dual link capture/playback , user can choose the color space of the data.
In single link SDI the color space of the signal is always YUB*/ YUV_ON_CONNECTOR=0 /** driver uses this information to choose the appropriate YUV conversion matrices.*/ SMPTE_RANGE=1 /**< In this mode RGB data expected by the user (capture) or provided by the user(playback) is in the range of 16-235(8 bit) or 64-940(10 bit0).
driver uses this information to choose the appropriate YUV conversion matrices.*/ }ERGBDataRange; typedef enum _EHD_XCONNECTOR_MODE { SD_SDI=1, HD_SDI=2 }EHD_XCONNECTOR_MODE; /**< @brief this enumerator can be used to set the image orienatation of the frame. */ typedef enum _EImageOrientation { ImageOrientation_Normal=0, /**< in this configuration , frame is top to bottom and left to right */ ImageOrientation_VerticalFlip=1, /**< in this configuration frame is bottom to top and left to right*/ ImageOrientation_Invalid=2, }EImageOrientation; /**< @brief this enumerator defines the reference signal source that can be used with bluefish cards */ typedef enum _EBlueGenlockSource { BlueGenlockBNC = 0, /** Genlock is used as reference signal source */ BlueSDIBNC = 0x10000, /** SDI input B is used as reference signal source */ BlueSDI_B_BNC = BlueSDIBNC, BlueSDI_A_BNC = 0x20000, /** SDI input A is used as reference signal source */ BlueAnalog_BNC = 0x40000, /** Analog input is used as reference signal source */ BlueSoftware = 0x80000, BlueFreeRunning = BlueSoftware, BlueGenlockAux = 0x100000, /** auxiliary genlock connector on Epoch Neutron cards */ BlueInterlock = 0x200000, /** interlock connector on Epoch Neutron cards */ }EBlueGenlockSource; typedef enum _EBlueVideoChannel { BLUE_VIDEOCHANNEL_A=0, BLUE_VIDEO_OUTPUT_CHANNEL_A=BLUE_VIDEOCHANNEL_A, BLUE_VIDEOCHANNEL_B=1, BLUE_VIDEO_OUTPUT_CHANNEL_B=BLUE_VIDEOCHANNEL_B, BLUE_VIDEOCHANNEL_C=2, BLUE_VIDEO_INPUT_CHANNEL_A=BLUE_VIDEOCHANNEL_C, BLUE_VIDEOCHANNEL_D=3, BLUE_VIDEO_INPUT_CHANNEL_B=BLUE_VIDEOCHANNEL_D, BLUE_VIDEOCHANNEL_E=4, BLUE_VIDEO_INPUT_CHANNEL_C=BLUE_VIDEOCHANNEL_E, BLUE_VIDEOCHANNEL_F=5, BLUE_VIDEO_INPUT_CHANNEL_D=BLUE_VIDEOCHANNEL_F, BLUE_VIDEOCHANNEL_G=6, BLUE_VIDEO_OUTPUT_CHANNEL_C=BLUE_VIDEOCHANNEL_G, BLUE_VIDEOCHANNEL_H=7, BLUE_VIDEO_OUTPUT_CHANNEL_D=BLUE_VIDEOCHANNEL_H, BLUE_OUTPUT_MEM_MODULE_A=BLUE_VIDEO_OUTPUT_CHANNEL_A, BLUE_OUTPUT_MEM_MODULE_B=BLUE_VIDEO_OUTPUT_CHANNEL_B, BLUE_INPUT_MEM_MODULE_A=BLUE_VIDEO_INPUT_CHANNEL_A, BLUE_INPUT_MEM_MODULE_B=BLUE_VIDEO_INPUT_CHANNEL_B, //BLUE_JETSTREAM_SCALER_MODULE_0=0x10, //BLUE_JETSTREAM_SCALER_MODULE_1=0x11, //BLUE_JETSTREAM_SCALER_MODULE_2=0x12, //BLUE_JETSTREAM_SCALER_MODULE_3=0x13, BLUE_VIDEOCHANNEL_INVALID=30 }EBlueVideoChannel; typedef enum _EBlueVideoRouting { BLUE_VIDEO_LINK_INVALID=0, BLUE_SDI_A_LINK1=4, BLUE_SDI_A_LINK2=5, BLUE_SDI_B_LINK1=6, BLUE_SDI_B_LINK2=7, BLUE_ANALOG_LINK1=8, BLUE_ANALOG_LINK2=9, BLUE_SDI_A_SINGLE_LINK=BLUE_SDI_A_LINK1, BLUE_SDI_B_SINGLE_LINK=BLUE_SDI_B_LINK1, BLUE_ANALOG_SINGLE_LINK=BLUE_ANALOG_LINK1 }EBlueVideoRouting; typedef enum { BLUE_FIFO_NULL_ATTRIBUTE=0x0, BLUE_FIFO_ECHOPORT_ENABLED=0x1, BLUE_FIFO_STEPMODE = 0x2, BLUE_FIFO_LOOPMODE = 0x4 }BlueVideoFifo_Attributes; typedef enum _BlueAudioOutputDest { Blue_AnalogAudio_Output=0x0, Blue_AES_Output=0x80000000, Blue_Emb_Output=0x40000000, }BlueAudioOutputDest; /**<@brief this enumerator is not used need to be removed*/ typedef enum _BlueAudioInputSource { Blue_AES=0x10, Blue_AnalogAudio=0x20, Blue_SDIA_Embed=0x40, Blue_SDIB_Embed=0x80, }BlueAudioInputSource; typedef enum _EBlueConnectorIdentifier { BLUE_CONNECTOR_INVALID = -1, // BNC connectors in order from top to bottom of shield BLUE_CONNECTOR_BNC_A = 0, // BNC closest to top of shield BLUE_CONNECTOR_BNC_B, BLUE_CONNECTOR_BNC_C, BLUE_CONNECTOR_BNC_D, BLUE_CONNECTOR_BNC_E, BLUE_CONNECTOR_BNC_F, BLUE_CONNECTOR_GENLOCK, BLUE_CONNECTOR_ANALOG_VIDEO_1 = 100, BLUE_CONNECTOR_ANALOG_VIDEO_2, BLUE_CONNECTOR_ANALOG_VIDEO_3, BLUE_CONNECTOR_ANALOG_VIDEO_4, BLUE_CONNECTOR_ANALOG_VIDEO_5, BLUE_CONNECTOR_ANALOG_VIDEO_6, BLUE_CONNECTOR_DVID_1 = 200, BLUE_CONNECTOR_SDI_OUTPUT_A= BLUE_CONNECTOR_DVID_1, BLUE_CONNECTOR_DVID_2, BLUE_CONNECTOR_SDI_OUTPUT_B= BLUE_CONNECTOR_DVID_2, BLUE_CONNECTOR_DVID_3, BLUE_CONNECTOR_SDI_INPUT_A= BLUE_CONNECTOR_DVID_3, BLUE_CONNECTOR_DVID_4, BLUE_CONNECTOR_SDI_INPUT_B= BLUE_CONNECTOR_DVID_4, BLUE_CONNECTOR_DVID_5, BLUE_CONNECTOR_SDI_OUTPUT_C, BLUE_CONNECTOR_SDI_OUTPUT_D, BLUE_CONNECTOR_AES = 300, BLUE_CONNECTOR_ANALOG_AUDIO_1, BLUE_CONNECTOR_ANALOG_AUDIO_2, BLUE_CONNECTOR_DVID_6, BLUE_CONNECTOR_SDI_INPUT_C= BLUE_CONNECTOR_DVID_6, BLUE_CONNECTOR_DVID_7, BLUE_CONNECTOR_SDI_INPUT_D= BLUE_CONNECTOR_DVID_7, //BLUE_CONNECTOR_RESOURCE_BLOCK=0x400, //BLUE_CONNECTOR_JETSTREAM_SCALER_0=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_JETSTREAM_SCALER_MODULE_0), //BLUE_CONNECTOR_JETSTREAM_SCALER_1=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_JETSTREAM_SCALER_MODULE_1), //BLUE_CONNECTOR_JETSTREAM_SCALER_2=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_JETSTREAM_SCALER_MODULE_2), //BLUE_CONNECTOR_JETSTREAM_SCALER_3=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_JETSTREAM_SCALER_MODULE_3), //BLUE_CONNECTOR_OUTPUT_MEM_MODULE_A=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_OUTPUT_MEM_MODULE_A), //BLUE_CONNECTOR_OUTPUT_MEM_MODULE_B=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_OUTPUT_MEM_MODULE_B), //BLUE_CONNECTOR_INPUT_MEM_MODULE_A=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_INPUT_MEM_MODULE_A), //BLUE_CONNECTOR_INPUT_MEM_MODULE_B=(BLUE_CONNECTOR_RESOURCE_BLOCK|BLUE_INPUT_MEM_MODULE_B), // }EBlueConnectorIdentifier; typedef enum _EBlueConnectorSignalDirection { BLUE_CONNECTOR_SIGNAL_INVALID=-1, BLUE_CONNECTOR_SIGNAL_INPUT=0, BLUE_CONNECTOR_SIGNAL_OUTPUT=1, }EBlueConnectorSignalDirection; typedef enum _EBlueDynamicConnectorType { BLUE_DYNAMIC_CONNECTOR_TYPE_INVALID = 0, BLUE_DYNAMIC_CONNECTOR_TYPE_OUTPUT = 1, BLUE_DYNAMIC_CONNECTOR_TYPE_INPUT = 2, BLUE_DYNAMIC_CONNECTOR_TYPE_GENLOCK = 3, }EBlueDynamicConnectorType; typedef enum _EBlueConnectorProperty { BLUE_INVALID_CONNECTOR_PROPERTY = -1, //signal property BLUE_CONNECTOR_PROP_INPUT_SIGNAL=0, BLUE_CONNECTOR_PROP_OUTPUT_SIGNAL=1, // Video output BLUE_CONNECTOR_PROP_SDI = 0, BLUE_CONNECTOR_PROP_YUV_Y, BLUE_CONNECTOR_PROP_YUV_U, BLUE_CONNECTOR_PROP_YUV_V, BLUE_CONNECTOR_PROP_RGB_R, BLUE_CONNECTOR_PROP_RGB_G, BLUE_CONNECTOR_PROP_RGB_B, BLUE_CONNECTOR_PROP_CVBS, BLUE_CONNECTOR_PROP_SVIDEO_Y, BLUE_CONNECTOR_PROP_SVIDEO_C, // Audio output BLUE_CONNECTOR_PROP_AUDIO_AES = 0x2000, BLUE_CONNECTOR_PROP_AUDIO_EMBEDDED, BLUE_CONNECTOR_PROP_AUDIO_ANALOG, BLUE_CONNECTOR_PROP_SINGLE_LINK=0x3000, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2, BLUE_CONNECTOR_PROP_DUALLINK_LINK, BLUE_CONNECTOR_PROP_STEREO_MODE_SIDE_BY_SIDE, BLUE_CONNECTOR_PROP_STEREO_MODE_TOP_DOWN, BLUE_CONNECTOR_PROP_STEREO_MODE_LINE_BY_LINE, }EBlueConnectorProperty; /* typedef enum _BLUE_AUDIOINPUT_SOURCE { BLUE_AES_AUDIO_INPUT=0x10000, BLUE_ANALOG_AUDIO_INPUT=0x20000, BLUE_SDIA_AUDIO_INPUT=0x30000, BLUE_SDIB_AUDIO_INPUT=0x40000 }BLUE_AUDIOINPUT_SOURCE; */ /** @desc use the values in this enumerator for controlling card property */ typedef enum _EBlueCardProperty { VIDEO_DUAL_LINK_OUTPUT=0,/**< Use this property to enable/diable cards dual link output property*/ VIDEO_DUAL_LINK_INPUT=1,/**< Use this property to enable/diable cards dual link input property*/ VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE=2, /** Use the macro's EPOCH_CORE_TEMP ,EPOCH_BOARD_TEMP and EPOCH_FAN_SPEED to retireive the respective values from the property.
*/ MR2_ROUTING=71, /**< Use this property to control the MR2 functionlity on epoch range of cards. Use the following macro with this property.
1) EPOCH_SET_ROUTING --> for setting the source, destination and link type of the routing connection,
2) EPOCH_ROUTING_GET_SRC_DATA --> for getting the routing source.
The possible source and destination elements supported by the routing matrix are defined in the enumerator EEpochRoutingElements.
*/ SAVEAS_POWERUP_SETTINGS=72, VIDEO_CAPTURE_AVAIL_BUFFER_COUNT=73, /**< This property will return the number of captured frame avail in the fifo at present. If the video engine is framestore this will give you the number of buffers that the framestore mode can you use with that video input channel */ EPOCH_APP_WATCHDOG_TIMER=74,/**< Use this property to control the application watchdog timer functionality. Possible values this property can accept is defined in the enumerator enum_blue_app_watchdog_timer_prop. */ EPOCH_RESET_VIDEO_INPUT_FIELDCOUNT=75, /**< Use this property to reset the field count on both the video channels of the card. You can pass the value that should be used as starting fieldcount after the reset. This property can be used to keep track sync between left and right signal when you are capturing in stereoscopic mode. */ EPOCH_RS422_PORT_FLAGS=76,/**< Use this property to set the master/slave property of the RS422 ports. Possible values this property can accept is defined in the enumerator enum_blue_rs422_port_flags. */ EPOCH_DVB_ASI_INPUT_TIMEOUT=77, /**< Current DVB ASI input firmware does not support this property in hardware, this is a future addition. Use this property to set the timeout of the DVB ASI input stream. timeout is specified in milliseconds.If hardware did not get the required no of packets( specified using EPOCH_DVB_ASI_INPUT_LATENCY_PACKET_COUNT) within the period specified in the timeout, hardware would generate a video input interrupt and it would be safe to read the dvb asi packet from the card. */ EPOCH_DVB_ASI_INPUT_PACKING_FORMAT=78, /**< Use this property to specify the packing method that should be used when capturing DVB ASI packets. The possible packing methods are defined in the enumerator enum_blue_dvb_asi_packing_format.*/ EPOCH_DVB_ASI_INPUT_LATENCY_PACKET_COUNT=79, /**< Use this property to set how many asi packets should be captured by the card , before it notifies the driver of available data using video input interrupt.
*/ VIDEO_PLAYBACK_FIFO_CURRENT_FRAME_UNIQUEID=80, /**< This property can be used to query the current unique id of the frame that is being displayed currently by the video output channel. This property is only usefull in the context of video fifo.
You get a uniqueid when you present a frame using video_playback_present function. Alternative ways to get this information are
1) using blue_wait_video_sync_async , the member current_display_frame_uniqueid contains the same information
2) using wait_video_output_sync function on epoch cards, if the flag UPD_FMT_FLAG_RETURN_CURRENT_UNIQUEID is appended with either UPD_FMT_FRAME or UPD_FMT_FIELD , the return value of the function wait_video_output_sync woukd contain the current display frames uniqueid.
*/ EPOCH_DVB_ASI_INPUT_GET_PACKET_SIZE = 81,/**< use this property to get the size of each asi transport stream packet (whether it is 188 or 204.*/ EPOCH_DVB_ASI_INPUT_PACKET_COUNT = 82,/**< this property would give you the number of packets captured during the last interrupt time frame. For ASI interrupt is generated if hardware captured the requested number of packets or it hit the timeout value */ EPOCH_DVB_ASI_INPUT_LIVE_PACKET_COUNT = 83,/**< this property would give you the number of packets that is being captured during the current interrupt time frame. For ASI interrupt is generated when has hardware captured the requested number of packets specified using EPOCH_DVB_ASI_INPUT_LATENCY_PACKET_COUNT property. */ EPOCH_DVB_ASI_INPUT_AVAIL_PACKETS_IN_FIFO = 84,/**< This property would return the number of ASI packets that has been captured into card memory , that can be retreived. This property is only valid when the video input channel is being used in FIFO modes. */ EPOCH_ROUTING_SOURCE_VIDEO_MODE=VIDEO_SCALER_MODE,/**< Use this property to change the video mode that scaler should be set to. USe the macro SET_EPOCH_SCALER_MODE when using this property, as this macro would allow you to select which one of the scaler blocks video mode should be updated. */ EPOCH_AVAIL_VIDEO_SCALER_COUNT=85,/**< This property would return available scaler processing block available on the card.*/ EPOCH_ENUM_AVAIL_VIDEO_SCALERS_ID=86,/**< You can enumerate the available scaler processing block available on the card using this property. You pass in the index value as input parameter to get the scaler id that should be used. Applications are recommended to use this property to query the available scaler id's rather than hardcoding a scaler id. As the scaler id's that you can use would vary based on whether you have VPS0 or VPS1 boards loaded on the base board. */ EPOCH_ALLOCATE_VIDEO_SCALER=87, /**< This is just a helper property for applications who need to use more than one scaler and just wants to query the next available scaler from the driver pool, rather than hardcoding each thread to use a particular scaler. Allocate a free scaler from the available scaler pool. User has got the option to specify whether they want to use the scaler for use with a single link or dual link stream */ EPOCH_RELEASE_VIDEO_SCALER=88, /**< Release the previously allocated scaler processing block back to the free pool. If the user passes in a value of 0, all the allocated scaler blocks in the driver are released. So effectively */ EPOCH_DMA_CARDMEMORY_PITCH=89, EPOCH_OUTPUT_CHANNEL_AV_OFFSET=90, EPOCH_SCALER_CHANNEL_MUX_MODE=91, EPOCH_INPUT_CHANNEL_AV_OFFSET=92, EPOCH_AUDIOOUTPUT_MANUAL_UCZV_GENERATION=93, /* ASI firmware only */ EPOCH_SAMPLE_RATE_CONVERTER_BYPASS=94, /** bypasses the sample rate converter for AES audio; only turn on for Dolby-E support * pass in a flag to signal which audio stereo pair should be bypassed: * bit 0: AES channels 0 and 1 * bit 1: AES channels 2 and 3 * bit 2: AES channels 4 and 5 * bit 3: AES channels 6 and 7 * For example: bypass the sample rate converter for channels 0 to 3: flag = 0x3; */ EPOCH_GET_PRODUCT_ID=95, /* returns the enum for the firmware type EEpochFirmwareProductID */ EPOCH_GENLOCK_IS_LOCKED=96, EPOCH_DVB_ASI_OUTPUT_PACKET_COUNT=97, /* ASI firmware only */ EPOCH_DVB_ASI_OUTPUT_BIT_RATE=98, /* ASI firmware only */ EPOCH_DVB_ASI_DUPLICATE_OUTPUT_A=99, /* ASI firmware only */ EPOCH_DVB_ASI_DUPLICATE_OUTPUT_B=100, /* ASI firmware only */ EPOCH_SCALER_HORIZONTAL_FLIP=101, /* see SideBySide_3D sample application */ EPOCH_CONNECTOR_DIRECTION=102, /* see application notes */ EPOCH_AUDIOOUTPUT_VALIDITY_BITS=103, /* ASI firmware only */ EPOCH_SIZEOF_DRIVER_ALLOCATED_MEMORY=104, /* video buffer allocated in Kernel space; accessible in userland via system_buffer_map() */ INVALID_VIDEO_MODE_FLAG=105, /* returns the enum for VID_FMT_INVALID that this SDK/Driver was compiled with; it changed between 5.9.x.x and 5.10.x.x driver branch and has to be handled differently for each driver if the application wants to use the VID_FMT_INVALID flag and support both driver branches */ EPOCH_VIDEO_INPUT_VPID=106, /* returns the VPID for the current video input signal. Input value is of type EBlueConnectorIdentifier */ EPOCH_LOW_LATENCY_DMA=107, /* deprecated; use new feature EPOCH_SUBFIELD_INPUT_INTERRUPTS instead */ EPOCH_VIDEO_INPUT_RGB_DATA_RANGE=108, EPOCH_DVB_ASI_OUTPUT_PACKET_SIZE=109, /* firmware supports either 188 or 204 bytes per ASI packet; set to either enum_blue_dvb_asi_packet_size_188_bytes or enum_blue_dvb_asi_packet_size_204_bytes */ EPOCH_SUBFIELD_INPUT_INTERRUPTS=110, /* similar to the EPOCH_LOW_LATENCY_DMA card feature, but this doesn't influence the DMA; it simply adds interrupts between the frame/field interrupts that trigger when a corresponding video chunk has been captured required minimum driver: 5.10.1.8*/ EPOCH_AUDIOOUTPUT_METADATA_SETTINGS = 111, /* Use the EAudioMetaDataSettings enumerator to change the audio output metadata settings */ EPOCH_HD_SDI_TRANSPORT = 112, /* output only: available modes are defined in the enum EHdSdiTransport; for inputs see EPOCH_HD_SDI_TRANSPORT_INPUT */ CARD_FEATURE_STREAM_INFO = 113, /* only supported from driver 5.10.2.x; info on how many in/out SDI/ASI streams are supported */ CARD_FEATURE_CONNECTOR_INFO = 114, /* only supported from driver 5.10.2.x; info on which connectors are supported: SDI in/out, AES, RS422, LTC, GPIO */ EPOCH_HANC_INPUT_FLAGS = 115, /* this property can be queried to test flags being set in the HANC space (e.g. HANC_FLAGS_IS_ARRI_RECORD_FLAG_SET) */ EPOCH_INPUT_VITC = 116, /* this property retrieves the current input VITC timecode; set .vt = VT_UI8 as this is a 64bit value; only supported by SuperNova 2i/2o firmware version 75 and above */ EPOCH_RAW_VIDEO_INPUT_TYPE = 117, /* specifies if the raw/bayer input is ARRI 10/12 bit or Weisscam; set to 0 to revert back to normal SDI mode */ EPOCH_PCIE_CONFIG_INFO = 118, /* only supported from driver 5.10.2.x; provides info on PCIE maximum payload size and maximum read request siize */ EPOCH_4K_QUADLINK_CHANNEL = 119, /* use this property to set the 4K quadrant number for the current channel in 4K output mode; quadrant numbers are 1 - 4 */ EXTERNAL_LTC_SOURCE_SELECTION = 120, /* use the enum EBlueExternalLtcSource to set the input source for the external LTC */ EPOCH_HD_SDI_TRANSPORT_INPUT = 121, /* can only be queried; return values are defined in the enum EHdSdiTransport. Input value is of type EBlueConnectorIdentifier */ CARD_CONNECTED_VIA_TB = 122, /* MAC only: use this to check if the Card is connected via ThunderBolt */ INTERLOCK_REFERENCE = 123, /* this feature is only supported on Epoch Neutron cards; check application note AN004_Genlock.pdf for more information */ VIDEO_ONBOARD_KEYER = 124, /* this property is currently only supported by Epoch Neutron cards; use the VIDEO_ONBOARD_KEYER_GET_STATUS macros for this property*/ EPOCH_OUTPUT_VITC_MANUAL_CONTROL = 125, /* Epoch Neutron only: this property enables the feature to allow output of a custom VITC timecode on a field by field basis (low frame rates only); for high frame rates the conventional way (using the HANC buffer) must be used */ EPOCH_OUTPUT_VITC = 126, /* Epoch Neutron only: this property sets the custom VITC timecode (64 bit value) on a field by field basis (for low frame rates only); set .vt = VT_UI8 as this is a 64bit value; */ EPOCH_INPUT_VITC_SOURCE = 127, /* this property selects the source for the card property EPOCH_INPUT_VITC for SD video modes; in SD video modes the VITC source can be either from VBI space or from RP188 packets; the default (value = 0) is set to RP188; setting this to 1 will select VBI space as the source for EPOCH_INPUT_VITC; set .vt = VT_UI4 */ TWO_SAMPLE_INTERLEAVE_OUTPUT = 128, /* enables two sample interleave mode for 4K video modes using two output channels; options are: 0 = turn feature off, 1 = turn feature on */ TWO_SAMPLE_INTERLEAVE_INPUT = 129, /* enables two sample interleave mode for 4K video modes using two input channels; options are: 0 = turn feature off, 1 = turn feature on */ BTC_TIMER = 130, /* BTC: Coordinated Bluefish Time; this timer has microsecond granularity and is started/reset when the driver starts; set .vt = VT_UI8 as this is a 64bit value; */ BFLOCK_SIGNAL_ENABLE = 131, /* S+ cards can generate a proprietary lock signal on the S+ connector (connector 0); options are 0 = turn off signal (connector 0 will be copy of SDI A output); 1 = turn on lock signal output; set .vt = VT_UI4 */ AES_OUTPUT_ROUTING = 132, /* set the stream source and source channels for the AES output; .vt = VT_UI4 */ MUTE_AES_OUTPUT_CHANNEL = 133, /* mute any of the AES output channels (0..7); to enable/disable mute use the SET_MUTE_AES_OUTPUT_CHANNEL macro; to query an AES output channels mute status set VT.ulVal to the AES output channel number (0..7) then call QueryCardProperty(); the return value will be 1 = muted or 0 = enabled; set .vt to VT_UI4 */ FORCE_SD_VBI_OUTPUT_BUFFER_TO_V210 = 134, /* this card property forces the VBI output buffer to V210 memory format in SD video modes (default for HD video modes) so that it can handle 10 bit VANC packets. set 1 = force to V210 or 0 = follow video memory fomat (default); set .vt to VT_UI4; when changing this property the video output mode and video output engine need to be set again manually! */ EMBEDDED_AUDIO_INPUT_INFO = 135, /* this card property returns info on how which embedded audio input channels are available (channel mask for channels 1 - 16 in lower 16 bits). it also returns the data payload for each channel (1 - 16) in the upper 16 bits (0 = embedded audio, 1 = other (e.g. Dolby Digital)) */ OVERRIDE_OUTPUT_VPID_DEFAULT = 136, /* this card property should only be used for debugging purposes if the default VPID needs to be changed; it will override the output VPID that is set up by default depending on the video mode, pixel format and signal format type. this property takes a 64 bit value (set .vt to VT_UI8) and is defined as follows (there are helper MACROS defined in the MACROS section at the end of this header file): 7...0: Byte 1 of VPID 15...8: Byte 2 of VPID 23..16: Byte 3 of VPID 31..24: Byte 4 of VPID 47..32: SDI output connector (EBlueConnectorIdentifier) 62..48: reserved (set to 0) 63: enable/disable VPID output (0 = disabled, 1 = enabled) */ FORCE_SD_VBI_INPUT_BUFFER_TO_V210 = 137, /* this card property forces the VBI input buffer to V210 memory format in SD video modes (default for HD video modes) so that it can handle 10 bit VANC packets. set 1 = force to V210 or 0 = follow video memory fomat (default); set .vt to VT_UI4; when changing this property the video input engine needs to be set again manually! */ VIDEO_CARDPROPERTY_INVALID = 1000 }EBlueCardProperty; typedef enum _EHdSdiTransport { HD_SDI_TRANSPORT_1_5G = 0x1, /* HD as 1.5G */ HD_SDI_TRANSPORT_3G_LEVEL_A = 0x2, /* 3G Level A */ HD_SDI_TRANSPORT_3G_LEVEL_B = 0x3, /* 3G Level B */ }EHdSdiTransport; typedef enum _EAudioMetaDataSettings { AUDIO_METADATA_KEEP_ALIVE = 0x1 /* When setting this bit for the EPOCH_AUDIOOUTPUT_METADATA_SETTINGS card property the audio meta data (like RP188 timecode will still be played out even after stopping audio playback; this is a static settings and only needs to be set once; it is channel based and can be changed for all output channels independently */ }EAudioMetaDataSettings; typedef enum _EAnalogConnectorSignalType { ANALOG_OUTPUTSIGNAL_CVBS_Y_C=1, ANALOG_OUTPUTSIGNAL_COMPONENT=2, ANALOG_OUTPUTSIGNAL_RGB=4 }EAnalogConnectorSignalType; /**< @brief Use this enumerator to set the analog video signal types and connectors. */ typedef enum _EAnalogInputConnectorType { /* Composite input */ ANALOG_VIDEO_INPUT_CVBS_AIN1=0x00, /**> BLUE_CARD_BUFFER_TYPE_OFFSET) #define GetDMADataType(value) ((value & 0xF0000) >> BLUE_DMA_DATA_TYPE_OFFSET) #define GetDMAFlags(value) ((value & 0xF00000) >> (BLUE_DMA_FLAGS_OFFSET)) #define GetEpochDMAFlags(value) ((value & 0xFF00000) >> (BLUE_DMA_FLAGS_OFFSET)) #define Blue_DMABuffer(CardBufferType,BufferId,DataType) ( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \ ( CardBufferType<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \ ( ((ULONG)BufferId&0xFFF)) |0) #define BlueImage_VBI_DMABuffer(BufferId,DataType) ( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \ ( BLUE_CARDBUFFER_IMAGE_VBI<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \ ( ((ULONG)BufferId&0xFFF)) |0) #define BlueImage_DMABuffer(BufferId,DataType) ( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \ ( BLUE_CARDBUFFER_IMAGE<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \ ( ((ULONG)BufferId&0xFFF)) |0) #define BlueImage_VBI_HANC_DMABuffer(BufferId,DataType) ( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \ ( BLUE_CARDBUFFER_IMAGE_VBI_HANC<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \ ( ((ULONG)BufferId&0xFFF)) |0) #define BlueImage_HANC_DMABuffer(BufferId,DataType) ( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \ ( BLUE_CARDBUFFER_IMAGE_HANC<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \ ( ((ULONG)BufferId&0xFFF)) |0) #define BlueBuffer(CardBufferType,BufferId) (((CardBufferType)<>8) #define SET_ANALOG_AUDIO_ROUTINGCHANNEL(left,right) (((right & 0xFF)<<8)|(left & 0xFF)) #define SET_AUDIO_OUTPUT_ROUTINGCHANNEL(output_type,src_channel_id,_output_channel_id) ((1<<31)|((output_type&3)<<29)|((_output_channel_id &0x3F)<<23)|((src_channel_id & 0x3F)<<16)) #define GET_AUDIO_OUTPUT_SRC_CHANNEL_ROUTING(value) ((value>>16) & 0x3F) #define GET_AUDIO_OUTPUT_CHANNEL_ROUTING(value) ((value>>23) & 0x3F) #define GET_AUDIO_OUTPUT_TYPE_ROUTING(value) ((value & 0x60000000)>>29) //AES_OUTPUT_ROUTING #define SET_AES_OUTPUT_ROUTING(OutputVideoChannel, AudioSrcChannel, AudioDstChannel) (((OutputVideoChannel & 0xFF) << 16) | ((AudioDstChannel & 0xFF) << 8) | (AudioSrcChannel & 0xFF)) #define GET_AES_OUTPUT_ROUTING_STREAM(value) ((value >> 16) & 0xFF) #define GET_AES_OUTPUT_ROUTING_DST_CHANNEL(value) ((value >> 8) & 0xFF) #define GET_AES_OUTPUT_ROUTING_SRC_CHANNEL(value) (value & 0xFF) //MUTE_AES_OUTPUT_CHANNEL #define SET_MUTE_AES_OUTPUT_CHANNEL(AudioDstChannel, Mute) (((Mute & 0x1) << 31) | AudioDstChannel & 0xFF) #define AUDIO_INPUT_SOURCE_SELECT_FLAG (1<<16) #define AUDIO_INPUT_SOURCE_SELECT(SynchCount,AudioInputSource) (AUDIO_INPUT_SOURCE_SELECT_FLAG|(SynchCount)|(AudioInputSource<<17)) struct blue_video_connection_routing_struct { BLUE_UINT32 video_channel; BLUE_UINT32 duallink_flag; BLUE_UINT32 link1_connector; BLUE_UINT32 link2_connector; }; #pragma pack(push, video_sync_struct, 1) typedef struct _blue_video_sync_struct { BLUE_UINT32 sync_wait_type; // field or frame (UPD_FMT_FIELD or UPD_FMT_FRAME) BLUE_UINT32 video_channel; // which video channel interrupt should the interrupt wait for, e.g. BLUE_VIDEO_INPUT_CHANNEL_A, BLUE_VIDEO_OUTPUT_CHANNEL_A, etc. BLUE_UINT32 timeout_video_msc; // field count when to return or IGNORE_SYNC_WAIT_TIMEOUT_VALUE to return at next field/frame sync BLUE_UINT32 video_msc; // current video msc (field count) BLUE_UINT32 current_display_frame_id; // current buffer id which is being displayed BLUE_UINT32 current_display_frame_uniqueid; // unique id associated with current buffer id which is being displayed // this is only valid when using fifo modes. BLUE_UINT16 subfield_interrupt; // subfield interrupt number; 0 == main frame sync BLUE_UINT16 subfield_lines; // number of lines of video captured at this subfield interrupt BLUE_UINT64 btcTimeStamp; // Coordinated Bluefish Time timestamp of field/frame which is currently being displayed BLUE_UINT8 pad[12]; }blue_video_sync_struct; struct blue_external_ltc_input_sync_struct { BLUE_UINT64 TimeCodeValue; BLUE_UINT32 TimeCodeIsValid; BLUE_UINT8 pad[20]; }; #pragma pack(pop,video_sync_struct) typedef enum _EBlueLUTType { BLUE_MAIN_LUT_B_Pb=0, BLUE_MAIN_LUT_G_Y=1, BLUE_MAIN_LUT_R_Pr=2, BLUE_AUX_LUT_B_Pb=3, BLUE_AUX_LUT_G_Y=4, BLUE_AUX_LUT_R_Pr=5, }EBlueLUTType; #pragma pack(push, video_frame, 1) struct VideoFeature_struct { BLUE_UINT32 Type; // Bluefish card type BLUE_UINT32 CardSubType; BLUE_UINT32 Bus; // Which PIC bus (bridge) it is on BLUE_UINT32 Slot; // Which slot card is plugged into BLUE_UINT32 Feature; // Look at the _EBlueFishCardFeatures definition to know what each bit mean BLUE_UINT32 FirmwareVersion; }; struct blue_videoframe_info { BLUE_UINT64 ltcTimeCode; unsigned long videochannel; unsigned long BufferId; unsigned long Count; unsigned long DroppedFrameCount; }; struct blue_videoframe_info_ex { BLUE_UINT64 ltcTimeCode; //LTC timecode, not used unsigned long videochannel; //the channel this frame was captured from long BufferId; //this buffer contains the captured frame unsigned long Count; //total captured frames unsigned long DroppedFrameCount; //dropped frame count unsigned long nFrameTimeStamp; //field count the frame was captured at unsigned long nVideoSignalType; //video mode of this frame unsigned int nASIPktCount; //only for DVB-ASI; how many ASI packets are in this frame unsigned int nASIPktSize; //only for DVB-ASI; how many bytes per packet unsigned int nAudioValidityBits; //part of the channels status block for audio BLUE_UINT64 btcTimeStamp; //Coordinated Bluefish Time timestamp unsigned char ucVideoModeLinkA; //only used in 1.5G dual link mode unsigned char ucVideoModeLinkB; //only used in 1.5G dual link mode unsigned char pad[10]; //not used }; struct blue_1d_lookup_table_struct { BLUE_UINT32 nVideoChannel; BLUE_UINT32 nLUTId; BLUE_UINT16 * pLUTData; BLUE_UINT32 nLUTElementCount; BLUE_UINT8 pad[256]; }; #pragma pack(pop, video_frame) #pragma pack(push, blue_dma_request, 1) struct blue_dma_request_struct { unsigned char * pBuffer; BLUE_UINT32 video_channel; BLUE_UINT32 BufferId; unsigned int BufferDataType; unsigned int FrameType; unsigned int BufferSize; unsigned int Offset; unsigned long BytesTransferred; unsigned char pad[64]; }; enum SerialPort_struct_flags { SerialPort_Read=1, SerialPort_Write=2, SerialPort_TX_Queue_Status=4, SerialPort_RX_Queue_Status=8, SerialPort_RX_FlushBuffer=16, SerialPort_RX_IntWait_Return_On_Data=32, }; struct SerialPort_struct { unsigned char Buffer[64]; unsigned int nBufLength; unsigned int nSerialPortId; unsigned int bFlag; // SerialPort_struct_flags unsigned short sTimeOut; }; struct blue_video_scaler_ceofficent { BLUE_UINT32 ioctl_read_only_flag; BLUE_UINT32 nScalerId; BLUE_UINT32 nScalerFilterType; BLUE_UINT32 nScalerCoefficentWeight[15]; }; enum blue_video_scaler_param_flags { scaler_flags_set_destrect_as_framesize = 0x1, }; struct blue_video_scaler_param_struct { BLUE_UINT32 ioctl_read_only_flag; BLUE_UINT32 nScalerId; BLUE_UINT32 nSrcVideoHeight; BLUE_UINT32 nSrcVideoWidth; BLUE_UINT32 nSrcVideoYPos; BLUE_UINT32 nSrcVideoXPos; BLUE_UINT32 nDestVideoHeight; BLUE_UINT32 nDestVideoWidth; BLUE_UINT32 nDestVideoYPos; BLUE_UINT32 nDestVideoXPos; BLUE_UINT32 nHScaleFactor; BLUE_UINT32 nVScaleFactor; BLUE_UINT32 nScalerOutputVideoMode; BLUE_UINT32 nScalerParamFlags; BLUE_UINT32 nScalerOutputRasterVideoMode; BLUE_UINT32 nScalerOutputRasterHeight; BLUE_UINT32 nScalerOutputRasterWidth; BLUE_UINT32 pad[125]; }; #ifndef EXCLUDE_USERLAND_STRUCT struct blue_color_matrix_struct{ BLUE_UINT32 VideoChannel; BLUE_UINT32 MatrixColumn; //MatrixColType enumerator defines this double Coeff_B; double Coeff_R; double Coeff_G; double Coeff_K; double const_value; }; #endif #pragma pack(pop, blue_dma_request) typedef enum _blue_output_hanc_ioctl_enum { blue_get_output_hanc_buffer = 0, blue_put_output_hanc_buffer = 1, blue_get_valid_silent_hanc_data_status = 3, blue_set_valid_silent_hanc_data_status = 4, blue_start_output_fifo = 5, blue_stop_output_fifo = 6, blue_init_output_fifo = 7, blue_get_queues_info = 8, blue_get_output_fifo_info=blue_get_queues_info, blue_get_output_fifo_status = 9, blue_start_output_fifo_no_auto_turn_off = 10 // this is used when we don't really use the FIFO, but handle audio playback ourselves in DirectShow; // need to make sure that our HANC output FIFO doesn't turn off audio as there are never any HANC frames to be played }blue_output_hanc_ioctl_enum; typedef enum _blue_input_hanc_ioctl_enum { blue_get_input_hanc_buffer=0, blue_start_input_fifo=3, blue_stop_input_fifo=4, blue_init_input_fifo=5, blue_playthru_input_fifo=6, blue_release_input_hanc_buffer=7, blue_map_input_hanc_buffer=8, blue_unmap_input_hanc_buffer=9, blue_get_info_input_hanc_fifo=10, blue_get_input_rp188=11, blue_get_input_fifo_status=12, }blue_input_hanc_ioctl_enum; #define HANC_PLAYBACK_INIT (0x00000001) #define HANC_PLAYBACK_START (0x00000002) #define HANC_PLAYBACK_STOP (0x00000004) #define HANC_CAPTURE_INIT (0x00000010) #define HANC_CAPTURE_START (0x00000020) #define HANC_CAPTURE_STOP (0x00000040) #define HANC_CAPTURE_PLAYTHRU (0x00000080) typedef enum _EOracFPGAConfigCMD { ORAC_FPGA_CONFIG_CMD_ERASE_SECTOR=0, ORAC_FPGA_CONFIG_CMD_UNLOCK_SECTOR=1, ORAC_FPGA_CONFIG_CMD_WRITE_DATA=2, ORAC_FPGA_CONFIG_CMD_STATUS=3, ORAC_FPGA_CONFIG_CMD_READMODE=4, ORAC_FPGA_CONFIG_RAW_WRITE=5, ORAC_FPGA_CONFIG_RAW_READ=6, ORAC_FPGA_CONFIG_CMD_READ_DATA=7, ORAC_FPGA_CONFIG_INIT=8, ORAC_FPGA_CONFIG_EXIT=9 }EOracFPGAConfigCMD; #define ANALOG_CHANNEL_0 MONO_CHANNEL_9 #define ANALOG_CHANNEL_1 MONO_CHANNEL_10 /*Assumes that the data is in stereo pairs not individual samples*/ #define STEREO_PAIR_1 (MONO_CHANNEL_1|MONO_CHANNEL_2) /* Mono Channel 1 & Mono channel 2* together*/ #define STEREO_PAIR_2 (MONO_CHANNEL_3|MONO_CHANNEL_4) /* Mono Channel 3 & Mono Channel 4* together*/ #define STEREO_PAIR_3 (MONO_CHANNEL_5|MONO_CHANNEL_6) /* Mono Channel 5 & Mono Channel 6* together*/ #define STEREO_PAIR_4 (MONO_CHANNEL_7|MONO_CHANNEL_8) /* Mono Channel 7 & Mono Channel 8* together*/ #define ANALOG_AUDIO_PAIR (ANALOG_CHANNEL_0|ANALOG_CHANNEL_1) #define BLUE_LITTLE_ENDIAN 0 #define BLUE_BIG_ENDIAN 1 #define GREED_SILENT_HANC_BUFFER1 250 #define GREED_SILENT_HANC_BUFFER2 251 #define AES_SRC_BYPASS_CHANNEL_1_2 0x1 #define AES_SRC_BYPASS_CHANNEL_3_4 0x2 #define AES_SRC_BYPASS_CHANNEL_5_6 0x4 #define AES_SRC_BYPASS_CHANNEL_7_8 0x8 typedef enum _EEpochRoutingElements { EPOCH_SRC_DEST_SCALER_0=0x1, EPOCH_SRC_DEST_SCALER_1, EPOCH_SRC_DEST_SCALER_2, EPOCH_SRC_DEST_SCALER_3, EPOCH_SRC_SDI_INPUT_A, EPOCH_SRC_SDI_INPUT_B, EPOCH_SRC_SDI_INPUT_C, EPOCH_SRC_SDI_INPUT_D, EPOCH_SRC_SDI_INPUT_A_3GB_LINK_A = EPOCH_SRC_SDI_INPUT_A, EPOCH_SRC_SDI_INPUT_B_3GB_LINK_A = EPOCH_SRC_SDI_INPUT_B, EPOCH_SRC_SDI_INPUT_C_3GB_LINK_A = EPOCH_SRC_SDI_INPUT_C, EPOCH_SRC_SDI_INPUT_D_3GB_LINK_A = EPOCH_SRC_SDI_INPUT_D, EPOCH_DEST_SDI_OUTPUT_A, EPOCH_DEST_SDI_OUTPUT_B, EPOCH_DEST_SDI_OUTPUT_C, EPOCH_DEST_SDI_OUTPUT_D, EPOCH_DEST_SDI_OUTPUT_A_3GB_LINK_A = EPOCH_DEST_SDI_OUTPUT_A, EPOCH_DEST_SDI_OUTPUT_B_3GB_LINK_A = EPOCH_DEST_SDI_OUTPUT_B, EPOCH_DEST_SDI_OUTPUT_C_3GB_LINK_A = EPOCH_DEST_SDI_OUTPUT_C, EPOCH_DEST_SDI_OUTPUT_D_3GB_LINK_A = EPOCH_DEST_SDI_OUTPUT_D, EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA, EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHB, EPOCH_DEST_INPUT_MEM_INTERFACE_CHA, EPOCH_DEST_INPUT_MEM_INTERFACE_CHB, EPOCH_DEST_AES_ANALOG_AUDIO_OUTPUT, EPOCH_SRC_AV_SIGNAL_GEN, EPOCH_SRC_DEST_VPIO_SCALER_0, EPOCH_SRC_DEST_VPIO_SCALER_1, EPOCH_DEST_VARIVUE_HDMI, EPOCH_DEST_INPUT_MEM_INTERFACE_CHC, EPOCH_DEST_INPUT_MEM_INTERFACE_CHD, EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC, EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHD, EPOCH_SRC_SDI_INPUT_A_3GB_LINK_B, EPOCH_SRC_SDI_INPUT_B_3GB_LINK_B, EPOCH_SRC_SDI_INPUT_C_3GB_LINK_B, EPOCH_SRC_SDI_INPUT_D_3GB_LINK_B, EPOCH_DEST_SDI_OUTPUT_A_3GB_LINK_B, EPOCH_DEST_SDI_OUTPUT_B_3GB_LINK_B, EPOCH_DEST_SDI_OUTPUT_C_3GB_LINK_B, EPOCH_DEST_SDI_OUTPUT_D_3GB_LINK_B, EPOCH_DEST_HDMI_OUTPUT, EPOCH_DEST_HDMI_OUTPUT_LINK_A = EPOCH_DEST_HDMI_OUTPUT, EPOCH_DEST_HDMI_OUTPUT_LINK_B, }EEpochRoutingElements; #define VPEnableFieldCountTrigger ((BLUE_UINT64)1<<63) #define VPTriggerGetFieldCount(value) ((BLUE_UINT64)value & 0xFFFFFFFF) typedef enum _EBlueScalerFilterType { BlueScalerHorizontalYFilter=1, BlueScalerHorizontalCFilter=2, BlueScalerVerticalYFilter=3, BlueScalerVerticalCFilter=4, }EBlueScalerFilterType; typedef enum _EBFLockSignalType { BFLOCK_SIGNAL_UNKNOWN = 0x1000, BFLOCK_SIGNAL_2398 = 0x1001, BFLOCK_SIGNAL_2400 = 0x1002, BFLOCK_SIGNAL_2500 = 0x1003, BFLOCK_SIGNAL_2997 = 0x1004, BFLOCK_SIGNAL_3000 = 0x1005, BFLOCK_SIGNAL_4795 = 0x1006, BFLOCK_SIGNAL_4800 = 0x1007, BFLOCK_SIGNAL_5000 = 0x1008, BFLOCK_SIGNAL_5994 = 0x1009, BFLOCK_SIGNAL_6000 = 0x100A, }EBFLockSignalType; #define SET_EPOCH_SCALER_MODE(scaler_id,video_mode) ((scaler_id <<16)|video_mode) #define GET_EPOCH_SCALER_MODE(value) (value&0xFFFF) #define GET_EPOCH_SCALER_ID(value) ((value&0xFFFF0000)>>16) // use these macros for retreiving the temp and fan speed. // on epoch range of cards. #define EPOCH_CORE_TEMP(value) (value & 0xFF) #define EPOCH_BOARD_TEMP(value) ((value>>16) & 0xFF) #define EPOCH_FAN_SPEED(value) ((value>>24) & 0xFF) /** @desc use these macro for doing the MR2 routing on epoch range of cards. MR2 routing can be controlled using the property MR_ROUTING. */ #define EPOCH_SET_ROUTING(routing_src,routing_dest,data_link_type) ((routing_src & 0xFF) | ((routing_dest & 0xFF)<<8) | ((data_link_type&0xFFFF)<<16)) #define EPOCH_ROUTING_GET_SRC_DATA(value) (value & 0xFF) #define EPOCH_ROUTING_GET_DEST_DATA(value) ((value>>8) & 0xFF) #define EPOCH_ROUTING_GET_LINK_TYPE_DATA(value) ((value>>16) & 0xFFFF) #define GPIO_TX_PORT_A (1) #define GPIO_TX_PORT_B (2) #define EPOCH_GPIO_TX(port,value) (port<<16|value) // if want to set each of the GPO // ports individually you should use this macro. // without the macro it would set both the GPO // ports on the card /** @desc use these macros for controlling epoch application watch dog settings. The card property EPOCH_APP_WATCHDOG_TIMER can be used to control the watchdog timer functionality. */ enum enum_blue_app_watchdog_timer_prop { enum_blue_app_watchdog_timer_start_stop=(1<<31), // can be used to enable/disable timer enum_blue_app_watchdog_timer_keepalive=(1<<30), // can be used to reset the timer value enum_blue_app_watchdog_timer_get_present_time=(1<<29), // can query to get the value of the timer enum_blue_app_watchdog_get_timer_activated_status=(1<<28), // can query to get whether the timer has been activated enum_blue_app_watchdog_get_timer_start_stop_status=(1<<27), // can query whether the timer has been set. enum_blue_app_watchdog_enable_gpo_on_active=(1<<26), // using this enumerator you can tell the system that when // application watchdog timer has expired whether a GPO output should be triggered or not. // you can use also use this enumerator to select // which GPO output should be triggered with this. to use GPO port A pass a value of // GPIO_TX_PORT_A when this enumerator is used. enum_blue_hardware_watchdog_enable_gpo=(1<<25) // can be used to enable/disable GPO trigger when hardware watchdog timer has been // triggered }; #define EPOCH_WATCHDOG_TIMER_SET_MACRO(prop,value) (prop|(value &0xFFFF)) #define EPOCH_WATCHDOG_TIMER_QUERY_MACRO(prop) (prop) #define EPOCH_WATCHDOG_TIMER_GET_VALUE_MACRO(value) (value&0xFFFF) enum enum_blue_rs422_port_flags { enum_blue_rs422_port_set_as_slave =(1<<0) // If this flag is set the RS422 port would be set to slave mode. // by default port is setup to work in master mode , where it would be acting // as master in the transactions. }; #define EPOCH_RS422_PORT_FLAG_SET_MACRO(portid,value) ((portid&0x3)|(value<<3)) #define EPOCH_RS422_PORT_FLAG_GET_FLAG_MACRO(value) ((value>>3)&0xFFFF) #define EPOCH_RS422_PORT_FLAG_GET_PORTID_MACRO(value) (value&0x3) enum enum_blue_dvb_asi_packing_format { enum_blue_dvb_asi_packed_format=1,/**< In this packing method the asi packets are stored as 188 or 204 bytes*/ enum_blue_dvb_asi_packed_format_with_timestamp=2,/**< In this packing method the asi packets are stored as (8+188) or (8+204) bytes The timestamp is stored at the begininig of the packet , using 8 bytes*/ enum_blue_dvb_asi_256byte_container_format=3, enum_blue_dvb_asi_256byte_container_format_with_timestamp=4 }; enum enum_blue_dvb_asi_packet_size { enum_blue_dvb_asi_packet_size_188_bytes = 1, enum_blue_dvb_asi_packet_size_204_bytes = 2 }; #define RS422_SERIALPORT_FLAG(timeout,port,RxFlushBuffer) (((unsigned long)(timeout)<<16)|(port & 0x3) | (RxFlushBuffer<<15)) // use this macro with Wait_For_SerialPort_InputData, // if you you want the function to return // immediatelty when it gets byte in the serial RX port. #define RS422_SERIALPORT_FLAG2(timeout,port,RxFlushBuffer,RXIntWaitReturnOnAvailData) (((unsigned long)(timeout)<<16)|(port & 0x3) | (RxFlushBuffer<<15)|(RXIntWaitReturnOnAvailData<<14)) typedef enum _blue_blackgenerator_status { ENUM_BLACKGENERATOR_OFF = 0, //producing normal video output ENUM_BLACKGENERATOR_ON = 1, //producing black video output ENUM_BLACKGENERATOR_SDI_SYNC_OFF = 2 //no valid SDI signal is coming out of our SDI output connector; only available in Epoch ASI firmware }blue_blackgenerator_status; typedef enum _EBlueExternalLtcSource { EXT_LTC_SRC_BREAKOUT_HEADER = 0, //default; header on the PCB board/Shield EXT_LTC_SRC_GENLOCK_BNC = 1 //Genlock BNC connector }EBlueExternalLtcSource; //////////////////////////////////////////////////////////////////////////////////// //H E L P E R M A C R O S //////////////////////////////////////////////////////////////////////////////////// //the following macros are used with card property OVERRIDE_OUTPUT_VPID_DEFAULT #define OUTPUT_VPID_SET_ENABLED(value) ((value) |= 0x8000000000000000ULL ) #define OUTPUT_VPID_SET_DISABLED(value) ((value) &= ~(0x8000000000000000ULL)) #define OUTPUT_VPID_SET_BYTES(value, byte1, byte2, byte3, byte4) (value = ((value & 0xFFFFFFFF00000000ULL) | ((((BLUE_UINT64)(byte4 & 0xFF)) << 24) | ((byte3 & 0xFF) << 16) | ((byte2 & 0xFF) << 8) | (byte1 & 0xFF)))) #define OUTPUT_VPID_SET_SDI_CONNECTOR(value, outputconnector) (value = ((value & 0xFFFF0000FFFFFFFFULL) | ((outputconnector & 0xFFFFULL) << 32))) #define OUTPUT_VPID_GET_ENABLED(value) ((value) & 0x8000000000000000ULL ) #define OUTPUT_VPID_GET_SDI_CONNECTOR(value) ((value >> 32) & 0xFFFFULL) #define OUTPUT_VPID_GET_VPID_BYTE1(value) (value & 0xFFLL) #define OUTPUT_VPID_GET_VPID_BYTE2(value) ((value >> 8) & 0xFFULL) #define OUTPUT_VPID_GET_VPID_BYTE3(value) ((value >> 16) & 0xFFULL) #define OUTPUT_VPID_GET_VPID_BYTE4(value) ((value >> 24) & 0xFFULL) //the following macros are used with card property INTERLOCK_REFERENCE #define INTERLOCK_REFERENCE_GET_OUTPUT_ENABLED(value) ((value) & 0x01) #define INTERLOCK_REFERENCE_GET_INPUT_DETECTED(value) ((value >> 1) & 0x01) #define INTERLOCK_REFERENCE_GET_SLAVE_POSITION(value) ((value >> 2) & 0x1F) //the following macros are used with card property CARD_FEATURE_STREAM_INFO #define CARD_FEATURE_GET_SDI_OUTPUT_STREAM_COUNT(value) ((value) & 0xF) #define CARD_FEATURE_GET_SDI_INPUT_STREAM_COUNT(value) ((value >> 4) & 0xF) #define CARD_FEATURE_GET_ASI_OUTPUT_STREAM_COUNT(value) ((value >> 8) & 0xF) #define CARD_FEATURE_GET_ASI_INPUT_STREAM_COUNT(value) ((value >> 12) & 0xF) #define CARD_FEATURE_GET_3G_SUPPORT(value) ((value >> 16) & 0xF) //the following macros are used with card property CARD_FEATURE_CONNECTOR_INFO #define CARD_FEATURE_GET_SDI_OUTPUT_CONNECTOR_COUNT(value) ((value) & 0xF) #define CARD_FEATURE_GET_SDI_INPUT_CONNECTOR_COUNT(value) ((value >> 4) & 0xF) #define CARD_FEATURE_GET_AES_CONNECTOR_SUPPORT(value) ((value >> 8) & 0x1) #define CARD_FEATURE_GET_RS422_CONNECTOR_SUPPORT(value) ((value >> 9) & 0x1) #define CARD_FEATURE_GET_LTC_CONNECTOR_SUPPORT(value) ((value >> 10) & 0x1) #define CARD_FEATURE_GET_GPIO_CONNECTOR_SUPPORT(value) ((value >> 11) & 0x1) #define CARD_FEATURE_GET_HDMI_CONNECTOR_SUPPORT(value) ((value >> 12) & 0x1) //the following macros are used with card property VIDEO_ONBOARD_KEYER #define VIDEO_ONBOARD_KEYER_GET_STATUS_ENABLED(value) ((value) & 0x1) #define VIDEO_ONBOARD_KEYER_GET_STATUS_OVER_BLACK(value) ((value) & 0x2) #define VIDEO_ONBOARD_KEYER_GET_STATUS_USE_INPUT_ANCILLARY(value) ((value) & 0x4) #define VIDEO_ONBOARD_KEYER_GET_STATUS_DATA_IS_PREMULTIPLIED(value) ((value) & 0x8) #define VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLED(value) (value |= 0x1) #define VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLED(value) (value &= ~(0x1)) #define VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLE_OVER_BLACK(value) (value |= 0x2) #define VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(value) (value &= ~(0x2)) #define VIDEO_ONBOARD_KEYER_SET_STATUS_USE_INPUT_ANCILLARY(value) (value |= 0x4) //only use this setting when keying over valid input (input must also match output video mode), includes HANC and VANC #define VIDEO_ONBOARD_KEYER_SET_STATUS_USE_OUTPUT_ANCILLARY(value) (value &= ~(0x4)) #define VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_PREMULTIPLIED(value) (value |= 0x8) #define VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_NOT_PREMULTIPLIED(value) (value &= ~(0x8)) //the following macros are used with card property EPOCH_HANC_INPUT_FLAGS #define HANC_FLAGS_IS_ARRI_RECORD_FLAG_SET(value) ((value) & 0x1) //the following macros are used with card property EPOCH_RAW_VIDEO_INPUT_TYPE #define RAW_VIDEO_INPUT_TYPE_IS_10BIT (0x01) #define RAW_VIDEO_INPUT_TYPE_IS_12BIT (0x02) #define RAW_VIDEO_INPUT_TYPE_IS_WEISSCAM (0x10) #define RAW_VIDEO_INPUT_TYPE_IS_ARRI (0x20) //the following macros are used with card property EPOCH_PCIE_CONFIG_INFO #define PCIE_CONFIG_INFO_GET_MAX_PAYLOAD_SIZE(value) ((value) & 0xFFFF) #define PCIE_CONFIG_INFO_GET_MAX_READREQUEST_SIZE(value) ((value >> 16) & 0xFFFF) #endif //_BLUEDRIVER_P_H__ server-2.2.0-stable/src/modules/bluefish/interop/BlueHancUtils.h000066400000000000000000000335351341175263200247010ustar00rootroot00000000000000/* -LICENSE-START- ** Copyright (c) 2018 Bluefish Technologies ** ** Permission is hereby granted, free of charge, to any person or organization ** obtaining a copy of the software and accompanying documentation covered by ** this license (the "Software") to use, reproduce, display, distribute, ** execute, and transmit the Software, and to prepare derivative works of the ** Software, and to permit third-parties to whom the Software is furnished to ** do so, all subject to the following: ** ** The copyright notices in the Software and this entire statement, including ** the above license grant, this restriction and the following disclaimer, ** must be included in all copies of the Software, in whole or in part, and ** all derivative works of the Software, unless such copies or derivative ** works are solely in the form of machine-executable object code generated by ** a source language processor. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ** DEALINGS IN THE SOFTWARE. ** -LICENSE-END- */ #pragma once #ifndef __linux__ #ifndef HANCUTILS_USE_STATIC_LIB #ifdef HANCUTILS_EXPORTS #define HANCUTILS_API __declspec(dllexport) #elif defined(__APPLE__) #define HANCUTILS_API #define //ATLTRACE printf #else #define HANCUTILS_API __declspec(dllimport) #endif #else #define HANCUTILS_API #endif #else #define HANCUTILS_API typedef bool BOOL; #endif #include "BlueDriver_p.h" #ifdef __cplusplus extern "C" { #endif /** @defgroup hanc_manipilation_function Embedded audio @{ */ #pragma pack(push, hanc_struct, 1) /** @brief The structure is used to extract/insert Embedded audio to and from the HANC stream of Greed and Leon based cards.*/ struct hanc_stream_info_struct { BLUE_INT32 AudioDBNArray[4]; /**< Contains the DBN values that should be used for each of the embedded audio groups; for default set to -1 */ BLUE_INT32 AudioChannelStatusBlock[4]; /**< channel status block information for each of the embedded audio group*/ BLUE_UINT32 flag_valid_time_code; /**< deprecated/unused flag; set to 0*/ BLUE_UINT64 time_code; /**< -->RP188 VITC timecode */ BLUE_UINT32* hanc_data_ptr; /**< Hanc Buffer which should be used as the source or destination for either extraction or insertion */ BLUE_UINT32 video_mode; /**< video mode which this hanc buffer which be used with. We need this information for do the required audio distribution especially NTSC */ BLUE_UINT64 ltc_time_code; /**< -->External LTC timecode */ BLUE_UINT64 sd_vitc_time_code; /**< -->SD VITC timecode */ BLUE_UINT64 rp188_ltc_time_code; /**< -->RP188 LTC timecode */ BLUE_UINT32 pad[126]; }; #define AUDIO_INPUT_SOURCE_EMB 0 #define AUDIO_INPUT_SOURCE_AES 1 struct hanc_decode_struct { void* audio_pcm_data_ptr; // Buffer which would be used to store the extracted PCM // audio data. // Must be filled in by app before calling function. BLUE_UINT32 audio_ch_required_mask; // Defines which audio channels should be extracted; // Use enumerator BlueAudioChannelDesc to set up this mask. // Must be filled in by app before calling function. BLUE_UINT32 type_of_sample_required;// Defines sample characteristics: // AUDIO_CHANNEL_16BIT: for 16 bit pcm data // AUDIO_CHANNEL_24BIT: for 24 bit pcm data // If neither AUDIO_CHANNEL_16BIT nor AUDIO_CHANNEL_24BIT are set 32 bit pcm data will be extracted // Must be filled in by app before calling function. BLUE_UINT32 no_audio_samples; // this would contain how many audio samples has been decoded from // the hanc buffer. BLUE_UINT64 timecodes[7]; // Only the first four elements are currently defined: // hanc_decode_struct::timcodes[0] ---> RP188 VITC timecode // hanc_decode_struct::timcodes[1] ---> RP188 LTC timecode // hanc_decode_struct::timcodes[2] ---> SD VITC timecode // hanc_decode_struct::timcodes[3] ---> External LTC timecode void * raw_custom_anc_pkt_data_ptr; // This buffer would contain the raw ANC packets that was found in the orac hanc buffer. // this would contain any ANC packets that is not of type embedded audio and RP188 TC. // Must be filled in by app before calling function. can be NULL BLUE_UINT32 sizeof_custom_anc_pkt_data_ptr; // size of the ANC buffer array // Must be filled in by app before calling function. can be NULL BLUE_UINT32 avail_custom_anc_pkt_data_bytes;// how many custom ANC packets has been decoded into raw_hanc_pkt_data_ptr // Must be filled in by app before calling function. can be NULL BLUE_UINT32 audio_input_source; // Used to select the audio input source. // whether it is AES or Embedded. // Must be filled in by app before calling function. BLUE_UINT32 audio_temp_buffer[16]; // deprecated/not used; // this is used to store split audio sample // which did not contain all its audio channels // in one audio frame // Must be initialised to zero by app before first instantiating the function. BLUE_UINT32 audio_split_buffer_mask; //deprecated/not used; // The mask would be used to make a note of // split audio sample information for a frame. // Must be initialised to zero by app before first instantiating the function. BLUE_UINT32 max_expected_audio_sample_count;// specify the maximum number of audio samples // that the provided audio pcm buffer can contain. // Must be filled in by app before calling function. BLUE_UINT32 pad[124]; }; #pragma pack(pop, hanc_struct) #if defined(_WIN32_) __declspec(deprecated("Deprecated. Do not use.")) #endif HANCUTILS_API BLUE_UINT32 encode_hanc_frame(struct hanc_stream_info_struct* hanc_stream_ptr, void* audio_pcm_ptr, BLUE_UINT32 no_audio_ch, BLUE_UINT32 no_audio_samples, BLUE_UINT32 nTypeOfSample, BLUE_UINT32 emb_audio_flag); HANCUTILS_API BLUE_UINT32 encode_hanc_frame_ex( BLUE_UINT32 card_type, struct hanc_stream_info_struct* hanc_stream_ptr, void* audio_pcm_ptr, BLUE_UINT32 no_audio_ch, BLUE_UINT32 no_audio_samples, BLUE_UINT32 nTypeOfSample, BLUE_UINT32 emb_audio_flag); HANCUTILS_API BLUE_UINT32 encode_hanc_frame_with_ucz( BLUE_UINT32 card_type, struct hanc_stream_info_struct* hanc_stream_ptr, void* audio_pcm_ptr, BLUE_UINT32 no_audio_ch, BLUE_UINT32 no_audio_samples, BLUE_UINT32 nTypeOfSample, BLUE_UINT32 emb_audio_flag, BLUE_UINT8* pUCZBuffer); #if defined(_WIN32_) __declspec(deprecated("Deprecated. Do not use.")) #endif HANCUTILS_API BLUE_UINT32 create_embed_audiosample( void* raw_data_ptr, BLUE_UINT32* emb_data_ptr, BLUE_UINT32 channels_per_audio_sample, BLUE_UINT32 bytes_per_ch, BLUE_UINT32 no_samples, BLUE_UINT32 emb_audio_flags, BLUE_UINT8* Audio_Groups_DBN_Array, BLUE_UINT8* Audio_Groups_statusblock_Array); #if defined(_WIN32_) __declspec(deprecated("Deprecated. Do not use.")) #endif HANCUTILS_API BLUE_UINT32* get_embed_audio_distribution_array(BLUE_UINT32 video_mode, BLUE_UINT32 sequence_no); //HANCUTILS_API BLUE_UINT32 * GetAudioFrameSequence(BLUE_UINT32 video_output_standard); #if defined(_WIN32_) __declspec(deprecated("Deprecated. Do not use.")) #endif HANCUTILS_API bool hanc_stream_analyzer(BLUE_UINT32 *src_hanc_buffer,struct hanc_stream_info_struct * hanc_stream_ptr); #if defined(_WIN32_) __declspec(deprecated("Deprecated. Do not use.")) #endif HANCUTILS_API bool orac_hanc_stream_analyzer(BLUE_UINT32 card_type,BLUE_UINT32 *src_hanc_buffer,struct hanc_decode_struct * decode_ptr,char * analyzer_output_file); HANCUTILS_API bool hanc_decoder_ex( BLUE_UINT32 card_type, BLUE_UINT32* src_hanc_buffer, struct hanc_decode_struct* hanc_decode_struct_ptr); /** @} */ /** @defgroup vanc_manipilation_function vanc packet I/O @{ */ /** @brief enumerator used by VANC manipulation function on HD cards to notify whether VANC pakcet shoule be inserted/extracted from VANC Y buffers or VANC CbCr buffer. This enumerator will only be used on HD video modes as it is the only with 2 type of ANC bufers ir Y and CbCr. On SD Modes the ANC data is inserted across both Y anc CbCr values. */ enum blue_vanc_pkt_type_enum { blue_vanc_pkt_y_comp=0, /**< ANC pkt should be inserted/extracted from the Y component buffer*/ blue_vanc_pkt_cbcr_comp=1, /**< ANC pkt should be inserted/extracted from the CbCr component buffer*/ blue_vanc_pkt_all_comp=2 /**< ANC pkt should be inserted/extracted from all components (SD video modes)*/ }; /*! @brief Use this function to initialise VANC buffer before inserting any packets into the buffer @param CardType type of bluefish card to which this vanc buffer was transferred to. @param nVideoMode video mode under which this vanc buffer will be used. @param pixels_per_line width in pixels of the vanc buffer that has to be initialised. @param lines_per_frame height of the vanc buffer that has to be initialised. @param pVancBuffer vanc buffer which has to be initialised. @remarks. */ HANCUTILS_API BLUE_UINT32 blue_init_vanc_buffer(BLUE_UINT32 CardType,BLUE_UINT32 nVideoMode,BLUE_UINT32 pixels_per_line,BLUE_UINT32 lines_per_frame,BLUE_UINT32 * pVancBuffer); /*! @brief this function can be used to extract ANC packet from HD cards. Currently we can only extract packets in the VANC space. @param CardType type of the card from which the vanc buffer was captured. @param vanc_pkt_type This parameter denotes whether to search for the VANC packet in Y Space or Cb/Cr Space. The values this parameter accepts are defined in the enumerator #blue_vanc_pkt_type_enum @param src_vanc_buffer Vanc buffer which was captured from bluefish card @param src_vanc_buffer_size size of the vanc buffer which should be parsed for the specified vanc packet @param pixels_per_line specifies how many pixels are there in each line of VANC buffer @param vanc_pkt_did specifies the DID of the Vanc packet which should be extracted from the buffer @param vanc_pkt_sdid Returns the SDID of the extracted VANC packet @param vanc_pkt_data_length returns the size of the extracted VANC packet. The size is specifed as number of UDW words that was contained in the packet @param vanc_pkt_data_ptr pointer to UDW of the VANC packets . The 10 bit UDW words are packed in a 16 bit integer. The bottom 10 bit of the 16 bit word contains the UDW data. @param vanc_pkt_line_no line number where the packet was found . @remarks. */ HANCUTILS_API BLUE_INT32 vanc_pkt_extract( BLUE_UINT32 CardType, BLUE_UINT32 vanc_pkt_type, BLUE_UINT32 * src_vanc_buffer, BLUE_UINT32 src_vanc_buffer_size, BLUE_UINT32 pixels_per_line, BLUE_UINT32 vanc_pkt_did, BLUE_UINT16 * vanc_pkt_sdid, BLUE_UINT16 * vanc_pkt_data_length, BLUE_UINT16 * vanc_pkt_data_ptr, BLUE_UINT16 * vanc_pkt_line_no); /** @brief use this function to insert ANC packets into the VANC space of the HD cards. @param CardType type of the card from which the vanc buffer was captured. @param vanc_pkt_type This parameter denotes whether to search for the VANC packet in Y Space or Cb/Cr Space. The values this parameter accepts are defined in the enumerator #blue_vanc_pkt_type_enum @param vanc_pkt_line_no line in th VANC buffer where the ANC packet should inserted. @param vanc_pkt_buffer vanc ANC packet which should be inserted into the VANC buffer. @param vanc_pkt_buffer_size size of the ANC packet including the checksum ,ADF , SDID, DID and Data Count @param dest_vanc_buffer VANC buffer into which the ANC packet will be inserted into. @param pixels_per_line specifies how many pixels are there in each line of VANC buffer */ HANCUTILS_API BLUE_INT32 vanc_pkt_insert( BLUE_UINT32 CardType, BLUE_UINT32 vanc_pkt_type, BLUE_UINT32 vanc_pkt_line_no, BLUE_UINT32 * vanc_pkt_buffer, BLUE_UINT32 vanc_pkt_buffer_size, BLUE_UINT32 * dest_vanc_buffer, BLUE_UINT32 pixels_per_line); /** @} */ /** @defgroup vanc_decode_encoder_helper ANC encoder/decoder @{ */ HANCUTILS_API BLUE_UINT32 decode_eia_708b_pkt(BLUE_UINT32 CardType,BLUE_UINT16 * vanc_pkt_data_ptr,BLUE_UINT16 pkt_udw_count,BLUE_UINT16 eia_pkt_subtype,BLUE_UINT8 * decoded_ch_str); //#ifndef BLUE_LINUX_CODE //HANCUTILS_API BLUE_UINT64 decode_rp188_packet(BLUE_UINT32 CardType,BLUE_UINT32 * src_vanc_buffer,BLUE_UINT32 UDW_Count,BLUE_UINT64 *rp188_dbb); //HANCUTILS_API bool blue_vitc_decoder_8bit_fmt(BLUE_UINT8 * raw_vbi_ptr,BLUE_UINT32 pixels_per_line,BLUE_UINT32 mem_fmt,BLUE_UINT32 vitc_line_no,BLUE_UINT64 * vitc_time_code); //HANCUTILS_API bool blue_vitc_decoder_10bit_v210(BLUE_UINT8 * raw_vbi_ptr, BLUE_UINT32 vitc_line_no, BLUE_UINT64 * vitc_time_code); //HANCUTILS_API unsigned int create_rp188_pkt( // BLUE_UINT32 cardType, // BLUE_UINT32 * emb_data_ptr, // BLUE_UINT32 line_no, // BLUE_UINT32 start_new_line, // BLUE_UINT64 timecode, // BLUE_UINT64 rp188_dbb); //#endif /** @} */ #ifdef __cplusplus } #endif server-2.2.0-stable/src/modules/bluefish/interop/BlueVelvetC.h000066400000000000000000000424761341175263200243630ustar00rootroot00000000000000/* -LICENSE-START- ** Copyright (c) 2018 Bluefish Technologies ** ** Permission is hereby granted, free of charge, to any person or organization ** obtaining a copy of the software and accompanying documentation covered by ** this license (the "Software") to use, reproduce, display, distribute, ** execute, and transmit the Software, and to prepare derivative works of the ** Software, and to permit third-parties to whom the Software is furnished to ** do so, all subject to the following: ** ** The copyright notices in the Software and this entire statement, including ** the above license grant, this restriction and the following disclaimer, ** must be included in all copies of the Software, in whole or in part, and ** all derivative works of the Software, unless such copies or derivative ** works are solely in the form of machine-executable object code generated by ** a source language processor. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ** DEALINGS IN THE SOFTWARE. ** -LICENSE-END- */ #ifndef HG_BLUEVELVET_C #define HG_BLUEVELVET_C #if defined (_WIN32) #include "BlueDriver_p.h" #include "BlueHancUtils.h" #ifdef BLUEVELVETC_EXPORTS #define BLUEVELVETC_API __declspec(dllexport) #else #define BLUEVELVETC_API __declspec(dllimport) #endif #elif defined (__APPLE__) #define DLLEXPORT __attribute__ ((visibility("default"))) #define DLLLOCAL __attribute__ ((visibility("hidden"))) #define BLUEVELVETC_API DLLEXPORT #include #include "BlueDriver_p.h" #include "BlueVelvetCDefines.h" #elif defined (__linux__) #define BLUEVELVETC_API #include #include "BlueVelvetCDefines.h" #endif //---------------------------------------------------------------------------- typedef void* BLUEVELVETC_HANDLE; typedef void* BFC_SYNC_INFO; #define BFC_SYNC_INFO_WAIT_INFINITE 0xFFFFFFFF typedef int BErr; #define BLUE_OK(a) (!a) // Test for succcess of a method returning BErr #define BLUE_FAIL(a) (a) // Test for failure of a method returning BErr //---------------------------------------------------------------------------- #if defined (_WIN32) || defined (__linux__) extern "C" { #endif /** * bfcGetVersion - return the current version of this SDK * * Example: * printf("This version of bfc is: %s \n", bfcGetVersion()); */ BLUEVELVETC_API const char* bfcGetVersion(); BLUEVELVETC_API const wchar_t* bfcGetVersionW(); /** * bfcFactory - create an instance of the BlueVelvetC SDK * */ BLUEVELVETC_API BLUEVELVETC_HANDLE bfcFactory(); /** * bfcDestroy - Destroy an instance of the BlueVelvetC SDK * * Example: * bfcDestroy(pBVC); */ BLUEVELVETC_API void bfcDestroy(BLUEVELVETC_HANDLE pHandle); /** * bfcEnumerate - return the number of Bluefish devices currently installed in the system * can be run prior to attaching to a specific device */ BLUEVELVETC_API BErr bfcEnumerate(BLUEVELVETC_HANDLE pHandle, int& iDevices); // Get the card type of the Card indicated by iDeviceID, if iDeviceID is 0, then get the cardtype for that card that this pHandle is attached to. // /** * bfcQueryCardType - Find out what card type is installed for the given Device location. * ideviceID is 1 indexed. * iCardType maps to ECardType in BlueDriver_p.h */ BLUEVELVETC_API BErr bfcQueryCardType(BLUEVELVETC_HANDLE pHandle, int& iCardType, int iDeviceID = 0); /** * bfcAttach - Attach to a specific Device in the current system * */ BLUEVELVETC_API BErr bfcAttach(BLUEVELVETC_HANDLE pHandle, int iDeviceId); /** * bfcDetach - Detach the SDK instance. * */ BLUEVELVETC_API BErr bfcDetach(BLUEVELVETC_HANDLE pHandle); /** * bfcQueryCardProperty32/64 - Query a property of the hardware * Properties are defined by EBlueCardProperty in BlueDriver_p.h * * Example: eg. to determine what memory format is set * BLUE_UINT32 nMemFmt; * bfcQueryCardProperty32(pBVC, VIDEO_MEMORY_FORMAT, nMemFmt); */ BLUEVELVETC_API BErr bfcQueryCardProperty32(BLUEVELVETC_HANDLE pHandle, const int iProperty, unsigned int& nValue); /** * bfcSetCardProperty32/64 - Set a property of the hardware * Properties are defined by EBlueCardProperty in BlueDriver_p.h * * Example: eg. to set the memory format * BLUE_UINT32 nMemFmt = MEM_FMT_V210; * bfcSetCardProperty32(pBVC, VIDEO_MEMORY_FORMAT, nMemFmt); */ BLUEVELVETC_API BErr bfcSetCardProperty32(BLUEVELVETC_HANDLE pHandle, const int iProperty, const unsigned int nValue); BLUEVELVETC_API BErr bfcQueryCardProperty64(BLUEVELVETC_HANDLE pHandle, const int iProperty, unsigned long long& ullValue); BLUEVELVETC_API BErr bfcSetCardProperty64(BLUEVELVETC_HANDLE pHandle, const int iProperty, const unsigned long long ullValue); BLUEVELVETC_API BErr bfcGetCardSerialNumber(BLUEVELVETC_HANDLE pHandle, char* pSerialNumber, unsigned int nStringSize); //nStringSize must be at least 20 BLUEVELVETC_API BErr bfcGetCardFwVersion(BLUEVELVETC_HANDLE pHandle, unsigned int& nValue); //Interrupt related functions #if defined(_WIN32) BLUEVELVETC_API BErr bfcWaitVideoSyncAsync(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, blue_video_sync_struct* pSyncData); #endif /** * bfcWaitVideoInputSync - A blocking function that allows you to synchronize with the video input interrupts of the card * ulUpdateType specifies what type of interrupt to wait for, of type EUpdateMethod * ulFieldCount - a returned value that gives the current fieldcount * */ BLUEVELVETC_API BErr bfcWaitVideoInputSync(BLUEVELVETC_HANDLE pHandle, unsigned long ulUpdateType, unsigned long& ulFieldCount); /** * bfcWaitVideoOutputSync - A blocking function that allows you to synchronize with the video output interrupts of the card * ulUpdateType specifies what type of interrupt to wait for, of type EUpdateMethod * ulFieldCount - a returned value that gives the current fieldcount * */ BLUEVELVETC_API BErr bfcWaitVideoOutputSync(BLUEVELVETC_HANDLE pHandle, unsigned long ulUpdateType, unsigned long& ulFieldCount); /** * bfcGetVideoOutputCurrentFieldCount - Returns the current output field count * ulFieldCount - a returned value that gives the current fieldcount * */ BLUEVELVETC_API BErr bfcGetVideoOutputCurrentFieldCount(BLUEVELVETC_HANDLE pHandle, unsigned long& ulFieldCount); /** * bfcGetVideoInputCurrentFieldCount - Returns the current input fieldcount * ulFieldCount - a returned value that gives the current fieldcount * */ BLUEVELVETC_API BErr bfcGetVideoInputCurrentFieldCount(BLUEVELVETC_HANDLE pHandle, unsigned long& ulFieldCount); //FIFO functions /** * bfcVideoCaptureStart - Start the video Capture engine, only available in FIFO mode. * */ BLUEVELVETC_API BErr bfcVideoCaptureStart(BLUEVELVETC_HANDLE pHandle); /** * bfcVideoCaptureStop - Stop the video Capture engine. * */ BLUEVELVETC_API BErr bfcVideoCaptureStop(BLUEVELVETC_HANDLE pHandle); /** * bfcVideoPlaybackStart - Start the video playback engine, only available in FIFO mode. * */ BLUEVELVETC_API BErr bfcVideoPlaybackStart(BLUEVELVETC_HANDLE pHandle, int iStep, int iLoop); /** * bfcVideoPlaybackStop - Stop the video playback engine. * */ BLUEVELVETC_API BErr bfcVideoPlaybackStop(BLUEVELVETC_HANDLE pHandle, int iWait, int iFlush); /** * bfcVideoPlaybackAllocate - Get an ID for an empty card buffer from the playback engine. * */ BLUEVELVETC_API BErr bfcVideoPlaybackAllocate(BLUEVELVETC_HANDLE pHandle, void** pAddress, unsigned long& ulBufferID, unsigned long& ulUnderrun); /** * bfcVideoPlaybackPresent - Tell the playback system that we have finished copying data into the buffer, and it is ready to be presented ( ie displayed on the SDI) * calling this function does not guaruntee that the specified buffer will be displayed on the next interrupt, It only tells the FIFO that this buffer is ready * If multiple buffers are already marked as ready the specified buffer will be added to the end of the "present queue" * Once a buffer is presented, the FIFO automatically releases it, and places it in the free/empty queue. */ BLUEVELVETC_API BErr bfcVideoPlaybackPresent(BLUEVELVETC_HANDLE pHandle, unsigned long& ulUniqueID, unsigned long ulBufferID, unsigned long ulCount, int iKeep, int iOdd=0); /** * bfcVideoPlaybackRelease - Release a buffer back onto the free/empty Queue without it playing out the card. * */ BLUEVELVETC_API BErr bfcVideoPlaybackRelease(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID); /** * bfcGetCaptureVideoFrameInfoEx - Checks if there is a capturee frame buffer available in the capture queue. * A bufferID of -1, indicates that no buffers are available. * nCaptureFifoSize indicates the numbers of buffers currently stored on the card. */ #if defined (_WIN32) BLUEVELVETC_API BErr bfcGetCaptureVideoFrameInfoEx(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, struct blue_videoframe_info_ex& VideoFrameInfo, int iCompostLater, unsigned int* nCaptureFifoSize); #elif defined (__APPLE__) BLUEVELVETC_API BErr bfcGetCaptureVideoFrameInfoEx(BLUEVELVETC_HANDLE pHandle, struct blue_videoframe_info_ex& VideoFrameInfo, int iCompostLater, unsigned int* nCaptureFifoSize); #elif defined(__linux__) BLUEVELVETC_API BErr bfcGetCaptureVideoFrameInfoEx(BLUEVELVETC_HANDLE pHandle, struct blue_videoframe_info_ex& VideoFrameInfo); #endif //FRAMESTORE functions /** * bfcRenderBufferCapture - Tell the card to capture the next incoming buffer to the bufferID specified. * The card does not start capturing until the next Interrupt for this channel and is not complete until the interrupta after that. */ BLUEVELVETC_API BErr bfcRenderBufferCapture(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID); /** * bfcRenderBufferUpdate - Tell the card to display the buffer specified by BufferID at the next interrupt. * */ BLUEVELVETC_API BErr bfcRenderBufferUpdate(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID); BLUEVELVETC_API BErr bfcGetRenderBufferCount(BLUEVELVETC_HANDLE pHandle, unsigned long& ulCount); //AUDIO Helper functions (BlueHancUtils) BLUEVELVETC_API BErr bfcEncodeHancFrameEx(BLUEVELVETC_HANDLE pHandle, unsigned int nCardType, struct hanc_stream_info_struct* pHancEncodeInfo, void* pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags); BLUEVELVETC_API BErr bfcDecodeHancFrameEx(BLUEVELVETC_HANDLE pHandle, unsigned int nCardType, unsigned int* pHancBuffer, struct hanc_decode_struct* pHancDecodeInfo); //DMA functions #if defined(_WIN32) BLUEVELVETC_API BErr bfcSystemBufferReadAsync(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset=0); BLUEVELVETC_API BErr bfcSystemBufferWriteAsync(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset=0); #elif defined(__APPLE__) || defined (__linux__) BLUEVELVETC_API BErr bfcSystemBufferRead(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset=0); BLUEVELVETC_API BErr bfcSystemBufferWrite(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset=0); #endif #if defined(__APPLE__) BLUEVELVETC_API BErr bfcSystemBufferReadAsync(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, dispatch_semaphore_t* sem, unsigned long ulBufferID, unsigned long ulOffset=0); BLUEVELVETC_API BErr bfcSystemBufferWriteAsync(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, dispatch_semaphore_t* sem, unsigned long ulBufferID, unsigned long ulOffset=0); #endif BLUEVELVETC_API BFC_SYNC_INFO bfcSyncInfoCreate(BLUEVELVETC_HANDLE pHandle); BLUEVELVETC_API BErr bfcSyncInfoDelete(BLUEVELVETC_HANDLE pHandle, BFC_SYNC_INFO SyncInfo); BLUEVELVETC_API BErr bfcSyncInfoWait(BLUEVELVETC_HANDLE pHandle, BFC_SYNC_INFO SyncInfo, const unsigned int nTimeOutInMilliSec); // Cross platform asynchronous DMA functions BLUEVELVETC_API BErr bfcDmaReadFromCardAsync(BLUEVELVETC_HANDLE pHandle, unsigned char* pData, unsigned long ulSize, BFC_SYNC_INFO SyncInfo, unsigned long ulBufferID, unsigned long ulOffset); BLUEVELVETC_API BErr bfcDmaWriteToCardAsync(BLUEVELVETC_HANDLE pHandle, unsigned char* pData, unsigned long ulSize, BFC_SYNC_INFO SyncInfo, unsigned long ulBufferID, unsigned long ulOffset); // RS422 Serial Port Functions BLUEVELVETC_API BErr bfcSerialPortWaitForInputData(BLUEVELVETC_HANDLE pHandle, unsigned int nPortFlags, unsigned int& nBufferLength); BLUEVELVETC_API BErr bfcSerialPortRead(BLUEVELVETC_HANDLE pHandle, unsigned int nPortFlags, unsigned char* pBuffer, unsigned int nReadLength); BLUEVELVETC_API BErr bfcSerialPortWrite(BLUEVELVETC_HANDLE pHandle, unsigned int nPortFlags, unsigned char* pBuffer, unsigned int nWriteLength); #if defined (_WIN32) //Miscellaneous functions BLUEVELVETC_API BErr bfcGetReferenceClockPhaseSettings(BLUEVELVETC_HANDLE pHandle, unsigned int& nHPhase, unsigned int& nVPhase, unsigned int& nHPhaseMax, unsigned int& nVPhaseMax); BLUEVELVETC_API BErr bfcLoadOutputLUT1D(BLUEVELVETC_HANDLE pHandle, struct blue_1d_lookup_table_struct* pLutData); BLUEVELVETC_API BErr bfcControlVideoScaler(BLUEVELVETC_HANDLE pHandle, unsigned int nScalerId, bool bOnlyReadValue, float* pSrcVideoHeight, float* pSrcVideoWidth, float* pSrcVideoYPos, float* pSrcVideoXPos, float* pDestVideoHeight, float* pDestVideoWidth, float* pDestVideoYPos, float* pDestVideoXPos); #endif // Video mode and Format information functions BLUEVELVETC_API BErr bfcGetBytesForGroupPixels(EMemoryFormat nMemoryFormat, unsigned int nVideoWidth, unsigned int& nVideoPitchBytes); BLUEVELVETC_API BErr bfcGetPixelsPerLine(EVideoMode nVideoMode, unsigned int& nPixelsPerLine); BLUEVELVETC_API BErr bfcGetLinesPerFrame(EVideoMode nVideoMode, EUpdateMethod nUpdateMethod, unsigned int& nLinesPerFrame); BLUEVELVETC_API BErr bfcGetBytesPerLine(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, unsigned int& nBytesPerLine); BLUEVELVETC_API BErr bfcGetBytesPerFrame(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame); BLUEVELVETC_API BErr bfcGetGoldenValue(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nGoldenFrameSize); BLUEVELVETC_API BErr bfcGetVBILines(EVideoMode nVideoMode, EDMADataType nDataType, unsigned int& nVBILinesPerFrame); BLUEVELVETC_API BErr bfcGetVANCGoldenValue(unsigned int nCardType, EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EDMADataType nDataFormat, unsigned int& nVANCGoldenValue); BLUEVELVETC_API BErr bfcGetVANCLineBytes(unsigned int nCardType, EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, unsigned int& nVANCLineBytes); BLUEVELVETC_API BErr bfcGetVANCLineCount(unsigned int nCardType, EVideoMode nVideoMode, EDMADataType nDataFormat, unsigned int& nVANCLineCount); #if defined (_WIN32) //AMD SDI-Link support BLUEVELVETC_API BErr bfcDmaWaitMarker(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, unsigned int nVideoChannel, unsigned int nBufferId, unsigned int nMarker); BLUEVELVETC_API BErr bfcDmaReadToBusAddressWithMarker( BLUEVELVETC_HANDLE pHandle, unsigned int nVideoChannel, unsigned long long n64DataAddress, unsigned int nSize, OVERLAPPED* pOverlap, unsigned int BufferID, unsigned long Offset, unsigned long long n64MarkerAddress, unsigned int nMarker); BLUEVELVETC_API BErr bfcDmaReadToBusAddress( BLUEVELVETC_HANDLE pHandle, unsigned int nVideoChannel, unsigned long long n64DataAddress, unsigned int nSize, OVERLAPPED* pOverlap, unsigned int BufferID, unsigned long Offset); BLUEVELVETC_API BErr bfcDmaWriteMarker( BLUEVELVETC_HANDLE pHandle, unsigned long long n64MarkerAddress, unsigned int nMarker); //misc BLUEVELVETC_API BErr bfcGetWindowsDriverHandle(BLUEVELVETC_HANDLE pHandle, HANDLE* pDriverHandle); BLUEVELVETC_API BErr bfcSetDynamicMemoryFormatChange(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, unsigned int nUniqueId, EMemoryFormat nMemoryFormat); #endif #if defined (_WIN32) || defined (__linux__) } //extern "C" #endif #endif //HG_BLUEVELVET_C server-2.2.0-stable/src/modules/bluefish/interop/BlueVelvetCUtils.h000066400000000000000000000232751341175263200254000ustar00rootroot00000000000000/* -LICENSE-START- ** Copyright (c) 2018 Bluefish Technologies ** ** Permission is hereby granted, free of charge, to any person or organization ** obtaining a copy of the software and accompanying documentation covered by ** this license (the "Software") to use, reproduce, display, distribute, ** execute, and transmit the Software, and to prepare derivative works of the ** Software, and to permit third-parties to whom the Software is furnished to ** do so, all subject to the following: ** ** The copyright notices in the Software and this entire statement, including ** the above license grant, this restriction and the following disclaimer, ** must be included in all copies of the Software, in whole or in part, and ** all derivative works of the Software, unless such copies or derivative ** works are solely in the form of machine-executable object code generated by ** a source language processor. ** ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ** DEALINGS IN THE SOFTWARE. ** -LICENSE-END- */ // A file that contains useful Util functions that can ssist in general development. // intended to be included as-is into BlueVelvetC projects and not part of a library. #ifndef BlueVelvetC_BlueVelvetCUtils_h #define BlueVelvetC_BlueVelvetCUtils_h #include "BlueVelvetC.h" #if defined(_WIN32) || defined(__linux__) extern "C" { #endif // Memory Allocation and Free'ing of page Aligned memory BLUEVELVETC_API void* bfAlloc(unsigned int nMemorySize); BLUEVELVETC_API void bfFree(unsigned int nMemSize, void* pMemory); // Get strings that give information about the card or card state BLUEVELVETC_API const char* bfcUtilsGetStringForCardType(const int iCardType); BLUEVELVETC_API const wchar_t* bfcUtilsGetWStringForCardType(const int iCardType); BLUEVELVETC_API const char* bfcUtilsGetStringForBlueProductId(const unsigned int nProductId); BLUEVELVETC_API const wchar_t* bfcUtilsGetWStringForBlueProductId(const unsigned int nProductId); BLUEVELVETC_API const char* bfcUtilsGetStringForVideoMode(const unsigned int nVideoMode); BLUEVELVETC_API const wchar_t* bfcUtilsGetWStringForVideoMode(const unsigned int nVideoMode); BLUEVELVETC_API const char* bfcUtilsGetStringForMemoryFormat(const unsigned int nMemoryFormat); BLUEVELVETC_API const wchar_t* bfcUtilsGetWStringForMemoryFormat(const unsigned int nMemoryFormat); // Get/Set MR2 Video mode info BLUEVELVETC_API int bfcUtilsGetScalerVideoMode(const BLUEVELVETC_HANDLE pHandle, const unsigned int nScalerMR2Node, unsigned int& nVideoMode); BLUEVELVETC_API int bfcUtilsSetScalerVideoMode(const BLUEVELVETC_HANDLE pHandle, const unsigned int nScalerMR2Node, unsigned int nVideoMode); // Change MR2 Routing using the EEpochRoutingElements enum values as src and dest BLUEVELVETC_API int bfcUtilsGetMR2Routing(const BLUEVELVETC_HANDLE pHandle, unsigned int& nSrcNode, const unsigned int nDestNode, unsigned int& nLinkType); BLUEVELVETC_API int bfcUtilsSetMR2Routing(const BLUEVELVETC_HANDLE pHandle, const unsigned int nSrcNode, const unsigned int nDestNode, const unsigned int nLinkType); // Get/Set Audio routing. BLUEVELVETC_API int bfcUtilsGetAudioOutputRouting(const BLUEVELVETC_HANDLE pHandle, const unsigned int nAudioConnectorType, unsigned int& nAudioSourceChannelId, unsigned int nAudioConnectorId); BLUEVELVETC_API int bfcUtilsSetAudioOutputRouting(const BLUEVELVETC_HANDLE pHandle, const unsigned int nAudioConnectorType, unsigned int nAudioSourceChannelId, unsigned int nAudioConnectorId); // General Video format helper funcs BLUEVELVETC_API bool bfcUtilsIsVideoModeProgressive(const unsigned int nVideoMode); BLUEVELVETC_API bool bfcUtilsIsVideoMode1001Framerate(const unsigned int nVideoMode); BLUEVELVETC_API int bfcUtilsGetFpsForVideoMode(const unsigned int nVideoMode); // returns closest interger FPS, use bfcUtilsIsVideoMode1001Framerate(), to determine if div 1001 is needed. // Get the Bluefish _EVideoMode for the given width, height and fps BLUEVELVETC_API int bfcUtilsGetVideoModeForFrameInfo(const BLUE_UINT32 nWidth, const BLUE_UINT32 nHeight, const BLUE_UINT32 nRate, const BLUE_UINT32 bIs1001, const BLUE_UINT32 bIsProgressive, BLUE_UINT32& nVideoMode); BLUEVELVETC_API int bfcUtilsGetFrameInfoForVideoMode(const BLUE_UINT32 nVideoMode, BLUE_UINT32& nWidth, BLUE_UINT32& nHeight, BLUE_UINT32& nRate, BLUE_UINT32& bIs1001, BLUE_UINT32& bIsProgressive); // Get the number of Audio Packets for a given frame of video in a specific mode. BLUEVELVETC_API int bfcUtilsGetAudioSamplesPerFrame(const BLUE_UINT32 nVideoMode, const BLUE_UINT32 nFrameNo); // HANC / VANC utils /** @brief enumerator used by VANC manipulation function on HD cards to notify whether VANC pakcet shoule be inserted/extracted from VANC Y buffers or VANC CbCr buffer. This enumerator will only be used on HD video modes as it is the only with 2 type of ANC bufers ir Y and CbCr. On SD Modes the ANC data is inserted across both Y anc CbCr values. */ enum BlueVancPktTypeEnum { BlueVancPktYComp=0, /**< ANC pkt should be inserted/extracted from the Y component buffer*/ BlueVancPktCbcrComp=1, /**< ANC pkt should be inserted/extracted from the CbCr component buffer*/ BlueVancPktAllComp=2 /**< ANC pkt should be inserted/extracted from all components (SD video modes)*/ }; /*! @brief Use this function to initialise VANC buffer before inserting any packets into the buffer @param CardType type of bluefish card to which this vanc buffer was transferred to. @param nVideoMode video mode under which this vanc buffer will be used. @param pixels_per_line width in pixels of the vanc buffer that has to be initialised. @param lines_per_frame height of the vanc buffer that has to be initialised. @param pVancBuffer vanc buffer which has to be initialised. @remarks. */ BLUEVELVETC_API BLUE_UINT32 bfcUtilsInitVancBuffer(BLUE_UINT32 nCardType, BLUE_UINT32 nVideoMode, BLUE_UINT32 nPixelsPerLine, BLUE_UINT32 nLinesPerFrame, BLUE_UINT32* pVancBuffer); /*! @brief this function can be used to extract ANC packet from HD cards. Currently we can only extract packets in the VANC space. @param CardType type of the card from which the vanc buffer was captured. @param vanc_pkt_type This parameter denotes whether to search for the VANC packet in Y Space or Cb/Cr Space. The values this parameter accepts are defined in the enumerator #BlueVancPktTypeEnum @param src_vanc_buffer Vanc buffer which was captured from bluefish card @param src_vanc_buffer_size size of the vanc buffer which should be parsed for the specified vanc packet @param pixels_per_line specifies how many pixels are there in each line of VANC buffer @param vanc_pkt_did specifies the DID of the Vanc packet which should be extracted from the buffer @param vanc_pkt_sdid Returns the SDID of the extracted VANC packet @param vanc_pkt_data_length returns the size of the extracted VANC packet. The size is specifed as number of UDW words that was contained in the packet @param vanc_pkt_data_ptr pointer to UDW of the VANC packets . The 10 bit UDW words are packed in a 16 bit integer. The bottom 10 bit of the 16 bit word contains the UDW data. @param vanc_pkt_line_no line number where the packet was found . @remarks. */ BLUEVELVETC_API BLUE_INT32 bfcUtilsVancPktExtract(BLUE_UINT32 nCardType, BLUE_UINT32 nVancPktType, BLUE_UINT32* pSrcVancBuffer, BLUE_UINT32 nSrcVancBufferSize, BLUE_UINT32 nPixelsPerLine, BLUE_UINT32 nVancPktDid, BLUE_UINT16* pVancPktSdid, BLUE_UINT16* pVancPktDataLength, BLUE_UINT16* pVancPktData, BLUE_UINT16* pVancPktLineNo); /** @brief use this function to insert ANC packets into the VANC space of the HD cards. @param CardType type of the card from which the vanc buffer was captured. @param vanc_pkt_type This parameter denotes whether to search for the VANC packet in Y Space or Cb/Cr Space. The values this parameter accepts are defined in the enumerator #blue_vanc_pkt_type_enum @param vanc_pkt_line_no line in th VANC buffer where the ANC packet should inserted. @param vanc_pkt_buffer vanc ANC packet which should be inserted into the VANC buffer. @param vanc_pkt_buffer_size size of the ANC packet including the checksum ,ADF , SDID, DID and Data Count @param dest_vanc_buffer VANC buffer into which the ANC packet will be inserted into. @param pixels_per_line specifies how many pixels are there in each line of VANC buffer */ BLUEVELVETC_API BLUE_INT32 bfcUtilsVancPktInsert(BLUE_UINT32 nCardType, BLUE_UINT32 nVancPktType, BLUE_UINT32 nVancPktLineNumber, BLUE_UINT32* pVancPktBuffer, BLUE_UINT32 nVancPktBufferSize, BLUE_UINT32* pDestVancBuffer, BLUE_UINT32 nPixelsPerLine); /** @} */ /** @defgroup vanc_decode_encoder_helper ANC encoder/decoder @{ */ BLUEVELVETC_API BLUE_UINT32 bfcUtilsDecodeEia708bPkt(BLUE_UINT32 nCardType, BLUE_UINT16* pVancPktData, BLUE_UINT16 usPktUdwCount, BLUE_UINT16 usEiaPktSubtype, BLUE_UINT8* pDecodedChStr); #if defined (_WIN32) || defined(__linux__) } //extern "C" #endif #endif // BlueVelvetC_BlueVelvetCUtils_h server-2.2.0-stable/src/modules/bluefish/packages.config000066400000000000000000000003251341175263200233020ustar00rootroot00000000000000 server-2.2.0-stable/src/modules/bluefish/producer/000077500000000000000000000000001341175263200221605ustar00rootroot00000000000000server-2.2.0-stable/src/modules/bluefish/producer/bluefish_producer.cpp000066400000000000000000000754341341175263200264050ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author:Robert Nagy, ronag89@gmail.com * satchit puthenveetil * James Wise, james.wise@bluefish444.com */ #include "../StdAfx.h" #include "bluefish_producer.h" #include "../util/blue_velvet.h" #include "../util/memory.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4244) #endif extern "C" { #include #include #include #include #include #include #include #include #include } #if defined(_MSC_VER) #pragma warning(pop) #endif using namespace caspar::ffmpeg; namespace caspar { namespace bluefish { static const size_t MAX_DECODED_AUDIO_BUFFER_SIZE = 2002 * 16; // max 2002 samples, 16 channels. template std::wstring to_string(const T& cadence) { return boost::join( cadence | boost::adaptors::transformed([](size_t i) { return boost::lexical_cast(i); }), L", "); } unsigned int get_bluesdk_input_videochannel_from_streamid(int stream_id) { /*This function would return the corresponding EBlueVideoChannel from them stream_id argument */ switch (stream_id) { case 1: return BLUE_VIDEO_INPUT_CHANNEL_A; case 2: return BLUE_VIDEO_INPUT_CHANNEL_B; case 3: return BLUE_VIDEO_INPUT_CHANNEL_C; case 4: return BLUE_VIDEO_INPUT_CHANNEL_D; default: return BLUE_VIDEO_INPUT_CHANNEL_A; } } unsigned int extract_pcm_data_from_hanc(bvc_wrapper& blue, struct hanc_decode_struct* decode_struct, unsigned int card_type, unsigned int* src_hanc_buffer, unsigned int* pcm_audio_buffer, int audio_channels_to_extract) { decode_struct->audio_pcm_data_ptr = pcm_audio_buffer; decode_struct->type_of_sample_required = 0; // No flags indicates default of 32bit samples. decode_struct->max_expected_audio_sample_count = 2002; if (audio_channels_to_extract == 2) decode_struct->audio_ch_required_mask = MONO_CHANNEL_1 | MONO_CHANNEL_2; else if (audio_channels_to_extract == 8) decode_struct->audio_ch_required_mask = MONO_CHANNEL_1 | MONO_CHANNEL_2 | MONO_CHANNEL_3 | MONO_CHANNEL_4 | MONO_CHANNEL_5 | MONO_CHANNEL_6 | MONO_CHANNEL_7 | MONO_CHANNEL_8; else if (audio_channels_to_extract == 16) decode_struct->audio_ch_required_mask = MONO_CHANNEL_1 | MONO_CHANNEL_2 | MONO_CHANNEL_3 | MONO_CHANNEL_4 | MONO_CHANNEL_5 | MONO_CHANNEL_6 | MONO_CHANNEL_7 | MONO_CHANNEL_8 | MONO_CHANNEL_11 | MONO_CHANNEL_12 | MONO_CHANNEL_13 | MONO_CHANNEL_14 | MONO_CHANNEL_15 | MONO_CHANNEL_16 | MONO_CHANNEL_17 | MONO_CHANNEL_18; blue.decode_hanc_frame(card_type, src_hanc_buffer, decode_struct); return decode_struct->no_audio_samples; } bool is_video_format_interlaced(const core::video_format format) { bool interlaced = false; if (format == core::video_format::x1080i5000 || format == core::video_format::x1080i5994 || format == core::video_format::x1080i6000 || format == core::video_format::pal || format == core::video_format::ntsc) interlaced = true; return interlaced; } bool is_bluefish_format_interlaced(unsigned int vid_mode) { bool interlaced = false; if (vid_mode == VID_FMT_PAL || vid_mode == VID_FMT_NTSC || vid_mode == VID_FMT_1080I_5000 || vid_mode == VID_FMT_1080I_5994 || vid_mode == VID_FMT_1080I_6000) interlaced = true; return interlaced; } struct bluefish_producer : boost::noncopyable { const int device_index_; const int stream_index_; spl::shared_ptr blue_; core::monitor::state state_; mutable std::mutex state_mutex_; spl::shared_ptr graph_; caspar::timer tick_timer_; caspar::timer processing_benchmark_timer_; std::vector audio_cadence_; const std::wstring model_name_ = std::wstring(L"bluefish"); std::atomic_bool process_capture_ = true; std::shared_ptr capture_thread_; std::array reserved_frames_; core::video_format_desc format_desc_; core::video_format_desc channel_format_desc_; unsigned int mode_; spl::shared_ptr frame_factory_; tbb::concurrent_bounded_queue frame_buffer_; std::exception_ptr exception_; ULONG schedule_capture_frame_id_ = 0; ULONG capturing_frame_id_ = std::numeric_limits::max(); ULONG dma_ready_captured_frame_id_ = std::numeric_limits::max(); struct hanc_decode_struct hanc_decode_struct_; std::vector decoded_audio_bytes_; unsigned int memory_format_on_card_; unsigned int sync_format_; bool first_frame_ = true; int frames_captured = 0; uint64_t capture_ts = 0; int remainaing_audio_samples_ = 0; public: bluefish_producer(const core::video_format_desc& format_desc, int device_index, int stream_index, const spl::shared_ptr& frame_factory) : blue_(create_blue(device_index)) , channel_format_desc_(format_desc) , device_index_(device_index) , stream_index_(stream_index) , frame_factory_(frame_factory) , model_name_(get_card_desc(*blue_, device_index)) , memory_format_on_card_(MEM_FMT_RGB) , sync_format_(UPD_FMT_FRAME) { mode_ = static_cast(VID_FMT_INVALID); frame_buffer_.set_capacity(2); unsigned int invalid_video_mode_flag = VID_FMT_INVALID; graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f)); graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f)); graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f)); graph_->set_color("output-buffer", diagnostics::color(0.0f, 1.0f, 0.0f)); graph_->set_text(print()); diagnostics::register_graph(graph_); memset(&hanc_decode_struct_, 0, sizeof(hanc_decode_struct_)); hanc_decode_struct_.audio_input_source = AUDIO_INPUT_SOURCE_EMB; decoded_audio_bytes_.resize(MAX_DECODED_AUDIO_BUFFER_SIZE); // Configure input connector and routing unsigned int bf_channel = get_bluesdk_input_videochannel_from_streamid(stream_index); if (BLUE_FAIL(blue_->set_card_property32(DEFAULT_VIDEO_INPUT_CHANNEL, (bf_channel)))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set input channel.")); if (BLUE_FAIL(configure_input_routing(bf_channel, true))) // to do: tofix pass rgba vs use actual dual link!! CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set input routing.")); // Select input memory format if (BLUE_FAIL(blue_->set_card_property32(VIDEO_INPUT_MEMORY_FORMAT, memory_format_on_card_))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set input memory format.")); // Select image orientation if (BLUE_FAIL(blue_->set_card_property32(VIDEO_INPUTFRAMESTORE_IMAGE_ORIENTATION, ImageOrientation_Normal))) CASPAR_LOG(warning) << print() << L" Failed to set image orientation to normal."; // Select data range if (BLUE_FAIL(blue_->set_card_property32( EPOCH_VIDEO_INPUT_RGB_DATA_RANGE, CGR_RANGE))) // todo: confirm if we want to pass CGR or SMPTe range to caspar!!!! CASPAR_LOG(warning) << print() << L" Failed to set RGB data range to CGR."; blue_->get_card_property32(VIDEO_INPUT_SIGNAL_VIDEO_MODE, mode_); blue_->get_card_property32(INVALID_VIDEO_MODE_FLAG, invalid_video_mode_flag); if (mode_ < invalid_video_mode_flag) { format_desc_ = get_format_desc( *blue_, static_cast(mode_), static_cast(memory_format_on_card_)); audio_cadence_ = format_desc_.audio_cadence; // If we have an interlaced input AND and interlaced project then we need to handle the incoming frames // differently and sync on fields, instead of frame barriers if (is_video_format_interlaced(format_desc.format) && is_bluefish_format_interlaced(mode_)) sync_format_ = UPD_FMT_FIELD; // Select Update Mode for input if (BLUE_FAIL(blue_->set_card_property32(VIDEO_INPUT_UPDATE_TYPE, UPD_FMT_FRAME))) /// HERE: this *might need to be sync format, but /// currently we will leave as Frame UPD CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set input update type.")); // Generate dma buffers int n = 0; boost::range::generate(reserved_frames_, [&] { return std::make_shared(static_cast(format_desc_.size), n++); }); // Set Video Engine if (BLUE_FAIL(blue_->set_card_property32(VIDEO_INPUT_ENGINE, VIDEO_ENGINE_FRAMESTORE))) CASPAR_LOG(warning) << print() << TEXT(" Failed to set video engine."); capture_thread_ = std::make_shared([this] { capture_thread_actual(); }); } } int configure_input_routing(const unsigned int bf_channel, bool dual_link) { unsigned int routing_value = 0; unsigned int routing_value_b = 0; /*This function would return the corresponding EBlueVideoChannel from the device output channel*/ switch (bf_channel) { case BLUE_VIDEO_INPUT_CHANNEL_A: if (dual_link) { routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_A, EPOCH_DEST_INPUT_MEM_INTERFACE_CHA, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1); routing_value_b = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_B, EPOCH_DEST_INPUT_MEM_INTERFACE_CHA, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2); } else routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_A, EPOCH_DEST_INPUT_MEM_INTERFACE_CHA, BLUE_CONNECTOR_PROP_SINGLE_LINK); break; case BLUE_VIDEO_INPUT_CHANNEL_B: if (dual_link) { routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_B, EPOCH_DEST_INPUT_MEM_INTERFACE_CHB, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1); routing_value_b = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_C, EPOCH_DEST_INPUT_MEM_INTERFACE_CHB, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2); } else routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_B, EPOCH_DEST_INPUT_MEM_INTERFACE_CHB, BLUE_CONNECTOR_PROP_SINGLE_LINK); break; case BLUE_VIDEO_INPUT_CHANNEL_C: if (dual_link) { routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_C, EPOCH_DEST_INPUT_MEM_INTERFACE_CHC, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1); routing_value_b = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_D, EPOCH_DEST_INPUT_MEM_INTERFACE_CHC, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2); } else routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_C, EPOCH_DEST_INPUT_MEM_INTERFACE_CHC, BLUE_CONNECTOR_PROP_SINGLE_LINK); break; case BLUE_VIDEO_INPUT_CHANNEL_D: routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_D, EPOCH_DEST_INPUT_MEM_INTERFACE_CHD, BLUE_CONNECTOR_PROP_SINGLE_LINK); break; default: routing_value = EPOCH_SET_ROUTING( EPOCH_SRC_SDI_INPUT_A, EPOCH_DEST_INPUT_MEM_INTERFACE_CHA, BLUE_CONNECTOR_PROP_SINGLE_LINK); break; } if (dual_link) { blue_->set_card_property32(MR2_ROUTING, routing_value); return blue_->set_card_property32(MR2_ROUTING, routing_value_b); } else return blue_->set_card_property32(MR2_ROUTING, routing_value); } void schedule_capture() { if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_)) { blue_->render_buffer_capture(BlueBuffer_Image_HANC(schedule_capture_frame_id_)); dma_ready_captured_frame_id_ = capturing_frame_id_; capturing_frame_id_ = schedule_capture_frame_id_; schedule_capture_frame_id_ = (++schedule_capture_frame_id_ % 4); } } void get_capture_time() { blue_->get_card_property64(BTC_TIMER, capture_ts); } HRESULT process_data() { caspar::timer frame_timer; // Get info for source video mode unsigned int width = 0; unsigned int height = 0; unsigned int rate = 0; unsigned int is_1001 = 0; unsigned int is_progressive = 0; unsigned int image_size = 0; blue_->get_frame_info_for_video_mode(mode_, width, height, rate, is_1001, is_progressive); blue_->get_bytes_per_frame(static_cast(mode_), static_cast(memory_format_on_card_), static_cast(sync_format_), image_size); double fps = rate; if (is_1001) fps = (rate * 1000) / 1001; CASPAR_SCOPE_EXIT { { std::lock_guard lock(state_mutex_); state_["file/name"] = model_name_; state_["file/path"] = device_index_; state_["file/video/width"] = static_cast(width); state_["file/video/height"] = static_cast(height); state_["file/audio/sample-rate"] = format_desc_.audio_sample_rate; state_["file/audio/channels"] = format_desc_.audio_channels; state_["file/fps"] = static_cast(fps); state_["profiler/time"] = {frame_timer.elapsed(), fps}; state_["buffer"] = {frame_buffer_.size(), frame_buffer_.capacity()}; } graph_->set_value("frame-time", frame_timer.elapsed() * fps / format_desc_.field_count * 0.5); graph_->set_value("output-buffer", static_cast(frame_buffer_.size()) / static_cast(frame_buffer_.capacity())); }; try { graph_->set_value("tick-time", tick_timer_.elapsed() * fps * 0.5); tick_timer_.restart(); { auto src_video = alloc_frame(); auto src_audio = alloc_frame(); // video src_video->format = AV_PIX_FMT_RGB24; src_video->width = width; src_video->height = height; src_video->interlaced_frame = !is_progressive; src_video->top_field_first = (height != 486); src_video->key_frame = 1; src_video->display_picture_number = frames_captured; src_video->pts = capture_ts; void* video_bytes = nullptr; video_bytes = reserved_frames_.front()->image_data(); if (reserved_frames_.front() && video_bytes) { src_video->data[0] = reinterpret_cast(reserved_frames_.front()->image_data()); src_video->linesize[0] = static_cast(width * 3); // image_size / height); } // Audio src_audio->format = AV_SAMPLE_FMT_S32; src_audio->channels = format_desc_.audio_channels; src_audio->sample_rate = format_desc_.audio_sample_rate; src_audio->nb_samples = 0; int samples_decoded = 0; // hmm is audio on first frame or do we need to wait till snd feild to get audio? if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && first_frame_)) { void* audio_bytes = nullptr; auto hanc_buffer = reinterpret_cast(reserved_frames_.front()->hanc_data()); if (hanc_buffer) { int card_type = CRD_INVALID; blue_->query_card_type(card_type, device_index_); auto no_extracted_pcm_samples = extract_pcm_data_from_hanc(*blue_, &hanc_decode_struct_, card_type, reinterpret_cast(hanc_buffer), reinterpret_cast(&decoded_audio_bytes_[0]), src_audio->channels); audio_bytes = reinterpret_cast(&decoded_audio_bytes_[0]); samples_decoded = no_extracted_pcm_samples / src_audio->channels; src_audio->nb_samples = samples_decoded; src_audio->data[0] = reinterpret_cast(audio_bytes); src_audio->linesize[0] = src_audio->nb_samples * src_audio->channels * av_get_bytes_per_sample(static_cast(src_audio->format)); src_audio->pts = capture_ts; } } if (sync_format_ == UPD_FMT_FIELD) { // since we provide an entire frame for each field in interlaced modes, we need to adjust the // src_audio if (first_frame_) { remainaing_audio_samples_ = src_audio->nb_samples - (src_audio->nb_samples / 2); src_audio->nb_samples = (src_audio->nb_samples / 2); } else { auto audio_bytes = reinterpret_cast(&decoded_audio_bytes_[0]); if (audio_bytes) { src_audio->nb_samples = remainaing_audio_samples_; int bytes_left = remainaing_audio_samples_ * 4 * src_audio->channels; src_audio->data[0] = audio_bytes + bytes_left; src_audio->linesize[0] = bytes_left; remainaing_audio_samples_ = 0; } } } // pass to caspar auto frame = core::draw_frame(make_frame(this, *frame_factory_, src_video, src_audio)); if (!frame_buffer_.try_push(frame)) { core::draw_frame dummy; frame_buffer_.try_pop(dummy); frame_buffer_.try_push(frame); graph_->set_tag(diagnostics::tag_severity::WARNING, "dropped-frame"); CASPAR_LOG(warning) << print() << TEXT(" ERROR dropped frame."); } if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_)) boost::range::rotate(audio_cadence_, std::end(audio_cadence_) - 1); } } catch (...) { exception_ = std::current_exception(); return E_FAIL; } return S_OK; } void grab_frame_from_bluefishcard() { try { if (reserved_frames_.front()->image_data()) { if (sync_format_ == UPD_FMT_FIELD && !first_frame_) { blue_->system_buffer_read(const_cast(reserved_frames_.front()->image_data()), static_cast(reserved_frames_.front()->image_size()), BlueImage_DMABuffer(dma_ready_captured_frame_id_, BLUE_DATA_FRAME), 0); } else if (sync_format_ == UPD_FMT_FRAME) { blue_->system_buffer_read(const_cast(reserved_frames_.front()->image_data()), static_cast(reserved_frames_.front()->image_size()), BlueImage_DMABuffer(dma_ready_captured_frame_id_, BLUE_DATA_IMAGE), 0); } } else CASPAR_LOG(warning) << print() << TEXT(" NO image data in reserved frames list."); if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_)) { if (reserved_frames_.front()->hanc_data()) { blue_->system_buffer_read(const_cast(reserved_frames_.front()->hanc_data()), static_cast(reserved_frames_.front()->hanc_size()), BlueImage_DMABuffer(dma_ready_captured_frame_id_, BLUE_DATA_HANC), 0); } } } catch (...) { exception_ = std::current_exception(); return; } } void capture_thread_actual() { ULONG current_field_count = 0; ULONG last_field_count = 0; ULONG start_field_count = 0; unsigned int invalid_video_mode_flag = VID_FMT_INVALID; unsigned int current_input_video_signal = VID_FMT_INVALID; blue_->get_card_property32(INVALID_VIDEO_MODE_FLAG, invalid_video_mode_flag); last_field_count = current_field_count; start_field_count = current_field_count; blue_->wait_video_input_sync(UPD_FMT_FRAME, current_field_count); while (process_capture_) { // tell the card to capture another frame at the next interrupt schedule_capture(); blue_->wait_video_input_sync((EUpdateMethod)sync_format_, current_field_count); get_capture_time(); if (last_field_count + 3 < current_field_count) CASPAR_LOG(warning) << L"Error: dropped " << ((current_field_count - last_field_count - 2) / 2) << L" frames" << L"Current " << current_field_count << L" Old " << last_field_count; last_field_count = current_field_count; blue_->get_card_property32(VIDEO_INPUT_SIGNAL_VIDEO_MODE, current_input_video_signal); if (current_input_video_signal < invalid_video_mode_flag && dma_ready_captured_frame_id_ != std::numeric_limits::max()) { // DoneID is now what ScheduleID was at the last iteration when we called // render_buffer_capture(ScheduleID) we just checked if the video signal for the buffer “DoneID” was // valid while it was capturing so we can DMA the buffer DMA the frame from the card to our buffer grab_frame_from_bluefishcard(); process_data(); processing_benchmark_timer_.restart(); } if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_)) boost::range::rotate(reserved_frames_, std::begin(reserved_frames_) + 1); frames_captured++; if (sync_format_ == UPD_FMT_FIELD) first_frame_ = !first_frame_; } } ~bluefish_producer() { try { process_capture_ = false; if (capture_thread_) { Sleep(41); capture_thread_->join(); } blue_->detach(); } catch (...) { CASPAR_LOG_CURRENT_EXCEPTION(); } } core::draw_frame get_frame() { if (exception_ != nullptr) std::rethrow_exception(exception_); core::draw_frame frame; if (!frame_buffer_.try_pop(frame)) { graph_->set_tag(diagnostics::tag_severity::WARNING, "late-frame"); } return frame; } std::wstring print() const { return model_name_ + L" [" + boost::lexical_cast(device_index_) + L"|" + format_desc_.name + L"]"; } core::monitor::state state() const { std::lock_guard lock(state_mutex_); return state_; } boost::rational get_out_framerate() const { return format_desc_.framerate; } }; class bluefish_producer_proxy : public core::frame_producer { std::unique_ptr producer_; const uint32_t length_; executor executor_; public: explicit bluefish_producer_proxy(const core::video_format_desc& format_desc, const spl::shared_ptr& frame_factory, int device_index, int stream_index, uint32_t length) : executor_(L"bluefish_producer[" + boost::lexical_cast(device_index) + L"]") , length_(length) { auto ctx = core::diagnostics::call_context::for_thread(); executor_.invoke([=] { core::diagnostics::call_context::for_thread() = ctx; producer_.reset(new bluefish_producer(format_desc, device_index, stream_index, frame_factory)); }); } ~bluefish_producer_proxy() { executor_.invoke([=] { producer_.reset(); }); } core::monitor::state state() const override { return producer_->state(); } // frame_producer core::draw_frame receive_impl(int nb_samples) override { return producer_->get_frame(); } uint32_t nb_frames() const override { return length_; } std::wstring print() const override { return producer_->print(); } std::wstring name() const override { return L"bluefish"; } boost::rational get_out_framerate() const { return producer_->get_out_framerate(); } }; spl::shared_ptr create_producer(const core::frame_producer_dependencies& dependencies, const std::vector& params) { if (params.empty() || !boost::iequals(params.at(0), "bluefish")) return core::frame_producer::empty(); auto device_index = get_param(L"DEVICE", params, -1); if (device_index == -1) device_index = boost::lexical_cast(params.at(1)); auto stream_index = get_param(L"SDI-STREAM", params, -1); if (stream_index == -1) stream_index = 1; auto length = get_param(L"LENGTH", params, std::numeric_limits::max()); auto in_format_desc = core::video_format_desc(get_param(L"FORMAT", params, L"INVALID")); auto producer = spl::make_shared( dependencies.format_desc, dependencies.frame_factory, device_index, stream_index, length); return create_destroy_proxy(producer); } }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/producer/bluefish_producer.h000066400000000000000000000024051341175263200260360ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com * satchit puthenveetil * James Wise, james.wise@bluefish444.com */ #pragma once #include #include #include namespace caspar { namespace bluefish { spl::shared_ptr create_producer(const core::frame_producer_dependencies& dependencies, const std::vector& params); }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/util/000077500000000000000000000000001341175263200213125ustar00rootroot00000000000000server-2.2.0-stable/src/modules/bluefish/util/blue_velvet.cpp000066400000000000000000000723761341175263200243510ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "blue_velvet.h" #include "../StdAfx.h" #include "../interop/BlueVelvetCUtils.h" #include #include #if defined(__APPLE__) #include #endif #if defined(_WIN32) #define GET_PROCADDR_FOR_FUNC(name, module) \ { \ name = (pFunc_##name)GetProcAddress(reinterpret_cast(module), #name); \ if (!name) { \ return false; \ } \ } #elif defined(__APPLE__) #define GET_PROCADDR_FOR_FUNC(name, module) \ { \ name = (pFunc_##name)dlsym(module, #name); \ if (!name) { \ return false; \ } \ } #endif namespace caspar { namespace bluefish { bvc_wrapper::bvc_wrapper() { if (!init_function_pointers()) CASPAR_THROW_EXCEPTION(not_supported() << msg_info("Bluefish drivers not found. Unable to init Funcion Pointers")); bvc_ = std::shared_ptr(bfcFactory(), bfcDestroy); if (!bvc_) CASPAR_THROW_EXCEPTION(not_supported() << msg_info("Bluefish drivers not found.")); } bool bvc_wrapper::init_function_pointers() { bool res = false; #if defined(_WIN32) #ifdef _DEBUG h_module_ = std::shared_ptr(LoadLibraryExA("BlueVelvetC64_d.dll", NULL, 0), FreeLibrary); #else h_module_ = std::shared_ptr(LoadLibraryExA("BlueVelvetC64.dll", NULL, 0), FreeLibrary); #endif #elif defined(__APPLE__) // Look for the framework and load it accordingly. char* libraryPath("/Library/Frameworks/BlueVelvetC.framework"); // full path may not be required, OSX might check in // /l/f by default - MUST TEST! h_module_ = std::shared_ptr(dlopen(libraryPath, RTLD_NOW), dlclose); #endif if (h_module_) { GET_PROCADDR_FOR_FUNC(bfcGetVersion, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcFactory, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcDestroy, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcEnumerate, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcQueryCardType, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcAttach, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcDetach, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcQueryCardProperty32, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcQueryCardProperty64, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcSetCardProperty32, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcSetCardProperty64, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetCardSerialNumber, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetCardFwVersion, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcWaitVideoSyncAsync, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcWaitVideoInputSync, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcWaitVideoOutputSync, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetVideoOutputCurrentFieldCount, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetVideoInputCurrentFieldCount, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcVideoCaptureStart, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcVideoCaptureStop, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackStart, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackStop, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackAllocate, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackPresent, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcVideoPlaybackRelease, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetCaptureVideoFrameInfoEx, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcRenderBufferCapture, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcRenderBufferUpdate, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetRenderBufferCount, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcEncodeHancFrameEx, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcDecodeHancFrameEx, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcSystemBufferReadAsync, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcSystemBufferWriteAsync, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetBytesForGroupPixels, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetPixelsPerLine, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetLinesPerFrame, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetBytesPerLine, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetBytesPerFrame, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetGoldenValue, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetVBILines, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetVANCGoldenValue, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetVANCLineBytes, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetVANCLineCount, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcGetWindowsDriverHandle, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForCardType, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForBlueProductId, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForVideoMode, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetStringForMemoryFormat, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetMR2Routing, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsSetMR2Routing, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetAudioOutputRouting, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsSetAudioOutputRouting, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsIsVideoModeProgressive, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsIsVideoMode1001Framerate, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetFpsForVideoMode, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetVideoModeForFrameInfo, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetFrameInfoForVideoMode, h_module_.get()); GET_PROCADDR_FOR_FUNC(bfcUtilsGetAudioSamplesPerFrame, h_module_.get()); res = true; } return res; } const char* bvc_wrapper::get_version() { return bfcGetVersion(); } BLUE_UINT32 bvc_wrapper::attach(int iDeviceId) { return bfcAttach(bvc_.get(), iDeviceId); } BLUE_UINT32 bvc_wrapper::detach() { return bfcDetach(bvc_.get()); } BLUE_UINT32 bvc_wrapper::get_card_property32(const int iProperty, unsigned int& nValue) { return (BLUE_UINT32)bfcQueryCardProperty32(bvc_.get(), iProperty, nValue); } BLUE_UINT32 bvc_wrapper::set_card_property32(const int iProperty, const unsigned int nValue) { return bfcSetCardProperty32(bvc_.get(), iProperty, nValue); } BLUE_UINT32 bvc_wrapper::get_card_property64(const int iProperty, unsigned long long& nValue) { return (BLUE_UINT32)bfcQueryCardProperty64(bvc_.get(), iProperty, nValue); } BLUE_UINT32 bvc_wrapper::set_card_property64(const int iProperty, const unsigned long long nValue) { return bfcSetCardProperty64(bvc_.get(), iProperty, nValue); } BLUE_UINT32 bvc_wrapper::enumerate(int& iDevices) { return bfcEnumerate(bvc_.get(), iDevices); } BLUE_UINT32 bvc_wrapper::query_card_type(int& iCardType, int iDeviceID) { return bfcQueryCardType(bvc_.get(), iCardType, iDeviceID); } BLUE_UINT32 bvc_wrapper::system_buffer_write(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset) { return bfcSystemBufferWriteAsync(bvc_.get(), pPixels, ulSize, nullptr, ulBufferID, ulOffset); } BLUE_UINT32 bvc_wrapper::system_buffer_read(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset) { return bfcSystemBufferReadAsync(bvc_.get(), pPixels, ulSize, nullptr, ulBufferID, ulOffset); } BLUE_UINT32 bvc_wrapper::video_playback_stop(int iWait, int iFlush) { return bfcVideoPlaybackStop(bvc_.get(), iWait, iFlush); } BLUE_UINT32 bvc_wrapper::video_playback_start(int step, int loop) { return bfcVideoPlaybackStart(bvc_.get(), step, loop); } BLUE_UINT32 bvc_wrapper::video_playback_allocate(unsigned long& buffer_id, unsigned long& underrun) { void* unused = nullptr; return bfcVideoPlaybackAllocate(bvc_.get(), &unused, buffer_id, underrun); } BLUE_UINT32 bvc_wrapper::video_playback_present(unsigned long buffer_id, unsigned long count, unsigned long keep, unsigned long odd) { unsigned long unique_id; return bfcVideoPlaybackPresent(bvc_.get(), unique_id, buffer_id, count, keep, odd); } BLUE_UINT32 bvc_wrapper::wait_video_output_sync(unsigned long ulUpdateType, unsigned long& ulFieldCount) { return bfcWaitVideoOutputSync(bvc_.get(), ulUpdateType, ulFieldCount); } BLUE_UINT32 bvc_wrapper::wait_video_input_sync(unsigned long ulUpdateType, unsigned long& ulFieldCount) { return bfcWaitVideoInputSync(bvc_.get(), ulUpdateType, ulFieldCount); } BLUE_UINT32 bvc_wrapper::render_buffer_update(unsigned long ulBufferID) { return bfcRenderBufferUpdate(bvc_.get(), ulBufferID); } BLUE_UINT32 bvc_wrapper::render_buffer_capture(unsigned long ulBufferID) { return bfcRenderBufferCapture(bvc_.get(), ulBufferID); } BLUE_UINT32 bvc_wrapper::encode_hanc_frame(unsigned int nCardType, hanc_stream_info_struct* pHancEncodeInfo, void* pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags) { return bfcEncodeHancFrameEx(bvc_.get(), CRD_BLUE_NEUTRON, pHancEncodeInfo, pAudioBuffer, nAudioChannels, nAudioSamples, nSampleType, nAudioFlags); } BLUE_UINT32 bvc_wrapper::decode_hanc_frame(unsigned int nCardType, unsigned int* pHancBuffer, hanc_decode_struct* pHancDecodeInfo) { return bfcDecodeHancFrameEx(bvc_.get(), CRD_BLUE_NEUTRON, pHancBuffer, pHancDecodeInfo); } BLUE_UINT32 bvc_wrapper::get_frame_info_for_video_mode(const unsigned int nVideoMode, unsigned int& nWidth, unsigned int& nHeight, unsigned int& nRate, unsigned int& bIs1001, unsigned int& bIsProgressive) { return bfcUtilsGetFrameInfoForVideoMode(nVideoMode, nWidth, nHeight, nRate, bIs1001, bIsProgressive); } BLUE_UINT32 bvc_wrapper::get_bytes_per_frame(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame) { return bfcGetGoldenValue(nVideoMode, nMemoryFormat, nUpdateMethod, nBytesPerFrame); } std::string bvc_wrapper::get_string_for_card_type(unsigned int nCardType) { return bfcUtilsGetStringForCardType(nCardType); } std::wstring bvc_wrapper::get_wstring_for_video_mode(unsigned int nVideoMode) { std::wstring mode_desc; switch (nVideoMode) { case VID_FMT_PAL: mode_desc = L"pal"; break; case VID_FMT_NTSC: mode_desc = L"ntsc"; break; case VID_FMT_720P_2398: mode_desc = L"720p23"; break; case VID_FMT_720P_2400: mode_desc = L"720p24"; break; case VID_FMT_720P_2500: mode_desc = L"720p25"; break; case VID_FMT_720P_5000: mode_desc = L"720p50"; break; case VID_FMT_720P_2997: mode_desc = L"720p29"; break; case VID_FMT_720P_5994: mode_desc = L"720p59"; break; case VID_FMT_720P_3000: mode_desc = L"720p30"; break; case VID_FMT_720P_6000: mode_desc = L"720p60"; break; case VID_FMT_1080P_2397: mode_desc = L"1080p23"; break; case VID_FMT_1080P_2400: mode_desc = L"1080p24"; break; case VID_FMT_1080I_5000: mode_desc = L"1080i50"; break; case VID_FMT_1080I_5994: mode_desc = L"1080i59"; break; case VID_FMT_1080I_6000: mode_desc = L"1080i60"; break; case VID_FMT_1080P_2500: mode_desc = L"1080p25"; break; case VID_FMT_1080P_2997: mode_desc = L"1080p29"; break; case VID_FMT_1080P_3000: mode_desc = L"1080p30"; break; case VID_FMT_1080P_5000: mode_desc = L"1080p50"; break; case VID_FMT_1080P_5994: mode_desc = L"1080p59"; break; case VID_FMT_1080P_6000: mode_desc = L"1080p60"; break; default: mode_desc = L"invalid"; break; } return mode_desc; } int bvc_wrapper::get_num_audio_samples_for_frame(const BLUE_UINT32 nVideoMode, const BLUE_UINT32 nFrameNo) { return bfcUtilsGetAudioSamplesPerFrame(nVideoMode, nFrameNo); } EVideoMode vid_fmt_from_video_format(const core::video_format& fmt) { switch (fmt) { case core::video_format::pal: return VID_FMT_PAL; case core::video_format::ntsc: return VID_FMT_NTSC; case core::video_format::x576p2500: return VID_FMT_INVALID; // not supported case core::video_format::x720p2398: return VID_FMT_720P_2398; case core::video_format::x720p2400: return VID_FMT_720P_2400; case core::video_format::x720p2500: return VID_FMT_720P_2500; case core::video_format::x720p5000: return VID_FMT_720P_5000; case core::video_format::x720p2997: return VID_FMT_720P_2997; case core::video_format::x720p5994: return VID_FMT_720P_5994; case core::video_format::x720p3000: return VID_FMT_720P_3000; case core::video_format::x720p6000: return VID_FMT_720P_6000; case core::video_format::x1080p2398: return VID_FMT_1080P_2397; case core::video_format::x1080p2400: return VID_FMT_1080P_2400; case core::video_format::x1080i5000: return VID_FMT_1080I_5000; case core::video_format::x1080i5994: return VID_FMT_1080I_5994; case core::video_format::x1080i6000: return VID_FMT_1080I_6000; case core::video_format::x1080p2500: return VID_FMT_1080P_2500; case core::video_format::x1080p2997: return VID_FMT_1080P_2997; case core::video_format::x1080p3000: return VID_FMT_1080P_3000; case core::video_format::x1080p5000: return VID_FMT_1080P_5000; case core::video_format::x1080p5994: return VID_FMT_1080P_5994; case core::video_format::x1080p6000: return VID_FMT_1080P_6000; default: return VID_FMT_INVALID; } } bool is_epoch_card(bvc_wrapper& blue) { int device_id = 1; int card_type = 0; blue.query_card_type(card_type, device_id); switch (card_type) { case CRD_BLUE_EPOCH_HORIZON: case CRD_BLUE_EPOCH_CORE: case CRD_BLUE_EPOCH_ULTRA: case CRD_BLUE_EPOCH_2K_HORIZON: case CRD_BLUE_EPOCH_2K_CORE: case CRD_BLUE_EPOCH_2K_ULTRA: case CRD_BLUE_CREATE_HD: case CRD_BLUE_CREATE_2K: case CRD_BLUE_CREATE_2K_ULTRA: case CRD_BLUE_SUPER_NOVA: case CRD_BLUE_SUPER_NOVA_S_PLUS: case CRD_BLUE_NEUTRON: case CRD_BLUE_EPOCH_CG: return true; default: return false; } } bool is_epoch_neutron_1i2o_card(bvc_wrapper& blue) { BLUE_UINT32 val = 0; blue.get_card_property32(EPOCH_GET_PRODUCT_ID, val); if (val == ORAC_NEUTRON_1_IN_2_OUT_FIRMWARE_PRODUCTID) return true; else return false; } bool is_epoch_neutron_3o_card(bvc_wrapper& blue) { BLUE_UINT32 val = 0; blue.get_card_property32(EPOCH_GET_PRODUCT_ID, val); if (val == ORAC_NEUTRON_0_IN_3_OUT_FIRMWARE_PRODUCTID) return true; else return false; } std::wstring get_card_desc(bvc_wrapper blue, int device_id) { std::wstring card_desc; int card_type = 0; blue.query_card_type(card_type, device_id); switch (card_type) { case CRD_BLUE_EPOCH_2K_CORE: card_desc = L"Bluefish Epoch 2K Core"; break; case CRD_BLUE_EPOCH_2K_ULTRA: card_desc = L"Bluefish Epoch 2K Ultra"; break; case CRD_BLUE_EPOCH_HORIZON: card_desc = L"Bluefish Epoch Horizon"; break; case CRD_BLUE_EPOCH_CORE: card_desc = L"Blufishe Epoch Core"; break; case CRD_BLUE_EPOCH_ULTRA: card_desc = L"Bluefish Epoch Ultra"; break; case CRD_BLUE_CREATE_HD: card_desc = L"Bluefish Create HD"; break; case CRD_BLUE_CREATE_2K: card_desc = L"Bluefish Create 2K"; break; case CRD_BLUE_CREATE_2K_ULTRA: card_desc = L"Bluefish Create 2K Ultra"; break; case CRD_BLUE_SUPER_NOVA: card_desc = L"Bluefish SuperNova"; break; case CRD_BLUE_SUPER_NOVA_S_PLUS: card_desc = L"Bluefish SuperNova s+"; break; case CRD_BLUE_NEUTRON: card_desc = L"Bluefish Neutron 4k"; break; case CRD_BLUE_EPOCH_CG: card_desc = L"Bluefish Epoch CG"; break; default: card_desc = L"Unknown"; } return card_desc; } EVideoMode get_video_mode(bvc_wrapper& blue, const core::video_format_desc& format_desc) { EVideoMode vid_fmt = VID_FMT_INVALID; BLUE_UINT32 invalid_fmt = 0; BErr err = 0; err = blue.get_card_property32(INVALID_VIDEO_MODE_FLAG, invalid_fmt); vid_fmt = vid_fmt_from_video_format(format_desc.format); if (vid_fmt == VID_FMT_INVALID) CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"video-mode not supported: " + format_desc.name)); if ((unsigned int)vid_fmt >= invalid_fmt) CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L"video-mode not supported - Outside of valid range: " + format_desc.name)); return vid_fmt; } spl::shared_ptr create_blue() { auto pWrap = new bvc_wrapper(); return spl::shared_ptr(pWrap); } spl::shared_ptr create_blue(int device_index) { auto blue = create_blue(); if (BLUE_FAIL(blue->attach(device_index))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to attach device.")); return blue; } core::video_format_desc get_format_desc(bvc_wrapper& blue, EVideoMode vid_fmt, EMemoryFormat mem_fmt) { core::video_format_desc fmt; unsigned int width, height, duration = 0, time_scale = 0, rate = 0, bIs1001 = 0, is_progressive = 0, size = 0; std::vector audio_cadence; int field_count = 1; blue.get_frame_info_for_video_mode(vid_fmt, width, height, rate, bIs1001, is_progressive); blue.get_bytes_per_frame(vid_fmt, mem_fmt, UPD_FMT_FRAME, size); switch (vid_fmt) { case VID_FMT_NTSC: case VID_FMT_1080I_5994: duration = 30000; time_scale = 1001; audio_cadence = {1601, 1602, 1601, 1602, 1602}; break; case VID_FMT_2048_1080P_2500: case VID_FMT_2048_1080PSF_2500: case VID_FMT_576I_5000: case VID_FMT_1080P_2500: case VID_FMT_1080I_5000: case VID_FMT_1080PSF_2500: case VID_FMT_720P_2500: duration = 25000; time_scale = 1000; audio_cadence = {1920, 1920, 1920, 1920, 1920}; break; case VID_FMT_720P_5994: case VID_FMT_2048_1080P_5994: case VID_FMT_1080P_5994: duration = 60000; time_scale = 1001; audio_cadence = {801, 800, 801, 800, 800}; break; case VID_FMT_1080P_6000: case VID_FMT_2048_1080P_6000: case VID_FMT_720P_6000: duration = 60000; time_scale = 1000; audio_cadence = {801, 800, 801, 800, 800}; break; case VID_FMT_1080PSF_2397: case VID_FMT_1080P_2397: case VID_FMT_720P_2398: case VID_FMT_2048_1080PSF_2397: case VID_FMT_2048_1080P_2397: duration = 24000; time_scale = 1000; break; case VID_FMT_1080PSF_2400: case VID_FMT_1080P_2400: case VID_FMT_720P_2400: case VID_FMT_2048_1080PSF_2400: case VID_FMT_2048_1080P_2400: duration = 24000; time_scale = 1000; break; case VID_FMT_1080I_6000: case VID_FMT_1080PSF_3000: duration = 30000; time_scale = 1000; break; case VID_FMT_720P_2997: case VID_FMT_1080P_2997: case VID_FMT_2048_1080PSF_2997: case VID_FMT_2048_1080P_2997: case VID_FMT_1080PSF_2997: duration = 30000; time_scale = 1001; break; case VID_FMT_720P_3000: case VID_FMT_1080P_3000: case VID_FMT_2048_1080PSF_3000: case VID_FMT_2048_1080P_3000: duration = 30000; time_scale = 1001; break; case VID_FMT_720P_5000: case VID_FMT_1080P_5000: case VID_FMT_2048_1080P_5000: audio_cadence = {960, 960, 960, 960, 960}; duration = 50000; time_scale = 1000; break; } if (!is_progressive) field_count = 2; fmt.field_count = field_count; fmt = get_caspar_video_format(vid_fmt); fmt.size = size; fmt.audio_cadence = audio_cadence; fmt.name = blue.get_wstring_for_video_mode(vid_fmt); return fmt; } std::wstring get_sdi_inputs(bvc_wrapper& blue) { BLUE_UINT32 val = 0; blue.get_card_property32(CARD_FEATURE_CONNECTOR_INFO, val); int connectors = CARD_FEATURE_GET_SDI_INPUT_CONNECTOR_COUNT(val); return std::to_wstring(connectors); } std::wstring get_sdi_outputs(bvc_wrapper& blue) { BLUE_UINT32 val = 0; blue.get_card_property32(CARD_FEATURE_CONNECTOR_INFO, val); int connectors = CARD_FEATURE_GET_SDI_OUTPUT_CONNECTOR_COUNT(val); return std::to_wstring(connectors); } EVideoMode get_bluefish_video_format(core::video_format fmt) { switch (fmt) { case core::video_format::pal: return VID_FMT_PAL; case core::video_format::ntsc: return VID_FMT_NTSC; case core::video_format::x720p2398: return VID_FMT_720P_2398; case core::video_format::x720p2400: return VID_FMT_720P_2400; case core::video_format::x720p2500: return VID_FMT_720P_2500; case core::video_format::x720p2997: return VID_FMT_720P_2997; case core::video_format::x720p3000: return VID_FMT_720P_3000; case core::video_format::x720p5000: return VID_FMT_720P_5000; case core::video_format::x720p5994: return VID_FMT_720P_5994; case core::video_format::x720p6000: return VID_FMT_720P_6000; case core::video_format::x1080i5000: return VID_FMT_1080I_5000; case core::video_format::x1080i5994: return VID_FMT_1080I_5994; case core::video_format::x1080i6000: return VID_FMT_1080I_6000; case core::video_format::x1080p2398: return VID_FMT_1080P_2397; case core::video_format::x1080p2400: return VID_FMT_1080P_2400; case core::video_format::x1080p2500: return VID_FMT_1080P_2500; case core::video_format::x1080p2997: return VID_FMT_1080P_2997; case core::video_format::x1080p3000: return VID_FMT_1080P_3000; case core::video_format::x1080p5000: return VID_FMT_1080P_5000; case core::video_format::x1080p5994: return VID_FMT_1080P_5994; case core::video_format::x1080p6000: return VID_FMT_1080P_6000; default: return VID_FMT_INVALID; } } static core::video_format get_caspar_video_format(EVideoMode fmt) { switch (fmt) { case VID_FMT_PAL: return core::video_format::pal; case VID_FMT_NTSC: return core::video_format::ntsc; case VID_FMT_720P_2398: return core::video_format::x720p2398; case VID_FMT_720P_2400: return core::video_format::x720p2400; case VID_FMT_720P_2500: return core::video_format::x720p2500; case VID_FMT_720P_5000: return core::video_format::x720p5000; case VID_FMT_720P_2997: return core::video_format::x720p2997; case VID_FMT_720P_5994: return core::video_format::x720p5994; case VID_FMT_720P_3000: return core::video_format::x720p3000; case VID_FMT_720P_6000: return core::video_format::x720p6000; case VID_FMT_1080P_2397: return core::video_format::x1080p2398; case VID_FMT_1080P_2400: return core::video_format::x1080p2400; case VID_FMT_1080I_5000: return core::video_format::x1080i5000; case VID_FMT_1080I_5994: return core::video_format::x1080i5994; case VID_FMT_1080I_6000: return core::video_format::x1080i6000; case VID_FMT_1080P_2500: return core::video_format::x1080p2500; case VID_FMT_1080P_2997: return core::video_format::x1080p2997; case VID_FMT_1080P_3000: return core::video_format::x1080p3000; case VID_FMT_1080P_5000: return core::video_format::x1080p5000; case VID_FMT_1080P_5994: return core::video_format::x1080p5994; case VID_FMT_1080P_6000: return core::video_format::x1080p6000; default: return core::video_format::invalid; } } }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/util/blue_velvet.h000066400000000000000000000620001341175263200237750ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include "../interop/BlueVelvetC.h" #include #include #include #include namespace caspar { namespace bluefish { class bvc_wrapper { // Define a different type for each of the function ptrs. typedef const char*(__cdecl* pFunc_bfcGetVersion)(); typedef BLUEVELVETC_HANDLE(__cdecl* pFunc_bfcFactory)(); typedef void(__cdecl* pFunc_bfcDestroy)(BLUEVELVETC_HANDLE pHandle); typedef int(__cdecl* pFunc_bfcEnumerate)(BLUEVELVETC_HANDLE pHandle, int& iDevices); typedef int(__cdecl* pFunc_bfcQueryCardType)(BLUEVELVETC_HANDLE pHandle, int& iCardType, int iDeviceID); typedef int(__cdecl* pFunc_bfcAttach)(BLUEVELVETC_HANDLE pHandle, int iDeviceId); typedef int(__cdecl* pFunc_bfcDetach)(BLUEVELVETC_HANDLE pHandle); typedef int(__cdecl* pFunc_bfcQueryCardProperty32)(BLUEVELVETC_HANDLE pHandle, const int iProperty, unsigned int& nValue); typedef int(__cdecl* pFunc_bfcQueryCardProperty64)(BLUEVELVETC_HANDLE pHandle, const int iProperty, unsigned long long& ullValue); typedef int(__cdecl* pFunc_bfcSetCardProperty32)(BLUEVELVETC_HANDLE pHandle, const int iProperty, const unsigned int nValue); typedef int(__cdecl* pFunc_bfcSetCardProperty64)(BLUEVELVETC_HANDLE pHandle, const int iProperty, const unsigned long long ullValue); typedef int(__cdecl* pFunc_bfcGetCardSerialNumber)(BLUEVELVETC_HANDLE pHandle, char* pSerialNumber, unsigned int nStringSize); typedef int(__cdecl* pFunc_bfcGetCardFwVersion)(BLUEVELVETC_HANDLE pHandle, unsigned int& nValue); typedef int(__cdecl* pFunc_bfcWaitVideoSyncAsync)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, blue_video_sync_struct* pSyncData); typedef int(__cdecl* pFunc_bfcWaitVideoInputSync)(BLUEVELVETC_HANDLE pHandle, unsigned long ulUpdateType, unsigned long& ulFieldCount); typedef int(__cdecl* pFunc_bfcWaitVideoOutputSync)(BLUEVELVETC_HANDLE pHandle, unsigned long ulUpdateType, unsigned long& ulFieldCount); typedef int(__cdecl* pFunc_bfcGetVideoOutputCurrentFieldCount)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulFieldCount); typedef int(__cdecl* pFunc_bfcGetVideoInputCurrentFieldCount)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulFieldCount); typedef int(__cdecl* pFunc_bfcVideoCaptureStart)(BLUEVELVETC_HANDLE pHandle); typedef int(__cdecl* pFunc_bfcVideoCaptureStop)(BLUEVELVETC_HANDLE pHandle); typedef int(__cdecl* pFunc_bfcVideoPlaybackStart)(BLUEVELVETC_HANDLE pHandle, int iStep, int iLoop); typedef int(__cdecl* pFunc_bfcVideoPlaybackStop)(BLUEVELVETC_HANDLE pHandle, int iWait, int iFlush); typedef int(__cdecl* pFunc_bfcVideoPlaybackAllocate)(BLUEVELVETC_HANDLE pHandle, void** pAddress, unsigned long& ulBufferID, unsigned long& ulUnderrun); typedef int(__cdecl* pFunc_bfcVideoPlaybackPresent)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulUniqueID, unsigned long ulBufferID, unsigned long ulCount, int iKeep, int iOdd); typedef int(__cdecl* pFunc_bfcVideoPlaybackRelease)(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID); typedef int(__cdecl* pFunc_bfcGetCaptureVideoFrameInfoEx)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, struct blue_videoframe_info_ex& VideoFrameInfo, int iCompostLater, unsigned int* nCaptureFifoSize); typedef int(__cdecl* pFunc_bfcRenderBufferCapture)(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID); typedef int(__cdecl* pFunc_bfcRenderBufferUpdate)(BLUEVELVETC_HANDLE pHandle, unsigned long ulBufferID); typedef int(__cdecl* pFunc_bfcGetRenderBufferCount)(BLUEVELVETC_HANDLE pHandle, unsigned long& ulCount); typedef int(__cdecl* pFunc_bfcEncodeHancFrameEx)(BLUEVELVETC_HANDLE pHandle, unsigned int nCardType, struct hanc_stream_info_struct* pHancEncodeInfo, void* pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags); typedef int(__cdecl* pFunc_bfcDecodeHancFrameEx)(BLUEVELVETC_HANDLE pHandle, unsigned int nCardType, unsigned int* pHancBuffer, struct hanc_decode_struct* pHancDecodeInfo); #if defined(_WIN32) typedef int(__cdecl* pFunc_bfcSystemBufferReadAsync)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset); typedef int(__cdecl* pFunc_bfcSystemBufferWriteAsync)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset); #else typedef int(__cdecl *pFunc_bfcSystemBufferRead)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset; typedef int(__cdecl *pFunc_bfcSystemBufferWrite)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset; #endif typedef int(__cdecl* pFunc_bfcGetBytesForGroupPixels)(EMemoryFormat nMemoryFormat, unsigned int nVideoWidth, unsigned int& nVideoPitchBytes); typedef int(__cdecl* pFunc_bfcGetPixelsPerLine)(EVideoMode nVideoMode, unsigned int& nPixelsPerLine); typedef int(__cdecl* pFunc_bfcGetLinesPerFrame)(EVideoMode nVideoMode, EUpdateMethod nUpdateMethod, unsigned int& nLinesPerFrame); typedef int(__cdecl* pFunc_bfcGetBytesPerLine)(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, unsigned int& nBytesPerLine); typedef int(__cdecl* pFunc_bfcGetBytesPerFrame)(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame); typedef int(__cdecl* pFunc_bfcGetGoldenValue)(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nGoldenFrameSize); typedef int(__cdecl* pFunc_bfcGetVBILines)(EVideoMode nVideoMode, EDMADataType nDataType, unsigned int& nVBILinesPerFrame); typedef int(__cdecl* pFunc_bfcGetVANCGoldenValue)(unsigned int nCardType, EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EDMADataType nDataFormat, unsigned int& nVANCGoldenValue); typedef int(__cdecl* pFunc_bfcGetVANCLineBytes)(unsigned int nCardType, EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, unsigned int& nVANCLineBytes); typedef int(__cdecl* pFunc_bfcGetVANCLineCount)(unsigned int nCardType, EVideoMode nVideoMode, EDMADataType nDataFormat, unsigned int& nVANCLineCount); typedef int(__cdecl* pFunc_bfcGetWindowsDriverHandle)(BLUEVELVETC_HANDLE pHandle, HANDLE* pDriverHandle); typedef int(__cdecl* pFunc_bfcSetDynamicMemoryFormatChange)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, unsigned int nUniqueId, EMemoryFormat nMemoryFormat); // BlueVelvetCUtils functions typedef char*(__cdecl* pFunc_bfcUtilsGetStringForCardType)(const int iCardType); typedef char*(__cdecl* pFunc_bfcUtilsGetStringForBlueProductId)(const unsigned int nProductId); typedef char*(__cdecl* pFunc_bfcUtilsGetStringForVideoMode)(const unsigned int nVideoMode); typedef char*(__cdecl* pFunc_bfcUtilsGetStringForMemoryFormat)(const unsigned int nMemoryFormat); typedef int(__cdecl* pFunc_bfcUtilsGetMR2Routing)(const BLUEVELVETC_HANDLE pHandle, unsigned int& nSrcNode, const unsigned int nDestNode, unsigned int& nLinkType); typedef int(__cdecl* pFunc_bfcUtilsSetMR2Routing)(const BLUEVELVETC_HANDLE pHandle, const unsigned int nSrcNode, const unsigned int nDestNode, const unsigned int nLinkType); typedef int(__cdecl* pFunc_bfcUtilsGetAudioOutputRouting)(const BLUEVELVETC_HANDLE pHandle, const unsigned int nAudioConnectorType, unsigned int& nAudioSourceChannelId, unsigned int nAudioConnectorId); typedef int(__cdecl* pFunc_bfcUtilsSetAudioOutputRouting)(const BLUEVELVETC_HANDLE pHandle, const unsigned int nAudioConnectorType, unsigned int nAudioSourceChannelId, unsigned int nAudioConnectorId); typedef bool(__cdecl* pFunc_bfcUtilsIsVideoModeProgressive)(const unsigned int nVideoMode); typedef bool(__cdecl* pFunc_bfcUtilsIsVideoMode1001Framerate)(const unsigned int nVideoMode); typedef int(__cdecl* pFunc_bfcUtilsGetFpsForVideoMode)(const unsigned int nVideoMode); typedef int(__cdecl* pFunc_bfcUtilsGetVideoModeForFrameInfo)(const BLUE_UINT32 nWidth, const BLUE_UINT32 nHeight, const BLUE_UINT32 nRate, const BLUE_UINT32 bIs1001, const BLUE_UINT32 bIsProgressive, BLUE_UINT32& nVideoMode); typedef int(__cdecl* pFunc_bfcUtilsGetFrameInfoForVideoMode)(const BLUE_UINT32 nVideoMode, BLUE_UINT32& nWidth, BLUE_UINT32& nHeight, BLUE_UINT32& nRate, BLUE_UINT32& bIs1001, BLUE_UINT32& bIsProgressive); typedef int(__cdecl* pFunc_bfcUtilsGetAudioSamplesPerFrame)(const BLUE_UINT32 nVideoMode, const BLUE_UINT32 nFrameNo); public: bvc_wrapper(); // bfcFactory + function pointer lookups const char* get_version(); BLUE_UINT32 enumerate(int& iDevices); BLUE_UINT32 query_card_type(int& iCardType, int iDeviceID); BLUE_UINT32 attach(int iDeviceId); BLUE_UINT32 detach(); BLUE_UINT32 get_card_property32(const int iProperty, unsigned int& nValue); BLUE_UINT32 set_card_property32(const int iProperty, const unsigned int nValue); BLUE_UINT32 get_card_property64(const int iProperty, unsigned long long& nValue); BLUE_UINT32 set_card_property64(const int iProperty, const unsigned long long nValue); BLUE_UINT32 system_buffer_write(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset); BLUE_UINT32 system_buffer_read(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset); BLUE_UINT32 video_playback_stop(int iWait, int iFlush); BLUE_UINT32 video_playback_start(int wait, int loop); BLUE_UINT32 video_playback_allocate(unsigned long& buffer_id, unsigned long& underrun); BLUE_UINT32 video_playback_present(unsigned long buffer_id, unsigned long count, unsigned long keep, unsigned long odd); BLUE_UINT32 wait_video_output_sync(unsigned long ulUpdateType, unsigned long& ulFieldCount); BLUE_UINT32 wait_video_input_sync(unsigned long ulUpdateType, unsigned long& ulFieldCount); BLUE_UINT32 render_buffer_update(unsigned long ulBufferID); BLUE_UINT32 render_buffer_capture(unsigned long ulBufferID); BLUE_UINT32 encode_hanc_frame(unsigned int nCardType, struct hanc_stream_info_struct* pHancEncodeInfo, void* pAudioBuffer, unsigned int nAudioChannels, unsigned int nAudioSamples, unsigned int nSampleType, unsigned int nAudioFlags); BLUE_UINT32 decode_hanc_frame(unsigned int nCardType, unsigned int* pHancBuffer, struct hanc_decode_struct* pHancDecodeInfo); BLUE_UINT32 get_frame_info_for_video_mode(const unsigned int nVideoMode, unsigned int& nWidth, unsigned int& nHeight, unsigned int& nRate, unsigned int& bIs1001, unsigned int& bIsProgressive); BLUE_UINT32 get_bytes_per_frame(EVideoMode nVideoMode, EMemoryFormat nMemoryFormat, EUpdateMethod nUpdateMethod, unsigned int& nBytesPerFrame); std::string get_string_for_card_type(unsigned int nCardType); std::wstring get_wstring_for_video_mode(unsigned int nVideoMode); int get_num_audio_samples_for_frame(const BLUE_UINT32 nVideoMode, const BLUE_UINT32 nFrameNo); private: bool init_function_pointers(); std::shared_ptr h_module_; std::shared_ptr bvc_; // BlueVelvetC function pointers members pFunc_bfcGetVersion bfcGetVersion = nullptr; pFunc_bfcFactory bfcFactory = nullptr; pFunc_bfcDestroy bfcDestroy = nullptr; pFunc_bfcEnumerate bfcEnumerate = nullptr; pFunc_bfcQueryCardType bfcQueryCardType = nullptr; pFunc_bfcAttach bfcAttach = nullptr; pFunc_bfcDetach bfcDetach = nullptr; pFunc_bfcQueryCardProperty32 bfcQueryCardProperty32 = nullptr; pFunc_bfcQueryCardProperty64 bfcQueryCardProperty64 = nullptr; pFunc_bfcSetCardProperty32 bfcSetCardProperty32 = nullptr; pFunc_bfcSetCardProperty64 bfcSetCardProperty64 = nullptr; pFunc_bfcGetCardSerialNumber bfcGetCardSerialNumber = nullptr; pFunc_bfcGetCardFwVersion bfcGetCardFwVersion = nullptr; pFunc_bfcWaitVideoSyncAsync bfcWaitVideoSyncAsync = nullptr; pFunc_bfcWaitVideoInputSync bfcWaitVideoInputSync = nullptr; pFunc_bfcWaitVideoOutputSync bfcWaitVideoOutputSync = nullptr; pFunc_bfcGetVideoOutputCurrentFieldCount bfcGetVideoOutputCurrentFieldCount = nullptr; pFunc_bfcGetVideoInputCurrentFieldCount bfcGetVideoInputCurrentFieldCount = nullptr; pFunc_bfcVideoCaptureStart bfcVideoCaptureStart = nullptr; pFunc_bfcVideoCaptureStop bfcVideoCaptureStop = nullptr; pFunc_bfcVideoPlaybackStart bfcVideoPlaybackStart = nullptr; pFunc_bfcVideoPlaybackStop bfcVideoPlaybackStop = nullptr; pFunc_bfcVideoPlaybackAllocate bfcVideoPlaybackAllocate = nullptr; pFunc_bfcVideoPlaybackPresent bfcVideoPlaybackPresent = nullptr; pFunc_bfcVideoPlaybackRelease bfcVideoPlaybackRelease = nullptr; pFunc_bfcGetCaptureVideoFrameInfoEx bfcGetCaptureVideoFrameInfoEx = nullptr; pFunc_bfcRenderBufferCapture bfcRenderBufferCapture = nullptr; pFunc_bfcRenderBufferUpdate bfcRenderBufferUpdate = nullptr; pFunc_bfcGetRenderBufferCount bfcGetRenderBufferCount = nullptr; pFunc_bfcEncodeHancFrameEx bfcEncodeHancFrameEx = nullptr; pFunc_bfcDecodeHancFrameEx bfcDecodeHancFrameEx = nullptr; #if defined(_WIN32) pFunc_bfcSystemBufferReadAsync bfcSystemBufferReadAsync = nullptr; pFunc_bfcSystemBufferWriteAsync bfcSystemBufferWriteAsync = nullptr; #else pFunc_bfcSystemBufferRead bfcSystemBufferRead = nullptr; pFunc_bfcSystemBufferWrite bfcSystemBufferWrite = nullptr; #endif pFunc_bfcGetBytesForGroupPixels bfcGetBytesForGroupPixels = nullptr; pFunc_bfcGetPixelsPerLine bfcGetPixelsPerLine = nullptr; pFunc_bfcGetLinesPerFrame bfcGetLinesPerFrame = nullptr; pFunc_bfcGetBytesPerLine bfcGetBytesPerLine = nullptr; pFunc_bfcGetBytesPerFrame bfcGetBytesPerFrame = nullptr; pFunc_bfcGetGoldenValue bfcGetGoldenValue = nullptr; pFunc_bfcGetVBILines bfcGetVBILines = nullptr; pFunc_bfcGetVANCGoldenValue bfcGetVANCGoldenValue = nullptr; pFunc_bfcGetVANCLineBytes bfcGetVANCLineBytes = nullptr; pFunc_bfcGetVANCLineCount bfcGetVANCLineCount = nullptr; pFunc_bfcGetWindowsDriverHandle bfcGetWindowsDriverHandle = nullptr; pFunc_bfcUtilsGetStringForCardType bfcUtilsGetStringForCardType = nullptr; pFunc_bfcUtilsGetStringForBlueProductId bfcUtilsGetStringForBlueProductId = nullptr; pFunc_bfcUtilsGetStringForVideoMode bfcUtilsGetStringForVideoMode = nullptr; pFunc_bfcUtilsGetStringForMemoryFormat bfcUtilsGetStringForMemoryFormat = nullptr; pFunc_bfcUtilsGetMR2Routing bfcUtilsGetMR2Routing = nullptr; pFunc_bfcUtilsSetMR2Routing bfcUtilsSetMR2Routing = nullptr; pFunc_bfcUtilsGetAudioOutputRouting bfcUtilsGetAudioOutputRouting = nullptr; pFunc_bfcUtilsSetAudioOutputRouting bfcUtilsSetAudioOutputRouting = nullptr; pFunc_bfcUtilsIsVideoModeProgressive bfcUtilsIsVideoModeProgressive = nullptr; pFunc_bfcUtilsIsVideoMode1001Framerate bfcUtilsIsVideoMode1001Framerate = nullptr; pFunc_bfcUtilsGetFpsForVideoMode bfcUtilsGetFpsForVideoMode = nullptr; pFunc_bfcUtilsGetVideoModeForFrameInfo bfcUtilsGetVideoModeForFrameInfo = nullptr; pFunc_bfcUtilsGetFrameInfoForVideoMode bfcUtilsGetFrameInfoForVideoMode = nullptr; pFunc_bfcUtilsGetAudioSamplesPerFrame bfcUtilsGetAudioSamplesPerFrame = nullptr; }; spl::shared_ptr create_blue(); spl::shared_ptr create_blue(int device_index); core::video_format_desc get_format_desc(bvc_wrapper& blue, EVideoMode vid_fmt, EMemoryFormat mem_fmt); bool is_epoch_card(bvc_wrapper& blue); bool is_epoch_neutron_1i2o_card(bvc_wrapper& blue); bool is_epoch_neutron_3o_card(bvc_wrapper& blue); std::wstring get_card_desc(bvc_wrapper blue, int device_id); std::wstring get_sdi_inputs(bvc_wrapper& blue); std::wstring get_sdi_outputs(bvc_wrapper& blue); EVideoMode get_bluefish_video_format(core::video_format fmt); static core::video_format get_caspar_video_format(EVideoMode fmt); }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/bluefish/util/memory.h000066400000000000000000000040671341175263200230020ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com James Wise, james.wise@bluefish444.com */ #pragma once #include #include #include namespace caspar { namespace bluefish { static const size_t MAX_HANC_BUFFER_SIZE = 256 * 1024; static const size_t MAX_VBI_BUFFER_SIZE = 36 * 1920 * 4; struct blue_dma_buffer { public: blue_dma_buffer(int image_size, int id) : id_(id) , image_size_(image_size) , hanc_size_(MAX_HANC_BUFFER_SIZE) , image_buffer_(image_size_) , hanc_buffer_(hanc_size_) { } int id() const { return id_; } PBYTE image_data() { return image_buffer_.data(); } PBYTE hanc_data() { return hanc_buffer_.data(); } size_t image_size() const { return image_size_; } size_t hanc_size() const { return hanc_size_; } private: int id_; size_t image_size_; size_t hanc_size_; std::vector> image_buffer_; std::vector> hanc_buffer_; }; typedef std::shared_ptr blue_dma_buffer_ptr; }} // namespace caspar::bluefish server-2.2.0-stable/src/modules/decklink/000077500000000000000000000000001341175263200203205ustar00rootroot00000000000000server-2.2.0-stable/src/modules/decklink/CMakeLists.txt000066400000000000000000000041621341175263200230630ustar00rootroot00000000000000cmake_minimum_required (VERSION 2.6) project (decklink) set(SOURCES consumer/decklink_consumer.cpp producer/decklink_producer.cpp decklink.cpp StdAfx.cpp ) set(HEADERS consumer/decklink_consumer.h producer/decklink_producer.h util/util.h decklink.h decklink_api.h StdAfx.h ) if (MSVC) set(OS_SPECIFIC_SOURCES StdAfx.c interop/DeckLinkAPI_i.c interop/DeckLinkAPI.h interop/DeckLinkAPIVersion.h ) else() set(OS_SPECIFIC_SOURCES linux_interop/DeckLinkAPIConfiguration.h linux_interop/DeckLinkAPIDeckControl.h linux_interop/DeckLinkAPIDispatch.cpp linux_interop/DeckLinkAPIModes.h linux_interop/DeckLinkAPI_v10_2.h linux_interop/DeckLinkAPI_v7_3.h linux_interop/DeckLinkAPI_v7_9.h linux_interop/DeckLinkAPI_v8_1.h linux_interop/DeckLinkAPI_v9_9.h linux_interop/LinuxCOM.h linux_interop/DeckLinkAPIConfiguration_v10_2.h linux_interop/DeckLinkAPIDiscovery.h linux_interop/DeckLinkAPI.h linux_interop/DeckLinkAPITypes.h linux_interop/DeckLinkAPI_v7_1.h linux_interop/DeckLinkAPI_v7_6.h linux_interop/DeckLinkAPI_v8_0.h linux_interop/DeckLinkAPI_v9_2.h linux_interop/DeckLinkAPIVersion.h ) endif () add_library(decklink ${SOURCES} ${HEADERS} ${OS_SPECIFIC_SOURCES}) add_precompiled_header(decklink StdAfx.h FORCEINCLUDE) configure_file("${PROJECT_SOURCE_DIR}/packages.config" "${CMAKE_CURRENT_BINARY_DIR}/packages.config") include_directories(..) include_directories(../..) include_directories(${BOOST_INCLUDE_PATH}) include_directories(${TBB_INCLUDE_PATH}) include_directories(${FFMPEG_INCLUDE_PATH}) set_target_properties(decklink PROPERTIES FOLDER modules) source_group(sources ./*) source_group(sources\\consumer consumer/*) source_group(sources\\interop interop/*) source_group(sources\\producer producer/*) source_group(sources\\util util/*) if (MSVC) target_link_libraries(decklink common core ffmpeg ) else() target_link_libraries(decklink common core ffmpeg dl ) endif () casparcg_add_include_statement("modules/decklink/decklink.h") casparcg_add_init_statement("decklink::init" "decklink") casparcg_add_module_project("decklink") server-2.2.0-stable/src/modules/decklink/StdAfx.c000066400000000000000000000016031341175263200216550ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "StdAfx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file server-2.2.0-stable/src/modules/decklink/StdAfx.cpp000066400000000000000000000016261341175263200222220ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "StdAfx.h" // TODO: reference any additional headers you need in STDAFX.H // and not in this file server-2.2.0-stable/src/modules/decklink/StdAfx.h000066400000000000000000000041661341175263200216710ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #ifdef __cplusplus #if defined _DEBUG && defined _MSC_VER #include #endif #define NOMINMAX #define WIN32_LEAN_AND_MEAN #if defined(_MSC_VER) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(_MSC_VER) #pragma warning(push) #pragma warning(disable : 4244) #endif extern "C" { #define __STDC_CONSTANT_MACROS #define __STDC_LIMIT_MACROS #include } #if defined(_MSC_VER) #pragma warning(pop) #endif #pragma warning(push) #pragma warning(disable : 4996) #if defined(_MSC_VER) #include #include #include #endif #pragma warning(pop) #include #include "../common/except.h" #include "../common/log.h" #include "../common/memory.h" #include "../common/timer.h" #include "../common/utf.h" #endif #if defined(_MSC_VER) #include #include #endif server-2.2.0-stable/src/modules/decklink/consumer/000077500000000000000000000000001341175263200221535ustar00rootroot00000000000000server-2.2.0-stable/src/modules/decklink/consumer/decklink_consumer.cpp000066400000000000000000000735361341175263200263740ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "../StdAfx.h" #include "decklink_consumer.h" #include "../decklink.h" #include "../util/util.h" #include "../decklink_api.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace caspar { namespace decklink { struct configuration { enum class keyer_t { internal_keyer, external_keyer, external_separate_device_keyer, default_keyer = external_keyer }; enum class latency_t { low_latency, normal_latency, default_latency = normal_latency }; int device_index = 1; int key_device_idx = 0; bool embedded_audio = false; keyer_t keyer = keyer_t::default_keyer; latency_t latency = latency_t::default_latency; bool key_only = false; int base_buffer_depth = 3; int buffer_depth() const { return base_buffer_depth + (latency == latency_t::low_latency ? 0 : 1) + (embedded_audio ? 1 : 0); // TODO: Do we need this? } int key_device_index() const { return key_device_idx == 0 ? device_index + 1 : key_device_idx; } }; template void set_latency(const com_iface_ptr& config, configuration::latency_t latency, const std::wstring& print) { if (latency == configuration::latency_t::low_latency) { config->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, true); CASPAR_LOG(info) << print << L" Enabled low-latency mode."; } else if (latency == configuration::latency_t::normal_latency) { config->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, false); CASPAR_LOG(info) << print << L" Disabled low-latency mode."; } } void set_keyer(const com_iface_ptr& attributes, const com_iface_ptr& decklink_keyer, configuration::keyer_t keyer, const std::wstring& print) { if (keyer == configuration::keyer_t::internal_keyer) { BOOL value = true; if (SUCCEEDED(attributes->GetFlag(BMDDeckLinkSupportsInternalKeying, &value)) && !value) CASPAR_LOG(error) << print << L" Failed to enable internal keyer."; else if (FAILED(decklink_keyer->Enable(FALSE))) CASPAR_LOG(error) << print << L" Failed to enable internal keyer."; else if (FAILED(decklink_keyer->SetLevel(255))) CASPAR_LOG(error) << print << L" Failed to set key-level to max."; else CASPAR_LOG(info) << print << L" Enabled internal keyer."; } else if (keyer == configuration::keyer_t::external_keyer) { BOOL value = true; if (SUCCEEDED(attributes->GetFlag(BMDDeckLinkSupportsExternalKeying, &value)) && !value) CASPAR_LOG(error) << print << L" Failed to enable external keyer."; else if (FAILED(decklink_keyer->Enable(TRUE))) CASPAR_LOG(error) << print << L" Failed to enable external keyer."; else if (FAILED(decklink_keyer->SetLevel(255))) CASPAR_LOG(error) << print << L" Failed to set key-level to max."; else CASPAR_LOG(info) << print << L" Enabled external keyer."; } } class decklink_frame : public IDeckLinkVideoFrame { core::video_format_desc format_desc_; std::shared_ptr data_; std::atomic ref_count_{0}; int nb_samples_; public: decklink_frame(std::shared_ptr data, const core::video_format_desc& format_desc, int nb_samples) : data_(data) , format_desc_(format_desc) , nb_samples_(nb_samples) { } // IUnknown virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) { return E_NOINTERFACE; } virtual ULONG STDMETHODCALLTYPE AddRef() { return ++ref_count_; } virtual ULONG STDMETHODCALLTYPE Release() { if (--ref_count_ == 0) { delete this; return 0; } return ref_count_; } // IDecklinkVideoFrame virtual long STDMETHODCALLTYPE GetWidth() { return static_cast(format_desc_.width); } virtual long STDMETHODCALLTYPE GetHeight() { return static_cast(format_desc_.height); } virtual long STDMETHODCALLTYPE GetRowBytes() { return static_cast(format_desc_.width * 4); } virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat() { return bmdFormat8BitBGRA; } virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags() { return bmdFrameFlagDefault; } virtual HRESULT STDMETHODCALLTYPE GetBytes(void** buffer) { *buffer = data_.get(); return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode** timecode) { return S_FALSE; } virtual HRESULT STDMETHODCALLTYPE GetAncillaryData(IDeckLinkVideoFrameAncillary** ancillary) { return S_FALSE; } int nb_samples() const { return nb_samples_; } }; struct key_video_context : public IDeckLinkVideoOutputCallback { const configuration config_; com_ptr decklink_ = get_device(config_.key_device_index()); com_iface_ptr output_ = iface_cast(decklink_); com_iface_ptr keyer_ = iface_cast(decklink_, true); com_iface_ptr attributes_ = iface_cast(decklink_); com_iface_ptr configuration_ = iface_cast(decklink_); std::atomic scheduled_frames_completed_; key_video_context(const configuration& config, const std::wstring& print) : config_(config) { scheduled_frames_completed_ = 0; set_latency(configuration_, config.latency, print); set_keyer(attributes_, keyer_, config.keyer, print); if (FAILED(output_->SetScheduledFrameCompletionCallback(this))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print + L" Failed to set key playback completion callback.") << boost::errinfo_api_function("SetScheduledFrameCompletionCallback")); } template void enable_video(BMDDisplayMode display_mode, const Print& print) { if (FAILED(output_->EnableVideoOutput(display_mode, bmdVideoOutputFlagDefault))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Could not enable key video output.")); if (FAILED(output_->SetScheduledFrameCompletionCallback(this))) CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set key playback completion callback.") << boost::errinfo_api_function("SetScheduledFrameCompletionCallback")); } virtual ~key_video_context() { if (output_) { output_->StopScheduledPlayback(0, nullptr, 0); output_->DisableVideoOutput(); } } virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) { return E_NOINTERFACE; } virtual ULONG STDMETHODCALLTYPE AddRef() { return 1; } virtual ULONG STDMETHODCALLTYPE Release() { return 1; } virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped() { return S_OK; } virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame* completed_frame, BMDOutputFrameCompletionResult result) { ++scheduled_frames_completed_; // Let the fill callback keep the pace, so no scheduling here. return S_OK; } }; struct decklink_consumer : public IDeckLinkVideoOutputCallback { const int channel_index_; const configuration config_; com_ptr decklink_ = get_device(config_.device_index); com_iface_ptr output_ = iface_cast(decklink_); com_iface_ptr configuration_ = iface_cast(decklink_); com_iface_ptr keyer_ = iface_cast(decklink_, true); com_iface_ptr attributes_ = iface_cast(decklink_); std::mutex exception_mutex_; std::exception_ptr exception_; const std::wstring model_name_ = get_model_name(decklink_); const core::video_format_desc format_desc_; std::mutex buffer_mutex_; std::condition_variable buffer_cond_; std::queue buffer_; int buffer_capacity_ = 1; const int buffer_size_ = config_.buffer_depth(); // Minimum buffer-size 3. long long video_scheduled_ = 0; long long audio_scheduled_ = 0; boost::circular_buffer> audio_container_{static_cast(buffer_size_ + 1)}; spl::shared_ptr graph_; caspar::timer tick_timer_; reference_signal_detector reference_signal_detector_{output_}; std::atomic scheduled_frames_completed_{0}; std::unique_ptr key_context_; com_ptr mode_ = get_display_mode(output_, format_desc_.format, bmdFormat8BitBGRA, bmdVideoOutputFlagDefault); int field_count_ = mode_->GetFieldDominance() != bmdProgressiveFrame ? 2 : 1; std::atomic abort_request_{false}; public: decklink_consumer(const configuration& config, const core::video_format_desc& format_desc, int channel_index) : channel_index_(channel_index) , config_(config) , format_desc_(format_desc) { if (config.keyer == configuration::keyer_t::external_separate_device_keyer) { key_context_.reset(new key_video_context(config, print())); } graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f)); graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f)); graph_->set_color("flushed-frame", diagnostics::color(0.4f, 0.3f, 0.8f)); graph_->set_color("buffered-audio", diagnostics::color(0.9f, 0.9f, 0.5f)); graph_->set_color("buffered-video", diagnostics::color(0.2f, 0.9f, 0.9f)); if (key_context_) { graph_->set_color("key-offset", diagnostics::color(1.0f, 0.0f, 0.0f)); } graph_->set_text(print()); diagnostics::register_graph(graph_); enable_video(mode_->GetDisplayMode()); if (config.embedded_audio) { enable_audio(); } set_latency(configuration_, config.latency, print()); set_keyer(attributes_, keyer_, config.keyer, print()); if (config.embedded_audio) { output_->BeginAudioPreroll(); } for (int n = 0; n < buffer_size_; ++n) { auto nb_samples = format_desc_.audio_cadence[n % format_desc_.audio_cadence.size()] * field_count_; if (config.embedded_audio) { schedule_next_audio(std::vector(nb_samples * format_desc_.audio_channels), nb_samples); } std::shared_ptr image_data(scalable_aligned_malloc(format_desc_.size, 64), scalable_aligned_free); schedule_next_video(image_data, nb_samples); } if (config.embedded_audio) { output_->EndAudioPreroll(); } start_playback(); } ~decklink_consumer() { abort_request_ = true; buffer_cond_.notify_all(); if (output_ != nullptr) { output_->StopScheduledPlayback(0, nullptr, 0); if (config_.embedded_audio) { output_->DisableAudioOutput(); } output_->DisableVideoOutput(); } } void enable_audio() { if (FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType32bitInteger, format_desc_.audio_channels, bmdAudioOutputStreamTimestamped))) { CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Could not enable audio output.")); } CASPAR_LOG(info) << print() << L" Enabled embedded-audio."; } void enable_video(BMDDisplayMode display_mode) { if (FAILED(output_->EnableVideoOutput(display_mode, bmdVideoOutputFlagDefault))) { CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Could not enable fill video output.")); } if (FAILED(output_->SetScheduledFrameCompletionCallback(this))) { CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to set fill playback completion callback.") << boost::errinfo_api_function("SetScheduledFrameCompletionCallback")); } if (key_context_) { key_context_->enable_video(display_mode, [this]() { return print(); }); } } void start_playback() { if (FAILED(output_->StartScheduledPlayback(0, format_desc_.time_scale, 1.0))) { CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to schedule fill playback.")); } if (key_context_ && FAILED(key_context_->output_->StartScheduledPlayback(0, format_desc_.time_scale, 1.0))) { CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L" Failed to schedule key playback.")); } } virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) { return E_NOINTERFACE; } virtual ULONG STDMETHODCALLTYPE AddRef() { return 1; } virtual ULONG STDMETHODCALLTYPE Release() { return 1; } virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped() { CASPAR_LOG(info) << print() << L" Scheduled playback has stopped."; return S_OK; } virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame* completed_frame, BMDOutputFrameCompletionResult result) { #ifdef WIN32 thread_local auto priority_set = false; if (!priority_set) { priority_set = true; SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); } #endif try { auto tick_time = tick_timer_.elapsed() * format_desc_.fps / field_count_ * 0.5; graph_->set_value("tick-time", tick_time); tick_timer_.restart(); reference_signal_detector_.detect_change([this]() { return print(); }); auto dframe = reinterpret_cast(completed_frame); ++scheduled_frames_completed_; if (key_context_) { graph_->set_value( "key-offset", static_cast(scheduled_frames_completed_ - key_context_->scheduled_frames_completed_) * 0.1 + 0.5); } if (result == bmdOutputFrameDisplayedLate) { graph_->set_tag(diagnostics::tag_severity::WARNING, "late-frame"); video_scheduled_ += format_desc_.duration * field_count_; audio_scheduled_ += dframe->nb_samples(); } else if (result == bmdOutputFrameDropped) { graph_->set_tag(diagnostics::tag_severity::WARNING, "dropped-frame"); } else if (result == bmdOutputFrameFlushed) { graph_->set_tag(diagnostics::tag_severity::WARNING, "flushed-frame"); } { UINT32 buffered; output_->GetBufferedVideoFrameCount(&buffered); graph_->set_value("buffered-video", static_cast(buffered) / (config_.buffer_depth())); if (config_.embedded_audio) { output_->GetBufferedAudioSampleFrameCount(&buffered); graph_->set_value("buffered-audio", static_cast(buffered) / (format_desc_.audio_cadence[0] * field_count_ * config_.buffer_depth())); } } std::shared_ptr image_data(scalable_aligned_malloc(format_desc_.size, 64), scalable_aligned_free); std::vector audio_data; std::vector frames{pop()}; if (mode_->GetFieldDominance() != bmdProgressiveFrame) { frames.push_back(pop()); if (abort_request_) { return E_FAIL; } if (mode_->GetFieldDominance() != bmdUpperFieldFirst) { std::swap(frames[0], frames[1]); } for (auto y = 0; y < format_desc_.height; ++y) { std::memcpy(reinterpret_cast(image_data.get()) + y * format_desc_.width * 4, frames[y % 2].image_data(0).data() + y * format_desc_.width * 4, format_desc_.width * 4); } audio_data.insert(audio_data.end(), frames[0].audio_data().begin(), frames[0].audio_data().end()); audio_data.insert(audio_data.end(), frames[1].audio_data().begin(), frames[1].audio_data().end()); } else { if (abort_request_) { return E_FAIL; } for (auto y = 0; y < format_desc_.height; ++y) { std::memcpy(reinterpret_cast(image_data.get()) + y * format_desc_.width * 4, frames[0].image_data(0).data() + y * format_desc_.width * 4, format_desc_.width * 4); } audio_data.insert(audio_data.end(), frames[0].audio_data().begin(), frames[0].audio_data().end()); } const auto nb_samples = static_cast(audio_data.size()) / format_desc_.audio_channels; schedule_next_video(image_data, nb_samples); if (config_.embedded_audio) { schedule_next_audio(std::move(audio_data), nb_samples); } } catch (...) { std::lock_guard lock(exception_mutex_); exception_ = std::current_exception(); return E_FAIL; } return S_OK; } core::const_frame pop() { core::const_frame frame; { std::unique_lock lock(buffer_mutex_); buffer_cond_.wait(lock, [&] { return !buffer_.empty() || abort_request_; }); if (!abort_request_) { frame = std::move(buffer_.front()); buffer_.pop(); } } buffer_cond_.notify_all(); return frame; } void schedule_next_audio(std::vector audio, int nb_samples) { // TODO (refactor) does ScheduleAudioSamples copy data? audio_container_.push_back(std::move(audio)); if (FAILED(output_->ScheduleAudioSamples(audio_container_.back().data(), nb_samples, audio_scheduled_, format_desc_.audio_sample_rate, nullptr))) { CASPAR_LOG(error) << print() << L" Failed to schedule audio."; } audio_scheduled_ += nb_samples; } void schedule_next_video(std::shared_ptr fill, int nb_samples) { std::shared_ptr key; if (key_context_ || config_.key_only) { key = std::shared_ptr(scalable_aligned_malloc(format_desc_.size, 64), scalable_aligned_free); aligned_memshfl(key.get(), fill.get(), format_desc_.size, 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303); if (config_.key_only) { fill = key; } } if (key_context_) { auto key_frame = wrap_raw(new decklink_frame(key, format_desc_, nb_samples)); if (FAILED(key_context_->output_->ScheduleVideoFrame(get_raw(key_frame), video_scheduled_, format_desc_.duration * field_count_, format_desc_.time_scale))) { CASPAR_LOG(error) << print() << L" Failed to schedule key video."; } } auto fill_frame = wrap_raw(new decklink_frame(fill, format_desc_, nb_samples)); if (FAILED(output_->ScheduleVideoFrame(get_raw(fill_frame), video_scheduled_, format_desc_.duration * field_count_, format_desc_.time_scale))) { CASPAR_LOG(error) << print() << L" Failed to schedule fill video."; } video_scheduled_ += format_desc_.duration * field_count_; } bool send(core::const_frame frame) { { std::lock_guard lock(exception_mutex_); if (exception_ != nullptr) { std::rethrow_exception(exception_); } } if (!frame) { return !abort_request_; } { std::unique_lock lock(buffer_mutex_); buffer_cond_.wait(lock, [&] { return buffer_.size() < buffer_capacity_ || abort_request_; }); buffer_.push(std::move(frame)); } buffer_cond_.notify_all(); return !abort_request_; } std::wstring print() const { if (config_.keyer == configuration::keyer_t::external_separate_device_keyer) { return model_name_ + L" [" + boost::lexical_cast(channel_index_) + L"-" + boost::lexical_cast(config_.device_index) + L"&&" + boost::lexical_cast(config_.key_device_index()) + L"|" + format_desc_.name + L"]"; } else { return model_name_ + L" [" + boost::lexical_cast(channel_index_) + L"-" + boost::lexical_cast(config_.device_index) + L"|" + format_desc_.name + L"]"; } } }; struct decklink_consumer_proxy : public core::frame_consumer { const configuration config_; std::unique_ptr consumer_; core::video_format_desc format_desc_; executor executor_; public: decklink_consumer_proxy(const configuration& config) : config_(config) , executor_(L"decklink_consumer[" + boost::lexical_cast(config.device_index) + L"]") { executor_.begin_invoke([=] { com_initialize(); }); } ~decklink_consumer_proxy() { executor_.invoke([=] { #ifdef WIN32 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); #endif consumer_.reset(); com_uninitialize(); }); } void initialize(const core::video_format_desc& format_desc, int channel_index) override { format_desc_ = format_desc; executor_.invoke([=] { consumer_.reset(); consumer_.reset(new decklink_consumer(config_, format_desc, channel_index)); }); } std::future send(core::const_frame frame) override { return executor_.begin_invoke([=] { return consumer_->send(frame); }); } std::wstring print() const override { return consumer_ ? consumer_->print() : L"[decklink_consumer]"; } std::wstring name() const override { return L"decklink"; } int index() const override { return 300 + config_.device_index; } bool has_synchronization_clock() const override { return true; } }; spl::shared_ptr create_consumer(const std::vector& params, std::vector> channels) { if (params.size() < 1 || !boost::iequals(params.at(0), L"DECKLINK")) { return core::frame_consumer::empty(); } configuration config; if (params.size() > 1) config.device_index = boost::lexical_cast(params.at(1)); if (contains_param(L"INTERNAL_KEY", params)) { config.keyer = configuration::keyer_t::internal_keyer; } else if (contains_param(L"EXTERNAL_KEY", params)) { config.keyer = configuration::keyer_t::external_keyer; } else if (contains_param(L"EXTERNAL_SEPARATE_DEVICE_KEY", params)) { config.keyer = configuration::keyer_t::external_separate_device_keyer; } else { config.keyer = configuration::keyer_t::default_keyer; } if (contains_param(L"LOW_LATENCY", params)) { config.latency = configuration::latency_t::low_latency; } config.embedded_audio = contains_param(L"EMBEDDED_AUDIO", params); config.key_only = contains_param(L"KEY_ONLY", params); return spl::make_shared(config); } spl::shared_ptr create_preconfigured_consumer(const boost::property_tree::wptree& ptree, std::vector> channels) { configuration config; auto keyer = ptree.get(L"keyer", L"default"); if (keyer == L"external") { config.keyer = configuration::keyer_t::external_keyer; } else if (keyer == L"internal") { config.keyer = configuration::keyer_t::internal_keyer; } else if (keyer == L"external_separate_device") { config.keyer = configuration::keyer_t::external_separate_device_keyer; } auto latency = ptree.get(L"latency", L"default"); if (latency == L"low") { config.latency = configuration::latency_t::low_latency; } else if (latency == L"normal") { config.latency = configuration::latency_t::normal_latency; } config.key_only = ptree.get(L"key-only", config.key_only); config.device_index = ptree.get(L"device", config.device_index); config.key_device_idx = ptree.get(L"key-device", config.key_device_idx); config.embedded_audio = ptree.get(L"embedded-audio", config.embedded_audio); config.base_buffer_depth = ptree.get(L"buffer-depth", config.base_buffer_depth); return spl::make_shared(config); } }} // namespace caspar::decklink /* ############################################################################## Pre-rolling Mail: 2011-05-09 Yoshan BMD Developer Support developer@blackmagic-design.com ----------------------------------------------------------------------------- Thanks for your inquiry. The minimum number of frames that you can preroll for scheduled playback is three frames for video and four frames for audio. As you mentioned if you preroll less frames then playback will not start or playback will be very sporadic. From our experience with Media Express, we recommended that at least seven frames are prerolled for smooth playback. Regarding the bmdDeckLinkConfigLowLatencyVideoOutput flag: There can be around 3 frames worth of latency on scheduled output. When the bmdDeckLinkConfigLowLatencyVideoOutput flag is used this latency is reduced or removed for scheduled playback. If the DisplayVideoFrameSync() method is used, the bmdDeckLinkConfigLowLatencyVideoOutput setting will guarantee that the provided frame will be output as soon the previous frame output has been completed. ################################################################################ */ /* ############################################################################## Async DMA Transfer without redundant copying Mail: 2011-05-10 Yoshan BMD Developer Support developer@blackmagic-design.com ----------------------------------------------------------------------------- Thanks for your inquiry. You could try subclassing IDeckLinkMutableVideoFrame and providing a pointer to your video buffer when GetBytes() is called. This may help to keep copying to a minimum. Please ensure that the pixel format is in bmdFormat10BitYUV, otherwise the DeckLink API / driver will have to colourspace convert which may result in additional copying. ################################################################################ */ server-2.2.0-stable/src/modules/decklink/consumer/decklink_consumer.h000066400000000000000000000027041341175263200260260ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include #include #include #include #include namespace caspar { namespace decklink { spl::shared_ptr create_consumer(const std::vector& params, std::vector> channels); spl::shared_ptr create_preconfigured_consumer(const boost::property_tree::wptree& ptree, std::vector> channels); }} // namespace caspar::decklink server-2.2.0-stable/src/modules/decklink/decklink.cpp000066400000000000000000000046301341175263200226130ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #include "StdAfx.h" #include "decklink.h" #include "util/util.h" #include "consumer/decklink_consumer.h" #include "producer/decklink_producer.h" #include #include #include #include "decklink_api.h" namespace caspar { namespace decklink { std::wstring get_version() { std::wstring ver = L"Not found"; struct co_init init; try { ver = decklink::version(create_iterator()); } catch (...) { } return ver; } std::vector device_list() { std::vector devices; struct co_init init; try { auto pDecklinkIterator = create_iterator(); IDeckLink* decklink; for (int n = 1; pDecklinkIterator->Next(&decklink) == S_OK; ++n) { String m_name; bool success = SUCCEEDED(decklink->GetModelName(&m_name)); decklink->Release(); std::wstring model_name = L"Unknown"; if (success) model_name = u16(m_name); devices.push_back(model_name + L" [" + boost::lexical_cast(n) + L"]"); } } catch (...) { } return devices; } void init(core::module_dependencies dependencies) { dependencies.consumer_registry->register_consumer_factory(L"Decklink Consumer", create_consumer); dependencies.consumer_registry->register_preconfigured_consumer_factory(L"decklink", create_preconfigured_consumer); dependencies.producer_registry->register_producer_factory(L"Decklink Producer", create_producer); } }} // namespace caspar::decklink server-2.2.0-stable/src/modules/decklink/decklink.h000066400000000000000000000020011341175263200222460ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Robert Nagy, ronag89@gmail.com */ #pragma once #include namespace caspar { namespace decklink { std::wstring get_version(); void init(core::module_dependencies dependencies); }} // namespace caspar::decklink server-2.2.0-stable/src/modules/decklink/decklink_api.h000066400000000000000000000116601341175263200231120ustar00rootroot00000000000000/* * Copyright (c) 2011 Sveriges Television AB * * This file is part of CasparCG (www.casparcg.com). * * CasparCG is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * CasparCG 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 CasparCG. If not, see . * * Author: Helge Norberg, helge.norberg@svt.se */ #pragma once #include #if defined(_MSC_VER) #include "interop/DeckLinkAPI.h" #pragma warning(push) #pragma warning(disable : 4996) #include #include #include #pragma warning(pop) namespace caspar { namespace decklink { typedef BSTR String; typedef unsigned int UINT32; static void com_initialize() { ::CoInitialize(nullptr); } static void com_uninitialize() { ::CoUninitialize(); } struct co_init { co_init() { ::CoInitialize(nullptr); } ~co_init() { ::CoUninitialize(); } }; template using com_ptr = CComPtr; template using com_iface_ptr = CComQIPtr; template