summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Doxyfile242
-rw-r--r--asdcplib/src/wscript14
-rw-r--r--doc/mainpage.txt76
-rw-r--r--examples/make_dcp.cc140
-rw-r--r--examples/read_dcp.cc90
-rw-r--r--examples/wscript12
-rw-r--r--libdcp-1.0.pc.in (renamed from libdcp.pc.in)0
-rwxr-xr-xrun/examples/read_dcp12
-rw-r--r--src/argb_frame.cc8
-rw-r--r--src/argb_frame.h18
-rw-r--r--src/asset.cc138
-rw-r--r--src/asset.h149
-rw-r--r--src/certificates.cc57
-rw-r--r--src/certificates.h31
-rw-r--r--src/colour_matrix.cc8
-rw-r--r--src/colour_matrix.h4
-rw-r--r--src/content.cc70
-rw-r--r--src/content.h83
-rw-r--r--src/cpl.cc331
-rw-r--r--src/cpl.h127
-rw-r--r--src/dcp.cc468
-rw-r--r--src/dcp.h101
-rw-r--r--src/dcp_time.cc36
-rw-r--r--src/dcp_time.h8
-rw-r--r--src/exceptions.cc14
-rw-r--r--src/exceptions.h52
-rw-r--r--src/file.cc46
-rw-r--r--src/file.h (renamed from src/rec709_linearised_gamma_lut.cc)45
-rw-r--r--src/font.cc (renamed from src/parse/subtitle.cc)84
-rw-r--r--src/font.h (renamed from src/parse/subtitle.h)65
-rw-r--r--src/gamma_lut.cc31
-rw-r--r--src/gamma_lut.h36
-rw-r--r--src/image.cc6
-rw-r--r--src/image.h4
-rw-r--r--src/kdm.cc58
-rw-r--r--src/kdm.h14
-rw-r--r--src/kdm_smpte_xml.h (renamed from src/xml/kdm_smpte.h)22
-rw-r--r--src/key.cc20
-rw-r--r--src/key.h9
-rw-r--r--src/load_font.cc (renamed from src/rec709_linearised_gamma_lut.h)18
-rw-r--r--src/load_font.h (renamed from src/srgb_linearised_gamma_lut.h)20
-rw-r--r--src/lut_cache.h26
-rw-r--r--src/metadata.cc16
-rw-r--r--src/metadata.h12
-rw-r--r--src/mono_picture_asset.cc200
-rw-r--r--src/mono_picture_asset.h64
-rw-r--r--src/mono_picture_frame.cc26
-rw-r--r--src/mono_picture_frame.h20
-rw-r--r--src/mono_picture_mxf.cc137
-rw-r--r--src/mono_picture_mxf.h62
-rw-r--r--src/mono_picture_mxf_writer.cc (renamed from src/mono_picture_asset_writer.cc)46
-rw-r--r--src/mono_picture_mxf_writer.h (renamed from src/mono_picture_asset_writer.h)31
-rw-r--r--src/mxf.cc (renamed from src/mxf_asset.cc)91
-rw-r--r--src/mxf.h (renamed from src/mxf_asset.h)81
-rw-r--r--src/mxf_writer.cc53
-rw-r--r--src/mxf_writer.h62
-rw-r--r--src/object.cc44
-rw-r--r--src/object.h (renamed from src/srgb_linearised_gamma_lut.cc)44
-rw-r--r--src/parse/asset_map.cc79
-rw-r--r--src/parse/asset_map.h81
-rw-r--r--src/parse/cpl.cc151
-rw-r--r--src/parse/cpl.h163
-rw-r--r--src/parse/pkl.cc52
-rw-r--r--src/picture_mxf.cc (renamed from src/picture_asset.cc)87
-rw-r--r--src/picture_mxf.h114
-rw-r--r--src/picture_mxf_writer.cc (renamed from src/picture_asset_writer.cc)25
-rw-r--r--src/picture_mxf_writer.h (renamed from src/picture_asset_writer.h)52
-rw-r--r--src/picture_mxf_writer_common.cc (renamed from src/picture_asset_writer_common.cc)17
-rw-r--r--src/reel.cc104
-rw-r--r--src/reel.h61
-rw-r--r--src/reel_asset.cc104
-rw-r--r--src/reel_asset.h113
-rw-r--r--src/reel_mono_picture_asset.cc54
-rw-r--r--src/reel_mono_picture_asset.h49
-rw-r--r--src/reel_picture_asset.cc91
-rw-r--r--src/reel_picture_asset.h59
-rw-r--r--src/reel_sound_asset.cc48
-rw-r--r--src/reel_sound_asset.h53
-rw-r--r--src/reel_stereo_picture_asset.cc67
-rw-r--r--src/reel_stereo_picture_asset.h51
-rw-r--r--src/reel_subtitle_asset.cc48
-rw-r--r--src/reel_subtitle_asset.h52
-rw-r--r--src/ref.h120
-rw-r--r--src/rgb_xyz.cc21
-rw-r--r--src/rgb_xyz.h10
-rw-r--r--src/signer.cc53
-rw-r--r--src/signer.h29
-rw-r--r--src/signer_chain.cc49
-rw-r--r--src/signer_chain.h8
-rw-r--r--src/sound_asset.cc401
-rw-r--r--src/sound_asset.h134
-rw-r--r--src/sound_frame.cc16
-rw-r--r--src/sound_frame.h20
-rw-r--r--src/sound_mxf.cc178
-rw-r--r--src/sound_mxf.h78
-rw-r--r--src/sound_mxf_writer.cc120
-rw-r--r--src/sound_mxf_writer.h55
-rw-r--r--src/stereo_picture_frame.cc20
-rw-r--r--src/stereo_picture_frame.h14
-rw-r--r--src/stereo_picture_mxf.cc (renamed from src/stereo_picture_asset.cc)125
-rw-r--r--src/stereo_picture_mxf.h (renamed from src/stereo_picture_asset.h)33
-rw-r--r--src/stereo_picture_mxf_writer.cc (renamed from src/stereo_picture_asset_writer.cc)54
-rw-r--r--src/stereo_picture_mxf_writer.h (renamed from src/stereo_picture_asset_writer.h)19
-rw-r--r--src/subtitle.cc60
-rw-r--r--src/subtitle.h (renamed from src/lut.h)62
-rw-r--r--src/subtitle_asset.h207
-rw-r--r--src/subtitle_content.cc (renamed from src/subtitle_asset.cc)275
-rw-r--r--src/subtitle_content.h113
-rw-r--r--src/subtitle_string.cc107
-rw-r--r--src/subtitle_string.h129
-rw-r--r--src/text.cc49
-rw-r--r--src/text.h (renamed from src/parse/pkl.h)56
-rw-r--r--src/types.cc54
-rw-r--r--src/types.h42
-rw-r--r--src/util.cc172
-rw-r--r--src/util.h39
-rw-r--r--src/version.h2
-rw-r--r--src/wscript79
-rw-r--r--src/xml.h6
-rw-r--r--src/xyz_frame.cc22
-rw-r--r--src/xyz_frame.h24
-rw-r--r--test/certificates_test.cc14
-rw-r--r--test/color_test.cc8
-rw-r--r--test/cpl_sar_test.cc (renamed from test/cpl_sar.cc)18
-rw-r--r--test/dcp_test.cc82
-rw-r--r--test/dcp_time_test.cc22
-rw-r--r--test/decryption_test.cc29
-rw-r--r--test/encryption_test.cc80
-rw-r--r--test/error_test.cc47
-rw-r--r--test/frame_info_test.cc9
-rw-r--r--test/kdm_key_test.cc2
-rw-r--r--test/kdm_test.cc8
-rw-r--r--test/lut_test.cc48
-rw-r--r--test/read_dcp_test.cc10
-rw-r--r--test/recovery_test.cc18
-rw-r--r--test/rewrite_subs.cc28
-rw-r--r--test/round_trip_test.cc71
-rw-r--r--test/subs_in_out.cc5
-rw-r--r--test/subtitle_tests.cc451
-rw-r--r--test/test.cc5
-rw-r--r--test/test.h2
-rw-r--r--test/utc_offset_to_string_test.cc12
-rw-r--r--test/util_test.cc69
-rw-r--r--test/wscript34
-rw-r--r--tools/dcpdiff.cc2
-rw-r--r--tools/dcpinfo.cc53
-rw-r--r--tools/wscript4
-rw-r--r--wscript130
148 files changed, 5498 insertions, 4375 deletions
diff --git a/Doxyfile b/Doxyfile
index 7e9dd59b..6c11ae97 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1,8 +1,10 @@
-# Doxyfile 1.8.1.2
+# Doxyfile 1.8.4
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
+# All text after a double hash (##) is considered a comment and is placed
+# in front of the TAG it is preceding .
# All text after a hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
@@ -70,9 +72,9 @@ CREATE_SUBDIRS = NO
# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian,
+# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic,
+# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
OUTPUT_LANGUAGE = English
@@ -126,7 +128,9 @@ FULL_PATH_NAMES = YES
# only done if one of the specified strings matches the left-hand part of
# the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the
-# path to strip.
+# path to strip. Note that you specify absolute paths here, but also
+# relative paths, which will be relative from the directory where doxygen is
+# started.
STRIP_FROM_PATH =
@@ -229,14 +233,15 @@ OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
-# parses. With this tag you can assign which parser to use for a given extension.
-# Doxygen has a built-in mapping, but you can override or extend it using this
-# tag. The format is ext=language, where ext is a file extension, and language
-# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
-# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
-# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
-# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
-# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension,
+# and language is one of the parsers supported by doxygen: IDL, Java,
+# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C,
+# C++. For instance to make doxygen treat .inc files as Fortran files (default
+# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note
+# that for custom extensions you also need to set FILE_PATTERNS otherwise the
+# files are not read by doxygen.
EXTENSION_MAPPING =
@@ -249,6 +254,13 @@ EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+
+AUTOLINK_SUPPORT = YES
+
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should
# set this tag to YES in order to let doxygen match functions declarations and
@@ -269,10 +281,10 @@ CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
-# For Microsoft's IDL there are propget and propput attributes to indicate getter
-# and setter methods for a property. Setting this option to YES (the default)
-# will make doxygen replace the get and set methods by a property in the
-# documentation. This will only work if the methods are indeed getting or
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES (the
+# default) will make doxygen replace the get and set methods by a property in
+# the documentation. This will only work if the methods are indeed getting or
# setting a simple type. If this is not the case, or you want to show the
# methods anyway, you should set this option to NO.
@@ -301,11 +313,11 @@ SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
-# unions with only public data fields will be shown inline in the documentation
-# of the scope in which they are defined (i.e. file, namespace, or group
-# documentation), provided this scope is documented. If set to NO (the default),
-# structs, classes, and unions are shown on a separate page (for HTML and Man
-# pages) or section (for LaTeX and RTF).
+# unions with only public data fields or simple typedef fields will be shown
+# inline in the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO (the default), structs, classes, and unions are shown on a separate
+# page (for HTML and Man pages) or section (for LaTeX and RTF).
INLINE_SIMPLE_STRUCTS = NO
@@ -319,30 +331,14 @@ INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
-# determine which symbols to keep in memory and which to flush to disk.
-# When the cache is full, less often used symbols will be written to disk.
-# For small to medium size projects (<1000 input files) the default value is
-# probably good enough. For larger projects a too small cache size can cause
-# doxygen to be busy swapping symbols to and from disk most of the time
-# causing a significant performance penalty.
-# If the system has enough physical memory increasing the cache will improve the
-# performance by keeping more symbols in memory. Note that the value works on
-# a logarithmic scale so increasing the size by one will roughly double the
-# memory usage. The cache size is given by this formula:
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
-
-SYMBOL_CACHE_SIZE = 0
-
-# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
-# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
-# their name and scope. Since this can be an expensive process and often the
-# same symbol appear multiple times in the code, doxygen keeps a cache of
-# pre-resolved symbols. If the cache is too small doxygen will become slower.
-# If the cache is too large, memory is wasted. The cache size is given by this
-# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
-# corresponding to a cache size of 2^16 = 65536 symbols.
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can
+# be an expensive process and often the same symbol appear multiple times in
+# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too
+# small doxygen will become slower. If the cache is too large, memory is wasted.
+# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid
+# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536
+# symbols.
LOOKUP_CACHE_SIZE = 0
@@ -353,16 +349,17 @@ LOOKUP_CACHE_SIZE = 0
# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
# documentation are documented, even if no documentation was available.
# Private class members and static file members will be hidden unless
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES
-EXTRACT_ALL = YES
+EXTRACT_ALL = NO
# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
# will be included in the documentation.
-EXTRACT_PRIVATE = NO
+EXTRACT_PRIVATE = YES
-# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation.
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
EXTRACT_PACKAGE = NO
@@ -533,7 +530,8 @@ GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional
-# documentation sections, marked by \if sectionname ... \endif.
+# documentation sections, marked by \if section-label ... \endif
+# and \cond section-label ... \endcond blocks.
ENABLED_SECTIONS =
@@ -591,7 +589,8 @@ LAYOUT_FILE =
# requires the bibtex tool to be installed. See also
# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
-# feature you need bibtex and perl available in the search path.
+# feature you need bibtex and perl available in the search path. Do not use
+# file names with spaces, bibtex cannot handle them.
CITE_BIB_FILES =
@@ -656,7 +655,7 @@ WARN_LOGFILE =
# with spaces.
INPUT = src \
- examples \
+ examples \
doc/mainpage.txt
# This tag can be used to specify the character encoding of the source files
@@ -745,8 +744,10 @@ IMAGE_PATH =
# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
# input file. Doxygen will then use the output that the filter program writes
# to standard output.
-# If FILTER_PATTERNS is specified, this tag will be
-# ignored.
+# If FILTER_PATTERNS is specified, this tag will be ignored.
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
INPUT_FILTER =
@@ -775,6 +776,13 @@ FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
+# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
@@ -896,17 +904,27 @@ HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to
-# fine-tune the look of the HTML output. If the tag is left blank doxygen
-# will generate a default style sheet. Note that doxygen will try to copy
-# the style sheet file to the HTML output directory, so don't put your own
-# style sheet in the HTML output directory as well, or it will be erased!
+# fine-tune the look of the HTML output. If left blank doxygen will
+# generate a default style sheet. Note that it is recommended to use
+# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
+# tag will in the future become obsolete.
HTML_STYLESHEET =
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
+# user-defined cascading style sheet that is included after the standard
+# style sheets created by doxygen. Using this option one can overrule
+# certain style aspects. This is preferred over using HTML_STYLESHEET
+# since it does not replace the standard style sheet and is therefor more
+# robust against future updates. Doxygen will copy the style sheet file to
+# the output directory.
+
+HTML_EXTRA_STYLESHEET =
+
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
-# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that
# the files will be copied as-is; there are no commands or markers available.
@@ -987,9 +1005,9 @@ DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
-# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
-# the documentation publisher. This should be a reverse domain-name style
-# string, e.g. com.mycompany.MyDocSet.documentation.
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely
+# identify the documentation publisher. This should be a reverse domain-name
+# style string, e.g. com.mycompany.MyDocSet.documentation.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
@@ -1174,6 +1192,13 @@ FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and
+# SVG. The default value is HTML-CSS, which is slower, but has the best
+# compatibility.
+
+MATHJAX_FORMAT = HTML-CSS
+
# When MathJax is enabled you need to specify the location relative to the
# HTML output directory using the MATHJAX_RELPATH option. The destination
# directory should contain the MathJax.js script. For instance, if the mathjax
@@ -1191,6 +1216,11 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript
+# pieces of code that will be used on startup of the MathJax code.
+
+MATHJAX_CODEFILE =
+
# When the SEARCHENGINE tag is enabled doxygen will generate a search box
# for the HTML output. The underlying search engine uses javascript
# and DHTML and should work on any modern browser. Note that when using
@@ -1202,15 +1232,55 @@ MATHJAX_EXTENSIONS =
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvantages are that it is more difficult to setup
-# and does not have live searching capabilities.
+# implemented using a web server instead of a web client using Javascript.
+# There are two flavours of web server based search depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools.
+# See the manual for details.
SERVER_BASED_SEARCH = NO
+# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain
+# the search results. Doxygen ships with an example indexer (doxyindexer) and
+# search engine (doxysearch.cgi) which are based on the open source search
+# engine library Xapian. See the manual for configuration details.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will returned the search results when EXTERNAL_SEARCH is enabled.
+# Doxygen ships with an example search engine (doxysearch) which is based on
+# the open source search engine library Xapian. See the manual for configuration
+# details.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id
+# of to a relative location where the documentation can be found.
+# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ...
+
+EXTRA_SEARCH_MAPPINGS =
+
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
@@ -1248,7 +1318,7 @@ COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used
# by the printer. Possible values are: a4, letter, legal and
-# executive. If left blank a4wide will be used.
+# executive. If left blank a4 will be used.
PAPER_TYPE = a4wide
@@ -1271,6 +1341,13 @@ LATEX_HEADER =
LATEX_FOOTER =
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images
+# or other source files which should be copied to the LaTeX output directory.
+# Note that the files will be copied as-is; there are no commands or markers
+# available.
+
+LATEX_EXTRA_FILES =
+
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
# is prepared for conversion to pdf (using ps2pdf). The pdf file will
# contain links (just like the HTML output) instead of page references
@@ -1416,6 +1493,21 @@ XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
+# configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files
+# that can be used to generate PDF.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it. If left blank docbook will be used as the default path.
+
+DOCBOOK_OUTPUT = docbook
+
+#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
@@ -1564,6 +1656,12 @@ ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed
+# in the related pages index. If set to NO, only the current project's
+# pages will be listed.
+
+EXTERNAL_PAGES = YES
+
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of `which perl').
@@ -1618,7 +1716,7 @@ DOT_NUM_THREADS = 0
# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
# directory containing the font.
-DOT_FONTNAME = FreeSans.ttf
+DOT_FONTNAME =
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
# The default size is 10pt.
@@ -1660,7 +1758,7 @@ UML_LOOK = NO
# the class node. If there are many fields or methods and many nodes the
# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS
# threshold limits the number of items for each type to make the size more
-# managable. Set this to 0 for no limit. Note that the threshold may be
+# manageable. Set this to 0 for no limit. Note that the threshold may be
# exceeded by 50% before the limit is enforced.
UML_LIMIT_NUM_FIELDS = 10
diff --git a/asdcplib/src/wscript b/asdcplib/src/wscript
index 661971ac..62f3a009 100644
--- a/asdcplib/src/wscript
+++ b/asdcplib/src/wscript
@@ -13,8 +13,8 @@ def build(bld):
else:
obj = bld(features = 'cxx cxxshlib')
- obj.name = 'libkumu-libdcp'
- obj.target = 'kumu-libdcp'
+ obj.name = 'libkumu-libdcp%s' % bld.env.API_VERSION
+ obj.target = 'kumu-libdcp%s' % bld.env.API_VERSION
obj.uselib = 'OPENSSL BOOST_FILESYSTEM'
obj.includes = ['.']
obj.export_includes = ['.']
@@ -32,10 +32,10 @@ def build(bld):
else:
obj = bld(features = 'cxx cxxshlib')
- obj.name = 'libasdcp-libdcp'
- obj.target = 'asdcp-libdcp'
+ obj.name = 'libasdcp-libdcp%s' % bld.env.API_VERSION
+ obj.target = 'asdcp-libdcp%s' % bld.env.API_VERSION
obj.uselib = 'OPENSSL'
- obj.use = 'libkumu-libdcp'
+ obj.use = 'libkumu-libdcp%s' % bld.env.API_VERSION
obj.includes = ['.']
obj.export_includes = ['.']
obj.source = """
@@ -67,5 +67,5 @@ def build(bld):
"""
if bld.env.STATIC:
- bld.install_files('${PREFIX}/lib', 'libkumu-libdcp.a')
- bld.install_files('${PREFIX}/lib', 'libasdcp-libdcp.a')
+ bld.install_files('${PREFIX}/lib', 'libkumu-libdcp%s.a' % bld.env.API_VERSION)
+ bld.install_files('${PREFIX}/lib', 'libasdcp-libdcp%s.a' % bld.env.API_VERSION)
diff --git a/doc/mainpage.txt b/doc/mainpage.txt
index b4cb21d5..6e2f3397 100644
--- a/doc/mainpage.txt
+++ b/doc/mainpage.txt
@@ -2,11 +2,13 @@
@mainpage libdcp
-libdcp is a library to create Digital Cinema Packages (DCPs) from JPEG2000 and WAV files, and also to
-read and process existing DCPs.
+libdcp is a library to create Digital Cinema Packages (DCPs) from
+video, audio and subtitle data, and also to read and process existing
+DCPs.
-Most of the hard work is done by a (slightly patched) version of asdcplib (http://www.cinecert.com/asdcplib/)
-which is included in the source distribution for libdcp.
+Most of the hard work is done by a (slightly patched) version of
+asdcplib (http://www.cinecert.com/asdcplib/) which is included in the
+source distribution for libdcp.
libdcp is distributed under the GNU GPL.
@@ -18,71 +20,7 @@ An example of DCP creation is given in examples/make_dcp.cc.
Reading existing DCPs
--
-libdcp can be used to read existing DCPs and examine their content. You might do
-
-@code
-#include <libdcp/dcp.h>
-using namespace std;
-
-libdcp::DCP dcp ("some-DCP-directory");
-@endcode
-
-libdcp will look at the XML files that make up the DCP and find its assets. You can then
-do things like
-
-@code
-boost::shared_ptr<Reel> reel = dcp.reels.front ();
-boost::shared_ptr<libdcp::PictureAsset> p = reel->main_picture ();
-boost::shared_ptr<libdcp::MonoPictureAsset> mp = boost::dynamic_pointer_cast<libdcp::MonoPictureAsset> (p);
-boost::shared_ptr<libdcp::ARGBFrame> f = mp->get_frame(42)->argb_frame ();
-uint8_t* data = f->data ();
-int size = f->size ();
-@endcode
-
-This will extract the image of frame 42 from the first reel of the DCP and make its ARGB data available
-for examination. We have to do a <code>dynamic_pointer_cast</code> from <code>libdcp::PictureAsset</code>
-to <code>libdcp::MonoPictureAsset</code>, as the picture asset may be either 2D (monoscopic) or 3D (stereoscopic).
-
-Audio data is accessed in chunks equal in length to the duration of a video frame. To
-get the audio that accompanies frame 66, you can do
-
-@code
-boost::shared_ptr<libdcp::SoundAsset> s = reel->main_sound ();
-cout << "Sound has " << s->channels() << " channels at " << s->sampling_rate() << "Hz\n";
-boost::shared_ptr<libdcp::SoundFrame> f = s->get_frame(66);
-uint8_t* data = f->data ();
-int size = f->size ();
-@endcode
-
-The returned data are interleaved 24-bit samples, so that
-
-@code
-int left = data[0] | (data[1] << 8) | (data[2] << 16);
-data += 3;
-int right = data[0] | (data[1] << 8) | (data[2] << 16);
-data += 3;
-int centre = data[0] | (data[1] << 8) | (data[2] << 16);
-data += 3;
-int lfe = data[0] | (data[1] << 8) | (data[2] << 16);
-data += 3;
-int ls = data[0] | (data[1] << 8) | (data[2] << 16);
-data += 3;
-int rs = data[0] | (data[1] << 8) | (data[2] << 16);
-data += 3;
-@endcode
-
-would obtain the first sample from each of the 6 channels for that frame.
-
-Subtitles can be read using code like
-
-@code
-boost::shared_ptr<SubtitleAsset> s = dcp.subtitle_asset ();
-list<boost::shared_ptr<libdcp::Text> > texts = s->subtitles_at (libdcp::Time (0, 3, 2, 5));
-@endcode
-
-This returns the subtitles that should be shown at 3 minutes, 2
-seconds, 5 ticks (where 1 tick is 4ms) into the DCP.
-
+An example of DCP reading is given in examples/read_dcp.cc.
*/
diff --git a/examples/make_dcp.cc b/examples/make_dcp.cc
index 6aa4268b..d86cd30a 100644
--- a/examples/make_dcp.cc
+++ b/examples/make_dcp.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,7 +18,7 @@
*/
/** @file examples/make_dcp.cc
- * @brief Shows how to make a DCP from some JPEG2000 and WAV files.
+ * @brief Shows how to make a DCP from some JPEG2000 and audio data.
*/
#include <vector>
@@ -33,94 +33,80 @@
#include "dcp.h"
#include "cpl.h"
-#include "mono_picture_asset.h"
-#include "sound_asset.h"
+#include "mono_picture_mxf.h"
+#include "mono_picture_mxf_writer.h"
+#include "sound_mxf.h"
+#include "sound_mxf_writer.h"
#include "reel.h"
-
-/* This method returns the filename of the JPEG2000 file to use for a given frame.
- In this example, we are using the same file for each frame, so we don't bother
- looking at the frame parameter, but it will called with frame=0, frame=1, ...
-*/
-std::string
-video_frame (int /* frame */)
-{
- return "examples/help.j2c";
-}
+#include "file.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_sound_asset.h"
int
main ()
{
- /* Make a DCP object. "My Film DCP" is the directory name for the DCP */
- libdcp::DCP dcp ("My Film DCP");
+ /* Create a directory to put the DCP in */
+ boost::filesystem::create_directory ("DCP");
- /* Now make a CPL object.
-
- "My Film" is the title that will be shown on the projector / TMS when the DCP is ingested.
- FEATURE is the type that the projector will list the DCP as.
- 24 is the frame rate, and the DCP will be 48 frames long (ie 2 seconds at 24 fps).
- */
- boost::shared_ptr<libdcp::CPL> cpl (new libdcp::CPL ("My Film DCP", "My Film", libdcp::FEATURE, 24, 48));
-
- /* And add the CPL to the DCP */
- dcp.add_cpl (cpl);
-
- /* Now make a `picture asset'. This is a collection of the JPEG2000 files that make up the picture; one per frame.
- First, create the object.
+ /* Make a picture MXF. This is a file which combines JPEG2000 files together to make
+ up the video of the DCP. First, create the object, specifying a frame rate of 24 frames
+ per second.
*/
- boost::shared_ptr<libdcp::MonoPictureAsset> picture_asset (
- new libdcp::MonoPictureAsset ("My Film DCP", "video.mxf")
- );
+ boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
- /* Now set up its parameters; we have the frame rate, the
- number of frames and the resolution of the frames;
- 1998x1080 is the DCI Flat specification for 2K projectors.
- */
-
- picture_asset->set_edit_rate (24);
- picture_asset->set_intrinsic_duration (24);
- picture_asset->set_size (libdcp::Size (1998, 1080));
-
- /* Now we can create the asset itself. Here using a function (video_frame) to obtain the name of the JPEG2000 file for each frame.
- The result will be an MXF file written to the directory "My Film DCP" (which should be the same as the DCP's
- directory above) called "video.mxf".
- */
+ /* Start off a write to it */
+ boost::shared_ptr<dcp::PictureMXFWriter> picture_writer = picture_mxf->start_write ("DCP/picture.mxf", dcp::SMPTE, false);
- picture_asset->create (video_frame);
+ /* Write 24 frames of the same JPEG2000 file */
+ dcp::File picture ("examples/help.j2c");
+ for (int i = 0; i < 24; ++i) {
+ picture_writer->write (picture.data(), picture.size());
+ }
- /* Now we will create a `sound asset', which is made up of a WAV file for each channel of audio. Here we're using
- stereo, so we add two WAV files to a vector.
+ /* And finish off */
+ picture_writer->finalize ();
- We could add more files here to use more channels; the file order is:
- Left
- Right
- Centre
- LFE (sub)
- Left surround
- Right surround
+ /* Now create a sound MXF. As before, create an object and a writer.
+ When creating the object we specify the sampling rate (48kHz) and the number of channels (2).
*/
- std::vector<boost::filesystem::path> sound_files;
- sound_files.push_back ("examples/sine_440_-12dB.wav");
- sound_files.push_back ("examples/sine_880_-12dB.wav");
-
- /* Now we can create the sound asset using these files */
- boost::shared_ptr<libdcp::SoundAsset> sound_asset (new libdcp::SoundAsset ("My Film DCP", "audio.mxf"));
- sound_asset->set_edit_rate (24);
- sound_asset->set_intrinsic_duration (48);
- sound_asset->create (sound_files);
-
- /* Now that we have the assets, we can create a Reel to put them in and add it to the CPL */
- cpl->add_reel (
- boost::shared_ptr<libdcp::Reel> (
- new libdcp::Reel (picture_asset, sound_asset, boost::shared_ptr<libdcp::SubtitleAsset> ())
- )
- );
-
- /* Finally, we call this to write the XML description files to the DCP. After this, the DCP
- is ready to ingest and play.
+ boost::shared_ptr<dcp::SoundMXF> sound_mxf (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 2));
+ boost::shared_ptr<dcp::SoundMXFWriter> sound_writer = sound_mxf->start_write ("DCP/sound.mxf", dcp::SMPTE);
+
+ /* Write some sine waves */
+ float* audio[2];
+ audio[0] = new float[48000];
+ audio[1] = new float[48000];
+ for (int i = 0; i < 48000; ++i) {
+ audio[0][i] = sin (2 * M_PI * i * 440 / 48000) * 0.25;
+ audio[1][i] = sin (2 * M_PI * i * 880 / 48000) * 0.25;
+ }
+ sound_writer->write (audio, 48000);
+
+ /* And tidy up */
+ delete[] audio[0];
+ delete[] audio[1];
+ sound_writer->finalize ();
+
+ /* Now create a reel */
+ boost::shared_ptr<dcp::Reel> reel (new dcp::Reel ());
+
+ /* Add picture and sound to it. The zeros are the `entry points', i.e. the first
+ (video) frame from the MXFs that the reel should play.
*/
- libdcp::XMLMetadata metadata;
- dcp.write_xml (false, metadata);
-
+ reel->add (boost::shared_ptr<dcp::ReelPictureAsset> (new dcp::ReelMonoPictureAsset (picture_mxf, 0)));
+ reel->add (boost::shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (sound_mxf, 0)));
+
+ /* Make a CPL with this reel */
+ boost::shared_ptr<dcp::CPL> cpl (new dcp::CPL ("My film", dcp::FEATURE));
+ cpl->add (reel);
+
+ /* Write the DCP */
+ dcp::DCP dcp ("DCP");
+ dcp.add (cpl);
+ dcp.add (picture_mxf);
+ dcp.add (sound_mxf);
+ dcp.write_xml (dcp::SMPTE);
+
return 0;
}
diff --git a/examples/read_dcp.cc b/examples/read_dcp.cc
new file mode 100644
index 00000000..f3c47a3c
--- /dev/null
+++ b/examples/read_dcp.cc
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/* If you are using an installed libdcp, these #includes would need to be changed to
+#include <libdcp/dcp.h>
+#include <libdcp/picture_mxf.h>
+... etc. ...
+*/
+
+#include "dcp.h"
+#include "cpl.h"
+#include "reel.h"
+#include "reel_picture_asset.h"
+#include "mono_picture_frame.h"
+#include "mono_picture_mxf.h"
+#include "stereo_picture_mxf.h"
+#include "sound_mxf.h"
+#include "subtitle_content.h"
+#include "argb_frame.h"
+#include <Magick++.h>
+
+/** @file examples/read_dcp.cc
+ * @brief Shows how to read a DCP.
+ */
+
+int
+main ()
+{
+ /* Create a DCP, specifying where our existing data is */
+ dcp::DCP dcp ("/home/carl/diagonal.com/APPASSIONATA_TLR_F_UK-DEFR_CH_51_2K_LOK_20121115_DGL_OV");
+ /* Read the DCP to find out about it */
+ dcp.read ();
+
+ if (dcp.encrypted ()) {
+ std::cout << "DCP is encrypted.\n";
+ } else {
+ std::cout << "DCP is not encrypted.\n";
+ }
+
+ std::cout << "DCP has " << dcp.cpls().size() << " CPLs.\n";
+ std::list<boost::shared_ptr<dcp::Asset> > assets = dcp.assets ();
+ std::cout << "DCP has " << assets.size() << " assets.\n";
+ for (std::list<boost::shared_ptr<dcp::Asset> >::const_iterator i = assets.begin(); i != assets.end(); ++i) {
+ if (boost::dynamic_pointer_cast<dcp::MonoPictureMXF> (*i)) {
+ std::cout << "2D picture\n";
+ } else if (boost::dynamic_pointer_cast<dcp::StereoPictureMXF> (*i)) {
+ std::cout << "3D picture\n";
+ } else if (boost::dynamic_pointer_cast<dcp::SoundMXF> (*i)) {
+ std::cout << "Sound\n";
+ } else if (boost::dynamic_pointer_cast<dcp::SubtitleContent> (*i)) {
+ std::cout << "Subtitle\n";
+ } else if (boost::dynamic_pointer_cast<dcp::CPL> (*i)) {
+ std::cout << "CPL\n";
+ }
+ std::cout << "\t" << (*i)->file().leaf().string() << "\n";
+ }
+
+ /* Take the first CPL */
+ boost::shared_ptr<dcp::CPL> cpl = dcp.cpls().front ();
+
+ /* Get the MXF of the picture asset in the first reel */
+ boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf = boost::dynamic_pointer_cast<dcp::MonoPictureMXF> (cpl->reels().front()->main_picture()->mxf ());
+
+ /* Get the 1000th frame of it */
+ boost::shared_ptr<const dcp::MonoPictureFrame> picture_frame_j2k = picture_mxf->get_frame(999);
+
+ /* Get a ARGB copy of it */
+ boost::shared_ptr<dcp::ARGBFrame> picture_frame_rgb = picture_frame_j2k->argb_frame ();
+
+ Magick::Image image (picture_frame_rgb->size().width, picture_frame_rgb->size().height, "BGRA", Magick::CharPixel, picture_frame_rgb->data ());
+ image.write ("frame.png");
+
+ return 0;
+}
diff --git a/examples/wscript b/examples/wscript
index 05cca98f..abb0885c 100644
--- a/examples/wscript
+++ b/examples/wscript
@@ -1,8 +1,16 @@
def build(bld):
obj = bld(features = 'cxx cxxprogram')
- obj.name = 'examples'
- obj.use = 'libdcp'
+ obj.name = 'make_dcp'
+ obj.use = 'libdcp%s' % bld.env.API_VERSION
obj.uselib = 'OPENJPEG CXML'
obj.source = 'make_dcp.cc'
obj.target = 'make_dcp'
obj.install_path = ''
+
+ obj = bld(features = 'cxx cxxprogram')
+ obj.name = 'read_dcp'
+ obj.use = 'libdcp%s' % bld.env.API_VERSION
+ obj.uselib = 'OPENJPEG CXML MAGICK'
+ obj.source = 'read_dcp.cc'
+ obj.target = 'read_dcp'
+ obj.install_path = ''
diff --git a/libdcp.pc.in b/libdcp-1.0.pc.in
index 0f3239b7..0f3239b7 100644
--- a/libdcp.pc.in
+++ b/libdcp-1.0.pc.in
diff --git a/run/examples/read_dcp b/run/examples/read_dcp
new file mode 100755
index 00000000..92f25b21
--- /dev/null
+++ b/run/examples/read_dcp
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+export LD_LIBRARY_PATH=build/src
+if [ "$1" == "--debug" ]; then
+ shift
+ gdb --args build/examples/read_dcp "$@"
+elif [ "$1" == "--valgrind" ]; then
+ shift
+ valgrind --tool="memcheck" --leak-check=full --show-reachable=yes build/examples/read_dcp "$@"
+else
+ build/examples/read_dcp "$@"
+fi
diff --git a/src/argb_frame.cc b/src/argb_frame.cc
index a48f80bb..99d6c814 100644
--- a/src/argb_frame.cc
+++ b/src/argb_frame.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,9 +17,13 @@
*/
+/** @file src/argb_frame.cc
+ * @brief ARGBFrame class.
+ */
+
#include "argb_frame.h"
-using namespace libdcp;
+using namespace dcp;
/** Construct an empty ARGBFrame of a given size and with
* undefined contents.
diff --git a/src/argb_frame.h b/src/argb_frame.h
index f26436cd..419227bb 100644
--- a/src/argb_frame.h
+++ b/src/argb_frame.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,13 +18,13 @@
*/
/** @file src/argb_frame.h
- * @brief Container for a single image from a picture asset.
+ * @brief ARGBFrame class.
*/
-#include <stdint.h>
#include "util.h"
+#include <stdint.h>
-namespace libdcp
+namespace dcp
{
/** @class ARGBFrame
@@ -42,26 +42,28 @@ namespace libdcp
*
* Lines are packed so that the second row directly follows the first.
*/
-class ARGBFrame
+class ARGBFrame : boost::noncopyable
{
public:
ARGBFrame (Size size);
~ARGBFrame ();
+ /** @return pointer to the image data */
uint8_t* data () const {
return _data;
}
- /** Length of one picture row in bytes */
+ /** @return length of one picture row in bytes */
int stride () const;
+ /** @return size of the picture in pixels */
Size size () const {
return _size;
}
private:
- Size _size;
- uint8_t* _data;
+ Size _size; ///< frame size in pixels
+ uint8_t* _data; ///< pointer to image data
};
}
diff --git a/src/asset.cc b/src/asset.cc
index 4ad29dde..aaa79dc7 100644
--- a/src/asset.cc
+++ b/src/asset.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,112 +18,106 @@
*/
/** @file src/asset.cc
- * @brief Parent class for assets of DCPs.
+ * @brief Asset class.
*/
-#include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/function.hpp>
-#include <libxml++/nodes/element.h>
-#include "AS_DCP.h"
-#include "KM_util.h"
#include "asset.h"
#include "util.h"
-#include "metadata.h"
+#include "exceptions.h"
#include "compose.hpp"
+#include <libxml++/libxml++.h>
+#include <boost/lexical_cast.hpp>
using std::string;
-using boost::shared_ptr;
using boost::lexical_cast;
-using namespace libdcp;
-
-Asset::Asset (boost::filesystem::path directory, boost::filesystem::path file_name)
- : _directory (directory)
- , _file_name (file_name)
- , _uuid (make_uuid ())
- , _edit_rate (0)
- , _entry_point (0)
- , _intrinsic_duration (0)
- , _duration (0)
+using boost::function;
+using boost::optional;
+using namespace dcp;
+
+/** Create an Asset with a randomly-generated ID */
+Asset::Asset ()
{
- if (_file_name.empty ()) {
- _file_name = _uuid + ".xml";
- }
+
+}
+
+/** Create an Asset from a given file. The ID will
+ * be extracted from the file.
+ * @param file File name.
+ */
+Asset::Asset (boost::filesystem::path file)
+ : _file (file)
+{
+
+}
+
+/** Create an Asset with a specified ID.
+ * @param id ID to use.
+ */
+Asset::Asset (string id)
+ : Object (id)
+{
+
}
void
-Asset::write_to_pkl (xmlpp::Node* node, bool interop) const
+Asset::write_to_pkl (xmlpp::Node* node, Standard standard) const
{
+ assert (!_file.empty ());
+
xmlpp::Node* asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid);
- asset->add_child("AnnotationText")->add_child_text (_file_name.string ());
- asset->add_child("Hash")->add_child_text (digest ());
- asset->add_child("Size")->add_child_text (lexical_cast<string> (boost::filesystem::file_size(path())));
- if (interop) {
- asset->add_child("Type")->add_child_text (String::compose ("application/x-smpte-mxf;asdcpKind=%1", asdcp_kind ()));
- } else {
- asset->add_child("Type")->add_child_text ("application/mxf");
- }
+ asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ asset->add_child("AnnotationText")->add_child_text (_id);
+ asset->add_child("Hash")->add_child_text (hash ());
+ asset->add_child("Size")->add_child_text (lexical_cast<string> (boost::filesystem::file_size (_file)));
+ asset->add_child("Type")->add_child_text (pkl_type (standard));
}
void
-Asset::write_to_assetmap (xmlpp::Node* node) const
+Asset::write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const
{
+ assert (!_file.empty ());
+
xmlpp::Node* asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid);
+ asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
xmlpp::Node* chunk_list = asset->add_child ("ChunkList");
xmlpp::Node* chunk = chunk_list->add_child ("Chunk");
- chunk->add_child("Path")->add_child_text (_file_name.string ());
+ optional<boost::filesystem::path> path = relative_to_root (root, _file);
+ if (!path) {
+ throw MiscError (String::compose ("Asset %1 is not within the directory %2", _file, root));
+ }
+ chunk->add_child("Path")->add_child_text (path.get().string ());
chunk->add_child("VolumeIndex")->add_child_text ("1");
chunk->add_child("Offset")->add_child_text ("0");
- chunk->add_child("Length")->add_child_text (lexical_cast<string> (boost::filesystem::file_size(path())));
-}
-
-boost::filesystem::path
-Asset::path () const
-{
- boost::filesystem::path p;
- p /= _directory;
- p /= _file_name;
- return p;
+ chunk->add_child("Length")->add_child_text (lexical_cast<string> (boost::filesystem::file_size (_file)));
}
string
-Asset::digest () const
-{
- if (_digest.empty ()) {
- _digest = make_digest (path().string(), 0);
- }
-
- return _digest;
-}
-
-void
-Asset::compute_digest (boost::function<void (float)> progress)
+Asset::hash (function<void (float)> progress) const
{
- if (!_digest.empty ()) {
- return;
+ assert (!_file.empty ());
+
+ if (_hash.empty ()) {
+ _hash = make_digest (_file, progress);
}
- _digest = make_digest (path().string(), &progress);
+ return _hash;
}
bool
-Asset::equals (shared_ptr<const Asset> other, EqualityOptions, boost::function<void (NoteType, string)> note) const
+Asset::equals (boost::shared_ptr<const Asset> other, EqualityOptions, function<void (NoteType, string)> note) const
{
- if (_edit_rate != other->_edit_rate) {
- note (ERROR, "asset edit rates differ");
+ if (_hash != other->_hash) {
+ note (ERROR, "Asset hashes differ");
return false;
}
-
- if (_intrinsic_duration != other->_intrinsic_duration) {
- note (ERROR, "asset intrinsic durations differ");
- }
-
- if (_duration != other->_duration) {
- note (ERROR, "asset durations differ");
- }
return true;
}
+
+void
+Asset::set_file (boost::filesystem::path file) const
+{
+ _file = boost::filesystem::absolute (file);
+ _hash.clear ();
+}
+
diff --git a/src/asset.h b/src/asset.h
index 6db8e5c2..bad982f1 100644
--- a/src/asset.h
+++ b/src/asset.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,141 +18,70 @@
*/
/** @file src/asset.h
- * @brief Parent class for assets of DCPs.
- */
+ * @brief Asset class.
+ */
#ifndef LIBDCP_ASSET_H
#define LIBDCP_ASSET_H
-#include <string>
-#include <list>
+#include "object.h"
+#include "types.h"
#include <boost/filesystem.hpp>
#include <boost/function.hpp>
-#include <libxml++/libxml++.h>
-#include "types.h"
-
-namespace ASDCP {
- struct WriterInfo;
-}
+#include <boost/bind.hpp>
namespace xmlpp {
- class Element;
+ class Node;
}
-namespace libdcp
-{
+namespace dcp {
-/** @brief Parent class for assets of DCPs
+/** @class Asset
+ * @brief Parent class for DCP assets, i.e. picture/sound/subtitles and CPLs.
*
- * These are collections of pictures or sound.
+ * Note that this class is not used for ReelAssets; those are just for the metadata
+ * that gets put into &lt;Reel&gt;s.
*/
-class Asset
+class Asset : public Object
{
public:
- /** Construct an Asset.
- * @param directory Directory where our XML or MXF file is.
- * @param file_name Name of our file within directory, or empty to make one up based on UUID.
+ Asset ();
+ Asset (boost::filesystem::path file);
+ Asset (std::string id);
+
+ virtual bool equals (
+ boost::shared_ptr<const Asset> other,
+ EqualityOptions opt,
+ boost::function<void (NoteType, std::string)> note
+ ) const;
+
+ /** Write details of the asset to a ASSETMAP.
+ * @param node Parent node.
*/
- Asset (boost::filesystem::path directory, boost::filesystem::path file_name = "");
-
- virtual ~Asset() {}
-
- /** Write details of the asset to a CPL AssetList node.
- * @param p Parent element.
- */
- virtual void write_to_cpl (xmlpp::Element* p) const = 0;
+ void write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const;
/** Write details of the asset to a PKL AssetList node.
- * @param p Parent node.
- */
- void write_to_pkl (xmlpp::Node *, bool interop) const;
-
- /** Write details of the asset to a ASSETMAP stream.
- * @param s Stream.
+ * @param node Parent node.
+ * @param standard Standard to use.
*/
- void write_to_assetmap (xmlpp::Node *) const;
-
- /** Compute the digest for this asset. Calling this is optional: if
- * it is not called, the digest will be computed when required. However,
- * calling this method allows the caller to see the progress of the
- * computation, which can be long for large assets.
- * @param Called with progress between 0 and 1.
- */
- void compute_digest (boost::function<void (float)> progress);
-
- std::string uuid () const {
- return _uuid;
- }
+ void write_to_pkl (xmlpp::Node* node, Standard standard) const;
- boost::filesystem::path path () const;
-
- void set_directory (boost::filesystem::path d) {
- _directory = d;
- }
-
- void set_file_name (boost::filesystem::path f) {
- _file_name = f;
- }
-
- int entry_point () const {
- return _entry_point;
+ boost::filesystem::path file () const {
+ return _file;
}
- int duration () const {
- return _duration;
- }
-
- int intrinsic_duration () const {
- return _intrinsic_duration;
- }
-
- int edit_rate () const {
- return _edit_rate;
- }
-
- void set_entry_point (int e) {
- _entry_point = e;
- }
-
- void set_duration (int d) {
- _duration = d;
- }
-
- void set_intrinsic_duration (int d) {
- _intrinsic_duration = d;
- }
-
- void set_edit_rate (int r) {
- _edit_rate = r;
- }
+ void set_file (boost::filesystem::path file) const;
- virtual bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)>) const;
+ /** @return the hash of this asset's file */
+ std::string hash (boost::function<void (float)> progress = 0) const;
protected:
+ virtual std::string pkl_type (Standard standard) const = 0;
- /** @return Interop PKL asdcpKind for the &lt;Type&gt; tag e.g. Picture, Sound etc. */
- virtual std::string asdcp_kind () const = 0;
-
- std::string digest () const;
-
- /** Directory that our MXF or XML file is in */
- boost::filesystem::path _directory;
- /** Name of our MXF or XML file */
- boost::filesystem::path _file_name;
- /** Our UUID */
- std::string _uuid;
- /** The edit rate; this is normally equal to the number of video frames per second */
- int _edit_rate;
- /** Start point to present in frames */
- int _entry_point;
- /** Total length in frames */
- int _intrinsic_duration;
- /** Length to present in frames */
- int _duration;
-
-private:
- /** Digest of our MXF or XML file */
- mutable std::string _digest;
+ /** The disk file that represents this asset, if one exists */
+ mutable boost::filesystem::path _file;
+ /** Hash of _file, or empty if the hash has not yet been computed */
+ mutable std::string _hash;
};
}
diff --git a/src/certificates.cc b/src/certificates.cc
index 2f5d47fd..0a0393c6 100644
--- a/src/certificates.cc
+++ b/src/certificates.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,27 +17,27 @@
*/
-#include <sstream>
-#include <vector>
-#include <cerrno>
-#include <boost/algorithm/string.hpp>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-#include <openssl/asn1.h>
-#include <openssl/err.h>
-#include <libxml++/nodes/element.h>
+/** @file src/certificates.cc
+ * @brief Certificate and CertificateChain classes.
+ */
+
#include "KM_util.h"
#include "certificates.h"
#include "compose.hpp"
#include "exceptions.h"
#include "util.h"
+#include <libxml++/nodes/element.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <boost/algorithm/string.hpp>
+#include <cerrno>
using std::list;
using std::string;
-using std::stringstream;
-using std::vector;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
/** @param c X509 certificate, which this object will take ownership of */
Certificate::Certificate (X509* c)
@@ -47,6 +47,9 @@ Certificate::Certificate (X509* c)
}
+/** Load an X509 certificate from a file.
+ * @param filename File to load.
+ */
Certificate::Certificate (boost::filesystem::path filename)
: _certificate (0)
, _public_key (0)
@@ -61,6 +64,9 @@ Certificate::Certificate (boost::filesystem::path filename)
}
}
+/** Load an X509 certificate from a string.
+ * @param cert String to read from.
+ */
Certificate::Certificate (string cert)
: _certificate (0)
, _public_key (0)
@@ -68,6 +74,9 @@ Certificate::Certificate (string cert)
read_string (cert);
}
+/** Copy constructor.
+ * @param other Certificate to copy.
+ */
Certificate::Certificate (Certificate const & other)
: _certificate (0)
, _public_key (0)
@@ -75,6 +84,9 @@ Certificate::Certificate (Certificate const & other)
read_string (other.certificate (true));
}
+/** Read a certificate from a string.
+ * @param cert String to read.
+ */
void
Certificate::read_string (string cert)
{
@@ -91,12 +103,16 @@ Certificate::read_string (string cert)
BIO_free (bio);
}
+/** Destructor */
Certificate::~Certificate ()
{
X509_free (_certificate);
RSA_free (_public_key);
}
+/** operator= for Certificate.
+ * @param other Certificate to read from.
+ */
Certificate &
Certificate::operator= (Certificate const & other)
{
@@ -114,6 +130,10 @@ Certificate::operator= (Certificate const & other)
return *this;
}
+/** Return the certificate as a string.
+ * @param with_begin_end true to include the -----BEGIN CERTIFICATE--- / -----END CERTIFICATE----- markers.
+ * @return Certificate string.
+ */
string
Certificate::certificate (bool with_begin_end) const
{
@@ -143,6 +163,10 @@ Certificate::certificate (bool with_begin_end) const
return s;
}
+/** @return Certificate's issuer, in the form
+ * dnqualifier=&lt;dnQualififer&gt;,CN=&lt;commonName&gt;,OU=&lt;organizationalUnitName&gt,O=&lt;organizationName&gt;
+ * and with + signs escaped to \+
+ */
string
Certificate::issuer () const
{
@@ -244,6 +268,7 @@ Certificate::thumbprint () const
return Kumu::base64encode (digest, 20, digest_base64, 64);
}
+/** @return RSA public key from this Certificate. Caller must not free the returned value. */
RSA *
Certificate::public_key () const
{
@@ -266,6 +291,7 @@ Certificate::public_key () const
return _public_key;
}
+/** @return Root certificate */
shared_ptr<Certificate>
CertificateChain::root () const
{
@@ -273,6 +299,7 @@ CertificateChain::root () const
return _certificates.front ();
}
+/** @return Leaf certificate */
shared_ptr<Certificate>
CertificateChain::leaf () const
{
@@ -280,6 +307,7 @@ CertificateChain::leaf () const
return _certificates.back ();
}
+/** @return Certificates in order from leaf to root */
list<shared_ptr<Certificate> >
CertificateChain::leaf_to_root () const
{
@@ -288,6 +316,9 @@ CertificateChain::leaf_to_root () const
return c;
}
+/** Add a certificate to the end of the chain.
+ * @param c Certificate to add.
+ */
void
CertificateChain::add (shared_ptr<Certificate> c)
{
diff --git a/src/certificates.h b/src/certificates.h
index 2bf8d0db..96a8cbb7 100644
--- a/src/certificates.h
+++ b/src/certificates.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,16 +17,19 @@
*/
+/** @file src/certificates.h
+ * @brief Certificate and CertificateChain classes.
+ */
+
#ifndef LIBDCP_CERTIFICATES_H
#define LIBDCP_CERTIFICATES_H
-#include <string>
-#include <list>
-#include <boost/noncopyable.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/filesystem.hpp>
#undef X509_NAME
#include <openssl/x509.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+#include <list>
class certificates;
@@ -34,8 +37,13 @@ namespace xmlpp {
class Element;
}
-namespace libdcp {
+namespace dcp {
+/** @class Certificate
+ * @brief A wrapper for an X509 certificate.
+ *
+ * This class can take a Certificate from a file, a string or an OpenSSL X509 object.
+ */
class Certificate
{
public:
@@ -51,16 +59,12 @@ public:
Certificate& operator= (Certificate const &);
- /** @param with_begin_end true to include BEGIN CERTIFICATE / END CERTIFICATE markers
- * @return the whole certificate as a string.
- */
std::string certificate (bool with_begin_end = false) const;
std::string issuer () const;
std::string serial () const;
std::string subject () const;
std::string common_name () const;
- /** @return RSA public key from this Certificate. Caller must not free the returned value. */
RSA* public_key () const;
std::string thumbprint () const;
@@ -76,12 +80,15 @@ private:
mutable RSA* _public_key;
};
+/** @class CertificateChain
+ * @brief A chain of any number of certificates, from root to leaf.
+ */
class CertificateChain
{
public:
CertificateChain () {}
- void add (boost::shared_ptr<Certificate>);
+ void add (boost::shared_ptr<Certificate> c);
boost::shared_ptr<Certificate> root () const;
boost::shared_ptr<Certificate> leaf () const;
diff --git a/src/colour_matrix.cc b/src/colour_matrix.cc
index b633e384..72f952c3 100644
--- a/src/colour_matrix.cc
+++ b/src/colour_matrix.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -23,19 +23,19 @@
EasyDCP player, I think.
*/
-double const libdcp::colour_matrix::xyz_to_rgb[3][3] = {
+double const dcp::colour_matrix::xyz_to_rgb[3][3] = {
{ 3.24096989631653, -1.5373831987381, -0.498610764741898 },
{ -0.96924364566803, 1.87596750259399, 0.0415550582110882 },
{ 0.0556300804018974, -0.203976958990097, 1.05697154998779 }
};
-double const libdcp::colour_matrix::srgb_to_xyz[3][3] = {
+double const dcp::colour_matrix::srgb_to_xyz[3][3] = {
{0.4124564, 0.3575761, 0.1804375},
{0.2126729, 0.7151522, 0.0721750},
{0.0193339, 0.1191920, 0.9503041}
};
-double const libdcp::colour_matrix::rec709_to_xyz[3][3] = {
+double const dcp::colour_matrix::rec709_to_xyz[3][3] = {
{ 0.412390799265959, 0.357584339383878, 0.180480788401834 },
{ 0.21263900587151, 0.715168678767756, 0.0721923153607337 },
{ 0.0193308187155918, 0.119194779794626, 0.950532152249661 }
diff --git a/src/colour_matrix.h b/src/colour_matrix.h
index 615e8b38..ce15051c 100644
--- a/src/colour_matrix.h
+++ b/src/colour_matrix.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,7 +17,7 @@
*/
-namespace libdcp {
+namespace dcp {
namespace colour_matrix {
diff --git a/src/content.cc b/src/content.cc
new file mode 100644
index 00000000..50db005a
--- /dev/null
+++ b/src/content.cc
@@ -0,0 +1,70 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "content.h"
+#include "util.h"
+#include "metadata.h"
+#include "AS_DCP.h"
+#include "KM_util.h"
+#include <libxml++/nodes/element.h>
+#include <boost/filesystem.hpp>
+#include <boost/function.hpp>
+#include <iostream>
+
+/* We need this here for the #undef ERROR for Windows */
+#include "types.h"
+
+using namespace std;
+using namespace boost;
+using namespace dcp;
+
+Content::Content (boost::filesystem::path file)
+ : Asset (file)
+ , _edit_rate (24, 1)
+ , _intrinsic_duration (0)
+{
+
+}
+
+Content::Content (Fraction edit_rate)
+ : _edit_rate (edit_rate)
+ , _intrinsic_duration (0)
+{
+
+}
+
+bool
+Content::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
+{
+ if (!Asset::equals (other, opt, note)) {
+ return false;
+ }
+
+ if (_edit_rate != other->_edit_rate) {
+ note (ERROR, "content edit rates differ");
+ return false;
+ }
+
+ if (_intrinsic_duration != other->_intrinsic_duration) {
+ note (ERROR, "asset intrinsic durations differ");
+ return false;
+ }
+
+ return true;
+}
diff --git a/src/content.h b/src/content.h
new file mode 100644
index 00000000..2059c8f5
--- /dev/null
+++ b/src/content.h
@@ -0,0 +1,83 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/content.h
+ * @brief Content class.
+ */
+
+#ifndef LIBDCP_CONTENT_H
+#define LIBDCP_CONTENT_H
+
+#include "types.h"
+#include "asset.h"
+#include <libxml++/libxml++.h>
+#include <boost/filesystem.hpp>
+#include <boost/function.hpp>
+#include <string>
+#include <list>
+
+namespace ASDCP {
+ class WriterInfo;
+}
+
+namespace xmlpp {
+ class Element;
+}
+
+namespace dcp
+{
+
+/** @class Content
+ * @brief An asset that represents a piece of content, i.e. picture, sound or subtitle.
+ *
+ * Such a piece of content will be contained in a file (either MXF or XML) within a DCP.
+ */
+class Content : public Asset
+{
+public:
+ Content (boost::filesystem::path file);
+ Content (Fraction edit_rate);
+ virtual ~Content () {}
+
+ bool equals (
+ boost::shared_ptr<const Content> other,
+ EqualityOptions opt,
+ boost::function<void (NoteType, std::string)>
+ ) const;
+
+ Fraction edit_rate () const {
+ return _edit_rate;
+ }
+
+ int64_t intrinsic_duration () const {
+ return _intrinsic_duration;
+ }
+
+protected:
+ friend class MXFWriter;
+
+ virtual std::string asdcp_kind () const = 0;
+
+ Fraction _edit_rate;
+ int64_t _intrinsic_duration;
+};
+
+}
+
+#endif
diff --git a/src/cpl.cc b/src/cpl.cc
index e333df0d..9eae09ad 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,20 +17,22 @@
*/
-#include <libxml/parser.h>
#include "cpl.h"
-#include "parse/cpl.h"
#include "util.h"
-#include "mono_picture_asset.h"
-#include "stereo_picture_asset.h"
-#include "sound_asset.h"
-#include "subtitle_asset.h"
-#include "parse/asset_map.h"
+#include "mono_picture_mxf.h"
+#include "stereo_picture_mxf.h"
+#include "sound_mxf.h"
+#include "subtitle_content.h"
#include "reel.h"
#include "metadata.h"
#include "signer.h"
#include "exceptions.h"
+#include "xml.h"
#include "compose.hpp"
+#include "reel_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
+#include <libxml/parser.h>
using std::string;
using std::stringstream;
@@ -41,167 +43,78 @@ using std::make_pair;
using boost::shared_ptr;
using boost::lexical_cast;
using boost::optional;
-using namespace libdcp;
+using namespace dcp;
-CPL::CPL (boost::filesystem::path directory, string name, ContentKind content_kind, int length, int frames_per_second)
- : _directory (directory)
- , _name (name)
+CPL::CPL (string annotation_text, ContentKind content_kind)
+ : _annotation_text (annotation_text)
+ /* default _content_title_text to _annotation_text */
+ , _content_title_text (annotation_text)
, _content_kind (content_kind)
- , _length (length)
- , _fps (frames_per_second)
+ , _content_version_id ("urn:uuid:" + make_uuid ())
{
- _id = make_uuid ();
+ /* default _content_version_id to and _content_version_label to
+ a random ID and the current time.
+ */
+ time_t now = time (0);
+ struct tm* tm = localtime (&now);
+ _content_version_id = "urn:uuid:" + make_uuid() + tm_to_string (tm);
+ _content_version_label_text = _content_version_id;
}
-/** Construct a CPL object from a XML file.
- * @param directory The directory containing this CPL's DCP.
- * @param file The CPL XML filename.
- * @param asset_maps AssetMaps to look for assets in.
- * @param require_mxfs true to throw an exception if a required MXF file does not exist.
- */
-CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> asset_maps, bool require_mxfs)
- : _directory (directory)
+/** Construct a CPL object from a XML file */
+CPL::CPL (boost::filesystem::path file)
+ : Asset (file)
, _content_kind (FEATURE)
- , _length (0)
- , _fps (0)
{
- /* Read the XML */
- shared_ptr<parse::CPL> cpl;
- try {
- cpl.reset (new parse::CPL (file));
- } catch (FileError& e) {
- boost::throw_exception (FileError ("could not load CPL file", file, e.number ()));
- }
-
- /* Now cherry-pick the required bits into our own data structure */
-
- _name = cpl->annotation_text;
- _content_kind = cpl->content_kind;
-
- /* Trim urn:uuid: off the front */
- _id = cpl->id.substr (9);
-
- for (list<shared_ptr<parse::Reel> >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) {
-
- shared_ptr<parse::Picture> p;
-
- if ((*i)->asset_list->main_picture) {
- p = (*i)->asset_list->main_picture;
- } else {
- p = (*i)->asset_list->main_stereoscopic_picture;
- }
-
- _fps = p->edit_rate.numerator;
- _length += p->duration;
-
- shared_ptr<PictureAsset> picture;
- shared_ptr<SoundAsset> sound;
- shared_ptr<SubtitleAsset> subtitle;
-
- /* Some rather twisted logic to decide if we are 3D or not;
- some DCPs give a MainStereoscopicPicture to indicate 3D, others
- just have a FrameRate twice the EditRate and apparently
- expect you to divine the fact that they are hence 3D.
- */
-
- if (!(*i)->asset_list->main_stereoscopic_picture && p->edit_rate == p->frame_rate) {
-
- try {
- pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
-
- picture.reset (new MonoPictureAsset (asset.first, asset.second->chunks.front()->path));
+ cxml::Document f ("CompositionPlaylist");
+ f.read_file (file);
- picture->read ();
- picture->set_edit_rate (_fps);
- picture->set_entry_point (p->entry_point);
- picture->set_duration (p->duration);
- if (p->key_id.length() > 9) {
- /* Trim urn:uuid: */
- picture->set_key_id (p->key_id.substr (9));
- }
- } catch (MXFFileError) {
- if (require_mxfs) {
- throw;
- }
- }
-
- } else {
- try {
- pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
-
- picture.reset (new StereoPictureAsset (asset.first, asset.second->chunks.front()->path));
-
- picture->read ();
- picture->set_edit_rate (_fps);
- picture->set_entry_point (p->entry_point);
- picture->set_duration (p->duration);
- if (p->key_id.length() > 9) {
- /* Trim urn:uuid: */
- picture->set_key_id (p->key_id.substr (9));
- }
-
- } catch (MXFFileError) {
- if (require_mxfs) {
- throw;
- }
- }
-
- }
-
- if ((*i)->asset_list->main_sound) {
-
- try {
- pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_sound->id);
-
- sound.reset (new SoundAsset (asset.first, asset.second->chunks.front()->path));
- shared_ptr<parse::MainSound> s = (*i)->asset_list->main_sound;
-
- sound->read ();
- sound->set_entry_point (s->entry_point);
- sound->set_duration (s->duration);
- if (s->key_id.length() > 9) {
- /* Trim urn:uuid: */
- sound->set_key_id (s->key_id.substr (9));
- }
- } catch (MXFFileError) {
- if (require_mxfs) {
- throw;
- }
- }
- }
-
- if ((*i)->asset_list->main_subtitle) {
-
- pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_subtitle->id);
+ _id = f.string_child ("Id");
+ if (_id.length() > 9) {
+ _id = _id.substr (9);
+ }
+ _annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
+ _metadata.issuer = f.optional_string_child ("Issuer").get_value_or ("");
+ _metadata.creator = f.optional_string_child ("Creator").get_value_or ("");
+ _metadata.issue_date = f.string_child ("IssueDate");
+ _content_title_text = f.string_child ("ContentTitleText");
+ _content_kind = content_kind_from_string (f.string_child ("ContentKind"));
+ shared_ptr<cxml::Node> content_version = f.optional_node_child ("ContentVersion");
+ if (content_version) {
+ _content_version_id = content_version->optional_string_child ("Id").get_value_or ("");
+ _content_version_label_text = content_version->string_child ("LabelText");
+ content_version->done ();
+ }
+ f.ignore_child ("RatingList");
+ _reels = type_grand_children<Reel> (f, "ReelList", "Reel");
- subtitle.reset (new SubtitleAsset (asset.first, asset.second->chunks.front()->path));
+ f.ignore_child ("Issuer");
+ f.ignore_child ("Signer");
+ f.ignore_child ("Signature");
- subtitle->set_entry_point ((*i)->asset_list->main_subtitle->entry_point);
- subtitle->set_duration ((*i)->asset_list->main_subtitle->duration);
- }
-
- _reels.push_back (shared_ptr<Reel> (new Reel (picture, sound, subtitle)));
- }
+ f.done ();
}
+/** Add a reel to this CPL.
+ * @param reel Reel to add.
+ */
void
-CPL::add_reel (shared_ptr<Reel> reel)
+CPL::add (boost::shared_ptr<Reel> reel)
{
_reels.push_back (reel);
}
+/** Write an CompositonPlaylist XML file.
+ * @param file Filename to write.
+ * @param standard INTEROP or SMPTE.
+ * @param signer Signer to sign the CPL, or 0 to add no signature.
+ */
void
-CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+CPL::write_xml (boost::filesystem::path file, Standard standard, shared_ptr<const Signer> signer) const
{
- boost::filesystem::path p;
- p /= _directory;
- stringstream s;
- s << _id << "_cpl.xml";
- p /= s.str();
-
xmlpp::Document doc;
xmlpp::Element* root;
- if (interop) {
+ if (standard == INTEROP) {
root = doc.create_root_node ("CompositionPlaylist", "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#");
} else {
root = doc.create_root_node ("CompositionPlaylist", "http://www.smpte-ra.org/schemas/429-7/2006/CPL");
@@ -212,90 +125,61 @@ CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Sig
}
root->add_child("Id")->add_child_text ("urn:uuid:" + _id);
- root->add_child("AnnotationText")->add_child_text (_name);
- root->add_child("IssueDate")->add_child_text (metadata.issue_date);
- root->add_child("Issuer")->add_child_text (metadata.issuer);
- root->add_child("Creator")->add_child_text (metadata.creator);
- root->add_child("ContentTitleText")->add_child_text (_name);
+ root->add_child("AnnotationText")->add_child_text (_annotation_text);
+ root->add_child("IssueDate")->add_child_text (_metadata.issue_date);
+ root->add_child("Issuer")->add_child_text (_metadata.issuer);
+ root->add_child("Creator")->add_child_text (_metadata.creator);
+ root->add_child("ContentTitleText")->add_child_text (_content_title_text);
root->add_child("ContentKind")->add_child_text (content_kind_to_string (_content_kind));
{
xmlpp::Node* cv = root->add_child ("ContentVersion");
- cv->add_child ("Id")->add_child_text ("urn:uri:" + _id + "_" + metadata.issue_date);
- cv->add_child ("LabelText")->add_child_text (_id + "_" + metadata.issue_date);
+ cv->add_child ("Id")->add_child_text (_content_version_id);
+ cv->add_child ("LabelText")->add_child_text (_content_version_label_text);
}
root->add_child("RatingList");
xmlpp::Element* reel_list = root->add_child ("ReelList");
for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
- (*i)->write_to_cpl (reel_list);
+ (*i)->write_to_cpl (reel_list, standard);
}
if (signer) {
- signer->sign (root, interop);
+ signer->sign (root, standard);
}
/* This must not be the _formatted version otherwise signature digests will be wrong */
- doc.write_to_file (p.string (), "UTF-8");
+ doc.write_to_file (file.string (), "UTF-8");
- _digest = make_digest (p.string (), 0);
- _length = boost::filesystem::file_size (p.string ());
+ set_file (file);
}
-void
-CPL::write_to_pkl (xmlpp::Node* node, bool interop) const
+list<shared_ptr<const Content> >
+CPL::content () const
{
- xmlpp::Node* asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
- asset->add_child("Hash")->add_child_text (_digest);
- asset->add_child("Size")->add_child_text (lexical_cast<string> (_length));
- if (interop) {
- asset->add_child("Type")->add_child_text ("text/xml;asdcpKind=CPL");
- } else {
- asset->add_child("Type")->add_child_text ("text/xml");
- }
-}
+ list<shared_ptr<const Content> > c;
-list<shared_ptr<const Asset> >
-CPL::assets () const
-{
- list<shared_ptr<const Asset> > a;
for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
if ((*i)->main_picture ()) {
- a.push_back ((*i)->main_picture ());
+ c.push_back ((*i)->main_picture()->mxf ());
}
if ((*i)->main_sound ()) {
- a.push_back ((*i)->main_sound ());
+ c.push_back ((*i)->main_sound()->mxf ());
}
if ((*i)->main_subtitle ()) {
- a.push_back ((*i)->main_subtitle ());
+ c.push_back ((*i)->main_subtitle()->subtitle_content ());
}
}
- return a;
-}
-
-void
-CPL::write_to_assetmap (xmlpp::Node* node) const
-{
- xmlpp::Node* asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
- xmlpp::Node* chunk_list = asset->add_child ("ChunkList");
- xmlpp::Node* chunk = chunk_list->add_child ("Chunk");
- chunk->add_child("Path")->add_child_text (_id + "_cpl.xml");
- chunk->add_child("VolumeIndex")->add_child_text ("1");
- chunk->add_child("Offset")->add_child_text("0");
- chunk->add_child("Length")->add_child_text(lexical_cast<string> (_length));
+ return c;
}
-
-
bool
CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
{
- if (_name != other._name && !opt.cpl_names_can_differ) {
+ if (_annotation_text != other._annotation_text && !opt.cpl_annotation_texts_can_differ) {
stringstream s;
- s << "names differ: " << _name << " vs " << other._name << "\n";
+ s << "annotation texts differ: " << _annotation_text << " vs " << other._annotation_text << "\n";
note (ERROR, s.str ());
return false;
}
@@ -305,16 +189,6 @@ CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteT
return false;
}
- if (_fps != other._fps) {
- note (ERROR, String::compose ("frames per second differ (%1 vs %2)", _fps, other._fps));
- return false;
- }
-
- if (_length != other._length) {
- stringstream s;
- note (ERROR, String::compose ("lengths differ (%1 vs %2)", _length, other._length));
- }
-
if (_reels.size() != other._reels.size()) {
note (ERROR, String::compose ("reel counts differ (%1 vs %2)", _reels.size(), other._reels.size()));
return false;
@@ -347,31 +221,48 @@ CPL::encrypted () const
return false;
}
+/** Add a KDM to this CPL. If the KDM is for any of this CPLs assets it will be used
+ * to decrypt those assets.
+ * @param kdm KDM.
+ */
void
-CPL::add_kdm (KDM const & kdm)
+CPL::add (KDM const & kdm)
{
for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
- (*i)->add_kdm (kdm);
+ (*i)->add (kdm);
}
}
-pair<string, shared_ptr<const parse::AssetMapAsset> >
-CPL::asset_from_id (list<PathAssetMap> asset_maps, string id) const
+/** Set a private key for every MXF referenced by this CPL. This will allow the data
+ * to be decrypted or encrypted.
+ * @param key Key to use.
+ */
+void
+CPL::set_mxf_keys (Key key)
{
- for (list<PathAssetMap>::const_iterator i = asset_maps.begin(); i != asset_maps.end(); ++i) {
- shared_ptr<parse::AssetMapAsset> a = i->second->asset_from_id (id);
- if (a) {
- return make_pair (i->first, a);
- }
+ for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
+ (*i)->set_mxf_keys (key);
}
-
- return make_pair ("", shared_ptr<const parse::AssetMapAsset> ());
}
void
-CPL::set_mxf_keys (Key key)
+CPL::resolve_refs (list<shared_ptr<Object> > objects)
{
for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
- (*i)->set_mxf_keys (key);
+ (*i)->resolve_refs (objects);
}
}
+
+string
+CPL::pkl_type (Standard standard) const
+{
+ switch (standard) {
+ case INTEROP:
+ return "text/xml;asdcpKind=CPL";
+ case SMPTE:
+ return "text/xml";
+ default:
+ assert (false);
+ }
+}
+
diff --git a/src/cpl.h b/src/cpl.h
index c50d8f90..8458a028 100644
--- a/src/cpl.h
+++ b/src/cpl.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
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
@@ -20,45 +20,66 @@
#ifndef LIBDCP_CPL_H
#define LIBDCP_CPL_H
-#include <list>
+#include "types.h"
+#include "certificates.h"
+#include "key.h"
+#include "asset.h"
+#include "metadata.h"
+#include <libxml++/libxml++.h>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/optional.hpp>
#include <boost/filesystem.hpp>
-#include <libxml++/libxml++.h>
-#include "types.h"
-#include "certificates.h"
-#include "key.h"
-
-namespace libdcp {
+#include <list>
-namespace parse {
- class AssetMap;
- class AssetMapAsset;
-}
+namespace dcp {
-class Asset;
+class Content;
class Reel;
class XMLMetadata;
class MXFMetadata;
class Signer;
class KDM;
-/** @brief A CPL within a DCP */
-class CPL
+/** @class CPL
+ * @brief A Composition Playlist.
+ */
+class CPL : public Asset
{
public:
- CPL (boost::filesystem::path directory, std::string name, ContentKind content_kind, int length, int frames_per_second);
- CPL (boost::filesystem::path, std::string file, std::list<PathAssetMap> asset_maps, bool require_mxfs = true);
+ CPL (std::string annotation_text, ContentKind content_kind);
+ CPL (boost::filesystem::path file);
- void add_reel (boost::shared_ptr<Reel> reel);
+ bool equals (
+ CPL const & other,
+ EqualityOptions options,
+ boost::function<void (NoteType, std::string)> note
+ ) const;
+
+ void add (boost::shared_ptr<Reel> reel);
+ void add (KDM const &);
+
+ /** @return contents of the &lt;AnnotationText&gt; node */
+ std::string annotation_text () const {
+ return _annotation_text;
+ }
- /** @return the length in frames */
- int length () const {
- return _length;
+ /** @return contents of the &lt;ContentTitleText&gt; node */
+ std::string content_title_text () const {
+ return _content_title_text;
+ }
+
+ /** @return contents of the &lt;Id&gt; node within &lt;ContentVersion&gt; */
+ void set_content_version_id (std::string id) {
+ _content_version_id = id;
}
+ /** @return contents of the &lt;LabelText&gt; node within &lt;ContentVersion&gt; */
+ void set_content_version_label_text (std::string text) {
+ _content_version_label_text = text;
+ }
+
/** @return the type of the content, used by media servers
* to categorise things (e.g. feature, trailer, etc.)
*/
@@ -66,59 +87,43 @@ public:
return _content_kind;
}
+ /** @return the reels in this CPL */
std::list<boost::shared_ptr<Reel> > reels () const {
return _reels;
}
- /** @return the CPL's name, as will be presented on projector
- * media servers and theatre management systems.
+ /** @return the Content in this CPL across all its reels
+ * (Content is picture, sound and subtitles)
*/
- std::string name () const {
- return _name;
- }
-
- /** @return the number of frames per second */
- int frames_per_second () const {
- return _fps;
- }
-
- std::list<boost::shared_ptr<const Asset> > assets () const;
+ std::list<boost::shared_ptr<const Content> > content () const;
bool encrypted () const;
void set_mxf_keys (Key);
- std::string id () const {
- return _id;
- }
-
- bool equals (CPL const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const;
-
- void write_xml (bool, XMLMetadata const &, boost::shared_ptr<const Signer>) const;
- void write_to_assetmap (xmlpp::Node *) const;
- void write_to_pkl (xmlpp::Node *, bool) const;
+ void write_xml (
+ boost::filesystem::path file,
+ Standard standard,
+ boost::shared_ptr<const Signer>
+ ) const;
+
+ void resolve_refs (std::list<boost::shared_ptr<Object> >);
+
+protected:
+ /** @return type string for PKLs for this asset */
+ std::string pkl_type (Standard standard) const;
- void add_kdm (KDM const &);
-
private:
- std::pair<std::string, boost::shared_ptr<const parse::AssetMapAsset> > asset_from_id (std::list<PathAssetMap>, std::string id) const;
-
- boost::filesystem::path _directory;
- /** the name of the DCP */
- std::string _name;
- /** the content kind of the CPL */
- ContentKind _content_kind;
- /** length in frames */
- mutable int _length;
- /** frames per second */
- int _fps;
- /** reels */
+ std::string _annotation_text; ///< &lt;AnnotationText&gt;
+ /** &lt;Issuer&gt;, &lt;Creator&gt; and &lt;IssueDate&gt;. These are grouped
+ * because they occur together in a few places.
+ */
+ XMLMetadata _metadata;
+ std::string _content_title_text; ///< &lt;ContentTitleText&gt;
+ ContentKind _content_kind; ///< &lt;ContentKind&gt;
+ std::string _content_version_id; ///< &lt;Id&gt; in &lt;ContentVersion&gt;
+ std::string _content_version_label_text; ///< &lt;LabelText&gt; in &lt;ContentVersion&gt;
std::list<boost::shared_ptr<Reel> > _reels;
-
- /** our UUID */
- std::string _id;
- /** a SHA1 digest of our XML */
- mutable std::string _digest;
};
}
diff --git a/src/dcp.cc b/src/dcp.cc
index ae692256..88e36506 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,80 +18,207 @@
*/
/** @file src/dcp.cc
- * @brief A class to create a DCP.
+ * @brief DCP class.
*/
-#include <sstream>
-#include <iomanip>
-#include <cassert>
-#include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libxml++/libxml++.h>
-#include <xmlsec/xmldsig.h>
-#include <xmlsec/app.h>
#include "dcp.h"
-#include "asset.h"
-#include "sound_asset.h"
-#include "picture_asset.h"
-#include "subtitle_asset.h"
+#include "sound_mxf.h"
+#include "picture_mxf.h"
+#include "subtitle_content.h"
+#include "mono_picture_mxf.h"
+#include "stereo_picture_mxf.h"
#include "util.h"
#include "metadata.h"
#include "exceptions.h"
-#include "parse/pkl.h"
-#include "parse/asset_map.h"
#include "reel.h"
#include "cpl.h"
#include "signer.h"
#include "kdm.h"
+#include "compose.hpp"
+#include "AS_DCP.h"
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/app.h>
+#include <libxml++/libxml++.h>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <sstream>
+#include <iomanip>
+#include <cassert>
+#include <iostream>
using std::string;
using std::list;
using std::stringstream;
using std::ostream;
-using std::copy;
-using std::back_inserter;
using std::make_pair;
+using std::map;
using boost::shared_ptr;
using boost::lexical_cast;
-using namespace libdcp;
+using namespace dcp;
DCP::DCP (boost::filesystem::path directory)
: _directory (directory)
{
boost::filesystem::create_directories (directory);
+ _directory = boost::filesystem::canonical (_directory);
}
void
-DCP::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+DCP::read ()
{
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- (*i)->write_xml (interop, metadata, signer);
+ /* Read the ASSETMAP */
+
+ boost::filesystem::path asset_map_file;
+ if (boost::filesystem::exists (_directory / "ASSETMAP")) {
+ asset_map_file = _directory / "ASSETMAP";
+ } else if (boost::filesystem::exists (_directory / "ASSETMAP.xml")) {
+ asset_map_file = _directory / "ASSETMAP.xml";
+ } else {
+ boost::throw_exception (DCPReadError ("could not find AssetMap file"));
}
- string pkl_uuid = make_uuid ();
- string pkl_path = write_pkl (pkl_uuid, interop, metadata, signer);
+ cxml::Document asset_map ("AssetMap");
+ asset_map.read_file (asset_map_file);
+ list<shared_ptr<cxml::Node> > asset_nodes = asset_map.node_child("AssetList")->node_children ("Asset");
+ map<string, boost::filesystem::path> paths;
+ for (list<shared_ptr<cxml::Node> >::const_iterator i = asset_nodes.begin(); i != asset_nodes.end(); ++i) {
+ if ((*i)->node_child("ChunkList")->node_children("Chunk").size() != 1) {
+ boost::throw_exception (XMLError ("unsupported asset chunk count"));
+ }
+ paths.insert (make_pair (
+ (*i)->string_child ("Id"),
+ (*i)->node_child("ChunkList")->node_child("Chunk")->string_child ("Path")
+ ));
+ }
+
+ /* Read all the assets from the asset map */
- write_volindex (interop);
- write_assetmap (pkl_uuid, boost::filesystem::file_size (pkl_path), interop, metadata);
+ for (map<string, boost::filesystem::path>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+ boost::filesystem::path path = _directory / i->second;
+ if (boost::algorithm::ends_with (path.string(), ".xml")) {
+ xmlpp::DomParser* p = new xmlpp::DomParser;
+ try {
+ p->parse_file (path.string());
+ } catch (std::exception& e) {
+ delete p;
+ continue;
+ }
+
+ string const root = p->get_document()->get_root_node()->get_name ();
+ delete p;
+
+ if (root == "CompositionPlaylist") {
+ _assets.push_back (shared_ptr<CPL> (new CPL (path)));
+ } else if (root == "DCSubtitle") {
+ _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (path)));
+ }
+ } else if (boost::algorithm::ends_with (path.string(), ".mxf")) {
+ ASDCP::EssenceType_t type;
+ if (ASDCP::EssenceType (path.string().c_str(), type) != ASDCP::RESULT_OK) {
+ throw DCPReadError ("Could not find essence type");
+ }
+ switch (type) {
+ case ASDCP::ESS_UNKNOWN:
+ case ASDCP::ESS_MPEG2_VES:
+ throw DCPReadError ("MPEG2 video essences are not supported");
+ case ASDCP::ESS_JPEG_2000:
+ _assets.push_back (shared_ptr<MonoPictureMXF> (new MonoPictureMXF (path)));
+ break;
+ case ASDCP::ESS_PCM_24b_48k:
+ case ASDCP::ESS_PCM_24b_96k:
+ _assets.push_back (shared_ptr<SoundMXF> (new SoundMXF (path)));
+ break;
+ case ASDCP::ESS_JPEG_2000_S:
+ _assets.push_back (shared_ptr<StereoPictureMXF> (new StereoPictureMXF (path)));
+ break;
+ default:
+ throw DCPReadError ("Unknown MXF essence type");
+ }
+ }
+ }
+
+ list<shared_ptr<CPL> > cpl = cpls ();
+ for (list<shared_ptr<CPL> >::const_iterator i = cpl.begin(); i != cpl.end(); ++i) {
+ (*i)->resolve_refs (list_of_type<Asset, Object> (assets ()));
+ }
}
-std::string
-DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+bool
+DCP::equals (DCP const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
{
- assert (!_cpls.empty ());
+ if (_assets.size() != other._assets.size()) {
+ note (ERROR, "Asset counts differ");
+ return false;
+ }
+
+ list<shared_ptr<Asset> >::const_iterator a = _assets.begin ();
+ list<shared_ptr<Asset> >::const_iterator b = other._assets.begin ();
+
+ while (a != _assets.end ()) {
+ if (!(*a)->equals (*b, opt, note)) {
+ return false;
+ }
+ ++a;
+ ++b;
+ }
+
+ return true;
+}
+
+void
+DCP::add (boost::shared_ptr<Asset> asset)
+{
+ _assets.push_back (asset);
+}
+
+class AssetComparator
+{
+public:
+ bool operator() (shared_ptr<const Content> a, shared_ptr<const Content> b) {
+ return a->id() < b->id();
+ }
+};
+
+bool
+DCP::encrypted () const
+{
+ list<shared_ptr<CPL> > cpl = cpls ();
+ for (list<shared_ptr<CPL> >::const_iterator i = cpl.begin(); i != cpl.end(); ++i) {
+ if ((*i)->encrypted ()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void
+DCP::add (KDM const & kdm)
+{
+ list<KDMKey> keys = kdm.keys ();
+ list<shared_ptr<CPL> > cpl = cpls ();
- boost::filesystem::path p;
- p /= _directory;
+ for (list<shared_ptr<CPL> >::iterator i = cpl.begin(); i != cpl.end(); ++i) {
+ for (list<KDMKey>::iterator j = keys.begin(); j != keys.end(); ++j) {
+ if (j->cpl_id() == (*i)->id()) {
+ (*i)->add (kdm);
+ }
+ }
+ }
+}
+
+boost::filesystem::path
+DCP::write_pkl (Standard standard, string pkl_uuid, XMLMetadata metadata, shared_ptr<const Signer> signer) const
+{
+ boost::filesystem::path p = _directory;
stringstream s;
s << pkl_uuid << "_pkl.xml";
p /= s.str();
xmlpp::Document doc;
xmlpp::Element* pkl;
- if (interop) {
+ if (standard == INTEROP) {
pkl = doc.create_root_node("PackingList", "http://www.digicine.com/PROTO-ASDCP-PKL-20040311#");
} else {
pkl = doc.create_root_node("PackingList", "http://www.smpte-ra.org/schemas/429-8/2007/PKL");
@@ -102,83 +229,112 @@ DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, sha
}
pkl->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid);
+
/* XXX: this is a bit of a hack */
- pkl->add_child("AnnotationText")->add_child_text(_cpls.front()->name());
+ assert (cpls().size() > 0);
+ pkl->add_child("AnnotationText")->add_child_text (cpls().front()->annotation_text ());
+
pkl->add_child("IssueDate")->add_child_text (metadata.issue_date);
pkl->add_child("Issuer")->add_child_text (metadata.issuer);
pkl->add_child("Creator")->add_child_text (metadata.creator);
xmlpp::Element* asset_list = pkl->add_child("AssetList");
- list<shared_ptr<const Asset> > a = assets ();
- for (list<shared_ptr<const Asset> >::const_iterator i = a.begin(); i != a.end(); ++i) {
- (*i)->write_to_pkl (asset_list, interop);
- }
-
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- (*i)->write_to_pkl (asset_list, interop);
+ for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ (*i)->write_to_pkl (asset_list, standard);
}
if (signer) {
- signer->sign (pkl, interop);
+ signer->sign (pkl, standard);
}
doc.write_to_file (p.string (), "UTF-8");
return p.string ();
}
+/** Write the VOLINDEX file.
+ * @param standard DCP standard to use (INTEROP or SMPTE)
+ */
void
-DCP::write_volindex (bool interop) const
+DCP::write_volindex (Standard standard) const
{
- boost::filesystem::path p;
- p /= _directory;
- if (interop) {
+ boost::filesystem::path p = _directory;
+ switch (standard) {
+ case INTEROP:
p /= "VOLINDEX";
- } else {
+ break;
+ case SMPTE:
p /= "VOLINDEX.xml";
+ break;
+ default:
+ assert (false);
}
xmlpp::Document doc;
xmlpp::Element* root;
- if (interop) {
+
+ switch (standard) {
+ case INTEROP:
root = doc.create_root_node ("VolumeIndex", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#");
- } else {
+ break;
+ case SMPTE:
root = doc.create_root_node ("VolumeIndex", "http://www.smpte-ra.org/schemas/429-9/2007/AM");
+ break;
+ default:
+ assert (false);
}
+
root->add_child("Index")->add_child_text ("1");
doc.write_to_file (p.string (), "UTF-8");
}
void
-DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata const & metadata) const
+DCP::write_assetmap (Standard standard, string pkl_uuid, int pkl_length, XMLMetadata metadata) const
{
- boost::filesystem::path p;
- p /= _directory;
- if (interop) {
+ boost::filesystem::path p = _directory;
+
+ switch (standard) {
+ case INTEROP:
p /= "ASSETMAP";
- } else {
+ break;
+ case SMPTE:
p /= "ASSETMAP.xml";
+ break;
+ default:
+ assert (false);
}
xmlpp::Document doc;
xmlpp::Element* root;
- if (interop) {
+
+ switch (standard) {
+ case INTEROP:
root = doc.create_root_node ("AssetMap", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#");
- } else {
+ break;
+ case SMPTE:
root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM");
+ break;
+ default:
+ assert (false);
}
root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid());
root->add_child("AnnotationText")->add_child_text ("Created by " + metadata.creator);
- if (interop) {
+
+ switch (standard) {
+ case INTEROP:
root->add_child("VolumeCount")->add_child_text ("1");
root->add_child("IssueDate")->add_child_text (metadata.issue_date);
root->add_child("Issuer")->add_child_text (metadata.issuer);
root->add_child("Creator")->add_child_text (metadata.creator);
- } else {
+ break;
+ case SMPTE:
root->add_child("Creator")->add_child_text (metadata.creator);
root->add_child("VolumeCount")->add_child_text ("1");
root->add_child("IssueDate")->add_child_text (metadata.issue_date);
root->add_child("Issuer")->add_child_text (metadata.issuer);
+ break;
+ default:
+ assert (false);
}
xmlpp::Node* asset_list = root->add_child ("AssetList");
@@ -193,187 +349,41 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
chunk->add_child("Offset")->add_child_text ("0");
chunk->add_child("Length")->add_child_text (lexical_cast<string> (pkl_length));
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- (*i)->write_to_assetmap (asset_list);
- }
-
- list<shared_ptr<const Asset> > a = assets ();
- for (list<shared_ptr<const Asset> >::const_iterator i = a.begin(); i != a.end(); ++i) {
- (*i)->write_to_assetmap (asset_list);
+ for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+ (*i)->write_to_assetmap (asset_list, _directory);
}
/* This must not be the _formatted version otherwise signature digests will be wrong */
doc.write_to_file (p.string (), "UTF-8");
}
+/** Write all the XML files for this DCP.
+ * @param standand INTEROP or SMPTE.
+ * @param metadata Metadata to use for PKL and asset map files.
+ * @param signer Signer to use, or 0.
+ */
void
-DCP::read (bool require_mxfs)
-{
- read_assets ();
- read_cpls (require_mxfs);
-}
-
-void
-DCP::read_assets ()
-{
- shared_ptr<parse::AssetMap> asset_map;
- try {
- boost::filesystem::path p = _directory;
- p /= "ASSETMAP";
- if (boost::filesystem::exists (p)) {
- asset_map.reset (new libdcp::parse::AssetMap (p.string ()));
- } else {
- p = _directory;
- p /= "ASSETMAP.xml";
- if (boost::filesystem::exists (p)) {
- asset_map.reset (new libdcp::parse::AssetMap (p.string ()));
- } else {
- boost::throw_exception (DCPReadError ("could not find AssetMap file"));
- }
- }
-
- } catch (FileError& e) {
- boost::throw_exception (FileError ("could not load AssetMap file", _files.asset_map, e.number ()));
- }
-
- for (list<shared_ptr<libdcp::parse::AssetMapAsset> >::const_iterator i = asset_map->assets.begin(); i != asset_map->assets.end(); ++i) {
- if ((*i)->chunks.size() != 1) {
- boost::throw_exception (XMLError ("unsupported asset chunk count"));
- }
-
- boost::filesystem::path t = _directory;
- t /= (*i)->chunks.front()->path;
-
- if (boost::algorithm::ends_with (t.string(), ".mxf") || boost::algorithm::ends_with (t.string(), ".ttf")) {
- continue;
- }
-
- xmlpp::DomParser* p = new xmlpp::DomParser;
- try {
- p->parse_file (t.string());
- } catch (std::exception& e) {
- delete p;
- continue;
- }
-
- string const root = p->get_document()->get_root_node()->get_name ();
- delete p;
-
- if (root == "CompositionPlaylist") {
- _files.cpls.push_back (t.string());
- } else if (root == "PackingList") {
- if (_files.pkl.empty ()) {
- _files.pkl = t.string();
- } else {
- boost::throw_exception (DCPReadError ("duplicate PKLs found"));
- }
- }
- }
-
- if (_files.cpls.empty ()) {
- boost::throw_exception (DCPReadError ("no CPL files found"));
- }
-
- if (_files.pkl.empty ()) {
- boost::throw_exception (DCPReadError ("no PKL file found"));
- }
-
- shared_ptr<parse::PKL> pkl;
- try {
- pkl.reset (new parse::PKL (_files.pkl));
- } catch (FileError& e) {
- boost::throw_exception (FileError ("could not load PKL file", _files.pkl, e.number ()));
- }
-
- _asset_maps.push_back (make_pair (boost::filesystem::absolute (_directory).string(), asset_map));
-}
-
-void
-DCP::read_cpls (bool require_mxfs)
-{
- for (list<string>::iterator i = _files.cpls.begin(); i != _files.cpls.end(); ++i) {
- _cpls.push_back (shared_ptr<CPL> (new CPL (_directory, *i, _asset_maps, require_mxfs)));
- }
-}
-
-bool
-DCP::equals (DCP const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
-{
- if (_cpls.size() != other._cpls.size()) {
- note (ERROR, "CPL counts differ");
- return false;
- }
-
- list<shared_ptr<CPL> >::const_iterator a = _cpls.begin ();
- list<shared_ptr<CPL> >::const_iterator b = other._cpls.begin ();
-
- while (a != _cpls.end ()) {
- if (!(*a)->equals (*b->get(), opt, note)) {
- return false;
- }
- ++a;
- ++b;
- }
-
- return true;
-}
-
-void
-DCP::add_cpl (shared_ptr<CPL> cpl)
-{
- _cpls.push_back (cpl);
-}
-
-class AssetComparator
-{
-public:
- bool operator() (shared_ptr<const Asset> a, shared_ptr<const Asset> b) {
- return a->uuid() < b->uuid();
- }
-};
-
-list<shared_ptr<const Asset> >
-DCP::assets () const
-{
- list<shared_ptr<const Asset> > a;
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- list<shared_ptr<const Asset> > t = (*i)->assets ();
- a.merge (t);
- }
-
- a.sort (AssetComparator ());
- a.unique ();
- return a;
-}
-
-bool
-DCP::encrypted () const
+DCP::write_xml (
+ Standard standard,
+ XMLMetadata metadata,
+ shared_ptr<const Signer> signer
+ )
{
- for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- if ((*i)->encrypted ()) {
- return true;
- }
+ list<shared_ptr<CPL> > cpl = cpls ();
+ for (list<shared_ptr<CPL> >::const_iterator i = cpl.begin(); i != cpl.end(); ++i) {
+ string const filename = (*i)->id() + "_cpl.xml";
+ (*i)->write_xml (_directory / filename, standard, signer);
}
- return false;
-}
-
-void
-DCP::add_kdm (KDM const & kdm)
-{
- list<KDMKey> keys = kdm.keys ();
+ string const pkl_uuid = make_uuid ();
+ boost::filesystem::path const pkl_path = write_pkl (standard, pkl_uuid, metadata, signer);
- for (list<shared_ptr<CPL> >::iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- for (list<KDMKey>::iterator j = keys.begin(); j != keys.end(); ++j) {
- if (j->cpl_id() == (*i)->id()) {
- (*i)->add_kdm (kdm);
- }
- }
- }
+ write_volindex (standard);
+ write_assetmap (standard, pkl_uuid, boost::filesystem::file_size (pkl_path), metadata);
}
-void
-DCP::add_assets_from (DCP const & ov)
+list<shared_ptr<CPL> >
+DCP::cpls () const
{
- copy (ov._asset_maps.begin(), ov._asset_maps.end(), back_inserter (_asset_maps));
+ return list_of_type<Asset, CPL> (_assets);
}
diff --git a/src/dcp.h b/src/dcp.h
index 45ccce88..d6275037 100644
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,18 +18,19 @@
*/
/** @file src/dcp.h
- * @brief A class to create or read a DCP.
+ * @brief DCP class.
*/
#ifndef LIBDCP_DCP_H
#define LIBDCP_DCP_H
-#include <string>
-#include <vector>
-#include <boost/shared_ptr.hpp>
-#include <boost/signals2.hpp>
#include "types.h"
#include "certificates.h"
+#include "metadata.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2.hpp>
+#include <string>
+#include <vector>
namespace xmlpp {
class Document;
@@ -37,18 +38,16 @@ namespace xmlpp {
}
/** @brief Namespace for everything in libdcp */
-namespace libdcp
+namespace dcp
{
-class Asset;
-class PictureAsset;
-class SoundAsset;
-class SubtitleAsset;
+class Content;
class Reel;
class CPL;
class XMLMetadata;
class Signer;
class KDM;
+class Asset;
namespace parse {
class AssetMap;
@@ -69,91 +68,59 @@ public:
*/
DCP (boost::filesystem::path directory);
- void read (bool require_mxfs = true);
-
- /** Read an existing DCP's assets.
- *
- * The DCP's XML metadata will be examined, and you can then look at the contents
- * of the DCP.
- */
- void read_assets ();
-
- void read_cpls (bool require_mxfs = true);
-
- /** Write the required XML files to the directory that was
- * passed into the constructor.
- */
- void write_xml (bool interop, XMLMetadata const &, boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> ()) const;
+ void read ();
/** Compare this DCP with another, according to various options.
* @param other DCP to compare this one to.
* @param options Options to define what "equality" means.
+ * @param note Functor to handle notes made by the equality operation.
* @return true if the DCPs are equal according to EqualityOptions, otherwise false.
*/
bool equals (DCP const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const;
- /** Add a CPL to this DCP.
- * @param cpl CPL to add.
- */
- void add_cpl (boost::shared_ptr<CPL> cpl);
+ void add (boost::shared_ptr<Asset> asset);
- /** @return The list of CPLs in this DCP */
- std::list<boost::shared_ptr<CPL> > cpls () const {
- return _cpls;
- }
+ std::list<boost::shared_ptr<CPL> > cpls () const;
- /** Add another DCP as a source of assets for this DCP. This should be called before
- * ::read() on the DCP that needs the extra assets. For example
- *
- * DCP original_version ("my_dcp_OV");
- * DCP supplemental ("my_dcp_VF");
- * supplemental.add_assets_from (original_version);
- * supplemental.read ();
- */
- void add_assets_from (libdcp::DCP const &);
+ /** @return All this DCP's assets (note that CPLs are assets) */
+ std::list<boost::shared_ptr<Asset> > assets () const {
+ return _assets;
+ }
bool encrypted () const;
- void add_kdm (KDM const &);
+ void add (KDM const &);
- /** Emitted with a parameter between 0 and 1 to indicate progress
- * for long jobs.
- */
- boost::signals2::signal<void (float)> Progress;
+ void write_xml (
+ Standard standard,
+ XMLMetadata metadata = XMLMetadata (),
+ boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> ()
+ );
private:
/** Write the PKL file.
* @param pkl_uuid UUID to use.
*/
- std::string write_pkl (std::string pkl_uuid, bool, XMLMetadata const &, boost::shared_ptr<const Signer>) const;
+ boost::filesystem::path write_pkl (
+ Standard standard,
+ std::string pkl_uuid,
+ XMLMetadata metadata,
+ boost::shared_ptr<const Signer> signer
+ ) const;
- /** Write the VOLINDEX file */
- void write_volindex (bool) const;
+ void write_volindex (Standard standard) const;
/** Write the ASSETMAP file.
* @param pkl_uuid UUID of our PKL.
* @param pkl_length Length of our PKL in bytes.
*/
- void write_assetmap (std::string pkl_uuid, int pkl_length, bool, XMLMetadata const &) const;
-
- /** @return Assets in all the CPLs in this DCP */
- std::list<boost::shared_ptr<const Asset> > assets () const;
-
- struct Files {
- std::list<std::string> cpls;
- std::string pkl;
- std::string asset_map;
- };
-
- Files _files;
+ void write_assetmap (Standard standard, std::string pkl_uuid, int pkl_length, XMLMetadata metadata) const;
/** the directory that we are writing to */
boost::filesystem::path _directory;
- /** our CPLs */
- std::list<boost::shared_ptr<CPL> > _cpls;
-
- std::list<PathAssetMap> _asset_maps;
+ /** the assets that make up this DCP */
+ std::list<boost::shared_ptr<Asset> > _assets;
};
}
diff --git a/src/dcp_time.cc b/src/dcp_time.cc
index 14155fdb..5376b972 100644
--- a/src/dcp_time.cc
+++ b/src/dcp_time.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,20 +18,20 @@
*/
/** @file src/dcp_time.cc
- * @brief A representation of time within a DCP.
+ * @brief Time class.
*/
-#include <iostream>
-#include <vector>
+#include "dcp_time.h"
+#include "exceptions.h"
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
+#include <iostream>
+#include <vector>
#include <cmath>
-#include "dcp_time.h"
-#include "exceptions.h"
using namespace std;
using namespace boost;
-using namespace libdcp;
+using namespace dcp;
Time::Time (int frame, int frames_per_second)
: h (0)
@@ -85,19 +85,19 @@ Time::Time (string time)
}
bool
-libdcp::operator== (Time const & a, Time const & b)
+dcp::operator== (Time const & a, Time const & b)
{
return (a.h == b.h && a.m == b.m && a.s == b.s && a.t == b.t);
}
bool
-libdcp::operator!= (Time const & a, Time const & b)
+dcp::operator!= (Time const & a, Time const & b)
{
return !(a == b);
}
bool
-libdcp::operator<= (Time const & a, Time const & b)
+dcp::operator<= (Time const & a, Time const & b)
{
if (a.h != b.h) {
return a.h <= b.h;
@@ -119,7 +119,7 @@ libdcp::operator<= (Time const & a, Time const & b)
}
bool
-libdcp::operator< (Time const & a, Time const & b)
+dcp::operator< (Time const & a, Time const & b)
{
if (a.h != b.h) {
return a.h < b.h;
@@ -141,7 +141,7 @@ libdcp::operator< (Time const & a, Time const & b)
}
bool
-libdcp::operator> (Time const & a, Time const & b)
+dcp::operator> (Time const & a, Time const & b)
{
if (a.h != b.h) {
return a.h > b.h;
@@ -163,14 +163,14 @@ libdcp::operator> (Time const & a, Time const & b)
}
ostream &
-libdcp::operator<< (ostream& s, Time const & t)
+dcp::operator<< (ostream& s, Time const & t)
{
s << t.h << ":" << t.m << ":" << t.s << "." << t.t;
return s;
}
-libdcp::Time
-libdcp::operator+ (Time a, Time const & b)
+dcp::Time
+dcp::operator+ (Time a, Time const & b)
{
Time r;
@@ -197,8 +197,8 @@ libdcp::operator+ (Time a, Time const & b)
return r;
}
-libdcp::Time
-libdcp::operator- (Time a, Time const & b)
+dcp::Time
+dcp::operator- (Time a, Time const & b)
{
Time r;
@@ -226,7 +226,7 @@ libdcp::operator- (Time a, Time const & b)
}
float
-libdcp::operator/ (Time a, Time const & b)
+dcp::operator/ (Time a, Time const & b)
{
int64_t const at = a.h * 3600 * 250 + a.m * 60 * 250 + a.s * 250 + a.t;
int64_t const bt = b.h * 3600 * 250 + b.m * 60 * 250 + b.s * 250 + b.t;
diff --git a/src/dcp_time.h b/src/dcp_time.h
index 92cee9a0..697ca230 100644
--- a/src/dcp_time.h
+++ b/src/dcp_time.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,17 +18,17 @@
*/
/** @file src/dcp_time.h
- * @brief A representation of time within a DCP.
+ * @brief Time class.
*/
#ifndef LIBDCP_TIME_H
#define LIBDCP_TIME_H
+#include <stdint.h>
#include <string>
#include <iostream>
-#include <stdint.h>
-namespace libdcp {
+namespace dcp {
/** @class Time
* @brief A representation of time within a DCP.
diff --git a/src/exceptions.cc b/src/exceptions.cc
index 6a32a33f..e5a46948 100644
--- a/src/exceptions.cc
+++ b/src/exceptions.cc
@@ -17,13 +17,17 @@
*/
+/** @file src/exceptions.cc
+ * @brief Exceptions thrown by libdcp.
+ */
+
#include "exceptions.h"
#include "compose.hpp"
using std::string;
-using namespace libdcp;
+using namespace dcp;
-FileError::FileError (std::string const & message, boost::filesystem::path filename, int number)
+FileError::FileError (string message, boost::filesystem::path filename, int number)
: _message (String::compose ("%1 (error %2) (%3)", message, filename.string(), number))
, _filename (filename)
, _number (number)
@@ -31,3 +35,9 @@ FileError::FileError (std::string const & message, boost::filesystem::path filen
}
+UnresolvedRefError::UnresolvedRefError (string id)
+ : _message (String::compose ("Unresolved reference to asset id %1", id))
+{
+
+}
+
diff --git a/src/exceptions.h b/src/exceptions.h
index 2070dd0f..bc5e83d1 100644
--- a/src/exceptions.h
+++ b/src/exceptions.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -26,14 +26,16 @@
* @brief Exceptions thrown by libdcp.
*/
-namespace libdcp
+namespace dcp
{
-/** @brief An exception related to a file */
+/** @class FileError
+ * @brief An exception related to a file
+ */
class FileError : public std::exception
{
public:
- FileError (std::string const & message, boost::filesystem::path filename, int number);
+ FileError (std::string message, boost::filesystem::path filename, int number);
~FileError () throw () {}
/** @return error message */
@@ -59,20 +61,24 @@ private:
int _number;
};
-/** @brief An exception related to an MXF file */
+/** @class MXFFileError
+ * @brief An exception related to an MXF file
+ */
class MXFFileError : public FileError
{
public:
- MXFFileError (std::string const & message, boost::filesystem::path filename, int number)
+ MXFFileError (std::string message, boost::filesystem::path filename, int number)
: FileError (message, filename, number)
{}
};
-/** @brief A miscellaneous exception */
+/** @class MiscError
+ * @brief A miscellaneous exception
+ */
class MiscError : public std::exception
{
public:
- MiscError (std::string const & message) : _message (message) {}
+ MiscError (std::string message) : _message (message) {}
~MiscError () throw () {}
/** @return error message */
@@ -85,11 +91,13 @@ private:
std::string _message;
};
-/** @brief A DCP read exception */
+/** @class DCPReadError
+ * @brief A DCP read exception
+ */
class DCPReadError : public std::exception
{
public:
- DCPReadError (std::string const & message) : _message (message) {}
+ DCPReadError (std::string message) : _message (message) {}
~DCPReadError () throw () {}
/** @return error message */
@@ -102,11 +110,13 @@ private:
std::string _message;
};
-/** @brief An XML error */
+/** @class XMLError
+ * @brief An XML error
+ */
class XMLError : public std::exception
{
public:
- XMLError (std::string const & message) : _message (message) {}
+ XMLError (std::string message) : _message (message) {}
~XMLError () throw () {}
/** @return error message */
@@ -118,6 +128,24 @@ private:
/** error message */
std::string _message;
};
+
+/** @class UnresolvedRefError
+ * @brief An exception caused by a reference (by UUID) to something which is not known
+ */
+class UnresolvedRefError : public std::exception
+{
+public:
+ UnresolvedRefError (std::string id);
+ ~UnresolvedRefError () throw () {}
+
+ /** @return error message */
+ char const * what () const throw () {
+ return _message.c_str ();
+ }
+
+private:
+ std::string _message;
+};
}
diff --git a/src/file.cc b/src/file.cc
new file mode 100644
index 00000000..aabda166
--- /dev/null
+++ b/src/file.cc
@@ -0,0 +1,46 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/file.cc
+ * @brief File class.
+ */
+
+#include "file.h"
+#include "util.h"
+
+using namespace dcp;
+
+/** Read a file into memory.
+ * @param file to read.
+ */
+File::File (boost::filesystem::path file)
+{
+ _size = boost::filesystem::file_size (file);
+ _data = new uint8_t[_size];
+ FILE* f = dcp::fopen_boost (file, "r");
+ assert (f);
+ fread (_data, 1, _size, f);
+ fclose (f);
+}
+
+/** File destructor */
+File::~File ()
+{
+ delete[] _data;
+}
diff --git a/src/rec709_linearised_gamma_lut.cc b/src/file.h
index f14e4472..b06cece0 100644
--- a/src/rec709_linearised_gamma_lut.cc
+++ b/src/file.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,22 +17,39 @@
*/
-#include "rec709_linearised_gamma_lut.h"
+/** @file src/file.h
+ * @brief File class.
+ */
-using namespace libdcp;
+#ifndef LIBDCP_FILE_H
+#define LIBDCP_FILE_H
-LUTCache<Rec709LinearisedGammaLUT> Rec709LinearisedGammaLUT::cache;
+#include <boost/filesystem.hpp>
-Rec709LinearisedGammaLUT::Rec709LinearisedGammaLUT (int bits, float gamma)
- : LUT (bits, gamma)
+namespace dcp {
+
+/** @class File
+ * @brief Helper class which loads a file into memory.
+ */
+class File
{
- int const bit_length = pow (2, bits);
- for (int i = 0; i < bit_length; ++i) {
- float const p = static_cast<float> (i) / (bit_length - 1);
- if (p > 0.08125) {
- _lut[i] = pow ((p + 0.099) / 1.099, gamma);
- } else {
- _lut[i] = p / 4.5;
- }
+public:
+ File (boost::filesystem::path file);
+ ~File ();
+
+ uint8_t* data () const {
+ return _data;
+ }
+
+ int64_t size () const {
+ return _size;
}
+
+private:
+ uint8_t* _data; ///< file's data
+ int64_t _size; ///< data size in bytes
+};
+
}
+
+#endif
diff --git a/src/parse/subtitle.cc b/src/font.cc
index 914be677..52996a73 100644
--- a/src/parse/subtitle.cc
+++ b/src/font.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,20 +17,18 @@
*/
-#include <boost/shared_ptr.hpp>
-#include <boost/optional.hpp>
-#include "subtitle.h"
-#include "../types.h"
+#include "font.h"
+#include "xml.h"
+#include "text.h"
+#include <libcxml/cxml.h>
using std::string;
using std::list;
using boost::shared_ptr;
using boost::optional;
-using boost::lexical_cast;
-using namespace libdcp;
-using namespace libdcp::parse;
+using namespace dcp;
-Font::Font (shared_ptr<const cxml::Node> node)
+Font::Font (boost::shared_ptr<const cxml::Node> node)
{
text = node->content ();
@@ -54,7 +52,7 @@ Font::Font (shared_ptr<const cxml::Node> node)
text_nodes = type_children<Text> (node, "Text");
}
-Font::Font (list<shared_ptr<Font> > const & font_nodes)
+Font::Font (std::list<boost::shared_ptr<Font> > const & font_nodes)
: size (0)
, italic (false)
, color ("FFFFFFFF")
@@ -81,69 +79,3 @@ Font::Font (list<shared_ptr<Font> > const & font_nodes)
}
}
}
-
-LoadFont::LoadFont (shared_ptr<const cxml::Node> node)
-{
- optional<string> x = node->optional_string_attribute ("Id");
- if (!x) {
- x = node->optional_string_attribute ("ID");
- }
- id = x.get_value_or ("");
-
- uri = node->optional_string_attribute ("URI");
-}
-
-Subtitle::Subtitle (shared_ptr<const cxml::Node> node)
-{
- in = Time (node->string_attribute ("TimeIn"));
- out = Time (node->string_attribute ("TimeOut"));
- font_nodes = type_children<Font> (node, "Font");
- text_nodes = type_children<Text> (node, "Text");
- fade_up_time = fade_time (node, "FadeUpTime");
- fade_down_time = fade_time (node, "FadeDownTime");
-}
-
-Time
-Subtitle::fade_time (shared_ptr<const cxml::Node> node, string name)
-{
- string const u = node->optional_string_attribute (name).get_value_or ("");
- Time t;
-
- if (u.empty ()) {
- t = Time (0, 0, 0, 20);
- } else if (u.find (":") != string::npos) {
- t = Time (u);
- } else {
- t = Time (0, 0, 0, lexical_cast<int> (u));
- }
-
- if (t > Time (0, 0, 8, 0)) {
- t = Time (0, 0, 8, 0);
- }
-
- return t;
-}
-
-Text::Text (shared_ptr<const cxml::Node> node)
- : v_align (CENTER)
-{
- /* Vertical position */
- text = node->content ();
- optional<float> x = node->optional_number_attribute<float> ("VPosition");
- if (!x) {
- x = node->number_attribute<float> ("Vposition");
- }
- v_position = x.get ();
-
- /* Vertical alignment */
- optional<string> v = node->optional_string_attribute ("VAlign");
- if (!v) {
- v = node->optional_string_attribute ("Valign");
- }
- if (v) {
- v_align = string_to_valign (v.get ());
- }
-
- font_nodes = type_children<Font> (node, "Font");
-}
-
diff --git a/src/parse/subtitle.h b/src/font.h
index 3d99d9bc..1b29e570 100644
--- a/src/parse/subtitle.h
+++ b/src/font.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,51 +17,18 @@
*/
-#include "../xml.h"
-#include "../dcp_time.h"
-#include "../types.h"
+#include "types.h"
+#include "subtitle.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+#include <list>
-namespace libdcp
-{
-
-namespace parse
-{
-
-class Font;
+namespace cxml {
+ class Node;
+}
-class Text
-{
-public:
- Text ()
- : v_position (0)
- , v_align (TOP)
- {}
+namespace dcp {
- Text (boost::shared_ptr<const cxml::Node> node);
-
- float v_position;
- VAlign v_align;
- std::string text;
- std::list<boost::shared_ptr<Font> > font_nodes;
-};
-
-class Subtitle
-{
-public:
- Subtitle () {}
- Subtitle (boost::shared_ptr<const cxml::Node> node);
-
- Time in;
- Time out;
- Time fade_up_time;
- Time fade_down_time;
- std::list<boost::shared_ptr<Font> > font_nodes;
- std::list<boost::shared_ptr<Text> > text_nodes;
-
-private:
- Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name);
-};
-
class Font
{
public:
@@ -85,16 +52,4 @@ public:
std::list<boost::shared_ptr<Text> > text_nodes;
};
-class LoadFont
-{
-public:
- LoadFont () {}
- LoadFont (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- boost::optional<std::string> uri;
-};
-
-}
-
}
diff --git a/src/gamma_lut.cc b/src/gamma_lut.cc
index 80d9b902..abe35b7c 100644
--- a/src/gamma_lut.cc
+++ b/src/gamma_lut.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,19 +17,34 @@
*/
-#include <cmath>
#include "gamma_lut.h"
#include "lut_cache.h"
+#include <cmath>
-using namespace libdcp;
+using namespace dcp;
LUTCache<GammaLUT> GammaLUT::cache;
-GammaLUT::GammaLUT(int bits, float gamma)
- : LUT (bits, gamma)
+GammaLUT::GammaLUT (int bit_depth, float gamma, bool linearised)
+ : _bit_depth (bit_depth)
+ , _gamma (gamma)
+ , _linearised (linearised)
{
- int const bit_length = pow(2, bits);
- for (int i = 0; i < bit_length; ++i) {
- _lut[i] = pow(float(i) / (bit_length - 1), gamma);
+ _lut = new float[int(std::pow(2.0f, _bit_depth))];
+ int const bit_length = pow (2, _bit_depth);
+
+ if (_linearised) {
+ for (int i = 0; i < bit_length; ++i) {
+ float const p = static_cast<float> (i) / (bit_length - 1);
+ if (p > 0.04045) {
+ _lut[i] = pow ((p + 0.055) / 1.055, gamma);
+ } else {
+ _lut[i] = p / 12.92;
+ }
+ }
+ } else {
+ for (int i = 0; i < bit_length; ++i) {
+ _lut[i] = pow(float(i) / (bit_length - 1), gamma);
+ }
}
}
diff --git a/src/gamma_lut.h b/src/gamma_lut.h
index 32e4af02..76a63ccf 100644
--- a/src/gamma_lut.h
+++ b/src/gamma_lut.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -20,16 +20,42 @@
#ifndef LIBDCP_GAMMA_LUT_H
#define LIBDCP_GAMMA_LUT_H
-#include "lut.h"
#include "lut_cache.h"
-namespace libdcp {
+namespace dcp {
-class GammaLUT : public LUT
+class GammaLUT
{
public:
- GammaLUT (int bit_length, float gamma);
+ GammaLUT (int bit_depth, float gamma, bool linearised);
+
+ ~GammaLUT () {
+ delete[] _lut;
+ }
+
+ float const * lut () const {
+ return _lut;
+ }
+
+ int bit_depth () const {
+ return _bit_depth;
+ }
+
+ float gamma () const {
+ return _gamma;
+ }
+
+ bool linearised () const {
+ return _linearised;
+ }
+
static LUTCache<GammaLUT> cache;
+
+private:
+ float* _lut;
+ int _bit_depth;
+ float _gamma;
+ bool _linearised;
};
}
diff --git a/src/image.cc b/src/image.cc
index 24174fca..15ff24dc 100644
--- a/src/image.cc
+++ b/src/image.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -20,7 +20,7 @@
#include "image.h"
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
Image::Image (Size s)
: _size (s)
@@ -34,7 +34,7 @@ Image::Image (Image const & other)
}
-Image::Image (shared_ptr<const Image> other)
+Image::Image (boost::shared_ptr<const Image> other)
: _size (other->_size)
{
diff --git a/src/image.h b/src/image.h
index 8b7fee09..069534ea 100644
--- a/src/image.h
+++ b/src/image.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -19,7 +19,7 @@
#include "util.h"
-namespace libdcp {
+namespace dcp {
class Image
{
diff --git a/src/kdm.cc b/src/kdm.cc
index 4132b242..fe7fe393 100644
--- a/src/kdm.cc
+++ b/src/kdm.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,23 +17,27 @@
*/
-#include <iomanip>
-#include <algorithm>
-#include <boost/algorithm/string.hpp>
-#include <openssl/rsa.h>
-#include <openssl/pem.h>
-#include <openssl/err.h>
-#include <libcxml/cxml.h>
-#include "AS_DCP.h"
-#include "KM_util.h"
+/** @file src/kdm.cc
+ * @brief KDM and KDMKey classes.
+ */
+
#include "util.h"
#include "kdm.h"
#include "compose.hpp"
#include "exceptions.h"
#include "signer.h"
#include "cpl.h"
-#include "mxf_asset.h"
-#include "xml/kdm_smpte.h"
+#include "mxf.h"
+#include "kdm_smpte_xml.h"
+#include "AS_DCP.h"
+#include "KM_util.h"
+#include <libcxml/cxml.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <boost/algorithm/string.hpp>
+#include <iomanip>
+#include <algorithm>
using std::list;
using std::string;
@@ -43,7 +47,7 @@ using std::setw;
using std::setfill;
using std::cout;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key)
: _xml_kdm (new xml::DCinemaSecurityMessage (kdm))
@@ -87,7 +91,9 @@ KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key)
}
KDM::KDM (
- shared_ptr<const CPL> cpl, shared_ptr<const Signer> signer, shared_ptr<const Certificate> recipient_cert,
+ boost::shared_ptr<const CPL> cpl,
+ boost::shared_ptr<const Signer> signer,
+ boost::shared_ptr<const Certificate> recipient_cert,
boost::posix_time::ptime not_valid_before, boost::posix_time::ptime not_valid_after,
string annotation_text, string issue_date
)
@@ -108,7 +114,7 @@ KDM::KDM (
apu.recipient.x509_subject_name = recipient_cert->subject ();
apu.composition_playlist_id = "urn:uuid:" + cpl->id ();
// apu.content_authenticator = signer->certificates().leaf()->thumbprint ();
- apu.content_title_text = cpl->name ();
+ apu.content_title_text = cpl->content_title_text ();
apu.content_keys_not_valid_before = ptime_to_string (not_valid_before);
apu.content_keys_not_valid_after = ptime_to_string (not_valid_after);
apu.authorized_device_info.device_list_identifier = "urn:uuid:" + make_uuid ();
@@ -124,10 +130,10 @@ KDM::KDM (
*/
apu.authorized_device_info.device_list.push_back ("2jmj7l5rSw0yVb/vlWAYkK/YBwk=");
- list<shared_ptr<const Asset> > assets = cpl->assets ();
- for (list<shared_ptr<const Asset> >::iterator i = assets.begin(); i != assets.end(); ++i) {
+ list<shared_ptr<const Content> > content = cpl->content ();
+ for (list<shared_ptr<const Content> >::iterator i = content.begin(); i != content.end(); ++i) {
/* XXX: non-MXF assets? */
- shared_ptr<const MXFAsset> mxf = boost::dynamic_pointer_cast<const MXFAsset> (*i);
+ shared_ptr<const MXF> mxf = boost::dynamic_pointer_cast<const MXF> (*i);
if (mxf) {
apu.key_id_list.push_back (xml::TypedKeyId (mxf->key_type(), "urn:uuid:" + mxf->key_id()));
}
@@ -138,9 +144,9 @@ KDM::KDM (
/* AuthenticatedPrivate */
- for (list<shared_ptr<const Asset> >::iterator i = assets.begin(); i != assets.end(); ++i) {
+ for (list<shared_ptr<const Content> >::iterator i = content.begin(); i != content.end(); ++i) {
/* XXX: non-MXF assets? */
- shared_ptr<const MXFAsset> mxf = boost::dynamic_pointer_cast<const MXFAsset> (*i);
+ shared_ptr<const MXF> mxf = boost::dynamic_pointer_cast<const MXF> (*i);
if (mxf) {
KDMKey kkey (
signer, cpl->id (), mxf->key_type (), mxf->key_id (),
@@ -202,7 +208,13 @@ KDM::as_xml () const
}
KDMKey::KDMKey (
- shared_ptr<const Signer> signer, string cpl_id, string key_type, string key_id, boost::posix_time::ptime from, boost::posix_time::ptime until, Key key
+ boost::shared_ptr<const Signer> signer,
+ string cpl_id,
+ string key_type,
+ string key_id,
+ boost::posix_time::ptime from,
+ boost::posix_time::ptime until,
+ Key key
)
: _cpl_id (cpl_id)
, _key_type (key_type)
@@ -275,7 +287,7 @@ KDMKey::operator= (KDMKey const & other)
}
string
-KDMKey::encrypted_base64 (shared_ptr<const Certificate> recipient_cert) const
+KDMKey::encrypted_base64 (boost::shared_ptr<const Certificate> recipient_cert) const
{
assert (_key_type.length() == 4);
assert (_not_valid_before.length() == 25);
@@ -383,7 +395,7 @@ KDMKey::put_uuid (uint8_t ** d, string id) const
}
bool
-libdcp::operator== (libdcp::KDMKey const & a, libdcp::KDMKey const & b)
+dcp::operator== (dcp::KDMKey const & a, dcp::KDMKey const & b)
{
if (memcmp (a._signer_thumbprint, b._signer_thumbprint, 20) != 0) {
return false;
diff --git a/src/kdm.h b/src/kdm.h
index 4e897ca8..02395a72 100644
--- a/src/kdm.h
+++ b/src/kdm.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,21 +18,21 @@
*/
/** @file src/kdm.h
- * @brief Handling of Key Delivery Messages (KDMs).
+ * @brief KDM and KDMKey classes.
*/
#ifndef LIBDCP_KDM_H
#define LIBDCP_KDM_H
+#include "key.h"
+#include "metadata.h"
#include <boost/filesystem.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
-#include "key.h"
-#include "metadata.h"
class kdm_key_test;
-namespace libdcp {
+namespace dcp {
namespace xml {
class DCinemaSecurityMessage;
@@ -161,8 +161,8 @@ public:
* @param recipient_cert Certificate of the projector that this KDM is targeted at.
* @param not_valid_before Start of validity period.
* @param not_valid_after End of validity period.
- * @param annotation_text Text for the <AnnotationText> node.
- * @param issue_date Text for the <IssueDate> node.
+ * @param annotation_text Text for the &lt;AnnotationText&gt; node.
+ * @param issue_date Text for the &lt;IssueDate&gt; node.
*/
KDM (
boost::shared_ptr<const CPL> cpl, boost::shared_ptr<const Signer> signer, boost::shared_ptr<const Certificate> recipient_cert,
diff --git a/src/xml/kdm_smpte.h b/src/kdm_smpte_xml.h
index 32a297f8..70b7847e 100644
--- a/src/xml/kdm_smpte.h
+++ b/src/kdm_smpte_xml.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,7 +17,7 @@
*/
-/** @file src/xml/kdm_smpte.h
+/** @file src/kdm_smpte_xml.h
* @brief 1:1ish C++ representations of the XML schema for a SMPTE KDM.
*
* This file contains classes which map pretty-much 1:1 to the elements in a SMPTE KDM
@@ -29,19 +29,19 @@
* change very often.
*/
-#ifndef LIBDCP_XML_KDM_SMPTE_H
-#define LIBDCP_XML_KDM_SMPTE_H
+#ifndef LIBDCP_KDM_SMPTE_XML_H
+#define LIBDCP_KDM_SMPTE_XML_H
-#include <string>
-#include <list>
-#include <boost/optional.hpp>
-#include <boost/filesystem.hpp>
+#include "exceptions.h"
+#include <libcxml/cxml.h>
#include <libxml/parser.h>
#include <libxml++/libxml++.h>
-#include <libcxml/cxml.h>
-#include "../exceptions.h"
+#include <boost/optional.hpp>
+#include <boost/filesystem.hpp>
+#include <string>
+#include <list>
-namespace libdcp {
+namespace dcp {
namespace xml {
class Writer
diff --git a/src/key.cc b/src/key.cc
index 8cac04a3..43e59dfc 100644
--- a/src/key.cc
+++ b/src/key.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,19 +17,23 @@
*/
-#include <sstream>
-#include <string>
-#include <iomanip>
+/** @file src/key.cc
+ * @brief Key class.
+ */
+
+#include "key.h"
#include "AS_DCP.h"
#include "KM_prng.h"
#include "KM_util.h"
-#include "key.h"
+#include <sstream>
+#include <string>
+#include <iomanip>
using std::string;
using std::stringstream;
using std::setw;
using std::setfill;
-using namespace libdcp;
+using namespace dcp;
Key::Key ()
: _value (new uint8_t[ASDCP::KeyLen])
@@ -86,13 +90,13 @@ Key::hex () const
}
bool
-libdcp::operator== (Key const & a, Key const & b)
+dcp::operator== (Key const & a, Key const & b)
{
return memcmp (a.value(), b.value(), ASDCP::KeyLen) == 0;
}
bool
-libdcp::operator!= (Key const & a, Key const & b)
+dcp::operator!= (Key const & a, Key const & b)
{
return !(a == b);
}
diff --git a/src/key.h b/src/key.h
index d0286627..248a2a95 100644
--- a/src/key.h
+++ b/src/key.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,18 +18,19 @@
*/
/** @file src/key.h
- * @brief Class to hold a key for encrypting MXFs.
+ * @brief Key class.
*/
#ifndef LIBDCP_KEY_H
#define LIBDCP_KEY_H
#include <stdint.h>
+#include <string>
-namespace libdcp {
+namespace dcp {
/** @class Key
- * @brief A key for encrypting MXFs.
+ * @brief A key for decrypting/encrypting MXFs.
*/
class Key
{
diff --git a/src/rec709_linearised_gamma_lut.h b/src/load_font.cc
index af0158a5..707f4a0b 100644
--- a/src/rec709_linearised_gamma_lut.h
+++ b/src/load_font.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,16 +17,14 @@
*/
-#include "lut.h"
-#include "lut_cache.h"
+#include "load_font.h"
+#include <libcxml/cxml.h>
-namespace libdcp {
+using boost::shared_ptr;
+using namespace dcp;
-class Rec709LinearisedGammaLUT : public LUT
+LoadFont::LoadFont (boost::shared_ptr<const cxml::Node> node)
{
-public:
- Rec709LinearisedGammaLUT (int bit_length, float gamma);
- static LUTCache<Rec709LinearisedGammaLUT> cache;
-};
-
+ id = node->string_attribute ("Id");
+ uri = node->string_attribute ("URI");
}
diff --git a/src/srgb_linearised_gamma_lut.h b/src/load_font.h
index 34800c66..6319b1de 100644
--- a/src/srgb_linearised_gamma_lut.h
+++ b/src/load_font.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,16 +17,22 @@
*/
-#include "lut.h"
-#include "lut_cache.h"
+#include <boost/shared_ptr.hpp>
-namespace libdcp {
+namespace cxml {
+ class Node;
+}
-class SRGBLinearisedGammaLUT : public LUT
+namespace dcp {
+
+class LoadFont
{
public:
- SRGBLinearisedGammaLUT (int bit_length, float gamma);
- static LUTCache<SRGBLinearisedGammaLUT> cache;
+ LoadFont () {}
+ LoadFont (boost::shared_ptr<const cxml::Node> node);
+
+ std::string id;
+ std::string uri;
};
}
diff --git a/src/lut_cache.h b/src/lut_cache.h
index b60ee109..5c75fe6a 100644
--- a/src/lut_cache.h
+++ b/src/lut_cache.h
@@ -1,14 +1,34 @@
+/*
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
#ifndef LIBDCP_LUT_CACHE_H
#define LIBDCP_LUT_CACHE_H
#include <list>
#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
template<class T>
-class LUTCache
+class LUTCache : public boost::noncopyable
{
public:
- boost::shared_ptr<T> get (int bit_depth, float gamma)
+ boost::shared_ptr<T> get (int bit_depth, float gamma, bool linearised)
{
for (typename std::list<boost::shared_ptr<T> >::iterator i = _cache.begin(); i != _cache.end(); ++i) {
if ((*i)->bit_depth() == bit_depth && (*i)->gamma() == gamma) {
@@ -16,7 +36,7 @@ public:
}
}
- boost::shared_ptr<T> lut (new T (bit_depth, gamma));
+ boost::shared_ptr<T> lut (new T (bit_depth, gamma, linearised));
_cache.push_back (lut);
return lut;
}
diff --git a/src/metadata.cc b/src/metadata.cc
index acbc3b2e..e3382613 100644
--- a/src/metadata.cc
+++ b/src/metadata.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,20 +18,20 @@
*/
/** @file src/metadata.cc
- * @brief Metadata for writing to the DCP.
+ * @brief XMLMetadata and MXFMetadata classes.
*/
-#include <sstream>
-#include <iomanip>
-#include <time.h>
+#include "metadata.h"
+#include "util.h"
#ifdef LIBDCP_WINDOWS
#include <windows.h>
#endif
-#include "metadata.h"
-#include "util.h"
+#include <sstream>
+#include <iomanip>
+#include <time.h>
using namespace std;
-using namespace libdcp;
+using namespace dcp;
MXFMetadata::MXFMetadata ()
: company_name ("libdcp")
diff --git a/src/metadata.h b/src/metadata.h
index b4c0896d..b1fcdd8e 100644
--- a/src/metadata.h
+++ b/src/metadata.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -21,16 +21,19 @@
#define LIBDCP_METADATA_H
/** @file src/metadata.h
- * @brief Metadata for writing to the DCP.
+ * @brief XMLMetadata and MXFMetadata classes.
*/
#include <string>
class utc_offset_to_string_test;
-namespace libdcp
+namespace dcp
{
+/** @class MXFMetadata
+ * @brief Metadata that is written to a MXF file's header
+ */
class MXFMetadata
{
public:
@@ -41,6 +44,9 @@ public:
std::string product_version;
};
+/** @class XMLMetadata
+ * @brief Common metadata that is written to a few different XML files
+ */
class XMLMetadata
{
public:
diff --git a/src/mono_picture_asset.cc b/src/mono_picture_asset.cc
deleted file mode 100644
index 0ac48d37..00000000
--- a/src/mono_picture_asset.cc
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_writer.h"
-#include "AS_DCP.h"
-#include "KM_fileio.h"
-#include "exceptions.h"
-#include "mono_picture_frame.h"
-
-using std::string;
-using std::vector;
-using boost::shared_ptr;
-using boost::dynamic_pointer_cast;
-using boost::lexical_cast;
-using namespace libdcp;
-
-MonoPictureAsset::MonoPictureAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name)
- : PictureAsset (directory, mxf_name)
-{
-
-}
-
-void
-MonoPictureAsset::create (vector<boost::filesystem::path> const & files)
-{
- create (boost::bind (&MonoPictureAsset::path_from_list, this, _1, files));
-}
-
-void
-MonoPictureAsset::create (boost::function<boost::filesystem::path (int)> get_path)
-{
- ASDCP::JP2K::CodestreamParser j2k_parser;
- ASDCP::JP2K::FrameBuffer frame_buffer (4 * Kumu::Megabyte);
- Kumu::Result_t r = j2k_parser.OpenReadFrame (get_path(0).string().c_str(), frame_buffer);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open JPEG2000 file for reading", get_path(0), r));
- }
-
- ASDCP::JP2K::PictureDescriptor picture_desc;
- j2k_parser.FillPictureDescriptor (picture_desc);
- picture_desc.EditRate = ASDCP::Rational (_edit_rate, 1);
-
- ASDCP::WriterInfo writer_info;
- fill_writer_info (&writer_info);
-
- ASDCP::JP2K::MXFWriter mxf_writer;
- r = mxf_writer.OpenWrite (path().string().c_str(), writer_info, picture_desc, 16384, false);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for writing", path().string(), r));
- }
-
- for (int i = 0; i < _intrinsic_duration; ++i) {
-
- boost::filesystem::path const path = get_path (i);
-
- Kumu::Result_t r = j2k_parser.OpenReadFrame (path.string().c_str(), frame_buffer);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open JPEG2000 file for reading", path, r));
- }
-
- r = mxf_writer.WriteFrame (frame_buffer, _encryption_context, 0);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in writing video MXF", this->path().string(), r));
- }
-
- if (_progress) {
- (*_progress) (0.5 * float (i) / _intrinsic_duration);
- }
- }
-
- r = mxf_writer.Finalize();
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in finalising video MXF", path().string(), r));
- }
-}
-
-void
-MonoPictureAsset::read ()
-{
- ASDCP::JP2K::MXFReader reader;
- Kumu::Result_t r = reader.OpenRead (path().string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
- }
-
- ASDCP::JP2K::PictureDescriptor desc;
- if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
- boost::throw_exception (DCPReadError ("could not read video MXF information"));
- }
-
- _size.width = desc.StoredWidth;
- _size.height = desc.StoredHeight;
- _edit_rate = desc.EditRate.Numerator;
- assert (desc.EditRate.Denominator == 1);
- _intrinsic_duration = desc.ContainerDuration;
-}
-
-boost::filesystem::path
-MonoPictureAsset::path_from_list (int f, vector<boost::filesystem::path> const & files) const
-{
- return files[f];
-}
-
-shared_ptr<const MonoPictureFrame>
-MonoPictureAsset::get_frame (int n) const
-{
- return shared_ptr<const MonoPictureFrame> (new MonoPictureFrame (path(), n, _decryption_context));
-}
-
-bool
-MonoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
-{
- if (!MXFAsset::equals (other, opt, note)) {
- return false;
- }
-
- ASDCP::JP2K::MXFReader reader_A;
- Kumu::Result_t r = reader_A.OpenRead (path().string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
- }
-
- ASDCP::JP2K::MXFReader reader_B;
- r = reader_B.OpenRead (other->path().string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
- }
-
- ASDCP::JP2K::PictureDescriptor desc_A;
- if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) {
- boost::throw_exception (DCPReadError ("could not read video MXF information"));
- }
- ASDCP::JP2K::PictureDescriptor desc_B;
- if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) {
- boost::throw_exception (DCPReadError ("could not read video MXF information"));
- }
-
- if (!descriptor_equals (desc_A, desc_B, note)) {
- return false;
- }
-
- shared_ptr<const MonoPictureAsset> other_picture = dynamic_pointer_cast<const MonoPictureAsset> (other);
- assert (other_picture);
-
- for (int i = 0; i < _intrinsic_duration; ++i) {
- if (i >= other_picture->intrinsic_duration()) {
- return false;
- }
-
- note (PROGRESS, "Comparing video frame " + lexical_cast<string> (i) + " of " + lexical_cast<string> (_intrinsic_duration));
- shared_ptr<const MonoPictureFrame> frame_A = get_frame (i);
- shared_ptr<const MonoPictureFrame> frame_B = other_picture->get_frame (i);
-
- if (!frame_buffer_equals (
- i, opt, note,
- frame_A->j2k_data(), frame_A->j2k_size(),
- frame_B->j2k_data(), frame_B->j2k_size()
- )) {
- return false;
- }
- }
-
- return true;
-}
-
-shared_ptr<PictureAssetWriter>
-MonoPictureAsset::start_write (bool overwrite)
-{
- /* XXX: can't we use shared_ptr here? */
- return shared_ptr<MonoPictureAssetWriter> (new MonoPictureAssetWriter (this, overwrite));
-}
-
-string
-MonoPictureAsset::cpl_node_name () const
-{
- return "MainPicture";
-}
-
-int
-MonoPictureAsset::edit_rate_factor () const
-{
- return 1;
-}
diff --git a/src/mono_picture_asset.h b/src/mono_picture_asset.h
deleted file mode 100644
index ae2df4d2..00000000
--- a/src/mono_picture_asset.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LIBDCP_MONO_PICTURE_ASSET_H
-#define LIBDCP_MONO_PICTURE_ASSET_H
-
-#include "picture_asset.h"
-
-namespace libdcp {
-
-/** A 2D (monoscopic) picture asset */
-class MonoPictureAsset : public PictureAsset
-{
-public:
- MonoPictureAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name);
-
- void read ();
-
- /** The following parameters must be set up (if required) before calling this:
- * Interop mode (set_interop)
- * Edit rate (set_edit_rate)
- * MXF Metadata (set_metadata)
- */
- void create (std::vector<boost::filesystem::path> const & files);
-
- /** The following parameters must be set up (if required) before calling this:
- * Interop mode (set_interop)
- * Edit rate (set_edit_rate)
- * MXF Metadata (set_metadata)
- */
- void create (boost::function<boost::filesystem::path (int)> get_path);
-
- /** Start a progressive write to a MonoPictureAsset */
- boost::shared_ptr<PictureAssetWriter> start_write (bool);
-
- boost::shared_ptr<const MonoPictureFrame> get_frame (int n) const;
- bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
-
-private:
- boost::filesystem::path path_from_list (int f, std::vector<boost::filesystem::path> const & files) const;
- void construct (boost::function<boost::filesystem::path (int)>, bool, MXFMetadata const &);
- std::string cpl_node_name () const;
- int edit_rate_factor () const;
-};
-
-}
-
-#endif
diff --git a/src/mono_picture_frame.cc b/src/mono_picture_frame.cc
index 890967d1..c2f8abb7 100644
--- a/src/mono_picture_frame.cc
+++ b/src/mono_picture_frame.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,26 +17,30 @@
*/
-#include <openjpeg.h>
-#include "AS_DCP.h"
-#include "KM_fileio.h"
+/** @file src/mono_picture_frame.cc
+ * @brief MonoPictureFrame class.
+ */
+
#include "mono_picture_frame.h"
#include "exceptions.h"
#include "argb_frame.h"
-#include "lut.h"
-#include "util.h"
#include "gamma_lut.h"
+#include "util.h"
#include "rgb_xyz.h"
+#include "KM_fileio.h"
+#include "AS_DCP.h"
+#include <openjpeg.h>
#define DCI_GAMMA 2.6
using std::string;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
/** Make a picture frame from a 2D (monoscopic) asset.
* @param mxf_path Path to the asset's MXF file.
* @param n Frame within the asset, not taking EntryPoint into account.
+ * @param c Context for decryption, or 0.
*/
MonoPictureFrame::MonoPictureFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext* c)
{
@@ -54,17 +58,20 @@ MonoPictureFrame::MonoPictureFrame (boost::filesystem::path mxf_path, int n, ASD
}
}
+/** MonoPictureFrame destructor */
MonoPictureFrame::~MonoPictureFrame ()
{
delete _buffer;
}
+/** @return Pointer to JPEG2000 data */
uint8_t const *
MonoPictureFrame::j2k_data () const
{
return _buffer->RoData ();
}
+/** @return Size of JPEG2000 data in bytes */
int
MonoPictureFrame::j2k_size () const
{
@@ -74,17 +81,18 @@ MonoPictureFrame::j2k_size () const
/** @param reduce a factor by which to reduce the resolution
* of the image, expressed as a power of two (pass 0 for no
* reduction).
+ * @param srgb_gamma Reciprocal of output gamma to use after
+ * the conversion from XYZ to RGB.
*
* @return An ARGB representation of this frame. This is ARGB in the
* Cairo sense, so that each pixel takes up 4 bytes; the first byte
* is blue, second green, third red and fourth alpha (always 255).
- *
*/
shared_ptr<ARGBFrame>
MonoPictureFrame::argb_frame (int reduce, float srgb_gamma) const
{
return xyz_to_rgb (
decompress_j2k (const_cast<uint8_t*> (_buffer->RoData()), _buffer->Size(), reduce),
- GammaLUT::cache.get (12, DCI_GAMMA), GammaLUT::cache.get (12, 1 / srgb_gamma)
+ GammaLUT::cache.get (12, DCI_GAMMA, false), GammaLUT::cache.get (12, 1 / srgb_gamma, false)
);
}
diff --git a/src/mono_picture_frame.h b/src/mono_picture_frame.h
index 0eedfb95..cc6096cd 100644
--- a/src/mono_picture_frame.h
+++ b/src/mono_picture_frame.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,10 +17,16 @@
*/
+/** @file src/mono_picture_frame.h
+ * @brief MonoPictureFrame class.
+ */
+
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/filesystem.hpp>
#include <string>
#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include "types.h"
namespace ASDCP {
namespace JP2K {
@@ -29,12 +35,14 @@ namespace ASDCP {
class AESDecContext;
}
-namespace libdcp {
+namespace dcp {
class ARGBFrame;
-/** A single frame of a 2D (monoscopic) picture asset */
-class MonoPictureFrame
+/** @class MonoPictureFrame
+ * @brief A single frame of a 2D (monoscopic) picture asset.
+ */
+class MonoPictureFrame : public boost::noncopyable
{
public:
MonoPictureFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext *);
diff --git a/src/mono_picture_mxf.cc b/src/mono_picture_mxf.cc
new file mode 100644
index 00000000..4af24008
--- /dev/null
+++ b/src/mono_picture_mxf.cc
@@ -0,0 +1,137 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "mono_picture_mxf.h"
+#include "mono_picture_mxf_writer.h"
+#include "AS_DCP.h"
+#include "KM_fileio.h"
+#include "exceptions.h"
+#include "mono_picture_frame.h"
+#include "compose.hpp"
+
+using std::string;
+using std::vector;
+using boost::shared_ptr;
+using boost::dynamic_pointer_cast;
+using namespace dcp;
+
+MonoPictureMXF::MonoPictureMXF (boost::filesystem::path file)
+ : PictureMXF (file)
+{
+ ASDCP::JP2K::MXFReader reader;
+ Kumu::Result_t r = reader.OpenRead (file.string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r));
+ }
+
+ ASDCP::JP2K::PictureDescriptor desc;
+ if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
+ boost::throw_exception (DCPReadError ("could not read video MXF information"));
+ }
+
+ read_picture_descriptor (desc);
+
+ ASDCP::WriterInfo info;
+ if (ASDCP_FAILURE (reader.FillWriterInfo (info))) {
+ boost::throw_exception (DCPReadError ("could not read video MXF information"));
+ }
+
+ read_writer_info (info);
+}
+
+MonoPictureMXF::MonoPictureMXF (Fraction edit_rate)
+ : PictureMXF (edit_rate)
+{
+
+}
+
+shared_ptr<const MonoPictureFrame>
+MonoPictureMXF::get_frame (int n) const
+{
+ return shared_ptr<const MonoPictureFrame> (new MonoPictureFrame (_file, n, _decryption_context));
+}
+
+bool
+MonoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
+{
+ if (!MXF::equals (other, opt, note)) {
+ return false;
+ }
+
+ ASDCP::JP2K::MXFReader reader_A;
+ Kumu::Result_t r = reader_A.OpenRead (_file.string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", _file.string(), r));
+ }
+
+ ASDCP::JP2K::MXFReader reader_B;
+ r = reader_B.OpenRead (other->file().string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", other->file().string(), r));
+ }
+
+ ASDCP::JP2K::PictureDescriptor desc_A;
+ if (ASDCP_FAILURE (reader_A.FillPictureDescriptor (desc_A))) {
+ boost::throw_exception (DCPReadError ("could not read video MXF information"));
+ }
+ ASDCP::JP2K::PictureDescriptor desc_B;
+ if (ASDCP_FAILURE (reader_B.FillPictureDescriptor (desc_B))) {
+ boost::throw_exception (DCPReadError ("could not read video MXF information"));
+ }
+
+ if (!descriptor_equals (desc_A, desc_B, note)) {
+ return false;
+ }
+
+ shared_ptr<const MonoPictureMXF> other_picture = dynamic_pointer_cast<const MonoPictureMXF> (other);
+ assert (other_picture);
+
+ for (int i = 0; i < _intrinsic_duration; ++i) {
+ if (i >= other_picture->intrinsic_duration()) {
+ return false;
+ }
+
+ note (PROGRESS, String::compose ("Comparing video frame %1 of %2", i, _intrinsic_duration));
+ shared_ptr<const MonoPictureFrame> frame_A = get_frame (i);
+ shared_ptr<const MonoPictureFrame> frame_B = other_picture->get_frame (i);
+
+ if (!frame_buffer_equals (
+ i, opt, note,
+ frame_A->j2k_data(), frame_A->j2k_size(),
+ frame_B->j2k_data(), frame_B->j2k_size()
+ )) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+shared_ptr<PictureMXFWriter>
+MonoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
+{
+ /* XXX: can't we use shared_ptr here? */
+ return shared_ptr<MonoPictureMXFWriter> (new MonoPictureMXFWriter (this, file, standard, overwrite));
+}
+
+string
+MonoPictureMXF::cpl_node_name () const
+{
+ return "MainPicture";
+}
diff --git a/src/mono_picture_mxf.h b/src/mono_picture_mxf.h
new file mode 100644
index 00000000..c02a63c1
--- /dev/null
+++ b/src/mono_picture_mxf.h
@@ -0,0 +1,62 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_MONO_PICTURE_MXF_H
+#define LIBDCP_MONO_PICTURE_MXF_H
+
+#include "picture_mxf.h"
+
+namespace dcp {
+
+class MonoPictureMXFWriter;
+
+/** @class MonoPictureMXF
+ * @brief A 2D (monoscopic) picture MXF.
+ */
+class MonoPictureMXF : public PictureMXF
+{
+public:
+ /** Create a MonoPictureMXF by reading a file.
+ * @param file MXF file to read.
+ */
+ MonoPictureMXF (boost::filesystem::path file);
+
+ /** Create a MonoPictureMXF with a given edit rate.
+ * @param edit_rate Edit rate (i.e. frame rate) in frames per second.
+ */
+ MonoPictureMXF (Fraction edit_rate);
+
+ /** Start a progressive write to a MonoPictureMXF */
+ boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path, Standard standard, bool);
+
+ bool equals (
+ boost::shared_ptr<const Content> other,
+ EqualityOptions opt,
+ boost::function<void (NoteType, std::string)> note
+ ) const;
+
+ boost::shared_ptr<const MonoPictureFrame> get_frame (int n) const;
+
+private:
+ std::string cpl_node_name () const;
+};
+
+}
+
+#endif
diff --git a/src/mono_picture_asset_writer.cc b/src/mono_picture_mxf_writer.cc
index 6f0ba973..5cc424e1 100644
--- a/src/mono_picture_asset_writer.cc
+++ b/src/mono_picture_mxf_writer.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,22 +17,25 @@
*/
+/** @file src/mono_picture_mxf_writer.cc
+ * @brief MonoPictureMXFWriter class
+ */
+
#include "AS_DCP.h"
#include "KM_fileio.h"
-#include "mono_picture_asset_writer.h"
+#include "mono_picture_mxf_writer.h"
#include "exceptions.h"
-#include "picture_asset.h"
+#include "picture_mxf.h"
-#include "picture_asset_writer_common.cc"
+#include "picture_mxf_writer_common.cc"
using std::istream;
using std::ostream;
using std::string;
using boost::shared_ptr;
-using boost::lexical_cast;
-using namespace libdcp;
+using namespace dcp;
-struct MonoPictureAssetWriter::ASDCPState : public ASDCPStateBase
+struct MonoPictureMXFWriter::ASDCPState : public ASDCPStateBase
{
ASDCP::JP2K::MXFWriter mxf_writer;
};
@@ -40,21 +43,22 @@ struct MonoPictureAssetWriter::ASDCPState : public ASDCPStateBase
/** @param a Asset to write to. `a' must not be deleted while
* this writer class still exists, or bad things will happen.
*/
-MonoPictureAssetWriter::MonoPictureAssetWriter (PictureAsset* asset, bool overwrite)
- : PictureAssetWriter (asset, overwrite)
- , _state (new MonoPictureAssetWriter::ASDCPState)
+MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem::path file, Standard standard, bool overwrite)
+ : PictureMXFWriter (asset, file, standard, overwrite)
+ , _state (new MonoPictureMXFWriter::ASDCPState)
{
_state->encryption_context = asset->encryption_context ();
}
void
-MonoPictureAssetWriter::start (uint8_t* data, int size)
+MonoPictureMXFWriter::start (uint8_t* data, int size)
{
- libdcp::start (this, _state, _asset, data, size);
+ dcp::start (this, _state, _standard, _picture_mxf, data, size);
+ _picture_mxf->set_frame_rate (_picture_mxf->edit_rate());
}
FrameInfo
-MonoPictureAssetWriter::write (uint8_t* data, int size)
+MonoPictureMXFWriter::write (uint8_t* data, int size)
{
assert (!_finalized);
@@ -71,7 +75,7 @@ MonoPictureAssetWriter::write (uint8_t* data, int size)
string hash;
ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0, &hash);
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string(), r));
+ boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r));
}
++_frames_written;
@@ -79,31 +83,27 @@ MonoPictureAssetWriter::write (uint8_t* data, int size)
}
void
-MonoPictureAssetWriter::fake_write (int size)
+MonoPictureMXFWriter::fake_write (int size)
{
assert (_started);
assert (!_finalized);
Kumu::Result_t r = _state->mxf_writer.FakeWriteFrame (size);
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string(), r));
+ boost::throw_exception (MXFFileError ("error in writing video MXF", _mxf->file().string(), r));
}
++_frames_written;
}
void
-MonoPictureAssetWriter::finalize ()
+MonoPictureMXFWriter::finalize ()
{
- assert (!_finalized);
-
Kumu::Result_t r = _state->mxf_writer.Finalize();
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in finalizing video MXF", _asset->path().string(), r));
+ boost::throw_exception (MXFFileError ("error in finalizing video MXF", _mxf->file().string(), r));
}
- _finalized = true;
- _asset->set_intrinsic_duration (_frames_written);
- _asset->set_duration (_frames_written);
+ PictureMXFWriter::finalize ();
}
diff --git a/src/mono_picture_asset_writer.h b/src/mono_picture_mxf_writer.h
index e3922623..065171c2 100644
--- a/src/mono_picture_asset_writer.h
+++ b/src/mono_picture_mxf_writer.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,26 +17,33 @@
*/
+/** @file src/mono_picture_mxf_writer.h
+ * @brief MonoPictureMXFWriter class
+ */
+
+#ifndef LIBDCP_MONO_PICTURE_MXF_WRITER_H
+#define LIBDCP_MONO_PICTURE_MXF_WRITER_H
+
+#include "picture_mxf_writer.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
#include <stdint.h>
#include <string>
#include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include "picture_asset_writer.h"
-namespace libdcp {
+namespace dcp {
-/** A helper class for writing to MonoPictureAssets progressively (i.e. writing frame-by-frame,
- * rather than giving libdcp all the frames in one go).
+/** @class MonoPictureMXFWriter
+ * @brief A helper class for writing to MonoPictureMXFs
*
- * Objects of this class can only be created with MonoPictureAsset::start_write().
+ * Objects of this class can only be created with MonoPictureMXF::start_write().
*
* Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image
* (a verbatim .j2c file). finalize() must be called after the last frame has been written.
* The action of finalize() can't be done in MonoPictureAssetWriter's destructor as it may
* throw an exception.
*/
-class MonoPictureAssetWriter : public PictureAssetWriter
+class MonoPictureMXFWriter : public PictureMXFWriter
{
public:
FrameInfo write (uint8_t *, int);
@@ -44,9 +51,9 @@ public:
void finalize ();
private:
- friend class MonoPictureAsset;
+ friend class MonoPictureMXF;
- MonoPictureAssetWriter (PictureAsset *, bool);
+ MonoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard standard, bool);
void start (uint8_t *, int);
/* do this with an opaque pointer so we don't have to include
@@ -58,3 +65,5 @@ private:
};
}
+
+#endif
diff --git a/src/mxf_asset.cc b/src/mxf.cc
index c2428a3c..e1ed9650 100644
--- a/src/mxf_asset.cc
+++ b/src/mxf.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -21,18 +21,18 @@
* @brief Parent class for assets of DCPs made up of MXF files.
*/
-#include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libxml++/nodes/element.h>
#include "AS_DCP.h"
#include "KM_prng.h"
#include "KM_util.h"
-#include "mxf_asset.h"
+#include "mxf.h"
#include "util.h"
#include "metadata.h"
#include "exceptions.h"
#include "kdm.h"
+#include "compose.hpp"
+#include <libxml++/nodes/element.h>
+#include <boost/filesystem.hpp>
+#include <iostream>
using std::string;
using std::list;
@@ -40,38 +40,44 @@ using std::pair;
using boost::shared_ptr;
using boost::lexical_cast;
using boost::dynamic_pointer_cast;
-using namespace libdcp;
+using namespace dcp;
+
+MXF::MXF (Fraction edit_rate)
+ : Content (edit_rate)
+ , _encryption_context (0)
+ , _decryption_context (0)
+{
-MXFAsset::MXFAsset (boost::filesystem::path directory, boost::filesystem::path file_name)
- : Asset (directory, file_name)
- , _progress (0)
+}
+
+MXF::MXF (boost::filesystem::path file)
+ : Content (file)
, _encryption_context (0)
, _decryption_context (0)
- , _interop (false)
{
}
-MXFAsset::~MXFAsset ()
+MXF::~MXF ()
{
delete _encryption_context;
delete _decryption_context;
}
void
-MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info)
+MXF::fill_writer_info (ASDCP::WriterInfo* writer_info, Standard standard)
{
writer_info->ProductVersion = _metadata.product_version;
writer_info->CompanyName = _metadata.company_name;
writer_info->ProductName = _metadata.product_name.c_str();
- if (_interop) {
+ if (standard == INTEROP) {
writer_info->LabelSetType = ASDCP::LS_MXF_INTEROP;
} else {
writer_info->LabelSetType = ASDCP::LS_MXF_SMPTE;
}
unsigned int c;
- Kumu::hex2bin (_uuid.c_str(), writer_info->AssetUUID, Kumu::UUID_Length, &c);
+ Kumu::hex2bin (_id.c_str(), writer_info->AssetUUID, Kumu::UUID_Length, &c);
assert (c == Kumu::UUID_Length);
if (_key) {
@@ -85,19 +91,19 @@ MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info)
}
bool
-MXFAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
+MXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
{
- if (!Asset::equals (other, opt, note)) {
+ if (!Content::equals (other, opt, note)) {
return false;
}
- shared_ptr<const MXFAsset> other_mxf = dynamic_pointer_cast<const MXFAsset> (other);
+ shared_ptr<const MXF> other_mxf = dynamic_pointer_cast<const MXF> (other);
if (!other_mxf) {
note (ERROR, "comparing an MXF asset with a non-MXF asset");
return false;
}
- if (_file_name != other_mxf->_file_name) {
+ if (_file != other_mxf->file ()) {
note (ERROR, "MXF names differ");
if (!opt.mxf_names_can_differ) {
return false;
@@ -107,27 +113,13 @@ MXFAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, boost::fun
return true;
}
+/** Set the (private) key that will be used to encrypt or decrypt this MXF's content.
+ * This is the top-secret key that is distributed (itself encrypted) to cinemas
+ * via Key Delivery Messages (KDMs).
+ * @param key Key to use.
+ */
void
-MXFAsset::write_to_cpl (xmlpp::Element* node) const
-{
- pair<string, string> const attr = cpl_node_attribute ();
- xmlpp::Element* a = node->add_child (cpl_node_name ());
- if (!attr.first.empty ()) {
- a->set_attribute (attr.first, attr.second);
- }
- a->add_child ("Id")->add_child_text ("urn:uuid:" + _uuid);
- a->add_child ("AnnotationText")->add_child_text (_file_name.string ());
- a->add_child ("EditRate")->add_child_text (lexical_cast<string> (_edit_rate) + " 1");
- a->add_child ("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration));
- a->add_child ("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point));
- a->add_child ("Duration")->add_child_text (lexical_cast<string> (_duration));
- if (!_key_id.empty ()) {
- a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id);
- }
-}
-
-void
-MXFAsset::set_key (Key key)
+MXF::set_key (Key key)
{
_key = key;
@@ -153,3 +145,24 @@ MXFAsset::set_key (Key key)
throw MiscError ("could not set up CBC initialization vector");
}
}
+
+void
+MXF::read_writer_info (ASDCP::WriterInfo const & info)
+{
+ char buffer[64];
+ Kumu::bin2UUIDhex (info.AssetUUID, 16, buffer, 64);
+ _id = buffer;
+}
+
+string
+MXF::pkl_type (Standard standard) const
+{
+ switch (standard) {
+ case INTEROP:
+ return String::compose ("application/x-smpte-mxf;asdcpKind=%1", asdcp_kind ());
+ case SMPTE:
+ return "application/x-smpte-mxf";
+ default:
+ assert (false);
+ }
+}
diff --git a/src/mxf_asset.h b/src/mxf.h
index 4eafdcba..c5ecd1b7 100644
--- a/src/mxf_asset.h
+++ b/src/mxf.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,13 +17,13 @@
*/
-#ifndef LIBDCP_MXF_ASSET_H
-#define LIBDCP_MXF_ASSET_H
+#ifndef LIBDCP_MXF_H
+#define LIBDCP_MXF_H
-#include <boost/signals2.hpp>
-#include "asset.h"
+#include "content.h"
#include "key.h"
#include "metadata.h"
+#include <boost/signals2.hpp>
namespace ASDCP {
class AESEncContext;
@@ -34,93 +34,88 @@ namespace ASDCP {
#undef Key
#undef set_key
-namespace libdcp
+namespace dcp
{
class MXFMetadata;
-/** @brief Parent class for assets which have MXF files */
-class MXFAsset : public Asset
+/** @class MXF
+ * @brief Parent class for classes which represent MXF files.
+ */
+class MXF : public Content
{
public:
- /** Construct an MXFAsset.
- * This class will not write anything to disk in this constructor, but subclasses may.
- *
- * @param directory Directory where MXF file is.
- * @param file_name Name of MXF file.
- */
- MXFAsset (boost::filesystem::path directory, boost::filesystem::path file_name);
-
- ~MXFAsset ();
+ MXF (Fraction edit_rate);
+ MXF (boost::filesystem::path file);
+ ~MXF ();
- virtual bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
- virtual void write_to_cpl (xmlpp::Element *) const;
+ /** @return the 4-character key type for this MXF (MDIK, MDAK, etc.) */
virtual std::string key_type () const = 0;
+ bool equals (
+ boost::shared_ptr<const Content> other,
+ EqualityOptions opt,
+ boost::function<void (NoteType, std::string)> note
+ ) const;
+
/** Fill in a ADSCP::WriteInfo struct.
* @param w struct to fill in.
+ * @param standard INTEROP or SMPTE.
*/
- void fill_writer_info (ASDCP::WriterInfo* w);
-
- void set_progress (boost::signals2::signal<void (float)>* progress) {
- _progress = progress;
- }
+ void fill_writer_info (ASDCP::WriterInfo* w, Standard standard);
+ /** @return true if the data is encrypted */
bool encrypted () const {
return !_key_id.empty ();
}
+ /** Set the ID of the key that is used for encryption/decryption.
+ * @param i key ID.
+ */
void set_key_id (std::string i) {
_key_id = i;
}
+ /** @return the ID of the key used for encryption/decryption, or an empty string */
std::string key_id () const {
return _key_id;
}
-
+
void set_key (Key);
+ /** @return encryption/decryption key, if one has been set */
boost::optional<Key> key () const {
return _key;
}
+ /** @return encryption context, set up with any key that has been passed to set_key() */
ASDCP::AESEncContext* encryption_context () const {
return _encryption_context;
}
+ /** Set the metadata that is written to the MXF file.
+ * @param m Metadata.
+ */
void set_metadata (MXFMetadata m) {
_metadata = m;
}
+ /** @return metadata from the MXF file */
MXFMetadata metadata () const {
return _metadata;
}
- /** Set whether or not the asset should be written in Interop mode.
- * @param i true to use interop.
- */
- void set_interop (bool i) {
- _interop = i;
- }
-
- bool interop () const {
- return _interop;
- }
-
protected:
- virtual std::string cpl_node_name () const = 0;
- virtual std::pair<std::string, std::string> cpl_node_attribute () const {
- return std::make_pair ("", "");
- }
+ std::string pkl_type (Standard standard) const;
+ void read_writer_info (ASDCP::WriterInfo const &);
- /** Signal to emit to report progress, or 0 */
- boost::signals2::signal<void (float)>* _progress;
ASDCP::AESEncContext* _encryption_context;
ASDCP::AESDecContext* _decryption_context;
+ /** ID of the key used for encryption/decryption, or an empty string */
std::string _key_id;
+ /** Key used for encryption/decryption, if there is one */
boost::optional<Key> _key;
MXFMetadata _metadata;
- bool _interop;
};
}
diff --git a/src/mxf_writer.cc b/src/mxf_writer.cc
new file mode 100644
index 00000000..374e6590
--- /dev/null
+++ b/src/mxf_writer.cc
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/mxf_writer.h
+ * @brief MXFWriter class.
+ */
+
+#include "mxf_writer.h"
+#include "mxf.h"
+
+using namespace dcp;
+
+/** Create an MXFWriter.
+ * @param mxf MXF that we are writing.
+ * @param file File to write to.
+ */
+MXFWriter::MXFWriter (MXF* mxf, boost::filesystem::path file)
+ : _mxf (mxf)
+ , _file (file)
+ , _frames_written (0)
+ , _finalized (false)
+{
+ mxf->set_file (file);
+}
+
+MXFWriter::~MXFWriter ()
+{
+ assert (_finalized);
+}
+
+void
+MXFWriter::finalize ()
+{
+ assert (!_finalized);
+ _finalized = true;
+ _mxf->_intrinsic_duration = _frames_written;
+}
diff --git a/src/mxf_writer.h b/src/mxf_writer.h
new file mode 100644
index 00000000..b4e20f33
--- /dev/null
+++ b/src/mxf_writer.h
@@ -0,0 +1,62 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/mxf_writer.h
+ * @brief MXFWriter class.
+ */
+
+#ifndef LIBDCP_MXF_WRITER_H
+#define LIBDCP_MXF_WRITER_H
+
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class MXF;
+
+/** @class MXFWriter
+ * @brief Parent class for classes which can write MXF files.
+ *
+ * The MXFWriter lasts for the duration of the write and is then discarded.
+ * They can only be created by calling start_write() on an MXF object.
+ */
+class MXFWriter : public boost::noncopyable
+{
+public:
+ virtual ~MXFWriter ();
+ virtual void finalize ();
+
+protected:
+ MXFWriter (MXF* mxf, boost::filesystem::path file);
+
+ /** MXF that we are writing */
+ MXF* _mxf;
+ /** File that we are writing to */
+ boost::filesystem::path _file;
+ /** Number of `frames' written so far; the definition of a frame
+ * varies depending on the subclass.
+ */
+ int64_t _frames_written;
+ /** true if finalize() has been called on this object */
+ bool _finalized;
+};
+
+}
+
+#endif
diff --git a/src/object.cc b/src/object.cc
new file mode 100644
index 00000000..315e501a
--- /dev/null
+++ b/src/object.cc
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/object.cc
+ * @brief Object class.
+ */
+
+#include "object.h"
+#include "util.h"
+
+using std::string;
+using namespace dcp;
+
+/** Create an Object with a random ID. */
+Object::Object ()
+ : _id (make_uuid ())
+{
+
+}
+
+/** Create an Object with a given ID.
+ * @param id ID to use.
+ */
+Object::Object (string id)
+ : _id (id)
+{
+
+}
diff --git a/src/srgb_linearised_gamma_lut.cc b/src/object.h
index 0d3650f4..82598c58 100644
--- a/src/srgb_linearised_gamma_lut.cc
+++ b/src/object.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,22 +17,38 @@
*/
-#include "srgb_linearised_gamma_lut.h"
+/** @file src/object.h
+ * @brief Object class.
+ */
-using namespace libdcp;
+#ifndef LIBDCP_OBJECT_H
+#define LIBDCP_OBJECT_H
-LUTCache<SRGBLinearisedGammaLUT> SRGBLinearisedGammaLUT::cache;
+#include <boost/noncopyable.hpp>
+#include <string>
-SRGBLinearisedGammaLUT::SRGBLinearisedGammaLUT (int bits, float gamma)
- : LUT (bits, gamma)
+namespace dcp {
+
+/** @class Object
+ * @brief Some part of a DCP that has a UUID.
+ */
+class Object : public boost::noncopyable
{
- int const bit_length = pow (2, bits);
- for (int i = 0; i < bit_length; ++i) {
- float const p = static_cast<float> (i) / (bit_length - 1);
- if (p > 0.04045) {
- _lut[i] = pow ((p + 0.055) / 1.055, gamma);
- } else {
- _lut[i] = p / 12.92;
- }
+public:
+ Object ();
+ Object (std::string id);
+ virtual ~Object () {}
+
+ /** @return ID */
+ std::string id () const {
+ return _id;
}
+
+protected:
+ /** ID */
+ std::string _id;
+};
+
}
+
+#endif
diff --git a/src/parse/asset_map.cc b/src/parse/asset_map.cc
deleted file mode 100644
index 484c2710..00000000
--- a/src/parse/asset_map.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/asset_map.cc
- * @brief Classes used to parse a AssetMap.
- */
-
-#include <boost/algorithm/string.hpp>
-#include "asset_map.h"
-#include "../util.h"
-#include "../xml.h"
-
-using std::string;
-using std::list;
-using boost::shared_ptr;
-using namespace libdcp::parse;
-
-AssetMap::AssetMap (string file)
-{
- cxml::Document f ("AssetMap");
- f.read_file (file);
-
- id = f.string_child ("Id");
- creator = f.string_child ("Creator");
- volume_count = f.number_child<int64_t> ("VolumeCount");
- issue_date = f.string_child ("IssueDate");
- issuer = f.string_child ("Issuer");
- assets = type_grand_children<AssetMapAsset> (f, "AssetList", "Asset");
-}
-
-AssetMapAsset::AssetMapAsset (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- packing_list = node->optional_string_child ("PackingList").get_value_or ("");
- chunks = type_grand_children<Chunk> (node, "ChunkList", "Chunk");
-}
-
-Chunk::Chunk (shared_ptr<const cxml::Node> node)
-{
- path = node->string_child ("Path");
-
- string const prefix = "file://";
-
- if (boost::algorithm::starts_with (path, prefix)) {
- path = path.substr (prefix.length());
- }
-
- volume_index = node->optional_number_child<int64_t> ("VolumeIndex").get_value_or (0);
- offset = node->optional_number_child<int64_t> ("Offset").get_value_or (0);
- length = node->optional_number_child<int64_t> ("Length").get_value_or (0);
-}
-
-shared_ptr<AssetMapAsset>
-AssetMap::asset_from_id (string id) const
-{
- for (list<shared_ptr<AssetMapAsset> >::const_iterator i = assets.begin (); i != assets.end(); ++i) {
- if ((*i)->id == id) {
- return *i;
- }
- }
-
- return shared_ptr<AssetMapAsset> ();
-}
diff --git a/src/parse/asset_map.h b/src/parse/asset_map.h
deleted file mode 100644
index af3e8918..00000000
--- a/src/parse/asset_map.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/asset_map.h
- * @brief Classes used to parse a AssetMap.
- */
-
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include <libcxml/cxml.h>
-
-namespace libdcp {
-
-namespace parse {
-
-/** @class Chunk
- * @brief A simple parser for and representation of a \<Chunk\> node within an asset map.
- */
-class Chunk
-{
-public:
- Chunk ();
- Chunk (boost::shared_ptr<const cxml::Node> node);
-
- std::string path;
- int64_t volume_index;
- int64_t offset;
- int64_t length;
-};
-
-/** @class AssetMapAsset
- * @brief A simple parser for and representation of an \<AssetMap\> node within an asset map.
- */
-class AssetMapAsset
-{
-public:
- AssetMapAsset ();
- AssetMapAsset (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string packing_list;
- std::list<boost::shared_ptr<Chunk> > chunks;
-};
-
-/** @class AssetMap
- * @brief A simple parser for and representation of an asset map file.
- */
-class AssetMap
-{
-public:
- AssetMap (std::string file);
-
- boost::shared_ptr<AssetMapAsset> asset_from_id (std::string id) const;
-
- std::string id;
- std::string creator;
- int64_t volume_count;
- std::string issue_date;
- std::string issuer;
- std::list<boost::shared_ptr<AssetMapAsset> > assets;
-};
-
-}
-
-}
diff --git a/src/parse/cpl.cc b/src/parse/cpl.cc
deleted file mode 100644
index f6ce434c..00000000
--- a/src/parse/cpl.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/cpl_file.cc
- * @brief Classes used to parse a CPL.
- */
-
-#include <iostream>
-#include "cpl.h"
-#include "../xml.h"
-#include "../util.h"
-
-using std::string;
-using std::bad_cast;
-using boost::shared_ptr;
-using namespace libdcp::parse;
-
-CPL::CPL (string file)
-{
- cxml::Document f ("CompositionPlaylist");
- f.read_file (file);
-
- id = f.string_child ("Id");
- annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
- issue_date = f.string_child ("IssueDate");
- creator = f.optional_string_child ("Creator").get_value_or ("");
- content_title_text = f.string_child ("ContentTitleText");
- content_kind = content_kind_from_string (f.string_child ("ContentKind"));
- content_version = optional_type_child<ContentVersion> (f, "ContentVersion");
- f.ignore_child ("RatingList");
- reels = type_grand_children<Reel> (f, "ReelList", "Reel");
-
- f.ignore_child ("Issuer");
- f.ignore_child ("Signer");
- f.ignore_child ("Signature");
-
- f.done ();
-}
-
-ContentVersion::ContentVersion (shared_ptr<const cxml::Node> node)
-{
- id = node->optional_string_child ("Id").get_value_or ("");
- label_text = node->string_child ("LabelText");
- node->done ();
-}
-
-Reel::Reel (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- asset_list = type_child<CPLAssetList> (node, "AssetList");
-
- node->ignore_child ("AnnotationText");
- node->done ();
-}
-
-CPLAssetList::CPLAssetList (shared_ptr<const cxml::Node> node)
-{
- main_picture = optional_type_child<MainPicture> (node, "MainPicture");
- main_stereoscopic_picture = optional_type_child<MainStereoscopicPicture> (node, "MainStereoscopicPicture");
- main_sound = optional_type_child<MainSound> (node, "MainSound");
- main_subtitle = optional_type_child<MainSubtitle> (node, "MainSubtitle");
-
- node->done ();
-}
-
-MainPicture::MainPicture (shared_ptr<const cxml::Node> node)
- : Picture (node)
-{
-
-}
-
-MainStereoscopicPicture::MainStereoscopicPicture (shared_ptr<const cxml::Node> node)
- : Picture (node)
-{
-
-}
-
-Picture::Picture (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- edit_rate = Fraction (node->string_child ("EditRate"));
- intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
- entry_point = node->number_child<int64_t> ("EntryPoint");
- duration = node->number_child<int64_t> ("Duration");
- frame_rate = Fraction (node->string_child ("FrameRate"));
- try {
- screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio"));
- } catch (XMLError& e) {
- /* Maybe it's not a fraction */
- }
- try {
- float f = node->number_child<float> ("ScreenAspectRatio");
- screen_aspect_ratio = Fraction (f * 1000, 1000);
- } catch (bad_cast& e) {
-
- }
-
- key_id = node->optional_string_child ("KeyId").get_value_or ("");
-
- node->ignore_child ("Hash");
-
- node->done ();
-}
-
-MainSound::MainSound (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- edit_rate = Fraction (node->string_child ("EditRate"));
- intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
- entry_point = node->number_child<int64_t> ("EntryPoint");
- duration = node->number_child<int64_t> ("Duration");
- key_id = node->optional_string_child ("KeyId").get_value_or ("");
-
- node->ignore_child ("Hash");
- node->ignore_child ("Language");
-
- node->done ();
-}
-
-MainSubtitle::MainSubtitle (shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- edit_rate = Fraction (node->string_child ("EditRate"));
- intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
- entry_point = node->number_child<int64_t> ("EntryPoint");
- duration = node->number_child<int64_t> ("Duration");
-
- node->ignore_child ("Hash");
- node->ignore_child ("Language");
-
- node->done ();
-}
diff --git a/src/parse/cpl.h b/src/parse/cpl.h
deleted file mode 100644
index 04bf9351..00000000
--- a/src/parse/cpl.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/parse/cpl.h
- * @brief Classes used to parse a CPL.
- */
-
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include <libcxml/cxml.h>
-#include "../types.h"
-
-namespace libdcp {
-
-namespace parse {
-
-/** @brief A simple representation of a CPL \<Picture\> node */
-class Picture
-{
-public:
- Picture () {}
- Picture (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string annotation_text;
- Fraction edit_rate;
- /** Duration of the whole thing */
- int64_t intrinsic_duration;
- /** Start point in frames */
- int64_t entry_point;
- /** Duration that will actually play */
- int64_t duration;
- Fraction frame_rate;
- Fraction screen_aspect_ratio;
- std::string key_id;
-};
-
-
-/** @brief A simple parser for and representation of a CPL \<MainPicture\> node */
-class MainPicture : public Picture
-{
-public:
- MainPicture () {}
- MainPicture (boost::shared_ptr<const cxml::Node> node);
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainStereoscopicPicture\> node */
-class MainStereoscopicPicture : public Picture
-{
-public:
- MainStereoscopicPicture () {}
- MainStereoscopicPicture (boost::shared_ptr<const cxml::Node> node);
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainSound\> node */
-class MainSound
-{
-public:
- MainSound () {}
- MainSound (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string annotation_text;
- Fraction edit_rate;
- int64_t intrinsic_duration;
- int64_t entry_point;
- int64_t duration;
- std::string key_id;
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainSubtitle\> node */
-class MainSubtitle
-{
-public:
- MainSubtitle () {}
- MainSubtitle (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string annotation_text;
- Fraction edit_rate;
- int64_t intrinsic_duration;
- int64_t entry_point;
- int64_t duration;
-};
-
-/** @brief A simple parser for and representation of a CPL \<AssetList\> node */
-class CPLAssetList
-{
-public:
- CPLAssetList () {}
- CPLAssetList (boost::shared_ptr<const cxml::Node> node);
-
- boost::shared_ptr<MainPicture> main_picture;
- boost::shared_ptr<MainStereoscopicPicture> main_stereoscopic_picture;
- boost::shared_ptr<MainSound> main_sound;
- boost::shared_ptr<MainSubtitle> main_subtitle;
-};
-
-/** @brief A simple parser for and representation of a CPL \<Reel\> node */
-class Reel
-{
-public:
- Reel () {}
- Reel (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- boost::shared_ptr<CPLAssetList> asset_list;
-};
-
-
-/** @brief A simple parser for and representation of a CPL \<ContentVersion\> node */
-class ContentVersion
-{
-public:
- ContentVersion () {}
- ContentVersion (boost::shared_ptr<const cxml::Node> node);
-
- std::string id;
- std::string label_text;
-};
-
-/** @class CPL
- * @brief Class to parse a CPL
- *
- * This class is used to parse XML CPL files. It is rarely necessary
- * for the caller to use it outside libdcp.
- */
-class CPL
-{
-public:
- /** Parse a CPL XML file into our member variables */
- CPL (std::string file);
-
- std::string id;
- std::string annotation_text;
- std::string issue_date;
- std::string creator;
- std::string content_title_text;
- ContentKind content_kind;
- boost::shared_ptr<ContentVersion> content_version;
- std::list<boost::shared_ptr<Reel> > reels;
-};
-
-}
-
-}
-
diff --git a/src/parse/pkl.cc b/src/parse/pkl.cc
deleted file mode 100644
index bbf070ae..00000000
--- a/src/parse/pkl.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/pkl_file.cc
- * @brief Classes used to parse a PKL.
- */
-
-#include <iostream>
-#include "pkl.h"
-
-using namespace std;
-using namespace boost;
-using namespace libdcp::parse;
-
-PKL::PKL (string file)
-{
- cxml::Document f ("PackingList");
- f.read_file (file);
-
- id = f.string_child ("Id");
- annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
- issue_date = f.string_child ("IssueDate");
- issuer = f.string_child ("Issuer");
- creator = f.string_child ("Creator");
- assets = type_grand_children<PKLAsset> (f, "AssetList", "Asset");
-}
-
-PKLAsset::PKLAsset (boost::shared_ptr<const cxml::Node> node)
-{
- id = node->string_child ("Id");
- annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
- hash = node->string_child ("Hash");
- size = node->number_child<int64_t> ("Size");
- type = node->string_child ("Type");
- original_file_name = node->optional_string_child ("OriginalFileName").get_value_or ("");
-}
diff --git a/src/picture_asset.cc b/src/picture_mxf.cc
index b2eecee5..4a8e477b 100644
--- a/src/picture_asset.cc
+++ b/src/picture_mxf.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,25 +17,21 @@
*/
-/** @file src/picture_asset.cc
- * @brief An asset made up of JPEG2000 files
- */
-
+#include "picture_mxf.h"
+#include "util.h"
+#include "exceptions.h"
+#include "xyz_frame.h"
+#include "picture_mxf_writer.h"
+#include "compose.hpp"
+#include "AS_DCP.h"
+#include "KM_fileio.h"
+#include <libxml++/nodes/element.h>
+#include <openjpeg.h>
+#include <boost/filesystem.hpp>
#include <list>
#include <stdexcept>
#include <iostream>
#include <sstream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <openjpeg.h>
-#include <libxml++/nodes/element.h>
-#include "AS_DCP.h"
-#include "KM_fileio.h"
-#include "picture_asset.h"
-#include "util.h"
-#include "exceptions.h"
-#include "xyz_frame.h"
-#include "picture_asset_writer.h"
using std::string;
using std::ostream;
@@ -48,41 +44,33 @@ using std::make_pair;
using std::istream;
using std::cout;
using boost::shared_ptr;
-using boost::dynamic_pointer_cast;
-using boost::lexical_cast;
-using namespace libdcp;
+using namespace dcp;
-PictureAsset::PictureAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name)
- : MXFAsset (directory, mxf_name)
+PictureMXF::PictureMXF (boost::filesystem::path file)
+ : MXF (file)
{
}
-void
-PictureAsset::write_to_cpl (xmlpp::Element* node) const
+PictureMXF::PictureMXF (Fraction edit_rate)
+ : MXF (edit_rate)
{
- MXFAsset::write_to_cpl (node);
-
- xmlpp::Node::NodeList c = node->get_children ();
- xmlpp::Node::NodeList::iterator i = c.begin();
- while (i != c.end() && (*i)->get_name() != cpl_node_name ()) {
- ++i;
- }
- assert (i != c.end ());
+}
- (*i)->add_child ("FrameRate")->add_child_text (lexical_cast<string> (_edit_rate * edit_rate_factor ()) + " 1");
- if (_interop) {
- stringstream s;
- s << std::fixed << std::setprecision (2) << (float (_size.width) / _size.height);
- (*i)->add_child ("ScreenAspectRatio")->add_child_text (s.str ());
- } else {
- (*i)->add_child ("ScreenAspectRatio")->add_child_text (lexical_cast<string> (_size.width) + " " + lexical_cast<string> (_size.height));
- }
+void
+PictureMXF::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc)
+{
+ _size.width = desc.StoredWidth;
+ _size.height = desc.StoredHeight;
+ _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator);
+ _intrinsic_duration = desc.ContainerDuration;
+ _frame_rate = Fraction (desc.SampleRate.Numerator, desc.SampleRate.Denominator);
+ _screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator);
}
bool
-PictureAsset::descriptor_equals (
+PictureMXF::descriptor_equals (
ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, boost::function<void (NoteType, string)> note
) const
{
@@ -124,7 +112,7 @@ PictureAsset::descriptor_equals (
}
bool
-PictureAsset::frame_buffer_equals (
+PictureMXF::frame_buffer_equals (
int frame, EqualityOptions opt, boost::function<void (NoteType, string)> note,
uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B
) const
@@ -148,7 +136,7 @@ PictureAsset::frame_buffer_equals (
for (int c = 0; c < 3; ++c) {
if (image_A->size() != image_B->size()) {
- note (ERROR, "image sizes for frame " + lexical_cast<string>(frame) + " differ");
+ note (ERROR, String::compose ("image sizes for frame %1 differ", frame));
return false;
}
@@ -174,14 +162,12 @@ PictureAsset::frame_buffer_equals (
double const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size());
- note (NOTE, "mean difference " + lexical_cast<string> (mean) + ", deviation " + lexical_cast<string> (std_dev));
+ note (NOTE, String::compose ("mean difference %1, deviation %2", mean, std_dev));
if (mean > opt.max_mean_pixel_error) {
note (
ERROR,
- "mean " + lexical_cast<string>(mean) +
- " out of range " + lexical_cast<string>(opt.max_mean_pixel_error) +
- " in frame " + lexical_cast<string>(frame)
+ String::compose ("mean %1 out of range %2 in frame %3", mean, opt.max_mean_pixel_error, frame)
);
return false;
@@ -190,9 +176,7 @@ PictureAsset::frame_buffer_equals (
if (std_dev > opt.max_std_dev_pixel_error) {
note (
ERROR,
- "standard deviation " + lexical_cast<string>(std_dev) +
- " out of range " + lexical_cast<string>(opt.max_std_dev_pixel_error) +
- " in frame " + lexical_cast<string>(frame)
+ String::compose ("standard deviation %1 out of range %2 in frame %3", std_dev, opt.max_std_dev_pixel_error, frame)
);
return false;
@@ -202,10 +186,7 @@ PictureAsset::frame_buffer_equals (
}
string
-PictureAsset::key_type () const
+PictureMXF::key_type () const
{
return "MDIK";
}
-
-
-
diff --git a/src/picture_mxf.h b/src/picture_mxf.h
new file mode 100644
index 00000000..1ce2e7de
--- /dev/null
+++ b/src/picture_mxf.h
@@ -0,0 +1,114 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_PICTURE_MXF_H
+#define LIBDCP_PICTURE_MXF_H
+
+/** @file src/picture_mxf.h
+ * @brief PictureMXF class.
+ */
+
+#include "mxf.h"
+#include "util.h"
+#include "metadata.h"
+#include <openjpeg.h>
+
+namespace ASDCP {
+ namespace JP2K {
+ class PictureDescriptor;
+ }
+}
+
+namespace dcp
+{
+
+class MonoPictureFrame;
+class StereoPictureFrame;
+class PictureMXFWriter;
+
+/** @class PictureMXF
+ * @brief An asset made up of JPEG2000 data.
+ */
+class PictureMXF : public MXF
+{
+public:
+ PictureMXF (boost::filesystem::path file);
+ PictureMXF (Fraction edit_rate);
+
+ virtual boost::shared_ptr<PictureMXFWriter> start_write (
+ boost::filesystem::path file,
+ Standard standard,
+ bool overwrite
+ ) = 0;
+
+ Size size () const {
+ return _size;
+ }
+
+ void set_size (Size s) {
+ _size = s;
+ }
+
+ Fraction frame_rate () const {
+ return _frame_rate;
+ }
+
+ void set_frame_rate (Fraction r) {
+ _frame_rate = r;
+ }
+
+ Fraction screen_aspect_ratio () const {
+ return _screen_aspect_ratio;
+ }
+
+ void set_screen_aspect_ratio (Fraction r) {
+ _screen_aspect_ratio = r;
+ }
+
+protected:
+
+ bool frame_buffer_equals (
+ int frame, EqualityOptions opt, boost::function<void (NoteType, std::string)> note,
+ uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B
+ ) const;
+
+ bool descriptor_equals (
+ ASDCP::JP2K::PictureDescriptor const & a,
+ ASDCP::JP2K::PictureDescriptor const & b,
+ boost::function<void (NoteType, std::string)>
+ ) const;
+
+ void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &);
+
+ /** picture size in pixels */
+ Size _size;
+ Fraction _frame_rate;
+ Fraction _screen_aspect_ratio;
+
+private:
+ std::string key_type () const;
+ std::string asdcp_kind () const {
+ return "Picture";
+ }
+};
+
+
+}
+
+#endif
diff --git a/src/picture_asset_writer.cc b/src/picture_mxf_writer.cc
index 92b384db..46426401 100644
--- a/src/picture_asset_writer.cc
+++ b/src/picture_mxf_writer.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,19 +17,19 @@
*/
-#include <inttypes.h>
-#include <stdint.h>
-#include "AS_DCP.h"
#include "KM_fileio.h"
-#include "picture_asset_writer.h"
+#include "picture_mxf_writer.h"
#include "exceptions.h"
-#include "picture_asset.h"
+#include "picture_mxf.h"
+#include "AS_DCP.h"
+#include <inttypes.h>
+#include <stdint.h>
using std::istream;
using std::ostream;
using std::string;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
FrameInfo::FrameInfo (istream& s)
: offset (0)
@@ -82,13 +82,12 @@ FrameInfo::write (FILE* f) const
#endif
}
-
-PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, bool overwrite)
- : _asset (asset)
- , _frames_written (0)
+PictureMXFWriter::PictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite)
+ : MXFWriter (mxf, file)
+ , _picture_mxf (mxf)
, _started (false)
- , _finalized (false)
+ , _standard (standard)
, _overwrite (overwrite)
{
-
+
}
diff --git a/src/picture_asset_writer.h b/src/picture_mxf_writer.h
index a62b20b2..d1baa7ad 100644
--- a/src/picture_asset_writer.h
+++ b/src/picture_mxf_writer.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,19 +17,29 @@
*/
+/** @file src/picture_mxf_writer.h
+ * @brief PictureMXFWriter and FrameInfo classes.
+ */
+
+#ifndef LIBDCP_PICTURE_MXF_WRITER_H
+#define LIBDCP_PICTURE_MXF_WRITER_H
+
+#include "metadata.h"
+#include "types.h"
+#include "mxf_writer.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
#include <stdint.h>
#include <string>
#include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include "metadata.h"
-#include "types.h"
-namespace libdcp {
+namespace dcp {
-class PictureAsset;
+class PictureMXF;
-/** Information about a single frame (either a monoscopic frame or a left *or* right eye stereoscopic frame) */
+/** @class FrameInfo
+ * @brief Information about a single frame (either a monoscopic frame or a left *or* right eye stereoscopic frame)
+ */
struct FrameInfo
{
FrameInfo (uint64_t o, uint64_t s, std::string h)
@@ -49,31 +59,27 @@ struct FrameInfo
std::string hash;
};
-class PictureAssetWriter : public boost::noncopyable
+/** @class PictureMXFWriter
+ * @brief Parent class for classes which write picture MXF files.
+ */
+class PictureMXFWriter : public MXFWriter
{
public:
- virtual ~PictureAssetWriter () {}
virtual FrameInfo write (uint8_t *, int) = 0;
- virtual void finalize () = 0;
virtual void fake_write (int) = 0;
-
+
protected:
template <class P, class Q>
- friend void start (PictureAssetWriter *, boost::shared_ptr<P>, Q *, uint8_t *, int);
+ friend void start (PictureMXFWriter *, boost::shared_ptr<P>, Standard, Q *, uint8_t *, int);
- PictureAssetWriter (PictureAsset *, bool);
+ PictureMXFWriter (PictureMXF *, boost::filesystem::path, Standard standard, bool);
- PictureAsset* _asset;
-
- /** Number of picture frames written to the asset so far. For stereo assets
- * this will be incremented for each eye (i.e. there will be twice the number
- * of frames as in a mono asset).
- */
- int _frames_written;
+ PictureMXF* _picture_mxf;
bool _started;
- /** true if finalize() has been called */
- bool _finalized;
+ Standard _standard;
bool _overwrite;
};
}
+
+#endif
diff --git a/src/picture_asset_writer_common.cc b/src/picture_mxf_writer_common.cc
index 52848745..d8d1589b 100644
--- a/src/picture_asset_writer_common.cc
+++ b/src/picture_mxf_writer_common.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -33,19 +33,24 @@ struct ASDCPStateBase
};
template <class P, class Q>
-void libdcp::start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint8_t* data, int size)
+void dcp::start (PictureMXFWriter* writer, shared_ptr<P> state, Standard standard, Q* mxf, uint8_t* data, int size)
{
+ mxf->set_file (writer->_file);
+
if (ASDCP_FAILURE (state->j2k_parser.OpenReadFrame (data, size, state->frame_buffer))) {
boost::throw_exception (MiscError ("could not parse J2K frame"));
}
state->j2k_parser.FillPictureDescriptor (state->picture_descriptor);
- state->picture_descriptor.EditRate = ASDCP::Rational (asset->edit_rate(), 1);
+ state->picture_descriptor.EditRate = ASDCP::Rational (mxf->edit_rate().numerator, mxf->edit_rate().denominator);
+
+ mxf->set_size (Size (state->picture_descriptor.StoredWidth, state->picture_descriptor.StoredHeight));
+ mxf->set_screen_aspect_ratio (Fraction (state->picture_descriptor.AspectRatio.Numerator, state->picture_descriptor.AspectRatio.Denominator));
- asset->fill_writer_info (&state->writer_info);
+ mxf->fill_writer_info (&state->writer_info, standard);
Kumu::Result_t r = state->mxf_writer.OpenWrite (
- asset->path().string().c_str(),
+ mxf->file().string().c_str(),
state->writer_info,
state->picture_descriptor,
16384,
@@ -53,7 +58,7 @@ void libdcp::start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, u
);
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for writing", asset->path().string(), r));
+ boost::throw_exception (MXFFileError ("could not open MXF file for writing", mxf->file().string(), r));
}
writer->_started = true;
diff --git a/src/reel.cc b/src/reel.cc
index ff51c025..4bdbcb5f 100644
--- a/src/reel.cc
+++ b/src/reel.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,46 +17,79 @@
*/
-#include <libxml++/nodes/element.h>
#include "reel.h"
#include "util.h"
-#include "picture_asset.h"
-#include "mono_picture_asset.h"
-#include "stereo_picture_asset.h"
-#include "sound_asset.h"
-#include "subtitle_asset.h"
+#include "picture_mxf.h"
+#include "mono_picture_mxf.h"
+#include "stereo_picture_mxf.h"
+#include "sound_mxf.h"
+#include "subtitle_content.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_stereo_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
#include "kdm.h"
+#include <libxml++/nodes/element.h>
using std::string;
using std::list;
using std::cout;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
-using namespace libdcp;
+using namespace dcp;
+
+Reel::Reel (boost::shared_ptr<const cxml::Node> node)
+ : Object (node->string_child ("Id"))
+{
+ shared_ptr<cxml::Node> asset_list = node->node_child ("AssetList");
+
+ shared_ptr<cxml::Node> main_picture = asset_list->optional_node_child ("MainPicture");
+ if (main_picture) {
+ _main_picture.reset (new ReelMonoPictureAsset (main_picture));
+ }
+
+ shared_ptr<cxml::Node> main_stereoscopic_picture = asset_list->optional_node_child ("MainStereoscopicPicture");
+ if (main_stereoscopic_picture) {
+ _main_picture.reset (new ReelStereoPictureAsset (main_stereoscopic_picture));
+ }
+
+ shared_ptr<cxml::Node> main_sound = asset_list->optional_node_child ("MainSound");
+ if (main_sound) {
+ _main_sound.reset (new ReelSoundAsset (main_sound));
+ }
+
+ shared_ptr<cxml::Node> main_subtitle = asset_list->optional_node_child ("MainSubtitle");
+ if (main_subtitle) {
+ _main_subtitle.reset (new ReelSubtitleAsset (main_subtitle));
+ }
+
+ node->ignore_child ("AnnotationText");
+ node->done ();
+}
void
-Reel::write_to_cpl (xmlpp::Element* node) const
+Reel::write_to_cpl (xmlpp::Element* node, Standard standard) const
{
xmlpp::Element* reel = node->add_child ("Reel");
reel->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid());
xmlpp::Element* asset_list = reel->add_child ("AssetList");
- if (_main_picture && dynamic_pointer_cast<MonoPictureAsset> (_main_picture)) {
+ if (_main_picture && dynamic_pointer_cast<ReelMonoPictureAsset> (_main_picture)) {
/* Mono pictures come before other stuff... */
- _main_picture->write_to_cpl (asset_list);
+ _main_picture->write_to_cpl (asset_list, standard);
}
if (_main_sound) {
- _main_sound->write_to_cpl (asset_list);
+ _main_sound->write_to_cpl (asset_list, standard);
}
if (_main_subtitle) {
- _main_subtitle->write_to_cpl (asset_list);
+ _main_subtitle->write_to_cpl (asset_list, standard);
}
- if (_main_picture && dynamic_pointer_cast<StereoPictureAsset> (_main_picture)) {
+ if (_main_picture && dynamic_pointer_cast<ReelStereoPictureAsset> (_main_picture)) {
/* ... but stereo pictures must come after */
- _main_picture->write_to_cpl (asset_list);
+ _main_picture->write_to_cpl (asset_list, standard);
}
}
@@ -100,16 +133,16 @@ Reel::encrypted () const
}
void
-Reel::add_kdm (KDM const & kdm)
+Reel::add (KDM const & kdm)
{
list<KDMKey> keys = kdm.keys ();
for (list<KDMKey>::iterator i = keys.begin(); i != keys.end(); ++i) {
if (i->key_id() == _main_picture->key_id()) {
- _main_picture->set_key (i->key ());
+ _main_picture->mxf()->set_key (i->key ());
}
if (i->key_id() == _main_sound->key_id()) {
- _main_sound->set_key (i->key ());
+ _main_sound->mxf()->set_key (i->key ());
}
}
}
@@ -117,10 +150,41 @@ Reel::add_kdm (KDM const & kdm)
void
Reel::set_mxf_keys (Key key)
{
- _main_picture->set_key (key);
+ _main_picture->mxf()->set_key (key);
if (_main_sound) {
- _main_sound->set_key (key);
+ _main_sound->mxf()->set_key (key);
}
/* XXX: subtitle asset? */
}
+
+void
+Reel::add (shared_ptr<ReelAsset> asset)
+{
+ shared_ptr<ReelPictureAsset> p = dynamic_pointer_cast<ReelPictureAsset> (asset);
+ shared_ptr<ReelSoundAsset> so = dynamic_pointer_cast<ReelSoundAsset> (asset);
+ shared_ptr<ReelSubtitleAsset> su = dynamic_pointer_cast<ReelSubtitleAsset> (asset);
+ if (p) {
+ _main_picture = p;
+ } else if (so) {
+ _main_sound = so;
+ } else if (su) {
+ _main_subtitle = su;
+ }
+}
+
+void
+Reel::resolve_refs (list<shared_ptr<Object> > objects)
+{
+ if (_main_picture) {
+ _main_picture->content().resolve (objects);
+ }
+
+ if (_main_sound) {
+ _main_sound->content().resolve (objects);
+ }
+
+ if (_main_subtitle) {
+ _main_subtitle->content().resolve (objects);
+ }
+}
diff --git a/src/reel.h b/src/reel.h
index 35302f17..14def9c8 100644
--- a/src/reel.h
+++ b/src/reel.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -20,64 +20,75 @@
#ifndef LIBDCP_REEL_H
#define LIBDCP_REEL_H
-#include <list>
-#include <boost/shared_ptr.hpp>
-#include <boost/function.hpp>
-#include <libxml++/libxml++.h>
#include "key.h"
#include "types.h"
+#include "ref.h"
+#include <libxml++/libxml++.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <list>
-namespace xmlpp {
+namespace cxml {
class Node;
}
-namespace libdcp {
+namespace dcp {
-class PictureAsset;
-class SoundAsset;
-class SubtitleAsset;
-class KDM;
+class KDM;
+class ReelAsset;
+class ReelPictureAsset;
+class ReelSoundAsset;
+class ReelSubtitleAsset;
+class Content;
-/** @brief A reel within a DCP; the part which actually contains picture, sound and subtitle data */
-class Reel
+/** @brief A reel within a DCP; the part which actually refers to picture, sound and subtitle data */
+class Reel : public Object
{
public:
+ Reel () {}
+
Reel (
- boost::shared_ptr<PictureAsset> picture,
- boost::shared_ptr<SoundAsset> sound,
- boost::shared_ptr<SubtitleAsset> subtitle
+ boost::shared_ptr<ReelPictureAsset> picture,
+ boost::shared_ptr<ReelSoundAsset> sound,
+ boost::shared_ptr<ReelSubtitleAsset> subtitle
)
: _main_picture (picture)
, _main_sound (sound)
, _main_subtitle (subtitle)
{}
+
+ Reel (boost::shared_ptr<const cxml::Node>);
- boost::shared_ptr<const PictureAsset> main_picture () const {
+ boost::shared_ptr<ReelPictureAsset> main_picture () const {
return _main_picture;
}
- boost::shared_ptr<const SoundAsset> main_sound () const {
+ boost::shared_ptr<ReelSoundAsset> main_sound () const {
return _main_sound;
}
- boost::shared_ptr<const SubtitleAsset> main_subtitle () const {
+ boost::shared_ptr<ReelSubtitleAsset> main_subtitle () const {
return _main_subtitle;
}
- void write_to_cpl (xmlpp::Element *) const;
+ void add (boost::shared_ptr<ReelAsset> asset);
+
+ void write_to_cpl (xmlpp::Element* node, Standard standard) const;
bool encrypted () const;
- void set_mxf_keys (libdcp::Key);
+ void set_mxf_keys (dcp::Key);
bool equals (boost::shared_ptr<const Reel> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> notes) const;
- void add_kdm (KDM const &);
+ void add (KDM const &);
+
+ void resolve_refs (std::list<boost::shared_ptr<Object> >);
private:
- boost::shared_ptr<PictureAsset> _main_picture;
- boost::shared_ptr<SoundAsset> _main_sound;
- boost::shared_ptr<SubtitleAsset> _main_subtitle;
+ boost::shared_ptr<ReelPictureAsset> _main_picture;
+ boost::shared_ptr<ReelSoundAsset> _main_sound;
+ boost::shared_ptr<ReelSubtitleAsset> _main_subtitle;
};
}
diff --git a/src/reel_asset.cc b/src/reel_asset.cc
new file mode 100644
index 00000000..fa0068c5
--- /dev/null
+++ b/src/reel_asset.cc
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "reel_asset.h"
+#include "content.h"
+#include "compose.hpp"
+#include <libcxml/cxml.h>
+
+using std::pair;
+using std::string;
+using std::make_pair;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+ReelAsset::ReelAsset ()
+ : Object (make_uuid ())
+ , _content (_id)
+ , _edit_rate (Fraction (24, 1))
+ , _intrinsic_duration (0)
+ , _entry_point (0)
+ , _duration (0)
+{
+
+}
+
+/** Construct a ReelAsset.
+ * @param content Content that this asset refers to.
+ * @param entry_point Entry point to use in that content.
+ */
+ReelAsset::ReelAsset (boost::shared_ptr<Content> content, int64_t entry_point)
+ : Object (content->id ())
+ , _content (content)
+ , _edit_rate (content->edit_rate ())
+ , _intrinsic_duration (content->intrinsic_duration ())
+ , _entry_point (entry_point)
+ , _duration (_intrinsic_duration - _entry_point)
+ , _hash (make_digest (content->file (), 0))
+{
+ /* default _annotation_text to the leaf name of our file */
+ _annotation_text = content->file().leaf().string ();
+}
+
+ReelAsset::ReelAsset (boost::shared_ptr<const cxml::Node> node)
+ : Object (node->string_child ("Id"))
+ , _content (_id)
+ , _annotation_text (node->optional_string_child ("AnnotationText").get_value_or (""))
+ , _edit_rate (Fraction (node->string_child ("EditRate")))
+ , _intrinsic_duration (node->number_child<int64_t> ("IntrinsicDuration"))
+ , _entry_point (node->number_child<int64_t> ("EntryPoint"))
+ , _duration (node->number_child<int64_t> ("Duration"))
+ , _hash (node->optional_string_child ("Hash").get_value_or (""))
+ , _key_id (node->optional_string_child ("KeyId").get_value_or (""))
+{
+ if (_id.length() > 9) {
+ _id = _id.substr (9);
+ _content.set_id (_id);
+ }
+
+ if (_key_id.length() > 9) {
+ _key_id = _key_id.substr (9);
+ }
+}
+
+void
+ReelAsset::write_to_cpl (xmlpp::Node* node, Standard) const
+{
+ pair<string, string> const attr = cpl_node_attribute ();
+ xmlpp::Element* a = node->add_child (cpl_node_name ());
+ if (!attr.first.empty ()) {
+ a->set_attribute (attr.first, attr.second);
+ }
+ a->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ a->add_child("AnnotationText")->add_child_text (_annotation_text);
+ a->add_child("EditRate")->add_child_text (String::compose ("%1 %2", _edit_rate.numerator, _edit_rate.denominator));
+ a->add_child("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration));
+ a->add_child("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point));
+ a->add_child("Duration")->add_child_text (lexical_cast<string> (_duration));
+ if (!_key_id.empty ()) {
+ a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id);
+ }
+}
+
+pair<string, string>
+ReelAsset::cpl_node_attribute () const
+{
+ return make_pair ("", "");
+}
diff --git a/src/reel_asset.h b/src/reel_asset.h
new file mode 100644
index 00000000..a71290ae
--- /dev/null
+++ b/src/reel_asset.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_REEL_ASSET_H
+#define LIBDCP_REEL_ASSET_H
+
+#include "object.h"
+#include "util.h"
+#include "ref.h"
+#include <boost/shared_ptr.hpp>
+
+namespace cxml {
+ class Node;
+}
+
+namespace xmlpp {
+ class Node;
+}
+
+namespace dcp {
+
+class Content;
+
+/** @class ReelAsset
+ * @brief An entry in a &lt;Reel&gt; which refers to a use of a piece of content.
+ *
+ * This class encapsulates the XML that exists in a &lt;Reel&gt; to say
+ * that a piece of content is used in this reel. It does not
+ * describe the content itself (but links to a Content object which does).
+ */
+class ReelAsset : public Object
+{
+public:
+ ReelAsset ();
+ ReelAsset (boost::shared_ptr<Content> content, int64_t entry_point);
+ ReelAsset (boost::shared_ptr<const cxml::Node>);
+
+ virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const;
+
+ virtual bool equals (
+ boost::shared_ptr<const ReelAsset>,
+ EqualityOptions,
+ boost::function<void (NoteType, std::string)>)
+ const {
+
+ return false;
+ }
+
+ /** @return a Ref to our actual content */
+ Ref<Content>& content () {
+ return _content;
+ }
+
+ /** @return true if a KeyId is specified for this asset, implying
+ * that its content is encrypted.
+ */
+ bool encrypted () const {
+ return !_key_id.empty ();
+ }
+
+ /** @return Key ID to describe the key that encrypts this asset's;
+ * content.
+ */
+ std::string key_id () const {
+ return _key_id;
+ }
+
+protected:
+ /** @return the node name that this asset uses in the CPL's &lt;Reel&gt; node
+ * e.g. MainPicture, MainSound etc.
+ */
+ virtual std::string cpl_node_name () const = 0;
+
+ /** @return Any attribute that should be used on the asset's node in the
+ * CPL.
+ */
+ virtual std::pair<std::string, std::string> cpl_node_attribute () const;
+
+ /** Reference to the content (MXF or XML file) that this reel entry
+ * applies to.
+ */
+ Ref<Content> _content;
+
+private:
+
+ std::string _annotation_text; ///< The <AnnotationText> from the reel's entry for this asset
+ Fraction _edit_rate; ///< The <EditRate> from the reel's entry for this asset
+ int64_t _intrinsic_duration; ///< The <IntrinsicDuration> from the reel's entry for this asset
+ int64_t _entry_point; ///< The <EntryPoint> from the reel's entry for this asset
+ int64_t _duration; ///< The <Duration> from the reel's entry for this asset
+ std::string _hash; ///< The <Hash> from the reel's entry for this asset
+ std::string _key_id; ///< The <KeyId> from the reel's entry for this asset, or empty if there isn't one
+};
+
+}
+
+#endif
diff --git a/src/reel_mono_picture_asset.cc b/src/reel_mono_picture_asset.cc
new file mode 100644
index 00000000..b4ed6301
--- /dev/null
+++ b/src/reel_mono_picture_asset.cc
@@ -0,0 +1,54 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_mono_picture_asset.cc
+ * @brief ReelMonoPictureAsset class.
+ */
+
+#include "reel_mono_picture_asset.h"
+#include "mono_picture_mxf.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelMonoPictureAsset::ReelMonoPictureAsset ()
+{
+
+}
+
+ReelMonoPictureAsset::ReelMonoPictureAsset (boost::shared_ptr<MonoPictureMXF> mxf, int64_t entry_point)
+ : ReelPictureAsset (mxf, entry_point)
+{
+
+}
+
+ReelMonoPictureAsset::ReelMonoPictureAsset (boost::shared_ptr<const cxml::Node> node)
+ : ReelPictureAsset (node)
+{
+ node->done ();
+}
+
+string
+ReelMonoPictureAsset::cpl_node_name () const
+{
+ return "MainPicture";
+}
+
diff --git a/src/reel_mono_picture_asset.h b/src/reel_mono_picture_asset.h
new file mode 100644
index 00000000..a25550a4
--- /dev/null
+++ b/src/reel_mono_picture_asset.h
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_mono_picture_asset.h
+ * @brief ReelMonoPictureAsset class.
+ */
+
+#ifndef LIBDCP_REEL_MONO_PICTURE_ASSET_H
+#define LIBDCP_REEL_MONO_PICTURE_ASSET_H
+
+#include "reel_picture_asset.h"
+
+namespace dcp {
+
+class MonoPictureMXF;
+
+/** @class ReelMonoPictureAsset
+ * @brief Part of a Reel's description which refers to a monoscopic picture MXF.
+ */
+class ReelMonoPictureAsset : public ReelPictureAsset
+{
+public:
+ ReelMonoPictureAsset ();
+ ReelMonoPictureAsset (boost::shared_ptr<MonoPictureMXF> content, int64_t entry_point);
+ ReelMonoPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+private:
+ std::string cpl_node_name () const;
+};
+
+}
+
+#endif
diff --git a/src/reel_picture_asset.cc b/src/reel_picture_asset.cc
new file mode 100644
index 00000000..d1910bb3
--- /dev/null
+++ b/src/reel_picture_asset.cc
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_picture_asset.h
+ * @brief ReelPictureAsset class.
+ */
+
+#include "content.h"
+#include "reel_picture_asset.h"
+#include "picture_mxf.h"
+#include "compose.hpp"
+#include <libcxml/cxml.h>
+
+using std::bad_cast;
+using std::string;
+using std::stringstream;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelPictureAsset::ReelPictureAsset ()
+ : _frame_rate (Fraction (24, 1))
+ , _screen_aspect_ratio (Fraction (1998, 1080))
+{
+
+}
+
+ReelPictureAsset::ReelPictureAsset (boost::shared_ptr<PictureMXF> content, int64_t entry_point)
+ : ReelAsset (content, entry_point)
+ , _frame_rate (content->frame_rate ())
+ , _screen_aspect_ratio (content->screen_aspect_ratio ())
+{
+
+}
+
+ReelPictureAsset::ReelPictureAsset (boost::shared_ptr<const cxml::Node> node)
+ : ReelAsset (node)
+{
+ _frame_rate = Fraction (node->string_child ("FrameRate"));
+ try {
+ _screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio"));
+ } catch (XMLError& e) {
+ /* Maybe it's not a fraction */
+ }
+ try {
+ float f = node->number_child<float> ("ScreenAspectRatio");
+ _screen_aspect_ratio = Fraction (f * 1000, 1000);
+ } catch (bad_cast& e) {
+
+ }
+}
+
+void
+ReelPictureAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+{
+ ReelAsset::write_to_cpl (node, standard);
+
+ xmlpp::Node::NodeList c = node->get_children ();
+ xmlpp::Node::NodeList::iterator i = c.begin();
+ while (i != c.end() && (*i)->get_name() != cpl_node_name ()) {
+ ++i;
+ }
+
+ assert (i != c.end ());
+
+ (*i)->add_child ("FrameRate")->add_child_text (String::compose ("%1 %2", _frame_rate.numerator, _frame_rate.denominator));
+ if (standard == INTEROP) {
+ stringstream s;
+ s << std::fixed << std::setprecision (2) << (float (_screen_aspect_ratio.numerator) / _screen_aspect_ratio.denominator);
+ (*i)->add_child ("ScreenAspectRatio")->add_child_text (s.str ());
+ } else {
+ (*i)->add_child ("ScreenAspectRatio")->add_child_text (
+ String::compose ("%1 %2", _screen_aspect_ratio.numerator, _screen_aspect_ratio.denominator)
+ );
+ }
+}
diff --git a/src/reel_picture_asset.h b/src/reel_picture_asset.h
new file mode 100644
index 00000000..547f3ada
--- /dev/null
+++ b/src/reel_picture_asset.h
@@ -0,0 +1,59 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_picture_asset.h
+ * @brief ReelPictureAsset class.
+ */
+
+#ifndef LIBDCP_REEL_PICTURE_ASSET_H
+#define LIBDCP_REEL_PICTURE_ASSET_H
+
+#include "reel_asset.h"
+#include "picture_mxf.h"
+
+namespace dcp {
+
+/** @class ReelPictureAsset
+ * @brief Part of a Reel's description which refers to a picture MXF.
+ */
+class ReelPictureAsset : public ReelAsset
+{
+public:
+ ReelPictureAsset ();
+ ReelPictureAsset (boost::shared_ptr<PictureMXF> content, int64_t entry_point);
+ ReelPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+ virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const;
+
+ boost::shared_ptr<PictureMXF> mxf () {
+ return boost::dynamic_pointer_cast<PictureMXF> (_content.object ());
+ }
+
+ void set_screen_aspect_ratio (Fraction a) {
+ _screen_aspect_ratio = a;
+ }
+
+private:
+ Fraction _frame_rate;
+ Fraction _screen_aspect_ratio;
+};
+
+}
+
+#endif
diff --git a/src/reel_sound_asset.cc b/src/reel_sound_asset.cc
new file mode 100644
index 00000000..984434dd
--- /dev/null
+++ b/src/reel_sound_asset.cc
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_sound_asset.cc
+ * @brief ReelSoundAsset class.
+ */
+
+#include "reel_sound_asset.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelSoundAsset::ReelSoundAsset (boost::shared_ptr<Content> content, int64_t entry_point)
+ : ReelAsset (content, entry_point)
+{
+
+}
+
+ReelSoundAsset::ReelSoundAsset (boost::shared_ptr<const cxml::Node> node)
+ : ReelAsset (node)
+{
+ node->ignore_child ("Language");
+ node->done ();
+}
+
+string
+ReelSoundAsset::cpl_node_name () const
+{
+ return "MainSound";
+}
diff --git a/src/reel_sound_asset.h b/src/reel_sound_asset.h
new file mode 100644
index 00000000..42835c84
--- /dev/null
+++ b/src/reel_sound_asset.h
@@ -0,0 +1,53 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_sound_asset.h
+ * @brief ReelSoundAsset class.
+ */
+
+#include "reel_asset.h"
+#include "sound_mxf.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+namespace dcp {
+
+/** @class ReelSoundAsset
+ * @brief Part of a Reel's description which refers to a sound MXF.
+ */
+class ReelSoundAsset : public ReelAsset
+{
+public:
+ ReelSoundAsset (boost::shared_ptr<Content> content, int64_t entry_point);
+ ReelSoundAsset (boost::shared_ptr<const cxml::Node>);
+
+ boost::shared_ptr<SoundMXF> mxf () {
+ return boost::dynamic_pointer_cast<SoundMXF> (_content.object ());
+ }
+
+ boost::shared_ptr<const SoundMXF> mxf () const {
+ return boost::dynamic_pointer_cast<const SoundMXF> (_content.object ());
+ }
+
+private:
+ std::string cpl_node_name () const;
+};
+
+}
+
diff --git a/src/reel_stereo_picture_asset.cc b/src/reel_stereo_picture_asset.cc
new file mode 100644
index 00000000..09178dc2
--- /dev/null
+++ b/src/reel_stereo_picture_asset.cc
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_stereo_picture_asset.cc
+ * @brief ReelStereoPictureAsset class.
+ */
+
+#include "reel_stereo_picture_asset.h"
+#include "stereo_picture_mxf.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using std::pair;
+using std::make_pair;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelStereoPictureAsset::ReelStereoPictureAsset ()
+{
+
+}
+
+ReelStereoPictureAsset::ReelStereoPictureAsset (boost::shared_ptr<StereoPictureMXF> mxf, int64_t entry_point)
+ : ReelPictureAsset (mxf, entry_point)
+{
+
+}
+
+ReelStereoPictureAsset::ReelStereoPictureAsset (boost::shared_ptr<const cxml::Node> node)
+ : ReelPictureAsset (node)
+{
+ node->done ();
+}
+
+string
+ReelStereoPictureAsset::cpl_node_name () const
+{
+ return "msp-cpl:MainStereoscopicPicture";
+}
+
+pair<string, string>
+ReelStereoPictureAsset::cpl_node_attribute (Standard standard) const
+{
+ if (standard == INTEROP) {
+ return make_pair ("xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL");
+ } else {
+ return make_pair ("xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL");
+ }
+
+ return make_pair ("", "");
+}
diff --git a/src/reel_stereo_picture_asset.h b/src/reel_stereo_picture_asset.h
new file mode 100644
index 00000000..57cc4da1
--- /dev/null
+++ b/src/reel_stereo_picture_asset.h
@@ -0,0 +1,51 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_stereo_picture_asset.h
+ * @brief ReelStereoPictureAsset class.
+ */
+
+#ifndef LIBDCP_REEL_STEREO_PICTURE_ASSET_H
+#define LIBDCP_REEL_STEREO_PICTURE_ASSET_H
+
+#include "reel_picture_asset.h"
+
+namespace dcp {
+
+class StereoPictureMXF;
+
+/** @class ReelStereoPictureAsset
+ * @brief Part of a Reel's description which refers to a stereoscopic picture MXF.
+ */
+class ReelStereoPictureAsset : public ReelPictureAsset
+{
+public:
+ ReelStereoPictureAsset ();
+ ReelStereoPictureAsset (boost::shared_ptr<StereoPictureMXF> content, int64_t entry_point);
+ ReelStereoPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+private:
+ std::string cpl_node_name () const;
+ std::pair<std::string, std::string> cpl_node_attribute (Standard standard) const;
+};
+
+}
+
+#endif
+
diff --git a/src/reel_subtitle_asset.cc b/src/reel_subtitle_asset.cc
new file mode 100644
index 00000000..1c948200
--- /dev/null
+++ b/src/reel_subtitle_asset.cc
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_subtitle_asset.cc
+ * @brief ReelSubtitleAsset class.
+ */
+
+#include "subtitle_content.h"
+#include "reel_subtitle_asset.h"
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelSubtitleAsset::ReelSubtitleAsset (boost::shared_ptr<SubtitleContent> content, int64_t entry_point)
+ : ReelAsset (content, entry_point)
+{
+
+}
+
+ReelSubtitleAsset::ReelSubtitleAsset (boost::shared_ptr<const cxml::Node> node)
+ : ReelAsset (node)
+{
+ node->ignore_child ("Language");
+ node->done ();
+}
+
+string
+ReelSubtitleAsset::cpl_node_name () const
+{
+ return "MainSubtitle";
+}
diff --git a/src/reel_subtitle_asset.h b/src/reel_subtitle_asset.h
new file mode 100644
index 00000000..5cdfac13
--- /dev/null
+++ b/src/reel_subtitle_asset.h
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/reel_subtitle_asset.h
+ * @brief ReelSubtitleAsset class.
+ */
+
+#ifndef LIBDCP_REEL_SUBTITLE_ASSET_H
+#define LIBDCP_REEL_SUBTITLE_ASSET_H
+
+#include "reel_asset.h"
+
+namespace dcp {
+
+class SubtitleContent;
+
+/** @class ReelSubtitleAsset
+ * @brief Part of a Reel's description which refers to a subtitle XML file.
+ */
+class ReelSubtitleAsset : public ReelAsset
+{
+public:
+ ReelSubtitleAsset (boost::shared_ptr<SubtitleContent> content, int64_t entry_point);
+ ReelSubtitleAsset (boost::shared_ptr<const cxml::Node>);
+
+ boost::shared_ptr<SubtitleContent> subtitle_content () const {
+ return boost::dynamic_pointer_cast<SubtitleContent> (_content.object ());
+ }
+
+private:
+ std::string cpl_node_name () const;
+};
+
+}
+
+#endif
diff --git a/src/ref.h b/src/ref.h
new file mode 100644
index 00000000..c22222cc
--- /dev/null
+++ b/src/ref.h
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/ref.h
+ * @brief Ref class.
+ */
+
+#ifndef LIBDCP_REF_H
+#define LIBDCP_REF_H
+
+#include "exceptions.h"
+#include "object.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+namespace dcp {
+
+/** @class Ref
+ * @brief A reference to an object which is identified by a universally-unique identifier (UUID).
+ *
+ * This class is a `pointer' to a thing. It will always know the
+ * UUID of the thing, and it may have a shared_ptr to the C++ object
+ * which represents the thing.
+ *
+ * If the Ref does not have a shared_ptr it may be given one by
+ * calling resolve() with a list of objects. The shared_ptr will be
+ * set up using any object on the list which has a matching ID.
+ */
+template<class T>
+class Ref
+{
+public:
+ /** Initialise a Ref with an ID but no shared_ptr */
+ Ref (std::string id)
+ : _id (id)
+ {}
+
+ /** Initialise a Ref with a shared_ptr to an object */
+ Ref (boost::shared_ptr<T> object)
+ : _id (object->id ())
+ , _object (object)
+ {}
+
+ /** Set the ID of this Ref */
+ void set_id (std::string id)
+ {
+ _id = id;
+ }
+
+ /** Look through a list of objects and copy a shared_ptr to any object
+ * which matches the ID of this one.
+ */
+ void resolve (std::list<boost::shared_ptr<Object> > objects)
+ {
+ typename std::list<boost::shared_ptr<Object> >::iterator i = objects.begin();
+ while (i != objects.end() && (*i)->id() != _id) {
+ ++i;
+ }
+
+ if (i != objects.end ()) {
+ _object = boost::dynamic_pointer_cast<T> (*i);
+ }
+ }
+
+ /** @return the ID of the thing that we are pointing to */
+ std::string id () const {
+ return _id;
+ }
+
+ /** @return a shared_ptr to the thing; an UnresolvedRefError is thrown
+ * if the shared_ptr is not known.
+ */
+ boost::shared_ptr<T> object () const {
+ if (!_object) {
+ throw UnresolvedRefError (_id);
+ }
+
+ return _object;
+ }
+
+ /** operator-> to access the shared_ptr; an UnresolvedRefError is thrown
+ * if the shared_ptr is not known.
+ */
+ T * operator->() const {
+ if (!_object) {
+ throw UnresolvedRefError (_id);
+ }
+
+ return _object.get ();
+ }
+
+ /** @return true if a shared_ptr is known for this Ref */
+ bool resolved () const {
+ return _object;
+ }
+
+private:
+ std::string _id; ///< ID; will always be known
+ boost::shared_ptr<T> _object; ///< shared_ptr to the thing, may be null.
+};
+
+}
+
+#endif
diff --git a/src/rgb_xyz.cc b/src/rgb_xyz.cc
index dea2106c..92997441 100644
--- a/src/rgb_xyz.cc
+++ b/src/rgb_xyz.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -27,16 +27,22 @@
using std::min;
using std::max;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
#define DCI_COEFFICIENT (48.0 / 52.37)
/** Convert an openjpeg XYZ image to RGB.
* @param xyz_frame Frame in XYZ.
+ * @param lut_in Input Gamma LUT to use.
+ * @param lut_out Output Gamma LUT to use.
* @return RGB image.
*/
shared_ptr<ARGBFrame>
-libdcp::xyz_to_rgb (shared_ptr<const XYZFrame> xyz_frame, shared_ptr<const LUT> lut_in, shared_ptr<const LUT> lut_out)
+dcp::xyz_to_rgb (
+ boost::shared_ptr<const XYZFrame> xyz_frame,
+ boost::shared_ptr<const GammaLUT> lut_in,
+ boost::shared_ptr<const GammaLUT> lut_out
+ )
{
int const max_colour = pow (2, lut_out->bit_depth()) - 1;
@@ -99,8 +105,13 @@ libdcp::xyz_to_rgb (shared_ptr<const XYZFrame> xyz_frame, shared_ptr<const LUT>
return argb_frame;
}
-shared_ptr<libdcp::XYZFrame>
-libdcp::rgb_to_xyz (shared_ptr<const Image> rgb, shared_ptr<const LUT> lut_in, shared_ptr<const LUT> lut_out, double const colour_matrix[3][3])
+shared_ptr<dcp::XYZFrame>
+dcp::rgb_to_xyz (
+ boost::shared_ptr<const Image> rgb,
+ boost::shared_ptr<const GammaLUT> lut_in,
+ boost::shared_ptr<const GammaLUT> lut_out,
+ double const colour_matrix[3][3]
+ )
{
assert (lut_in->bit_depth() == 12);
assert (lut_out->bit_depth() == 16);
diff --git a/src/rgb_xyz.h b/src/rgb_xyz.h
index 87959cb3..28e09230 100644
--- a/src/rgb_xyz.h
+++ b/src/rgb_xyz.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -19,19 +19,19 @@
#include <boost/shared_ptr.hpp>
-namespace libdcp {
+namespace dcp {
class ARGBFrame;
class XYZFrame;
-class LUT;
+class GammaLUT;
class Image;
extern boost::shared_ptr<ARGBFrame> xyz_to_rgb (
- boost::shared_ptr<const XYZFrame>, boost::shared_ptr<const LUT>, boost::shared_ptr<const LUT>
+ boost::shared_ptr<const XYZFrame>, boost::shared_ptr<const GammaLUT>, boost::shared_ptr<const GammaLUT>
);
extern boost::shared_ptr<XYZFrame> rgb_to_xyz (
- boost::shared_ptr<const Image>, boost::shared_ptr<const LUT>, boost::shared_ptr<const LUT>, double const colour_matrix[3][3]
+ boost::shared_ptr<const Image>, boost::shared_ptr<const GammaLUT>, boost::shared_ptr<const GammaLUT>, double const colour_matrix[3][3]
);
}
diff --git a/src/signer.cc b/src/signer.cc
index 11cf5eb8..8b3cf31d 100644
--- a/src/signer.cc
+++ b/src/signer.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,34 +17,49 @@
*/
+/** @file src/signer.cc
+ * @brief Signer class.
+ */
+
+#include "signer.h"
+#include "exceptions.h"
+#include <libcxml/cxml.h>
#include <libxml++/libxml++.h>
#include <xmlsec/xmldsig.h>
#include <xmlsec/dl.h>
#include <xmlsec/app.h>
#include <xmlsec/crypto.h>
-#include <libcxml/cxml.h>
-#include "signer.h"
-#include "exceptions.h"
-#include "compose.hpp"
using std::string;
using std::list;
using std::cout;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
-/** @param signer_key Filename of private key to sign with */
+/** Add a &lt;Signer&gt; and &lt;ds:Signature&gt; nodes to an XML node.
+ * @param parent XML node to add to.
+ * @param standard INTEROP or SMPTE.
+ */
void
-Signer::sign (xmlpp::Element* parent, bool interop) const
+Signer::sign (xmlpp::Element* parent, Standard standard) const
{
- add_signer (parent, "dsig");
+ /* <Signer> */
+
+ xmlpp::Element* signer = parent->add_child("Signer");
+ xmlpp::Element* data = signer->add_child("X509Data", "dsig");
+ xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", "dsig");
+ serial_element->add_child("X509IssuerName", "dsig")->add_child_text (_certificates.leaf()->issuer());
+ serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (_certificates.leaf()->serial());
+ data->add_child("X509SubjectName", "dsig")->add_child_text (_certificates.leaf()->subject());
+ /* <Signature> */
+
xmlpp::Element* signature = parent->add_child("Signature", "dsig");
xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig");
signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
- if (interop) {
+ if (standard == INTEROP) {
signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1");
} else {
signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
@@ -115,21 +130,3 @@ Signer::add_signature_value (xmlpp::Node* parent, string ns) const
xmlSecDSigCtxDestroy (signature_context);
}
-
-void
-Signer::add_signer (xmlpp::Element* parent, string ns) const
-{
- xmlpp::Element* signer = parent->add_child("Signer");
-
- {
- xmlpp::Element* data = signer->add_child("X509Data", ns);
-
- {
- xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", ns);
- serial_element->add_child("X509IssuerName", ns)->add_child_text (_certificates.leaf()->issuer());
- serial_element->add_child("X509SerialNumber", ns)->add_child_text (_certificates.leaf()->serial());
- }
-
- data->add_child("X509SubjectName", ns)->add_child_text (_certificates.leaf()->subject());
- }
-}
diff --git a/src/signer.h b/src/signer.h
index efb8099b..6e258f8d 100644
--- a/src/signer.h
+++ b/src/signer.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,25 +17,39 @@
*/
-#include <boost/filesystem.hpp>
+#ifndef LIBDCP_SIGNER_H
+#define LIBDCP_SIGNER_H
+
+/** @file src/signer.h
+ * @brief Signer class.
+ */
+
#include "certificates.h"
+#include "types.h"
+#include <boost/filesystem.hpp>
namespace xmlpp {
class Element;
class Node;
}
-namespace libdcp {
+namespace dcp {
-class Signer
+/** @class Signer
+ * @brief A class which can sign XML files.
+ */
+class Signer : public boost::noncopyable
{
public:
+ /** @param c Certificate chain to sign with.
+ * @param k Key to sign with.
+ */
Signer (CertificateChain c, boost::filesystem::path k)
: _certificates (c)
, _key (k)
{}
- void sign (xmlpp::Element* parent, bool interop) const;
+ void sign (xmlpp::Element* parent, Standard standard) const;
void add_signature_value (xmlpp::Node* parent, std::string ns) const;
CertificateChain const & certificates () const {
@@ -44,11 +58,12 @@ public:
private:
- void add_signer (xmlpp::Element* parent, std::string ns) const;
-
+ /** Certificate chain to sign with */
CertificateChain _certificates;
/** Filename of signer key */
boost::filesystem::path _key;
};
}
+
+#endif
diff --git a/src/signer_chain.cc b/src/signer_chain.cc
index f35e4ff6..3b75b06c 100644
--- a/src/signer_chain.cc
+++ b/src/signer_chain.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,17 +17,21 @@
*/
-#include <fstream>
-#include <sstream>
-#include <boost/filesystem.hpp>
-#include <boost/algorithm/string.hpp>
-#include <openssl/sha.h>
-#include <openssl/bio.h>
-#include <openssl/evp.h>
-#include "KM_util.h"
+/** @file src/signer_chain.cc
+ * @brief Functions to make signer chains.
+ */
+
#include "signer_chain.h"
#include "exceptions.h"
#include "util.h"
+#include "KM_util.h"
+#include <openssl/sha.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <boost/filesystem.hpp>
+#include <boost/algorithm/string.hpp>
+#include <fstream>
+#include <sstream>
using std::string;
using std::ofstream;
@@ -35,7 +39,11 @@ using std::ifstream;
using std::stringstream;
using std::cout;
-static void command (string cmd)
+/** Run a shell command.
+ * @param cmd Command to run (UTF8-encoded).
+ */
+static void
+command (string cmd)
{
#ifdef LIBDCP_WINDOWS
/* We need to use CreateProcessW on Windows so that the UTF-8/16 mess
@@ -77,16 +85,15 @@ static void command (string cmd)
if (code) {
stringstream s;
s << "error " << code << " in " << cmd << " within " << boost::filesystem::current_path();
- throw libdcp::MiscError (s.str());
+ throw dcp::MiscError (s.str());
}
}
/** Extract a public key from a private key and create a SHA1 digest of it.
- * @param key Private key
+ * @param private_key Private key
* @param openssl openssl binary name (or full path if openssl is not on the system path).
* @return SHA1 digest of corresponding public key, with escaped / characters.
*/
-
static string
public_key_digest (boost::filesystem::path private_key, boost::filesystem::path openssl)
{
@@ -102,7 +109,7 @@ public_key_digest (boost::filesystem::path private_key, boost::filesystem::path
string pub;
ifstream f (public_name.string().c_str ());
if (!f.good ()) {
- throw libdcp::MiscError ("public key not found");
+ throw dcp::MiscError ("public key not found");
}
bool read = false;
@@ -121,22 +128,22 @@ public_key_digest (boost::filesystem::path private_key, boost::filesystem::path
/* Decode the base64 of the public key */
unsigned char buffer[512];
- int const N = libdcp::base64_decode (pub, buffer, 1024);
+ int const N = dcp::base64_decode (pub, buffer, 1024);
/* Hash it with SHA1 (without the first 24 bytes, for reasons that are not entirely clear) */
SHA_CTX context;
if (!SHA1_Init (&context)) {
- throw libdcp::MiscError ("could not init SHA1 context");
+ throw dcp::MiscError ("could not init SHA1 context");
}
if (!SHA1_Update (&context, buffer + 24, N - 24)) {
- throw libdcp::MiscError ("could not update SHA1 digest");
+ throw dcp::MiscError ("could not update SHA1 digest");
}
unsigned char digest[SHA_DIGEST_LENGTH];
if (!SHA1_Final (digest, &context)) {
- throw libdcp::MiscError ("could not finish SHA1 digest");
+ throw dcp::MiscError ("could not finish SHA1 digest");
}
char digest_base64[64];
@@ -149,8 +156,12 @@ public_key_digest (boost::filesystem::path private_key, boost::filesystem::path
return dig;
}
+/** Generate a chain of root, intermediate and leaf keys by running an OpenSSL binary.
+ * @param directory Directory to write the files to.
+ * @param openssl openssl binary path.
+ */
void
-libdcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem::path openssl)
+dcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem::path openssl)
{
boost::filesystem::path const cwd = boost::filesystem::current_path ();
diff --git a/src/signer_chain.h b/src/signer_chain.h
index 50f56ed9..f039caf3 100644
--- a/src/signer_chain.h
+++ b/src/signer_chain.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,9 +17,13 @@
*/
+/** @file src/signer_chain.h
+ * @brief Functions to make signer chains.
+ */
+
#include <boost/filesystem.hpp>
-namespace libdcp {
+namespace dcp {
/** Create a chain of certificates for signing things.
* @param directory Directory to write files to.
diff --git a/src/sound_asset.cc b/src/sound_asset.cc
deleted file mode 100644
index 95244b90..00000000
--- a/src/sound_asset.cc
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/** @file src/sound_asset.cc
- * @brief An asset made up of WAV files
- */
-
-#include <iostream>
-#include <stdexcept>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libxml++/nodes/element.h>
-#include "KM_fileio.h"
-#include "AS_DCP.h"
-#include "sound_asset.h"
-#include "util.h"
-#include "exceptions.h"
-#include "sound_frame.h"
-
-using std::string;
-using std::stringstream;
-using std::ostream;
-using std::vector;
-using std::list;
-using boost::shared_ptr;
-using boost::lexical_cast;
-using namespace libdcp;
-
-SoundAsset::SoundAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name)
- : MXFAsset (directory, mxf_name)
- , _channels (0)
- , _sampling_rate (0)
-{
-
-}
-
-void
-SoundAsset::create (vector<boost::filesystem::path> const & files)
-{
- create (boost::bind (&SoundAsset::path_from_channel, this, _1, files));
-}
-
-void
-SoundAsset::read ()
-{
- ASDCP::PCM::MXFReader reader;
- Kumu::Result_t r = reader.OpenRead (path().string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
- }
-
- ASDCP::PCM::AudioDescriptor desc;
- if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) {
- boost::throw_exception (DCPReadError ("could not read audio MXF information"));
- }
-
- _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator;
- _channels = desc.ChannelCount;
- _edit_rate = desc.EditRate.Numerator;
- assert (desc.EditRate.Denominator == 1);
- _intrinsic_duration = desc.ContainerDuration;
-}
-
-boost::filesystem::path
-SoundAsset::path_from_channel (Channel channel, vector<boost::filesystem::path> const & files)
-{
- unsigned int const c = int (channel);
- assert (c < files.size ());
- return files[c];
-}
-
-void
-SoundAsset::create (boost::function<boost::filesystem::path (Channel)> get_path)
-{
- ASDCP::Rational asdcp_edit_rate (_edit_rate, 1);
-
- assert (_channels > 0);
- ASDCP::PCM::WAVParser* pcm_parser_channel[_channels];
- for (int i = 0; i < _channels; ++i) {
- pcm_parser_channel[i] = new ASDCP::PCM::WAVParser ();
- }
-
- Kumu::Result_t r = pcm_parser_channel[0]->OpenRead (get_path(LEFT).string().c_str(), asdcp_edit_rate);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open WAV file for reading", get_path(LEFT), r));
- }
-
- ASDCP::PCM::AudioDescriptor audio_desc;
- pcm_parser_channel[0]->FillAudioDescriptor (audio_desc);
- audio_desc.ChannelCount = 0;
- audio_desc.BlockAlign = 0;
- audio_desc.EditRate = asdcp_edit_rate;
- audio_desc.AvgBps = audio_desc.AvgBps * _channels;
-
- Channel channels[] = {
- LEFT,
- RIGHT,
- CENTRE,
- LFE,
- LS,
- RS,
- /* XXX: not quite sure what these should be yet */
- CHANNEL_7,
- CHANNEL_8
- };
-
- assert (int(_channels) <= int(sizeof(channels) / sizeof(Channel)));
-
- ASDCP::PCM::FrameBuffer* frame_buffer_channel[_channels];
- ASDCP::PCM::AudioDescriptor* audio_desc_channel[_channels];
- for (int i = 0; i < _channels; ++i) {
- frame_buffer_channel[i] = new ASDCP::PCM::FrameBuffer ();
- audio_desc_channel[i] = new ASDCP::PCM::AudioDescriptor ();
- }
-
- for (int i = 0; i < _channels; ++i) {
-
- boost::filesystem::path const path = get_path (channels[i]);
-
- Kumu::Result_t r = pcm_parser_channel[i]->OpenRead (path.string().c_str(), asdcp_edit_rate);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open WAV file for reading", path, r));
- }
-
- pcm_parser_channel[i]->FillAudioDescriptor (*audio_desc_channel[i]);
- frame_buffer_channel[i]->Capacity (ASDCP::PCM::CalcFrameBufferSize (*audio_desc_channel[i]));
-
- audio_desc.ChannelCount += audio_desc_channel[i]->ChannelCount;
- audio_desc.BlockAlign += audio_desc_channel[i]->BlockAlign;
- }
-
- ASDCP::PCM::FrameBuffer frame_buffer;
- frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (audio_desc));
- frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (audio_desc));
-
- ASDCP::WriterInfo writer_info;
- MXFAsset::fill_writer_info (&writer_info);
-
- ASDCP::PCM::MXFWriter mxf_writer;
- r = mxf_writer.OpenWrite (path().string().c_str(), writer_info, audio_desc);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open audio MXF for writing", path().string(), r));
- }
-
- for (int i = 0; i < _intrinsic_duration; ++i) {
-
- for (int j = 0; j < _channels; ++j) {
- memset (frame_buffer_channel[j]->Data(), 0, frame_buffer_channel[j]->Capacity());
- if (ASDCP_FAILURE (pcm_parser_channel[j]->ReadFrame (*frame_buffer_channel[j]))) {
- boost::throw_exception (MiscError ("could not read audio frame"));
- }
- }
-
- byte_t *data_s = frame_buffer.Data();
- byte_t *data_e = data_s + frame_buffer.Capacity();
- byte_t sample_size = ASDCP::PCM::CalcSampleSize (*audio_desc_channel[0]);
- int offset = 0;
-
- while (data_s < data_e) {
- for (int j = 0; j < _channels; ++j) {
- byte_t* frame = frame_buffer_channel[j]->Data() + offset;
- memcpy (data_s, frame, sample_size);
- data_s += sample_size;
- }
- offset += sample_size;
- }
-
- if (ASDCP_FAILURE (mxf_writer.WriteFrame (frame_buffer, _encryption_context, 0))) {
- boost::throw_exception (MiscError ("could not write audio MXF frame"));
- }
-
- if (_progress) {
- (*_progress) (0.5 * float (i) / _intrinsic_duration);
- }
- }
-
- bool const failed = ASDCP_FAILURE (mxf_writer.Finalize());
-
- for (int i = 0; i < _channels; ++i) {
- delete pcm_parser_channel[i];
- delete frame_buffer_channel[i];
- delete audio_desc_channel[i];
- }
-
- if (failed) {
- boost::throw_exception (MiscError ("could not finalise audio MXF"));
- }
-}
-
-string
-SoundAsset::cpl_node_name () const
-{
- return "MainSound";
-}
-
-bool
-SoundAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
-{
- if (!MXFAsset::equals (other, opt, note)) {
- return false;
- }
-
- ASDCP::PCM::MXFReader reader_A;
- Kumu::Result_t r = reader_A.OpenRead (path().string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
- }
-
- ASDCP::PCM::MXFReader reader_B;
- r = reader_B.OpenRead (other->path().string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
- }
-
- ASDCP::PCM::AudioDescriptor desc_A;
- if (ASDCP_FAILURE (reader_A.FillAudioDescriptor (desc_A))) {
- boost::throw_exception (DCPReadError ("could not read audio MXF information"));
- }
- ASDCP::PCM::AudioDescriptor desc_B;
- if (ASDCP_FAILURE (reader_B.FillAudioDescriptor (desc_B))) {
- boost::throw_exception (DCPReadError ("could not read audio MXF information"));
- }
-
- if (
- desc_A.EditRate != desc_B.EditRate ||
- desc_A.AudioSamplingRate != desc_B.AudioSamplingRate ||
- desc_A.Locked != desc_B.Locked ||
- desc_A.ChannelCount != desc_B.ChannelCount ||
- desc_A.QuantizationBits != desc_B.QuantizationBits ||
- desc_A.BlockAlign != desc_B.BlockAlign ||
- desc_A.AvgBps != desc_B.AvgBps ||
- desc_A.LinkedTrackID != desc_B.LinkedTrackID ||
- desc_A.ContainerDuration != desc_B.ContainerDuration
-// desc_A.ChannelFormat != desc_B.ChannelFormat ||
- ) {
-
- note (ERROR, "audio MXF picture descriptors differ");
- return false;
- }
-
- ASDCP::PCM::FrameBuffer buffer_A (1 * Kumu::Megabyte);
- ASDCP::PCM::FrameBuffer buffer_B (1 * Kumu::Megabyte);
-
- for (int i = 0; i < _intrinsic_duration; ++i) {
- if (ASDCP_FAILURE (reader_A.ReadFrame (i, buffer_A))) {
- boost::throw_exception (DCPReadError ("could not read audio frame"));
- }
-
- if (ASDCP_FAILURE (reader_B.ReadFrame (i, buffer_B))) {
- boost::throw_exception (DCPReadError ("could not read audio frame"));
- }
-
- if (buffer_A.Size() != buffer_B.Size()) {
- note (ERROR, "sizes of audio data for frame " + lexical_cast<string>(i) + " differ");
- return false;
- }
-
- if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) {
- for (uint32_t i = 0; i < buffer_A.Size(); ++i) {
- int const d = abs (buffer_A.RoData()[i] - buffer_B.RoData()[i]);
- if (d > opt.max_audio_sample_error) {
- note (ERROR, "PCM data difference of " + lexical_cast<string> (d));
- return false;
- }
- }
- }
- }
-
- return true;
-}
-
-shared_ptr<const SoundFrame>
-SoundAsset::get_frame (int n) const
-{
- /* XXX: should add on entry point here? */
- return shared_ptr<const SoundFrame> (new SoundFrame (path().string(), n, _decryption_context));
-}
-
-shared_ptr<SoundAssetWriter>
-SoundAsset::start_write ()
-{
- /* XXX: can't we use a shared_ptr here? */
- return shared_ptr<SoundAssetWriter> (new SoundAssetWriter (this));
-}
-
-struct SoundAssetWriter::ASDCPState
-{
- ASDCP::PCM::MXFWriter mxf_writer;
- ASDCP::PCM::FrameBuffer frame_buffer;
- ASDCP::WriterInfo writer_info;
- ASDCP::PCM::AudioDescriptor audio_desc;
- ASDCP::AESEncContext* encryption_context;
-};
-
-SoundAssetWriter::SoundAssetWriter (SoundAsset* a)
- : _state (new SoundAssetWriter::ASDCPState)
- , _asset (a)
- , _finalized (false)
- , _frames_written (0)
- , _frame_buffer_offset (0)
-{
- _state->encryption_context = a->encryption_context ();
-
- /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */
- _state->audio_desc.EditRate = ASDCP::Rational (_asset->edit_rate(), 1);
- _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_asset->sampling_rate(), 1);
- _state->audio_desc.Locked = 0;
- _state->audio_desc.ChannelCount = _asset->channels ();
- _state->audio_desc.QuantizationBits = 24;
- _state->audio_desc.BlockAlign = 3 * _asset->channels();
- _state->audio_desc.AvgBps = _asset->sampling_rate() * _state->audio_desc.BlockAlign;
- _state->audio_desc.LinkedTrackID = 0;
- _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE;
-
- _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
- _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
- memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
-
- _asset->fill_writer_info (&_state->writer_info);
-
- Kumu::Result_t r = _state->mxf_writer.OpenWrite (_asset->path().string().c_str(), _state->writer_info, _state->audio_desc);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (FileError ("could not open audio MXF for writing", _asset->path().string(), r));
- }
-}
-
-void
-SoundAssetWriter::write (float const * const * data, int frames)
-{
- for (int i = 0; i < frames; ++i) {
-
- byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset;
-
- /* Write one sample per channel */
- for (int j = 0; j < _asset->channels(); ++j) {
- int32_t const s = data[j][i] * (1 << 23);
- *out++ = (s & 0xff);
- *out++ = (s & 0xff00) >> 8;
- *out++ = (s & 0xff0000) >> 16;
- }
- _frame_buffer_offset += 3 * _asset->channels();
-
- assert (_frame_buffer_offset <= int (_state->frame_buffer.Capacity()));
-
- /* Finish the MXF frame if required */
- if (_frame_buffer_offset == int (_state->frame_buffer.Capacity())) {
- write_current_frame ();
- _frame_buffer_offset = 0;
- memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
- }
- }
-}
-
-void
-SoundAssetWriter::write_current_frame ()
-{
- ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0);
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MiscError ("could not write audio MXF frame (" + lexical_cast<string> (int (r)) + ")"));
- }
-
- ++_frames_written;
-}
-
-void
-SoundAssetWriter::finalize ()
-{
- if (_frame_buffer_offset > 0) {
- write_current_frame ();
- }
-
- if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) {
- boost::throw_exception (MiscError ("could not finalise audio MXF"));
- }
-
- _finalized = true;
- _asset->set_intrinsic_duration (_frames_written);
- _asset->set_duration (_frames_written);
-}
-
-string
-SoundAsset::key_type () const
-{
- return "MDAK";
-}
diff --git a/src/sound_asset.h b/src/sound_asset.h
deleted file mode 100644
index c52a5436..00000000
--- a/src/sound_asset.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LIBDCP_SOUND_ASSET_H
-#define LIBDCP_SOUND_ASSET_H
-
-/** @file src/sound_asset.h
- * @brief An asset made up of PCM audio data files
- */
-
-#include "mxf_asset.h"
-#include "types.h"
-#include "metadata.h"
-
-namespace libdcp
-{
-
-class SoundFrame;
-class SoundAsset;
-
-class SoundAssetWriter
-{
-public:
- void write (float const * const *, int);
- void finalize ();
-
-private:
- friend class SoundAsset;
-
- SoundAssetWriter (SoundAsset *);
-
- /* no copy construction */
- SoundAssetWriter (SoundAssetWriter const &);
- SoundAssetWriter& operator= (SoundAssetWriter const &);
-
- void write_current_frame ();
-
- /* do this with an opaque pointer so we don't have to include
- ASDCP headers
- */
-
- struct ASDCPState;
- boost::shared_ptr<ASDCPState> _state;
-
- SoundAsset* _asset;
- bool _finalized;
- int _frames_written;
- int _frame_buffer_offset;
-};
-
-/** @brief An asset made up of WAV files */
-class SoundAsset : public MXFAsset
-{
-public:
- SoundAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name);
-
- void read ();
-
- /** The following parameters must be set up (if required) before calling this:
- * Interop mode (set_interop)
- * Edit rate (set_edit_rate)
- * MXF Metadata (set_metadata)
- * Channels (set_channels)
- * Intrinsic duration (set_intrinsic_duration)
- */
- void create (std::vector<boost::filesystem::path> const & files);
-
- /** The following parameters must be set up (if required) before calling this:
- * Interop mode (set_interop)
- * Edit rate (set_edit_rate)
- * MXF Metadata (set_metadata)
- * Channels (set_channels)
- * Intrinsic duration (set_intrinsic_duration)
- */
- void create (boost::function<boost::filesystem::path (Channel)> get_path);
-
- boost::shared_ptr<SoundAssetWriter> start_write ();
-
- bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
-
- boost::shared_ptr<const SoundFrame> get_frame (int n) const;
-
- void set_channels (int c) {
- _channels = c;
- }
-
- int channels () const {
- return _channels;
- }
-
- void set_sampling_rate (int s) {
- _sampling_rate = s;
- }
-
- int sampling_rate () const {
- return _sampling_rate;
- }
-
-protected:
-
- std::string asdcp_kind () const {
- return "Sound";
- }
-
-private:
- std::string key_type () const;
- void construct (boost::function<boost::filesystem::path (Channel)> get_path);
- boost::filesystem::path path_from_channel (Channel channel, std::vector<boost::filesystem::path> const & files);
- std::string cpl_node_name () const;
-
- /** Number of channels in the asset */
- int _channels;
- int _sampling_rate;
-};
-
-}
-
-#endif
diff --git a/src/sound_frame.cc b/src/sound_frame.cc
index 6bc52c1a..c79b29b3 100644
--- a/src/sound_frame.cc
+++ b/src/sound_frame.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,18 +17,22 @@
*/
-#include "AS_DCP.h"
-#include "KM_fileio.h"
+/** @file src/sound_frame.cc
+ * @brief SoundFrame class.
+ */
+
#include "sound_frame.h"
#include "exceptions.h"
+#include "AS_DCP.h"
+#include "KM_fileio.h"
using namespace std;
-using namespace libdcp;
+using namespace dcp;
-SoundFrame::SoundFrame (string mxf_path, int n, ASDCP::AESDecContext* c)
+SoundFrame::SoundFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext* c)
{
ASDCP::PCM::MXFReader reader;
- Kumu::Result_t r = reader.OpenRead (mxf_path.c_str());
+ Kumu::Result_t r = reader.OpenRead (mxf_path.string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (FileError ("could not open MXF file for reading", mxf_path, r));
}
diff --git a/src/sound_frame.h b/src/sound_frame.h
index 154ff84b..26f738d3 100644
--- a/src/sound_frame.h
+++ b/src/sound_frame.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,11 +17,17 @@
*/
+/** @file src/sound_frame.h
+ * @brief SoundFrame class.
+ */
+
#ifndef LIBDCP_SOUND_FRAME_H
#define LIBDCP_SOUND_FRAME_H
-#include <string>
+#include <boost/noncopyable.hpp>
+#include <boost/filesystem.hpp>
#include <stdint.h>
+#include <string>
namespace ASDCP {
namespace PCM {
@@ -30,18 +36,22 @@ namespace ASDCP {
class AESDecContext;
}
-namespace libdcp {
+namespace dcp {
-class SoundFrame
+/** @class SoundFrame
+ * @brief One &lsquo;frame&rsquo; of sound data from a MXF.
+ */
+class SoundFrame : public boost::noncopyable
{
public:
- SoundFrame (std::string mxf_path, int n, ASDCP::AESDecContext *);
+ SoundFrame (boost::filesystem::path mxf_path, int n, ASDCP::AESDecContext *);
~SoundFrame ();
uint8_t const * data () const;
int size () const;
private:
+ /** a buffer to hold the frame */
ASDCP::PCM::FrameBuffer* _buffer;
};
diff --git a/src/sound_mxf.cc b/src/sound_mxf.cc
new file mode 100644
index 00000000..fa48a6c1
--- /dev/null
+++ b/src/sound_mxf.cc
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/sound_mxf.cc
+ * @brief SoundMXF class.
+ */
+
+#include "sound_mxf.h"
+#include "util.h"
+#include "exceptions.h"
+#include "sound_frame.h"
+#include "sound_mxf_writer.h"
+#include "compose.hpp"
+#include "KM_fileio.h"
+#include "AS_DCP.h"
+#include <libxml++/nodes/element.h>
+#include <boost/filesystem.hpp>
+#include <iostream>
+#include <stdexcept>
+
+using std::string;
+using std::stringstream;
+using std::ostream;
+using std::vector;
+using std::list;
+using boost::shared_ptr;
+using namespace dcp;
+
+SoundMXF::SoundMXF (boost::filesystem::path file)
+ : MXF (file)
+ , _channels (0)
+ , _sampling_rate (0)
+{
+ ASDCP::PCM::MXFReader reader;
+ Kumu::Result_t r = reader.OpenRead (file.string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r));
+ }
+
+ ASDCP::PCM::AudioDescriptor desc;
+ if (ASDCP_FAILURE (reader.FillAudioDescriptor (desc))) {
+ boost::throw_exception (DCPReadError ("could not read audio MXF information"));
+ }
+
+ _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator;
+ _channels = desc.ChannelCount;
+ _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator);
+
+ _intrinsic_duration = desc.ContainerDuration;
+
+ ASDCP::WriterInfo info;
+ if (ASDCP_FAILURE (reader.FillWriterInfo (info))) {
+ boost::throw_exception (DCPReadError ("could not read audio MXF information"));
+ }
+
+ read_writer_info (info);
+
+}
+
+SoundMXF::SoundMXF (Fraction edit_rate, int sampling_rate, int channels)
+ : MXF (edit_rate)
+ , _channels (channels)
+ , _sampling_rate (sampling_rate)
+{
+
+}
+
+bool
+SoundMXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
+{
+ if (!MXF::equals (other, opt, note)) {
+ return false;
+ }
+
+ ASDCP::PCM::MXFReader reader_A;
+ Kumu::Result_t r = reader_A.OpenRead (file().string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file().string(), r));
+ }
+
+ ASDCP::PCM::MXFReader reader_B;
+ r = reader_B.OpenRead (other->file().string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file().string(), r));
+ }
+
+ ASDCP::PCM::AudioDescriptor desc_A;
+ if (ASDCP_FAILURE (reader_A.FillAudioDescriptor (desc_A))) {
+ boost::throw_exception (DCPReadError ("could not read audio MXF information"));
+ }
+ ASDCP::PCM::AudioDescriptor desc_B;
+ if (ASDCP_FAILURE (reader_B.FillAudioDescriptor (desc_B))) {
+ boost::throw_exception (DCPReadError ("could not read audio MXF information"));
+ }
+
+ if (
+ desc_A.EditRate != desc_B.EditRate ||
+ desc_A.AudioSamplingRate != desc_B.AudioSamplingRate ||
+ desc_A.Locked != desc_B.Locked ||
+ desc_A.ChannelCount != desc_B.ChannelCount ||
+ desc_A.QuantizationBits != desc_B.QuantizationBits ||
+ desc_A.BlockAlign != desc_B.BlockAlign ||
+ desc_A.AvgBps != desc_B.AvgBps ||
+ desc_A.LinkedTrackID != desc_B.LinkedTrackID ||
+ desc_A.ContainerDuration != desc_B.ContainerDuration
+// desc_A.ChannelFormat != desc_B.ChannelFormat ||
+ ) {
+
+ note (ERROR, "audio MXF picture descriptors differ");
+ return false;
+ }
+
+ ASDCP::PCM::FrameBuffer buffer_A (1 * Kumu::Megabyte);
+ ASDCP::PCM::FrameBuffer buffer_B (1 * Kumu::Megabyte);
+
+ for (int i = 0; i < _intrinsic_duration; ++i) {
+ if (ASDCP_FAILURE (reader_A.ReadFrame (i, buffer_A))) {
+ boost::throw_exception (DCPReadError ("could not read audio frame"));
+ }
+
+ if (ASDCP_FAILURE (reader_B.ReadFrame (i, buffer_B))) {
+ boost::throw_exception (DCPReadError ("could not read audio frame"));
+ }
+
+ if (buffer_A.Size() != buffer_B.Size()) {
+ note (ERROR, String::compose ("sizes of audio data for frame %1 differ", i));
+ return false;
+ }
+
+ if (memcmp (buffer_A.RoData(), buffer_B.RoData(), buffer_A.Size()) != 0) {
+ for (uint32_t i = 0; i < buffer_A.Size(); ++i) {
+ int const d = abs (buffer_A.RoData()[i] - buffer_B.RoData()[i]);
+ if (d > opt.max_audio_sample_error) {
+ note (ERROR, String::compose ("PCM data difference of %1", d));
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+shared_ptr<const SoundFrame>
+SoundMXF::get_frame (int n) const
+{
+ /* XXX: should add on entry point here? */
+ return shared_ptr<const SoundFrame> (new SoundFrame (file(), n, _decryption_context));
+}
+
+shared_ptr<SoundMXFWriter>
+SoundMXF::start_write (boost::filesystem::path file, Standard standard)
+{
+ /* XXX: can't we use a shared_ptr here? */
+ return shared_ptr<SoundMXFWriter> (new SoundMXFWriter (this, file, standard));
+}
+
+string
+SoundMXF::key_type () const
+{
+ return "MDAK";
+}
diff --git a/src/sound_mxf.h b/src/sound_mxf.h
new file mode 100644
index 00000000..50d10957
--- /dev/null
+++ b/src/sound_mxf.h
@@ -0,0 +1,78 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/sound_mxf.h
+ * @brief SoundMXF class
+ */
+
+#ifndef LIBDCP_SOUND_MXF_H
+#define LIBDCP_SOUND_MXF_H
+
+#include "mxf.h"
+#include "types.h"
+#include "metadata.h"
+
+namespace dcp
+{
+
+class SoundFrame;
+class SoundMXFWriter;
+
+/** @class SoundMXF
+ * @brief Representation of a MXF file containing sound
+ */
+class SoundMXF : public MXF
+{
+public:
+ SoundMXF (boost::filesystem::path file);
+ SoundMXF (Fraction edit_rate, int sampling_rate, int channels);
+
+ boost::shared_ptr<SoundMXFWriter> start_write (boost::filesystem::path file, Standard standard);
+
+ bool equals (
+ boost::shared_ptr<const Content> other,
+ EqualityOptions opt,
+ boost::function<void (NoteType, std::string)> note
+ ) const;
+
+ boost::shared_ptr<const SoundFrame> get_frame (int n) const;
+
+ /** @return number of channels */
+ int channels () const {
+ return _channels;
+ }
+
+ /** @return sampling rate in Hz */
+ int sampling_rate () const {
+ return _sampling_rate;
+ }
+
+private:
+ std::string key_type () const;
+ std::string asdcp_kind () const {
+ return "Sound";
+ }
+
+ int _channels; ///< number of channels
+ int _sampling_rate; ///< sampling rate in Hz
+};
+
+}
+
+#endif
diff --git a/src/sound_mxf_writer.cc b/src/sound_mxf_writer.cc
new file mode 100644
index 00000000..51ba7e40
--- /dev/null
+++ b/src/sound_mxf_writer.cc
@@ -0,0 +1,120 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "sound_mxf_writer.h"
+#include "sound_mxf.h"
+#include "exceptions.h"
+#include "compose.hpp"
+#include "AS_DCP.h"
+
+using namespace dcp;
+
+struct SoundMXFWriter::ASDCPState
+{
+ ASDCP::PCM::MXFWriter mxf_writer;
+ ASDCP::PCM::FrameBuffer frame_buffer;
+ ASDCP::WriterInfo writer_info;
+ ASDCP::PCM::AudioDescriptor audio_desc;
+ ASDCP::AESEncContext* encryption_context;
+};
+
+SoundMXFWriter::SoundMXFWriter (SoundMXF* m, boost::filesystem::path file, Standard standard)
+ : MXFWriter (m, file)
+ , _state (new SoundMXFWriter::ASDCPState)
+ , _sound_mxf (m)
+ , _frame_buffer_offset (0)
+{
+ _state->encryption_context = m->encryption_context ();
+
+ /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */
+ _state->audio_desc.EditRate = ASDCP::Rational (_sound_mxf->edit_rate().numerator, _sound_mxf->edit_rate().denominator);
+ _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_sound_mxf->sampling_rate(), 1);
+ _state->audio_desc.Locked = 0;
+ _state->audio_desc.ChannelCount = _sound_mxf->channels ();
+ _state->audio_desc.QuantizationBits = 24;
+ _state->audio_desc.BlockAlign = 3 * _sound_mxf->channels();
+ _state->audio_desc.AvgBps = _sound_mxf->sampling_rate() * _state->audio_desc.BlockAlign;
+ _state->audio_desc.LinkedTrackID = 0;
+ _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE;
+
+ _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
+ _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
+ memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
+
+ _sound_mxf->fill_writer_info (&_state->writer_info, standard);
+
+ Kumu::Result_t r = _state->mxf_writer.OpenWrite (file.string().c_str(), _state->writer_info, _state->audio_desc);
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (FileError ("could not open audio MXF for writing", file.string(), r));
+ }
+}
+
+void
+SoundMXFWriter::write (float const * const * data, int frames)
+{
+ assert (!_finalized);
+
+ for (int i = 0; i < frames; ++i) {
+
+ byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset;
+
+ /* Write one sample per channel */
+ for (int j = 0; j < _sound_mxf->channels(); ++j) {
+ int32_t const s = data[j][i] * (1 << 23);
+ *out++ = (s & 0xff);
+ *out++ = (s & 0xff00) >> 8;
+ *out++ = (s & 0xff0000) >> 16;
+ }
+ _frame_buffer_offset += 3 * _sound_mxf->channels();
+
+ assert (_frame_buffer_offset <= int (_state->frame_buffer.Capacity()));
+
+ /* Finish the MXF frame if required */
+ if (_frame_buffer_offset == int (_state->frame_buffer.Capacity())) {
+ write_current_frame ();
+ _frame_buffer_offset = 0;
+ memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
+ }
+ }
+}
+
+void
+SoundMXFWriter::write_current_frame ()
+{
+ ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0);
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MiscError (String::compose ("could not write audio MXF frame (%1)", int (r))));
+ }
+
+ ++_frames_written;
+}
+
+void
+SoundMXFWriter::finalize ()
+{
+ if (_frame_buffer_offset > 0) {
+ write_current_frame ();
+ }
+
+ if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) {
+ boost::throw_exception (MiscError ("could not finalise audio MXF"));
+ }
+
+ MXFWriter::finalize ();
+}
diff --git a/src/sound_mxf_writer.h b/src/sound_mxf_writer.h
new file mode 100644
index 00000000..4f60074c
--- /dev/null
+++ b/src/sound_mxf_writer.h
@@ -0,0 +1,55 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "mxf_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class SoundFrame;
+class SoundMXF;
+
+class SoundMXFWriter : public MXFWriter
+{
+public:
+ void write (float const * const *, int);
+ void finalize ();
+
+private:
+ friend class SoundMXF;
+
+ SoundMXFWriter (SoundMXF *, boost::filesystem::path, Standard standard);
+
+ void write_current_frame ();
+
+ /* do this with an opaque pointer so we don't have to include
+ ASDCP headers
+ */
+
+ struct ASDCPState;
+ boost::shared_ptr<ASDCPState> _state;
+
+ SoundMXF* _sound_mxf;
+ int _frame_buffer_offset;
+};
+
+}
+
diff --git a/src/stereo_picture_frame.cc b/src/stereo_picture_frame.cc
index dce1f106..0b56b216 100644
--- a/src/stereo_picture_frame.cc
+++ b/src/stereo_picture_frame.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,22 +17,21 @@
*/
-#include <openjpeg.h>
-#include "AS_DCP.h"
-#include "KM_fileio.h"
#include "stereo_picture_frame.h"
#include "exceptions.h"
#include "argb_frame.h"
-#include "lut.h"
#include "util.h"
#include "gamma_lut.h"
#include "rgb_xyz.h"
+#include "AS_DCP.h"
+#include "KM_fileio.h"
+#include <openjpeg.h>
#define DCI_GAMMA 2.6
using std::string;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
/** Make a picture frame from a 3D (stereoscopic) asset.
* @param mxf_path Path to the asset's MXF file.
@@ -59,11 +58,12 @@ StereoPictureFrame::~StereoPictureFrame ()
delete _buffer;
}
-/** @param reduce a factor by which to reduce the resolution
+/** @param eye Eye to return (EYE_LEFT or EYE_RIGHT).
+ * @param reduce a factor by which to reduce the resolution
* of the image, expressed as a power of two (pass 0 for no
* reduction).
- *
- * @param eye Eye to return (EYE_LEFT or EYE_RIGHT).
+ * @param srgb_gamma Reciprocal of gamma to use when doing the
+ * output gamma correction (after conversion from XYZ to RGB).
*
* @return An ARGB representation of one of the eyes (left or right)
* of this frame. This is ARGB in the Cairo sense, so that each
@@ -84,7 +84,7 @@ StereoPictureFrame::argb_frame (Eye eye, int reduce, float srgb_gamma) const
break;
}
- return xyz_to_rgb (xyz_frame, GammaLUT::cache.get (12, DCI_GAMMA), GammaLUT::cache.get (12, 1 / srgb_gamma));
+ return xyz_to_rgb (xyz_frame, GammaLUT::cache.get (12, DCI_GAMMA, false), GammaLUT::cache.get (12, 1 / srgb_gamma, false));
}
uint8_t const *
diff --git a/src/stereo_picture_frame.h b/src/stereo_picture_frame.h
index 878f6ab4..fe363da5 100644
--- a/src/stereo_picture_frame.h
+++ b/src/stereo_picture_frame.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,10 +17,12 @@
*/
-#include <string>
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/filesystem.hpp>
+#include <stdint.h>
+#include <string>
namespace ASDCP {
namespace JP2K {
@@ -29,12 +31,12 @@ namespace ASDCP {
class AESDecContext;
}
-namespace libdcp {
+namespace dcp {
class ARGBFrame;
/** A single frame of a 3D (stereoscopic) picture asset */
-class StereoPictureFrame
+class StereoPictureFrame : public boost::noncopyable
{
public:
StereoPictureFrame (boost::filesystem::path mxf_path, int n);
diff --git a/src/stereo_picture_asset.cc b/src/stereo_picture_mxf.cc
index 47a41cc2..0188e4e7 100644
--- a/src/stereo_picture_asset.cc
+++ b/src/stereo_picture_mxf.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -18,35 +18,78 @@
*/
#include "AS_DCP.h"
-#include "stereo_picture_asset.h"
+#include "stereo_picture_mxf.h"
#include "stereo_picture_frame.h"
#include "exceptions.h"
-#include "stereo_picture_asset_writer.h"
+#include "stereo_picture_mxf_writer.h"
using std::string;
using std::pair;
using std::make_pair;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
-using namespace libdcp;
+using namespace dcp;
+
+StereoPictureMXF::StereoPictureMXF (boost::filesystem::path file)
+ : PictureMXF (file)
+{
+ ASDCP::JP2K::MXFSReader reader;
+ Kumu::Result_t r = reader.OpenRead (file.string().c_str());
+ if (ASDCP_FAILURE (r)) {
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r));
+ }
+
+ ASDCP::JP2K::PictureDescriptor desc;
+ if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
+ boost::throw_exception (DCPReadError ("could not read video MXF information"));
+ }
+
+ read_picture_descriptor (desc);
+
+ ASDCP::WriterInfo info;
+ if (ASDCP_FAILURE (reader.FillWriterInfo (info))) {
+ boost::throw_exception (DCPReadError ("could not read video MXF information"));
+ }
+
+ read_writer_info (info);
+}
+
+StereoPictureMXF::StereoPictureMXF (Fraction edit_rate)
+ : PictureMXF
+ (edit_rate)
+{
+
+}
+
+shared_ptr<const StereoPictureFrame>
+StereoPictureMXF::get_frame (int n) const
+{
+ return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (file().string(), n));
+}
+
+shared_ptr<PictureMXFWriter>
+StereoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
+{
+ return shared_ptr<StereoPictureMXFWriter> (new StereoPictureMXFWriter (this, file, standard, overwrite));
+}
bool
-StereoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
+StereoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
{
- if (!MXFAsset::equals (other, opt, note)) {
+ if (!MXF::equals (other, opt, note)) {
return false;
}
ASDCP::JP2K::MXFSReader reader_A;
- Kumu::Result_t r = reader_A.OpenRead (path().string().c_str());
+ Kumu::Result_t r = reader_A.OpenRead (file().string().c_str());
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file().string(), r));
}
ASDCP::JP2K::MXFSReader reader_B;
- r = reader_B.OpenRead (other->path().string().c_str());
+ r = reader_B.OpenRead (other->file().string().c_str());
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
+ boost::throw_exception (MXFFileError ("could not open MXF file for reading", file().string(), r));
}
ASDCP::JP2K::PictureDescriptor desc_A;
@@ -62,7 +105,7 @@ StereoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt,
return false;
}
- shared_ptr<const StereoPictureAsset> other_picture = dynamic_pointer_cast<const StereoPictureAsset> (other);
+ shared_ptr<const StereoPictureMXF> other_picture = dynamic_pointer_cast<const StereoPictureMXF> (other);
assert (other_picture);
for (int i = 0; i < _intrinsic_duration; ++i) {
@@ -88,63 +131,3 @@ StereoPictureAsset::equals (shared_ptr<const Asset> other, EqualityOptions opt,
return true;
}
-
-StereoPictureAsset::StereoPictureAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name)
- : PictureAsset (directory, mxf_name)
-{
-
-}
-
-void
-StereoPictureAsset::read ()
-{
- ASDCP::JP2K::MXFSReader reader;
- Kumu::Result_t r = reader.OpenRead (path().string().c_str());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", path().string(), r));
- }
-
- ASDCP::JP2K::PictureDescriptor desc;
- if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
- boost::throw_exception (DCPReadError ("could not read video MXF information"));
- }
-
- _size.width = desc.StoredWidth;
- _size.height = desc.StoredHeight;
-}
-
-shared_ptr<const StereoPictureFrame>
-StereoPictureAsset::get_frame (int n) const
-{
- return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (path().string(), n));
-}
-
-shared_ptr<PictureAssetWriter>
-StereoPictureAsset::start_write (bool overwrite)
-{
- return shared_ptr<StereoPictureAssetWriter> (new StereoPictureAssetWriter (this, overwrite));
-}
-
-string
-StereoPictureAsset::cpl_node_name () const
-{
- return "msp-cpl:MainStereoscopicPicture";
-}
-
-pair<string, string>
-StereoPictureAsset::cpl_node_attribute () const
-{
- if (_interop) {
- return make_pair ("xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL");
- } else {
- return make_pair ("xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL");
- }
-
- return make_pair ("", "");
-}
-
-int
-StereoPictureAsset::edit_rate_factor () const
-{
- return 2;
-}
diff --git a/src/stereo_picture_asset.h b/src/stereo_picture_mxf.h
index 64cdb6b3..dc4605c7 100644
--- a/src/stereo_picture_asset.h
+++ b/src/stereo_picture_mxf.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,31 +17,30 @@
*/
-#ifndef LIBDCP_STEREO_PICTURE_ASSET_H
-#define LIBDCP_STEREO_PICTURE_ASSET_H
+#ifndef LIBDCP_STEREO_PICTURE_MXF_H
+#define LIBDCP_STEREO_PICTURE_MXF_H
-#include "picture_asset.h"
+#include "picture_mxf.h"
-namespace libdcp {
+namespace dcp {
/** A 3D (stereoscopic) picture asset */
-class StereoPictureAsset : public PictureAsset
+class StereoPictureMXF : public PictureMXF
{
public:
- StereoPictureAsset (boost::filesystem::path directory, boost::filesystem::path mxf_name);
+ StereoPictureMXF (boost::filesystem::path file);
+ StereoPictureMXF (Fraction edit_rate);
- void read ();
-
- /** Start a progressive write to a StereoPictureAsset */
- boost::shared_ptr<PictureAssetWriter> start_write (bool);
+ /** Start a progressive write to a StereoPictureMXF */
+ boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, Standard, bool);
+ bool equals (
+ boost::shared_ptr<const Content> other,
+ EqualityOptions opt,
+ boost::function<void (NoteType, std::string)> note
+ ) const;
+
boost::shared_ptr<const StereoPictureFrame> get_frame (int n) const;
- bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
-
-private:
- std::string cpl_node_name () const;
- std::pair<std::string, std::string> cpl_node_attribute () const;
- int edit_rate_factor () const;
};
}
diff --git a/src/stereo_picture_asset_writer.cc b/src/stereo_picture_mxf_writer.cc
index b4b0ad52..4f98c60e 100644
--- a/src/stereo_picture_asset_writer.cc
+++ b/src/stereo_picture_mxf_writer.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,37 +17,38 @@
*/
+#include "stereo_picture_mxf_writer.h"
+#include "exceptions.h"
+#include "picture_mxf.h"
#include "AS_DCP.h"
#include "KM_fileio.h"
-#include "stereo_picture_asset_writer.h"
-#include "exceptions.h"
-#include "picture_asset.h"
-#include "picture_asset_writer_common.cc"
+#include "picture_mxf_writer_common.cc"
using std::istream;
using std::ostream;
using std::string;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
-struct StereoPictureAssetWriter::ASDCPState : public ASDCPStateBase
+struct StereoPictureMXFWriter::ASDCPState : public ASDCPStateBase
{
ASDCP::JP2K::MXFSWriter mxf_writer;
};
-StereoPictureAssetWriter::StereoPictureAssetWriter (PictureAsset* asset, bool overwrite)
- : PictureAssetWriter (asset, overwrite)
- , _state (new StereoPictureAssetWriter::ASDCPState)
+StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite)
+ : PictureMXFWriter (mxf, file, standard, overwrite)
+ , _state (new StereoPictureMXFWriter::ASDCPState)
, _next_eye (EYE_LEFT)
{
- _state->encryption_context = asset->encryption_context ();
+ _state->encryption_context = mxf->encryption_context ();
}
void
-StereoPictureAssetWriter::start (uint8_t* data, int size)
+StereoPictureMXFWriter::start (uint8_t* data, int size)
{
- libdcp::start (this, _state, _asset, data, size);
+ dcp::start (this, _state, _standard, _picture_mxf, data, size);
+ _picture_mxf->set_frame_rate (Fraction (_picture_mxf->edit_rate().numerator * 2, _picture_mxf->edit_rate().denominator));
}
/** Write a frame for one eye. Frames must be written left, then right, then left etc.
@@ -55,7 +56,7 @@ StereoPictureAssetWriter::start (uint8_t* data, int size)
* @param size Size of data.
*/
FrameInfo
-StereoPictureAssetWriter::write (uint8_t* data, int size)
+StereoPictureMXFWriter::write (uint8_t* data, int size)
{
assert (!_finalized);
@@ -79,41 +80,42 @@ StereoPictureAssetWriter::write (uint8_t* data, int size)
);
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string(), r));
+ boost::throw_exception (MXFFileError ("error in writing video MXF", _mxf->file().string(), r));
}
_next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
- ++_frames_written;
+ if (_next_eye == EYE_LEFT) {
+ ++_frames_written;
+ }
+
return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
void
-StereoPictureAssetWriter::fake_write (int size)
+StereoPictureMXFWriter::fake_write (int size)
{
assert (_started);
assert (!_finalized);
Kumu::Result_t r = _state->mxf_writer.FakeWriteFrame (size, _next_eye == EYE_LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT);
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in writing video MXF", _asset->path().string(), r));
+ boost::throw_exception (MXFFileError ("error in writing video MXF", _mxf->file().string(), r));
}
_next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
- ++_frames_written;
+ if (_next_eye == EYE_LEFT) {
+ ++_frames_written;
+ }
}
void
-StereoPictureAssetWriter::finalize ()
+StereoPictureMXFWriter::finalize ()
{
- assert (!_finalized);
-
Kumu::Result_t r = _state->mxf_writer.Finalize();
if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("error in finalizing video MXF", _asset->path().string(), r));
+ boost::throw_exception (MXFFileError ("error in finalizing video MXF", _mxf->file().string(), r));
}
- _finalized = true;
- _asset->set_intrinsic_duration (_frames_written / 2);
- _asset->set_duration (_frames_written / 2);
+ PictureMXFWriter::finalize ();
}
diff --git a/src/stereo_picture_asset_writer.h b/src/stereo_picture_mxf_writer.h
index 771524c4..ebd9dbec 100644
--- a/src/stereo_picture_asset_writer.h
+++ b/src/stereo_picture_mxf_writer.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,14 +17,15 @@
*/
+#include "picture_mxf_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
#include <stdint.h>
#include <string>
#include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include "picture_asset_writer.h"
-namespace libdcp {
+namespace dcp {
/** A helper class for writing to StereoPictureAssets progressively (i.e. writing frame-by-frame,
* rather than giving libdcp all the frames in one go).
@@ -36,7 +37,7 @@ namespace libdcp {
* The action of finalize() can't be done in MonoPictureAssetWriter's destructor as it may
* throw an exception.
*/
-class StereoPictureAssetWriter : public PictureAssetWriter
+class StereoPictureMXFWriter : public PictureMXFWriter
{
public:
FrameInfo write (uint8_t *, int);
@@ -44,9 +45,9 @@ public:
void finalize ();
private:
- friend class StereoPictureAsset;
+ friend class StereoPictureMXF;
- StereoPictureAssetWriter (PictureAsset *, bool);
+ StereoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard, bool);
void start (uint8_t *, int);
/* do this with an opaque pointer so we don't have to include
@@ -56,7 +57,7 @@ private:
struct ASDCPState;
boost::shared_ptr<ASDCPState> _state;
- libdcp::Eye _next_eye;
+ dcp::Eye _next_eye;
};
}
diff --git a/src/subtitle.cc b/src/subtitle.cc
new file mode 100644
index 00000000..8c40254a
--- /dev/null
+++ b/src/subtitle.cc
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "subtitle.h"
+#include "xml.h"
+#include "font.h"
+#include "text.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+Subtitle::Subtitle (boost::shared_ptr<const cxml::Node> node)
+{
+ in = Time (node->string_attribute ("TimeIn"));
+ out = Time (node->string_attribute ("TimeOut"));
+ font_nodes = type_children<Font> (node, "Font");
+ text_nodes = type_children<Text> (node, "Text");
+ fade_up_time = fade_time (node, "FadeUpTime");
+ fade_down_time = fade_time (node, "FadeDownTime");
+}
+
+Time
+Subtitle::fade_time (shared_ptr<const cxml::Node> node, string name)
+{
+ string const u = node->optional_string_attribute (name).get_value_or ("");
+ Time t;
+
+ if (u.empty ()) {
+ t = Time (0, 0, 0, 20);
+ } else if (u.find (":") != string::npos) {
+ t = Time (u);
+ } else {
+ t = Time (0, 0, 0, lexical_cast<int> (u));
+ }
+
+ if (t > Time (0, 0, 8, 0)) {
+ t = Time (0, 0, 8, 0);
+ }
+
+ return t;
+}
diff --git a/src/lut.h b/src/subtitle.h
index ad291467..073bfb0c 100644
--- a/src/lut.h
+++ b/src/subtitle.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,45 +17,37 @@
*/
-#ifndef LIBDCP_LUT_H
-#define LIBDCP_LUT_H
+#ifndef LIBDCP_SUBTITLE_H
+#define LIBDCP_SUBTITLE_H
-#include <cmath>
-#include <boost/utility.hpp>
+#include "dcp_time.h"
+#include <boost/shared_ptr.hpp>
+#include <list>
-namespace libdcp {
+namespace cxml {
+ class Node;
+}
+
+namespace dcp {
+
+class Font;
+class Text;
-class LUT : boost::noncopyable
+class Subtitle
{
public:
- LUT(int bit_depth, float gamma)
- : _lut(0)
- , _bit_depth (bit_depth)
- , _gamma (gamma)
- {
- _lut = new float[int(std::pow(2.0f, _bit_depth))];
- }
-
- virtual ~LUT() {
- delete[] _lut;
- }
-
- float const * lut() const {
- return _lut;
- }
-
- int bit_depth () const {
- return _bit_depth;
- }
-
- float gamma () const {
- return _gamma;
- }
-
-protected:
- float* _lut;
- int _bit_depth;
- float _gamma;
+ Subtitle () {}
+ Subtitle (boost::shared_ptr<const cxml::Node> node);
+
+ Time in;
+ Time out;
+ Time fade_up_time;
+ Time fade_down_time;
+ std::list<boost::shared_ptr<Font> > font_nodes;
+ std::list<boost::shared_ptr<Text> > text_nodes;
+
+private:
+ Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name);
};
}
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
deleted file mode 100644
index a7ec641c..00000000
--- a/src/subtitle_asset.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#ifndef LIBDCP_SUBTITLE_ASSET_H
-#define LIBDCP_SUBTITLE_ASSET_H
-
-#include <libcxml/cxml.h>
-#include "asset.h"
-#include "dcp_time.h"
-
-namespace libdcp
-{
-
-namespace parse
-{
- class Font;
- class Text;
- class Subtitle;
- class LoadFont;
-}
-
-class Subtitle
-{
-public:
- Subtitle (
- std::string font,
- bool italic,
- Color color,
- int size,
- Time in,
- Time out,
- float v_position,
- VAlign v_align,
- std::string text,
- Effect effect,
- Color effect_color,
- Time fade_up_time,
- Time fade_down_time
- );
-
- std::string font () const {
- return _font;
- }
-
- bool italic () const {
- return _italic;
- }
-
- Color color () const {
- return _color;
- }
-
- Time in () const {
- return _in;
- }
-
- Time out () const {
- return _out;
- }
-
- std::string text () const {
- return _text;
- }
-
- float v_position () const {
- return _v_position;
- }
-
- VAlign v_align () const {
- return _v_align;
- }
-
- Effect effect () const {
- return _effect;
- }
-
- Color effect_color () const {
- return _effect_color;
- }
-
- Time fade_up_time () const {
- return _fade_up_time;
- }
-
- Time fade_down_time () const {
- return _fade_down_time;
- }
-
- int size () const {
- return _size;
- }
-
- int size_in_pixels (int screen_height) const;
-
-private:
- std::string _font;
- bool _italic;
- Color _color;
- /** Size in points as if the screen height is 11 inches, so a 72pt font
- * would be 1/11th of the screen height.
- */
- int _size;
- Time _in;
- Time _out;
- /** Vertical position as a proportion of the screen height from the top
- * (between 0 and 1)
- */
- float _v_position;
- VAlign _v_align;
- std::string _text;
- Effect _effect;
- Color _effect_color;
- Time _fade_up_time;
- Time _fade_down_time;
-};
-
-bool operator== (Subtitle const & a, Subtitle const & b);
-std::ostream& operator<< (std::ostream& s, Subtitle const & sub);
-
-class SubtitleAsset : public Asset
-{
-public:
- SubtitleAsset (std::string directory, std::string xml_file);
- SubtitleAsset (std::string directory, std::string movie_title, std::string language);
-
- void write_to_cpl (xmlpp::Element *) const;
- virtual bool equals (boost::shared_ptr<const Asset>, EqualityOptions, boost::function<void (NoteType, std::string)> note) const {
- /* XXX */
- note (ERROR, "subtitle assets not compared yet");
- return true;
- }
-
- std::string language () const {
- return _language;
- }
-
- std::list<boost::shared_ptr<Subtitle> > subtitles_at (Time t) const;
- std::list<boost::shared_ptr<Subtitle> > const & subtitles () const {
- return _subtitles;
- }
-
- void add (boost::shared_ptr<Subtitle>);
-
- void read_xml (std::string);
- void write_xml () const;
- Glib::ustring xml_as_string () const;
-
-protected:
-
- std::string asdcp_kind () const {
- return "Subtitle";
- }
-
-private:
- std::string font_id_to_name (std::string id) const;
- void read_mxf (std::string);
- void read_xml (boost::shared_ptr<cxml::Document>);
-
- struct ParseState {
- std::list<boost::shared_ptr<parse::Font> > font_nodes;
- std::list<boost::shared_ptr<parse::Text> > text_nodes;
- std::list<boost::shared_ptr<parse::Subtitle> > subtitle_nodes;
- };
-
- void maybe_add_subtitle (std::string text, ParseState const & parse_state);
-
- void examine_font_nodes (
- boost::shared_ptr<const cxml::Node> xml,
- std::list<boost::shared_ptr<parse::Font> > const & font_nodes,
- ParseState& parse_state
- );
-
- void examine_text_nodes (
- boost::shared_ptr<const cxml::Node> xml,
- std::list<boost::shared_ptr<parse::Text> > const & text_nodes,
- ParseState& parse_state
- );
-
- boost::optional<std::string> _movie_title;
- /* strangely, this is sometimes a string */
- std::string _reel_number;
- std::string _language;
- std::list<boost::shared_ptr<parse::LoadFont> > _load_font_nodes;
-
- std::list<boost::shared_ptr<Subtitle> > _subtitles;
- bool _need_sort;
-};
-
-}
-
-#endif
diff --git a/src/subtitle_asset.cc b/src/subtitle_content.cc
index 4eb1a9cd..f338517e 100644
--- a/src/subtitle_asset.cc
+++ b/src/subtitle_content.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,17 +17,17 @@
*/
-#include <fstream>
-#include <cerrno>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <libxml++/nodes/element.h>
-#include "AS_DCP.h"
-#include "KM_util.h"
-#include "subtitle_asset.h"
-#include "parse/subtitle.h"
+#include "subtitle_content.h"
#include "util.h"
#include "xml.h"
+#include "font.h"
+#include "text.h"
+#include "load_font.h"
+#include "subtitle_string.h"
+#include <libxml++/nodes/element.h>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+#include <fstream>
using std::string;
using std::list;
@@ -38,117 +38,56 @@ using std::cout;
using boost::shared_ptr;
using boost::lexical_cast;
using boost::optional;
-using namespace libdcp;
+using namespace dcp;
-SubtitleAsset::SubtitleAsset (string directory, string file)
- : Asset (directory, file)
- , _need_sort (false)
-{
- /* Grotesque hack: we should look in the PKL to see what type this file is;
- instead we'll look at the first character to decide what to do.
- I think this is easily fixable (properly) in 1.0.
- */
-
- FILE* f = fopen_boost (path(), "r");
- if (!f) {
- throw FileError ("Could not open file for reading", file, errno);
- }
- unsigned char test[1];
- fread (test, 1, 1, f);
- fclose (f);
-
- if (test[0] == '<' || test[0] == 0xef) {
- read_xml (path().string());
- } else {
- read_mxf (path().string());
- }
-}
-
-SubtitleAsset::SubtitleAsset (string directory, string movie_title, string language)
- : Asset (directory)
- , _movie_title (movie_title)
- , _reel_number ("1")
- , _language (language)
+SubtitleContent::SubtitleContent (boost::filesystem::path file)
+ : Content (file)
, _need_sort (false)
{
-
-}
-
-void
-SubtitleAsset::read_mxf (string mxf_file)
-{
- ASDCP::TimedText::MXFReader reader;
- Kumu::Result_t r = reader.OpenRead (mxf_file.c_str ());
- if (ASDCP_FAILURE (r)) {
- boost::throw_exception (MXFFileError ("could not open MXF file for reading", mxf_file, r));
- }
-
- string s;
- reader.ReadTimedTextResource (s, 0, 0);
- shared_ptr<cxml::Document> xml (new cxml::Document ("SubtitleReel"));
- stringstream t;
- t << s;
- xml->read_stream (t);
- read_xml (xml);
-}
-
-void
-SubtitleAsset::read_xml (string xml_file)
-{
shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
- xml->read_file (xml_file);
- read_xml (xml);
-}
-
-void
-SubtitleAsset::read_xml (shared_ptr<cxml::Document> xml)
-{
- /* XXX: hacks aplenty in here; need separate parsers for DCSubtitle and SubtitleReel */
+ xml->read_file (file);
- /* DCSubtitle */
- optional<string> x = xml->optional_string_child ("SubtitleID");
- if (!x) {
- /* SubtitleReel */
- x = xml->optional_string_child ("Id");
- }
- _uuid = x.get_value_or ("");
-
- _movie_title = xml->optional_string_child ("MovieTitle");
+ _id = xml->string_child ("SubtitleID");
+ _movie_title = xml->string_child ("MovieTitle");
_reel_number = xml->string_child ("ReelNumber");
_language = xml->string_child ("Language");
xml->ignore_child ("LoadFont");
- list<shared_ptr<libdcp::parse::Font> > font_nodes = type_children<libdcp::parse::Font> (xml, "Font");
- _load_font_nodes = type_children<libdcp::parse::LoadFont> (xml, "LoadFont");
+ list<shared_ptr<dcp::Font> > font_nodes = type_children<dcp::Font> (xml, "Font");
+ _load_font_nodes = type_children<dcp::LoadFont> (xml, "LoadFont");
/* Now make Subtitle objects to represent the raw XML nodes
in a sane way.
*/
-
- shared_ptr<cxml::Node> subtitle_list = xml->optional_node_child ("SubtitleList");
- if (subtitle_list) {
- list<shared_ptr<libdcp::parse::Font> > font = type_children<libdcp::parse::Font> (subtitle_list, "Font");
- copy (font.begin(), font.end(), back_inserter (font_nodes));
- }
ParseState parse_state;
examine_font_nodes (xml, font_nodes, parse_state);
}
+SubtitleContent::SubtitleContent (Fraction edit_rate, string movie_title, string language)
+ : Content (edit_rate)
+ , _movie_title (movie_title)
+ , _reel_number ("1")
+ , _language (language)
+ , _need_sort (false)
+{
+
+}
+
void
-SubtitleAsset::examine_font_nodes (
+SubtitleContent::examine_font_nodes (
shared_ptr<const cxml::Node> xml,
- list<shared_ptr<libdcp::parse::Font> > const & font_nodes,
+ list<shared_ptr<dcp::Font> > const & font_nodes,
ParseState& parse_state
)
{
- for (list<shared_ptr<libdcp::parse::Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
+ for (list<shared_ptr<dcp::Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
parse_state.font_nodes.push_back (*i);
maybe_add_subtitle ((*i)->text, parse_state);
- for (list<shared_ptr<libdcp::parse::Subtitle> >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) {
+ for (list<shared_ptr<dcp::Subtitle> >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) {
parse_state.subtitle_nodes.push_back (*j);
examine_text_nodes (xml, (*j)->text_nodes, parse_state);
examine_font_nodes (xml, (*j)->font_nodes, parse_state);
@@ -163,13 +102,13 @@ SubtitleAsset::examine_font_nodes (
}
void
-SubtitleAsset::examine_text_nodes (
+SubtitleContent::examine_text_nodes (
shared_ptr<const cxml::Node> xml,
- list<shared_ptr<libdcp::parse::Text> > const & text_nodes,
+ list<shared_ptr<dcp::Text> > const & text_nodes,
ParseState& parse_state
)
{
- for (list<shared_ptr<libdcp::parse::Text> >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) {
+ for (list<shared_ptr<dcp::Text> >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) {
parse_state.text_nodes.push_back (*i);
maybe_add_subtitle ((*i)->text, parse_state);
examine_font_nodes (xml, (*i)->font_nodes, parse_state);
@@ -178,7 +117,7 @@ SubtitleAsset::examine_text_nodes (
}
void
-SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
+SubtitleContent::maybe_add_subtitle (string text, ParseState const & parse_state)
{
if (empty_or_white_space (text)) {
return;
@@ -191,13 +130,13 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
assert (!parse_state.text_nodes.empty ());
assert (!parse_state.subtitle_nodes.empty ());
- libdcp::parse::Font effective_font (parse_state.font_nodes);
- libdcp::parse::Text effective_text (*parse_state.text_nodes.back ());
- libdcp::parse::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ());
+ dcp::Font effective_font (parse_state.font_nodes);
+ dcp::Text effective_text (*parse_state.text_nodes.back ());
+ dcp::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ());
_subtitles.push_back (
- shared_ptr<Subtitle> (
- new Subtitle (
+ shared_ptr<SubtitleString> (
+ new SubtitleString (
font_id_to_name (effective_font.id),
effective_font.italic.get(),
effective_font.color.get(),
@@ -216,11 +155,11 @@ SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
);
}
-list<shared_ptr<Subtitle> >
-SubtitleAsset::subtitles_at (Time t) const
+list<shared_ptr<SubtitleString> >
+SubtitleContent::subtitles_at (Time t) const
{
- list<shared_ptr<Subtitle> > s;
- for (list<shared_ptr<Subtitle> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+ list<shared_ptr<SubtitleString> > s;
+ for (list<shared_ptr<SubtitleString> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
if ((*i)->in() <= t && t <= (*i)->out ()) {
s.push_back (*i);
}
@@ -230,9 +169,9 @@ SubtitleAsset::subtitles_at (Time t) const
}
std::string
-SubtitleAsset::font_id_to_name (string id) const
+SubtitleContent::font_id_to_name (string id) const
{
- list<shared_ptr<libdcp::parse::LoadFont> >::const_iterator i = _load_font_nodes.begin();
+ list<shared_ptr<dcp::LoadFont> >::const_iterator i = _load_font_nodes.begin();
while (i != _load_font_nodes.end() && (*i)->id != id) {
++i;
}
@@ -241,116 +180,22 @@ SubtitleAsset::font_id_to_name (string id) const
return "";
}
- if ((*i)->uri && (*i)->uri.get() == "arial.ttf") {
+ if ((*i)->uri == "arial.ttf") {
return "Arial";
}
return "";
}
-Subtitle::Subtitle (
- string font,
- bool italic,
- Color color,
- int size,
- Time in,
- Time out,
- float v_position,
- VAlign v_align,
- string text,
- Effect effect,
- Color effect_color,
- Time fade_up_time,
- Time fade_down_time
- )
- : _font (font)
- , _italic (italic)
- , _color (color)
- , _size (size)
- , _in (in)
- , _out (out)
- , _v_position (v_position)
- , _v_align (v_align)
- , _text (text)
- , _effect (effect)
- , _effect_color (effect_color)
- , _fade_up_time (fade_up_time)
- , _fade_down_time (fade_down_time)
-{
-
-}
-
-int
-Subtitle::size_in_pixels (int screen_height) const
-{
- /* Size in the subtitle file is given in points as if the screen
- height is 11 inches, so a 72pt font would be 1/11th of the screen
- height.
- */
-
- return _size * screen_height / (11 * 72);
-}
-
-bool
-libdcp::operator== (Subtitle const & a, Subtitle const & b)
-{
- return (
- a.font() == b.font() &&
- a.italic() == b.italic() &&
- a.color() == b.color() &&
- a.size() == b.size() &&
- a.in() == b.in() &&
- a.out() == b.out() &&
- a.v_position() == b.v_position() &&
- a.v_align() == b.v_align() &&
- a.text() == b.text() &&
- a.effect() == b.effect() &&
- a.effect_color() == b.effect_color() &&
- a.fade_up_time() == b.fade_up_time() &&
- a.fade_down_time() == b.fade_down_time()
- );
-}
-
-ostream&
-libdcp::operator<< (ostream& s, Subtitle const & sub)
-{
- s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
- << "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
- << "font " << sub.font() << ", ";
-
- if (sub.italic()) {
- s << "italic";
- } else {
- s << "non-italic";
- }
-
- s << ", size " << sub.size() << ", color " << sub.color() << ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align()) << ";\n"
- << "effect " << ((int) sub.effect()) << ", effect color " << sub.effect_color();
-
- return s;
-}
-
void
-SubtitleAsset::add (shared_ptr<Subtitle> s)
+SubtitleContent::add (shared_ptr<SubtitleString> s)
{
_subtitles.push_back (s);
_need_sort = true;
}
-void
-SubtitleAsset::write_to_cpl (xmlpp::Element* node) const
-{
- /* XXX: should EditRate, Duration and IntrinsicDuration be in here? */
-
- xmlpp::Node* ms = node->add_child ("MainSubtitle");
- ms->add_child("Id")->add_child_text("urn:uuid:" + _uuid);
- ms->add_child("AnnotationText")->add_child_text (_file_name.string ());
- /* XXX */
- ms->add_child("EntryPoint")->add_child_text ("0");
-}
-
struct SubtitleSorter {
- bool operator() (shared_ptr<Subtitle> a, shared_ptr<Subtitle> b) {
+ bool operator() (shared_ptr<SubtitleString> a, shared_ptr<SubtitleString> b) {
if (a->in() != b->in()) {
return a->in() < b->in();
}
@@ -359,25 +204,23 @@ struct SubtitleSorter {
};
void
-SubtitleAsset::write_xml () const
+SubtitleContent::write_xml () const
{
- FILE* f = fopen_boost (path (), "r");
+ FILE* f = fopen_boost (file (), "r");
Glib::ustring const s = xml_as_string ();
fwrite (s.c_str(), 1, s.length(), f);
fclose (f);
}
Glib::ustring
-SubtitleAsset::xml_as_string () const
+SubtitleContent::xml_as_string () const
{
xmlpp::Document doc;
xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
root->set_attribute ("Version", "1.0");
- root->add_child("SubtitleID")->add_child_text (_uuid);
- if (_movie_title) {
- root->add_child("MovieTitle")->add_child_text (_movie_title.get ());
- }
+ root->add_child("SubtitleID")->add_child_text (_id);
+ root->add_child("MovieTitle")->add_child_text (_movie_title);
root->add_child("ReelNumber")->add_child_text (lexical_cast<string> (_reel_number));
root->add_child("Language")->add_child_text (_language);
@@ -388,12 +231,10 @@ SubtitleAsset::xml_as_string () const
if (!_load_font_nodes.empty ()) {
xmlpp::Element* load_font = root->add_child("LoadFont");
load_font->set_attribute("Id", _load_font_nodes.front()->id);
- if (_load_font_nodes.front()->uri) {
- load_font->set_attribute("URI", _load_font_nodes.front()->uri.get ());
- }
+ load_font->set_attribute("URI", _load_font_nodes.front()->uri);
}
- list<shared_ptr<Subtitle> > sorted = _subtitles;
+ list<shared_ptr<SubtitleString> > sorted = _subtitles;
if (_need_sort) {
sorted.sort (SubtitleSorter ());
}
@@ -415,7 +256,7 @@ SubtitleAsset::xml_as_string () const
xmlpp::Element* font = 0;
xmlpp::Element* subtitle = 0;
- for (list<shared_ptr<Subtitle> >::iterator i = sorted.begin(); i != sorted.end(); ++i) {
+ for (list<shared_ptr<SubtitleString> >::iterator i = sorted.begin(); i != sorted.end(); ++i) {
/* We will start a new <Font>...</Font> whenever some font property changes.
I suppose we should really make an optimal hierarchy of <Font> tags, but
diff --git a/src/subtitle_content.h b/src/subtitle_content.h
new file mode 100644
index 00000000..410c5934
--- /dev/null
+++ b/src/subtitle_content.h
@@ -0,0 +1,113 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_SUBTITLE_CONTENT_H
+#define LIBDCP_SUBTITLE_CONTENT_H
+
+#include "content.h"
+#include "dcp_time.h"
+#include <libcxml/cxml.h>
+
+namespace dcp
+{
+
+class SubtitleString;
+class Font;
+class Text;
+class Subtitle;
+class LoadFont;
+
+/** @class SubtitleContent
+ * @brief A representation of an XML file containing subtitles.
+ */
+class SubtitleContent : public Content
+{
+public:
+ SubtitleContent (boost::filesystem::path file);
+ SubtitleContent (Fraction edit_rate, std::string movie_title, std::string language);
+
+ bool equals (
+ boost::shared_ptr<const Content>,
+ EqualityOptions,
+ boost::function<void (NoteType, std::string)> note
+ ) const {
+ /* XXX */
+ note (ERROR, "subtitle content not compared yet");
+ return true;
+ }
+
+ std::string language () const {
+ return _language;
+ }
+
+ std::list<boost::shared_ptr<SubtitleString> > subtitles_at (Time t) const;
+ std::list<boost::shared_ptr<SubtitleString> > const & subtitles () const {
+ return _subtitles;
+ }
+
+ void add (boost::shared_ptr<SubtitleString>);
+
+ void write_xml () const;
+ Glib::ustring xml_as_string () const;
+
+protected:
+ std::string pkl_type (Standard) const {
+ return "text/xml";
+ }
+
+ std::string asdcp_kind () const {
+ return "Subtitle";
+ }
+
+private:
+ std::string font_id_to_name (std::string id) const;
+
+ struct ParseState {
+ std::list<boost::shared_ptr<Font> > font_nodes;
+ std::list<boost::shared_ptr<Text> > text_nodes;
+ std::list<boost::shared_ptr<Subtitle> > subtitle_nodes;
+ };
+
+ void maybe_add_subtitle (std::string text, ParseState const & parse_state);
+
+ void examine_font_nodes (
+ boost::shared_ptr<const cxml::Node> xml,
+ std::list<boost::shared_ptr<Font> > const & font_nodes,
+ ParseState& parse_state
+ );
+
+ void examine_text_nodes (
+ boost::shared_ptr<const cxml::Node> xml,
+ std::list<boost::shared_ptr<Text> > const & text_nodes,
+ ParseState& parse_state
+ );
+
+ std::string _movie_title;
+ /* strangely, this is sometimes a string */
+ std::string _reel_number;
+ std::string _language;
+ std::list<boost::shared_ptr<LoadFont> > _load_font_nodes;
+
+ std::list<boost::shared_ptr<SubtitleString> > _subtitles;
+ bool _need_sort;
+};
+
+}
+
+#endif
diff --git a/src/subtitle_string.cc b/src/subtitle_string.cc
new file mode 100644
index 00000000..66869fd5
--- /dev/null
+++ b/src/subtitle_string.cc
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "subtitle_string.h"
+#include "xml.h"
+
+using std::string;
+using std::ostream;
+using namespace dcp;
+
+SubtitleString::SubtitleString (
+ string font,
+ bool italic,
+ Color color,
+ int size,
+ Time in,
+ Time out,
+ float v_position,
+ VAlign v_align,
+ string text,
+ Effect effect,
+ Color effect_color,
+ Time fade_up_time,
+ Time fade_down_time
+ )
+ : _font (font)
+ , _italic (italic)
+ , _color (color)
+ , _size (size)
+ , _in (in)
+ , _out (out)
+ , _v_position (v_position)
+ , _v_align (v_align)
+ , _text (text)
+ , _effect (effect)
+ , _effect_color (effect_color)
+ , _fade_up_time (fade_up_time)
+ , _fade_down_time (fade_down_time)
+{
+
+}
+
+int
+SubtitleString::size_in_pixels (int screen_height) const
+{
+ /* Size in the subtitle file is given in points as if the screen
+ height is 11 inches, so a 72pt font would be 1/11th of the screen
+ height.
+ */
+
+ return _size * screen_height / (11 * 72);
+}
+
+bool
+dcp::operator== (SubtitleString const & a, SubtitleString const & b)
+{
+ return (
+ a.font() == b.font() &&
+ a.italic() == b.italic() &&
+ a.color() == b.color() &&
+ a.size() == b.size() &&
+ a.in() == b.in() &&
+ a.out() == b.out() &&
+ a.v_position() == b.v_position() &&
+ a.v_align() == b.v_align() &&
+ a.text() == b.text() &&
+ a.effect() == b.effect() &&
+ a.effect_color() == b.effect_color() &&
+ a.fade_up_time() == b.fade_up_time() &&
+ a.fade_down_time() == b.fade_down_time()
+ );
+}
+
+ostream&
+dcp::operator<< (ostream& s, SubtitleString const & sub)
+{
+ s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
+ << "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
+ << "font " << sub.font() << ", ";
+
+ if (sub.italic()) {
+ s << "italic";
+ } else {
+ s << "non-italic";
+ }
+
+ s << ", size " << sub.size() << ", color " << sub.color() << ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align()) << ";\n"
+ << "effect " << ((int) sub.effect()) << ", effect color " << sub.effect_color();
+
+ return s;
+}
diff --git a/src/subtitle_string.h b/src/subtitle_string.h
new file mode 100644
index 00000000..076a6ec7
--- /dev/null
+++ b/src/subtitle_string.h
@@ -0,0 +1,129 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#ifndef LIBDCP_SUBTITLE_STRING_H
+#define LIBDCP_SUBTITLE_STRING_H
+
+#include "types.h"
+#include "dcp_time.h"
+#include <string>
+
+namespace dcp {
+
+class SubtitleString
+{
+public:
+ SubtitleString (
+ std::string font,
+ bool italic,
+ Color color,
+ int size,
+ Time in,
+ Time out,
+ float v_position,
+ VAlign v_align,
+ std::string text,
+ Effect effect,
+ Color effect_color,
+ Time fade_up_time,
+ Time fade_down_time
+ );
+
+ std::string font () const {
+ return _font;
+ }
+
+ bool italic () const {
+ return _italic;
+ }
+
+ Color color () const {
+ return _color;
+ }
+
+ Time in () const {
+ return _in;
+ }
+
+ Time out () const {
+ return _out;
+ }
+
+ std::string text () const {
+ return _text;
+ }
+
+ float v_position () const {
+ return _v_position;
+ }
+
+ VAlign v_align () const {
+ return _v_align;
+ }
+
+ Effect effect () const {
+ return _effect;
+ }
+
+ Color effect_color () const {
+ return _effect_color;
+ }
+
+ Time fade_up_time () const {
+ return _fade_up_time;
+ }
+
+ Time fade_down_time () const {
+ return _fade_down_time;
+ }
+
+ int size () const {
+ return _size;
+ }
+
+ int size_in_pixels (int screen_height) const;
+
+private:
+ std::string _font;
+ bool _italic;
+ Color _color;
+ /** Size in points as if the screen height is 11 inches, so a 72pt font
+ * would be 1/11th of the screen height.
+ */
+ int _size;
+ Time _in;
+ Time _out;
+ /** Vertical position as a proportion of the screen height from the top
+ * (between 0 and 1)
+ */
+ float _v_position;
+ VAlign _v_align;
+ std::string _text;
+ Effect _effect;
+ Color _effect_color;
+ Time _fade_up_time;
+ Time _fade_down_time;
+};
+
+bool operator== (SubtitleString const & a, SubtitleString const & b);
+std::ostream& operator<< (std::ostream& s, SubtitleString const & sub);
+
+}
+
+#endif
diff --git a/src/text.cc b/src/text.cc
new file mode 100644
index 00000000..888cab29
--- /dev/null
+++ b/src/text.cc
@@ -0,0 +1,49 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+/** @file src/text.cc
+ * @brief Text class for parsing subtitle XML.
+ */
+
+#include "text.h"
+#include "xml.h"
+#include "font.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using boost::optional;
+using namespace dcp;
+
+/** Read a &lt;Text&gt; node from a subtitle XML file, noting its contents
+ * in this object's member variables.
+ * @param node Node to read.
+ */
+Text::Text (boost::shared_ptr<const cxml::Node> node)
+ : v_align (CENTER)
+{
+ text = node->content ();
+ v_position = node->number_attribute<float> ("VPosition");
+ optional<string> v = node->optional_string_attribute ("VAlign");
+ if (v) {
+ v_align = string_to_valign (v.get ());
+ }
+
+ font_nodes = type_children<Font> (node, "Font");
+}
diff --git a/src/parse/pkl.h b/src/text.h
index 13d87fa1..268d146c 100644
--- a/src/parse/pkl.h
+++ b/src/text.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,44 +17,40 @@
*/
-/** @file src/parse/pkl.h
- * @brief Classes used to parse a PKL
+/** @file src/text.h
+ * @brief Text class for parsing subtitle XML.
*/
+#include "types.h"
#include <boost/shared_ptr.hpp>
-#include "../xml.h"
+#include <list>
-namespace libdcp {
+namespace cxml {
+ class Node;
+}
-namespace parse {
+namespace dcp {
-class PKLAsset
-{
-public:
- PKLAsset () {}
- PKLAsset (boost::shared_ptr<const cxml::Node>);
-
- std::string id;
- std::string annotation_text;
- std::string hash;
- int64_t size;
- std::string type;
- std::string original_file_name;
-};
+class Font;
-class PKL
+/** @class Text
+ * @brief Parser for Text nodes from subtitle XML.
+ */
+class Text
{
public:
- PKL (std::string file);
-
- std::string id;
- std::string annotation_text;
- std::string issue_date;
- std::string issuer;
- std::string creator;
- std::list<boost::shared_ptr<PKLAsset> > assets;
-};
+ /** Construct a default text node */
+ Text ()
+ : v_position (0)
+ , v_align (TOP)
+ {}
-}
+ Text (boost::shared_ptr<const cxml::Node> node);
+
+ float v_position;
+ VAlign v_align;
+ std::string text;
+ std::list<boost::shared_ptr<Font> > font_nodes;
+};
}
diff --git a/src/types.cc b/src/types.cc
index 693b9ab2..0ecf7a16 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -1,15 +1,37 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "types.h"
+#include "exceptions.h"
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
#include <vector>
#include <cstdio>
#include <iomanip>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include "types.h"
-#include "exceptions.h"
using namespace std;
-using namespace libdcp;
+using namespace dcp;
using namespace boost;
+/** Construct a Fraction from a string of the form <numerator> <denominator>
+ * e.g. "1 3".
+ */
Fraction::Fraction (string s)
{
vector<string> b;
@@ -22,17 +44,18 @@ Fraction::Fraction (string s)
}
bool
-libdcp::operator== (Fraction const & a, Fraction const & b)
+dcp::operator== (Fraction const & a, Fraction const & b)
{
return (a.numerator == b.numerator && a.denominator == b.denominator);
}
bool
-libdcp::operator!= (Fraction const & a, Fraction const & b)
+dcp::operator!= (Fraction const & a, Fraction const & b)
{
return (a.numerator != b.numerator || a.denominator != b.denominator);
}
+/** Construct a Color, initialising it to black. */
Color::Color ()
: r (0)
, g (0)
@@ -41,6 +64,9 @@ Color::Color ()
}
+/** Construct a Color from R, G and B. The values run between
+ * 0 and 255.
+ */
Color::Color (int r_, int g_, int b_)
: r (r_)
, g (g_)
@@ -84,7 +110,7 @@ Color::to_argb_string () const
* @param b Second color to compare.
*/
bool
-libdcp::operator== (Color const & a, Color const & b)
+dcp::operator== (Color const & a, Color const & b)
{
return (a.r == b.r && a.g == b.g && a.b == b.b);
}
@@ -94,20 +120,20 @@ libdcp::operator== (Color const & a, Color const & b)
* @param b Second color to compare.
*/
bool
-libdcp::operator!= (Color const & a, Color const & b)
+dcp::operator!= (Color const & a, Color const & b)
{
return !(a == b);
}
ostream &
-libdcp::operator<< (ostream& s, Color const & c)
+dcp::operator<< (ostream& s, Color const & c)
{
s << "(" << c.r << ", " << c.g << ", " << c.b << ")";
return s;
}
string
-libdcp::effect_to_string (Effect e)
+dcp::effect_to_string (Effect e)
{
switch (e) {
case NONE:
@@ -122,7 +148,7 @@ libdcp::effect_to_string (Effect e)
}
Effect
-libdcp::string_to_effect (string s)
+dcp::string_to_effect (string s)
{
if (s == "none") {
return NONE;
@@ -136,7 +162,7 @@ libdcp::string_to_effect (string s)
}
string
-libdcp::valign_to_string (VAlign v)
+dcp::valign_to_string (VAlign v)
{
switch (v) {
case TOP:
@@ -151,7 +177,7 @@ libdcp::valign_to_string (VAlign v)
}
VAlign
-libdcp::string_to_valign (string s)
+dcp::string_to_valign (string s)
{
if (s == "top") {
return TOP;
diff --git a/src/types.h b/src/types.h
index 013c1863..ece7d44c 100644
--- a/src/types.h
+++ b/src/types.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -24,10 +24,10 @@
#ifndef LIBDCP_TYPES_H
#define LIBDCP_TYPES_H
-#include <string>
#include <boost/shared_ptr.hpp>
+#include <string>
-namespace libdcp
+namespace dcp
{
namespace parse {
@@ -85,12 +85,20 @@ enum Eye
EYE_LEFT,
EYE_RIGHT
};
-
+
+/** @class Fraction
+ * @brief A fraction (i.e. a thing with an integer numerator and an integer denominator).
+ */
class Fraction
{
public:
+ /** Construct a fraction of 0/0 */
Fraction () : numerator (0), denominator (0) {}
Fraction (std::string s);
+ /** Construct a fraction with a specified numerator and denominator.
+ * @param n Numerator.
+ * @param d Denominator.
+ */
Fraction (int n, int d) : numerator (n), denominator (d) {}
int numerator;
@@ -99,20 +107,33 @@ public:
extern bool operator== (Fraction const & a, Fraction const & b);
extern bool operator!= (Fraction const & a, Fraction const & b);
-
-struct EqualityOptions {
+
+/** @struct EqualityOptions
+ * @brief A class to describe what "equality" means for a particular test.
+ *
+ * When comparing things, we want to be able to ignore some differences;
+ * this class expresses those differences.
+ */
+struct EqualityOptions
+{
+ /** Construct an EqualityOptions where nothing at all can differ */
EqualityOptions ()
: max_mean_pixel_error (0)
, max_std_dev_pixel_error (0)
, max_audio_sample_error (0)
- , cpl_names_can_differ (false)
+ , cpl_annotation_texts_can_differ (false)
, mxf_names_can_differ (false)
{}
+ /** The maximum allowable mean difference in pixel value between two images */
double max_mean_pixel_error;
+ /** The maximum standard deviation of the differences in pixel value between two images */
double max_std_dev_pixel_error;
+ /** The maximum difference in audio sample value between two soundtracks */
int max_audio_sample_error;
- bool cpl_names_can_differ;
+ /** true if the <AnnotationText> nodes of CPLs are allowed to differ */
+ bool cpl_annotation_texts_can_differ;
+ /** true if MXF filenames are allowed to differ */
bool mxf_names_can_differ;
};
@@ -125,6 +146,11 @@ enum NoteType {
NOTE
};
+enum Standard {
+ INTEROP,
+ SMPTE
+};
+
/** @class Color
* @brief An RGB color (aka colour).
*/
diff --git a/src/util.cc b/src/util.cc
index a668b7fc..1e32fbc9 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -21,22 +21,6 @@
* @brief Utility methods.
*/
-#include <stdexcept>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <openssl/sha.h>
-#include <libxml++/nodes/element.h>
-#include <libxml++/document.h>
-#include <xmlsec/xmldsig.h>
-#include <xmlsec/dl.h>
-#include <xmlsec/app.h>
-#include <xmlsec/crypto.h>
-#include "KM_util.h"
-#include "KM_fileio.h"
-#include "AS_DCP.h"
#include "util.h"
#include "exceptions.h"
#include "types.h"
@@ -44,6 +28,22 @@
#include "certificates.h"
#include "gamma_lut.h"
#include "xyz_frame.h"
+#include "compose.hpp"
+#include "KM_util.h"
+#include "KM_fileio.h"
+#include "AS_DCP.h"
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/app.h>
+#include <xmlsec/crypto.h>
+#include <libxml++/nodes/element.h>
+#include <libxml++/document.h>
+#include <openssl/sha.h>
+#include <boost/filesystem.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
using std::string;
using std::wstring;
@@ -54,15 +54,17 @@ using std::max;
using std::list;
using std::setw;
using std::setfill;
+using std::ostream;
using boost::shared_ptr;
-using boost::lexical_cast;
-using namespace libdcp;
+using boost::optional;
+using boost::function;
+using namespace dcp;
/** Create a UUID.
* @return UUID.
*/
string
-libdcp::make_uuid ()
+dcp::make_uuid ()
{
char buffer[64];
Kumu::UUID id;
@@ -74,15 +76,15 @@ libdcp::make_uuid ()
/** Create a digest for a file.
* @param filename File name.
- * @param progress Pointer to a progress reporting function, or 0. The function will be called
+ * @param progress Optional progress reporting function. The function will be called
* with a progress value between 0 and 1.
* @return Digest.
*/
string
-libdcp::make_digest (string filename, boost::function<void (float)>* progress)
+dcp::make_digest (boost::filesystem::path filename, function<void (float)> progress)
{
Kumu::FileReader reader;
- Kumu::Result_t r = reader.OpenRead (filename.c_str ());
+ Kumu::Result_t r = reader.OpenRead (filename.string().c_str ());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (FileError ("could not open file to compute digest", filename, r));
}
@@ -108,7 +110,7 @@ libdcp::make_digest (string filename, boost::function<void (float)>* progress)
SHA1_Update (&sha, read_buffer.Data(), read);
if (progress) {
- (*progress) (float (done) / size);
+ progress (float (done) / size);
done += read;
}
}
@@ -121,12 +123,12 @@ libdcp::make_digest (string filename, boost::function<void (float)>* progress)
}
/** Convert a content kind to a string which can be used in a
- * <ContentKind> node.
+ * &lt;ContentKind&gt; node.
* @param kind ContentKind.
* @return string.
*/
string
-libdcp::content_kind_to_string (ContentKind kind)
+dcp::content_kind_to_string (ContentKind kind)
{
switch (kind) {
case FEATURE:
@@ -154,35 +156,35 @@ libdcp::content_kind_to_string (ContentKind kind)
assert (false);
}
-/** Convert a string from a <ContentKind> node to a libdcp ContentKind.
+/** Convert a string from a &lt;ContentKind&gt; node to a libdcp ContentKind.
* Reasonably tolerant about varying case.
- * @param type Content kind string.
+ * @param kind Content kind string.
* @return libdcp ContentKind.
*/
-libdcp::ContentKind
-libdcp::content_kind_from_string (string type)
+dcp::ContentKind
+dcp::content_kind_from_string (string kind)
{
- transform (type.begin(), type.end(), type.begin(), ::tolower);
+ transform (kind.begin(), kind.end(), kind.begin(), ::tolower);
- if (type == "feature") {
+ if (kind == "feature") {
return FEATURE;
- } else if (type == "short") {
+ } else if (kind == "short") {
return SHORT;
- } else if (type == "trailer") {
+ } else if (kind == "trailer") {
return TRAILER;
- } else if (type == "test") {
+ } else if (kind == "test") {
return TEST;
- } else if (type == "transitional") {
+ } else if (kind == "transitional") {
return TRANSITIONAL;
- } else if (type == "rating") {
+ } else if (kind == "rating") {
return RATING;
- } else if (type == "teaser") {
+ } else if (kind == "teaser") {
return TEASER;
- } else if (type == "policy") {
+ } else if (kind == "policy") {
return POLICY;
- } else if (type == "psa") {
+ } else if (kind == "psa") {
return PUBLIC_SERVICE_ANNOUNCEMENT;
- } else if (type == "advertisement") {
+ } else if (kind == "advertisement") {
return ADVERTISEMENT;
}
@@ -198,8 +200,8 @@ libdcp::content_kind_from_string (string type)
* This is useful for scaling 4K DCP images down to 2K.
* @return XYZ image.
*/
-shared_ptr<libdcp::XYZFrame>
-libdcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
+shared_ptr<dcp::XYZFrame>
+dcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
{
opj_dinfo_t* decoder = opj_create_decompress (CODEC_J2K);
opj_dparameters_t parameters;
@@ -211,7 +213,7 @@ libdcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
if (!image) {
opj_destroy_decompress (decoder);
opj_cio_close (cio);
- boost::throw_exception (DCPReadError ("could not decode JPEG2000 codestream of " + lexical_cast<string> (size) + " bytes."));
+ boost::throw_exception (DCPReadError (String::compose ("could not decode JPEG2000 codestream of %1 bytes.", size)));
}
opj_destroy_decompress (decoder);
@@ -226,7 +228,7 @@ libdcp::decompress_j2k (uint8_t* data, int64_t size, int reduce)
* @return true if the string contains only space, newline or tab characters, or is empty.
*/
bool
-libdcp::empty_or_white_space (string s)
+dcp::empty_or_white_space (string s)
{
for (size_t i = 0; i < s.length(); ++i) {
if (s[i] != ' ' && s[i] != '\n' && s[i] != '\t') {
@@ -237,8 +239,11 @@ libdcp::empty_or_white_space (string s)
return true;
}
+/** Set up various bits that the library needs. Should be called one
+ * by client applications.
+ */
void
-libdcp::init ()
+dcp::init ()
{
if (xmlSecInit() < 0) {
throw MiscError ("could not initialise xmlsec");
@@ -259,21 +264,33 @@ libdcp::init ()
}
}
-bool libdcp::operator== (libdcp::Size const & a, libdcp::Size const & b)
+bool dcp::operator== (dcp::Size const & a, dcp::Size const & b)
{
return (a.width == b.width && a.height == b.height);
}
-bool libdcp::operator!= (libdcp::Size const & a, libdcp::Size const & b)
+bool dcp::operator!= (dcp::Size const & a, dcp::Size const & b)
{
return !(a == b);
}
-/** The base64 decode routine in KM_util.cpp gives different values to both
- * this and the command-line base64 for some inputs. Not sure why.
+ostream& dcp::operator<< (ostream& s, dcp::Size const & a)
+{
+ s << a.width << "x" << a.height;
+ return s;
+}
+
+/** Decode a base64 string. The base64 decode routine in KM_util.cpp
+ * gives different values to both this and the command-line base64
+ * for some inputs. Not sure why.
+ *
+ * @param in base64-encoded string.
+ * @param out Output buffer.
+ * @param out_length Length of output buffer.
+ * @return Number of characters written to the output buffer.
*/
int
-libdcp::base64_decode (string const & in, unsigned char* out, int out_length)
+dcp::base64_decode (string const & in, unsigned char* out, int out_length)
{
BIO* b64 = BIO_new (BIO_f_base64 ());
@@ -297,8 +314,13 @@ libdcp::base64_decode (string const & in, unsigned char* out, int out_length)
return N;
}
+/** Convert a struct tm to a string of the form
+ * 2014-01-26T21:39:00+01:00
+ * @param tm struct tm.
+ * @return Time as a string.
+ */
string
-libdcp::tm_to_string (struct tm* tm)
+dcp::tm_to_string (struct tm* tm)
{
char buffer[64];
strftime (buffer, 64, "%Y-%m-%dT%H:%M:%S", tm);
@@ -320,7 +342,7 @@ libdcp::tm_to_string (struct tm* tm)
* @return string of the form e.g. -01:00.
*/
string
-libdcp::utc_offset_to_string (int b)
+dcp::utc_offset_to_string (int b)
{
bool const negative = (b < 0);
b = negative ? -b : b;
@@ -339,20 +361,29 @@ libdcp::utc_offset_to_string (int b)
return o.str ();
}
+/** Convert a boost::posix_time::ptime to a string of the form
+ * 2014-01-26T21:39:00+01:00.
+ * @param t boost::posix_time::ptime.
+ * @return Time as a string.
+ */
string
-libdcp::ptime_to_string (boost::posix_time::ptime t)
+dcp::ptime_to_string (boost::posix_time::ptime t)
{
struct tm t_tm = boost::posix_time::to_tm (t);
return tm_to_string (&t_tm);
}
-/* Apparently there is no way to create an ofstream using a UTF-8
- filename under Windows. We are hence reduced to using fopen
- with this wrapper.
-*/
+/** @param p Path to open.
+ * @param t mode flags, as for fopen(3).
+ * @return FILE pointer or 0 on error.
+ *
+ * Apparently there is no way to create an ofstream using a UTF-8
+ * filename under Windows. We are hence reduced to using fopen
+ * with this wrapper.
+ */
FILE *
-libdcp::fopen_boost (boost::filesystem::path p, string t)
+dcp::fopen_boost (boost::filesystem::path p, string t)
{
#ifdef LIBDCP_WINDOWS
wstring w (t.begin(), t.end());
@@ -362,3 +393,26 @@ libdcp::fopen_boost (boost::filesystem::path p, string t)
return fopen (p.c_str(), t.c_str ());
#endif
}
+
+optional<boost::filesystem::path>
+dcp::relative_to_root (boost::filesystem::path root, boost::filesystem::path file)
+{
+ boost::filesystem::path::const_iterator i = root.begin ();
+ boost::filesystem::path::const_iterator j = file.begin ();
+
+ while (i != root.end() && j != file.end() && *i == *j) {
+ ++i;
+ ++j;
+ }
+
+ if (i != root.end ()) {
+ return optional<boost::filesystem::path> ();
+ }
+
+ boost::filesystem::path rel;
+ while (j != file.end ()) {
+ rel /= *j++;
+ }
+
+ return rel;
+}
diff --git a/src/util.h b/src/util.h
index 2a6aae1b..ca00ecb9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -24,27 +24,32 @@
* @brief Utility methods.
*/
-#include <string>
-#include <stdint.h>
+#include "types.h"
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/filesystem.hpp>
+#include <boost/optional.hpp>
#include <openjpeg.h>
-#include "types.h"
+#include <string>
+#include <stdint.h>
namespace xmlpp {
class Element;
}
-namespace libdcp {
+namespace dcp {
class ARGBFrame;
class CertificateChain;
class GammaLUT;
class XYZFrame;
-struct Size {
+/** @struct Size
+ * @brief The integer, two-dimensional size of something.
+ */
+struct Size
+{
Size ()
: width (0)
, height (0)
@@ -65,9 +70,10 @@ struct Size {
extern bool operator== (Size const & a, Size const & b);
extern bool operator!= (Size const & a, Size const & b);
+extern std::ostream& operator<< (std::ostream& s, Size const & a);
extern std::string make_uuid ();
-extern std::string make_digest (std::string filename, boost::function<void (float)> *);
+extern std::string make_digest (boost::filesystem::path filename, boost::function<void (float)>);
extern std::string content_kind_to_string (ContentKind kind);
extern ContentKind content_kind_from_string (std::string kind);
extern bool empty_or_white_space (std::string s);
@@ -75,16 +81,31 @@ extern boost::shared_ptr<XYZFrame> decompress_j2k (uint8_t* data, int64_t size,
extern void init ();
-extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, bool interop);
+extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, Standard standard);
extern void add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, std::string const & ns);
extern void add_signer (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & ns);
extern int base64_decode (std::string const & in, unsigned char* out, int out_length);
-
+extern boost::optional<boost::filesystem::path> relative_to_root (boost::filesystem::path root, boost::filesystem::path file);
extern std::string tm_to_string (struct tm *);
extern std::string utc_offset_to_string (int);
extern std::string ptime_to_string (boost::posix_time::ptime);
extern FILE * fopen_boost (boost::filesystem::path, std::string);
+
+template <class F, class T>
+std::list<boost::shared_ptr<T> >
+list_of_type (std::list<boost::shared_ptr<F> > const & from)
+{
+ std::list<boost::shared_ptr<T> > out;
+ for (typename std::list<boost::shared_ptr<F> >::const_iterator i = from.begin(); i != from.end(); ++i) {
+ boost::shared_ptr<T> check = boost::dynamic_pointer_cast<T> (*i);
+ if (check) {
+ out.push_back (check);
+ }
+ }
+
+ return out;
+}
}
diff --git a/src/version.h b/src/version.h
index 52abd13a..9b6dc65f 100644
--- a/src/version.h
+++ b/src/version.h
@@ -1,5 +1,5 @@
-namespace libdcp {
+namespace dcp {
extern char const * version;
extern char const * git_commit;
diff --git a/src/wscript b/src/wscript
index cdf3c062..c06ca1bd 100644
--- a/src/wscript
+++ b/src/wscript
@@ -6,51 +6,61 @@ def build(bld):
else:
obj = bld(features = 'cxx cxxshlib')
- obj.name = 'libdcp'
- obj.target = 'dcp'
+ obj.name = 'libdcp%s' % bld.env.API_VERSION
+ obj.target = 'dcp%s' % bld.env.API_VERSION
obj.export_includes = ['.']
obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1'
- obj.use = 'libkumu-libdcp libasdcp-libdcp'
+ obj.use = 'libkumu-libdcp%s libasdcp-libdcp%s' % (bld.env.API_VERSION, bld.env.API_VERSION)
obj.source = """
argb_frame.cc
asset.cc
certificates.cc
colour_matrix.cc
+ content.cc
cpl.cc
dcp.cc
dcp_time.cc
exceptions.cc
+ file.cc
+ font.cc
gamma_lut.cc
image.cc
kdm.cc
key.cc
+ load_font.cc
metadata.cc
- mono_picture_asset.cc
- mono_picture_asset_writer.cc
+ mono_picture_mxf.cc
+ mono_picture_mxf_writer.cc
mono_picture_frame.cc
- mxf_asset.cc
- picture_asset.cc
- picture_asset_writer.cc
- rec709_linearised_gamma_lut.cc
+ mxf.cc
+ mxf_writer.cc
+ object.cc
+ picture_mxf.cc
+ picture_mxf_writer.cc
reel.cc
+ reel_asset.cc
+ reel_mono_picture_asset.cc
+ reel_picture_asset.cc
+ reel_sound_asset.cc
+ reel_stereo_picture_asset.cc
+ reel_subtitle_asset.cc
rgb_xyz.cc
signer.cc
signer_chain.cc
- sound_asset.cc
+ sound_mxf.cc
+ sound_mxf_writer.cc
sound_frame.cc
- srgb_linearised_gamma_lut.cc
- stereo_picture_asset.cc
- stereo_picture_asset_writer.cc
+ stereo_picture_mxf.cc
+ stereo_picture_mxf_writer.cc
stereo_picture_frame.cc
- subtitle_asset.cc
+ subtitle.cc
+ subtitle_content.cc
+ subtitle_string.cc
+ text.cc
types.cc
util.cc
version.cc
xyz_frame.cc
- parse/asset_map.cc
- parse/cpl.cc
- parse/pkl.cc
- parse/subtitle.cc
"""
headers = """
@@ -58,6 +68,7 @@ def build(bld):
certificates.h
colour_matrix.h
cpl.h
+ content.h
dcp.h
dcp_time.h
exceptions.h
@@ -65,32 +76,40 @@ def build(bld):
image.h
kdm.h
key.h
- lut.h
lut_cache.h
metadata.h
- mono_picture_asset.h
+ mono_picture_mxf.h
mono_picture_frame.h
- mxf_asset.h
- picture_asset.h
- picture_asset_writer.h
+ mxf.h
+ mxf_writer.h
+ object.h
+ picture_mxf.h
+ picture_mxf_writer.h
rgb_xyz.h
- rec709_linearised_gamma_lut.h
reel.h
+ reel_asset.h
+ reel_mono_picture_asset.h
+ reel_picture_asset.h
+ reel_sound_asset.h
+ reel_stereo_picture_asset.h
+ ref.h
argb_frame.h
signer.h
signer_chain.h
- sound_asset.h
sound_frame.h
- srgb_linearised_gamma_lut.h
- stereo_picture_asset.h
+ sound_mxf.h
+ sound_mxf_writer.h
+ stereo_picture_mxf.h
stereo_picture_frame.h
- subtitle_asset.h
+ subtitle.h
+ subtitle_content.h
+ subtitle_string.h
types.h
util.h
version.h
xyz_frame.h
"""
- bld.install_files('${PREFIX}/include/libdcp', headers)
+ bld.install_files('${PREFIX}/include/libdcp%s/dcp' % bld.env.API_VERSION, headers)
if bld.env.STATIC:
- bld.install_files('${PREFIX}/lib', 'libdcp.a')
+ bld.install_files('${PREFIX}/lib', 'libdcp%s.a' % bld.env.API_VERSION)
diff --git a/src/xml.h b/src/xml.h
index 5978ff7e..b89d8ccd 100644
--- a/src/xml.h
+++ b/src/xml.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -20,10 +20,10 @@
#ifndef LIBDCP_XML_H
#define LIBDCP_XML_H
-#include <libcxml/cxml.h>
#include "exceptions.h"
+#include <libcxml/cxml.h>
-namespace libdcp
+namespace dcp
{
template <class T>
diff --git a/src/xyz_frame.cc b/src/xyz_frame.cc
index f5b0ee86..cba90883 100644
--- a/src/xyz_frame.cc
+++ b/src/xyz_frame.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,11 +17,15 @@
*/
+/** @file src/xyz_frame.cc
+ * @brief XZYFrame class.
+ */
+
+#include "xyz_frame.h"
#include <cassert>
#include <stdexcept>
-#include "xyz_frame.h"
-using namespace libdcp;
+using namespace dcp;
/** Construct an XYZFrame, taking ownership of the opj_image_t */
XYZFrame::XYZFrame (opj_image_t* image)
@@ -30,6 +34,9 @@ XYZFrame::XYZFrame (opj_image_t* image)
assert (_opj_image->numcomps == 3);
}
+/** Construct a new XYZFrame with undefined contents.
+ * @param size Size for the frame in pixels.
+ */
XYZFrame::XYZFrame (Size size)
{
opj_image_cmptparm_t cmptparm[3];
@@ -58,11 +65,15 @@ XYZFrame::XYZFrame (Size size)
_opj_image->y1 = size.height;
}
+/** XYZFrame destructor */
XYZFrame::~XYZFrame ()
{
opj_image_destroy (_opj_image);
}
+/** @param c Component index (0, 1 or 2)
+ * @return Pointer to the data for component c.
+ */
int *
XYZFrame::data (int c) const
{
@@ -70,9 +81,10 @@ XYZFrame::data (int c) const
return _opj_image->comps[c].data;
}
-libdcp::Size
+/** @return Size of the image in pixels */
+dcp::Size
XYZFrame::size () const
{
/* XXX: this may not be right; x0 and y0 can presumably be non-zero */
- return libdcp::Size (_opj_image->x1, _opj_image->y1);
+ return dcp::Size (_opj_image->x1, _opj_image->y1);
}
diff --git a/src/xyz_frame.h b/src/xyz_frame.h
index a4dcb2c0..8ba829b2 100644
--- a/src/xyz_frame.h
+++ b/src/xyz_frame.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,12 +17,21 @@
*/
-#include <openjpeg.h>
+/** @file src/xyz_frame.h
+ * @brief XZYFrame class.
+ */
+
#include "util.h"
+#include <openjpeg.h>
-namespace libdcp {
+namespace dcp {
-class XYZFrame
+/** @class XYZFrame
+ * @brief An image in XYZ colour.
+ *
+ * This class is a thin wrapper of libopenjpeg's opj_image_t.
+ */
+class XYZFrame : public boost::noncopyable
{
public:
XYZFrame (opj_image_t *);
@@ -30,14 +39,17 @@ public:
~XYZFrame ();
int* data (int) const;
- libdcp::Size size () const;
+ dcp::Size size () const;
+ /** @return Pointer to opj_image_t struct. The caller
+ * must not delete this.
+ */
opj_image_t* opj_image () const {
return _opj_image;
}
private:
- opj_image_t* _opj_image;
+ opj_image_t* _opj_image; ///< opj_image_t that we are managing
};
}
diff --git a/test/certificates_test.cc b/test/certificates_test.cc
index 0a66bc66..690afa77 100644
--- a/test/certificates_test.cc
+++ b/test/certificates_test.cc
@@ -25,15 +25,15 @@ using boost::shared_ptr;
BOOST_AUTO_TEST_CASE (certificates)
{
- libdcp::CertificateChain c;
+ dcp::CertificateChain c;
- c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem"))));
- c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem"))));
- c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem"))));
+ c.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem"))));
+ c.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem"))));
+ c.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem"))));
- list<shared_ptr<libdcp::Certificate> > leaf_to_root = c.leaf_to_root ();
+ list<shared_ptr<dcp::Certificate> > leaf_to_root = c.leaf_to_root ();
- list<shared_ptr<libdcp::Certificate> >::iterator i = leaf_to_root.begin ();
+ list<shared_ptr<dcp::Certificate> >::iterator i = leaf_to_root.begin ();
/* Leaf */
BOOST_CHECK_EQUAL (*i, c.leaf ());
@@ -78,6 +78,6 @@ BOOST_AUTO_TEST_CASE (certificates)
);
/* Check that reconstruction from a string works */
- libdcp::Certificate test (c.root()->certificate (true));
+ dcp::Certificate test (c.root()->certificate (true));
BOOST_CHECK_EQUAL (test.certificate(), c.root()->certificate());
}
diff --git a/test/color_test.cc b/test/color_test.cc
index 30a96a0d..d68f59d4 100644
--- a/test/color_test.cc
+++ b/test/color_test.cc
@@ -21,24 +21,24 @@
#include "util.h"
-/* Check that libdcp::Color works */
+/* Check that dcp::Color works */
BOOST_AUTO_TEST_CASE (color)
{
- libdcp::Color c ("FFFF0000");
+ dcp::Color c ("FFFF0000");
BOOST_CHECK_EQUAL (c.r, 255);
BOOST_CHECK_EQUAL (c.g, 0);
BOOST_CHECK_EQUAL (c.b, 0);
BOOST_CHECK_EQUAL (c.to_argb_string(), "FFFF0000");
- c = libdcp::Color ("FF00FF00");
+ c = dcp::Color ("FF00FF00");
BOOST_CHECK_EQUAL (c.r, 0);
BOOST_CHECK_EQUAL (c.g, 255);
BOOST_CHECK_EQUAL (c.b, 0);
BOOST_CHECK_EQUAL (c.to_argb_string(), "FF00FF00");
- c = libdcp::Color ("FF0000FF");
+ c = dcp::Color ("FF0000FF");
BOOST_CHECK_EQUAL (c.r, 0);
BOOST_CHECK_EQUAL (c.g, 0);
diff --git a/test/cpl_sar.cc b/test/cpl_sar_test.cc
index c91ce287..0c62ea8b 100644
--- a/test/cpl_sar.cc
+++ b/test/cpl_sar_test.cc
@@ -17,10 +17,11 @@
*/
-#include <boost/test/unit_test.hpp>
-#include <libcxml/cxml.h>
#include "cpl.h"
-#include "mono_picture_asset.h"
+#include "reel_mono_picture_asset.h"
+#include "mono_picture_mxf.h"
+#include <libcxml/cxml.h>
+#include <boost/test/unit_test.hpp>
using boost::shared_ptr;
@@ -29,24 +30,23 @@ using boost::shared_ptr;
*/
BOOST_AUTO_TEST_CASE (cpl_sar)
{
- shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset ("build/test/foo", "video.mxf"));
- mp->set_interop (true);
+ shared_ptr<dcp::ReelMonoPictureAsset> pa (new dcp::ReelMonoPictureAsset ());
{
- mp->set_size (libdcp::Size (1998, 1080));
+ pa->set_screen_aspect_ratio (dcp::Fraction (1998, 1080));
xmlpp::Document doc;
xmlpp::Element* el = doc.create_root_node ("Test");
- mp->write_to_cpl (el);
+ pa->write_to_cpl (el, dcp::INTEROP);
cxml::Node node (el);
BOOST_CHECK_EQUAL (node.node_child("MainPicture")->string_child ("ScreenAspectRatio"), "1.85");
}
{
- mp->set_size (libdcp::Size (2048, 858));
+ pa->set_screen_aspect_ratio (dcp::Fraction (2048, 858));
xmlpp::Document doc;
xmlpp::Element* el = doc.create_root_node ("Test");
- mp->write_to_cpl (el);
+ pa->write_to_cpl (el, dcp::INTEROP);
cxml::Node node (el);
BOOST_CHECK_EQUAL (node.node_child("MainPicture")->string_child ("ScreenAspectRatio"), "2.39");
diff --git a/test/dcp_test.cc b/test/dcp_test.cc
index d0c8b973..1736cb60 100644
--- a/test/dcp_test.cc
+++ b/test/dcp_test.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,15 +17,22 @@
*/
-#include <boost/test/unit_test.hpp>
#include "dcp.h"
#include "metadata.h"
#include "cpl.h"
-#include "mono_picture_asset.h"
-#include "sound_asset.h"
+#include "mono_picture_mxf.h"
+#include "picture_mxf_writer.h"
+#include "sound_mxf_writer.h"
+#include "sound_mxf.h"
+#include "subtitle_content.h"
#include "reel.h"
#include "test.h"
+#include "file.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_sound_asset.h"
#include "KM_util.h"
+#include <sndfile.h>
+#include <boost/test/unit_test.hpp>
using boost::shared_ptr;
@@ -35,43 +42,66 @@ BOOST_AUTO_TEST_CASE (dcp_test)
Kumu::libdcp_test = true;
/* Some known metadata */
- libdcp::XMLMetadata xml_meta;
+ dcp::XMLMetadata xml_meta;
xml_meta.issuer = "OpenDCP 0.0.25";
xml_meta.creator = "OpenDCP 0.0.25";
xml_meta.issue_date = "2012-07-17T04:45:18+00:00";
- libdcp::MXFMetadata mxf_meta;
+ dcp::MXFMetadata mxf_meta;
mxf_meta.company_name = "OpenDCP";
mxf_meta.product_name = "OpenDCP";
mxf_meta.product_version = "0.0.25";
- /* We're making build/test/DCP/foo */
+ /* We're making build/test/foo */
boost::filesystem::remove_all ("build/test/DCP/foo");
boost::filesystem::create_directories ("build/test/DCP/foo");
- libdcp::DCP d ("build/test/DCP/foo");
- shared_ptr<libdcp::CPL> cpl (new libdcp::CPL ("build/test/DCP/foo", "A Test DCP", libdcp::FEATURE, 24, 24));
+ dcp::DCP d ("build/test/DCP/foo");
+ shared_ptr<dcp::CPL> cpl (new dcp::CPL ("A Test DCP", dcp::FEATURE));
+ cpl->set_content_version_id ("urn:uri:81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
+ cpl->set_content_version_label_text ("81fb54df-e1bf-4647-8788-ea7ba154375b_2012-07-17T04:45:18+00:00");
- shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset ("build/test/DCP/foo", "video.mxf"));
- mp->set_progress (&d.Progress);
- mp->set_edit_rate (24);
- mp->set_intrinsic_duration (24);
- mp->set_duration (24);
- mp->set_size (libdcp::Size (32, 32));
+ shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
mp->set_metadata (mxf_meta);
- mp->create (j2c);
+ shared_ptr<dcp::PictureMXFWriter> picture_writer = mp->start_write ("build/test/DCP/foo/video.mxf", dcp::SMPTE, false);
+ dcp::File j2c ("test/data/32x32_red_square.j2c");
+ for (int i = 0; i < 24; ++i) {
+ picture_writer->write (j2c.data (), j2c.size ());
+ }
+ picture_writer->finalize ();
- shared_ptr<libdcp::SoundAsset> ms (new libdcp::SoundAsset ("build/test/DCP/foo", "audio.mxf"));
- ms->set_progress (&d.Progress);
- ms->set_edit_rate (24);
- ms->set_intrinsic_duration (24);
- ms->set_duration (24);
- ms->set_channels (2);
+ shared_ptr<dcp::SoundMXF> ms (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 1));
ms->set_metadata (mxf_meta);
- ms->create (wav);
+ shared_ptr<dcp::SoundMXFWriter> sound_writer = ms->start_write ("build/test/DCP/foo/audio.mxf", dcp::SMPTE);
+
+ SF_INFO info;
+ info.format = 0;
+ SNDFILE* sndfile = sf_open ("test/data/1s_24-bit_48k_silence.wav", SFM_READ, &info);
+ BOOST_CHECK (sndfile);
+ float buffer[4096*6];
+ float* channels[1];
+ channels[0] = buffer;
+ while (1) {
+ sf_count_t N = sf_readf_float (sndfile, buffer, 4096);
+ sound_writer->write (channels, N);
+ if (N < 4096) {
+ break;
+ }
+ }
+
+ sound_writer->finalize ();
- cpl->add_reel (shared_ptr<libdcp::Reel> (new libdcp::Reel (mp, ms, shared_ptr<libdcp::SubtitleAsset> ())));
- d.add_cpl (cpl);
+ cpl->add (shared_ptr<dcp::Reel> (
+ new dcp::Reel (
+ shared_ptr<dcp::ReelMonoPictureAsset> (new dcp::ReelMonoPictureAsset (mp, 0)),
+ shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (ms, 0)),
+ shared_ptr<dcp::ReelSubtitleAsset> ()
+ )
+ ));
+
+ d.add (cpl);
+ d.add (mp);
+ d.add (ms);
- d.write_xml (false, xml_meta);
+ d.write_xml (dcp::SMPTE, xml_meta);
/* build/test/DCP/foo is checked against test/ref/DCP/foo by run-tests.sh */
}
diff --git a/test/dcp_time_test.cc b/test/dcp_time_test.cc
index 6892711e..2a5bca1b 100644
--- a/test/dcp_time_test.cc
+++ b/test/dcp_time_test.cc
@@ -20,10 +20,10 @@
#include <boost/test/unit_test.hpp>
#include "dcp_time.h"
-/** Check that libdcp::Time works */
+/** Check that dcp::Time works */
BOOST_AUTO_TEST_CASE (dcp_time)
{
- libdcp::Time t (977143, 24);
+ dcp::Time t (977143, 24);
BOOST_CHECK_EQUAL (t.t, 73);
BOOST_CHECK_EQUAL (t.s, 34);
@@ -32,10 +32,10 @@ BOOST_AUTO_TEST_CASE (dcp_time)
BOOST_CHECK_EQUAL (t.to_string(), "11:18:34:73");
BOOST_CHECK_EQUAL (t.to_ticks(), 10178573);
- libdcp::Time a (3, 2, 3, 4);
- libdcp::Time b (2, 3, 4, 5);
+ dcp::Time a (3, 2, 3, 4);
+ dcp::Time b (2, 3, 4, 5);
- libdcp::Time r = a - b;
+ dcp::Time r = a - b;
BOOST_CHECK_EQUAL (r.h, 0);
BOOST_CHECK_EQUAL (r.m, 58);
BOOST_CHECK_EQUAL (r.s, 58);
@@ -43,8 +43,8 @@ BOOST_AUTO_TEST_CASE (dcp_time)
BOOST_CHECK_EQUAL (r.to_string(), "0:58:58:249");
BOOST_CHECK_EQUAL (r.to_ticks(), 884749);
- a = libdcp::Time (1, 58, 56, 240);
- b = libdcp::Time (1, 7, 12, 120);
+ a = dcp::Time (1, 58, 56, 240);
+ b = dcp::Time (1, 7, 12, 120);
r = a + b;
BOOST_CHECK_EQUAL (r.h, 3);
BOOST_CHECK_EQUAL (r.m, 6);
@@ -53,10 +53,10 @@ BOOST_AUTO_TEST_CASE (dcp_time)
BOOST_CHECK_EQUAL (r.to_string(), "3:6:9:110");
BOOST_CHECK_EQUAL (r.to_ticks(), 2792360);
- a = libdcp::Time (24, 12, 6, 3);
- b = libdcp::Time (16, 8, 4, 2);
+ a = dcp::Time (24, 12, 6, 3);
+ b = dcp::Time (16, 8, 4, 2);
BOOST_CHECK_CLOSE (a / b, 1.5, 1e-5);
- BOOST_CHECK_EQUAL (libdcp::Time (4128391203LL).to_ticks(), 4128391203LL);
- BOOST_CHECK_EQUAL (libdcp::Time (60000).to_ticks(), 60000);
+ BOOST_CHECK_EQUAL (dcp::Time (4128391203LL).to_ticks(), 4128391203LL);
+ BOOST_CHECK_EQUAL (dcp::Time (60000).to_ticks(), 60000);
}
diff --git a/test/decryption_test.cc b/test/decryption_test.cc
index d0e067ee..8dfeffa6 100644
--- a/test/decryption_test.cc
+++ b/test/decryption_test.cc
@@ -23,22 +23,23 @@
#include "mono_picture_frame.h"
#include "cpl.h"
#include "argb_frame.h"
-#include "mono_picture_asset.h"
+#include "mono_picture_mxf.h"
+#include "reel_picture_asset.h"
#include "reel.h"
#include "test.h"
using boost::dynamic_pointer_cast;
using boost::shared_ptr;
-static shared_ptr<const libdcp::ARGBFrame>
-get_frame (libdcp::DCP const & dcp)
+static shared_ptr<const dcp::ARGBFrame>
+get_frame (dcp::DCP const & dcp)
{
- shared_ptr<const libdcp::Reel> reel = dcp.cpls().front()->reels().front ();
- shared_ptr<const libdcp::PictureAsset> picture = reel->main_picture ();
+ shared_ptr<const dcp::Reel> reel = dcp.cpls().front()->reels().front ();
+ shared_ptr<dcp::PictureMXF> picture = reel->main_picture()->mxf ();
BOOST_CHECK (picture);
- shared_ptr<const libdcp::MonoPictureAsset> mono_picture = dynamic_pointer_cast<const libdcp::MonoPictureAsset> (picture);
- shared_ptr<const libdcp::MonoPictureFrame> j2k_frame = mono_picture->get_frame (0);
+ shared_ptr<const dcp::MonoPictureMXF> mono_picture = dynamic_pointer_cast<const dcp::MonoPictureMXF> (picture);
+ shared_ptr<const dcp::MonoPictureFrame> j2k_frame = mono_picture->get_frame (0);
return j2k_frame->argb_frame ();
}
@@ -47,25 +48,25 @@ BOOST_AUTO_TEST_CASE (decryption_test)
{
boost::filesystem::path plaintext_path = private_test;
plaintext_path /= "TONEPLATES-SMPTE-PLAINTEXT_TST_F_XX-XX_ITL-TD_51-XX_2K_WOE_20111001_WOE_OV";
- libdcp::DCP plaintext (plaintext_path.string ());
+ dcp::DCP plaintext (plaintext_path.string ());
plaintext.read ();
BOOST_CHECK_EQUAL (plaintext.encrypted (), false);
boost::filesystem::path encrypted_path = private_test;
encrypted_path /= "TONEPLATES-SMPTE-ENCRYPTED_TST_F_XX-XX_ITL-TD_51-XX_2K_WOE_20111001_WOE_OV";
- libdcp::DCP encrypted (encrypted_path.string ());
+ dcp::DCP encrypted (encrypted_path.string ());
encrypted.read ();
BOOST_CHECK_EQUAL (encrypted.encrypted (), true);
- libdcp::KDM kdm (
+ dcp::KDM kdm (
"test/data/kdm_TONEPLATES-SMPTE-ENC_.smpte-430-2.ROOT.NOT_FOR_PRODUCTION_20130706_20230702_CAR_OV_t1_8971c838.xml",
"test/data/private.key"
);
- encrypted.add_kdm (kdm);
+ encrypted.add (kdm);
- shared_ptr<const libdcp::ARGBFrame> plaintext_frame = get_frame (plaintext);
- shared_ptr<const libdcp::ARGBFrame> encrypted_frame = get_frame (encrypted);
+ shared_ptr<const dcp::ARGBFrame> plaintext_frame = get_frame (plaintext);
+ shared_ptr<const dcp::ARGBFrame> encrypted_frame = get_frame (encrypted);
/* Check that plaintext and encrypted are the same */
BOOST_CHECK_EQUAL (plaintext_frame->stride(), encrypted_frame->stride());
@@ -77,7 +78,7 @@ BOOST_AUTO_TEST_CASE (decryption_test)
/** Load in a KDM that didn't work at first */
BOOST_AUTO_TEST_CASE (failing_kdm_test)
{
- libdcp::KDM kdm (
+ dcp::KDM kdm (
"test/data/target.pem.crt.de5d4eba-e683-41ca-bdda-aa4ad96af3f4.kdm.xml",
"test/data/private.key"
);
diff --git a/test/encryption_test.cc b/test/encryption_test.cc
index f08d4827..d029d4d5 100644
--- a/test/encryption_test.cc
+++ b/test/encryption_test.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,7 +17,6 @@
*/
-#include <boost/test/unit_test.hpp>
#include "kdm.h"
#include "KM_util.h"
#include "metadata.h"
@@ -25,82 +24,83 @@
#include "dcp.h"
#include "signer.h"
#include "cpl.h"
-#include "mono_picture_asset.h"
-#include "sound_asset.h"
+#include "mono_picture_mxf.h"
+#include "picture_mxf_writer.h"
+#include "sound_mxf.h"
#include "reel.h"
#include "test.h"
+#include "file.h"
#include "signer_chain.h"
+#include "subtitle_content.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_sound_asset.h"
+#include <boost/test/unit_test.hpp>
+#include <boost/shared_ptr.hpp>
using boost::shared_ptr;
/* Load a certificate chain from build/test/data/ *.pem and then build
an encrypted DCP and a KDM using it.
*/
-BOOST_AUTO_TEST_CASE (encryption)
+BOOST_AUTO_TEST_CASE (encryption_test)
{
boost::filesystem::remove_all ("build/test/signer");
boost::filesystem::create_directory ("build/test/signer");
- libdcp::make_signer_chain ("build/test/signer", "openssl");
+ dcp::make_signer_chain ("build/test/signer", "openssl");
Kumu::libdcp_test = true;
- libdcp::MXFMetadata mxf_metadata;
+ dcp::MXFMetadata mxf_metadata;
mxf_metadata.company_name = "OpenDCP";
mxf_metadata.product_name = "OpenDCP";
mxf_metadata.product_version = "0.0.25";
- libdcp::XMLMetadata xml_metadata;
+ dcp::XMLMetadata xml_metadata;
xml_metadata.issuer = "OpenDCP 0.0.25";
xml_metadata.creator = "OpenDCP 0.0.25";
xml_metadata.issue_date = "2012-07-17T04:45:18+00:00";
boost::filesystem::remove_all ("build/test/DCP/bar");
boost::filesystem::create_directories ("build/test/DCP/bar");
- libdcp::DCP d ("build/test/DCP/bar");
+ dcp::DCP d ("build/test/DCP/bar");
/* Use test/ref/crypt so this test is repeatable */
- libdcp::CertificateChain chain;
- chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem"))));
- chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem"))));
- chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem"))));
+ dcp::CertificateChain chain;
+ chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem"))));
+ chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem"))));
+ chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem"))));
- shared_ptr<libdcp::Signer> signer (
- new libdcp::Signer (
+ shared_ptr<dcp::Signer> signer (
+ new dcp::Signer (
chain,
"test/ref/crypt/leaf.key"
)
);
- shared_ptr<libdcp::CPL> cpl (new libdcp::CPL ("build/test/DCP/bar", "A Test DCP", libdcp::FEATURE, 24, 24));
+ shared_ptr<dcp::CPL> cpl (new dcp::CPL ("A Test DCP", dcp::FEATURE));
- libdcp::Key key;
+ dcp::Key key;
- shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset ("build/test/DCP/bar", "video.mxf"));
- mp->set_progress (&d.Progress);
- mp->set_edit_rate (24);
- mp->set_intrinsic_duration (24);
- mp->set_duration (24);
- mp->set_size (libdcp::Size (32, 32));
+ shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
mp->set_metadata (mxf_metadata);
mp->set_key (key);
- mp->create (j2c);
-
- shared_ptr<libdcp::SoundAsset> ms (new libdcp::SoundAsset ("build/test/DCP/bar", "audio.mxf"));
- ms->set_progress (&d.Progress);
- ms->set_edit_rate (24);
- ms->set_intrinsic_duration (24);
- mp->set_duration (24);
- ms->set_channels (2);
- ms->set_metadata (mxf_metadata);
- ms->set_key (key);
- ms->create (wav);
-
- cpl->add_reel (shared_ptr<libdcp::Reel> (new libdcp::Reel (mp, ms, shared_ptr<libdcp::SubtitleAsset> ())));
- d.add_cpl (cpl);
-
- d.write_xml (false, xml_metadata, signer);
- libdcp::KDM kdm (
+ shared_ptr<dcp::PictureMXFWriter> writer = mp->start_write ("build/test/DCP/bar/video.mxf", dcp::SMPTE, false);
+ dcp::File j2c ("test/data/32x32_red_square.j2c");
+ for (int i = 0; i < 24; ++i) {
+ writer->write (j2c.data (), j2c.size ());
+ }
+ writer->finalize ();
+
+ cpl->add (shared_ptr<dcp::Reel> (new dcp::Reel (
+ shared_ptr<dcp::ReelMonoPictureAsset> (new dcp::ReelMonoPictureAsset (mp, 0)),
+ shared_ptr<dcp::ReelSoundAsset> (),
+ shared_ptr<dcp::ReelSubtitleAsset> ()
+ )));
+ d.add (cpl);
+ d.write_xml (dcp::SMPTE, xml_metadata, signer);
+
+ dcp::KDM kdm (
cpl,
signer,
signer->certificates().leaf(),
diff --git a/test/error_test.cc b/test/error_test.cc
deleted file mode 100644
index eeff4f41..00000000
--- a/test/error_test.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <boost/test/unit_test.hpp>
-#include "dcp.h"
-#include "mono_picture_asset.h"
-#include "sound_asset.h"
-#include "util.h"
-#include "exceptions.h"
-
-using std::vector;
-using std::string;
-
-/* Check that an exception is thrown when trying to create MXFs from non-existant sources */
-BOOST_AUTO_TEST_CASE (error_test)
-{
- /* Create an empty DCP */
- libdcp::DCP d ("build/test/fred");
-
- /* Random filename that does not exist */
- vector<boost::filesystem::path> p;
- p.push_back ("frobozz");
-
- /* Trying to create video/audio MXFs using a non-existant file should throw an exception */
- libdcp::MonoPictureAsset pa ("build/test/fred", "video.mxf");
- BOOST_CHECK_THROW (pa.create (p), libdcp::FileError);
-
- libdcp::SoundAsset sa ("build/test/fred", "audio.mxf");
- sa.set_channels (1);
- BOOST_CHECK_THROW (sa.create (p), libdcp::FileError);
-}
diff --git a/test/frame_info_test.cc b/test/frame_info_test.cc
index db73d7fb..02ff83aa 100644
--- a/test/frame_info_test.cc
+++ b/test/frame_info_test.cc
@@ -19,14 +19,15 @@
#include <fstream>
#include <boost/test/unit_test.hpp>
-#include "picture_asset_writer.h"
+#include "picture_mxf.h"
+#include "picture_mxf_writer.h"
using namespace std;
/* Test writing and reading of frame_info_test with fstream and stdio */
BOOST_AUTO_TEST_CASE (frame_info_test)
{
- libdcp::FrameInfo a (8589934592LL, 17179869184LL, "thisisahash");
+ dcp::FrameInfo a (8589934592LL, 17179869184LL, "thisisahash");
ofstream o1 ("build/test/frame_info1");
a.write (o1);
@@ -48,11 +49,11 @@ BOOST_AUTO_TEST_CASE (frame_info_test)
BOOST_CHECK_EQUAL (s1, s2);
ifstream l1 ("build/test/frame_info1");
- libdcp::FrameInfo b1 (l1);
+ dcp::FrameInfo b1 (l1);
FILE* l2 = fopen ("build/test/frame_info2", "r");
BOOST_CHECK (l2);
- libdcp::FrameInfo b2 (l2);
+ dcp::FrameInfo b2 (l2);
BOOST_CHECK_EQUAL (b1.offset, b2.offset);
BOOST_CHECK_EQUAL (b1.size, b2.size);
diff --git a/test/kdm_key_test.cc b/test/kdm_key_test.cc
index 05b85312..4a84fe3b 100644
--- a/test/kdm_key_test.cc
+++ b/test/kdm_key_test.cc
@@ -24,7 +24,7 @@ BOOST_AUTO_TEST_CASE (kdm_key_test)
{
uint8_t foo[138];
memset (foo, 0, 138);
- libdcp::KDMKey kkey (foo, 138);
+ dcp::KDMKey kkey (foo, 138);
uint8_t* raw = new uint8_t[16];
uint8_t* p = raw;
diff --git a/test/kdm_test.cc b/test/kdm_test.cc
index 0f0db031..a3928f7a 100644
--- a/test/kdm_test.cc
+++ b/test/kdm_test.cc
@@ -19,19 +19,19 @@
#include <boost/test/unit_test.hpp>
#include "kdm.h"
-#include "xml/kdm_smpte.h"
+#include "kdm_smpte_xml.h"
using std::list;
using boost::shared_ptr;
BOOST_AUTO_TEST_CASE (kdm_test)
{
- libdcp::KDM kdm (
+ dcp::KDM kdm (
"test/data/kdm_TONEPLATES-SMPTE-ENC_.smpte-430-2.ROOT.NOT_FOR_PRODUCTION_20130706_20230702_CAR_OV_t1_8971c838.xml",
"test/data/private.key"
);
- list<libdcp::KDMKey> keys = kdm.keys ();
+ list<dcp::KDMKey> keys = kdm.keys ();
BOOST_CHECK_EQUAL (keys.size(), 2);
@@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE (kdm_test)
/* Check that we can read in a KDM and then write it back out again the same */
BOOST_AUTO_TEST_CASE (kdm_passthrough_test)
{
- libdcp::xml::DCinemaSecurityMessage kdm (
+ dcp::xml::DCinemaSecurityMessage kdm (
"test/data/kdm_TONEPLATES-SMPTE-ENC_.smpte-430-2.ROOT.NOT_FOR_PRODUCTION_20130706_20230702_CAR_OV_t1_8971c838.xml"
);
diff --git a/test/lut_test.cc b/test/lut_test.cc
deleted file mode 100644
index c90dff76..00000000
--- a/test/lut_test.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include <boost/test/unit_test.hpp>
-#include "opendcp_lut.h"
-#include "opendcp_lut.cc"
-#include "srgb_linearised_gamma_lut.h"
-#include "rec709_linearised_gamma_lut.h"
-#include "gamma_lut.h"
-
-/* Check that some of our LUTs match the ones from OpenDCP that
- DVD-o-matic uses / once used.
-*/
-BOOST_AUTO_TEST_CASE (lut_test)
-{
- libdcp::SRGBLinearisedGammaLUT lut_in_srgb (12, 2.4);
- for (int i = 0; i < 4096; ++i) {
- /* Hmm; 1% isn't exactly great... */
- BOOST_CHECK_CLOSE (opendcp::lut_in[0][i], lut_in_srgb.lut()[i], 1);
- }
-
- libdcp::Rec709LinearisedGammaLUT lut_in_rec709 (12, 1 / 0.45);
- for (int i = 0; i < 4096; ++i) {
- /* Hmm; 1% isn't exactly great... */
- BOOST_CHECK_CLOSE (opendcp::lut_in[1][i], lut_in_rec709.lut()[i], 1);
- }
-
- libdcp::GammaLUT lut_out (16, 1 / 2.6);
- for (int i = 0; i < 65536; ++i) {
- BOOST_CHECK_CLOSE (opendcp::lut_out[0][i], lut_out.lut()[i] * 4096, 1);
- }
-}
diff --git a/test/read_dcp_test.cc b/test/read_dcp_test.cc
index 0a9ac119..a17b0a01 100644
--- a/test/read_dcp_test.cc
+++ b/test/read_dcp_test.cc
@@ -27,14 +27,12 @@ using boost::shared_ptr;
/* Read DCP that is in git and make sure that basic stuff is read in correctly */
BOOST_AUTO_TEST_CASE (read_dcp)
{
- libdcp::DCP d ("test/ref/DCP/foo");
+ dcp::DCP d ("test/ref/DCP/foo");
d.read ();
- list<shared_ptr<libdcp::CPL> > cpls = d.cpls ();
+ list<shared_ptr<dcp::CPL> > cpls = d.cpls ();
BOOST_CHECK_EQUAL (cpls.size(), 1);
- BOOST_CHECK_EQUAL (cpls.front()->name(), "A Test DCP");
- BOOST_CHECK_EQUAL (cpls.front()->content_kind(), libdcp::FEATURE);
- BOOST_CHECK_EQUAL (cpls.front()->frames_per_second(), 24);
- BOOST_CHECK_EQUAL (cpls.front()->length(), 24);
+ BOOST_CHECK_EQUAL (cpls.front()->annotation_text(), "A Test DCP");
+ BOOST_CHECK_EQUAL (cpls.front()->content_kind(), dcp::FEATURE);
}
diff --git a/test/recovery_test.cc b/test/recovery_test.cc
index 42697c37..1d51a711 100644
--- a/test/recovery_test.cc
+++ b/test/recovery_test.cc
@@ -19,8 +19,8 @@
#include <boost/test/unit_test.hpp>
#include <boost/filesystem.hpp>
-#include "mono_picture_asset_writer.h"
-#include "mono_picture_asset.h"
+#include "mono_picture_mxf_writer.h"
+#include "mono_picture_mxf.h"
#include "KM_util.h"
using std::string;
@@ -48,14 +48,12 @@ BOOST_AUTO_TEST_CASE (recovery)
boost::filesystem::remove_all ("build/test/baz");
boost::filesystem::create_directories ("build/test/baz");
- shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset ("build/test/baz", "video1.mxf"));
- mp->set_edit_rate (24);
- mp->set_size (libdcp::Size (32, 32));
- shared_ptr<libdcp::PictureAssetWriter> writer = mp->start_write (false);
+ shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+ shared_ptr<dcp::PictureMXFWriter> writer = mp->start_write ("build/test/baz/video1.mxf", dcp::SMPTE, false);
int written_size = 0;
for (int i = 0; i < 24; ++i) {
- libdcp::FrameInfo info = writer->write (data, size);
+ dcp::FrameInfo info = writer->write (data, size);
written_size = info.size;
}
@@ -78,10 +76,8 @@ BOOST_AUTO_TEST_CASE (recovery)
Kumu::ResetTestRNG ();
#endif
- mp.reset (new libdcp::MonoPictureAsset ("build/test/baz", "video2.mxf"));
- mp->set_edit_rate (24);
- mp->set_size (libdcp::Size (32, 32));
- writer = mp->start_write (true);
+ mp.reset (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+ writer = mp->start_write ("build/test/baz/video2.mxf", dcp::SMPTE, true);
writer->write (data, size);
diff --git a/test/rewrite_subs.cc b/test/rewrite_subs.cc
index 3a982d1b..3b177b21 100644
--- a/test/rewrite_subs.cc
+++ b/test/rewrite_subs.cc
@@ -1,15 +1,35 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
#include <iostream>
#include "dcp.h"
#include "cpl.h"
#include "reel.h"
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
+#include "reel_subtitle_asset.h"
#include "exceptions.h"
using std::cout;
using std::cerr;
using std::list;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
int
main (int argc, char* argv[])
@@ -21,7 +41,7 @@ main (int argc, char* argv[])
}
DCP* dcp = new DCP (argv[1]);
- dcp->read (false);
+ dcp->read ();
list<shared_ptr<CPL> > cpls = dcp->cpls ();
for (list<boost::shared_ptr<CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) {
@@ -30,7 +50,7 @@ main (int argc, char* argv[])
for (list<shared_ptr<Reel> >::iterator j = reels.begin(); j != reels.end(); ++j) {
if ((*j)->main_subtitle()) {
- (*j)->main_subtitle()->write_xml ();
+ (*j)->main_subtitle()->subtitle_content()->write_xml ();
}
}
}
diff --git a/test/round_trip_test.cc b/test/round_trip_test.cc
index a6ee2097..e94d8c72 100644
--- a/test/round_trip_test.cc
+++ b/test/round_trip_test.cc
@@ -17,19 +17,23 @@
*/
-#include <iostream>
-#include <boost/test/unit_test.hpp>
#include "certificates.h"
#include "kdm.h"
#include "signer.h"
-#include "mono_picture_asset.h"
-#include "sound_asset.h"
+#include "mono_picture_mxf.h"
+#include "sound_mxf.h"
#include "reel.h"
#include "test.h"
#include "cpl.h"
#include "mono_picture_frame.h"
#include "argb_frame.h"
#include "signer_chain.h"
+#include "mono_picture_mxf_writer.h"
+#include "reel_picture_asset.h"
+#include "reel_mono_picture_asset.h"
+#include "file.h"
+#include <boost/test/unit_test.hpp>
+#include <iostream>
using std::list;
using boost::shared_ptr;
@@ -39,15 +43,15 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
{
boost::filesystem::remove_all ("build/test/signer");
boost::filesystem::create_directory ("build/test/signer");
- libdcp::make_signer_chain ("build/test/signer", "openssl");
+ dcp::make_signer_chain ("build/test/signer", "openssl");
- libdcp::CertificateChain chain;
- chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("build/test/signer/ca.self-signed.pem"))));
- chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("build/test/signer/intermediate.signed.pem"))));
- chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("build/test/signer/leaf.signed.pem"))));
+ dcp::CertificateChain chain;
+ chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("build/test/signer/ca.self-signed.pem"))));
+ chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("build/test/signer/intermediate.signed.pem"))));
+ chain.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("build/test/signer/leaf.signed.pem"))));
- shared_ptr<libdcp::Signer> signer (
- new libdcp::Signer (
+ shared_ptr<dcp::Signer> signer (
+ new dcp::Signer (
chain,
"test/data/signer.key"
)
@@ -56,21 +60,25 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
boost::filesystem::path work_dir = "build/test/round_trip_test";
boost::filesystem::create_directory (work_dir);
- shared_ptr<libdcp::MonoPictureAsset> asset_A (new libdcp::MonoPictureAsset (work_dir, "video.mxf"));
- asset_A->set_edit_rate (24);
- asset_A->set_intrinsic_duration (24);
- asset_A->set_size (libdcp::Size (32, 32));
- asset_A->create (j2c);
+ shared_ptr<dcp::MonoPictureMXF> mxf_A (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+ shared_ptr<dcp::PictureMXFWriter> writer = mxf_A->start_write (work_dir / "video.mxf", dcp::SMPTE, false);
+ dcp::File j2c ("test/data/32x32_red_square.j2c");
+ for (int i = 0; i < 24; ++i) {
+ writer->write (j2c.data (), j2c.size ());
+ }
+ writer->finalize ();
- libdcp::Key key;
+ dcp::Key key;
- asset_A->set_key (key);
+ mxf_A->set_key (key);
- shared_ptr<libdcp::CPL> cpl (new libdcp::CPL (work_dir, "A Test DCP", libdcp::FEATURE, 24, 24));
- cpl->add_reel (shared_ptr<libdcp::Reel> (new libdcp::Reel (asset_A, shared_ptr<libdcp::SoundAsset> (), shared_ptr<libdcp::SubtitleAsset> ())));
+ shared_ptr<dcp::CPL> cpl (new dcp::CPL ("A Test DCP", dcp::FEATURE));
+ shared_ptr<dcp::Reel> reel (new dcp::Reel ());
+ reel->add (shared_ptr<dcp::ReelMonoPictureAsset> (new dcp::ReelMonoPictureAsset (mxf_A, 0)));
+ cpl->add (reel);
/* A KDM using our certificate chain's leaf key pair */
- libdcp::KDM kdm_A (
+ dcp::KDM kdm_A (
cpl,
signer,
signer->certificates().leaf(),
@@ -85,14 +93,14 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
kdm_A.as_xml (kdm_file);
/* Reload the KDM, using our private key to decrypt it */
- libdcp::KDM kdm_B (kdm_file, "build/test/signer/leaf.key");
+ dcp::KDM kdm_B (kdm_file, "build/test/signer/leaf.key");
/* Check that the decrypted KDMKeys are the same as the ones we started with */
BOOST_CHECK_EQUAL (kdm_A.keys().size(), kdm_B.keys().size());
- list<libdcp::KDMKey> keys_A = kdm_A.keys ();
- list<libdcp::KDMKey> keys_B = kdm_B.keys ();
- list<libdcp::KDMKey>::const_iterator i = keys_A.begin();
- list<libdcp::KDMKey>::const_iterator j = keys_B.begin();
+ list<dcp::KDMKey> keys_A = kdm_A.keys ();
+ list<dcp::KDMKey> keys_B = kdm_B.keys ();
+ list<dcp::KDMKey>::const_iterator i = keys_A.begin();
+ list<dcp::KDMKey>::const_iterator j = keys_B.begin();
while (i != keys_A.end ()) {
BOOST_CHECK (*i == *j);
++i;
@@ -100,14 +108,15 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
}
/* Reload the picture MXF */
- shared_ptr<libdcp::MonoPictureAsset> asset_B (
- new libdcp::MonoPictureAsset (work_dir, "video.mxf")
+ shared_ptr<dcp::MonoPictureMXF> mxf_B (
+ new dcp::MonoPictureMXF (work_dir / "video.mxf")
);
- asset_B->set_key (kdm_B.keys().front().key());
+ BOOST_CHECK (!kdm_B.keys().empty ());
+ mxf_B->set_key (kdm_B.keys().front().key());
- shared_ptr<libdcp::ARGBFrame> frame_A = asset_A->get_frame(0)->argb_frame ();
- shared_ptr<libdcp::ARGBFrame> frame_B = asset_B->get_frame(0)->argb_frame ();
+ shared_ptr<dcp::ARGBFrame> frame_A = mxf_A->get_frame(0)->argb_frame ();
+ shared_ptr<dcp::ARGBFrame> frame_B = mxf_B->get_frame(0)->argb_frame ();
BOOST_CHECK_EQUAL (frame_A->size().width, frame_B->size().width);
BOOST_CHECK_EQUAL (frame_A->size().height, frame_B->size().height);
BOOST_CHECK_EQUAL (memcmp (frame_A->data(), frame_B->data(), frame_A->size().width * frame_A->size().height), 0);
diff --git a/test/subs_in_out.cc b/test/subs_in_out.cc
index f0a7e96f..9b2c2e9b 100644
--- a/test/subs_in_out.cc
+++ b/test/subs_in_out.cc
@@ -1,5 +1,5 @@
#include <iostream>
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
using namespace std;
@@ -10,8 +10,7 @@ int main (int argc, char* argv[])
exit (EXIT_FAILURE);
}
- libdcp::SubtitleAsset s ("foo", "bar", "baz");
- s.read_xml (argv[1]);
+ dcp::SubtitleContent s (argv[1]);
cout << s.xml_as_string ();
return 0;
}
diff --git a/test/subtitle_tests.cc b/test/subtitle_tests.cc
index a8fa78b7..77dd29d7 100644
--- a/test/subtitle_tests.cc
+++ b/test/subtitle_tests.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
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
@@ -17,407 +17,408 @@
*/
+#include "subtitle_content.h"
+#include "subtitle_string.h"
#include <boost/test/unit_test.hpp>
-#include "subtitle_asset.h"
using std::list;
using boost::shared_ptr;
-/* Load a subtitle asset from XML and check that it is read correctly */
+/* Load some subtitle content from XML and check that it is read correctly */
BOOST_AUTO_TEST_CASE (subtitles1)
{
- libdcp::SubtitleAsset subs ("test/data", "subs1.xml");
+ dcp::SubtitleContent subs ("test/data/subs1.xml");
BOOST_CHECK_EQUAL (subs.language(), "French");
- list<shared_ptr<libdcp::Subtitle> > s = subs.subtitles_at (libdcp::Time (0, 0, 6, 1));
+ list<shared_ptr<dcp::SubtitleString> > s = subs.subtitles_at (dcp::Time (0, 0, 6, 1));
BOOST_CHECK_EQUAL (s.size(), 1);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
39,
- libdcp::Time (0, 0, 5, 198),
- libdcp::Time (0, 0, 7, 115),
+ dcp::Time (0, 0, 5, 198),
+ dcp::Time (0, 0, 7, 115),
15,
- libdcp::BOTTOM,
+ dcp::BOTTOM,
"My jacket was Idi Amin's",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 1),
- libdcp::Time (0, 0, 0, 1)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 1),
+ dcp::Time (0, 0, 0, 1)
));
- s = subs.subtitles_at (libdcp::Time (0, 0, 7, 190));
+ s = subs.subtitles_at (dcp::Time (0, 0, 7, 190));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
39,
- libdcp::Time (0, 0, 7, 177),
- libdcp::Time (0, 0, 11, 31),
+ dcp::Time (0, 0, 7, 177),
+ dcp::Time (0, 0, 11, 31),
21,
- libdcp::BOTTOM,
+ dcp::BOTTOM,
"My corset was H.M. The Queen's",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 1),
- libdcp::Time (0, 0, 0, 1)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 1),
+ dcp::Time (0, 0, 0, 1)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
39,
- libdcp::Time (0, 0, 7, 177),
- libdcp::Time (0, 0, 11, 31),
+ dcp::Time (0, 0, 7, 177),
+ dcp::Time (0, 0, 11, 31),
15,
- libdcp::BOTTOM,
+ dcp::BOTTOM,
"My large wonderbra",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 1),
- libdcp::Time (0, 0, 0, 1)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 1),
+ dcp::Time (0, 0, 0, 1)
));
- s = subs.subtitles_at (libdcp::Time (0, 0, 11, 95));
+ s = subs.subtitles_at (dcp::Time (0, 0, 11, 95));
BOOST_CHECK_EQUAL (s.size(), 1);
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
39,
- libdcp::Time (0, 0, 11, 94),
- libdcp::Time (0, 0, 13, 63),
+ dcp::Time (0, 0, 11, 94),
+ dcp::Time (0, 0, 13, 63),
15,
- libdcp::BOTTOM,
+ dcp::BOTTOM,
"Once belonged to the Shah",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 1),
- libdcp::Time (0, 0, 0, 1)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 1),
+ dcp::Time (0, 0, 0, 1)
));
- s = subs.subtitles_at (libdcp::Time (0, 0, 14, 42));
+ s = subs.subtitles_at (dcp::Time (0, 0, 14, 42));
BOOST_CHECK_EQUAL (s.size(), 1);
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
39,
- libdcp::Time (0, 0, 13, 104),
- libdcp::Time (0, 0, 15, 177),
+ dcp::Time (0, 0, 13, 104),
+ dcp::Time (0, 0, 15, 177),
15,
- libdcp::BOTTOM,
+ dcp::BOTTOM,
"And these are Roy Hattersley's jeans",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 1),
- libdcp::Time (0, 0, 0, 1)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 1),
+ dcp::Time (0, 0, 0, 1)
));
}
/** And similarly for another one */
BOOST_AUTO_TEST_CASE (subtitles2)
{
- libdcp::SubtitleAsset subs ("test/data", "subs2.xml");
+ dcp::SubtitleContent subs ("test/data/subs2.xml");
- list<shared_ptr<libdcp::Subtitle> > s = subs.subtitles_at (libdcp::Time (0, 0, 42, 100));
+ list<shared_ptr<dcp::SubtitleString> > s = subs.subtitles_at (dcp::Time (0, 0, 42, 100));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 0, 41, 62),
- libdcp::Time (0, 0, 43, 52),
+ dcp::Time (0, 0, 41, 62),
+ dcp::Time (0, 0, 43, 52),
89,
- libdcp::TOP,
+ dcp::TOP,
"At afternoon tea with John Peel",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 0, 41, 62),
- libdcp::Time (0, 0, 43, 52),
+ dcp::Time (0, 0, 41, 62),
+ dcp::Time (0, 0, 43, 52),
95,
- libdcp::TOP,
+ dcp::TOP,
"I enquired if his accent was real",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 0, 50, 50));
+ s = subs.subtitles_at (dcp::Time (0, 0, 50, 50));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 0, 50, 42),
- libdcp::Time (0, 0, 52, 21),
+ dcp::Time (0, 0, 50, 42),
+ dcp::Time (0, 0, 52, 21),
89,
- libdcp::TOP,
+ dcp::TOP,
"He said \"out of the house",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 0, 50, 42),
- libdcp::Time (0, 0, 52, 21),
+ dcp::Time (0, 0, 50, 42),
+ dcp::Time (0, 0, 52, 21),
95,
- libdcp::TOP,
+ dcp::TOP,
"I'm incredibly scouse",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 1, 2, 300));
+ s = subs.subtitles_at (dcp::Time (0, 1, 2, 300));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 2, 208),
- libdcp::Time (0, 1, 4, 10),
+ dcp::Time (0, 1, 2, 208),
+ dcp::Time (0, 1, 4, 10),
89,
- libdcp::TOP,
+ dcp::TOP,
"At home it depends how I feel.\"",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 2, 208),
- libdcp::Time (0, 1, 4, 10),
+ dcp::Time (0, 1, 2, 208),
+ dcp::Time (0, 1, 4, 10),
95,
- libdcp::TOP,
+ dcp::TOP,
"I spent a long weekend in Brighton",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 1, 15, 50));
+ s = subs.subtitles_at (dcp::Time (0, 1, 15, 50));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 15, 42),
- libdcp::Time (0, 1, 16, 42),
+ dcp::Time (0, 1, 15, 42),
+ dcp::Time (0, 1, 16, 42),
89,
- libdcp::TOP,
+ dcp::TOP,
"With the legendary Miss Enid Blyton",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 15, 42),
- libdcp::Time (0, 1, 16, 42),
+ dcp::Time (0, 1, 15, 42),
+ dcp::Time (0, 1, 16, 42),
95,
- libdcp::TOP,
+ dcp::TOP,
"She said \"you be Noddy",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 1, 27, 200));
+ s = subs.subtitles_at (dcp::Time (0, 1, 27, 200));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 27, 115),
- libdcp::Time (0, 1, 28, 208),
+ dcp::Time (0, 1, 27, 115),
+ dcp::Time (0, 1, 28, 208),
89,
- libdcp::TOP,
+ dcp::TOP,
"That curious creature the Sphinx",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 27, 115),
- libdcp::Time (0, 1, 28, 208),
+ dcp::Time (0, 1, 27, 115),
+ dcp::Time (0, 1, 28, 208),
95,
- libdcp::TOP,
+ dcp::TOP,
"Is smarter than anyone thinks",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 1, 42, 300));
+ s = subs.subtitles_at (dcp::Time (0, 1, 42, 300));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 42, 229),
- libdcp::Time (0, 1, 45, 62),
+ dcp::Time (0, 1, 42, 229),
+ dcp::Time (0, 1, 45, 62),
89,
- libdcp::TOP,
+ dcp::TOP,
"It sits there and smirks",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 42, 229),
- libdcp::Time (0, 1, 45, 62),
+ dcp::Time (0, 1, 42, 229),
+ dcp::Time (0, 1, 45, 62),
95,
- libdcp::TOP,
+ dcp::TOP,
"And you don't think it works",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 1, 45, 200));
+ s = subs.subtitles_at (dcp::Time (0, 1, 45, 200));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 45, 146),
- libdcp::Time (0, 1, 47, 94),
+ dcp::Time (0, 1, 45, 146),
+ dcp::Time (0, 1, 47, 94),
89,
- libdcp::TOP,
+ dcp::TOP,
"Then when you're not looking, it winks.",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 45, 146),
- libdcp::Time (0, 1, 47, 94),
+ dcp::Time (0, 1, 45, 146),
+ dcp::Time (0, 1, 47, 94),
95,
- libdcp::TOP,
+ dcp::TOP,
"When it snows you will find Sister Sledge",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 1, 47, 249));
+ s = subs.subtitles_at (dcp::Time (0, 1, 47, 249));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 47, 146),
- libdcp::Time (0, 1, 48, 167),
+ dcp::Time (0, 1, 47, 146),
+ dcp::Time (0, 1, 48, 167),
89,
- libdcp::TOP,
+ dcp::TOP,
"Out mooning, at night, on the ledge",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
false,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 1, 47, 146),
- libdcp::Time (0, 1, 48, 167),
+ dcp::Time (0, 1, 47, 146),
+ dcp::Time (0, 1, 48, 167),
95,
- libdcp::TOP,
+ dcp::TOP,
"One storey down",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- s = subs.subtitles_at (libdcp::Time (0, 2, 6, 210));
+ s = subs.subtitles_at (dcp::Time (0, 2, 6, 210));
BOOST_CHECK_EQUAL (s.size(), 2);
- BOOST_CHECK_EQUAL (*(s.front().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 2, 5, 208),
- libdcp::Time (0, 2, 7, 31),
+ dcp::Time (0, 2, 5, 208),
+ dcp::Time (0, 2, 7, 31),
89,
- libdcp::TOP,
+ dcp::TOP,
"HELLO",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
- BOOST_CHECK_EQUAL (*(s.back().get()), libdcp::Subtitle (
+ BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
"Arial",
true,
- libdcp::Color (255, 255, 255),
+ dcp::Color (255, 255, 255),
42,
- libdcp::Time (0, 2, 5, 208),
- libdcp::Time (0, 2, 7, 31),
+ dcp::Time (0, 2, 5, 208),
+ dcp::Time (0, 2, 7, 31),
95,
- libdcp::TOP,
+ dcp::TOP,
"WORLD",
- libdcp::BORDER,
- libdcp::Color (0, 0, 0),
- libdcp::Time (0, 0, 0, 0),
- libdcp::Time (0, 0, 0, 0)
+ dcp::BORDER,
+ dcp::Color (0, 0, 0),
+ dcp::Time (0, 0, 0, 0),
+ dcp::Time (0, 0, 0, 0)
));
diff --git a/test/test.cc b/test/test.cc
index c58966f4..0b56b903 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -21,6 +21,7 @@
#define BOOST_TEST_MODULE libdcp_test
#include <boost/test/unit_test.hpp>
#include "util.h"
+#include "test.h"
using std::string;
@@ -28,7 +29,7 @@ struct TestConfig
{
TestConfig()
{
- libdcp::init ();
+ dcp::init ();
}
};
@@ -41,7 +42,7 @@ j2c (int)
}
boost::filesystem::path
-wav (libdcp::Channel)
+wav (dcp::Channel)
{
return "test/data/1s_24-bit_48k_silence.wav";
}
diff --git a/test/test.h b/test/test.h
index 47a615d8..f139fa28 100644
--- a/test/test.h
+++ b/test/test.h
@@ -17,6 +17,4 @@
*/
-extern boost::filesystem::path j2c (int);
-extern boost::filesystem::path wav (libdcp::Channel);
extern std::string private_test;
diff --git a/test/utc_offset_to_string_test.cc b/test/utc_offset_to_string_test.cc
index af9c6533..3b4e0b46 100644
--- a/test/utc_offset_to_string_test.cc
+++ b/test/utc_offset_to_string_test.cc
@@ -21,12 +21,12 @@
#include "metadata.h"
#include "util.h"
-/** Test libdcp::utc_offset_to_string */
+/** Test dcp::utc_offset_to_string */
BOOST_AUTO_TEST_CASE (utc_offset_to_string_test)
{
- BOOST_CHECK_EQUAL (libdcp::utc_offset_to_string (30), "+00:30");
- BOOST_CHECK_EQUAL (libdcp::utc_offset_to_string (60), "+01:00");
- BOOST_CHECK_EQUAL (libdcp::utc_offset_to_string (61), "+01:01");
- BOOST_CHECK_EQUAL (libdcp::utc_offset_to_string (7 * 60), "+07:00");
- BOOST_CHECK_EQUAL (libdcp::utc_offset_to_string (-11 * 60), "-11:00");
+ BOOST_CHECK_EQUAL (dcp::utc_offset_to_string (30), "+00:30");
+ BOOST_CHECK_EQUAL (dcp::utc_offset_to_string (60), "+01:00");
+ BOOST_CHECK_EQUAL (dcp::utc_offset_to_string (61), "+01:01");
+ BOOST_CHECK_EQUAL (dcp::utc_offset_to_string (7 * 60), "+07:00");
+ BOOST_CHECK_EQUAL (dcp::utc_offset_to_string (-11 * 60), "-11:00");
}
diff --git a/test/util_test.cc b/test/util_test.cc
index f7114e90..15f22f57 100644
--- a/test/util_test.cc
+++ b/test/util_test.cc
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE (base64_decode_test)
}
unsigned char decoded[N];
- int const r = libdcp::base64_decode (s, decoded, N);
+ int const r = dcp::base64_decode (s, decoded, N);
BOOST_CHECK_EQUAL (r, N);
for (int i = 0; i < N; ++i) {
@@ -57,16 +57,59 @@ BOOST_AUTO_TEST_CASE (base64_decode_test)
BOOST_AUTO_TEST_CASE (content_kind_test)
{
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("feature"), libdcp::FEATURE);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("Feature"), libdcp::FEATURE);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("FeaturE"), libdcp::FEATURE);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("Short"), libdcp::SHORT);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("trailer"), libdcp::TRAILER);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("test"), libdcp::TEST);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("transitional"), libdcp::TRANSITIONAL);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("rating"), libdcp::RATING);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("teaser"), libdcp::TEASER);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("policy"), libdcp::POLICY);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("psa"), libdcp::PUBLIC_SERVICE_ANNOUNCEMENT);
- BOOST_CHECK_EQUAL (libdcp::content_kind_from_string ("advertisement"), libdcp::ADVERTISEMENT);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("feature"), dcp::FEATURE);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("Feature"), dcp::FEATURE);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("FeaturE"), dcp::FEATURE);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("Short"), dcp::SHORT);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("trailer"), dcp::TRAILER);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("test"), dcp::TEST);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("transitional"), dcp::TRANSITIONAL);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("rating"), dcp::RATING);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("teaser"), dcp::TEASER);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("policy"), dcp::POLICY);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("psa"), dcp::PUBLIC_SERVICE_ANNOUNCEMENT);
+ BOOST_CHECK_EQUAL (dcp::content_kind_from_string ("advertisement"), dcp::ADVERTISEMENT);
+}
+
+BOOST_AUTO_TEST_CASE (relative_to_root_test)
+{
+ {
+ boost::filesystem::path root = "a";
+ root /= "b";
+
+ boost::filesystem::path file = "a";
+ file /= "b";
+ file /= "c";
+
+ boost::optional<boost::filesystem::path> rel = dcp::relative_to_root (root, file);
+ BOOST_CHECK (rel);
+ BOOST_CHECK_EQUAL (rel.get(), boost::filesystem::path ("c"));
+ }
+
+ {
+ boost::filesystem::path root = "a";
+ root /= "b";
+ root /= "c";
+
+ boost::filesystem::path file = "a";
+ file /= "b";
+
+ boost::optional<boost::filesystem::path> rel = dcp::relative_to_root (root, file);
+ BOOST_CHECK (!rel);
+ }
+
+ {
+ boost::filesystem::path root = "a";
+
+ boost::filesystem::path file = "a";
+ file /= "b";
+ file /= "c";
+
+ boost::optional<boost::filesystem::path> rel = dcp::relative_to_root (root, file);
+ BOOST_CHECK (rel);
+
+ boost::filesystem::path check = "b";
+ check /= "c";
+ BOOST_CHECK_EQUAL (rel.get(), check);
+ }
}
diff --git a/test/wscript b/test/wscript
index 7bb68252..407765af 100644
--- a/test/wscript
+++ b/test/wscript
@@ -4,35 +4,33 @@ def configure(conf):
else:
boost_lib_suffix = ''
- conf.check_cxx(fragment = """
- #define BOOST_TEST_MODULE Config test\n
- #include <boost/test/unit_test.hpp>\n
- int main() {}
- """,
- msg = 'Checking for boost unit testing library',
- lib = 'boost_unit_test_framework%s' % boost_lib_suffix,
- uselib_store = 'BOOST_TEST')
+ conf.check_cxx(fragment="""
+ #define BOOST_TEST_MODULE Config test\n
+ #include <boost/test/unit_test.hpp>\n
+ int main() {}
+ """,
+ msg='Checking for boost unit testing library',
+ lib='boost_unit_test_framework%s' % boost_lib_suffix,
+ uselib_store='BOOST_TEST')
conf.env.prepend_value('LINKFLAGS', '-Lsrc')
def build(bld):
- obj = bld(features = 'cxx cxxprogram')
+ obj = bld(features='cxx cxxprogram')
obj.name = 'tests'
- obj.uselib = 'BOOST_TEST OPENJPEG CXML XMLSEC1'
- obj.use = 'libdcp'
+ obj.uselib = 'BOOST_TEST OPENJPEG CXML XMLSEC1 SNDFILE'
+ obj.use = 'libdcp%s' % bld.env.API_VERSION
obj.source = """
certificates_test.cc
color_test.cc
- cpl_sar.cc
+ cpl_sar_test.cc
dcp_test.cc
dcp_time_test.cc
decryption_test.cc
encryption_test.cc
- error_test.cc
frame_info_test.cc
kdm_key_test.cc
kdm_test.cc
- lut_test.cc
read_dcp_test.cc
recovery_test.cc
round_trip_test.cc
@@ -44,18 +42,18 @@ def build(bld):
obj.target = 'tests'
obj.install_path = ''
- obj = bld(features = 'cxx cxxprogram')
+ obj = bld(features='cxx cxxprogram')
obj.name = 'subs_in_out'
obj.uselib = 'BOOST_TEST OPENJPEG CXML'
- obj.use = 'libdcp'
+ obj.use = 'libdcp%s' % bld.env.API_VERSION
obj.source = 'subs_in_out.cc'
obj.target = 'subs_in_out'
obj.install_path = ''
- obj = bld(features = 'cxx cxxprogram')
+ obj = bld(features='cxx cxxprogram')
obj.name = 'rewrite_subs'
obj.uselib = 'BOOST_TEST OPENJPEG CXML'
- obj.use = 'libdcp'
+ obj.use = 'libdcp%s' % bld.env.API_VERSION
obj.source = 'rewrite_subs.cc'
obj.target = 'rewrite_subs'
obj.install_path = ''
diff --git a/tools/dcpdiff.cc b/tools/dcpdiff.cc
index b361b93a..dda7c3c3 100644
--- a/tools/dcpdiff.cc
+++ b/tools/dcpdiff.cc
@@ -6,7 +6,7 @@
using namespace std;
using namespace boost;
-using namespace libdcp;
+using namespace dcp;
static bool verbose = false;
diff --git a/tools/dcpinfo.cc b/tools/dcpinfo.cc
index 56d71f99..b76993bf 100644
--- a/tools/dcpinfo.cc
+++ b/tools/dcpinfo.cc
@@ -1,3 +1,22 @@
+/*
+ Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
#include <iostream>
#include <cstdlib>
#include <boost/filesystem.hpp>
@@ -5,9 +24,13 @@
#include "dcp.h"
#include "exceptions.h"
#include "reel.h"
-#include "sound_asset.h"
-#include "picture_asset.h"
-#include "subtitle_asset.h"
+#include "sound_mxf.h"
+#include "picture_mxf.h"
+#include "subtitle_content.h"
+#include "reel_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
+#include "subtitle_string.h"
#include "cpl.h"
using std::string;
@@ -15,7 +38,7 @@ using std::cerr;
using std::cout;
using std::list;
using boost::shared_ptr;
-using namespace libdcp;
+using namespace dcp;
static void
help (string n)
@@ -70,7 +93,7 @@ main (int argc, char* argv[])
DCP* dcp = 0;
try {
dcp = new DCP (argv[optind]);
- dcp->read (false);
+ dcp->read ();
} catch (FileError& e) {
cerr << "Could not read DCP " << argv[optind] << "; " << e.what() << " " << e.filename() << "\n";
exit (EXIT_FAILURE);
@@ -81,9 +104,7 @@ main (int argc, char* argv[])
list<shared_ptr<CPL> > cpls = dcp->cpls ();
for (list<shared_ptr<CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) {
- cout << " CPL: " << (*i)->name() << "\n"
- << " Length: " << (*i)->length() << "\n"
- << " Frames per second: " << (*i)->frames_per_second() << "\n";
+ cout << " CPL: " << (*i)->annotation_text() << "\n";
list<shared_ptr<Reel> > reels = (*i)->reels ();
@@ -92,16 +113,22 @@ main (int argc, char* argv[])
cout << " Reel " << R << "\n";
if ((*j)->main_picture()) {
- cout << " Picture: " << (*j)->main_picture()->size().width << "x" << (*j)->main_picture()->size().height << "\n";
+ cout << " Picture: "
+ << (*j)->main_picture()->mxf()->size().width
+ << "x"
+ << (*j)->main_picture()->mxf()->size().height << "\n";
}
if ((*j)->main_sound()) {
- cout << " Sound: " << (*j)->main_sound()->channels() << " channels at " << (*j)->main_sound()->sampling_rate() << "Hz\n";
+ cout << " Sound: "
+ << (*j)->main_sound()->mxf()->channels()
+ << " channels at "
+ << (*j)->main_sound()->mxf()->sampling_rate() << "Hz\n";
}
if ((*j)->main_subtitle()) {
- list<shared_ptr<Subtitle> > subs = (*j)->main_subtitle()->subtitles ();
- cout << " Subtitle: " << subs.size() << " subtitles in " << (*j)->main_subtitle()->language() << "\n";
+ list<shared_ptr<SubtitleString> > subs = (*j)->main_subtitle()->subtitle_content()->subtitles ();
+ cout << " Subtitle: " << subs.size() << " subtitles in " << (*j)->main_subtitle()->subtitle_content()->language() << "\n";
if (subtitles) {
- for (list<shared_ptr<Subtitle> >::const_iterator k = subs.begin(); k != subs.end(); ++k) {
+ for (list<shared_ptr<SubtitleString> >::const_iterator k = subs.begin(); k != subs.end(); ++k) {
cout << " " << (*k)->text() << "\n";
cout << " "
<< "font:" << (*k)->font() << "; "
diff --git a/tools/wscript b/tools/wscript
index e4a32534..518f0026 100644
--- a/tools/wscript
+++ b/tools/wscript
@@ -1,12 +1,12 @@
def build(bld):
obj = bld(features = 'cxx cxxprogram')
- obj.use = ['libdcp']
+ obj.use = ['libdcp%s' % bld.env.API_VERSION]
obj.uselib = 'OPENJPEG CXML'
obj.source = 'dcpdiff.cc'
obj.target = 'dcpdiff'
obj = bld(features = 'cxx cxxprogram')
- obj.use = ['libdcp']
+ obj.use = ['libdcp%s' % bld.env.API_VERSION]
obj.uselib = 'OPENJPEG CXML'
obj.source = 'dcpinfo.cc'
obj.target = 'dcpinfo'
diff --git a/wscript b/wscript
index 3f7da877..a647c62c 100644
--- a/wscript
+++ b/wscript
@@ -2,14 +2,15 @@ import subprocess
import os
APPNAME = 'libdcp'
-VERSION = '0.93pre'
+VERSION = '1.00.0devel'
+API_VERSION = '-1.0'
def options(opt):
opt.load('compiler_cxx')
- opt.add_option('--target-windows', action='store_true', default = False, help = 'set up to do a cross-compile to Windows')
- opt.add_option('--osx', action='store_true', default = False, help = 'set up to build on OS X')
- opt.add_option('--enable-debug', action='store_true', default = False, help = 'build with debugging information and without optimisation')
- opt.add_option('--static', action='store_true', default = False, help = 'build libdcp and in-tree dependencies statically, and link statically to openjpeg and cxml')
+ opt.add_option('--target-windows', action='store_true', default=False, help='set up to do a cross-compile to Windows')
+ opt.add_option('--target-osx', action='store_true', default=False, help='set up to build on OS X')
+ opt.add_option('--enable-debug', action='store_true', default=False, help='build with debugging information and without optimisation')
+ opt.add_option('--static', action='store_true', default=False, help='build libdcp and in-tree dependencies statically, and link statically to openjpeg and cxml')
def configure(conf):
conf.load('compiler_cxx')
@@ -17,34 +18,37 @@ def configure(conf):
conf.env.append_value('CXXFLAGS', ['-DLIBDCP_VERSION="%s"' % VERSION])
conf.env.TARGET_WINDOWS = conf.options.target_windows
- conf.env.STATIC = conf.options.static
- conf.env.OSX = conf.options.osx
+ conf.env.TARGET_OSX = conf.options.target_osx
conf.env.ENABLE_DEBUG = conf.options.enable_debug
+ conf.env.STATIC = conf.options.static
+ conf.env.API_VERSION = API_VERSION
if conf.options.target_windows:
conf.env.append_value('CXXFLAGS', '-DLIBDCP_WINDOWS')
else:
conf.env.append_value('CXXFLAGS', '-DLIBDCP_POSIX')
- if not conf.options.osx:
+ if not conf.options.target_osx:
conf.env.append_value('CXXFLAGS', ['-Wno-unused-result', '-Wno-unused-parameter'])
- conf.check_cfg(package = 'openssl', args = '--cflags --libs', uselib_store = 'OPENSSL', mandatory = True)
- conf.check_cfg(package = 'libxml++-2.6', args = '--cflags --libs', uselib_store = 'LIBXML++', mandatory = True)
- conf.check_cfg(package = 'xmlsec1', args = '--cflags --libs', uselib_store = 'XMLSEC1', mandatory = True)
+ conf.check_cfg(package='openssl', args='--cflags --libs', uselib_store='OPENSSL', mandatory=True)
+ conf.check_cfg(package='libxml++-2.6', args='--cflags --libs', uselib_store='LIBXML++', mandatory=True)
+ conf.check_cfg(package='xmlsec1', args='--cflags --libs', uselib_store='XMLSEC1', mandatory=True)
# Remove erroneous escaping of quotes from xmlsec1 defines
conf.env.DEFINES_XMLSEC1 = [f.replace('\\', '') for f in conf.env.DEFINES_XMLSEC1]
+ conf.check_cfg(package='', path='Magick++-config', args='--cppflags --cxxflags --libs', uselib_store='MAGICK', mandatory=False)
+ conf.check_cfg(package='sndfile', args='--cflags --libs', uselib_store='SNDFILE', mandatory=False)
if conf.options.static:
- conf.check_cc(fragment = """
- #include <stdio.h>\n
- #include <openjpeg.h>\n
- int main () {\n
- void* p = (void *) opj_image_create;\n
- return 0;\n
- }
- """,
- msg = 'Checking for library openjpeg', stlib = 'openjpeg', uselib_store = 'OPENJPEG', mandatory = True)
+ conf.check_cc(fragment="""
+ #include <stdio.h>\n
+ #include <openjpeg.h>\n
+ int main () {\n
+ void* p = (void *) opj_image_create;\n
+ return 0;\n
+ }
+ """,
+ msg='Checking for library openjpeg', stlib='openjpeg', uselib_store='OPENJPEG', mandatory=True)
conf.env.HAVE_CXML = 1
conf.env.STLIB_CXML = ['cxml']
@@ -64,42 +68,42 @@ def configure(conf):
# Windows builds are any more reliable
conf.env.append_value('CXXFLAGS', '-O2')
- conf.check_cxx(fragment = """
- #include <boost/version.hpp>\n
- #if BOOST_VERSION < 104500\n
- #error boost too old\n
- #endif\n
- int main(void) { return 0; }\n
- """,
- mandatory = True,
- msg = 'Checking for boost library >= 1.45',
- okmsg = 'yes',
- errmsg = 'too old\nPlease install boost version 1.45 or higher.')
-
- conf.check_cxx(fragment = """
- #include <boost/filesystem.hpp>\n
- int main() { boost::filesystem::copy_file ("a", "b"); }\n
- """,
- msg = 'Checking for boost filesystem library',
- libpath = '/usr/local/lib',
- lib = ['boost_filesystem%s' % boost_lib_suffix, 'boost_system%s' % boost_lib_suffix],
- uselib_store = 'BOOST_FILESYSTEM')
-
- conf.check_cxx(fragment = """
- #include <boost/signals2.hpp>\n
- int main() { boost::signals2::signal<void (int)> x; }\n
- """,
- msg = 'Checking for boost signals2 library',
- uselib_store = 'BOOST_SIGNALS2')
-
- conf.check_cxx(fragment = """
- #include <boost/date_time.hpp>\n
- int main() { boost::gregorian::day_clock::local_day(); }\n
- """,
- msg = 'Checking for boost datetime library',
- libpath = '/usr/local/lib',
- lib = ['boost_date_time%s' % boost_lib_suffix, 'boost_system%s' % boost_lib_suffix],
- uselib_store = 'BOOST_DATETIME')
+ conf.check_cxx(fragment="""
+ #include <boost/version.hpp>\n
+ #if BOOST_VERSION < 104500\n
+ #error boost too old\n
+ #endif\n
+ int main(void) { return 0; }\n
+ """,
+ mandatory=True,
+ msg='Checking for boost library >= 1.45',
+ okmsg='yes',
+ errmsg='too old\nPlease install boost version 1.45 or higher.')
+
+ conf.check_cxx(fragment="""
+ #include <boost/filesystem.hpp>\n
+ int main() { boost::filesystem::copy_file ("a", "b"); }\n
+ """,
+ msg='Checking for boost filesystem library',
+ libpath='/usr/local/lib',
+ lib=['boost_filesystem%s' % boost_lib_suffix, 'boost_system%s' % boost_lib_suffix],
+ uselib_store='BOOST_FILESYSTEM')
+
+ conf.check_cxx(fragment="""
+ #include <boost/signals2.hpp>\n
+ int main() { boost::signals2::signal<void (int)> x; }\n
+ """,
+ msg='Checking for boost signals2 library',
+ uselib_store='BOOST_SIGNALS2')
+
+ conf.check_cxx(fragment="""
+ #include <boost/date_time.hpp>\n
+ int main() { boost::gregorian::day_clock::local_day(); }\n
+ """,
+ msg='Checking for boost datetime library',
+ libpath='/usr/local/lib',
+ lib=['boost_date_time%s' % boost_lib_suffix, 'boost_system%s' % boost_lib_suffix],
+ uselib_store='BOOST_DATETIME')
conf.recurse('test')
conf.recurse('asdcplib')
@@ -112,11 +116,11 @@ def build(bld):
else:
boost_lib_suffix = ''
- bld(source = 'libdcp.pc.in',
- version = VERSION,
- includedir = '%s/include' % bld.env.PREFIX,
- libs = "-L${libdir} -ldcp -lasdcp-libdcp -lkumu-libdcp -lcxml -lboost_system%s" % boost_lib_suffix,
- install_path = '${LIBDIR}/pkgconfig')
+ bld(source='libdcp%s.pc.in' % bld.env.API_VERSION,
+ version=VERSION,
+ includedir='%s/include/libdcp%s' % (bld.env.PREFIX, bld.env.API_VERSION),
+ libs="-L${libdir} -ldcp%s -lasdcp-libdcp%s -lkumu-libdcp%s -lcxml -lboost_system%s" % (API_VERSION, API_VERSION, API_VERSION, boost_lib_suffix),
+ install_path='${LIBDIR}/pkgconfig')
bld.recurse('src')
bld.recurse('tools')
@@ -140,8 +144,8 @@ def create_version_cc(bld, version):
try:
text = '#include "version.h"\n'
- text += 'char const * libdcp::git_commit = \"%s\";\n' % commit
- text += 'char const * libdcp::version = \"%s\";\n' % version
+ text += 'char const * dcp::git_commit = \"%s\";\n' % commit
+ text += 'char const * dcp::version = \"%s\";\n' % version
if bld.env.ENABLE_DEBUG:
debug_string = 'true'
else: