summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--benchmark/wscript2
-rw-r--r--cscript20
-rw-r--r--examples/make_dcp.cc8
-rw-r--r--examples/read_dcp.cc14
-rw-r--r--examples/wscript2
-rw-r--r--libdcp-1.0.pc.in2
-rwxr-xr-xrun/test/subs_in_out2
-rwxr-xr-xrun/tools/dcpmap16
-rwxr-xr-xscripts/check-boilerplate23
-rw-r--r--src/asset_factory.cc19
-rw-r--r--src/asset_list.h4
-rw-r--r--src/asset_map.cc40
-rw-r--r--src/asset_reader.h14
-rw-r--r--src/atmos_asset.cc4
-rw-r--r--src/behaviour.h52
-rw-r--r--src/certificate_chain.cc49
-rw-r--r--src/chromaticity.h4
-rw-r--r--src/colour_conversion.h4
-rw-r--r--src/cpl.cc106
-rw-r--r--src/dcp.cc12
-rw-r--r--src/dcp_time.h4
-rw-r--r--src/encrypted_kdm.cc121
-rw-r--r--src/exceptions.h27
-rw-r--r--src/ffmpeg_image.cc122
-rw-r--r--src/ffmpeg_image.h107
-rw-r--r--src/frame_info.h109
-rw-r--r--src/interop_subtitle_asset.cc10
-rw-r--r--src/interop_subtitle_asset.h4
-rw-r--r--src/j2k_picture_asset.cc229
-rw-r--r--src/j2k_picture_asset.h110
-rw-r--r--src/j2k_picture_asset_writer.cc (renamed from src/picture_asset_writer.cc)12
-rw-r--r--src/j2k_picture_asset_writer.h (renamed from src/picture_asset_writer.h)46
-rw-r--r--src/j2k_picture_asset_writer_common.cc (renamed from src/picture_asset_writer_common.cc)10
-rw-r--r--src/language_tag.h2
-rw-r--r--src/locale_convert.h2
-rw-r--r--src/mono_j2k_picture_asset.cc (renamed from src/mono_picture_asset.cc)50
-rw-r--r--src/mono_j2k_picture_asset.h (renamed from src/mono_picture_asset.h)32
-rw-r--r--src/mono_j2k_picture_asset_reader.h (renamed from src/stereo_picture_asset_reader.h)12
-rw-r--r--src/mono_j2k_picture_asset_writer.cc (renamed from src/mono_picture_asset_writer.cc)34
-rw-r--r--src/mono_j2k_picture_asset_writer.h (renamed from src/mono_picture_asset_writer.h)30
-rw-r--r--src/mono_j2k_picture_frame.cc (renamed from src/mono_picture_frame.cc)18
-rw-r--r--src/mono_j2k_picture_frame.h (renamed from src/mono_picture_frame.h)26
-rw-r--r--src/mono_mpeg2_picture_asset.cc86
-rw-r--r--src/mono_mpeg2_picture_asset.h73
-rw-r--r--src/mono_mpeg2_picture_asset_reader.h58
-rw-r--r--src/mono_mpeg2_picture_asset_writer.cc144
-rw-r--r--src/mono_mpeg2_picture_asset_writer.h68
-rw-r--r--src/mono_mpeg2_picture_frame.cc91
-rw-r--r--src/mono_mpeg2_picture_frame.h81
-rw-r--r--src/mpeg2_picture_asset.cc74
-rw-r--r--src/mpeg2_picture_asset.h90
-rw-r--r--src/mpeg2_picture_asset_writer.cc48
-rw-r--r--src/mpeg2_picture_asset_writer.h73
-rw-r--r--src/mpeg2_picture_asset_writer_common.cc93
-rw-r--r--src/mpeg2_transcode.cc216
-rw-r--r--src/mpeg2_transcode.h108
-rw-r--r--src/mxf.h7
-rw-r--r--src/name_format.h4
-rw-r--r--src/picture_asset.cc187
-rw-r--r--src/picture_asset.h72
-rw-r--r--src/pkl.cc26
-rw-r--r--src/pkl.h2
-rw-r--r--src/rating.cc4
-rw-r--r--src/reel.cc14
-rw-r--r--src/reel.h2
-rw-r--r--src/reel_asset.cc18
-rw-r--r--src/reel_asset.h2
-rw-r--r--src/reel_atmos_asset.cc6
-rw-r--r--src/reel_atmos_asset.h2
-rw-r--r--src/reel_file_asset.cc10
-rw-r--r--src/reel_file_asset.h2
-rw-r--r--src/reel_interop_closed_caption_asset.cc6
-rw-r--r--src/reel_interop_closed_caption_asset.h2
-rw-r--r--src/reel_markers_asset.cc12
-rw-r--r--src/reel_markers_asset.h4
-rw-r--r--src/reel_mono_picture_asset.cc4
-rw-r--r--src/reel_mono_picture_asset.h29
-rw-r--r--src/reel_picture_asset.cc18
-rw-r--r--src/reel_picture_asset.h36
-rw-r--r--src/reel_smpte_closed_caption_asset.cc6
-rw-r--r--src/reel_smpte_closed_caption_asset.h2
-rw-r--r--src/reel_smpte_subtitle_asset.h4
-rw-r--r--src/reel_stereo_picture_asset.cc4
-rw-r--r--src/reel_stereo_picture_asset.h18
-rw-r--r--src/reel_subtitle_asset.cc6
-rw-r--r--src/reel_subtitle_asset.h2
-rw-r--r--src/rgb_xyz.h2
-rw-r--r--src/smpte_subtitle_asset.cc31
-rw-r--r--src/sound_asset.cc11
-rw-r--r--src/stereo_j2k_picture_asset.cc (renamed from src/stereo_picture_asset.cc)46
-rw-r--r--src/stereo_j2k_picture_asset.h (renamed from src/stereo_picture_asset.h)26
-rw-r--r--src/stereo_j2k_picture_asset_reader.h (renamed from src/mono_picture_asset_reader.h)12
-rw-r--r--src/stereo_j2k_picture_asset_writer.cc (renamed from src/stereo_picture_asset_writer.cc)34
-rw-r--r--src/stereo_j2k_picture_asset_writer.h (renamed from src/stereo_picture_asset_writer.h)26
-rw-r--r--src/stereo_j2k_picture_frame.cc (renamed from src/stereo_picture_frame.cc)28
-rw-r--r--src/stereo_j2k_picture_frame.h (renamed from src/stereo_picture_frame.h)28
-rw-r--r--src/subtitle_asset_internal.cc16
-rw-r--r--src/types.cc8
-rw-r--r--src/verify.cc955
-rw-r--r--src/verify.h50
-rw-r--r--src/verify_j2k.h4
-rw-r--r--src/verify_report.cc144
-rw-r--r--src/verify_report.h237
-rw-r--r--src/wscript71
-rw-r--r--test/combine_test.cc12
-rw-r--r--test/cpl_sar_test.cc4
-rw-r--r--test/data/text_formatter.txt8
-rw-r--r--test/data/text_formatter_windows.txt8
-rw-r--r--test/dcp_test.cc26
-rw-r--r--test/decryption_test.cc14
-rw-r--r--test/encryption_test.cc8
-rw-r--r--test/frame_info_hash_test.cc16
-rw-r--r--test/kdm_test.cc12
-rw-r--r--test/mca_test.cc3
-rw-r--r--test/mono_mpeg2_picture_read_test.cc62
-rw-r--r--test/mono_mpeg2_picture_write_test.cc101
-rw-r--r--test/recovery_test.cc16
-rw-r--r--test/ref/DCP/dcp_test1/ASSETMAP.xml2
-rw-r--r--test/ref/DCP/dcp_test1/audio.mxfbin881326 -> 881326 bytes
-rw-r--r--test/ref/DCP/dcp_test1/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml4
-rw-r--r--test/ref/DCP/dcp_test1/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml8
-rw-r--r--test/ref/DCP/dcp_test1/video.mxfbin49240 -> 31648 bytes
-rw-r--r--test/ref/DCP/dcp_test2/audio.mxfbin161326 -> 161326 bytes
-rw-r--r--test/ref/DCP/dcp_test2/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml4
-rw-r--r--test/ref/DCP/dcp_test2/pkl_8577c7c0-be29-4eb5-a449-1e3870a42bbd.xml6
-rw-r--r--test/ref/DCP/dcp_test2/video.mxfbin63160 -> 63160 bytes
-rw-r--r--test/ref/DCP/dcp_test5/audio.mxfbin161326 -> 161326 bytes
-rw-r--r--test/ref/DCP/dcp_test5/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml4
-rw-r--r--test/ref/DCP/dcp_test5/pkl_d76fdaaf-8316-42dc-a87e-1719ad6ca3ca.xml6
-rw-r--r--test/ref/DCP/dcp_test5/video.mxfbin40144 -> 40144 bytes
-rw-r--r--test/ref/DCP/dcp_test7/ASSETMAP2
-rw-r--r--test/ref/DCP/dcp_test7/audio.mxfbin881326 -> 881326 bytes
-rw-r--r--test/ref/DCP/dcp_test7/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml4
-rw-r--r--test/ref/DCP/dcp_test7/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml8
-rw-r--r--test/ref/DCP/dcp_test7/video.mxfbin49240 -> 31648 bytes
-rw-r--r--test/ref/DCP/encryption_test/audio.mxfbin165454 -> 165454 bytes
-rw-r--r--test/ref/DCP/encryption_test/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml18
-rw-r--r--test/ref/DCP/encryption_test/pkl_5203f3d4-9d62-4062-8bf1-7a114eff99df.xml20
-rw-r--r--test/ref/DCP/encryption_test/video.mxfbin44008 -> 44008 bytes
-rw-r--r--test/round_trip_test.cc14
-rw-r--r--test/shared_subtitle_test.cc12
-rw-r--r--test/stream_operators.cc3
-rw-r--r--test/test.cc30
-rw-r--r--test/test.h4
-rw-r--r--test/verify_report_test.cc67
-rw-r--r--test/verify_test.cc2769
-rw-r--r--test/wscript9
-rw-r--r--tools/dcpdecryptmxf.cc10
-rw-r--r--tools/dcpdumpimage.cc4
-rw-r--r--tools/dcpinfo.cc10
-rw-r--r--tools/dcpverify.cc21
-rw-r--r--tools/wscript2
-rw-r--r--wscript33
153 files changed, 6449 insertions, 1972 deletions
diff --git a/benchmark/wscript b/benchmark/wscript
index 7097a762..7305bdaa 100644
--- a/benchmark/wscript
+++ b/benchmark/wscript
@@ -35,7 +35,7 @@ def build(bld):
for p in ['rgb_to_xyz', 'j2k_transcode']:
obj = bld(features='cxx cxxprogram')
obj.name = p
- obj.uselib = 'BOOST_FILESYSTEM ASDCPLIB_CTH CXML'
+ obj.uselib = 'BOOST_FILESYSTEM ASDCPLIB_DCPOMATIC CXML AVCODEC AVUTIL'
obj.cppflags = ['-g', '-O2']
obj.use = 'libdcp%s' % bld.env.API_VERSION
obj.source = "%s.cc" % p
diff --git a/cscript b/cscript
index 618b2fb9..bec2a383 100644
--- a/cscript
+++ b/cscript
@@ -35,7 +35,22 @@ import os
import shutil
def dependencies(target, options):
- return (('libcxml', 'v0.17.6'), ('openjpeg', '925ca5192bb16d4f58a6fddc8b1623eced7f0203'), ('asdcplib', '8a4a2f25cac0c58aac1d4267facab20e5ec3b57f'))
+ deps = [
+ ('libcxml', 'v0.17.9', options),
+ ('openjpeg', 'ad8edaacd54a862940d0a77c41ecda5858b54d6e'),
+ ('asdcplib', 'v1.0.1')
+ ]
+
+ if target.platform == 'linux':
+ ffmpeg_options = { 'shared': False }
+ else:
+ ffmpeg_options = {}
+
+ if target.platform != 'linux' or target.distro != 'arch':
+ # Use distro-provided FFmpeg on Arch, otherwise our own
+ deps.append(('ffmpeg', '0b73d2f5e70a04a67aa902902c42e3025ef3bb77', ffmpeg_options))
+
+ return deps
def build(target, options):
cmd = './waf configure --disable-examples --disable-dumpimage --disable-benchmarks --prefix=%s' % target.directory
@@ -47,6 +62,9 @@ def build(target, options):
elif target.platform == 'windows':
cmd += f' --target-windows-{target.bits}'
+ if 'c++17' in options and options['c++17']:
+ cmd += ' --c++17'
+
if target.debug:
cmd += ' --enable-debug'
diff --git a/examples/make_dcp.cc b/examples/make_dcp.cc
index 6e0961a5..80e5f52b 100644
--- a/examples/make_dcp.cc
+++ b/examples/make_dcp.cc
@@ -33,8 +33,8 @@
#include "dcp.h"
#include "cpl.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_writer.h"
#include "sound_asset.h"
#include "sound_asset_writer.h"
#include "reel.h"
@@ -56,10 +56,10 @@ main ()
per second.
*/
- auto picture_asset = std::make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
+ auto picture_asset = std::make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
/* Start off a write to it */
- auto picture_writer = picture_asset->start_write("DCP/picture.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto picture_writer = picture_asset->start_write("DCP/picture.mxf", dcp::Behaviour::MAKE_NEW);
/* Write 24 frames of the same JPEG2000 file */
dcp::ArrayData picture("examples/help.j2c");
diff --git a/examples/read_dcp.cc b/examples/read_dcp.cc
index f099409f..fff02288 100644
--- a/examples/read_dcp.cc
+++ b/examples/read_dcp.cc
@@ -27,10 +27,10 @@
#include "cpl.h"
#include "reel.h"
#include "reel_picture_asset.h"
-#include "mono_picture_frame.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_reader.h"
-#include "stereo_picture_asset.h"
+#include "mono_j2k_picture_frame.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_reader.h"
+#include "stereo_j2k_picture_asset.h"
#include "sound_asset.h"
#include "subtitle_asset.h"
#include "openjpeg_image.h"
@@ -71,9 +71,9 @@ main ()
auto assets = dcp.assets();
std::cout << "DCP has " << assets.size() << " assets.\n";
for (auto i: assets) {
- if (std::dynamic_pointer_cast<dcp::MonoPictureAsset>(i)) {
+ if (std::dynamic_pointer_cast<dcp::MonoJ2KPictureAsset>(i)) {
std::cout << "2D picture\n";
- } else if (std::dynamic_pointer_cast<dcp::StereoPictureAsset>(i)) {
+ } else if (std::dynamic_pointer_cast<dcp::StereoJ2KPictureAsset>(i)) {
std::cout << "3D picture\n";
} else if (std::dynamic_pointer_cast<dcp::SoundAsset>(i)) {
std::cout << "Sound\n";
@@ -89,7 +89,7 @@ main ()
auto cpl = dcp.cpls().front();
/* Get the picture asset in the first reel */
- auto picture_asset = std::dynamic_pointer_cast<dcp::MonoPictureAsset>(
+ auto picture_asset = std::dynamic_pointer_cast<dcp::MonoJ2KPictureAsset>(
cpl->reels()[0]->main_picture()->asset()
);
diff --git a/examples/wscript b/examples/wscript
index d062af1b..68cd79ee 100644
--- a/examples/wscript
+++ b/examples/wscript
@@ -21,7 +21,7 @@ def build(bld):
obj = bld(features='cxx cxxprogram')
obj.name = example
obj.use = 'libdcp%s' % bld.env.API_VERSION
- obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM OPENSSL XMLSEC1 MAGICK'
+ obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC BOOST_FILESYSTEM OPENSSL XMLSEC1 MAGICK AVCODEC AVUTIL'
obj.source = example + '.cc'
obj.target = example
obj.install_path = ''
diff --git a/libdcp-1.0.pc.in b/libdcp-1.0.pc.in
index 04b326ca..a8d1007f 100644
--- a/libdcp-1.0.pc.in
+++ b/libdcp-1.0.pc.in
@@ -5,6 +5,6 @@ includedir=@includedir@
Name: libdcp
Description: DCP reading and writing library
Version: @version@
-Requires: openssl libxml++-2.6 xmlsec1 libasdcp-carl xerces-c
+Requires: openssl libxml++-@xmlpp_api@ xmlsec1 libasdcp-dcpomatic xerces-c libavutil libavcodec
Libs: @libs@
Cflags: -I${includedir}
diff --git a/run/test/subs_in_out b/run/test/subs_in_out
index 513294d1..2bf4fea4 100755
--- a/run/test/subs_in_out
+++ b/run/test/subs_in_out
@@ -2,7 +2,7 @@
export LD_LIBRARY_PATH=build/src:build/asdcplib/src:$LD_LIBRARY_PATH
# SIP stops this being passed in from the caller's environment
-export DYLD_LIBRARY_PATH=/Users/ci/osx-environment/x86_64/10.10/lib
+export DYLD_LIBRARY_PATH=/Users/ci/osx-environment/x86_64/10.10/lib:/Users/ci/workspace/lib
if [ "$1" == "--debug" ]; then
shift
gdb --args build/test/subs_in_out "$@"
diff --git a/run/tools/dcpmap b/run/tools/dcpmap
new file mode 100755
index 00000000..ab236329
--- /dev/null
+++ b/run/tools/dcpmap
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+top=$DIR/../..
+export LIBDCP_RESOURCES=$top
+
+export LD_LIBRARY_PATH=$top/build/src:build/asdcplib/src:$LD_LIBRARY_PATH
+if [ "$1" == "--debug" ]; then
+ shift
+ gdb --args $top/build/tools/dcpmap "$@"
+elif [ "$1" == "--valgrind" ]; then
+ shift
+ valgrind --tool="memcheck" --leak-check=full --show-reachable=yes $top/build/tools/dcpmap "$@"
+else
+ $top/build/tools/dcpmap "$@"
+fi
diff --git a/scripts/check-boilerplate b/scripts/check-boilerplate
new file mode 100755
index 00000000..311f95b8
--- /dev/null
+++ b/scripts/check-boilerplate
@@ -0,0 +1,23 @@
+#!/usr/bin/python
+
+import glob
+import os
+import sys
+
+for file in glob.glob('src/*.h'):
+ for line in open(file).readlines():
+ if line.find('@file') != -1:
+ filename = line.strip().split()[2]
+ if filename != file:
+ print(f'AWOOGA: {file} {filename}')
+ sys.exit(1)
+ elif line.find('ifndef') != -1:
+ guard = line.strip().split()[1]
+ if not guard.startswith('LIBDCP'):
+ print(f'AWOOGA: {file} {guard}')
+ sys.exit(1)
+ correct_guard = 'LIBDCP_' + os.path.basename(file).upper().replace('.', '_')
+ if guard != correct_guard:
+ print(f'AWOOGA: {file} {guard} {correct_guard}')
+ sys.exit(1)
+
diff --git a/src/asset_factory.cc b/src/asset_factory.cc
index be4f6b49..26811366 100644
--- a/src/asset_factory.cc
+++ b/src/asset_factory.cc
@@ -40,11 +40,12 @@
#include "asset_factory.h"
#include "atmos_asset.h"
#include "compose.hpp"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_mpeg2_picture_asset.h"
#include "smpte_subtitle_asset.h"
#include "sound_asset.h"
-#include "stereo_picture_asset.h"
-#include "stereo_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
#include <memory>
@@ -61,21 +62,23 @@ dcp::asset_factory (boost::filesystem::path path, bool ignore_incorrect_picture_
*/
ASDCP::EssenceType_t type;
- auto const result = ASDCP::EssenceType(dcp::filesystem::fix_long_path(path).string().c_str(), type);
+ Kumu::FileReaderFactory factory;
+ auto const result = ASDCP::EssenceType(dcp::filesystem::fix_long_path(path).string().c_str(), type, factory);
if (!ASDCP_SUCCESS(result)) {
throw ReadError(String::compose("Could not find essence type (%1)", result.Message()), path.string());
}
switch (type) {
case ASDCP::ESS_UNKNOWN:
+ throw ReadError("Unknown asset type");
case ASDCP::ESS_MPEG2_VES:
- throw ReadError ("MPEG2 video essences are not supported");
+ return make_shared<MonoMPEG2PictureAsset>(path);
case ASDCP::ESS_JPEG_2000:
try {
- return make_shared<MonoPictureAsset>(path);
+ return make_shared<MonoJ2KPictureAsset>(path);
} catch (dcp::MXFFileError& e) {
if (ignore_incorrect_picture_mxf_type && e.number() == ASDCP::RESULT_SFORMAT) {
/* Tried to load it as mono but the error says it's stereo; try that instead */
- auto stereo = make_shared<StereoPictureAsset>(path);
+ auto stereo = make_shared<StereoJ2KPictureAsset>(path);
if (stereo && found_threed_marked_as_twod) {
*found_threed_marked_as_twod = true;
}
@@ -88,7 +91,7 @@ dcp::asset_factory (boost::filesystem::path path, bool ignore_incorrect_picture_
case ASDCP::ESS_PCM_24b_96k:
return make_shared<SoundAsset>(path);
case ASDCP::ESS_JPEG_2000_S:
- return make_shared<StereoPictureAsset>(path);
+ return make_shared<StereoJ2KPictureAsset>(path);
case ASDCP::ESS_TIMED_TEXT:
return make_shared<SMPTESubtitleAsset>(path);
case ASDCP::ESS_DCDATA_DOLBY_ATMOS:
diff --git a/src/asset_list.h b/src/asset_list.h
index 5c50495d..29563a8a 100644
--- a/src/asset_list.h
+++ b/src/asset_list.h
@@ -32,8 +32,8 @@
*/
-#ifndef DCP_ASSET_LIST_H
-#define DCP_ASSET_LIST_H
+#ifndef LIBDCP_ASSET_LIST_H
+#define LIBDCP_ASSET_LIST_H
#include "types.h"
diff --git a/src/asset_map.cc b/src/asset_map.cc
index 281f27c3..0ee4b486 100644
--- a/src/asset_map.cc
+++ b/src/asset_map.cc
@@ -165,29 +165,29 @@ AssetMap::write_xml(boost::filesystem::path file) const
DCP_ASSERT (false);
}
- root->add_child("Id")->add_child_text("urn:uuid:" + _id);
+ cxml::add_text_child(root, "Id", "urn:uuid:" + _id);
if (_annotation_text) {
- root->add_child("AnnotationText")->add_child_text(*_annotation_text);
+ cxml::add_text_child(root, "AnnotationText", *_annotation_text);
}
switch (_standard) {
case Standard::INTEROP:
- root->add_child("VolumeCount")->add_child_text("1");
- root->add_child("IssueDate")->add_child_text(_issue_date);
- root->add_child("Issuer")->add_child_text(_issuer);
- root->add_child("Creator")->add_child_text(_creator);
+ cxml::add_text_child(root, "VolumeCount", "1");
+ cxml::add_text_child(root, "IssueDate", _issue_date);
+ cxml::add_text_child(root, "Issuer", _issuer);
+ cxml::add_text_child(root, "Creator", _creator);
break;
case Standard::SMPTE:
- root->add_child("Creator")->add_child_text(_creator);
- root->add_child("VolumeCount")->add_child_text("1");
- root->add_child("IssueDate")->add_child_text(_issue_date);
- root->add_child("Issuer")->add_child_text(_issuer);
+ cxml::add_text_child(root, "Creator", _creator);
+ cxml::add_text_child(root, "VolumeCount", "1");
+ cxml::add_text_child(root, "IssueDate", _issue_date);
+ cxml::add_text_child(root, "Issuer", _issuer);
break;
default:
DCP_ASSERT (false);
}
- auto asset_list = root->add_child("AssetList");
+ auto asset_list = cxml::add_child(root, "AssetList");
for (auto const& asset: _assets) {
asset.write_xml(asset_list, file.parent_path());
}
@@ -200,20 +200,20 @@ AssetMap::write_xml(boost::filesystem::path file) const
void
AssetMap::Asset::write_xml(xmlpp::Element* asset_list, boost::filesystem::path dcp_root_directory) const
{
- auto node = asset_list->add_child("Asset");
- node->add_child("Id")->add_child_text("urn:uuid:" + _id);
+ auto node = cxml::add_child(asset_list, "Asset");
+ cxml::add_text_child(node, "Id", "urn:uuid:" + _id);
if (_pkl) {
- node->add_child("PackingList")->add_child_text("true");
+ cxml::add_text_child(node, "PackingList", "true");
}
- auto chunk_list = node->add_child("ChunkList");
- auto chunk = chunk_list->add_child("Chunk");
+ auto chunk_list = cxml::add_child(node, "ChunkList");
+ auto chunk = cxml::add_child(chunk_list, "Chunk");
auto relative_path = relative_to_root(filesystem::canonical(dcp_root_directory), filesystem::canonical(_path));
DCP_ASSERT(relative_path);
- chunk->add_child("Path")->add_child_text(relative_path->generic_string());
- chunk->add_child("VolumeIndex")->add_child_text("1");
- chunk->add_child("Offset")->add_child_text("0");
- chunk->add_child("Length")->add_child_text(raw_convert<string>(filesystem::file_size(_path)));
+ cxml::add_text_child(chunk, "Path", relative_path->generic_string());
+ cxml::add_text_child(chunk, "VolumeIndex", "1");
+ cxml::add_text_child(chunk, "Offset", "0");
+ cxml::add_text_child(chunk, "Length", raw_convert<string>(filesystem::file_size(_path)));
}
diff --git a/src/asset_reader.h b/src/asset_reader.h
index c8953e09..091ac915 100644
--- a/src/asset_reader.h
+++ b/src/asset_reader.h
@@ -53,9 +53,9 @@ namespace dcp {
class AtmosAsset;
-class MonoPictureAsset;
+class MonoJ2KPictureAsset;
class SoundAsset;
-class StereoPictureAsset;
+class StereoJ2KPictureAsset;
template <class R, class F>
@@ -90,14 +90,16 @@ protected:
private:
friend class AtmosAsset;
- friend class MonoPictureAsset;
+ friend class MonoJ2KPictureAsset;
+ friend class MonoMPEG2PictureAsset;
friend class SoundAsset;
- friend class StereoPictureAsset;
+ friend class StereoJ2KPictureAsset;
- explicit AssetReader (Asset const * asset, boost::optional<Key> key, Standard standard)
+ AssetReader(Asset const * asset, boost::optional<Key> key, Standard standard)
: _crypto_context (new DecryptionContext(key, standard))
{
- _reader = new R ();
+ Kumu::FileReaderFactory factory;
+ _reader = new R(factory);
DCP_ASSERT (asset->file());
auto const r = _reader->OpenRead(dcp::filesystem::fix_long_path(*asset->file()).string().c_str());
if (ASDCP_FAILURE(r)) {
diff --git a/src/atmos_asset.cc b/src/atmos_asset.cc
index 42a0774e..09a22c1e 100644
--- a/src/atmos_asset.cc
+++ b/src/atmos_asset.cc
@@ -42,6 +42,7 @@
#include "atmos_asset_writer.h"
#include "exceptions.h"
#include <asdcp/AS_DCP.h>
+#include <asdcp/KM_fileio.h>
using std::string;
@@ -67,7 +68,8 @@ AtmosAsset::AtmosAsset (boost::filesystem::path file)
: Asset (file)
, MXF (Standard::SMPTE)
{
- ASDCP::ATMOS::MXFReader reader;
+ Kumu::FileReaderFactory factory;
+ ASDCP::ATMOS::MXFReader reader(factory);
auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
diff --git a/src/behaviour.h b/src/behaviour.h
new file mode 100644
index 00000000..1600966c
--- /dev/null
+++ b/src/behaviour.h
@@ -0,0 +1,52 @@
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_BEHAVIOUR_H
+#define LIBDCP_BEHAVIOUR_H
+
+
+namespace dcp {
+
+
+enum class Behaviour {
+ OVERWRITE_EXISTING,
+ MAKE_NEW
+};
+
+
+}
+
+
+#endif
+
diff --git a/src/certificate_chain.cc b/src/certificate_chain.cc
index c4e3a9b0..2bbddc7f 100644
--- a/src/certificate_chain.cc
+++ b/src/certificate_chain.cc
@@ -606,47 +606,47 @@ CertificateChain::sign (xmlpp::Element* parent, Standard standard) const
/* <Signer> */
parent->add_child_text(" ");
- auto signer = parent->add_child("Signer");
+ auto signer = cxml::add_child(parent, "Signer");
signer->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig");
- auto data = signer->add_child("X509Data", "dsig");
- auto serial_element = data->add_child("X509IssuerSerial", "dsig");
- serial_element->add_child("X509IssuerName", "dsig")->add_child_text (leaf().issuer());
- serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (leaf().serial());
- data->add_child("X509SubjectName", "dsig")->add_child_text (leaf().subject());
+ auto data = cxml::add_child(signer, "X509Data", string("dsig"));
+ auto serial_element = cxml::add_child(data, "X509IssuerSerial", string("dsig"));
+ cxml::add_child(serial_element, "X509IssuerName", string("dsig"))->add_child_text(leaf().issuer());
+ cxml::add_child(serial_element, "X509SerialNumber", string("dsig"))->add_child_text(leaf().serial());
+ cxml::add_child(data, "X509SubjectName", string("dsig"))->add_child_text(leaf().subject());
indent (signer, 2);
/* <Signature> */
parent->add_child_text("\n ");
- auto signature = parent->add_child("Signature");
+ auto signature = cxml::add_child(parent, "Signature");
signature->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig");
signature->set_namespace ("dsig");
parent->add_child_text("\n");
- auto 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");
+ auto signed_info = cxml::add_child(signature, "SignedInfo", string("dsig"));
+ cxml::add_child(signed_info, "CanonicalizationMethod", string("dsig"))->set_attribute("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
if (standard == Standard::INTEROP) {
- signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1");
+ cxml::add_child(signed_info, "SignatureMethod", string("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");
+ cxml::add_child(signed_info, "SignatureMethod", string("dsig"))->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
}
- auto reference = signed_info->add_child("Reference", "dsig");
+ auto reference = cxml::add_child(signed_info, "Reference", string("dsig"));
reference->set_attribute ("URI", "");
- auto transforms = reference->add_child("Transforms", "dsig");
- transforms->add_child("Transform", "dsig")->set_attribute (
+ auto transforms = cxml::add_child(reference, "Transforms", string("dsig"));
+ cxml::add_child(transforms, "Transform", string("dsig"))->set_attribute(
"Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
);
- reference->add_child("DigestMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
+ cxml::add_child(reference, "DigestMethod", string("dsig"))->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
/* This will be filled in by the signing later */
- reference->add_child("DigestValue", "dsig");
+ cxml::add_child(reference, "DigestValue", string("dsig"));
- signature->add_child("SignatureValue", "dsig");
- signature->add_child("KeyInfo", "dsig");
+ cxml::add_child(signature, "SignatureValue", string("dsig"));
+ cxml::add_child(signature, "KeyInfo", string("dsig"));
add_signature_value (signature, "dsig", true);
}
@@ -655,19 +655,20 @@ void
CertificateChain::add_signature_value (xmlpp::Element* parent, string ns, bool add_indentation) const
{
cxml::Node cp (parent);
- auto key_info = cp.node_child("KeyInfo")->node();
+ auto key_info = dynamic_cast<xmlpp::Element*>(cp.node_child("KeyInfo")->node());
+ DCP_ASSERT(key_info);
/* Add the certificate chain to the KeyInfo child node of parent */
for (auto const& i: leaf_to_root()) {
- auto data = key_info->add_child("X509Data", ns);
+ auto data = cxml::add_child(key_info, "X509Data", ns);
{
- auto serial = data->add_child("X509IssuerSerial", ns);
- serial->add_child("X509IssuerName", ns)->add_child_text (i.issuer ());
- serial->add_child("X509SerialNumber", ns)->add_child_text (i.serial ());
+ auto serial = cxml::add_child(data, "X509IssuerSerial", ns);
+ cxml::add_child(serial, "X509IssuerName", ns)->add_child_text(i.issuer());
+ cxml::add_child(serial, "X509SerialNumber", ns)->add_child_text(i.serial());
}
- data->add_child("X509Certificate", ns)->add_child_text (i.certificate());
+ cxml::add_child(data, "X509Certificate", ns)->add_child_text(i.certificate());
}
auto signature_context = xmlSecDSigCtxCreate (0);
diff --git a/src/chromaticity.h b/src/chromaticity.h
index 41bb8fda..52edd7bf 100644
--- a/src/chromaticity.h
+++ b/src/chromaticity.h
@@ -37,8 +37,8 @@
*/
-#ifndef DCP_CHROMATICITY_H
-#define DCP_CHROMATICITY_H
+#ifndef LIBDCP_CHROMATICITY_H
+#define LIBDCP_CHROMATICITY_H
#include <cmath>
diff --git a/src/colour_conversion.h b/src/colour_conversion.h
index 8501699a..29140541 100644
--- a/src/colour_conversion.h
+++ b/src/colour_conversion.h
@@ -37,8 +37,8 @@
*/
-#ifndef DCP_COLOUR_CONVERSION_H
-#define DCP_COLOUR_CONVERSION_H
+#ifndef LIBDCP_COLOUR_CONVERSION_H
+#define LIBDCP_COLOUR_CONVERSION_H
#include "chromaticity.h"
diff --git a/src/cpl.cc b/src/cpl.cc
index 6a25863a..e8cec95c 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -213,15 +213,15 @@ CPL::write_xml(boost::filesystem::path file, shared_ptr<const CertificateChain>
root = doc.create_root_node ("CompositionPlaylist", cpl_smpte_ns);
}
- root->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ cxml::add_text_child(root, "Id", "urn:uuid:" + _id);
if (_annotation_text) {
- root->add_child("AnnotationText")->add_child_text (*_annotation_text);
+ cxml::add_text_child(root, "AnnotationText", *_annotation_text);
}
- root->add_child("IssueDate")->add_child_text (_issue_date);
- root->add_child("Issuer")->add_child_text (_issuer);
- root->add_child("Creator")->add_child_text (_creator);
- root->add_child("ContentTitleText")->add_child_text (_content_title_text);
- auto content_kind = root->add_child("ContentKind");
+ cxml::add_text_child(root, "IssueDate", _issue_date);
+ cxml::add_text_child(root, "Issuer", _issuer);
+ cxml::add_text_child(root, "Creator", _creator);
+ cxml::add_text_child(root, "ContentTitleText", _content_title_text);
+ auto content_kind = cxml::add_child(root, "ContentKind");
content_kind->add_child_text(_content_kind.name());
if (_content_kind.scope()) {
content_kind->set_attribute("scope", *_content_kind.scope());
@@ -233,12 +233,12 @@ CPL::write_xml(boost::filesystem::path file, shared_ptr<const CertificateChain>
_content_versions[0].as_xml (root);
}
- auto rating_list = root->add_child("RatingList");
+ auto rating_list = cxml::add_child(root, "RatingList");
for (auto i: _ratings) {
- i.as_xml (rating_list->add_child("Rating"));
+ i.as_xml(cxml::add_child(rating_list, "Rating"));
}
- auto reel_list = root->add_child ("ReelList");
+ auto reel_list = cxml::add_child(root, "ReelList");
if (_reels.empty()) {
throw NoReelsError ();
@@ -403,27 +403,27 @@ CPL::write_mca_subdescriptors(xmlpp::Element* parent, shared_ptr<const SoundAsse
reinterpret_cast<ASDCP::MXF::InterchangeObject**>(&soundfield)
);
if (KM_SUCCESS(r)) {
- auto mca_subs = parent->add_child("mca:MCASubDescriptors");
+ auto mca_subs = cxml::add_child(parent, "mca:MCASubDescriptors");
mca_subs->set_namespace_declaration (mca_sub_descriptors_ns, "mca");
mca_subs->set_namespace_declaration (smpte_395_ns, "r0");
mca_subs->set_namespace_declaration (smpte_335_ns, "r1");
- auto sf = mca_subs->add_child("SoundfieldGroupLabelSubDescriptor", "r0");
+ auto sf = cxml::add_child(mca_subs, "SoundfieldGroupLabelSubDescriptor", string("r0"));
char buffer[64];
soundfield->InstanceUID.EncodeString(buffer, sizeof(buffer));
- sf->add_child("InstanceID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ cxml::add_child(sf, "InstanceID", string("r1"))->add_child_text("urn:uuid:" + string(buffer));
soundfield->MCALabelDictionaryID.EncodeString(buffer, sizeof(buffer));
- sf->add_child("MCALabelDictionaryID", "r1")->add_child_text("urn:smpte:ul:" + string(buffer));
+ cxml::add_child(sf, "MCALabelDictionaryID", string("r1"))->add_child_text("urn:smpte:ul:" + string(buffer));
soundfield->MCALinkID.EncodeString(buffer, sizeof(buffer));
- sf->add_child("MCALinkID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ cxml::add_child(sf, "MCALinkID", string("r1"))->add_child_text("urn:uuid:" + string(buffer));
soundfield->MCATagSymbol.EncodeString(buffer, sizeof(buffer));
- sf->add_child("MCATagSymbol", "r1")->add_child_text(buffer);
+ cxml::add_child(sf, "MCATagSymbol", string("r1"))->add_child_text(buffer);
if (!soundfield->MCATagName.empty()) {
soundfield->MCATagName.get().EncodeString(buffer, sizeof(buffer));
- sf->add_child("MCATagName", "r1")->add_child_text(buffer);
+ cxml::add_child(sf, "MCATagName", string("r1"))->add_child_text(buffer);
}
if (!soundfield->RFC5646SpokenLanguage.empty()) {
soundfield->RFC5646SpokenLanguage.get().EncodeString(buffer, sizeof(buffer));
- sf->add_child("RFC5646SpokenLanguage", "r1")->add_child_text(buffer);
+ cxml::add_child(sf, "RFC5646SpokenLanguage", string("r1"))->add_child_text(buffer);
}
/* Find the MCA subdescriptors in the MXF so that we can also write them here */
@@ -435,29 +435,29 @@ CPL::write_mca_subdescriptors(xmlpp::Element* parent, shared_ptr<const SoundAsse
for (auto i: channels) {
auto channel = reinterpret_cast<ASDCP::MXF::AudioChannelLabelSubDescriptor*>(i);
- auto ch = mca_subs->add_child("AudioChannelLabelSubDescriptor", "r0");
+ auto ch = cxml::add_child(mca_subs, "AudioChannelLabelSubDescriptor", string("r0"));
channel->InstanceUID.EncodeString(buffer, sizeof(buffer));
- ch->add_child("InstanceID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ cxml::add_child(ch, "InstanceID", string("r1"))->add_child_text("urn:uuid:" + string(buffer));
channel->MCALabelDictionaryID.EncodeString(buffer, sizeof(buffer));
- ch->add_child("MCALabelDictionaryID", "r1")->add_child_text("urn:smpte:ul:" + string(buffer));
+ cxml::add_child(ch, "MCALabelDictionaryID", string("r1"))->add_child_text("urn:smpte:ul:" + string(buffer));
channel->MCALinkID.EncodeString(buffer, sizeof(buffer));
- ch->add_child("MCALinkID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ cxml::add_child(ch, "MCALinkID", string("r1"))->add_child_text("urn:uuid:" + string(buffer));
channel->MCATagSymbol.EncodeString(buffer, sizeof(buffer));
- ch->add_child("MCATagSymbol", "r1")->add_child_text(buffer);
+ cxml::add_child(ch, "MCATagSymbol", string("r1"))->add_child_text(buffer);
if (!channel->MCATagName.empty()) {
channel->MCATagName.get().EncodeString(buffer, sizeof(buffer));
- ch->add_child("MCATagName", "r1")->add_child_text(buffer);
+ cxml::add_child(ch, "MCATagName", string("r1"))->add_child_text(buffer);
}
if (!channel->MCAChannelID.empty()) {
- ch->add_child("MCAChannelID", "r1")->add_child_text(raw_convert<string>(channel->MCAChannelID.get()));
+ cxml::add_child(ch, "MCAChannelID", string("r1"))->add_child_text(raw_convert<string>(channel->MCAChannelID.get()));
}
if (!channel->RFC5646SpokenLanguage.empty()) {
channel->RFC5646SpokenLanguage.get().EncodeString(buffer, sizeof(buffer));
- ch->add_child("RFC5646SpokenLanguage", "r1")->add_child_text(buffer);
+ cxml::add_child(ch, "RFC5646SpokenLanguage", string("r1"))->add_child_text(buffer);
}
if (!channel->SoundfieldGroupLinkID.empty()) {
channel->SoundfieldGroupLinkID.get().EncodeString(buffer, sizeof(buffer));
- ch->add_child("SoundfieldGroupLinkID", "r1")->add_child_text("urn:uuid:" + string(buffer));
+ cxml::add_child(ch, "SoundfieldGroupLinkID", string("r1"))->add_child_text("urn:uuid:" + string(buffer));
}
}
}
@@ -481,16 +481,16 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m
return;
}
- auto meta = node->add_child("meta:CompositionMetadataAsset");
+ auto meta = cxml::add_child(node, "meta:CompositionMetadataAsset");
meta->set_namespace_declaration (cpl_metadata_ns, "meta");
- meta->add_child("Id")->add_child_text("urn:uuid:" + _cpl_metadata_id);
+ cxml::add_text_child(meta, "Id", "urn:uuid:" + _cpl_metadata_id);
auto mp = _reels.front()->main_picture();
- meta->add_child("EditRate")->add_child_text(mp->edit_rate().as_string());
- meta->add_child("IntrinsicDuration")->add_child_text(raw_convert<string>(mp->intrinsic_duration()));
+ cxml::add_text_child(meta, "EditRate", mp->edit_rate().as_string());
+ cxml::add_text_child(meta, "IntrinsicDuration", raw_convert<string>(mp->intrinsic_duration()));
- auto fctt = meta->add_child("FullContentTitleText", "meta");
+ auto fctt = cxml::add_child(meta, "FullContentTitleText", string("meta"));
if (_full_content_title_text && !_full_content_title_text->empty()) {
fctt->add_child_text (*_full_content_title_text);
}
@@ -499,11 +499,11 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m
}
if (_release_territory) {
- meta->add_child("ReleaseTerritory", "meta")->add_child_text(*_release_territory);
+ cxml::add_child(meta, "ReleaseTerritory", string("meta"))->add_child_text(*_release_territory);
}
if (_version_number) {
- xmlpp::Element* vn = meta->add_child("VersionNumber", "meta");
+ auto vn = cxml::add_child(meta, "VersionNumber", string("meta"));
vn->add_child_text(raw_convert<string>(*_version_number));
if (_status) {
vn->set_attribute("status", status_to_string(*_status));
@@ -511,19 +511,19 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m
}
if (_chain) {
- meta->add_child("Chain", "meta")->add_child_text(*_chain);
+ cxml::add_child(meta, "Chain", string("meta"))->add_child_text(*_chain);
}
if (_distributor) {
- meta->add_child("Distributor", "meta")->add_child_text(*_distributor);
+ cxml::add_child(meta, "Distributor", string("meta"))->add_child_text(*_distributor);
}
if (_facility) {
- meta->add_child("Facility", "meta")->add_child_text(*_facility);
+ cxml::add_child(meta, "Facility", string("meta"))->add_child_text(*_facility);
}
if (_content_versions.size() > 1) {
- xmlpp::Element* vc = meta->add_child("AlternateContentVersionList", "meta");
+ auto vc = cxml::add_child(meta, "AlternateContentVersionList", string("meta"));
for (size_t i = 1; i < _content_versions.size(); ++i) {
_content_versions[i].as_xml (vc);
}
@@ -534,17 +534,17 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m
}
if (_main_sound_configuration) {
- meta->add_child("MainSoundConfiguration", "meta")->add_child_text(_main_sound_configuration->to_string());
+ cxml::add_child(meta, "MainSoundConfiguration", string("meta"))->add_child_text(_main_sound_configuration->to_string());
}
- meta->add_child("MainSoundSampleRate", "meta")->add_child_text(raw_convert<string>(*_main_sound_sample_rate) + " 1");
+ cxml::add_child(meta, "MainSoundSampleRate", string("meta"))->add_child_text(raw_convert<string>(*_main_sound_sample_rate) + " 1");
- auto stored = meta->add_child("MainPictureStoredArea", "meta");
- stored->add_child("Width", "meta")->add_child_text(raw_convert<string>(_main_picture_stored_area->width));
- stored->add_child("Height", "meta")->add_child_text(raw_convert<string>(_main_picture_stored_area->height));
+ auto stored = cxml::add_child(meta, "MainPictureStoredArea", string("meta"));
+ cxml::add_child(stored, "Width", string("meta"))->add_child_text(raw_convert<string>(_main_picture_stored_area->width));
+ cxml::add_child(stored, "Height", string("meta"))->add_child_text(raw_convert<string>(_main_picture_stored_area->height));
- auto active = meta->add_child("MainPictureActiveArea", "meta");
- active->add_child("Width", "meta")->add_child_text(raw_convert<string>(_main_picture_active_area->width));
- active->add_child("Height", "meta")->add_child_text(raw_convert<string>(_main_picture_active_area->height));
+ auto active = cxml::add_child(meta, "MainPictureActiveArea", string("meta"));
+ cxml::add_child(active, "Width", string("meta"))->add_child_text(raw_convert<string>(_main_picture_active_area->width));
+ cxml::add_child(active, "Height", string("meta"))->add_child_text(raw_convert<string>(_main_picture_active_area->height));
optional<string> first_subtitle_language;
for (auto i: _reels) {
@@ -567,18 +567,18 @@ CPL::maybe_write_composition_metadata_asset(xmlpp::Element* node, bool include_m
}
lang += i;
}
- meta->add_child("MainSubtitleLanguageList", "meta")->add_child_text(lang);
+ cxml::add_child(meta, "MainSubtitleLanguageList", string("meta"))->add_child_text(lang);
}
- auto metadata_list = meta->add_child("ExtensionMetadataList", "meta");
+ auto metadata_list = cxml::add_child(meta, "ExtensionMetadataList", string("meta"));
auto add_extension_metadata = [metadata_list](string scope, string name, string property_name, string property_value) {
- auto extension = metadata_list->add_child("ExtensionMetadata", "meta");
+ auto extension = cxml::add_child(metadata_list, "ExtensionMetadata", string("meta"));
extension->set_attribute("scope", scope);
- extension->add_child("Name", "meta")->add_child_text(name);
- auto property = extension->add_child("PropertyList", "meta")->add_child("Property", "meta");
- property->add_child("Name", "meta")->add_child_text(property_name);
- property->add_child("Value", "meta")->add_child_text(property_value);
+ cxml::add_child(extension, "Name", string("meta"))->add_child_text(name);
+ auto property = cxml::add_child(cxml::add_child(extension, "PropertyList", string("meta")), "Property", string("meta"));
+ cxml::add_child(property, "Name", string("meta"))->add_child_text(property_name);
+ cxml::add_child(property, "Value", string("meta"))->add_child_text(property_value);
};
/* SMPTE Bv2.1 8.6.3 */
diff --git a/src/dcp.cc b/src/dcp.cc
index eb21b47d..f0379202 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -51,15 +51,16 @@
#include "font_asset.h"
#include "interop_subtitle_asset.h"
#include "metadata.h"
-#include "mono_picture_asset.h"
-#include "picture_asset.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_mpeg2_picture_asset.h"
+#include "j2k_picture_asset.h"
#include "pkl.h"
#include "raw_convert.h"
#include "reel_asset.h"
#include "reel_subtitle_asset.h"
#include "smpte_subtitle_asset.h"
#include "sound_asset.h"
-#include "stereo_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
#include "util.h"
#include "verify.h"
#include "warnings.h"
@@ -246,7 +247,8 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m
other_assets.push_back (make_shared<InteropSubtitleAsset>(path));
}
} else if (
- *pkl_type == remove_parameters(PictureAsset::static_pkl_type(standard)) ||
+ *pkl_type == remove_parameters(J2KPictureAsset::static_pkl_type(standard)) ||
+ *pkl_type == remove_parameters(MPEG2PictureAsset::static_pkl_type(standard)) ||
*pkl_type == remove_parameters(SoundAsset::static_pkl_type(standard)) ||
*pkl_type == remove_parameters(AtmosAsset::static_pkl_type(standard)) ||
*pkl_type == remove_parameters(SMPTESubtitleAsset::static_pkl_type(standard))
@@ -441,7 +443,7 @@ DCP::write_volindex (Standard standard) const
DCP_ASSERT (false);
}
- root->add_child("Index")->add_child_text ("1");
+ cxml::add_text_child(root, "Index", "1");
doc.write_to_file_formatted(dcp::filesystem::fix_long_path(p).string(), "UTF-8");
}
diff --git a/src/dcp_time.h b/src/dcp_time.h
index 506dafda..21b59921 100644
--- a/src/dcp_time.h
+++ b/src/dcp_time.h
@@ -37,8 +37,8 @@
*/
-#ifndef LIBDCP_TIME_H
-#define LIBDCP_TIME_H
+#ifndef LIBDCP_DCP_TIME_H
+#define LIBDCP_DCP_TIME_H
#include "types.h"
diff --git a/src/encrypted_kdm.cc b/src/encrypted_kdm.cc
index 465a657d..d1089c0b 100644
--- a/src/encrypted_kdm.cc
+++ b/src/encrypted_kdm.cc
@@ -44,6 +44,7 @@
#include "file.h"
#include "util.h"
#include <libcxml/cxml.h>
+#include <libxml++/attributenode.h>
#include <libxml++/document.h>
#include <libxml++/nodes/element.h>
#include <libxml/parser.h>
@@ -85,8 +86,8 @@ public:
void as_xml (xmlpp::Element* node) const
{
- node->add_child("X509IssuerName", "ds")->add_child_text (x509_issuer_name);
- node->add_child("X509SerialNumber", "ds")->add_child_text (x509_serial_number);
+ cxml::add_child(node, "X509IssuerName", string("ds"))->add_child_text(x509_issuer_name);
+ cxml::add_child(node, "X509SerialNumber", string("ds"))->add_child_text(x509_serial_number);
}
string x509_issuer_name;
@@ -108,8 +109,8 @@ public:
void as_xml (xmlpp::Element* node) const
{
- x509_issuer_serial.as_xml (node->add_child ("X509IssuerSerial", "ds"));
- node->add_child("X509Certificate", "ds")->add_child_text (x509_certificate);
+ x509_issuer_serial.as_xml(cxml::add_child(node, "X509IssuerSerial", string("ds")));
+ cxml::add_child(node, "X509Certificate", string("ds"))->add_child_text(x509_certificate);
}
Signer x509_issuer_serial;
@@ -136,8 +137,8 @@ public:
void as_xml (xmlpp::Element* node) const
{
node->set_attribute ("URI", uri);
- node->add_child("DigestMethod", "ds")->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256");
- node->add_child("DigestValue", "ds")->add_child_text (digest_value);
+ cxml::add_child(node, "DigestMethod", string("ds"))->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256");
+ cxml::add_child(node, "DigestValue", string("ds"))->add_child_text(digest_value);
}
string uri;
@@ -168,16 +169,16 @@ public:
void as_xml (xmlpp::Element* node) const
{
- node->add_child ("CanonicalizationMethod", "ds")->set_attribute (
+ cxml::add_child(node, "CanonicalizationMethod", string("ds"))->set_attribute(
"Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"
);
- node->add_child ("SignatureMethod", "ds")->set_attribute (
+ cxml::add_child(node, "SignatureMethod", string("ds"))->set_attribute(
"Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
);
- authenticated_public.as_xml (node->add_child ("Reference", "ds"));
- authenticated_private.as_xml (node->add_child ("Reference", "ds"));
+ authenticated_public.as_xml(cxml::add_child(node, "Reference", string("ds")));
+ authenticated_private.as_xml(cxml::add_child(node, "Reference", string("ds")));
}
private:
@@ -200,14 +201,14 @@ public:
}
}
- void as_xml (xmlpp::Node* node) const
+ void as_xml(xmlpp::Element* element) const
{
- signed_info.as_xml (node->add_child ("SignedInfo", "ds"));
- node->add_child("SignatureValue", "ds")->add_child_text (signature_value);
+ signed_info.as_xml(cxml::add_child(element, "SignedInfo", string("ds")));
+ cxml::add_child(element, "SignatureValue", string("ds"))->add_child_text(signature_value);
- auto key_info_node = node->add_child("KeyInfo", "ds");
+ auto key_info_node = cxml::add_child(element, "KeyInfo", string("ds"));
for (auto i: x509_data) {
- i.as_xml (key_info_node->add_child("X509Data", "ds"));
+ i.as_xml(cxml::add_child(key_info_node, "X509Data", string("ds")));
}
}
@@ -229,22 +230,22 @@ public:
}
}
- void as_xml (xmlpp::Element* node, map<string, xmlpp::Attribute *>& references) const
+ void as_xml (xmlpp::Element* node, map<string, xmlpp::AttributeNode*>& references) const
{
- references["ID_AuthenticatedPrivate"] = node->set_attribute ("Id", "ID_AuthenticatedPrivate");
+ references["ID_AuthenticatedPrivate"] = dynamic_cast<xmlpp::AttributeNode*>(node->set_attribute("Id", "ID_AuthenticatedPrivate"));
for (auto i: encrypted_key) {
- auto encrypted_key = node->add_child ("EncryptedKey", "enc");
+ auto encrypted_key = cxml::add_child(node, "EncryptedKey", string("enc"));
/* XXX: hack for testing with Dolby */
encrypted_key->set_namespace_declaration ("http://www.w3.org/2001/04/xmlenc#", "enc");
- auto encryption_method = encrypted_key->add_child("EncryptionMethod", "enc");
+ auto encryption_method = cxml::add_child(encrypted_key, "EncryptionMethod", string("enc"));
encryption_method->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p");
- auto digest_method = encryption_method->add_child ("DigestMethod", "ds");
+ auto digest_method = cxml::add_child(encryption_method, "DigestMethod", string("ds"));
/* XXX: hack for testing with Dolby */
digest_method->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "ds");
digest_method->set_attribute ("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
- auto cipher_data = encrypted_key->add_child("CipherData", "enc");
- cipher_data->add_child("CipherValue", "enc")->add_child_text (i);
+ auto cipher_data = cxml::add_child(encrypted_key, "CipherData", string("enc"));
+ cxml::add_child(cipher_data, "CipherValue", string("enc"))->add_child_text(i);
}
}
@@ -271,9 +272,9 @@ public:
void as_xml (xmlpp::Element* node) const
{
- auto type = node->add_child("KeyType");
+ auto type = cxml::add_child(node, "KeyType");
type->add_child_text (key_type);
- node->add_child("KeyId")->add_child_text ("urn:uuid:" + key_id);
+ cxml::add_text_child(node, "KeyId", "urn:uuid:" + key_id);
/* XXX: this feels like a bit of a hack */
if (key_type == "MDEK") {
type->set_attribute ("scope", "http://www.dolby.com/cp850/2012/KDM#kdm-key-type");
@@ -302,7 +303,7 @@ public:
void as_xml (xmlpp::Element* node) const
{
for (auto const& i: typed_key_id) {
- i.as_xml (node->add_child("TypedKeyId"));
+ i.as_xml(cxml::add_child(node, ("TypedKeyId")));
}
}
@@ -326,13 +327,13 @@ public:
void as_xml (xmlpp::Element* node) const
{
- node->add_child ("DeviceListIdentifier")->add_child_text ("urn:uuid:" + device_list_identifier);
+ cxml::add_text_child(node, "DeviceListIdentifier", "urn:uuid:" + device_list_identifier);
if (device_list_description) {
- node->add_child ("DeviceListDescription")->add_child_text (device_list_description.get());
+ cxml::add_text_child(node, "DeviceListDescription", device_list_description.get());
}
- auto device_list = node->add_child ("DeviceList");
+ auto device_list = cxml::add_child(node, "DeviceList");
for (auto i: certificate_thumbprints) {
- device_list->add_child("CertificateThumbprint")->add_child_text (i);
+ cxml::add_text_child(device_list, "CertificateThumbprint", i);
}
}
@@ -357,8 +358,8 @@ public:
void as_xml (xmlpp::Element* node) const
{
- node->add_child("X509IssuerName", "ds")->add_child_text (x509_issuer_name);
- node->add_child("X509SerialNumber", "ds")->add_child_text (x509_serial_number);
+ cxml::add_child(node, "X509IssuerName", string("ds"))->add_child_text(x509_issuer_name);
+ cxml::add_child(node, "X509SerialNumber", string("ds"))->add_child_text(x509_serial_number);
}
string x509_issuer_name;
@@ -380,8 +381,8 @@ public:
void as_xml (xmlpp::Element* node) const
{
- x509_issuer_serial.as_xml (node->add_child ("X509IssuerSerial"));
- node->add_child("X509SubjectName")->add_child_text (x509_subject_name);
+ x509_issuer_serial.as_xml(cxml::add_child(node, "X509IssuerSerial"));
+ cxml::add_text_child(node, "X509SubjectName", x509_subject_name);
}
X509IssuerSerial x509_issuer_serial;
@@ -428,30 +429,30 @@ public:
{
node->set_attribute ("xmlns", "http://www.smpte-ra.org/schemas/430-1/2006/KDM");
- recipient.as_xml (node->add_child ("Recipient"));
- node->add_child("CompositionPlaylistId")->add_child_text ("urn:uuid:" + composition_playlist_id);
- node->add_child("ContentTitleText")->add_child_text (content_title_text);
+ recipient.as_xml(cxml::add_child(node, "Recipient"));
+ cxml::add_text_child(node, "CompositionPlaylistId", "urn:uuid:" + composition_playlist_id);
+ cxml::add_text_child(node, "ContentTitleText", content_title_text);
if (content_authenticator) {
- node->add_child("ContentAuthenticator")->add_child_text (content_authenticator.get ());
+ cxml::add_text_child(node, "ContentAuthenticator", content_authenticator.get());
}
- node->add_child("ContentKeysNotValidBefore")->add_child_text (not_valid_before.as_string ());
- node->add_child("ContentKeysNotValidAfter")->add_child_text (not_valid_after.as_string ());
+ cxml::add_text_child(node, "ContentKeysNotValidBefore", not_valid_before.as_string());
+ cxml::add_text_child(node, "ContentKeysNotValidAfter", not_valid_after.as_string());
if (authorized_device_info) {
- authorized_device_info->as_xml (node->add_child ("AuthorizedDeviceInfo"));
+ authorized_device_info->as_xml(cxml::add_child(node, "AuthorizedDeviceInfo"));
}
- key_id_list.as_xml (node->add_child ("KeyIdList"));
+ key_id_list.as_xml(cxml::add_child(node, "KeyIdList"));
if (disable_forensic_marking_picture || disable_forensic_marking_audio) {
- auto forensic_mark_flag_list = node->add_child ("ForensicMarkFlagList");
+ auto forensic_mark_flag_list = cxml::add_child(node, "ForensicMarkFlagList");
if (disable_forensic_marking_picture) {
- forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text(picture_disable);
+ cxml::add_text_child(forensic_mark_flag_list, "ForensicMarkFlag", picture_disable);
}
if (disable_forensic_marking_audio) {
auto mrkflg = audio_disable;
if (*disable_forensic_marking_audio > 0) {
mrkflg += String::compose ("-above-channel-%1", *disable_forensic_marking_audio);
}
- forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text (mrkflg);
+ cxml::add_text_child(forensic_mark_flag_list, "ForensicMarkFlag", mrkflg);
}
}
}
@@ -490,7 +491,7 @@ public:
void as_xml (xmlpp::Element* node) const
{
- kdm_required_extensions.as_xml (node->add_child ("KDMRequiredExtensions"));
+ kdm_required_extensions.as_xml(cxml::add_child(node, "KDMRequiredExtensions"));
}
KDMRequiredExtensions kdm_required_extensions;
@@ -517,21 +518,21 @@ public:
}
- void as_xml (xmlpp::Element* node, map<string, xmlpp::Attribute *>& references) const
+ void as_xml (xmlpp::Element* node, map<string, xmlpp::AttributeNode*>& references) const
{
- references["ID_AuthenticatedPublic"] = node->set_attribute ("Id", "ID_AuthenticatedPublic");
+ references["ID_AuthenticatedPublic"] = dynamic_cast<xmlpp::AttributeNode*>(node->set_attribute("Id", "ID_AuthenticatedPublic"));
- node->add_child("MessageId")->add_child_text ("urn:uuid:" + message_id);
- node->add_child("MessageType")->add_child_text ("http://www.smpte-ra.org/430-1/2006/KDM#kdm-key-type");
+ cxml::add_text_child(node, "MessageId", "urn:uuid:" + message_id);
+ cxml::add_text_child(node, "MessageType", "http://www.smpte-ra.org/430-1/2006/KDM#kdm-key-type");
if (annotation_text) {
- node->add_child("AnnotationText")->add_child_text (annotation_text.get ());
+ cxml::add_text_child(node, "AnnotationText", annotation_text.get());
}
- node->add_child("IssueDate")->add_child_text (issue_date);
+ cxml::add_text_child(node, "IssueDate", issue_date);
- signer.as_xml (node->add_child ("Signer"));
- required_extensions.as_xml (node->add_child ("RequiredExtensions"));
+ signer.as_xml(cxml::add_child(node, "Signer"));
+ required_extensions.as_xml(cxml::add_child(node, "RequiredExtensions"));
- node->add_child ("NonCriticalExtensions");
+ cxml::add_child(node, "NonCriticalExtensions");
}
string message_id;
@@ -563,14 +564,14 @@ public:
shared_ptr<xmlpp::Document> as_xml () const
{
- shared_ptr<xmlpp::Document> document (new xmlpp::Document ());
- xmlpp::Element* root = document->create_root_node ("DCinemaSecurityMessage", "http://www.smpte-ra.org/schemas/430-3/2006/ETM");
+ auto document = make_shared<xmlpp::Document>();
+ auto root = document->create_root_node("DCinemaSecurityMessage", "http://www.smpte-ra.org/schemas/430-3/2006/ETM");
root->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "ds");
root->set_namespace_declaration ("http://www.w3.org/2001/04/xmlenc#", "enc");
- map<string, xmlpp::Attribute *> references;
- authenticated_public.as_xml (root->add_child ("AuthenticatedPublic"), references);
- authenticated_private.as_xml (root->add_child ("AuthenticatedPrivate"), references);
- signature.as_xml (root->add_child ("Signature", "ds"));
+ map<string, xmlpp::AttributeNode*> references;
+ authenticated_public.as_xml(cxml::add_child(root, "AuthenticatedPublic"), references);
+ authenticated_private.as_xml(cxml::add_child(root, "AuthenticatedPrivate"), references);
+ signature.as_xml(cxml::add_child(root, "Signature", string("ds")));
for (auto i: references) {
xmlAddID (0, document->cobj(), (const xmlChar *) i.first.c_str(), i.second->cobj());
diff --git a/src/exceptions.h b/src/exceptions.h
index 8d85f02a..3858b763 100644
--- a/src/exceptions.h
+++ b/src/exceptions.h
@@ -140,6 +140,33 @@ public:
};
+class MPEG2CodecError : public MiscError
+{
+public:
+ explicit MPEG2CodecError(std::string message)
+ : MiscError(message)
+ {}
+};
+
+
+class MPEG2DecompressionError : public ReadError
+{
+public:
+ explicit MPEG2DecompressionError(std::string message)
+ : ReadError(message)
+ {}
+};
+
+
+class MPEG2CompressionError : public MiscError
+{
+public:
+ explicit MPEG2CompressionError(std::string message)
+ : MiscError(message)
+ {}
+};
+
+
class BadContentKindError : public ReadError
{
public:
diff --git a/src/ffmpeg_image.cc b/src/ffmpeg_image.cc
new file mode 100644
index 00000000..deebe1b6
--- /dev/null
+++ b/src/ffmpeg_image.cc
@@ -0,0 +1,122 @@
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "ffmpeg_image.h"
+#include "types.h"
+extern "C" {
+#include <libavutil/pixfmt.h>
+}
+
+
+using namespace dcp;
+
+
+FFmpegImage::FFmpegImage(int64_t pts)
+{
+ auto const width = size().width;
+ auto const height = size().height;
+
+ _frame = av_frame_alloc();
+ if (!_frame) {
+ throw std::bad_alloc();
+ }
+
+ _frame->buf[0] = av_buffer_alloc(width * height);
+ _frame->buf[1] = av_buffer_alloc(width * height / 4);
+ _frame->buf[2] = av_buffer_alloc(width * height / 4);
+
+ _frame->linesize[0] = width;
+ _frame->linesize[1] = width / 2;
+ _frame->linesize[2] = width / 2;
+
+ for (auto i = 0; i < 3; ++i) {
+ _frame->data[i] = _frame->buf[i]->data;
+ }
+
+ _frame->width = width;
+ _frame->height = height;
+ _frame->format = AV_PIX_FMT_YUV420P;
+ _frame->pts = pts;
+}
+
+
+void
+FFmpegImage::set_pts(int64_t pts)
+{
+ _frame->pts = pts;
+}
+
+
+uint8_t*
+FFmpegImage::y()
+{
+ return _frame->data[0];
+}
+
+
+int
+FFmpegImage::y_stride() const
+{
+ return _frame->linesize[0];
+}
+
+
+uint8_t*
+FFmpegImage::u()
+{
+ return _frame->data[1];
+}
+
+
+int
+FFmpegImage::u_stride() const
+{
+ return _frame->linesize[1];
+}
+
+
+uint8_t*
+FFmpegImage::v()
+{
+ return _frame->data[2];
+}
+
+
+int
+FFmpegImage::v_stride() const
+{
+ return _frame->linesize[2];
+}
+
+
diff --git a/src/ffmpeg_image.h b/src/ffmpeg_image.h
new file mode 100644
index 00000000..44eb0db7
--- /dev/null
+++ b/src/ffmpeg_image.h
@@ -0,0 +1,107 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_FFMPEG_IMAGE_H
+#define LIBDCP_FFMPEG_IMAGE_H
+
+
+#include "types.h"
+#include "warnings.h"
+LIBDCP_DISABLE_WARNINGS
+extern "C" {
+#include <libavutil/frame.h>
+}
+LIBDCP_ENABLE_WARNINGS
+#include <algorithm>
+#include <vector>
+
+
+namespace dcp {
+
+
+class FFmpegImage
+{
+public:
+ explicit FFmpegImage(int64_t pts);
+
+ explicit FFmpegImage(AVFrame* frame)
+ : _frame(frame)
+ {}
+
+ FFmpegImage(FFmpegImage const& other) = delete;
+ FFmpegImage& operator=(FFmpegImage const& other) = delete;
+
+ FFmpegImage(FFmpegImage&& other) {
+ std::swap(_frame, other._frame);
+ }
+
+ FFmpegImage& operator=(FFmpegImage&& other) {
+ std::swap(_frame, other._frame);
+ return *this;
+ }
+
+ ~FFmpegImage()
+ {
+ av_frame_free(&_frame);
+ }
+
+ AVFrame const * frame() const {
+ return _frame;
+ }
+
+ uint8_t* y();
+ int y_stride() const;
+
+ uint8_t* u();
+ int u_stride() const;
+
+ uint8_t* v();
+ int v_stride() const;
+
+ Size size() const {
+ return { 1920, 1080 };
+ }
+
+ void set_pts(int64_t pts);
+
+private:
+ AVFrame* _frame = nullptr;
+};
+
+
+}
+
+
+#endif
+
diff --git a/src/frame_info.h b/src/frame_info.h
new file mode 100644
index 00000000..325350c4
--- /dev/null
+++ b/src/frame_info.h
@@ -0,0 +1,109 @@
+/*
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_FRAME_INFO_H
+#define LIBDCP_FRAME_INFO_H
+
+
+#include "warnings.h"
+LIBDCP_DISABLE_WARNINGS
+#include <asdcp/AS_DCP.h>
+LIBDCP_ENABLE_WARNINGS
+#include <stdint.h>
+#include <string>
+
+
+namespace dcp {
+
+
+/** @class FrameInfo
+ * @brief Information about a single frame (either a monoscopic frame or a left *or* right eye stereoscopic frame)
+ */
+struct FrameInfo
+{
+ FrameInfo () = default;
+
+ FrameInfo(uint64_t o, uint64_t s, std::string h)
+ : offset(o)
+ , size(s)
+ , hash(h)
+ {}
+
+ uint64_t offset = 0;
+ uint64_t size = 0;
+ std::string hash;
+};
+
+
+struct J2KFrameInfo : public FrameInfo
+{
+ J2KFrameInfo() = default;
+
+ J2KFrameInfo(uint64_t offset_, uint64_t size_, std::string hash_)
+ : FrameInfo(offset_, size_, hash_)
+ {}
+};
+
+
+struct MPEG2FrameInfo : public FrameInfo
+{
+ MPEG2FrameInfo() = default;
+
+ MPEG2FrameInfo(
+ uint64_t offset_,
+ uint64_t size_,
+ std::string hash_,
+ ASDCP::MPEG2::FrameType_t type_,
+ bool gop_start_,
+ bool closed_gop_,
+ uint8_t temporal_offset_
+ )
+ : FrameInfo(offset_, size_, hash_)
+ , type(type_)
+ , gop_start(gop_start_)
+ , closed_gop(closed_gop_)
+ , temporal_offset(temporal_offset_)
+ {}
+
+ ASDCP::MPEG2::FrameType_t type;
+ bool gop_start;
+ bool closed_gop;
+ uint8_t temporal_offset;
+};
+
+
+}
+
+
+#endif
diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc
index 32c3f66a..a4594207 100644
--- a/src/interop_subtitle_asset.cc
+++ b/src/interop_subtitle_asset.cc
@@ -115,13 +115,13 @@ InteropSubtitleAsset::xml_as_string () const
auto root = doc.create_root_node ("DCSubtitle");
root->set_attribute ("Version", "1.0");
- root->add_child("SubtitleID")->add_child_text (_id);
- root->add_child("MovieTitle")->add_child_text (_movie_title);
- root->add_child("ReelNumber")->add_child_text (raw_convert<string> (_reel_number));
- root->add_child("Language")->add_child_text (_language);
+ cxml::add_text_child(root, "SubtitleID", _id);
+ cxml::add_text_child(root, "MovieTitle", _movie_title);
+ cxml::add_text_child(root, "ReelNumber", raw_convert<string> (_reel_number));
+ cxml::add_text_child(root, "Language", _language);
for (auto i: _load_font_nodes) {
- auto load_font = root->add_child("LoadFont");
+ auto load_font = cxml::add_child(root, "LoadFont");
load_font->set_attribute ("Id", i->id);
load_font->set_attribute ("URI", i->uri);
}
diff --git a/src/interop_subtitle_asset.h b/src/interop_subtitle_asset.h
index f63740d5..ad1c68a7 100644
--- a/src/interop_subtitle_asset.h
+++ b/src/interop_subtitle_asset.h
@@ -37,8 +37,8 @@
*/
-#ifndef DCP_INTEROP_SUBTITLE_ASSET_H
-#define DCP_INTEROP_SUBTITLE_ASSET_H
+#ifndef LIBDCP_INTEROP_SUBTITLE_ASSET_H
+#define LIBDCP_INTEROP_SUBTITLE_ASSET_H
#include "subtitle_asset.h"
diff --git a/src/j2k_picture_asset.cc b/src/j2k_picture_asset.cc
new file mode 100644
index 00000000..98792253
--- /dev/null
+++ b/src/j2k_picture_asset.cc
@@ -0,0 +1,229 @@
+/*
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+/** @file src/picture_asset.cc
+ * @brief J2KPictureAsset class
+ */
+
+
+#include "compose.hpp"
+#include "dcp_assert.h"
+#include "equality_options.h"
+#include "exceptions.h"
+#include "j2k_transcode.h"
+#include "openjpeg_image.h"
+#include "j2k_picture_asset.h"
+#include "j2k_picture_asset_writer.h"
+#include "util.h"
+#include <asdcp/AS_DCP.h>
+#include <asdcp/KM_fileio.h>
+#include <libxml++/nodes/element.h>
+#include <boost/filesystem.hpp>
+#include <list>
+#include <stdexcept>
+
+
+using std::string;
+using std::list;
+using std::vector;
+using std::max;
+using std::pair;
+using std::make_pair;
+using std::shared_ptr;
+using namespace dcp;
+
+
+J2KPictureAsset::J2KPictureAsset(boost::filesystem::path file)
+ : PictureAsset(file)
+{
+
+}
+
+
+J2KPictureAsset::J2KPictureAsset(Fraction edit_rate, Standard standard)
+ : PictureAsset(edit_rate, standard)
+{
+
+}
+
+
+void
+J2KPictureAsset::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
+J2KPictureAsset::descriptor_equals (
+ ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, NoteHandler note
+ ) const
+{
+ if (
+ a.EditRate != b.EditRate ||
+ a.SampleRate != b.SampleRate ||
+ a.StoredWidth != b.StoredWidth ||
+ a.StoredHeight != b.StoredHeight ||
+ a.AspectRatio != b.AspectRatio ||
+ a.Rsize != b.Rsize ||
+ a.Xsize != b.Xsize ||
+ a.Ysize != b.Ysize ||
+ a.XOsize != b.XOsize ||
+ a.YOsize != b.YOsize ||
+ a.XTsize != b.XTsize ||
+ a.YTsize != b.YTsize ||
+ a.XTOsize != b.XTOsize ||
+ a.YTOsize != b.YTOsize ||
+ a.Csize != b.Csize
+// a.CodingStyleDefault != b.CodingStyleDefault ||
+// a.QuantizationDefault != b.QuantizationDefault
+ ) {
+
+ note (NoteType::ERROR, "video MXF picture descriptors differ");
+ return false;
+ }
+
+ if (a.ContainerDuration != b.ContainerDuration) {
+ note (NoteType::ERROR, "video container durations differ");
+ }
+
+// for (unsigned int j = 0; j < ASDCP::JP2K::MaxComponents; ++j) {
+// if (a.ImageComponents[j] != b.ImageComponents[j]) {
+// notes.pack_start ("video MXF picture descriptors differ");
+// }
+// }
+
+ return true;
+}
+
+
+bool
+J2KPictureAsset::frame_buffer_equals (
+ int frame, EqualityOptions const& opt, NoteHandler note,
+ uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B
+ ) const
+{
+ if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) {
+ note (NoteType::NOTE, "J2K identical");
+ /* Easy result; the J2K data is identical */
+ return true;
+ }
+
+ /* Decompress the images to bitmaps */
+ auto image_A = decompress_j2k (const_cast<uint8_t*>(data_A), size_A, 0);
+ auto image_B = decompress_j2k (const_cast<uint8_t*>(data_B), size_B, 0);
+
+ /* Compare them */
+
+ vector<int> abs_diffs (image_A->size().width * image_A->size().height * 3);
+ int d = 0;
+ int max_diff = 0;
+
+ for (int c = 0; c < 3; ++c) {
+
+ if (image_A->size() != image_B->size()) {
+ note (NoteType::ERROR, String::compose ("image sizes for frame %1 differ", frame));
+ return false;
+ }
+
+ int const pixels = image_A->size().width * image_A->size().height;
+ for (int j = 0; j < pixels; ++j) {
+ int const t = abs (image_A->data(c)[j] - image_B->data(c)[j]);
+ abs_diffs[d++] = t;
+ max_diff = max (max_diff, t);
+ }
+ }
+
+ uint64_t total = 0;
+ for (vector<int>::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) {
+ total += *j;
+ }
+
+ double const mean = double (total) / abs_diffs.size ();
+
+ uint64_t total_squared_deviation = 0;
+ for (auto j: abs_diffs) {
+ total_squared_deviation += pow (j - mean, 2);
+ }
+
+ auto const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size());
+
+ note (NoteType::NOTE, String::compose("mean difference %1 deviation %2", mean, std_dev));
+
+ if (mean > opt.max_mean_pixel_error) {
+ note (
+ NoteType::ERROR,
+ String::compose ("mean %1 out of range %2 in frame %3", mean, opt.max_mean_pixel_error, frame)
+ );
+
+ return false;
+ }
+
+ if (std_dev > opt.max_std_dev_pixel_error) {
+ note (
+ NoteType::ERROR,
+ String::compose ("standard deviation %1 out of range %2 in frame %3", std_dev, opt.max_std_dev_pixel_error, frame)
+ );
+
+ return false;
+ }
+
+ return true;
+}
+
+
+string
+J2KPictureAsset::static_pkl_type (Standard standard)
+{
+ switch (standard) {
+ case Standard::INTEROP:
+ return "application/x-smpte-mxf;asdcpKind=Picture";
+ case Standard::SMPTE:
+ return "application/mxf";
+ default:
+ DCP_ASSERT (false);
+ }
+}
+
+
+string
+J2KPictureAsset::pkl_type (Standard standard) const
+{
+ return static_pkl_type (standard);
+}
diff --git a/src/j2k_picture_asset.h b/src/j2k_picture_asset.h
new file mode 100644
index 00000000..972de43e
--- /dev/null
+++ b/src/j2k_picture_asset.h
@@ -0,0 +1,110 @@
+/*
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+/** @file src/j2k_picture_asset.h
+ * @brief J2KPictureAsset class
+ */
+
+
+#ifndef LIBDCP_J2K_PICTURE_ASSET_H
+#define LIBDCP_J2K_PICTURE_ASSET_H
+
+
+#include "behaviour.h"
+#include "mxf.h"
+#include "metadata.h"
+#include "picture_asset.h"
+#include "util.h"
+
+
+namespace ASDCP {
+ namespace JP2K {
+ struct PictureDescriptor;
+ }
+}
+
+
+namespace dcp {
+
+
+class MonoJ2KPictureFrame;
+class StereoJ2KPictureFrame;
+class J2KPictureAssetWriter;
+
+
+/** @class J2KPictureAsset
+ * @brief An asset made up of JPEG2000 data
+ */
+class J2KPictureAsset : public PictureAsset
+{
+public:
+ /** Load a J2KPictureAsset from a file */
+ explicit J2KPictureAsset (boost::filesystem::path file);
+
+ /** Create a new J2KPictureAsset with a given edit rate and standard */
+ J2KPictureAsset (Fraction edit_rate, Standard standard);
+
+ virtual std::shared_ptr<J2KPictureAssetWriter> start_write (
+ boost::filesystem::path file,
+ Behaviour behaviour
+ ) = 0;
+
+ static std::string static_pkl_type (Standard standard);
+
+protected:
+ friend class MonoJ2KPictureAssetWriter;
+ friend class StereoJ2KPictureAssetWriter;
+
+ bool frame_buffer_equals (
+ int frame, EqualityOptions const& opt, NoteHandler 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,
+ NoteHandler note
+ ) const;
+
+ void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &);
+
+private:
+ std::string pkl_type (Standard standard) const override;
+};
+
+
+}
+
+
+#endif
diff --git a/src/picture_asset_writer.cc b/src/j2k_picture_asset_writer.cc
index c30be1bc..75be51ba 100644
--- a/src/picture_asset_writer.cc
+++ b/src/j2k_picture_asset_writer.cc
@@ -33,13 +33,13 @@
/** @file src/picture_asset_writer.cc
- * @brief PictureAssetWriter and FrameInfo classes
+ * @brief J2KPictureAssetWriter and FrameInfo classes
*/
-#include "picture_asset_writer.h"
+#include "j2k_picture_asset_writer.h"
#include "exceptions.h"
-#include "picture_asset.h"
+#include "j2k_picture_asset.h"
#include <asdcp/KM_fileio.h>
#include <asdcp/AS_DCP.h>
#include <inttypes.h>
@@ -51,7 +51,7 @@ using std::shared_ptr;
using namespace dcp;
-PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, boost::filesystem::path file, bool overwrite)
+J2KPictureAssetWriter::J2KPictureAssetWriter (J2KPictureAsset* asset, boost::filesystem::path file, bool overwrite)
: AssetWriter (asset, file)
, _picture_asset (asset)
, _overwrite (overwrite)
@@ -60,8 +60,8 @@ PictureAssetWriter::PictureAssetWriter (PictureAsset* asset, boost::filesystem::
}
-FrameInfo
-PictureAssetWriter::write (Data const& data)
+J2KFrameInfo
+J2KPictureAssetWriter::write (Data const& data)
{
return write (data.data(), data.size());
}
diff --git a/src/picture_asset_writer.h b/src/j2k_picture_asset_writer.h
index 0caa8815..0077b3e0 100644
--- a/src/picture_asset_writer.h
+++ b/src/j2k_picture_asset_writer.h
@@ -32,16 +32,17 @@
*/
-/** @file src/picture_asset_writer.h
- * @brief PictureAssetWriter and FrameInfo classes.
+/** @file src/j2k_picture_asset_writer.h
+ * @brief J2KPictureAssetWriter and FrameInfo classes.
*/
-#ifndef LIBDCP_PICTURE_ASSET_WRITER_H
-#define LIBDCP_PICTURE_ASSET_WRITER_H
+#ifndef LIBDCP_J2K_PICTURE_ASSET_WRITER_H
+#define LIBDCP_J2K_PICTURE_ASSET_WRITER_H
#include "asset_writer.h"
+#include "frame_info.h"
#include "metadata.h"
#include <boost/utility.hpp>
#include <memory>
@@ -53,46 +54,27 @@ namespace dcp {
class Data;
-class PictureAsset;
+class J2KPictureAsset;
-/** @class FrameInfo
- * @brief Information about a single frame (either a monoscopic frame or a left *or* right eye stereoscopic frame)
- */
-struct FrameInfo
-{
- FrameInfo () {}
-
- FrameInfo (uint64_t o, uint64_t s, std::string h)
- : offset (o)
- , size (s)
- , hash (h)
- {}
-
- uint64_t offset = 0;
- uint64_t size = 0;
- std::string hash;
-};
-
-
-/** @class PictureAssetWriter
+/** @class J2KPictureAssetWriter
* @brief Parent class for classes which write picture assets.
*/
-class PictureAssetWriter : public AssetWriter
+class J2KPictureAssetWriter : public AssetWriter
{
public:
- virtual FrameInfo write (uint8_t const *, int) = 0;
- virtual void fake_write (int) = 0;
+ virtual J2KFrameInfo write(uint8_t const *, int) = 0;
+ virtual void fake_write(J2KFrameInfo const& info) = 0;
- FrameInfo write (Data const& data);
+ J2KFrameInfo write(Data const& data);
protected:
template <class P, class Q>
- friend void start (PictureAssetWriter *, std::shared_ptr<P>, Q *, uint8_t const *, int);
+ friend void start (J2KPictureAssetWriter *, std::shared_ptr<P>, Q *, uint8_t const *, int);
- PictureAssetWriter (PictureAsset *, boost::filesystem::path, bool);
+ J2KPictureAssetWriter (J2KPictureAsset *, boost::filesystem::path, bool);
- PictureAsset* _picture_asset = nullptr;
+ J2KPictureAsset* _picture_asset = nullptr;
bool _overwrite = false;
};
diff --git a/src/picture_asset_writer_common.cc b/src/j2k_picture_asset_writer_common.cc
index 82866aac..a86da194 100644
--- a/src/picture_asset_writer_common.cc
+++ b/src/j2k_picture_asset_writer_common.cc
@@ -32,8 +32,8 @@
*/
-/** @file src/picture_asset_writer_common.cc
- * @brief Common parts of PictureAssetWriter
+/** @file src/j2k_picture_asset_writer_common.cc
+ * @brief Common parts of J2KPictureAssetWriter
*/
@@ -46,9 +46,9 @@ using std::shared_ptr;
namespace dcp {
-struct ASDCPStateBase
+struct ASDCPJ2KStateBase
{
- ASDCPStateBase ()
+ ASDCPJ2KStateBase()
: frame_buffer (4 * Kumu::Megabyte)
{}
@@ -63,7 +63,7 @@ struct ASDCPStateBase
template <class P, class Q>
-void dcp::start (PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint8_t const * data, int size)
+void dcp::start (J2KPictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint8_t const * data, int size)
{
asset->set_file (writer->_file);
diff --git a/src/language_tag.h b/src/language_tag.h
index 6f46c16b..3232dda9 100644
--- a/src/language_tag.h
+++ b/src/language_tag.h
@@ -32,7 +32,7 @@
*/
-/** @file src/language_tag.cc
+/** @file src/language_tag.h
* @brief LanguageTag class
*/
diff --git a/src/locale_convert.h b/src/locale_convert.h
index 37510a96..1323e704 100644
--- a/src/locale_convert.h
+++ b/src/locale_convert.h
@@ -32,7 +32,7 @@
*/
-/** @file src/locale_convert.cc
+/** @file src/locale_convert.h
* @brief Methods to convert to/from string using the current locale
*/
diff --git a/src/mono_picture_asset.cc b/src/mono_j2k_picture_asset.cc
index a72fd7d4..f718525d 100644
--- a/src/mono_picture_asset.cc
+++ b/src/mono_j2k_picture_asset.cc
@@ -33,7 +33,7 @@
/** @file src/mono_picture_asset.cc
- * @brief MonoPictureAsset class
+ * @brief MonoJ2KPictureAsset class
*/
@@ -42,10 +42,10 @@
#include "equality_options.h"
#include "exceptions.h"
#include "filesystem.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_reader.h"
-#include "mono_picture_asset_writer.h"
-#include "mono_picture_frame.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_reader.h"
+#include "mono_j2k_picture_asset_writer.h"
+#include "mono_j2k_picture_frame.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_fileio.h>
@@ -63,10 +63,11 @@ using namespace boost::placeholders;
using namespace dcp;
-MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file)
- : PictureAsset (file)
+MonoJ2KPictureAsset::MonoJ2KPictureAsset (boost::filesystem::path file)
+ : J2KPictureAsset (file)
{
- ASDCP::JP2K::MXFReader reader;
+ Kumu::FileReaderFactory factory;
+ ASDCP::JP2K::MXFReader reader(factory);
auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
@@ -88,8 +89,8 @@ MonoPictureAsset::MonoPictureAsset (boost::filesystem::path file)
}
-MonoPictureAsset::MonoPictureAsset (Fraction edit_rate, Standard standard)
- : PictureAsset (edit_rate, standard)
+MonoJ2KPictureAsset::MonoJ2KPictureAsset (Fraction edit_rate, Standard standard)
+ : J2KPictureAsset (edit_rate, standard)
{
}
@@ -103,20 +104,21 @@ storing_note_handler (list<pair<NoteType, string>>& notes, NoteType t, string s)
bool
-MonoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& opt, NoteHandler note) const
+MonoJ2KPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& opt, NoteHandler note) const
{
- if (!dynamic_pointer_cast<const MonoPictureAsset>(other)) {
+ if (!dynamic_pointer_cast<const MonoJ2KPictureAsset>(other)) {
return false;
}
- ASDCP::JP2K::MXFReader reader_A;
+ Kumu::FileReaderFactory factory;
+ ASDCP::JP2K::MXFReader reader_A(factory);
DCP_ASSERT (_file);
auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*_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;
+ ASDCP::JP2K::MXFReader reader_B(factory);
DCP_ASSERT (other->file ());
r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str());
if (ASDCP_FAILURE (r)) {
@@ -136,7 +138,7 @@ MonoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& o
return false;
}
- auto other_picture = dynamic_pointer_cast<const MonoPictureAsset> (other);
+ auto other_picture = dynamic_pointer_cast<const MonoJ2KPictureAsset> (other);
DCP_ASSERT (other_picture);
bool result = true;
@@ -184,23 +186,23 @@ MonoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& o
}
-shared_ptr<PictureAssetWriter>
-MonoPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour)
+shared_ptr<J2KPictureAssetWriter>
+MonoJ2KPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour)
{
- /* Can't use make_shared here as the MonoPictureAssetWriter constructor is private */
- return shared_ptr<MonoPictureAssetWriter>(new MonoPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING));
+ /* Can't use make_shared here as the MonoJ2KPictureAssetWriter constructor is private */
+ return shared_ptr<MonoJ2KPictureAssetWriter>(new MonoJ2KPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING));
}
-shared_ptr<MonoPictureAssetReader>
-MonoPictureAsset::start_read () const
+shared_ptr<MonoJ2KPictureAssetReader>
+MonoJ2KPictureAsset::start_read () const
{
- /* Can't use make_shared here as the MonoPictureAssetReader constructor is private */
- return shared_ptr<MonoPictureAssetReader>(new MonoPictureAssetReader(this, key(), standard()));
+ /* Can't use make_shared here as the MonoJ2KPictureAssetReader constructor is private */
+ return shared_ptr<MonoJ2KPictureAssetReader>(new MonoJ2KPictureAssetReader(this, key(), standard()));
}
string
-MonoPictureAsset::cpl_node_name () const
+MonoJ2KPictureAsset::cpl_node_name () const
{
return "MainPicture";
}
diff --git a/src/mono_picture_asset.h b/src/mono_j2k_picture_asset.h
index 9658dcf6..d716b8ff 100644
--- a/src/mono_picture_asset.h
+++ b/src/mono_j2k_picture_asset.h
@@ -32,50 +32,50 @@
*/
-/** @file src/mono_picture_asset.cc
- * @brief MonoPictureAsset class
+/** @file src/mono_j2k_picture_asset.h
+ * @brief MonoJ2KPictureAsset class
*/
-#ifndef LIBDCP_MONO_PICTURE_ASSET_H
-#define LIBDCP_MONO_PICTURE_ASSET_H
+#ifndef LIBDCP_MONO_J2K_PICTURE_ASSET_H
+#define LIBDCP_MONO_J2K_PICTURE_ASSET_H
-#include "picture_asset.h"
-#include "mono_picture_asset_reader.h"
+#include "j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_reader.h"
namespace dcp {
-class MonoPictureAssetWriter;
+class MonoJ2KPictureAssetWriter;
-/** @class MonoPictureAsset
+/** @class MonoJ2KPictureAsset
* @brief A 2D (monoscopic) picture asset
*/
-class MonoPictureAsset : public PictureAsset
+class MonoJ2KPictureAsset : public J2KPictureAsset
{
public:
- /** Create a MonoPictureAsset by reading a file.
+ /** Create a MonoJ2KPictureAsset by reading a file.
* @param file Asset file to read.
*/
- explicit MonoPictureAsset (boost::filesystem::path file);
+ explicit MonoJ2KPictureAsset (boost::filesystem::path file);
- /** Create a MonoPictureAsset with a given edit rate.
+ /** Create a MonoJ2KPictureAsset with a given edit rate.
* @param edit_rate Edit rate (i.e. frame rate) in frames per second.
* @param standard DCP standard (INTEROP or SMPTE).
*/
- MonoPictureAsset(Fraction edit_rate, Standard standard);
+ MonoJ2KPictureAsset(Fraction edit_rate, Standard standard);
- /** Start a progressive write to a MonoPictureAsset.
+ /** Start a progressive write to a MonoJ2KPictureAsset.
* @path file File to write to.
* @path behaviour OVERWRITE_EXISTING to overwrite and potentially add to an existing file
* (after a write previously failed), MAKE_NEW to create a new file.
* If in doubt, use MAKE_NEW here.
*/
- std::shared_ptr<PictureAssetWriter> start_write(boost::filesystem::path file, Behaviour behaviour) override;
- std::shared_ptr<MonoPictureAssetReader> start_read () const;
+ std::shared_ptr<J2KPictureAssetWriter> start_write(boost::filesystem::path file, Behaviour behaviour) override;
+ std::shared_ptr<MonoJ2KPictureAssetReader> start_read () const;
bool equals (
std::shared_ptr<const Asset> other,
diff --git a/src/stereo_picture_asset_reader.h b/src/mono_j2k_picture_asset_reader.h
index 9cb05263..8376e939 100644
--- a/src/stereo_picture_asset_reader.h
+++ b/src/mono_j2k_picture_asset_reader.h
@@ -32,23 +32,23 @@
*/
-/** @file src/stereo_picture_asset_reader.h
- * @brief StereoPictureAssetReader typedef
+/** @file src/mono_j2k_picture_asset_reader.h
+ * @brief MonoJ2KPictureAssetReader typedef
*/
-#ifndef LIBDCP_STEREO_PICTURE_ASSET_READER_H
-#define LIBDCP_STEREO_PICTURE_ASSET_READER_H
+#ifndef LIBDCP_MONO_J2K_PICTURE_ASSET_READER_H
+#define LIBDCP_MONO_J2K_PICTURE_ASSET_READER_H
#include "asset_reader.h"
-#include "stereo_picture_frame.h"
+#include "mono_j2k_picture_frame.h"
namespace dcp {
-typedef AssetReader<ASDCP::JP2K::MXFSReader, StereoPictureFrame> StereoPictureAssetReader;
+typedef AssetReader<ASDCP::JP2K::MXFReader, MonoJ2KPictureFrame> MonoJ2KPictureAssetReader;
}
diff --git a/src/mono_picture_asset_writer.cc b/src/mono_j2k_picture_asset_writer.cc
index 7fd58114..1188701e 100644
--- a/src/mono_picture_asset_writer.cc
+++ b/src/mono_j2k_picture_asset_writer.cc
@@ -33,15 +33,15 @@
/** @file src/mono_picture_asset_writer.cc
- * @brief MonoPictureAssetWriter class
+ * @brief MonoJ2KPictureAssetWriter class
*/
#include "crypto_context.h"
#include "dcp_assert.h"
#include "exceptions.h"
-#include "mono_picture_asset_writer.h"
-#include "picture_asset.h"
+#include "mono_j2k_picture_asset_writer.h"
+#include "j2k_picture_asset.h"
#include "warnings.h"
LIBDCP_DISABLE_WARNINGS
#include <asdcp/AS_DCP.h>
@@ -49,7 +49,7 @@ LIBDCP_DISABLE_WARNINGS
LIBDCP_ENABLE_WARNINGS
-#include "picture_asset_writer_common.cc"
+#include "j2k_picture_asset_writer_common.cc"
using std::string;
@@ -57,7 +57,7 @@ using std::shared_ptr;
using namespace dcp;
-struct MonoPictureAssetWriter::ASDCPState : public ASDCPStateBase
+struct MonoJ2KPictureAssetWriter::ASDCPState : public ASDCPJ2KStateBase
{
ASDCP::JP2K::MXFWriter mxf_writer;
};
@@ -66,15 +66,15 @@ 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, boost::filesystem::path file, bool overwrite)
- : PictureAssetWriter (asset, file, overwrite)
- , _state (new MonoPictureAssetWriter::ASDCPState)
+MonoJ2KPictureAssetWriter::MonoJ2KPictureAssetWriter (J2KPictureAsset* asset, boost::filesystem::path file, bool overwrite)
+ : J2KPictureAssetWriter (asset, file, overwrite)
+ , _state (new MonoJ2KPictureAssetWriter::ASDCPState)
{
}
-MonoPictureAssetWriter::~MonoPictureAssetWriter()
+MonoJ2KPictureAssetWriter::~MonoJ2KPictureAssetWriter()
{
try {
/* Last-resort finalization to close the file, at least */
@@ -86,15 +86,15 @@ MonoPictureAssetWriter::~MonoPictureAssetWriter()
void
-MonoPictureAssetWriter::start (uint8_t const * data, int size)
+MonoJ2KPictureAssetWriter::start (uint8_t const * data, int size)
{
dcp::start (this, _state, _picture_asset, data, size);
_picture_asset->set_frame_rate (_picture_asset->edit_rate());
}
-FrameInfo
-MonoPictureAssetWriter::write (uint8_t const * data, int size)
+J2KFrameInfo
+MonoJ2KPictureAssetWriter::write (uint8_t const * data, int size)
{
DCP_ASSERT (!_finalized);
@@ -117,17 +117,17 @@ MonoPictureAssetWriter::write (uint8_t const * data, int size)
}
++_frames_written;
- return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
+ return J2KFrameInfo(before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
void
-MonoPictureAssetWriter::fake_write (int size)
+MonoJ2KPictureAssetWriter::fake_write(J2KFrameInfo const& info)
{
DCP_ASSERT (_started);
DCP_ASSERT (!_finalized);
- auto r = _state->mxf_writer.FakeWriteFrame (size);
+ auto r = _state->mxf_writer.FakeWriteFrame(info.size);
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("error in writing video MXF", _file.string(), r));
}
@@ -137,7 +137,7 @@ MonoPictureAssetWriter::fake_write (int size)
bool
-MonoPictureAssetWriter::finalize ()
+MonoJ2KPictureAssetWriter::finalize ()
{
if (_started) {
auto r = _state->mxf_writer.Finalize();
@@ -147,5 +147,5 @@ MonoPictureAssetWriter::finalize ()
}
_picture_asset->_intrinsic_duration = _frames_written;
- return PictureAssetWriter::finalize ();
+ return J2KPictureAssetWriter::finalize ();
}
diff --git a/src/mono_picture_asset_writer.h b/src/mono_j2k_picture_asset_writer.h
index 551d8c80..b3f57191 100644
--- a/src/mono_picture_asset_writer.h
+++ b/src/mono_j2k_picture_asset_writer.h
@@ -32,16 +32,16 @@
*/
-/** @file src/mono_picture_asset_writer.h
- * @brief MonoPictureAssetWriter class
+/** @file src/mono_j2k_picture_asset_writer.h
+ * @brief MonoJ2KPictureAssetWriter class
*/
-#ifndef LIBDCP_MONO_PICTURE_ASSET_WRITER_H
-#define LIBDCP_MONO_PICTURE_ASSET_WRITER_H
+#ifndef LIBDCP_MONO_J2K_PICTURE_ASSET_WRITER_H
+#define LIBDCP_MONO_J2K_PICTURE_ASSET_WRITER_H
-#include "picture_asset_writer.h"
+#include "j2k_picture_asset_writer.h"
#include <memory>
#include <boost/utility.hpp>
#include <stdint.h>
@@ -51,29 +51,29 @@
namespace dcp {
-/** @class MonoPictureAssetWriter
- * @brief A helper class for writing to MonoPictureAssets
+/** @class MonoJ2KPictureAssetWriter
+ * @brief A helper class for writing to MonoJ2KPictureAssets
*
- * Objects of this class can only be created with MonoPictureAsset::start_write().
+ * Objects of this class can only be created with MonoJ2KPictureAsset::start_write().
*
- * Frames can be written to the MonoPictureAsset by calling write() with a JPEG2000 image
+ * Frames can be written to the MonoJ2KPictureAsset by calling write() with a JPEG2000 image
* (a verbatim .j2c file). finalize() should be called after the last frame has been written,
* but if it is not, it will be called by the destructor (though in that case any error
* during finalization will be ignored).
*/
-class MonoPictureAssetWriter : public PictureAssetWriter
+class MonoJ2KPictureAssetWriter : public J2KPictureAssetWriter
{
public:
- ~MonoPictureAssetWriter();
+ ~MonoJ2KPictureAssetWriter();
- FrameInfo write (uint8_t const *, int) override;
- void fake_write (int size) override;
+ J2KFrameInfo write(uint8_t const *, int) override;
+ void fake_write(J2KFrameInfo const& info) override;
bool finalize () override;
private:
- friend class MonoPictureAsset;
+ friend class MonoJ2KPictureAsset;
- MonoPictureAssetWriter (PictureAsset* a, boost::filesystem::path file, bool);
+ MonoJ2KPictureAssetWriter (J2KPictureAsset* a, boost::filesystem::path file, bool);
void start (uint8_t const *, int);
diff --git a/src/mono_picture_frame.cc b/src/mono_j2k_picture_frame.cc
index 2abd57e4..69ba9a59 100644
--- a/src/mono_picture_frame.cc
+++ b/src/mono_j2k_picture_frame.cc
@@ -33,7 +33,7 @@
/** @file src/mono_picture_frame.cc
- * @brief MonoPictureFrame class
+ * @brief MonoJ2KPictureFrame class
*/
@@ -44,7 +44,7 @@
#include "file.h"
#include "filesystem.h"
#include "j2k_transcode.h"
-#include "mono_picture_frame.h"
+#include "mono_j2k_picture_frame.h"
#include "rgb_xyz.h"
#include "util.h"
#include <asdcp/KM_fileio.h>
@@ -58,7 +58,7 @@ using boost::optional;
using namespace dcp;
-MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path)
+MonoJ2KPictureFrame::MonoJ2KPictureFrame (boost::filesystem::path path)
{
auto const size = filesystem::file_size(path);
_buffer.reset(new ASDCP::JP2K::FrameBuffer(size));
@@ -81,7 +81,7 @@ MonoPictureFrame::MonoPictureFrame (boost::filesystem::path path)
* @param c Context for decryption, or 0.
* @param check_hmac true to check the HMAC and give an error if it is not as expected.
*/
-MonoPictureFrame::MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, shared_ptr<DecryptionContext> c, bool check_hmac)
+MonoJ2KPictureFrame::MonoJ2KPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, shared_ptr<DecryptionContext> c, bool check_hmac)
{
/* XXX: unfortunate guesswork on this buffer size */
_buffer = make_shared<ASDCP::JP2K::FrameBuffer>(4 * Kumu::Megabyte);
@@ -94,7 +94,7 @@ MonoPictureFrame::MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, share
}
-MonoPictureFrame::MonoPictureFrame (uint8_t const * data, int size)
+MonoJ2KPictureFrame::MonoJ2KPictureFrame (uint8_t const * data, int size)
{
_buffer = make_shared<ASDCP::JP2K::FrameBuffer>(size);
_buffer->Size (size);
@@ -103,28 +103,28 @@ MonoPictureFrame::MonoPictureFrame (uint8_t const * data, int size)
uint8_t const *
-MonoPictureFrame::data () const
+MonoJ2KPictureFrame::data () const
{
return _buffer->RoData ();
}
uint8_t *
-MonoPictureFrame::data ()
+MonoJ2KPictureFrame::data ()
{
return _buffer->Data ();
}
int
-MonoPictureFrame::size () const
+MonoJ2KPictureFrame::size () const
{
return _buffer->Size ();
}
shared_ptr<OpenJPEGImage>
-MonoPictureFrame::xyz_image (int reduce) const
+MonoJ2KPictureFrame::xyz_image (int reduce) const
{
return decompress_j2k (const_cast<uint8_t*>(_buffer->RoData()), _buffer->Size(), reduce);
}
diff --git a/src/mono_picture_frame.h b/src/mono_j2k_picture_frame.h
index 43575864..f08e7343 100644
--- a/src/mono_picture_frame.h
+++ b/src/mono_j2k_picture_frame.h
@@ -32,13 +32,13 @@
*/
-/** @file src/mono_picture_frame.h
- * @brief MonoPictureFrame class
+/** @file src/mono_j2k_picture_frame.h
+ * @brief MonoJ2KPictureFrame class
*/
-#ifndef LIBDCP_MONO_PICTURE_FRAME_H
-#define LIBDCP_MONO_PICTURE_FRAME_H
+#ifndef LIBDCP_MONO_J2K_PICTURE_FRAME_H
+#define LIBDCP_MONO_J2K_PICTURE_FRAME_H
#include "asset_reader.h"
@@ -64,20 +64,20 @@ namespace dcp {
class OpenJPEGImage;
-/** @class MonoPictureFrame
+/** @class MonoJ2KPictureFrame
* @brief A single frame of a 2D (monoscopic) picture asset
*/
-class MonoPictureFrame : public Data
+class MonoJ2KPictureFrame : public Data
{
public:
/** Make a picture frame from a JPEG2000 file.
* @param path Path to JPEG2000 file.
*/
- explicit MonoPictureFrame (boost::filesystem::path path);
- MonoPictureFrame (uint8_t const * data, int size);
+ explicit MonoJ2KPictureFrame (boost::filesystem::path path);
+ MonoJ2KPictureFrame (uint8_t const * data, int size);
- MonoPictureFrame (MonoPictureFrame const&) = delete;
- MonoPictureFrame& operator= (MonoPictureFrame const&) = delete;
+ MonoJ2KPictureFrame (MonoJ2KPictureFrame const&) = delete;
+ MonoJ2KPictureFrame& operator= (MonoJ2KPictureFrame const&) = delete;
/** @param reduce a factor by which to reduce the resolution
* of the image, expressed as a power of two (pass 0 for no
@@ -95,12 +95,12 @@ public:
int size () const override;
private:
- /* XXX: this is a bit of a shame, but I tried friend MonoPictureAssetReader and it's
+ /* XXX: this is a bit of a shame, but I tried friend MonoJ2KPictureAssetReader and it's
rejected by some (seemingly older) GCCs.
*/
- friend class AssetReader<ASDCP::JP2K::MXFReader, MonoPictureFrame>;
+ friend class AssetReader<ASDCP::JP2K::MXFReader, MonoJ2KPictureFrame>;
- MonoPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
+ MonoJ2KPictureFrame (ASDCP::JP2K::MXFReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
std::shared_ptr<ASDCP::JP2K::FrameBuffer> _buffer;
};
diff --git a/src/mono_mpeg2_picture_asset.cc b/src/mono_mpeg2_picture_asset.cc
new file mode 100644
index 00000000..380da0fe
--- /dev/null
+++ b/src/mono_mpeg2_picture_asset.cc
@@ -0,0 +1,86 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "filesystem.h"
+#include "mono_mpeg2_picture_asset.h"
+#include "mono_mpeg2_picture_asset_reader.h"
+#include "mono_mpeg2_picture_asset_writer.h"
+#include <asdcp/AS_DCP.h>
+
+
+using std::shared_ptr;
+using namespace dcp;
+
+
+MonoMPEG2PictureAsset::MonoMPEG2PictureAsset(boost::filesystem::path file)
+ : MPEG2PictureAsset(file)
+{
+ Kumu::FileReaderFactory factory;
+ ASDCP::MPEG2::MXFReader reader(factory);
+ auto const result = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
+ if (ASDCP_FAILURE(result)) {
+ boost::throw_exception(MXFFileError("could not open MXF file for reading", file.string(), result));
+ }
+
+ ASDCP::MPEG2::VideoDescriptor desc;
+ if (ASDCP_FAILURE(reader.FillVideoDescriptor(desc))) {
+ boost::throw_exception(ReadError("could not read video MXF information"));
+ }
+
+ read_video_descriptor(desc);
+
+ ASDCP::WriterInfo info;
+ if (ASDCP_FAILURE(reader.FillWriterInfo(info))) {
+ boost::throw_exception(ReadError("could not read video MXF information"));
+ }
+
+ _id = read_writer_info(info);
+}
+
+
+shared_ptr<MonoMPEG2PictureAssetReader>
+MonoMPEG2PictureAsset::start_read () const
+{
+ /* Can't use make_shared here as the MonoMPEG2PictureAssetReader constructor is private */
+ return shared_ptr<MonoMPEG2PictureAssetReader>(new MonoMPEG2PictureAssetReader(this, key(), standard()));
+
+}
+
+
+shared_ptr<MPEG2PictureAssetWriter>
+MonoMPEG2PictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour)
+{
+ /* Can't use make_shared here as the MonoJ2KPictureAssetWriter constructor is private */
+ return shared_ptr<MonoMPEG2PictureAssetWriter>(new MonoMPEG2PictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING));
+}
diff --git a/src/mono_mpeg2_picture_asset.h b/src/mono_mpeg2_picture_asset.h
new file mode 100644
index 00000000..8ef3653e
--- /dev/null
+++ b/src/mono_mpeg2_picture_asset.h
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MONO_MPEG2_PICTURE_ASSET_H
+#define LIBDCP_MONO_MPEG2_PICTURE_ASSET_H
+
+
+/** @file src/mono_mpeg2_picture_asset.h
+ * @brief MonoMPEG2PictureAsset class
+ */
+
+
+#include "behaviour.h"
+#include "mpeg2_picture_asset.h"
+#include "mono_mpeg2_picture_asset_reader.h"
+
+
+namespace dcp {
+
+
+class MonoMPEG2PictureAssetWriter;
+
+
+class MonoMPEG2PictureAsset : public MPEG2PictureAsset
+{
+public:
+ MonoMPEG2PictureAsset(Fraction edit_rate)
+ : MPEG2PictureAsset(edit_rate)
+ {}
+
+ explicit MonoMPEG2PictureAsset(boost::filesystem::path file);
+
+ std::shared_ptr<MPEG2PictureAssetWriter> start_write(boost::filesystem::path file, Behaviour behaviour) override;
+ std::shared_ptr<MonoMPEG2PictureAssetReader> start_read() const;
+};
+
+
+
+}
+
+
+#endif
diff --git a/src/mono_mpeg2_picture_asset_reader.h b/src/mono_mpeg2_picture_asset_reader.h
new file mode 100644
index 00000000..75155f40
--- /dev/null
+++ b/src/mono_mpeg2_picture_asset_reader.h
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+/** @file src/mono_mpeg2_picture_asset_reader.h
+ * @brief MonoJ2KPictureAssetReader typedef
+ */
+
+
+#ifndef LIBDCP_MONO_MPEG2_PICTURE_ASSET_READER_H
+#define LIBDCP_MONO_MPEG2_PICTURE_ASSET_READER_H
+
+
+#include "asset_reader.h"
+#include "mono_mpeg2_picture_frame.h"
+
+
+namespace dcp {
+
+
+typedef AssetReader<ASDCP::MPEG2::MXFReader, MonoMPEG2PictureFrame> MonoMPEG2PictureAssetReader;
+
+
+}
+
+
+#endif
+
diff --git a/src/mono_mpeg2_picture_asset_writer.cc b/src/mono_mpeg2_picture_asset_writer.cc
new file mode 100644
index 00000000..f8101c54
--- /dev/null
+++ b/src/mono_mpeg2_picture_asset_writer.cc
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mono_mpeg2_picture_asset_writer.h"
+#include "mpeg2_picture_asset.h"
+#include "mpeg2_picture_asset_writer.h"
+
+
+using std::string;
+using namespace dcp;
+
+
+struct MonoMPEG2PictureAssetWriter::ASDCPState : public ASDCPMPEG2StateBase
+{
+ ASDCP::MPEG2::MXFWriter mxf_writer;
+};
+
+
+
+
+MonoMPEG2PictureAssetWriter::MonoMPEG2PictureAssetWriter(MPEG2PictureAsset* asset, boost::filesystem::path file, bool overwrite)
+ : MPEG2PictureAssetWriter(asset, file, overwrite)
+ , _state(new MonoMPEG2PictureAssetWriter::ASDCPState)
+{
+ asset->set_file(file);
+}
+
+
+MonoMPEG2PictureAssetWriter::~MonoMPEG2PictureAssetWriter()
+{
+ try {
+ /* Last-resort finalization to close the file, at least */
+ if (!_finalized) {
+ _state->mxf_writer.Finalize();
+ }
+ } catch (...) {}
+}
+
+
+void
+MonoMPEG2PictureAssetWriter::start(uint8_t const * data, int size)
+{
+ dcp::start(this, _state, _picture_asset, data, size);
+ _picture_asset->set_frame_rate (_picture_asset->edit_rate());
+}
+
+
+MPEG2FrameInfo
+MonoMPEG2PictureAssetWriter::write(uint8_t const * data, int size)
+{
+ DCP_ASSERT(!_finalized);
+
+ if (!_started) {
+ start(data, size);
+ }
+
+ ASDCP::MPEG2::FrameBuffer buffer;
+ buffer.SetData(const_cast<uint8_t*>(data), size);
+ buffer.Size(size);
+ buffer.PlaintextOffset(0);
+
+ auto const before_offset = _state->mxf_writer.Tell();
+
+ string hash;
+ auto const r = _state->mxf_writer.WriteFrame(buffer, _crypto_context->context(), _crypto_context->hmac(), &hash);
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception(MXFFileError("error in writing video MXF", _file.string(), r));
+ }
+
+ ++_frames_written;
+ return MPEG2FrameInfo(
+ before_offset,
+ _state->mxf_writer.Tell() - before_offset,
+ hash,
+ buffer.FrameType(),
+ buffer.GOPStart(),
+ buffer.ClosedGOP(),
+ buffer.TemporalOffset()
+ );
+}
+
+
+void
+MonoMPEG2PictureAssetWriter::fake_write(MPEG2FrameInfo const& info)
+{
+ DCP_ASSERT(_started);
+ DCP_ASSERT(!_finalized);
+
+ DCP_ASSERT(false);
+
+ auto r = _state->mxf_writer.FakeWriteFrame(info.size, info.type, info.gop_start, info.closed_gop, info.temporal_offset);
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception(MXFFileError("error in writing video MXF", _file.string(), r));
+ }
+
+ ++_frames_written;
+}
+
+
+bool
+MonoMPEG2PictureAssetWriter::finalize()
+{
+ if (_started) {
+ auto r = _state->mxf_writer.Finalize();
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception(MXFFileError("error in finalizing video MXF", _file.string(), r));
+ }
+ }
+
+ _picture_asset->_intrinsic_duration = _frames_written;
+ return MPEG2PictureAssetWriter::finalize();
+}
+
diff --git a/src/mono_mpeg2_picture_asset_writer.h b/src/mono_mpeg2_picture_asset_writer.h
new file mode 100644
index 00000000..bf7a6cc9
--- /dev/null
+++ b/src/mono_mpeg2_picture_asset_writer.h
@@ -0,0 +1,68 @@
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mpeg2_picture_asset_writer.h"
+
+
+#include "mpeg2_picture_asset_writer_common.cc"
+
+
+namespace dcp {
+
+
+class MonoMPEG2PictureAsset;
+
+
+class MonoMPEG2PictureAssetWriter : public MPEG2PictureAssetWriter
+{
+public:
+ ~MonoMPEG2PictureAssetWriter();
+
+ MPEG2FrameInfo write(uint8_t const *, int) override;
+ void fake_write(MPEG2FrameInfo const& info) override;
+ bool finalize() override;
+
+private:
+ friend class MonoMPEG2PictureAsset;
+
+ MonoMPEG2PictureAssetWriter(MPEG2PictureAsset* asset, boost::filesystem::path file, bool overwrite);
+
+ void start(uint8_t const *, int);
+
+ struct ASDCPState;
+ std::shared_ptr<ASDCPState> _state;
+};
+
+
+}
diff --git a/src/mono_mpeg2_picture_frame.cc b/src/mono_mpeg2_picture_frame.cc
new file mode 100644
index 00000000..3c79a94c
--- /dev/null
+++ b/src/mono_mpeg2_picture_frame.cc
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "compose.hpp"
+#include "mono_mpeg2_picture_frame.h"
+
+
+using std::make_shared;
+using std::shared_ptr;
+using namespace dcp;
+
+
+
+MonoMPEG2PictureFrame::MonoMPEG2PictureFrame(uint8_t const* data, int size)
+{
+ _buffer = make_shared<ASDCP::MPEG2::FrameBuffer>(size);
+ memcpy(_buffer->Data(), data, size);
+ _buffer->Size(size);
+}
+
+
+/** Make a picture frame from a 2D (monoscopic) asset.
+ * @param reader Reader for the asset's MXF file.
+ * @param n Frame within the asset, not taking EntryPoint into account.
+ * @param c Context for decryption, or 0.
+ * @param check_hmac true to check the HMAC and give an error if it is not as expected.
+ */
+MonoMPEG2PictureFrame::MonoMPEG2PictureFrame(ASDCP::MPEG2::MXFReader* reader, int n, shared_ptr<DecryptionContext> context, bool check_hmac)
+{
+ /* XXX: unfortunate guesswork on this buffer size */
+ _buffer = make_shared<ASDCP::MPEG2::FrameBuffer>(4 * Kumu::Megabyte);
+
+ auto const r = reader->ReadFrame(n, *_buffer, context->context(), check_hmac ? context->hmac() : nullptr);
+
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception(ReadError(String::compose("could not read video frame %1 (%2)", n, static_cast<int>(r))));
+ }
+}
+
+
+uint8_t const *
+MonoMPEG2PictureFrame::data() const
+{
+ return _buffer->RoData();
+}
+
+
+uint8_t *
+MonoMPEG2PictureFrame::data()
+{
+ return _buffer->Data();
+}
+
+
+int
+MonoMPEG2PictureFrame::size() const
+{
+ return _buffer->Size();
+}
+
diff --git a/src/mono_mpeg2_picture_frame.h b/src/mono_mpeg2_picture_frame.h
new file mode 100644
index 00000000..6a7669f7
--- /dev/null
+++ b/src/mono_mpeg2_picture_frame.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MONO_MPEG2_PICTURE_FRAME_H
+#define LIBDCP_MONO_MPEG2_PICTURE_FRAME_H
+
+
+#include "asset_reader.h"
+#include "data.h"
+
+
+namespace dcp {
+
+
+class MonoMPEG2PictureFrame : public Data
+{
+public:
+ MonoMPEG2PictureFrame(uint8_t const * data, int size);
+
+ MonoMPEG2PictureFrame(MonoMPEG2PictureFrame const&) = delete;
+ MonoMPEG2PictureFrame& operator=(MonoMPEG2PictureFrame const&) = delete;
+
+ /* XXX: couldn't we just return the frame buffer */
+
+ /** @return Pointer to MPEG2 data */
+ uint8_t const * data() const override;
+
+ /** @return Pointer to MPEG2 data */
+ uint8_t* data () override;
+
+ /** @return Size of MPEG2 data in bytes */
+ int size() const override;
+
+private:
+ /* XXX: this is a bit of a shame, but I tried friend MonoMPEG2PictureAssetReader and it's
+ rejected by some (seemingly older) GCCs.
+ */
+ friend class AssetReader<ASDCP::MPEG2::MXFReader, MonoMPEG2PictureFrame>;
+
+ MonoMPEG2PictureFrame(ASDCP::MPEG2::MXFReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
+
+ /* XXX why is this a shared_ptr? */
+ std::shared_ptr<ASDCP::MPEG2::FrameBuffer> _buffer;
+};
+
+
+}
+
+
+#endif
diff --git a/src/mpeg2_picture_asset.cc b/src/mpeg2_picture_asset.cc
new file mode 100644
index 00000000..6cd0b428
--- /dev/null
+++ b/src/mpeg2_picture_asset.cc
@@ -0,0 +1,74 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mpeg2_picture_asset.h"
+
+
+using std::string;
+using namespace dcp;
+
+
+MPEG2PictureAsset::MPEG2PictureAsset(boost::filesystem::path file)
+ : PictureAsset(file)
+{
+
+}
+
+
+void
+MPEG2PictureAsset::read_video_descriptor(ASDCP::MPEG2::VideoDescriptor const& descriptor)
+{
+ _size.width = descriptor.StoredWidth;
+ _size.height = descriptor.StoredHeight;
+ _edit_rate = Fraction(descriptor.EditRate.Numerator, descriptor.EditRate.Denominator);
+ _intrinsic_duration = descriptor.ContainerDuration;
+ _frame_rate = Fraction(descriptor.SampleRate.Numerator, descriptor.SampleRate.Denominator);
+ _screen_aspect_ratio = Fraction(descriptor.AspectRatio.Numerator, descriptor.AspectRatio.Denominator);
+}
+
+
+string
+MPEG2PictureAsset::pkl_type (Standard standard) const
+{
+ DCP_ASSERT(standard == Standard::INTEROP);
+ return "application/x-smpte-mxf;asdcpKind=Picture";
+}
+
+
+string
+MPEG2PictureAsset::static_pkl_type(Standard standard)
+{
+ DCP_ASSERT(standard == Standard::INTEROP);
+ return "application/x-smpte-mxf;asdcpKind=Picture";
+}
diff --git a/src/mpeg2_picture_asset.h b/src/mpeg2_picture_asset.h
new file mode 100644
index 00000000..38b8e0a0
--- /dev/null
+++ b/src/mpeg2_picture_asset.h
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MPEG2_PICTURE_ASSET_H
+#define LIBDCP_MPEG2_PICTURE_ASSET_H
+
+
+/** @file src/mpeg2_picture_asset.h
+ * @brief MPEG2PictureAsset class
+ */
+
+
+#include "behaviour.h"
+#include "mpeg2_picture_asset_writer.h"
+#include "picture_asset.h"
+#include <boost/filesystem/path.hpp>
+
+
+namespace ASDCP {
+ namespace MPEG2 {
+ struct VideoDescriptor;
+ }
+}
+
+
+namespace dcp {
+
+
+class MPEG2PictureAsset : public PictureAsset
+{
+public:
+ MPEG2PictureAsset(Fraction edit_rate)
+ : PictureAsset(edit_rate, Standard::INTEROP)
+ {}
+
+ explicit MPEG2PictureAsset(boost::filesystem::path file);
+
+ virtual std::shared_ptr<MPEG2PictureAssetWriter> start_write(
+ boost::filesystem::path file,
+ Behaviour behaviour
+ ) = 0;
+
+ static std::string static_pkl_type(Standard standard);
+
+protected:
+ friend class MonoMPEG2PictureAssetWriter;
+
+ void read_video_descriptor(ASDCP::MPEG2::VideoDescriptor const& descriptor);
+
+private:
+ std::string pkl_type(Standard standard) const override;
+};
+
+
+}
+
+
+#endif
+
diff --git a/src/mpeg2_picture_asset_writer.cc b/src/mpeg2_picture_asset_writer.cc
new file mode 100644
index 00000000..f5ead775
--- /dev/null
+++ b/src/mpeg2_picture_asset_writer.cc
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mpeg2_picture_asset.h"
+#include "mpeg2_picture_asset_writer.h"
+
+
+using namespace dcp;
+
+
+MPEG2PictureAssetWriter::MPEG2PictureAssetWriter(MPEG2PictureAsset* asset, boost::filesystem::path file, bool overwrite)
+ : AssetWriter(asset, file)
+ , _picture_asset(asset)
+ , _overwrite(overwrite)
+{
+ asset->set_file(file);
+}
diff --git a/src/mpeg2_picture_asset_writer.h b/src/mpeg2_picture_asset_writer.h
new file mode 100644
index 00000000..a370ef9b
--- /dev/null
+++ b/src/mpeg2_picture_asset_writer.h
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MPEG2_PICTURE_ASSET_WRITER_H
+#define LIBDCP_MPEG2_PICTURE_ASSET_WRITER_H
+
+
+#include "asset_writer.h"
+#include "frame_info.h"
+
+
+namespace dcp {
+
+
+class Data;
+class MPEG2PictureAsset;
+
+
+class MPEG2PictureAssetWriter : public AssetWriter
+{
+public:
+ virtual MPEG2FrameInfo write(uint8_t const* data, int size) = 0;
+ virtual void fake_write(MPEG2FrameInfo const& info) = 0;
+
+ MPEG2FrameInfo write(Data const& data);
+
+protected:
+ template <class P, class Q>
+ friend void start(MPEG2PictureAssetWriter *, std::shared_ptr<P>, Q *, uint8_t const *, int);
+
+ MPEG2PictureAssetWriter(MPEG2PictureAsset* asset, boost::filesystem::path file, bool overwrite);
+
+ MPEG2PictureAsset* _picture_asset = nullptr;
+ bool _overwrite = false;
+};
+
+
+}
+
+
+#endif
+
diff --git a/src/mpeg2_picture_asset_writer_common.cc b/src/mpeg2_picture_asset_writer_common.cc
new file mode 100644
index 00000000..d46057f7
--- /dev/null
+++ b/src/mpeg2_picture_asset_writer_common.cc
@@ -0,0 +1,93 @@
+/*
+ Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+/** @file src/mpeg2_picture_asset_writer_common.cc
+ * @brief Common parts of MPEG2PictureAssetWriter
+ */
+
+
+#include "filesystem.h"
+
+
+using std::shared_ptr;
+
+
+namespace dcp {
+
+
+class MPEG2PictureAssetWriter;
+
+
+struct ASDCPMPEG2StateBase
+{
+ ASDCP::MPEG2::Parser mpeg2_parser;
+ ASDCP::WriterInfo writer_info;
+ ASDCP::MPEG2::VideoDescriptor video_descriptor;
+};
+
+
+}
+
+
+template <class P, class Q>
+void dcp::start(MPEG2PictureAssetWriter* writer, shared_ptr<P> state, Q* asset, uint8_t const * data, int size)
+{
+ asset->set_file (writer->_file);
+
+ if (ASDCP_FAILURE(state->mpeg2_parser.OpenRead(data, size))) {
+ boost::throw_exception(MiscError("could not parse MPEG2 frame"));
+ }
+
+ state->mpeg2_parser.FillVideoDescriptor(state->video_descriptor);
+ state->video_descriptor.EditRate = ASDCP::Rational(asset->edit_rate().numerator, asset->edit_rate().denominator);
+
+ asset->set_size(Size(state->video_descriptor.StoredWidth, state->video_descriptor.StoredHeight));
+ asset->set_screen_aspect_ratio(Fraction(state->video_descriptor.AspectRatio.Numerator, state->video_descriptor.AspectRatio.Denominator));
+
+ asset->fill_writer_info(&state->writer_info, asset->id());
+
+ auto r = state->mxf_writer.OpenWrite(
+ dcp::filesystem::fix_long_path(*asset->file()).string().c_str(),
+ state->writer_info,
+ state->video_descriptor,
+ 16384,
+ writer->_overwrite
+ );
+
+ if (ASDCP_FAILURE(r)) {
+ boost::throw_exception(MXFFileError("could not open MXF file for writing", asset->file()->string(), r));
+ }
+
+ writer->_started = true;
+}
diff --git a/src/mpeg2_transcode.cc b/src/mpeg2_transcode.cc
new file mode 100644
index 00000000..0ac2c1af
--- /dev/null
+++ b/src/mpeg2_transcode.cc
@@ -0,0 +1,216 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "compose.hpp"
+#include "exceptions.h"
+#include "mono_mpeg2_picture_frame.h"
+#include "mpeg2_transcode.h"
+#include "scope_guard.h"
+extern "C" {
+#include <libavcodec/avcodec.h>
+}
+
+
+using std::make_shared;
+using std::shared_ptr;
+using std::vector;
+using boost::optional;
+using namespace dcp;
+
+
+MPEG2Codec::~MPEG2Codec()
+{
+ avcodec_free_context(&_context);
+}
+
+
+
+MPEG2Decompressor::MPEG2Decompressor()
+{
+ _codec = avcodec_find_decoder_by_name("mpeg2video");
+ if (!_codec) {
+ throw MPEG2CodecError("could not find codec");
+ }
+
+ _context = avcodec_alloc_context3(_codec);
+ if (!_context) {
+ throw MPEG2CodecError("could not allocate codec context");
+ }
+
+ int const r = avcodec_open2(_context, _codec, nullptr);
+ if (r < 0) {
+ avcodec_free_context(&_context);
+ throw MPEG2CodecError("could not open codec");
+ }
+
+ _decompressed_frame = av_frame_alloc();
+ if (!_decompressed_frame) {
+ throw std::bad_alloc();
+ }
+}
+
+
+MPEG2Decompressor::~MPEG2Decompressor()
+{
+ av_frame_free(&_decompressed_frame);
+}
+
+
+vector<FFmpegImage>
+MPEG2Decompressor::decompress_frame(shared_ptr<const MonoMPEG2PictureFrame> frame)
+{
+ /* XXX: can we avoid this? */
+ auto copy = av_malloc(frame->size() + AV_INPUT_BUFFER_PADDING_SIZE);
+ if (!copy) {
+ throw std::bad_alloc();
+ }
+ memcpy(copy, frame->data(), frame->size());
+
+ AVPacket packet;
+ av_init_packet(&packet);
+ av_packet_from_data(&packet, reinterpret_cast<uint8_t*>(copy), frame->size());
+
+ auto images = decompress_packet(&packet);
+
+ av_packet_unref(&packet);
+
+ return images;
+}
+
+
+vector<FFmpegImage>
+MPEG2Decompressor::flush()
+{
+ return decompress_packet(nullptr);
+}
+
+
+vector<FFmpegImage>
+MPEG2Decompressor::decompress_packet(AVPacket* packet)
+{
+ int const r = avcodec_send_packet(_context, packet);
+ if (r < 0) {
+ throw MPEG2DecompressionError(String::compose("avcodec_send_packet failed (%1)", r));
+ }
+
+ vector<FFmpegImage> images;
+ while (true) {
+ int const r = avcodec_receive_frame(_context, _decompressed_frame);
+ if (r == AVERROR(EAGAIN) || r == AVERROR_EOF) {
+ break;
+ } else if (r < 0) {
+ throw MPEG2DecompressionError("avcodec_receive_frame failed");
+ }
+
+ auto clone = av_frame_clone(_decompressed_frame);
+ if (!clone) {
+ throw std::bad_alloc();
+ }
+
+ images.push_back(FFmpegImage(clone));
+ }
+
+ return images;
+}
+
+
+MPEG2Compressor::MPEG2Compressor(dcp::Size size, int video_frame_rate, int64_t bit_rate)
+{
+ _codec = avcodec_find_encoder_by_name("mpeg2video");
+ if (!_codec) {
+ throw MPEG2CodecError("could not find codec");
+ }
+
+ _context = avcodec_alloc_context3(_codec);
+ if (!_context) {
+ throw MPEG2CodecError("could not allocate codec context");
+ }
+
+ _context->width = size.width;
+ _context->height = size.height;
+ _context->time_base = AVRational{1, video_frame_rate};
+ _context->pix_fmt = AV_PIX_FMT_YUV420P;
+ _context->bit_rate = bit_rate;
+
+ int const r = avcodec_open2(_context, _codec, nullptr);
+ if (r < 0) {
+ avcodec_free_context(&_context);
+ throw MPEG2CodecError("could not open codec");
+ }
+}
+
+
+optional<MPEG2Compressor::IndexedFrame>
+MPEG2Compressor::send_and_receive(AVFrame const* frame)
+{
+ int r = avcodec_send_frame(_context, frame);
+ if (r < 0) {
+ throw MPEG2CompressionError(String::compose("avcodec_send_frame failed (%1", r));
+ }
+
+ auto packet = av_packet_alloc();
+ if (!packet) {
+ throw MPEG2CompressionError("could not allocate packet");
+ }
+
+ r = avcodec_receive_packet(_context, packet);
+ if (r < 0 && r != AVERROR(EAGAIN)) {
+ throw MPEG2CompressionError(String::compose("avcodec_receive_packet failed (%1)", r));
+ }
+
+ ScopeGuard sg = [&packet]() {
+ av_packet_free(&packet);
+ };
+
+ if (packet->size == 0) {
+ return {};
+ }
+
+ DCP_ASSERT(_context->time_base.num == 1);
+ return IndexedFrame{make_shared<MonoMPEG2PictureFrame>(packet->data, packet->size), std::round(static_cast<double>(packet->pts) / _context->time_base.den)};
+}
+
+
+optional<MPEG2Compressor::IndexedFrame>
+MPEG2Compressor::compress_frame(FFmpegImage const& image)
+{
+ return send_and_receive(image.frame());
+}
+
+
+optional<MPEG2Compressor::IndexedFrame>
+MPEG2Compressor::flush()
+{
+ return send_and_receive(nullptr);
+}
diff --git a/src/mpeg2_transcode.h b/src/mpeg2_transcode.h
new file mode 100644
index 00000000..1f13cfc3
--- /dev/null
+++ b/src/mpeg2_transcode.h
@@ -0,0 +1,108 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#ifndef LIBDCP_MPEG2_TRANSCODE_H
+#define LIBDCP_MPEG2_TRANSCODE_H
+
+
+#include "ffmpeg_image.h"
+#include <memory>
+
+
+struct AVCodec;
+struct AVCodecContext;
+struct AVFrame;
+struct AVPacket;
+
+
+namespace dcp {
+
+
+class MonoMPEG2PictureFrame;
+
+
+class MPEG2Codec
+{
+public:
+ MPEG2Codec() = default;
+ virtual ~MPEG2Codec();
+
+ MPEG2Codec(MPEG2Codec const&) = delete;
+ MPEG2Codec& operator=(MPEG2Codec const&) = delete;
+
+protected:
+ AVCodec const* _codec;
+ AVCodecContext* _context;
+};
+
+
+class MPEG2Decompressor : public MPEG2Codec
+{
+public:
+ MPEG2Decompressor();
+ ~MPEG2Decompressor();
+
+ std::vector<FFmpegImage> decompress_frame(std::shared_ptr<const MonoMPEG2PictureFrame> frame);
+ std::vector<FFmpegImage> flush();
+
+private:
+ std::vector<FFmpegImage> decompress_packet(AVPacket* packet);
+
+ AVFrame* _decompressed_frame;
+};
+
+
+class MPEG2Compressor : public MPEG2Codec
+{
+public:
+ MPEG2Compressor(dcp::Size size, int video_frame_rate, int64_t bit_rate);
+
+ MPEG2Compressor(MPEG2Compressor const&) = delete;
+ MPEG2Compressor& operator=(MPEG2Compressor const&) = delete;
+
+ /** Frame data with frame index within the asset */
+ typedef std::pair<std::shared_ptr<MonoMPEG2PictureFrame>, int64_t> IndexedFrame;
+
+ boost::optional<IndexedFrame> compress_frame(FFmpegImage const& image);
+ boost::optional<IndexedFrame> flush();
+
+private:
+ boost::optional<IndexedFrame> send_and_receive(AVFrame const* frame);
+};
+
+
+}
+
+
+#endif
diff --git a/src/mxf.h b/src/mxf.h
index 19d4a956..1692fbd0 100644
--- a/src/mxf.h
+++ b/src/mxf.h
@@ -64,7 +64,8 @@ namespace dcp
class MXFMetadata;
-class PictureAssetWriter;
+class J2KPictureAssetWriter;
+class MPEG2PictureAssetWriter;
/** @class MXF
@@ -136,7 +137,9 @@ public:
protected:
template <class P, class Q>
- friend void start (PictureAssetWriter* writer, std::shared_ptr<P> state, Q* mxf, uint8_t const * data, int size);
+ friend void start (J2KPictureAssetWriter* writer, std::shared_ptr<P> state, Q* mxf, uint8_t const * data, int size);
+ template <class P, class Q>
+ friend void start (MPEG2PictureAssetWriter* writer, std::shared_ptr<P> state, Q* mxf, uint8_t const * data, int size);
MXF ();
diff --git a/src/name_format.h b/src/name_format.h
index 6401fe82..3eb0277b 100644
--- a/src/name_format.h
+++ b/src/name_format.h
@@ -37,8 +37,8 @@
*/
-#ifndef LIBDCP_NAME_FORMAT
-#define LIBDCP_NAME_FORMAT
+#ifndef LIBDCP_NAME_FORMAT_H
+#define LIBDCP_NAME_FORMAT_H
#include <string>
diff --git a/src/picture_asset.cc b/src/picture_asset.cc
index c9f669a6..3b28bf4b 100644
--- a/src/picture_asset.cc
+++ b/src/picture_asset.cc
@@ -32,199 +32,24 @@
*/
-/** @file src/picture_asset.cc
- * @brief PictureAsset class
- */
-
-
-#include "compose.hpp"
-#include "dcp_assert.h"
-#include "equality_options.h"
-#include "exceptions.h"
-#include "j2k_transcode.h"
-#include "openjpeg_image.h"
#include "picture_asset.h"
-#include "picture_asset_writer.h"
-#include "util.h"
-#include <asdcp/AS_DCP.h>
-#include <asdcp/KM_fileio.h>
-#include <libxml++/nodes/element.h>
-#include <boost/filesystem.hpp>
-#include <list>
-#include <stdexcept>
-
-
-using std::string;
-using std::list;
-using std::vector;
-using std::max;
-using std::pair;
-using std::make_pair;
-using std::shared_ptr;
-using namespace dcp;
-
-
-PictureAsset::PictureAsset (boost::filesystem::path file)
- : Asset (file)
-{
-
-}
-
-PictureAsset::PictureAsset (Fraction edit_rate, Standard standard)
- : MXF (standard)
- , _edit_rate (edit_rate)
-{
-}
+using namespace dcp;
-void
-PictureAsset::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc)
+PictureAsset::PictureAsset(boost::filesystem::path file)
+ : Asset(file)
{
- _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 (
- ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, NoteHandler note
- ) const
-{
- if (
- a.EditRate != b.EditRate ||
- a.SampleRate != b.SampleRate ||
- a.StoredWidth != b.StoredWidth ||
- a.StoredHeight != b.StoredHeight ||
- a.AspectRatio != b.AspectRatio ||
- a.Rsize != b.Rsize ||
- a.Xsize != b.Xsize ||
- a.Ysize != b.Ysize ||
- a.XOsize != b.XOsize ||
- a.YOsize != b.YOsize ||
- a.XTsize != b.XTsize ||
- a.YTsize != b.YTsize ||
- a.XTOsize != b.XTOsize ||
- a.YTOsize != b.YTOsize ||
- a.Csize != b.Csize
-// a.CodingStyleDefault != b.CodingStyleDefault ||
-// a.QuantizationDefault != b.QuantizationDefault
- ) {
-
- note (NoteType::ERROR, "video MXF picture descriptors differ");
- return false;
- }
-
- if (a.ContainerDuration != b.ContainerDuration) {
- note (NoteType::ERROR, "video container durations differ");
- }
-
-// for (unsigned int j = 0; j < ASDCP::JP2K::MaxComponents; ++j) {
-// if (a.ImageComponents[j] != b.ImageComponents[j]) {
-// notes.pack_start ("video MXF picture descriptors differ");
-// }
-// }
-
- return true;
}
-bool
-PictureAsset::frame_buffer_equals (
- int frame, EqualityOptions const& opt, NoteHandler note,
- uint8_t const * data_A, unsigned int size_A, uint8_t const * data_B, unsigned int size_B
- ) const
+PictureAsset::PictureAsset(Fraction edit_rate, Standard standard)
+ : MXF(standard)
+ , _edit_rate(edit_rate)
{
- if (size_A == size_B && memcmp (data_A, data_B, size_A) == 0) {
- note (NoteType::NOTE, "J2K identical");
- /* Easy result; the J2K data is identical */
- return true;
- }
-
- /* Decompress the images to bitmaps */
- auto image_A = decompress_j2k (const_cast<uint8_t*>(data_A), size_A, 0);
- auto image_B = decompress_j2k (const_cast<uint8_t*>(data_B), size_B, 0);
-
- /* Compare them */
-
- vector<int> abs_diffs (image_A->size().width * image_A->size().height * 3);
- int d = 0;
- int max_diff = 0;
- for (int c = 0; c < 3; ++c) {
-
- if (image_A->size() != image_B->size()) {
- note (NoteType::ERROR, String::compose ("image sizes for frame %1 differ", frame));
- return false;
- }
-
- int const pixels = image_A->size().width * image_A->size().height;
- for (int j = 0; j < pixels; ++j) {
- int const t = abs (image_A->data(c)[j] - image_B->data(c)[j]);
- abs_diffs[d++] = t;
- max_diff = max (max_diff, t);
- }
- }
-
- uint64_t total = 0;
- for (vector<int>::iterator j = abs_diffs.begin(); j != abs_diffs.end(); ++j) {
- total += *j;
- }
-
- double const mean = double (total) / abs_diffs.size ();
-
- uint64_t total_squared_deviation = 0;
- for (auto j: abs_diffs) {
- total_squared_deviation += pow (j - mean, 2);
- }
-
- auto const std_dev = sqrt (double (total_squared_deviation) / abs_diffs.size());
-
- note (NoteType::NOTE, String::compose("mean difference %1 deviation %2", mean, std_dev));
-
- if (mean > opt.max_mean_pixel_error) {
- note (
- NoteType::ERROR,
- String::compose ("mean %1 out of range %2 in frame %3", mean, opt.max_mean_pixel_error, frame)
- );
-
- return false;
- }
-
- if (std_dev > opt.max_std_dev_pixel_error) {
- note (
- NoteType::ERROR,
- String::compose ("standard deviation %1 out of range %2 in frame %3", std_dev, opt.max_std_dev_pixel_error, frame)
- );
-
- return false;
- }
-
- return true;
}
-string
-PictureAsset::static_pkl_type (Standard standard)
-{
- switch (standard) {
- case Standard::INTEROP:
- return "application/x-smpte-mxf;asdcpKind=Picture";
- case Standard::SMPTE:
- return "application/mxf";
- default:
- DCP_ASSERT (false);
- }
-}
-
-
-string
-PictureAsset::pkl_type (Standard standard) const
-{
- return static_pkl_type (standard);
-}
diff --git a/src/picture_asset.h b/src/picture_asset.h
index 9ad1eb22..36364485 100644
--- a/src/picture_asset.h
+++ b/src/picture_asset.h
@@ -32,56 +32,31 @@
*/
-/** @file src/picture_asset.h
- * @brief PictureAsset class
- */
-
-
#ifndef LIBDCP_PICTURE_ASSET_H
#define LIBDCP_PICTURE_ASSET_H
+#include "asset.h"
#include "mxf.h"
-#include "util.h"
-#include "metadata.h"
-
-
-namespace ASDCP {
- namespace JP2K {
- struct PictureDescriptor;
- }
-}
+#include "types.h"
namespace dcp {
-class MonoPictureFrame;
-class StereoPictureFrame;
-class PictureAssetWriter;
-
-
-/** @class PictureAsset
- * @brief An asset made up of JPEG2000 data
- */
class PictureAsset : public Asset, public MXF
{
public:
- /** Load a PictureAsset from a file */
- explicit PictureAsset (boost::filesystem::path file);
-
- /** Create a new PictureAsset with a given edit rate and standard */
+ explicit PictureAsset(boost::filesystem::path file);
PictureAsset(Fraction edit_rate, Standard standard);
- enum class Behaviour {
- OVERWRITE_EXISTING,
- MAKE_NEW
- };
+ Fraction edit_rate () const {
+ return _edit_rate;
+ }
- virtual std::shared_ptr<PictureAssetWriter> start_write (
- boost::filesystem::path file,
- Behaviour behaviour
- ) = 0;
+ int64_t intrinsic_duration () const {
+ return _intrinsic_duration;
+ }
Size size () const {
return _size;
@@ -107,33 +82,7 @@ public:
_screen_aspect_ratio = r;
}
- Fraction edit_rate () const {
- return _edit_rate;
- }
-
- int64_t intrinsic_duration () const {
- return _intrinsic_duration;
- }
-
- static std::string static_pkl_type (Standard standard);
-
protected:
- friend class MonoPictureAssetWriter;
- friend class StereoPictureAssetWriter;
-
- bool frame_buffer_equals (
- int frame, EqualityOptions const& opt, NoteHandler 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,
- NoteHandler note
- ) const;
-
- void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &);
-
Fraction _edit_rate;
/** The total length of this content in video frames. The amount of
* content presented may be less than this.
@@ -144,8 +93,6 @@ protected:
Fraction _frame_rate;
Fraction _screen_aspect_ratio;
-private:
- std::string pkl_type (Standard standard) const override;
};
@@ -153,3 +100,4 @@ private:
#endif
+
diff --git a/src/pkl.cc b/src/pkl.cc
index 57eda9da..463d046a 100644
--- a/src/pkl.cc
+++ b/src/pkl.cc
@@ -105,26 +105,26 @@ PKL::write_xml (boost::filesystem::path file, shared_ptr<const CertificateChain>
pkl = doc.create_root_node("PackingList", pkl_smpte_ns);
}
- pkl->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ cxml::add_text_child(pkl, "Id", "urn:uuid:" + _id);
if (_annotation_text) {
- pkl->add_child("AnnotationText")->add_child_text (*_annotation_text);
+ cxml::add_text_child(pkl, "AnnotationText", *_annotation_text);
}
- pkl->add_child("IssueDate")->add_child_text (_issue_date);
- pkl->add_child("Issuer")->add_child_text (_issuer);
- pkl->add_child("Creator")->add_child_text (_creator);
+ cxml::add_text_child(pkl, "IssueDate", _issue_date);
+ cxml::add_text_child(pkl, "Issuer", _issuer);
+ cxml::add_text_child(pkl, "Creator", _creator);
- auto asset_list = pkl->add_child("AssetList");
+ auto asset_list = cxml::add_child(pkl, "AssetList");
for (auto i: _assets) {
- auto asset = asset_list->add_child("Asset");
- asset->add_child("Id")->add_child_text ("urn:uuid:" + i->id());
+ auto asset = cxml::add_child(asset_list, "Asset");
+ cxml::add_text_child(asset, "Id", "urn:uuid:" + i->id());
if (i->annotation_text()) {
- asset->add_child("AnnotationText")->add_child_text (*i->annotation_text());
+ cxml::add_text_child(asset, "AnnotationText", *i->annotation_text());
}
- asset->add_child("Hash")->add_child_text (i->hash());
- asset->add_child("Size")->add_child_text (raw_convert<string>(i->size()));
- asset->add_child("Type")->add_child_text (i->type());
+ cxml::add_text_child(asset, "Hash", i->hash());
+ cxml::add_text_child(asset, "Size", raw_convert<string>(i->size()));
+ cxml::add_text_child(asset, "Type", i->type());
if (auto filename = i->original_filename()) {
- asset->add_child("OriginalFileName")->add_child_text(*filename);
+ cxml::add_text_child(asset, "OriginalFileName", *filename);
}
}
diff --git a/src/pkl.h b/src/pkl.h
index d0a11188..88443057 100644
--- a/src/pkl.h
+++ b/src/pkl.h
@@ -32,7 +32,7 @@
*/
-/** @file src/pkl.cc
+/** @file src/pkl.h
* @brief PKL class
*/
diff --git a/src/rating.cc b/src/rating.cc
index 21960365..156d5ad0 100644
--- a/src/rating.cc
+++ b/src/rating.cc
@@ -61,8 +61,8 @@ Rating::Rating (cxml::ConstNodePtr node)
void
Rating::as_xml (xmlpp::Element* parent) const
{
- parent->add_child("Agency")->add_child_text(agency);
- parent->add_child("Label")->add_child_text(label);
+ cxml::add_text_child(parent, "Agency", agency);
+ cxml::add_text_child(parent, "Label", label);
}
diff --git a/src/reel.cc b/src/reel.cc
index a8481d59..acd7c7fc 100644
--- a/src/reel.cc
+++ b/src/reel.cc
@@ -41,8 +41,8 @@
#include "decrypted_kdm_key.h"
#include "equality_options.h"
#include "interop_subtitle_asset.h"
-#include "mono_picture_asset.h"
-#include "picture_asset.h"
+#include "mono_j2k_picture_asset.h"
+#include "j2k_picture_asset.h"
#include "reel.h"
#include "reel_atmos_asset.h"
#include "reel_closed_caption_asset.h"
@@ -57,7 +57,7 @@
#include "reel_subtitle_asset.h"
#include "smpte_subtitle_asset.h"
#include "sound_asset.h"
-#include "stereo_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
#include "subtitle_asset.h"
#include "util.h"
#include <libxml++/nodes/element.h>
@@ -141,9 +141,9 @@ Reel::Reel (std::shared_ptr<const cxml::Node> node, dcp::Standard standard)
xmlpp::Element *
Reel::write_to_cpl (xmlpp::Element* node, Standard standard) const
{
- auto reel = node->add_child ("Reel");
- reel->add_child("Id")->add_child_text("urn:uuid:" + _id);
- xmlpp::Element* asset_list = reel->add_child ("AssetList");
+ auto reel = cxml::add_child(node, "Reel");
+ cxml::add_text_child(reel, "Id", "urn:uuid:" + _id);
+ auto asset_list = cxml::add_child(reel, "AssetList");
if (_main_markers) {
_main_markers->write_to_cpl (asset_list, standard);
@@ -327,7 +327,7 @@ Reel::give_kdm_to_assets (DecryptedKDM const & kdm)
{
for (auto const& i: kdm.keys()) {
if (_main_picture && i.id() == _main_picture->key_id() && _main_picture->asset_ref().resolved()) {
- _main_picture->asset()->set_key (i.key());
+ _main_picture->j2k_asset()->set_key(i.key());
}
if (_main_sound && i.id() == _main_sound->key_id() && _main_sound->asset_ref().resolved()) {
_main_sound->asset()->set_key (i.key());
diff --git a/src/reel.h b/src/reel.h
index 52f41bfa..df6d12a9 100644
--- a/src/reel.h
+++ b/src/reel.h
@@ -32,7 +32,7 @@
*/
-/** @file src/reel.cc
+/** @file src/reel.h
* @brief Reel class
*/
diff --git a/src/reel_asset.cc b/src/reel_asset.cc
index 3a3ae731..c782cf2b 100644
--- a/src/reel_asset.cc
+++ b/src/reel_asset.cc
@@ -84,10 +84,10 @@ ReelAsset::ReelAsset (shared_ptr<const cxml::Node> node)
}
-xmlpp::Node*
-ReelAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element*
+ReelAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
- auto a = node->add_child (cpl_node_name (standard));
+ auto a = cxml::add_child(node, cpl_node_name(standard));
auto const attr = cpl_node_attribute (standard);
if (!attr.first.empty ()) {
a->set_attribute (attr.first, attr.second);
@@ -96,18 +96,18 @@ ReelAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
if (!ns.first.empty()) {
a->set_namespace_declaration (ns.first, ns.second);
}
- a->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+ cxml::add_text_child(a, "Id", "urn:uuid:" + _id);
/* Empty <AnnotationText> tags cause refusal to play on some Sony SRX320 / LMT3000 systems (DoM bug #2124) */
if (_annotation_text && !_annotation_text->empty()) {
- a->add_child("AnnotationText")->add_child_text(*_annotation_text);
+ cxml::add_text_child(a, "AnnotationText", *_annotation_text);
}
- a->add_child("EditRate")->add_child_text (_edit_rate.as_string());
- a->add_child("IntrinsicDuration")->add_child_text (raw_convert<string> (_intrinsic_duration));
+ cxml::add_text_child(a, "EditRate", _edit_rate.as_string());
+ cxml::add_text_child(a, "IntrinsicDuration", raw_convert<string>(_intrinsic_duration));
if (_entry_point) {
- a->add_child("EntryPoint")->add_child_text(raw_convert<string>(*_entry_point));
+ cxml::add_text_child(a, "EntryPoint", raw_convert<string>(*_entry_point));
}
if (_duration) {
- a->add_child("Duration")->add_child_text(raw_convert<string>(*_duration));
+ cxml::add_text_child(a, "Duration", raw_convert<string>(*_duration));
}
return a;
}
diff --git a/src/reel_asset.h b/src/reel_asset.h
index e928cb18..8dad739e 100644
--- a/src/reel_asset.h
+++ b/src/reel_asset.h
@@ -83,7 +83,7 @@ public:
explicit ReelAsset (std::shared_ptr<const cxml::Node>);
- virtual xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const;
+ virtual xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const;
virtual bool encryptable () const {
return false;
diff --git a/src/reel_atmos_asset.cc b/src/reel_atmos_asset.cc
index ef39a4eb..c2cdb7f3 100644
--- a/src/reel_atmos_asset.cc
+++ b/src/reel_atmos_asset.cc
@@ -82,11 +82,11 @@ ReelAtmosAsset::cpl_node_namespace () const
}
-xmlpp::Node *
-ReelAtmosAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element*
+ReelAtmosAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
auto asset = ReelFileAsset::write_to_cpl (node, standard);
- asset->add_child("axd:DataType")->add_child_text("urn:smpte:ul:060e2b34.04010105.0e090604.00000000");
+ cxml::add_text_child(asset, "axd:DataType", "urn:smpte:ul:060e2b34.04010105.0e090604.00000000");
return asset;
}
diff --git a/src/reel_atmos_asset.h b/src/reel_atmos_asset.h
index 298cbbfd..c3de76a8 100644
--- a/src/reel_atmos_asset.h
+++ b/src/reel_atmos_asset.h
@@ -68,7 +68,7 @@ public:
return asset_of_type<AtmosAsset>();
}
- xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const override;
+ xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
bool equals(std::shared_ptr<const ReelAtmosAsset>, EqualityOptions const&, NoteHandler) const;
private:
diff --git a/src/reel_file_asset.cc b/src/reel_file_asset.cc
index 5fefda27..8fed8012 100644
--- a/src/reel_file_asset.cc
+++ b/src/reel_file_asset.cc
@@ -94,15 +94,15 @@ ReelFileAsset::file_asset_equals(shared_ptr<const ReelFileAsset> other, Equality
}
-xmlpp::Node *
-ReelFileAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element*
+ReelFileAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
- auto asset = ReelAsset::write_to_cpl (node, standard);
+ auto asset = ReelAsset::write_to_cpl(node, standard);
if (_key_id) {
- asset->add_child("KeyId")->add_child_text("urn:uuid:" + *_key_id);
+ cxml::add_text_child(asset, "KeyId", "urn:uuid:" + *_key_id);
}
if (_hash) {
- asset->add_child("Hash")->add_child_text(*_hash);
+ cxml::add_text_child(asset, "Hash", *_hash);
}
return asset;
}
diff --git a/src/reel_file_asset.h b/src/reel_file_asset.h
index 687e0d3e..48fdf215 100644
--- a/src/reel_file_asset.h
+++ b/src/reel_file_asset.h
@@ -56,7 +56,7 @@ public:
ReelFileAsset (std::shared_ptr<Asset> asset, boost::optional<std::string> key_id, std::string id, Fraction edit_rate, int64_t intrinsic_duration, int64_t entry_point);
explicit ReelFileAsset (std::shared_ptr<const cxml::Node> node);
- virtual xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const override;
+ virtual xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
/** @return a Ref to our actual asset */
Ref const & asset_ref () const {
diff --git a/src/reel_interop_closed_caption_asset.cc b/src/reel_interop_closed_caption_asset.cc
index be968068..c4539fd7 100644
--- a/src/reel_interop_closed_caption_asset.cc
+++ b/src/reel_interop_closed_caption_asset.cc
@@ -75,12 +75,12 @@ ReelInteropClosedCaptionAsset::cpl_node_namespace () const
}
-xmlpp::Node *
-ReelInteropClosedCaptionAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element*
+ReelInteropClosedCaptionAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
auto asset = ReelClosedCaptionAsset::write_to_cpl (node, standard);
if (_language) {
- asset->add_child("Language")->add_child_text(*_language);
+ cxml::add_text_child(asset, "Language", *_language);
}
return asset;
}
diff --git a/src/reel_interop_closed_caption_asset.h b/src/reel_interop_closed_caption_asset.h
index 5e8f7c1e..5a074357 100644
--- a/src/reel_interop_closed_caption_asset.h
+++ b/src/reel_interop_closed_caption_asset.h
@@ -62,7 +62,7 @@ public:
return asset_of_type<InteropSubtitleAsset>();
}
- xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const override;
+ xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
private:
std::string cpl_node_name (Standard) const override;
diff --git a/src/reel_markers_asset.cc b/src/reel_markers_asset.cc
index d71a22ec..4b1b3472 100644
--- a/src/reel_markers_asset.cc
+++ b/src/reel_markers_asset.cc
@@ -104,16 +104,16 @@ ReelMarkersAsset::get (Marker m) const
}
-xmlpp::Node*
-ReelMarkersAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element*
+ReelMarkersAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
int const tcr = edit_rate().numerator / edit_rate().denominator;
auto asset = ReelAsset::write_to_cpl (node, standard);
- auto ml = asset->add_child("MarkerList");
+ auto ml = cxml::add_child(asset, "MarkerList");
for (auto const& i: _markers) {
- auto m = ml->add_child("Marker");
- m->add_child("Label")->add_child_text(marker_to_string(i.first));
- m->add_child("Offset")->add_child_text(raw_convert<string>(i.second.as_editable_units_ceil(tcr)));
+ auto m = cxml::add_child(ml, "Marker");
+ cxml::add_text_child(m, "Label", marker_to_string(i.first));
+ cxml::add_text_child(m, "Offset", raw_convert<string>(i.second.as_editable_units_ceil(tcr)));
}
return asset;
diff --git a/src/reel_markers_asset.h b/src/reel_markers_asset.h
index 2a1480a2..e2b65585 100644
--- a/src/reel_markers_asset.h
+++ b/src/reel_markers_asset.h
@@ -32,7 +32,7 @@
*/
-/** @file src/reel_markers_asset.cc
+/** @file src/reel_markers_asset.h
* @brief ReelMarkersAsset class
*/
@@ -51,7 +51,7 @@ public:
ReelMarkersAsset (Fraction edit_rate, int64_t intrinsic_duration);
explicit ReelMarkersAsset (std::shared_ptr<const cxml::Node>);
- xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const override;
+ xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
bool equals(std::shared_ptr<const ReelMarkersAsset>, EqualityOptions const&, NoteHandler) const;
void set (Marker, Time);
diff --git a/src/reel_mono_picture_asset.cc b/src/reel_mono_picture_asset.cc
index 9c44ec20..81eb4df9 100644
--- a/src/reel_mono_picture_asset.cc
+++ b/src/reel_mono_picture_asset.cc
@@ -38,7 +38,7 @@
#include "reel_mono_picture_asset.h"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
#include <libcxml/cxml.h>
@@ -47,7 +47,7 @@ using std::shared_ptr;
using namespace dcp;
-ReelMonoPictureAsset::ReelMonoPictureAsset (std::shared_ptr<MonoPictureAsset> asset, int64_t entry_point)
+ReelMonoPictureAsset::ReelMonoPictureAsset(std::shared_ptr<PictureAsset> asset, int64_t entry_point)
: ReelPictureAsset (asset, entry_point)
{
diff --git a/src/reel_mono_picture_asset.h b/src/reel_mono_picture_asset.h
index fb2dff70..13c6545e 100644
--- a/src/reel_mono_picture_asset.h
+++ b/src/reel_mono_picture_asset.h
@@ -42,13 +42,14 @@
#include "reel_picture_asset.h"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_mpeg2_picture_asset.h"
namespace dcp {
-class MonoPictureAsset;
+class MonoJ2KPictureAsset;
/** @class ReelMonoPictureAsset
@@ -57,17 +58,27 @@ class MonoPictureAsset;
class ReelMonoPictureAsset : public ReelPictureAsset
{
public:
- ReelMonoPictureAsset (std::shared_ptr<MonoPictureAsset> asset, int64_t entry_point);
+ ReelMonoPictureAsset(std::shared_ptr<PictureAsset> asset, int64_t entry_point);
explicit ReelMonoPictureAsset (std::shared_ptr<const cxml::Node>);
- /** @return the MonoPictureAsset that this object refers to */
- std::shared_ptr<const MonoPictureAsset> mono_asset () const {
- return asset_of_type<const MonoPictureAsset>();
+ /** @return the MonoJ2KPictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const MonoJ2KPictureAsset> mono_j2k_asset() const {
+ return asset_of_type<const MonoJ2KPictureAsset>();
}
- /** @return the MonoPictureAsset that this object refers to */
- std::shared_ptr<MonoPictureAsset> mono_asset () {
- return asset_of_type<MonoPictureAsset>();
+ /** @return the MonoJ2KPictureAsset that this object refers to */
+ std::shared_ptr<MonoJ2KPictureAsset> mono_j2k_asset() {
+ return asset_of_type<MonoJ2KPictureAsset>();
+ }
+
+ /** @return the MonoMPEG2PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const MonoMPEG2PictureAsset> mono_mpeg2_asset() const {
+ return asset_of_type<const MonoMPEG2PictureAsset>();
+ }
+
+ /** @return the MonoMPEG2PictureAsset that this object refers to */
+ std::shared_ptr<MonoMPEG2PictureAsset> mono_mpeg2_asset() {
+ return asset_of_type<MonoMPEG2PictureAsset>();
}
private:
diff --git a/src/reel_picture_asset.cc b/src/reel_picture_asset.cc
index eb87d039..37a6bfcc 100644
--- a/src/reel_picture_asset.cc
+++ b/src/reel_picture_asset.cc
@@ -39,7 +39,7 @@
#include "compose.hpp"
#include "dcp_assert.h"
-#include "picture_asset.h"
+#include "j2k_picture_asset.h"
#include "raw_convert.h"
#include "reel_picture_asset.h"
#include "warnings.h"
@@ -59,7 +59,7 @@ using boost::optional;
using namespace dcp;
-ReelPictureAsset::ReelPictureAsset (shared_ptr<PictureAsset> asset, int64_t entry_point)
+ReelPictureAsset::ReelPictureAsset(shared_ptr<PictureAsset> asset, int64_t entry_point)
: ReelFileAsset (asset, asset->key_id(), asset->id(), asset->edit_rate(), asset->intrinsic_duration(), entry_point)
, _frame_rate (asset->frame_rate ())
, _screen_aspect_ratio (asset->screen_aspect_ratio ())
@@ -86,12 +86,12 @@ ReelPictureAsset::ReelPictureAsset (shared_ptr<const cxml::Node> node)
}
-xmlpp::Node*
-ReelPictureAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element*
+ReelPictureAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
auto asset = ReelFileAsset::write_to_cpl (node, standard);
- asset->add_child("FrameRate")->add_child_text(String::compose("%1 %2", _frame_rate.numerator, _frame_rate.denominator));
+ cxml::add_text_child(asset, "FrameRate", String::compose("%1 %2", _frame_rate.numerator, _frame_rate.denominator));
if (standard == Standard::INTEROP) {
@@ -113,10 +113,12 @@ ReelPictureAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
}
}
- asset->add_child("ScreenAspectRatio")->add_child_text(raw_convert<string>(closest.get(), 2, true));
+ cxml::add_text_child(asset, "ScreenAspectRatio", raw_convert<string>(closest.get(), 2, true));
} else {
- asset->add_child("ScreenAspectRatio")->add_child_text(
- String::compose ("%1 %2", _screen_aspect_ratio.numerator, _screen_aspect_ratio.denominator)
+ cxml::add_text_child(
+ asset,
+ "ScreenAspectRatio",
+ 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
index bf7d40aa..9f42a5b6 100644
--- a/src/reel_picture_asset.h
+++ b/src/reel_picture_asset.h
@@ -42,7 +42,8 @@
#include "reel_file_asset.h"
-#include "picture_asset.h"
+#include "j2k_picture_asset.h"
+#include "mpeg2_picture_asset.h"
namespace dcp {
@@ -54,20 +55,41 @@ namespace dcp {
class ReelPictureAsset : public ReelFileAsset
{
public:
- ReelPictureAsset (std::shared_ptr<PictureAsset> asset, int64_t entry_point);
+ ReelPictureAsset(std::shared_ptr<PictureAsset> asset, int64_t entry_point);
explicit ReelPictureAsset (std::shared_ptr<const cxml::Node>);
- /** @return the PictureAsset that this object refers to */
- std::shared_ptr<const PictureAsset> asset () const {
+ /** @return the PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const PictureAsset> asset() const {
return asset_of_type<const PictureAsset>();
}
- /** @return the PictureAsset that this object refers to */
- std::shared_ptr<PictureAsset> asset () {
+ /** @return the PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<PictureAsset> asset() {
return asset_of_type<PictureAsset>();
}
- virtual xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const override;
+ /** @return the J2KPictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const J2KPictureAsset> j2k_asset() const {
+ return asset_of_type<const J2KPictureAsset>();
+ }
+
+ /** @return the J2KPictureAsset that this object refers to, if applicable */
+ std::shared_ptr<J2KPictureAsset> j2k_asset() {
+ return asset_of_type<J2KPictureAsset>();
+ }
+
+ /** @return the MPEG2PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<const MPEG2PictureAsset> mpeg2_asset() const {
+ return asset_of_type<const MPEG2PictureAsset>();
+ }
+
+ /** @return the MPEG2PictureAsset that this object refers to, if applicable */
+ std::shared_ptr<MPEG2PictureAsset> mpeg2_asset() {
+ return asset_of_type<MPEG2PictureAsset>();
+ }
+
+ virtual xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
+
bool equals(std::shared_ptr<const ReelPictureAsset>, EqualityOptions const&, NoteHandler) const;
/** @return picture frame rate */
diff --git a/src/reel_smpte_closed_caption_asset.cc b/src/reel_smpte_closed_caption_asset.cc
index a2a68202..70e5eb36 100644
--- a/src/reel_smpte_closed_caption_asset.cc
+++ b/src/reel_smpte_closed_caption_asset.cc
@@ -65,12 +65,12 @@ ReelSMPTEClosedCaptionAsset::ReelSMPTEClosedCaptionAsset (shared_ptr<const cxml:
}
-xmlpp::Node *
-ReelSMPTEClosedCaptionAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element*
+ReelSMPTEClosedCaptionAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
auto asset = ReelClosedCaptionAsset::write_to_cpl (node, standard);
if (_language) {
- asset->add_child("Language", "tt")->add_child_text(*_language);
+ cxml::add_child(asset, "Language", string("tt"))->add_child_text(*_language);
}
return asset;
}
diff --git a/src/reel_smpte_closed_caption_asset.h b/src/reel_smpte_closed_caption_asset.h
index 32a79efd..e7a26f65 100644
--- a/src/reel_smpte_closed_caption_asset.h
+++ b/src/reel_smpte_closed_caption_asset.h
@@ -63,7 +63,7 @@ public:
return asset_of_type<const SMPTESubtitleAsset>();
}
- xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const override;
+ xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
private:
diff --git a/src/reel_smpte_subtitle_asset.h b/src/reel_smpte_subtitle_asset.h
index 2a097309..49b6000b 100644
--- a/src/reel_smpte_subtitle_asset.h
+++ b/src/reel_smpte_subtitle_asset.h
@@ -32,8 +32,8 @@
*/
-/** @file src/reel_interop_subtitle_asset.h
- * @brief ReelInteropSubtitleAsset class
+/** @file src/reel_smpte_subtitle_asset.h
+ * @brief ReelSMPTESubtitleAsset class
*/
diff --git a/src/reel_stereo_picture_asset.cc b/src/reel_stereo_picture_asset.cc
index 5bf4756c..13bfec8e 100644
--- a/src/reel_stereo_picture_asset.cc
+++ b/src/reel_stereo_picture_asset.cc
@@ -38,7 +38,7 @@
#include "reel_stereo_picture_asset.h"
-#include "stereo_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
#include <libcxml/cxml.h>
@@ -49,7 +49,7 @@ using std::shared_ptr;
using namespace dcp;
-ReelStereoPictureAsset::ReelStereoPictureAsset (std::shared_ptr<StereoPictureAsset> mxf, int64_t entry_point)
+ReelStereoPictureAsset::ReelStereoPictureAsset (std::shared_ptr<StereoJ2KPictureAsset> mxf, int64_t entry_point)
: ReelPictureAsset (mxf, entry_point)
{
diff --git a/src/reel_stereo_picture_asset.h b/src/reel_stereo_picture_asset.h
index 7cac1c8b..09170ddd 100644
--- a/src/reel_stereo_picture_asset.h
+++ b/src/reel_stereo_picture_asset.h
@@ -42,13 +42,13 @@
#include "reel_picture_asset.h"
-#include "stereo_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
namespace dcp {
-class StereoPictureAsset;
+class StereoJ2KPictureAsset;
/** @class ReelStereoPictureAsset
@@ -57,17 +57,17 @@ class StereoPictureAsset;
class ReelStereoPictureAsset : public ReelPictureAsset
{
public:
- ReelStereoPictureAsset (std::shared_ptr<StereoPictureAsset> content, int64_t entry_point);
+ ReelStereoPictureAsset (std::shared_ptr<StereoJ2KPictureAsset> content, int64_t entry_point);
explicit ReelStereoPictureAsset (std::shared_ptr<const cxml::Node>);
- /** @return the StereoPictureAsset that this object refers to */
- std::shared_ptr<const StereoPictureAsset> stereo_asset () const {
- return asset_of_type<const StereoPictureAsset>();
+ /** @return the StereoJ2KPictureAsset that this object refers to */
+ std::shared_ptr<const StereoJ2KPictureAsset> stereo_asset () const {
+ return asset_of_type<const StereoJ2KPictureAsset>();
}
- /** @return the StereoPictureAsset that this object refers to */
- std::shared_ptr<StereoPictureAsset> stereo_asset () {
- return asset_of_type<StereoPictureAsset>();
+ /** @return the StereoJ2KPictureAsset that this object refers to */
+ std::shared_ptr<StereoJ2KPictureAsset> stereo_asset () {
+ return asset_of_type<StereoJ2KPictureAsset>();
}
private:
diff --git a/src/reel_subtitle_asset.cc b/src/reel_subtitle_asset.cc
index d856a05e..436aa69f 100644
--- a/src/reel_subtitle_asset.cc
+++ b/src/reel_subtitle_asset.cc
@@ -103,12 +103,12 @@ ReelSubtitleAsset::equals(shared_ptr<const ReelSubtitleAsset> other, EqualityOpt
}
-xmlpp::Node *
-ReelSubtitleAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+xmlpp::Element *
+ReelSubtitleAsset::write_to_cpl(xmlpp::Element* node, Standard standard) const
{
auto asset = ReelFileAsset::write_to_cpl (node, standard);
if (_language) {
- asset->add_child("Language")->add_child_text(*_language);
+ cxml::add_text_child(asset, "Language", *_language);
}
return asset;
}
diff --git a/src/reel_subtitle_asset.h b/src/reel_subtitle_asset.h
index 8b694fd6..c619c752 100644
--- a/src/reel_subtitle_asset.h
+++ b/src/reel_subtitle_asset.h
@@ -73,7 +73,7 @@ public:
return asset_of_type<SubtitleAsset>();
}
- xmlpp::Node* write_to_cpl (xmlpp::Node* node, Standard standard) const override;
+ xmlpp::Element* write_to_cpl(xmlpp::Element* node, Standard standard) const override;
bool equals(std::shared_ptr<const ReelSubtitleAsset>, EqualityOptions const&, NoteHandler) const;
diff --git a/src/rgb_xyz.h b/src/rgb_xyz.h
index c41fdee0..315295ea 100644
--- a/src/rgb_xyz.h
+++ b/src/rgb_xyz.h
@@ -32,7 +32,7 @@
*/
-/** @file rgb_xyz.h
+/** @file src/rgb_xyz.h
* @brief Conversion between RGB and XYZ
*/
diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc
index 0ff1d7ef..4f611583 100644
--- a/src/smpte_subtitle_asset.cc
+++ b/src/smpte_subtitle_asset.cc
@@ -95,7 +95,8 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
{
auto xml = make_shared<cxml::Document>("SubtitleReel");
- auto reader = make_shared<ASDCP::TimedText::MXFReader>();
+ Kumu::FileReaderFactory factory;
+ auto reader = make_shared<ASDCP::TimedText::MXFReader>(factory);
auto r = Kumu::RESULT_OK;
{
ASDCPErrorSuspender sus;
@@ -320,7 +321,8 @@ SMPTESubtitleAsset::set_key (Key key)
/* Our data was encrypted; now we can decrypt it */
- auto reader = make_shared<ASDCP::TimedText::MXFReader>();
+ Kumu::FileReaderFactory factory;
+ auto reader = make_shared<ASDCP::TimedText::MXFReader>(factory);
auto r = reader->OpenRead(dcp::filesystem::fix_long_path(*_file).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (
@@ -354,7 +356,8 @@ SMPTESubtitleAsset::load_font_nodes () const
bool
SMPTESubtitleAsset::valid_mxf (boost::filesystem::path file)
{
- ASDCP::TimedText::MXFReader reader;
+ Kumu::FileReaderFactory factory;
+ ASDCP::TimedText::MXFReader reader(factory);
Kumu::DefaultLogSink().UnsetFilterFlag(Kumu::LOG_ALLOW_ALL);
auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
Kumu::DefaultLogSink().SetFilterFlag(Kumu::LOG_ALLOW_ALL);
@@ -369,31 +372,31 @@ SMPTESubtitleAsset::xml_as_string () const
auto root = doc.create_root_node ("SubtitleReel");
DCP_ASSERT (_xml_id);
- root->add_child("Id")->add_child_text("urn:uuid:" + *_xml_id);
- root->add_child("ContentTitleText")->add_child_text(_content_title_text);
+ cxml::add_text_child(root, "Id", "urn:uuid:" + *_xml_id);
+ cxml::add_text_child(root, "ContentTitleText", _content_title_text);
if (_annotation_text) {
- root->add_child("AnnotationText")->add_child_text(_annotation_text.get());
+ cxml::add_text_child(root, "AnnotationText", _annotation_text.get());
}
- root->add_child("IssueDate")->add_child_text(_issue_date.as_string(false, false));
+ cxml::add_text_child(root, "IssueDate", _issue_date.as_string(false, false));
if (_reel_number) {
- root->add_child("ReelNumber")->add_child_text(raw_convert<string>(_reel_number.get()));
+ cxml::add_text_child(root, "ReelNumber", raw_convert<string>(_reel_number.get()));
}
if (_language) {
- root->add_child("Language")->add_child_text(_language.get());
+ cxml::add_text_child(root, "Language", _language.get());
}
- root->add_child("EditRate")->add_child_text(_edit_rate.as_string());
- root->add_child("TimeCodeRate")->add_child_text(raw_convert<string>(_time_code_rate));
+ cxml::add_text_child(root, "EditRate", _edit_rate.as_string());
+ cxml::add_text_child(root, "TimeCodeRate", raw_convert<string>(_time_code_rate));
if (_start_time) {
- root->add_child("StartTime")->add_child_text(_start_time.get().as_string(Standard::SMPTE));
+ cxml::add_text_child(root, "StartTime", _start_time.get().as_string(Standard::SMPTE));
}
for (auto i: _load_font_nodes) {
- auto load_font = root->add_child("LoadFont");
+ auto load_font = cxml::add_child(root, "LoadFont");
load_font->add_child_text ("urn:uuid:" + i->urn);
load_font->set_attribute ("ID", i->id);
}
- subtitles_as_xml (root->add_child("SubtitleList"), _time_code_rate, Standard::SMPTE);
+ subtitles_as_xml(cxml::add_child(root, "SubtitleList"), _time_code_rate, Standard::SMPTE);
return format_xml(doc, std::make_pair(string{}, schema_namespace()));
}
diff --git a/src/sound_asset.cc b/src/sound_asset.cc
index 0ceba53d..90075278 100644
--- a/src/sound_asset.cc
+++ b/src/sound_asset.cc
@@ -70,7 +70,8 @@ using namespace dcp;
SoundAsset::SoundAsset (boost::filesystem::path file)
: Asset (file)
{
- ASDCP::PCM::MXFReader reader;
+ Kumu::FileReaderFactory factory;
+ ASDCP::PCM::MXFReader reader(factory);
auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
@@ -138,14 +139,15 @@ SoundAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& opt, No
return true;
}
- ASDCP::PCM::MXFReader reader_A;
+ Kumu::FileReaderFactory factory;
+ ASDCP::PCM::MXFReader reader_A(factory);
DCP_ASSERT (file());
auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*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;
+ ASDCP::PCM::MXFReader reader_B(factory);
r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", other->file()->string(), r));
@@ -278,7 +280,8 @@ SoundAsset::static_pkl_type (Standard standard)
bool
SoundAsset::valid_mxf (boost::filesystem::path file)
{
- ASDCP::PCM::MXFReader reader;
+ Kumu::FileReaderFactory factory;
+ ASDCP::PCM::MXFReader reader(factory);
Kumu::Result_t r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
return !ASDCP_FAILURE (r);
}
diff --git a/src/stereo_picture_asset.cc b/src/stereo_j2k_picture_asset.cc
index 2ce3cdc9..6a5e7d79 100644
--- a/src/stereo_picture_asset.cc
+++ b/src/stereo_j2k_picture_asset.cc
@@ -33,7 +33,7 @@
/** @file src/stereo_picture_asset.cc
- * @brief StereoPictureAsset class
+ * @brief StereoJ2KPictureAsset class
*/
@@ -41,10 +41,10 @@
#include "equality_options.h"
#include "exceptions.h"
#include "filesystem.h"
-#include "stereo_picture_asset.h"
-#include "stereo_picture_asset_reader.h"
-#include "stereo_picture_asset_writer.h"
-#include "stereo_picture_frame.h"
+#include "stereo_j2k_picture_asset.h"
+#include "stereo_j2k_picture_asset_reader.h"
+#include "stereo_j2k_picture_asset_writer.h"
+#include "stereo_j2k_picture_frame.h"
#include <asdcp/AS_DCP.h>
@@ -56,10 +56,11 @@ using std::dynamic_pointer_cast;
using namespace dcp;
-StereoPictureAsset::StereoPictureAsset (boost::filesystem::path file)
- : PictureAsset (file)
+StereoJ2KPictureAsset::StereoJ2KPictureAsset (boost::filesystem::path file)
+ : J2KPictureAsset (file)
{
- ASDCP::JP2K::MXFSReader reader;
+ Kumu::FileReaderFactory factory;
+ ASDCP::JP2K::MXFSReader reader(factory);
auto r = reader.OpenRead(dcp::filesystem::fix_long_path(file).string().c_str());
if (ASDCP_FAILURE(r)) {
boost::throw_exception (MXFFileError("could not open MXF file for reading", file.string(), r));
@@ -81,38 +82,39 @@ StereoPictureAsset::StereoPictureAsset (boost::filesystem::path file)
}
-StereoPictureAsset::StereoPictureAsset (Fraction edit_rate, Standard standard)
- : PictureAsset (edit_rate, standard)
+StereoJ2KPictureAsset::StereoJ2KPictureAsset (Fraction edit_rate, Standard standard)
+ : J2KPictureAsset (edit_rate, standard)
{
}
-shared_ptr<PictureAssetWriter>
-StereoPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour)
+shared_ptr<J2KPictureAssetWriter>
+StereoJ2KPictureAsset::start_write(boost::filesystem::path file, Behaviour behaviour)
{
- return shared_ptr<StereoPictureAssetWriter>(new StereoPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING));
+ return shared_ptr<StereoJ2KPictureAssetWriter>(new StereoJ2KPictureAssetWriter(this, file, behaviour == Behaviour::OVERWRITE_EXISTING));
}
-shared_ptr<StereoPictureAssetReader>
-StereoPictureAsset::start_read () const
+shared_ptr<StereoJ2KPictureAssetReader>
+StereoJ2KPictureAsset::start_read () const
{
- return shared_ptr<StereoPictureAssetReader> (new StereoPictureAssetReader(this, key(), standard()));
+ return shared_ptr<StereoJ2KPictureAssetReader> (new StereoJ2KPictureAssetReader(this, key(), standard()));
}
bool
-StereoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& opt, NoteHandler note) const
+StereoJ2KPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const& opt, NoteHandler note) const
{
- ASDCP::JP2K::MXFSReader reader_A;
+ Kumu::FileReaderFactory factory;
+ ASDCP::JP2K::MXFSReader reader_A(factory);
DCP_ASSERT (file());
auto r = reader_A.OpenRead(dcp::filesystem::fix_long_path(*file()).string().c_str());
if (ASDCP_FAILURE (r)) {
boost::throw_exception (MXFFileError ("could not open MXF file for reading", file()->string(), r));
}
- ASDCP::JP2K::MXFSReader reader_B;
+ ASDCP::JP2K::MXFSReader reader_B(factory);
DCP_ASSERT (other->file());
r = reader_B.OpenRead(dcp::filesystem::fix_long_path(*other->file()).string().c_str());
if (ASDCP_FAILURE (r)) {
@@ -132,7 +134,7 @@ StereoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const&
return false;
}
- auto other_picture = dynamic_pointer_cast<const StereoPictureAsset> (other);
+ auto other_picture = dynamic_pointer_cast<const StereoJ2KPictureAsset> (other);
DCP_ASSERT (other_picture);
auto reader = start_read ();
@@ -141,8 +143,8 @@ StereoPictureAsset::equals(shared_ptr<const Asset> other, EqualityOptions const&
bool result = true;
for (int i = 0; i < _intrinsic_duration; ++i) {
- shared_ptr<const StereoPictureFrame> frame_A;
- shared_ptr<const StereoPictureFrame> frame_B;
+ shared_ptr<const StereoJ2KPictureFrame> frame_A;
+ shared_ptr<const StereoJ2KPictureFrame> frame_B;
try {
frame_A = reader->get_frame (i);
frame_B = other_reader->get_frame (i);
diff --git a/src/stereo_picture_asset.h b/src/stereo_j2k_picture_asset.h
index 6ee1d423..7ef86ec5 100644
--- a/src/stereo_picture_asset.h
+++ b/src/stereo_j2k_picture_asset.h
@@ -32,34 +32,34 @@
*/
-/** @file src/stereo_picture_asset.h
- * @brief StereoPictureAsset class
+/** @file src/stereo_j2k_picture_asset.h
+ * @brief StereoJ2KPictureAsset class
*/
-#ifndef LIBDCP_STEREO_PICTURE_ASSET_H
-#define LIBDCP_STEREO_PICTURE_ASSET_H
+#ifndef LIBDCP_STEREO_J2K_PICTURE_ASSET_H
+#define LIBDCP_STEREO_J2K_PICTURE_ASSET_H
-#include "picture_asset.h"
-#include "stereo_picture_asset_reader.h"
+#include "j2k_picture_asset.h"
+#include "stereo_j2k_picture_asset_reader.h"
namespace dcp {
-/** @class StereoPictureAsset
+/** @class StereoJ2KPictureAsset
* @brief A 3D (stereoscopic) picture asset
*/
-class StereoPictureAsset : public PictureAsset
+class StereoJ2KPictureAsset : public J2KPictureAsset
{
public:
- explicit StereoPictureAsset (boost::filesystem::path file);
- explicit StereoPictureAsset (Fraction edit_rate, Standard standard);
+ explicit StereoJ2KPictureAsset (boost::filesystem::path file);
+ explicit StereoJ2KPictureAsset (Fraction edit_rate, Standard standard);
- /** Start a progressive write to a StereoPictureAsset */
- std::shared_ptr<PictureAssetWriter> start_write(boost::filesystem::path file, Behaviour behaviour) override;
- std::shared_ptr<StereoPictureAssetReader> start_read () const;
+ /** Start a progressive write to a StereoJ2KPictureAsset */
+ std::shared_ptr<J2KPictureAssetWriter> start_write(boost::filesystem::path file, Behaviour behaviour) override;
+ std::shared_ptr<StereoJ2KPictureAssetReader> start_read () const;
bool equals (
std::shared_ptr<const Asset> other,
diff --git a/src/mono_picture_asset_reader.h b/src/stereo_j2k_picture_asset_reader.h
index 5bead791..e4812a8e 100644
--- a/src/mono_picture_asset_reader.h
+++ b/src/stereo_j2k_picture_asset_reader.h
@@ -32,23 +32,23 @@
*/
-/** @file src/mono_picture_asset_reader.h
- * @brief MonoPictureAssetReader typedef
+/** @file src/stereo_j2k_picture_asset_reader.h
+ * @brief StereoJ2KPictureAssetReader typedef
*/
-#ifndef LIBDCP_MONO_PICTURE_ASSET_READER_H
-#define LIBDCP_MONO_PICTURE_ASSET_READER_H
+#ifndef LIBDCP_STEREO_J2K_PICTURE_ASSET_READER_H
+#define LIBDCP_STEREO_J2K_PICTURE_ASSET_READER_H
#include "asset_reader.h"
-#include "mono_picture_frame.h"
+#include "stereo_j2k_picture_frame.h"
namespace dcp {
-typedef AssetReader<ASDCP::JP2K::MXFReader, MonoPictureFrame> MonoPictureAssetReader;
+typedef AssetReader<ASDCP::JP2K::MXFSReader, StereoJ2KPictureFrame> StereoJ2KPictureAssetReader;
}
diff --git a/src/stereo_picture_asset_writer.cc b/src/stereo_j2k_picture_asset_writer.cc
index 6ee271bc..e59de02f 100644
--- a/src/stereo_picture_asset_writer.cc
+++ b/src/stereo_j2k_picture_asset_writer.cc
@@ -33,20 +33,20 @@
/** @file src/stereo_picture_asset_writer.cc
- * @brief StereoPictureAssetWriter class
+ * @brief StereoJ2KPictureAssetWriter class
*/
-#include "stereo_picture_asset_writer.h"
+#include "stereo_j2k_picture_asset_writer.h"
#include "exceptions.h"
#include "dcp_assert.h"
-#include "picture_asset.h"
+#include "j2k_picture_asset.h"
#include "crypto_context.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_fileio.h>
-#include "picture_asset_writer_common.cc"
+#include "j2k_picture_asset_writer_common.cc"
using std::string;
@@ -54,21 +54,21 @@ using std::shared_ptr;
using namespace dcp;
-struct StereoPictureAssetWriter::ASDCPState : public ASDCPStateBase
+struct StereoJ2KPictureAssetWriter::ASDCPState : public ASDCPJ2KStateBase
{
ASDCP::JP2K::MXFSWriter mxf_writer;
};
-StereoPictureAssetWriter::StereoPictureAssetWriter (PictureAsset* mxf, boost::filesystem::path file, bool overwrite)
- : PictureAssetWriter (mxf, file, overwrite)
- , _state (new StereoPictureAssetWriter::ASDCPState)
+StereoJ2KPictureAssetWriter::StereoJ2KPictureAssetWriter (J2KPictureAsset* mxf, boost::filesystem::path file, bool overwrite)
+ : J2KPictureAssetWriter (mxf, file, overwrite)
+ , _state (new StereoJ2KPictureAssetWriter::ASDCPState)
{
}
-StereoPictureAssetWriter::~StereoPictureAssetWriter()
+StereoJ2KPictureAssetWriter::~StereoJ2KPictureAssetWriter()
{
try {
/* Last-resort finalization to close the file, at least */
@@ -80,15 +80,15 @@ StereoPictureAssetWriter::~StereoPictureAssetWriter()
void
-StereoPictureAssetWriter::start (uint8_t const * data, int size)
+StereoJ2KPictureAssetWriter::start (uint8_t const * data, int size)
{
dcp::start (this, _state, _picture_asset, data, size);
_picture_asset->set_frame_rate (Fraction (_picture_asset->edit_rate().numerator * 2, _picture_asset->edit_rate().denominator));
}
-FrameInfo
-StereoPictureAssetWriter::write (uint8_t const * data, int size)
+J2KFrameInfo
+StereoJ2KPictureAssetWriter::write (uint8_t const * data, int size)
{
DCP_ASSERT (!_finalized);
@@ -123,17 +123,17 @@ StereoPictureAssetWriter::write (uint8_t const * data, int size)
++_frames_written;
}
- return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
+ return J2KFrameInfo(before_offset, _state->mxf_writer.Tell() - before_offset, hash);
}
void
-StereoPictureAssetWriter::fake_write (int size)
+StereoJ2KPictureAssetWriter::fake_write(J2KFrameInfo const& info)
{
DCP_ASSERT (_started);
DCP_ASSERT (!_finalized);
- auto r = _state->mxf_writer.FakeWriteFrame (size, _next_eye == Eye::LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT);
+ auto r = _state->mxf_writer.FakeWriteFrame(info.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", _file.string(), r));
}
@@ -146,7 +146,7 @@ StereoPictureAssetWriter::fake_write (int size)
bool
-StereoPictureAssetWriter::finalize ()
+StereoJ2KPictureAssetWriter::finalize ()
{
if (_started) {
auto r = _state->mxf_writer.Finalize();
@@ -156,5 +156,5 @@ StereoPictureAssetWriter::finalize ()
}
_picture_asset->_intrinsic_duration = _frames_written;
- return PictureAssetWriter::finalize ();
+ return J2KPictureAssetWriter::finalize ();
}
diff --git a/src/stereo_picture_asset_writer.h b/src/stereo_j2k_picture_asset_writer.h
index 1cee1202..e3f39a0b 100644
--- a/src/stereo_picture_asset_writer.h
+++ b/src/stereo_j2k_picture_asset_writer.h
@@ -32,12 +32,12 @@
*/
-/** @file src/stereo_picture_asset_writer.h
- * @brief StereoPictureAssetWriter class
+/** @file src/stereo_j2k_picture_asset_writer.h
+ * @brief StereoJ2KPictureAssetWriter class
*/
-#include "picture_asset_writer.h"
+#include "j2k_picture_asset_writer.h"
#include <memory>
#include <stdint.h>
#include <string>
@@ -46,33 +46,33 @@
namespace dcp {
-/** @class StereoPictureAssetWriter
- * @brief A helper class for writing to StereoPictureAssets.
+/** @class StereoJ2KPictureAssetWriter
+ * @brief A helper class for writing to StereoJ2KPictureAssets.
*
- * Objects of this class can only be created with StereoPictureAsset::start_write().
+ * Objects of this class can only be created with StereoJ2KPictureAsset::start_write().
*
- * Frames can be written to the StereoPictureAsset by calling write() with a JPEG2000 image
+ * Frames can be written to the StereoJ2KPictureAsset by calling write() with a JPEG2000 image
* (a verbatim .j2c file). finalize() should be called after the last frame has been written,
* but if it is not, it will be called by the destructor (though in that case any error
* during finalization will be ignored).
*/
-class StereoPictureAssetWriter : public PictureAssetWriter
+class StereoJ2KPictureAssetWriter : public J2KPictureAssetWriter
{
public:
- ~StereoPictureAssetWriter();
+ ~StereoJ2KPictureAssetWriter();
/** Write a frame for one eye. Frames must be written left, then right, then left etc.
* @param data JPEG2000 data.
* @param size Size of data.
*/
- FrameInfo write (uint8_t const * data, int size) override;
- void fake_write (int size) override;
+ J2KFrameInfo write(uint8_t const * data, int size) override;
+ void fake_write(J2KFrameInfo const& info) override;
bool finalize () override;
private:
- friend class StereoPictureAsset;
+ friend class StereoJ2KPictureAsset;
- StereoPictureAssetWriter (PictureAsset *, boost::filesystem::path file, bool);
+ StereoJ2KPictureAssetWriter (J2KPictureAsset *, boost::filesystem::path file, bool);
void start (uint8_t const *, int);
/* do this with an opaque pointer so we don't have to include
diff --git a/src/stereo_picture_frame.cc b/src/stereo_j2k_picture_frame.cc
index 8d3a2757..9ef91c5c 100644
--- a/src/stereo_picture_frame.cc
+++ b/src/stereo_j2k_picture_frame.cc
@@ -33,7 +33,7 @@
/** @file src/stereo_picture_frame.cc
- * @brief StereoPictureFrame class
+ * @brief StereoJ2KPictureFrame class
*/
@@ -43,7 +43,7 @@
#include "exceptions.h"
#include "j2k_transcode.h"
#include "rgb_xyz.h"
-#include "stereo_picture_frame.h"
+#include "stereo_j2k_picture_frame.h"
#include "util.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_fileio.h>
@@ -55,7 +55,7 @@ using std::make_shared;
using namespace dcp;
-StereoPictureFrame::Part::Part (shared_ptr<ASDCP::JP2K::SFrameBuffer> buffer, Eye eye)
+StereoJ2KPictureFrame::Part::Part (shared_ptr<ASDCP::JP2K::SFrameBuffer> buffer, Eye eye)
: _buffer (buffer)
, _eye (eye)
{
@@ -64,28 +64,28 @@ StereoPictureFrame::Part::Part (shared_ptr<ASDCP::JP2K::SFrameBuffer> buffer, Ey
ASDCP::JP2K::FrameBuffer &
-StereoPictureFrame::Part::mono () const
+StereoJ2KPictureFrame::Part::mono () const
{
return _eye == Eye::LEFT ? _buffer->Left : _buffer->Right;
}
uint8_t const *
-StereoPictureFrame::Part::data () const
+StereoJ2KPictureFrame::Part::data () const
{
return mono().RoData();
}
uint8_t *
-StereoPictureFrame::Part::data ()
+StereoJ2KPictureFrame::Part::data ()
{
return mono().Data();
}
int
-StereoPictureFrame::Part::size () const
+StereoJ2KPictureFrame::Part::size () const
{
return mono().Size();
}
@@ -96,7 +96,7 @@ StereoPictureFrame::Part::size () const
* @param n Frame within the asset, not taking EntryPoint into account.
* @param check_hmac true to check the HMAC and give an error if it is not as expected.
*/
-StereoPictureFrame::StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, shared_ptr<DecryptionContext> c, bool check_hmac)
+StereoJ2KPictureFrame::StereoJ2KPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, shared_ptr<DecryptionContext> c, bool check_hmac)
{
/* XXX: unfortunate guesswork on this buffer size */
_buffer = make_shared<ASDCP::JP2K::SFrameBuffer>(4 * Kumu::Megabyte);
@@ -107,7 +107,7 @@ StereoPictureFrame::StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n,
}
-StereoPictureFrame::StereoPictureFrame ()
+StereoJ2KPictureFrame::StereoJ2KPictureFrame ()
{
_buffer = make_shared<ASDCP::JP2K::SFrameBuffer>(4 * Kumu::Megabyte);
}
@@ -119,7 +119,7 @@ StereoPictureFrame::StereoPictureFrame ()
* reduction).
*/
shared_ptr<OpenJPEGImage>
-StereoPictureFrame::xyz_image (Eye eye, int reduce) const
+StereoJ2KPictureFrame::xyz_image (Eye eye, int reduce) const
{
switch (eye) {
case Eye::LEFT:
@@ -132,15 +132,15 @@ StereoPictureFrame::xyz_image (Eye eye, int reduce) const
}
-shared_ptr<StereoPictureFrame::Part>
-StereoPictureFrame::right () const
+shared_ptr<StereoJ2KPictureFrame::Part>
+StereoJ2KPictureFrame::right () const
{
return make_shared<Part>(_buffer, Eye::RIGHT);
}
-shared_ptr<StereoPictureFrame::Part>
-StereoPictureFrame::left () const
+shared_ptr<StereoJ2KPictureFrame::Part>
+StereoJ2KPictureFrame::left () const
{
return make_shared<Part>(_buffer, Eye::LEFT);
}
diff --git a/src/stereo_picture_frame.h b/src/stereo_j2k_picture_frame.h
index b0c0f0c8..193960f3 100644
--- a/src/stereo_picture_frame.h
+++ b/src/stereo_j2k_picture_frame.h
@@ -32,13 +32,13 @@
*/
-/** @file src/stereo_picture_frame.h
- * @brief StereoPictureFrame class
+/** @file src/stereo_j2k_picture_frame.h
+ * @brief StereoJ2KPictureFrame class
*/
-#ifndef LIBDCP_STEREO_PICTURE_FRAME_H
-#define LIBDCP_STEREO_PICTURE_FRAME_H
+#ifndef LIBDCP_STEREO_J2K_PICTURE_FRAME_H
+#define LIBDCP_STEREO_J2K_PICTURE_FRAME_H
#include "asset_reader.h"
@@ -61,19 +61,19 @@ namespace dcp {
class OpenJPEGImage;
-class StereoPictureFrame;
+class StereoJ2KPictureFrame;
-/** @class StereoPictureFrame
+/** @class StereoJ2KPictureFrame
* @brief A single frame of a 3D (stereoscopic) picture asset
*/
-class StereoPictureFrame
+class StereoJ2KPictureFrame
{
public:
- StereoPictureFrame ();
+ StereoJ2KPictureFrame ();
- StereoPictureFrame (StereoPictureFrame const &) = delete;
- StereoPictureFrame& operator= (StereoPictureFrame const &) = delete;
+ StereoJ2KPictureFrame (StereoJ2KPictureFrame const &) = delete;
+ StereoJ2KPictureFrame& operator= (StereoJ2KPictureFrame const &) = delete;
std::shared_ptr<OpenJPEGImage> xyz_image (Eye eye, int reduce = 0) const;
@@ -87,7 +87,7 @@ public:
int size () const override;
private:
- friend class StereoPictureFrame;
+ friend class StereoJ2KPictureFrame;
ASDCP::JP2K::FrameBuffer& mono () const;
@@ -99,12 +99,12 @@ public:
std::shared_ptr<Part> right () const;
private:
- /* XXX: this is a bit of a shame, but I tried friend StereoPictureAssetReader and it's
+ /* XXX: this is a bit of a shame, but I tried friend StereoJ2KPictureAssetReader and it's
rejected by some (seemingly older) GCCs.
*/
- friend class AssetReader<ASDCP::JP2K::MXFSReader, StereoPictureFrame>;
+ friend class AssetReader<ASDCP::JP2K::MXFSReader, StereoJ2KPictureFrame>;
- StereoPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
+ StereoJ2KPictureFrame (ASDCP::JP2K::MXFSReader* reader, int n, std::shared_ptr<DecryptionContext>, bool check_hmac);
std::shared_ptr<ASDCP::JP2K::SFrameBuffer> _buffer;
};
diff --git a/src/subtitle_asset_internal.cc b/src/subtitle_asset_internal.cc
index 99d8411b..39f68624 100644
--- a/src/subtitle_asset_internal.cc
+++ b/src/subtitle_asset_internal.cc
@@ -77,7 +77,7 @@ order::Font::Font (shared_ptr<SubtitleString> s, Standard standard)
xmlpp::Element*
order::Font::as_xml (xmlpp::Element* parent, Context&) const
{
- auto e = parent->add_child("Font");
+ auto e = cxml::add_child(parent, "Font");
for (const auto& i: _values) {
e->set_attribute (i.first, i.second);
}
@@ -137,7 +137,7 @@ xmlpp::Element*
order::String::as_xml (xmlpp::Element* parent, Context& context) const
{
if (fabs(_space_before) > SPACE_BEFORE_EPSILON) {
- auto space = parent->add_child("Space");
+ auto space = cxml::add_child(parent, "Space");
auto size = raw_convert<string>(_space_before, 2);
if (context.standard == Standard::INTEROP) {
size += "em";
@@ -212,7 +212,7 @@ position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, floa
xmlpp::Element*
order::Text::as_xml (xmlpp::Element* parent, Context& context) const
{
- auto e = parent->add_child ("Text");
+ auto e = cxml::add_child(parent, "Text");
position_align(e, context, _h_align, _h_position, _v_align, _v_position, _z_position);
@@ -224,9 +224,9 @@ order::Text::as_xml (xmlpp::Element* parent, Context& context) const
}
for (auto const& ruby: _rubies) {
- auto xml = e->add_child("Ruby");
- xml->add_child("Rb")->add_child_text(ruby.base);
- auto rt = xml->add_child("Rt");
+ auto xml = cxml::add_child(e, "Ruby");
+ cxml::add_child(xml, "Rb")->add_child_text(ruby.base);
+ auto rt = cxml::add_child(xml, "Rt");
rt->add_child_text(ruby.annotation);
rt->set_attribute("Size", dcp::raw_convert<string>(ruby.size, 6));
rt->set_attribute("Position", ruby.position == RubyPosition::BEFORE ? "before" : "after");
@@ -242,7 +242,7 @@ order::Text::as_xml (xmlpp::Element* parent, Context& context) const
xmlpp::Element*
order::Subtitle::as_xml (xmlpp::Element* parent, Context& context) const
{
- auto e = parent->add_child ("Subtitle");
+ auto e = cxml::add_child(parent, "Subtitle");
e->set_attribute ("SpotNumber", raw_convert<string> (context.spot_number++));
e->set_attribute ("TimeIn", _in.rebase(context.time_code_rate).as_string(context.standard));
e->set_attribute ("TimeOut", _out.rebase(context.time_code_rate).as_string(context.standard));
@@ -274,7 +274,7 @@ order::Font::clear ()
xmlpp::Element *
order::Image::as_xml (xmlpp::Element* parent, Context& context) const
{
- auto e = parent->add_child ("Image");
+ auto e = cxml::add_child(parent, "Image");
position_align(e, context, _h_align, _h_position, _v_align, _v_position, _z_position);
if (context.standard == Standard::SMPTE) {
diff --git a/src/types.cc b/src/types.cc
index e2165548..d58256a5 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -310,9 +310,9 @@ ContentVersion::ContentVersion (string label_text_)
void
ContentVersion::as_xml (xmlpp::Element* parent) const
{
- auto cv = parent->add_child("ContentVersion");
- cv->add_child("Id")->add_child_text(id);
- cv->add_child("LabelText")->add_child_text(label_text);
+ auto cv = cxml::add_child(parent, "ContentVersion");
+ cxml::add_text_child(cv, "Id", id);
+ cxml::add_text_child(cv, "LabelText", label_text);
}
@@ -345,7 +345,7 @@ Luminance::set_value (float v)
void
Luminance::as_xml (xmlpp::Element* parent, string ns) const
{
- auto lum = parent->add_child("Luminance", ns);
+ auto lum = cxml::add_child(parent, "Luminance", ns);
lum->set_attribute("units", unit_to_string(_unit));
lum->add_child_text(raw_convert<string>(_value, 3));
}
diff --git a/src/verify.cc b/src/verify.cc
index 112a5bb5..56e6b5b8 100644
--- a/src/verify.cc
+++ b/src/verify.cc
@@ -43,8 +43,8 @@
#include "exceptions.h"
#include "filesystem.h"
#include "interop_subtitle_asset.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_frame.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_frame.h"
#include "raw_convert.h"
#include "reel.h"
#include "reel_closed_caption_asset.h"
@@ -55,8 +55,8 @@
#include "reel_smpte_subtitle_asset.h"
#include "reel_subtitle_asset.h"
#include "smpte_subtitle_asset.h"
-#include "stereo_picture_asset.h"
-#include "stereo_picture_frame.h"
+#include "stereo_j2k_picture_asset.h"
+#include "stereo_j2k_picture_frame.h"
#include "verify.h"
#include "verify_j2k.h"
#include <libxml/parserInternals.h>
@@ -88,6 +88,7 @@
using std::cout;
using std::dynamic_pointer_cast;
+using std::function;
using std::list;
using std::make_shared;
using std::map;
@@ -97,7 +98,6 @@ using std::shared_ptr;
using std::string;
using std::vector;
using boost::optional;
-using boost::function;
using namespace dcp;
@@ -293,9 +293,83 @@ parse (XercesDOMParser& parser, string xml)
}
+class Context
+{
+public:
+ Context(
+ std::vector<VerificationNote>& notes_,
+ boost::filesystem::path xsd_dtd_directory_,
+ function<void (string, optional<boost::filesystem::path>)> stage_,
+ function<void (float)> progress_,
+ VerificationOptions options_
+ )
+ : notes(notes_)
+ , xsd_dtd_directory(xsd_dtd_directory_)
+ , stage(stage_)
+ , progress(progress_)
+ , options(options_)
+ {
+
+ }
+
+ Context(Context const&) = delete;
+ Context& operator=(Context const&) = delete;
+
+ template<typename... Args>
+ void ok(dcp::VerificationNote::Code code, Args... args)
+ {
+ add_note({dcp::VerificationNote::Type::OK, code, std::forward<Args>(args)...});
+ }
+
+ template<typename... Args>
+ void warning(dcp::VerificationNote::Code code, Args... args)
+ {
+ add_note({dcp::VerificationNote::Type::WARNING, code, std::forward<Args>(args)...});
+ }
+
+ template<typename... Args>
+ void bv21_error(dcp::VerificationNote::Code code, Args... args)
+ {
+ add_note({dcp::VerificationNote::Type::BV21_ERROR, code, std::forward<Args>(args)...});
+ }
+
+ template<typename... Args>
+ void error(dcp::VerificationNote::Code code, Args... args)
+ {
+ add_note({dcp::VerificationNote::Type::ERROR, code, std::forward<Args>(args)...});
+ }
+
+ void add_note(dcp::VerificationNote note)
+ {
+ if (cpl) {
+ note.set_cpl_id(cpl->id());
+ }
+ notes.push_back(std::move(note));
+ }
+
+ void add_note_if_not_existing(dcp::VerificationNote note)
+ {
+ if (find(notes.begin(), notes.end(), note) == notes.end()) {
+ add_note(note);
+ }
+ }
+
+ std::vector<VerificationNote>& notes;
+ std::shared_ptr<const DCP> dcp;
+ std::shared_ptr<const CPL> cpl;
+ boost::filesystem::path xsd_dtd_directory;
+ function<void (string, optional<boost::filesystem::path>)> stage;
+ function<void (float)> progress;
+ VerificationOptions options;
+
+ boost::optional<string> subtitle_language;
+ boost::optional<int> audio_channels;
+};
+
+
template <class T>
void
-validate_xml (T xml, boost::filesystem::path xsd_dtd_directory, vector<VerificationNote>& notes)
+validate_xml(Context& context, T xml)
{
try {
XMLPlatformUtils::Initialize ();
@@ -348,7 +422,7 @@ validate_xml (T xml, boost::filesystem::path xsd_dtd_directory, vector<Verificat
parser.setValidationSchemaFullChecking(true);
parser.setErrorHandler(&error_handler);
- LocalFileResolver resolver (xsd_dtd_directory);
+ LocalFileResolver resolver(context.xsd_dtd_directory);
parser.setEntityResolver(&resolver);
try {
@@ -366,13 +440,12 @@ validate_xml (T xml, boost::filesystem::path xsd_dtd_directory, vector<Verificat
XMLPlatformUtils::Terminate ();
for (auto i: error_handler.errors()) {
- notes.push_back ({
- VerificationNote::Type::ERROR,
+ context.error(
VerificationNote::Code::INVALID_XML,
i.message(),
boost::trim_copy(i.public_id() + " " + i.system_id()),
i.line()
- });
+ );
}
}
@@ -386,9 +459,8 @@ enum class VerifyAssetResult {
static VerifyAssetResult
verify_asset(
- shared_ptr<const DCP> dcp,
+ Context& context,
shared_ptr<const ReelFileAsset> reel_file_asset,
- function<void (float)> progress,
string* reference_hash,
string* calculated_hash
)
@@ -402,11 +474,11 @@ verify_asset(
* call to hash().
*/
reel_file_asset->asset_ref()->unset_hash();
- *calculated_hash = reel_file_asset->asset_ref()->hash([progress](int64_t done, int64_t total) {
- progress(float(done) / total);
+ *calculated_hash = reel_file_asset->asset_ref()->hash([&context](int64_t done, int64_t total) {
+ context.progress(float(done) / total);
});
- auto pkls = dcp->pkls();
+ auto pkls = context.dcp->pkls();
/* We've read this DCP in so it must have at least one PKL */
DCP_ASSERT (!pkls.empty());
@@ -436,103 +508,106 @@ verify_asset(
}
-void
-verify_language_tag (string tag, vector<VerificationNote>& notes)
+static void
+verify_language_tag(Context& context, string tag)
{
try {
LanguageTag test (tag);
} catch (LanguageTagError &) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_LANGUAGE, tag});
+ context.bv21_error(VerificationNote::Code::INVALID_LANGUAGE, tag);
}
}
static void
-verify_picture_asset(shared_ptr<const ReelFileAsset> reel_file_asset, boost::filesystem::path file, int64_t start_frame, vector<VerificationNote>& notes, function<void (float)> progress)
+verify_picture_asset(
+ Context& context,
+ shared_ptr<const ReelFileAsset> reel_file_asset,
+ boost::filesystem::path file,
+ int64_t start_frame
+ )
{
- auto asset = dynamic_pointer_cast<PictureAsset>(reel_file_asset->asset_ref().asset());
+ auto asset = dynamic_pointer_cast<J2KPictureAsset>(reel_file_asset->asset_ref().asset());
auto const duration = asset->intrinsic_duration ();
- auto check_and_add = [&notes](vector<VerificationNote> const& j2k_notes) {
+ auto check_and_add = [&context](vector<VerificationNote> const& j2k_notes) {
for (auto i: j2k_notes) {
- if (find(notes.begin(), notes.end(), i) == notes.end()) {
- notes.push_back (i);
- }
+ context.add_note_if_not_existing(i);
}
};
int const max_frame = rint(250 * 1000000 / (8 * asset->edit_rate().as_float()));
int const risky_frame = rint(230 * 1000000 / (8 * asset->edit_rate().as_float()));
- auto check_frame_size = [max_frame, risky_frame, file, start_frame](int index, int size, int frame_rate, vector<VerificationNote>& notes) {
+ bool any_bad_frames_seen = false;
+
+ auto check_frame_size = [max_frame, risky_frame, file, start_frame, &any_bad_frames_seen](Context& context, int index, int size, int frame_rate) {
if (size > max_frame) {
- notes.push_back(
+ context.add_note(
VerificationNote(
VerificationNote::Type::ERROR, VerificationNote::Code::INVALID_PICTURE_FRAME_SIZE_IN_BYTES, file
).set_frame(start_frame + index).set_frame_rate(frame_rate)
);
+ any_bad_frames_seen = true;
} else if (size > risky_frame) {
- notes.push_back(
+ context.add_note(
VerificationNote(
VerificationNote::Type::WARNING, VerificationNote::Code::NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES, file
).set_frame(start_frame + index).set_frame_rate(frame_rate)
);
+ any_bad_frames_seen = true;
}
};
- if (auto mono_asset = dynamic_pointer_cast<MonoPictureAsset>(reel_file_asset->asset_ref().asset())) {
+ if (auto mono_asset = dynamic_pointer_cast<MonoJ2KPictureAsset>(reel_file_asset->asset_ref().asset())) {
auto reader = mono_asset->start_read ();
for (int64_t i = 0; i < duration; ++i) {
auto frame = reader->get_frame (i);
- check_frame_size(i, frame->size(), mono_asset->frame_rate().numerator, notes);
+ check_frame_size(context, i, frame->size(), mono_asset->frame_rate().numerator);
if (!mono_asset->encrypted() || mono_asset->key()) {
vector<VerificationNote> j2k_notes;
verify_j2k(frame, start_frame, i, mono_asset->frame_rate().numerator, j2k_notes);
check_and_add (j2k_notes);
}
- progress (float(i) / duration);
+ context.progress(float(i) / duration);
}
- } else if (auto stereo_asset = dynamic_pointer_cast<StereoPictureAsset>(asset)) {
+ } else if (auto stereo_asset = dynamic_pointer_cast<StereoJ2KPictureAsset>(asset)) {
auto reader = stereo_asset->start_read ();
for (int64_t i = 0; i < duration; ++i) {
auto frame = reader->get_frame (i);
- check_frame_size(i, frame->left()->size(), stereo_asset->frame_rate().numerator, notes);
- check_frame_size(i, frame->right()->size(), stereo_asset->frame_rate().numerator, notes);
+ check_frame_size(context, i, frame->left()->size(), stereo_asset->frame_rate().numerator);
+ check_frame_size(context, i, frame->right()->size(), stereo_asset->frame_rate().numerator);
if (!stereo_asset->encrypted() || stereo_asset->key()) {
vector<VerificationNote> j2k_notes;
verify_j2k(frame->left(), start_frame, i, stereo_asset->frame_rate().numerator, j2k_notes);
verify_j2k(frame->right(), start_frame, i, stereo_asset->frame_rate().numerator, j2k_notes);
check_and_add (j2k_notes);
}
- progress (float(i) / duration);
+ context.progress(float(i) / duration);
}
}
+
+ if (!any_bad_frames_seen) {
+ context.ok(VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, file);
+ }
}
static void
-verify_main_picture_asset (
- shared_ptr<const DCP> dcp,
- shared_ptr<const ReelPictureAsset> reel_asset,
- int64_t start_frame,
- function<void (string, optional<boost::filesystem::path>)> stage,
- function<void (float)> progress,
- VerificationOptions options,
- vector<VerificationNote>& notes
- )
+verify_main_picture_asset(Context& context, shared_ptr<const ReelPictureAsset> reel_asset, int64_t start_frame)
{
auto asset = reel_asset->asset();
auto const file = *asset->file();
- if (options.check_asset_hashes && (!options.maximum_asset_size_for_hash_check || filesystem::file_size(file) < *options.maximum_asset_size_for_hash_check)) {
- stage ("Checking picture asset hash", file);
+ if (context.options.check_asset_hashes && (!context.options.maximum_asset_size_for_hash_check || filesystem::file_size(file) < *context.options.maximum_asset_size_for_hash_check)) {
+ context.stage("Checking picture asset hash", file);
string reference_hash;
string calculated_hash;
- auto const r = verify_asset(dcp, reel_asset, progress, &reference_hash, &calculated_hash);
+ auto const r = verify_asset(context, reel_asset, &reference_hash, &calculated_hash);
switch (r) {
case VerifyAssetResult::BAD:
- notes.push_back(
+ context.add_note(
dcp::VerificationNote(
VerificationNote::Type::ERROR,
VerificationNote::Code::INCORRECT_PICTURE_HASH,
@@ -541,17 +616,16 @@ verify_main_picture_asset (
);
break;
case VerifyAssetResult::CPL_PKL_DIFFER:
- notes.push_back ({
- VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_PICTURE_HASHES, file
- });
+ context.error(VerificationNote::Code::MISMATCHED_PICTURE_HASHES, file);
break;
default:
+ context.ok(VerificationNote::Code::CORRECT_PICTURE_HASH, file);
break;
}
}
- stage ("Checking picture frame sizes", asset->file());
- verify_picture_asset(reel_asset, file, start_frame, notes, progress);
+ context.stage("Checking picture frame sizes", asset->file());
+ verify_picture_asset(context, reel_asset, file, start_frame);
/* Only flat/scope allowed by Bv2.1 */
if (
@@ -559,12 +633,7 @@ verify_main_picture_asset (
asset->size() != Size(1998, 1080) &&
asset->size() != Size(4096, 1716) &&
asset->size() != Size(3996, 2160)) {
- notes.push_back({
- VerificationNote::Type::BV21_ERROR,
- VerificationNote::Code::INVALID_PICTURE_SIZE_IN_PIXELS,
- String::compose("%1x%2", asset->size().width, asset->size().height),
- file
- });
+ context.bv21_error(VerificationNote::Code::INVALID_PICTURE_SIZE_IN_PIXELS, String::compose("%1x%2", asset->size().width, asset->size().height), file);
}
/* Only 24, 25, 48fps allowed for 2K */
@@ -572,69 +641,50 @@ verify_main_picture_asset (
(asset->size() == Size(2048, 858) || asset->size() == Size(1998, 1080)) &&
(asset->edit_rate() != Fraction(24, 1) && asset->edit_rate() != Fraction(25, 1) && asset->edit_rate() != Fraction(48, 1))
) {
- notes.push_back({
- VerificationNote::Type::BV21_ERROR,
+ context.bv21_error(
VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_2K,
String::compose("%1/%2", asset->edit_rate().numerator, asset->edit_rate().denominator),
file
- });
+ );
}
if (asset->size() == Size(4096, 1716) || asset->size() == Size(3996, 2160)) {
/* Only 24fps allowed for 4K */
if (asset->edit_rate() != Fraction(24, 1)) {
- notes.push_back({
- VerificationNote::Type::BV21_ERROR,
+ context.bv21_error(
VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_4K,
String::compose("%1/%2", asset->edit_rate().numerator, asset->edit_rate().denominator),
file
- });
+ );
}
/* Only 2D allowed for 4K */
- if (dynamic_pointer_cast<const StereoPictureAsset>(asset)) {
- notes.push_back({
- VerificationNote::Type::BV21_ERROR,
+ if (dynamic_pointer_cast<const StereoJ2KPictureAsset>(asset)) {
+ context.bv21_error(
VerificationNote::Code::INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D,
String::compose("%1/%2", asset->edit_rate().numerator, asset->edit_rate().denominator),
file
- });
+ );
}
}
-
}
-struct State
-{
- boost::optional<string> subtitle_language;
- boost::optional<int> audio_channels;
-};
-
-
static void
-verify_main_sound_asset (
- shared_ptr<const DCP> dcp,
- shared_ptr<const ReelSoundAsset> reel_asset,
- function<void (string, optional<boost::filesystem::path>)> stage,
- function<void (float)> progress,
- VerificationOptions options,
- vector<VerificationNote>& notes,
- State& state
- )
+verify_main_sound_asset(Context& context, shared_ptr<const ReelSoundAsset> reel_asset)
{
auto asset = reel_asset->asset();
auto const file = *asset->file();
- if (options.check_asset_hashes && (!options.maximum_asset_size_for_hash_check || filesystem::file_size(file) < *options.maximum_asset_size_for_hash_check)) {
- stage("Checking sound asset hash", file);
+ if (context.options.check_asset_hashes && (!context.options.maximum_asset_size_for_hash_check || filesystem::file_size(file) < *context.options.maximum_asset_size_for_hash_check)) {
+ context.stage("Checking sound asset hash", file);
string reference_hash;
string calculated_hash;
- auto const r = verify_asset(dcp, reel_asset, progress, &reference_hash, &calculated_hash);
+ auto const r = verify_asset(context, reel_asset, &reference_hash, &calculated_hash);
switch (r) {
case VerifyAssetResult::BAD:
- notes.push_back(
+ context.add_note(
dcp::VerificationNote(
VerificationNote::Type::ERROR,
VerificationNote::Code::INCORRECT_SOUND_HASH,
@@ -643,58 +693,58 @@ verify_main_sound_asset (
);
break;
case VerifyAssetResult::CPL_PKL_DIFFER:
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_SOUND_HASHES, file});
+ context.error(VerificationNote::Code::MISMATCHED_SOUND_HASHES, file);
break;
default:
break;
}
}
- if (!state.audio_channels) {
- state.audio_channels = asset->channels();
- } else if (*state.audio_channels != asset->channels()) {
- notes.push_back({ VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS, file });
+ if (!context.audio_channels) {
+ context.audio_channels = asset->channels();
+ } else if (*context.audio_channels != asset->channels()) {
+ context.error(VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS, file);
}
- stage ("Checking sound asset metadata", file);
+ context.stage("Checking sound asset metadata", file);
if (auto lang = asset->language()) {
- verify_language_tag (*lang, notes);
+ verify_language_tag(context, *lang);
}
if (asset->sampling_rate() != 48000) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_SOUND_FRAME_RATE, raw_convert<string>(asset->sampling_rate()), file});
+ context.bv21_error(VerificationNote::Code::INVALID_SOUND_FRAME_RATE, raw_convert<string>(asset->sampling_rate()), file);
}
}
static void
-verify_main_subtitle_reel (shared_ptr<const ReelSubtitleAsset> reel_asset, vector<VerificationNote>& notes)
+verify_main_subtitle_reel(Context& context, shared_ptr<const ReelSubtitleAsset> reel_asset)
{
/* XXX: is Language compulsory? */
if (reel_asset->language()) {
- verify_language_tag (*reel_asset->language(), notes);
+ verify_language_tag(context, *reel_asset->language());
}
if (!reel_asset->entry_point()) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_SUBTITLE_ENTRY_POINT, reel_asset->id() });
+ context.bv21_error(VerificationNote::Code::MISSING_SUBTITLE_ENTRY_POINT, reel_asset->id());
} else if (reel_asset->entry_point().get()) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INCORRECT_SUBTITLE_ENTRY_POINT, reel_asset->id() });
+ context.bv21_error(VerificationNote::Code::INCORRECT_SUBTITLE_ENTRY_POINT, reel_asset->id());
}
}
static void
-verify_closed_caption_reel (shared_ptr<const ReelClosedCaptionAsset> reel_asset, vector<VerificationNote>& notes)
+verify_closed_caption_reel(Context& context, shared_ptr<const ReelClosedCaptionAsset> reel_asset)
{
/* XXX: is Language compulsory? */
if (reel_asset->language()) {
- verify_language_tag (*reel_asset->language(), notes);
+ verify_language_tag(context, *reel_asset->language());
}
if (!reel_asset->entry_point()) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_CLOSED_CAPTION_ENTRY_POINT, reel_asset->id() });
+ context.bv21_error(VerificationNote::Code::MISSING_CLOSED_CAPTION_ENTRY_POINT, reel_asset->id());
} else if (reel_asset->entry_point().get()) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ENTRY_POINT, reel_asset->id() });
+ context.bv21_error(VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ENTRY_POINT, reel_asset->id());
}
}
@@ -702,22 +752,20 @@ verify_closed_caption_reel (shared_ptr<const ReelClosedCaptionAsset> reel_asset,
/** Verify stuff that is common to both subtitles and closed captions */
void
verify_smpte_timed_text_asset (
+ Context& context,
shared_ptr<const SMPTESubtitleAsset> asset,
- optional<int64_t> reel_asset_duration,
- vector<VerificationNote>& notes
+ optional<int64_t> reel_asset_duration
)
{
if (asset->language()) {
- verify_language_tag (*asset->language(), notes);
+ verify_language_tag(context, *asset->language());
} else {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, *asset->file() });
+ context.bv21_error(VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, *asset->file());
}
auto const size = filesystem::file_size(asset->file().get());
if (size > 115 * 1024 * 1024) {
- notes.push_back (
- { VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, raw_convert<string>(size), *asset->file() }
- );
+ context.bv21_error(VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, raw_convert<string>(size), *asset->file());
}
/* XXX: I'm not sure what Bv2.1_7.2.1 means when it says "the font resource shall not be larger than 10MB"
@@ -729,54 +777,48 @@ verify_smpte_timed_text_asset (
total_size += i.second.size();
}
if (total_size > 10 * 1024 * 1024) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, raw_convert<string>(total_size), asset->file().get() });
+ context.bv21_error(VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, raw_convert<string>(total_size), asset->file().get());
}
if (!asset->start_time()) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_SUBTITLE_START_TIME, asset->file().get() });
+ context.bv21_error(VerificationNote::Code::MISSING_SUBTITLE_START_TIME, asset->file().get());
} else if (asset->start_time() != Time()) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_SUBTITLE_START_TIME, asset->file().get() });
+ context.bv21_error(VerificationNote::Code::INVALID_SUBTITLE_START_TIME, asset->file().get());
}
if (reel_asset_duration && *reel_asset_duration != asset->intrinsic_duration()) {
- notes.push_back (
- {
- VerificationNote::Type::BV21_ERROR,
- VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION,
- String::compose("%1 %2", *reel_asset_duration, asset->intrinsic_duration()),
- asset->file().get()
- });
+ context.bv21_error(
+ VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION,
+ String::compose("%1 %2", *reel_asset_duration, asset->intrinsic_duration()),
+ asset->file().get()
+ );
}
}
/** Verify Interop subtitle / CCAP stuff */
void
-verify_interop_text_asset(shared_ptr<const InteropSubtitleAsset> asset, vector<VerificationNote>& notes)
+verify_interop_text_asset(Context& context, shared_ptr<const InteropSubtitleAsset> asset)
{
if (asset->subtitles().empty()) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_SUBTITLE, asset->id(), asset->file().get() });
+ context.error(VerificationNote::Code::MISSING_SUBTITLE, asset->id(), asset->file().get());
}
auto const unresolved = asset->unresolved_fonts();
if (!unresolved.empty()) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_FONT, unresolved.front() });
+ context.error(VerificationNote::Code::MISSING_FONT, unresolved.front());
}
}
/** Verify SMPTE subtitle-only stuff */
void
-verify_smpte_subtitle_asset (
- shared_ptr<const SMPTESubtitleAsset> asset,
- vector<VerificationNote>& notes,
- State& state
- )
+verify_smpte_subtitle_asset(Context& context, shared_ptr<const SMPTESubtitleAsset> asset)
{
if (asset->language()) {
- if (!state.subtitle_language) {
- state.subtitle_language = *asset->language();
- } else if (state.subtitle_language != *asset->language()) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISMATCHED_SUBTITLE_LANGUAGES });
+ if (!context.subtitle_language) {
+ context.subtitle_language = *asset->language();
+ } else if (context.subtitle_language != *asset->language()) {
+ context.bv21_error(VerificationNote::Code::MISMATCHED_SUBTITLE_LANGUAGES);
}
}
@@ -784,14 +826,14 @@ verify_smpte_subtitle_asset (
auto xml_id = asset->xml_id();
if (xml_id) {
if (asset->resource_id().get() != xml_id) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISMATCHED_TIMED_TEXT_RESOURCE_ID });
+ context.bv21_error(VerificationNote::Code::MISMATCHED_TIMED_TEXT_RESOURCE_ID);
}
if (asset->id() == asset->resource_id().get() || asset->id() == xml_id) {
- notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID });
+ context.bv21_error(VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID);
}
} else {
- notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ context.warning(VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED);
}
if (asset->raw_xml()) {
@@ -801,7 +843,7 @@ verify_smpte_subtitle_asset (
auto issue_date = doc.string_child("IssueDate");
std::regex reg("^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d$");
if (!std::regex_match(issue_date, reg)) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, issue_date});
+ context.warning(VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, issue_date);
}
}
}
@@ -809,23 +851,16 @@ verify_smpte_subtitle_asset (
/** Verify all subtitle stuff */
static void
-verify_subtitle_asset (
- shared_ptr<const SubtitleAsset> asset,
- optional<int64_t> reel_asset_duration,
- function<void (string, optional<boost::filesystem::path>)> stage,
- boost::filesystem::path xsd_dtd_directory,
- vector<VerificationNote>& notes,
- State& state
- )
+verify_subtitle_asset(Context& context, shared_ptr<const SubtitleAsset> asset, optional<int64_t> reel_asset_duration)
{
- stage ("Checking subtitle XML", asset->file());
+ context.stage("Checking subtitle XML", asset->file());
/* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk
* gets passed through libdcp which may clean up and therefore hide errors.
*/
if (asset->raw_xml()) {
- validate_xml (asset->raw_xml().get(), xsd_dtd_directory, notes);
+ validate_xml(context, asset->raw_xml().get());
} else {
- notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ context.warning(VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED);
}
auto namespace_count = [](shared_ptr<const SubtitleAsset> asset, string root_node) {
@@ -841,19 +876,19 @@ verify_subtitle_asset (
auto interop = dynamic_pointer_cast<const InteropSubtitleAsset>(asset);
if (interop) {
- verify_interop_text_asset(interop, notes);
+ verify_interop_text_asset(context, interop);
if (namespace_count(asset, "DCSubtitle") > 1) {
- notes.push_back({ VerificationNote::Type::WARNING, VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id() });
+ context.warning(VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id());
}
}
auto smpte = dynamic_pointer_cast<const SMPTESubtitleAsset>(asset);
if (smpte) {
- verify_smpte_timed_text_asset (smpte, reel_asset_duration, notes);
- verify_smpte_subtitle_asset (smpte, notes, state);
+ verify_smpte_timed_text_asset(context, smpte, reel_asset_duration);
+ verify_smpte_subtitle_asset(context, smpte);
/* This asset may be encrypted and in that case we'll have no raw_xml() */
if (asset->raw_xml() && namespace_count(asset, "SubtitleReel") > 1) {
- notes.push_back({ VerificationNote::Type::WARNING, VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id()});
+ context.warning(VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id());
}
}
}
@@ -862,35 +897,33 @@ verify_subtitle_asset (
/** Verify all closed caption stuff */
static void
verify_closed_caption_asset (
+ Context& context,
shared_ptr<const SubtitleAsset> asset,
- optional<int64_t> reel_asset_duration,
- function<void (string, optional<boost::filesystem::path>)> stage,
- boost::filesystem::path xsd_dtd_directory,
- vector<VerificationNote>& notes
+ optional<int64_t> reel_asset_duration
)
{
- stage ("Checking closed caption XML", asset->file());
+ context.stage("Checking closed caption XML", asset->file());
/* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk
* gets passed through libdcp which may clean up and therefore hide errors.
*/
auto raw_xml = asset->raw_xml();
if (raw_xml) {
- validate_xml (*raw_xml, xsd_dtd_directory, notes);
+ validate_xml(context, *raw_xml);
if (raw_xml->size() > 256 * 1024) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, raw_convert<string>(raw_xml->size()), *asset->file()});
+ context.bv21_error(VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, raw_convert<string>(raw_xml->size()), *asset->file());
}
} else {
- notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ context.warning(VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED);
}
auto interop = dynamic_pointer_cast<const InteropSubtitleAsset>(asset);
if (interop) {
- verify_interop_text_asset(interop, notes);
+ verify_interop_text_asset(context, interop);
}
auto smpte = dynamic_pointer_cast<const SMPTESubtitleAsset>(asset);
if (smpte) {
- verify_smpte_timed_text_asset (smpte, reel_asset_duration, notes);
+ verify_smpte_timed_text_asset(context, smpte, reel_asset_duration);
}
}
@@ -899,10 +932,9 @@ verify_closed_caption_asset (
static
void
verify_text_details (
- dcp::Standard standard,
+ Context& context,
vector<shared_ptr<Reel>> reels,
int edit_rate,
- vector<VerificationNote>& notes,
std::function<bool (shared_ptr<Reel>)> check,
std::function<optional<string> (shared_ptr<Reel>)> xml,
std::function<int64_t (shared_ptr<Reel>)> duration,
@@ -996,7 +1028,7 @@ verify_text_details (
auto reel_xml = xml(reels[i]);
if (!reel_xml) {
- notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ context.warning(VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED);
continue;
}
@@ -1007,7 +1039,7 @@ verify_text_details (
shared_ptr<cxml::Document> doc;
optional<int> tcr;
optional<Time> start_time;
- switch (standard) {
+ switch (context.dcp->standard().get_value_or(dcp::Standard::SMPTE)) {
case dcp::Standard::INTEROP:
doc = make_shared<cxml::Document>("DCSubtitle");
doc->read_string (*reel_xml);
@@ -1030,8 +1062,8 @@ verify_text_details (
}
reel_offset = end;
- if (standard == dcp::Standard::SMPTE && has_text && font_ids.empty()) {
- notes.push_back(dcp::VerificationNote(dcp::VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_LOAD_FONT).set_id(id(reels[i])));
+ if (context.dcp->standard() && *context.dcp->standard() == dcp::Standard::SMPTE && has_text && font_ids.empty()) {
+ context.add_note(dcp::VerificationNote(dcp::VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_LOAD_FONT).set_id(id(reels[i])));
}
}
@@ -1040,47 +1072,34 @@ verify_text_details (
}
if (too_early) {
- notes.push_back({
- VerificationNote::Type::WARNING, VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
- });
+ context.warning(VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME);
}
if (too_short) {
- notes.push_back ({
- VerificationNote::Type::WARNING, VerificationNote::Code::INVALID_SUBTITLE_DURATION
- });
+ context.warning(VerificationNote::Code::INVALID_SUBTITLE_DURATION);
}
if (too_close) {
- notes.push_back ({
- VerificationNote::Type::WARNING, VerificationNote::Code::INVALID_SUBTITLE_SPACING
- });
+ context.warning(VerificationNote::Code::INVALID_SUBTITLE_SPACING);
}
if (reel_overlap) {
- notes.push_back ({
- VerificationNote::Type::ERROR, VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY
- });
+ context.error(VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY);
}
if (empty_text) {
- notes.push_back ({
- VerificationNote::Type::WARNING, VerificationNote::Code::EMPTY_TEXT
- });
+ context.warning(VerificationNote::Code::EMPTY_TEXT);
}
if (missing_load_font_id) {
- notes.push_back(dcp::VerificationNote(VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_LOAD_FONT_FOR_FONT).set_id(*missing_load_font_id));
+ context.add_note(dcp::VerificationNote(VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_LOAD_FONT_FOR_FONT).set_id(*missing_load_font_id));
}
}
static
void
-verify_closed_caption_details (
- vector<shared_ptr<Reel>> reels,
- vector<VerificationNote>& notes
- )
+verify_closed_caption_details(Context& context, vector<shared_ptr<Reel>> reels)
{
std::function<void (cxml::ConstNodePtr node, std::vector<cxml::ConstNodePtr>& text_or_image)> find_text_or_image;
find_text_or_image = [&find_text_or_image](cxml::ConstNodePtr node, std::vector<cxml::ConstNodePtr>& text_or_image) {
@@ -1146,7 +1165,7 @@ verify_closed_caption_details (
for (auto ccap: reel->closed_captions()) {
auto reel_xml = ccap->asset()->raw_xml();
if (!reel_xml) {
- notes.push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED});
+ context.warning(VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED);
continue;
}
@@ -1169,15 +1188,11 @@ verify_closed_caption_details (
}
if (mismatched_valign) {
- notes.push_back ({
- VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_VALIGN,
- });
+ context.error(VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_VALIGN);
}
if (incorrect_order) {
- notes.push_back ({
- VerificationNote::Type::ERROR, VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ORDERING,
- });
+ context.error(VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ORDERING);
}
}
@@ -1283,14 +1298,14 @@ verify_text_lines_and_characters (
static
void
-verify_text_details(dcp::Standard standard, vector<shared_ptr<Reel>> reels, vector<VerificationNote>& notes)
+verify_text_details(Context& context, vector<shared_ptr<Reel>> reels)
{
if (reels.empty()) {
return;
}
if (reels[0]->main_subtitle() && reels[0]->main_subtitle()->asset_ref().resolved()) {
- verify_text_details(standard, reels, reels[0]->main_subtitle()->edit_rate().numerator, notes,
+ verify_text_details(context, reels, reels[0]->main_subtitle()->edit_rate().numerator,
[](shared_ptr<Reel> reel) {
return static_cast<bool>(reel->main_subtitle());
},
@@ -1307,7 +1322,7 @@ verify_text_details(dcp::Standard standard, vector<shared_ptr<Reel>> reels, vect
}
for (auto i = 0U; i < reels[0]->closed_captions().size(); ++i) {
- verify_text_details(standard, reels, reels[0]->closed_captions()[i]->edit_rate().numerator, notes,
+ verify_text_details(context, reels, reels[0]->closed_captions()[i]->edit_rate().numerator,
[i](shared_ptr<Reel> reel) {
return i < reel->closed_captions().size();
},
@@ -1323,12 +1338,12 @@ verify_text_details(dcp::Standard standard, vector<shared_ptr<Reel>> reels, vect
);
}
- verify_closed_caption_details (reels, notes);
+ verify_closed_caption_details(context, reels);
}
void
-verify_extension_metadata(shared_ptr<const CPL> cpl, vector<VerificationNote>& notes)
+verify_extension_metadata(Context& context, shared_ptr<const CPL> cpl)
{
DCP_ASSERT (cpl->file());
cxml::Document doc ("CompositionPlaylist");
@@ -1378,9 +1393,9 @@ verify_extension_metadata(shared_ptr<const CPL> cpl, vector<VerificationNote>& n
}
if (missing) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_EXTENSION_METADATA, cpl->id(), cpl->file().get()});
+ context.bv21_error(VerificationNote::Code::MISSING_EXTENSION_METADATA, cpl->file().get());
} else if (!malformed.empty()) {
- notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_EXTENSION_METADATA, malformed, cpl->file().get()});
+ context.bv21_error(VerificationNote::Code::INVALID_EXTENSION_METADATA, malformed, cpl->file().get());
}
}
@@ -1413,17 +1428,10 @@ pkl_has_encrypted_assets(shared_ptr<const DCP> dcp, shared_ptr<const PKL> pkl)
static
void
verify_reel(
- shared_ptr<const DCP> dcp,
- shared_ptr<const CPL> cpl,
+ Context& context,
shared_ptr<const Reel> reel,
int64_t start_frame,
optional<dcp::Size> main_picture_active_area,
- function<void (string, optional<boost::filesystem::path>)> stage,
- boost::filesystem::path xsd_dtd_directory,
- function<void (float)> progress,
- VerificationOptions options,
- vector<VerificationNote>& notes,
- State& state,
bool* have_main_subtitle,
bool* have_no_main_subtitle,
size_t* most_closed_captions,
@@ -1433,24 +1441,24 @@ verify_reel(
{
for (auto i: reel->assets()) {
if (i->duration() && (i->duration().get() * i->edit_rate().denominator / i->edit_rate().numerator) < 1) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::INVALID_DURATION, i->id()});
+ context.error(VerificationNote::Code::INVALID_DURATION, i->id());
}
if ((i->intrinsic_duration() * i->edit_rate().denominator / i->edit_rate().numerator) < 1) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::INVALID_INTRINSIC_DURATION, i->id()});
+ context.error(VerificationNote::Code::INVALID_INTRINSIC_DURATION, i->id());
}
auto file_asset = dynamic_pointer_cast<ReelFileAsset>(i);
if (i->encryptable() && !file_asset->hash()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_HASH, i->id()});
+ context.bv21_error(VerificationNote::Code::MISSING_HASH, i->id());
}
}
- if (dcp->standard() == Standard::SMPTE) {
+ if (context.dcp->standard() == Standard::SMPTE) {
boost::optional<int64_t> duration;
for (auto i: reel->assets()) {
if (!duration) {
duration = i->actual_duration();
} else if (*duration != i->actual_duration()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISMATCHED_ASSET_DURATION});
+ context.bv21_error(VerificationNote::Code::MISMATCHED_ASSET_DURATION);
break;
}
}
@@ -1467,32 +1475,26 @@ verify_reel(
frame_rate.numerator != 50 &&
frame_rate.numerator != 60 &&
frame_rate.numerator != 96)) {
- notes.push_back({
- VerificationNote::Type::ERROR,
- VerificationNote::Code::INVALID_PICTURE_FRAME_RATE,
- String::compose("%1/%2", frame_rate.numerator, frame_rate.denominator)
- });
+ context.error(VerificationNote::Code::INVALID_PICTURE_FRAME_RATE, String::compose("%1/%2", frame_rate.numerator, frame_rate.denominator));
}
/* Check asset */
if (reel->main_picture()->asset_ref().resolved()) {
- verify_main_picture_asset(dcp, reel->main_picture(), start_frame, stage, progress, options, notes);
+ verify_main_picture_asset(context, reel->main_picture(), start_frame);
auto const asset_size = reel->main_picture()->asset()->size();
if (main_picture_active_area) {
if (main_picture_active_area->width > asset_size.width) {
- notes.push_back({
- VerificationNote::Type::ERROR,
- VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
- String::compose("width %1 is bigger than the asset width %2", main_picture_active_area->width, asset_size.width),
- cpl->file().get()
- });
+ context.error(
+ VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
+ String::compose("width %1 is bigger than the asset width %2", main_picture_active_area->width, asset_size.width),
+ context.cpl->file().get()
+ );
}
if (main_picture_active_area->height > asset_size.height) {
- notes.push_back({
- VerificationNote::Type::ERROR,
- VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
- String::compose("height %1 is bigger than the asset height %2", main_picture_active_area->height, asset_size.height),
- cpl->file().get()
- });
+ context.error(
+ VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
+ String::compose("height %1 is bigger than the asset height %2", main_picture_active_area->height, asset_size.height),
+ context.cpl->file().get()
+ );
}
}
}
@@ -1500,13 +1502,13 @@ verify_reel(
}
if (reel->main_sound() && reel->main_sound()->asset_ref().resolved()) {
- verify_main_sound_asset(dcp, reel->main_sound(), stage, progress, options, notes, state);
+ verify_main_sound_asset(context, reel->main_sound());
}
if (reel->main_subtitle()) {
- verify_main_subtitle_reel(reel->main_subtitle(), notes);
+ verify_main_subtitle_reel(context, reel->main_subtitle());
if (reel->main_subtitle()->asset_ref().resolved()) {
- verify_subtitle_asset(reel->main_subtitle()->asset(), reel->main_subtitle()->duration(), stage, xsd_dtd_directory, notes, state);
+ verify_subtitle_asset(context, reel->main_subtitle()->asset(), reel->main_subtitle()->duration());
}
*have_main_subtitle = true;
} else {
@@ -1514,9 +1516,9 @@ verify_reel(
}
for (auto i: reel->closed_captions()) {
- verify_closed_caption_reel(i, notes);
+ verify_closed_caption_reel(context, i);
if (i->asset_ref().resolved()) {
- verify_closed_caption_asset(i->asset(), i->duration(), stage, xsd_dtd_directory, notes);
+ verify_closed_caption_asset(context, i->asset(), i->duration());
}
}
@@ -1525,10 +1527,10 @@ verify_reel(
markers_seen->insert(i);
}
if (reel->main_markers()->entry_point()) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::UNEXPECTED_ENTRY_POINT});
+ context.error(VerificationNote::Code::UNEXPECTED_ENTRY_POINT);
}
if (reel->main_markers()->duration()) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::UNEXPECTED_DURATION});
+ context.error(VerificationNote::Code::UNEXPECTED_DURATION);
}
}
@@ -1540,26 +1542,21 @@ verify_reel(
static
void
-verify_cpl(
- shared_ptr<const DCP> dcp,
- shared_ptr<const CPL> cpl,
- function<void (string, optional<boost::filesystem::path>)> stage,
- boost::filesystem::path xsd_dtd_directory,
- function<void (float)> progress,
- VerificationOptions options,
- vector<VerificationNote>& notes,
- State& state
- )
+verify_cpl(Context& context, shared_ptr<const CPL> cpl)
{
- stage("Checking CPL", cpl->file());
- validate_xml(cpl->file().get(), xsd_dtd_directory, notes);
+ context.stage("Checking CPL", cpl->file());
+ validate_xml(context, cpl->file().get());
if (cpl->any_encrypted() && !cpl->all_encrypted()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::PARTIALLY_ENCRYPTED});
+ context.bv21_error(VerificationNote::Code::PARTIALLY_ENCRYPTED);
+ } else if (cpl->all_encrypted()) {
+ context.ok(VerificationNote::Code::ALL_ENCRYPTED);
+ } else if (!cpl->all_encrypted()) {
+ context.ok(VerificationNote::Code::NONE_ENCRYPTED);
}
for (auto const& i: cpl->additional_subtitle_languages()) {
- verify_language_tag(i, notes);
+ verify_language_tag(context, i);
}
if (!cpl->content_kind().scope() || *cpl->content_kind().scope() == "http://www.smpte-ra.org/schemas/429-7/2006/CPL#standard-content") {
@@ -1571,61 +1568,71 @@ verify_cpl(
transform(name.begin(), name.end(), name.begin(), ::tolower);
auto iter = std::find_if(all.begin(), all.end(), [name](ContentKind const& k) { return !k.scope() && k.name() == name; });
if (iter == all.end()) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::INVALID_CONTENT_KIND, cpl->content_kind().name()});
+ context.error(VerificationNote::Code::INVALID_CONTENT_KIND, cpl->content_kind().name());
+ } else {
+ context.ok(VerificationNote::Code::VALID_CONTENT_KIND, cpl->content_kind().name());
}
}
if (cpl->release_territory()) {
if (!cpl->release_territory_scope() || cpl->release_territory_scope().get() != "http://www.smpte-ra.org/schemas/429-16/2014/CPL-Metadata#scope/release-territory/UNM49") {
auto terr = cpl->release_territory().get();
+ bool valid = true;
/* Must be a valid region tag, or "001" */
try {
LanguageTag::RegionSubtag test(terr);
} catch (...) {
if (terr != "001") {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_LANGUAGE, terr});
+ context.bv21_error(VerificationNote::Code::INVALID_LANGUAGE, terr);
+ valid = false;
}
}
+ if (valid) {
+ context.ok(VerificationNote::Code::VALID_RELEASE_TERRITORY, terr);
+ }
}
}
for (auto version: cpl->content_versions()) {
if (version.label_text.empty()) {
- notes.push_back(
- dcp::VerificationNote(VerificationNote::Type::WARNING, VerificationNote::Code::EMPTY_CONTENT_VERSION_LABEL_TEXT, cpl->file().get()).set_id(cpl->id())
- );
+ context.warning(VerificationNote::Code::EMPTY_CONTENT_VERSION_LABEL_TEXT, cpl->file().get());
break;
+ } else {
+ context.ok(VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, version.label_text);
}
}
- if (dcp->standard() == Standard::SMPTE) {
+ if (context.dcp->standard() == Standard::SMPTE) {
if (!cpl->annotation_text()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_CPL_ANNOTATION_TEXT, cpl->id(), cpl->file().get()});
+ context.bv21_error(VerificationNote::Code::MISSING_CPL_ANNOTATION_TEXT, cpl->file().get());
} else if (cpl->annotation_text().get() != cpl->content_title_text()) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::MISMATCHED_CPL_ANNOTATION_TEXT, cpl->id(), cpl->file().get()});
+ context.warning(VerificationNote::Code::MISMATCHED_CPL_ANNOTATION_TEXT, cpl->file().get());
+ } else {
+ context.ok(VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, cpl->annotation_text().get());
}
}
- for (auto i: dcp->pkls()) {
+ for (auto i: context.dcp->pkls()) {
/* Check that the CPL's hash corresponds to the PKL */
optional<string> h = i->hash(cpl->id());
auto calculated_cpl_hash = make_digest(ArrayData(*cpl->file()));
if (h && calculated_cpl_hash != *h) {
- notes.push_back(
+ context.add_note(
dcp::VerificationNote(
VerificationNote::Type::ERROR,
VerificationNote::Code::MISMATCHED_CPL_HASHES,
- cpl->id(),
cpl->file().get()
).set_calculated_hash(calculated_cpl_hash).set_reference_hash(*h)
);
+ } else {
+ context.ok(VerificationNote::Code::MATCHING_CPL_HASHES);
}
/* Check that any PKL with a single CPL has its AnnotationText the same as the CPL's ContentTitleText */
optional<string> required_annotation_text;
for (auto j: i->assets()) {
/* See if this is a CPL */
- for (auto k: dcp->cpls()) {
+ for (auto k: context.dcp->cpls()) {
if (j->id() == k->id()) {
if (!required_annotation_text) {
/* First CPL we have found; this is the required AnnotationText unless we find another */
@@ -1639,7 +1646,9 @@ verify_cpl(
}
if (required_annotation_text && i->annotation_text() != required_annotation_text) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, i->id(), i->file().get()});
+ context.bv21_error(VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, i->id(), i->file().get());
+ } else {
+ context.ok(VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL);
}
}
@@ -1654,38 +1663,39 @@ verify_cpl(
map<Marker, Time> markers_seen;
auto const main_picture_active_area = cpl->main_picture_active_area();
+ bool active_area_ok = true;
if (main_picture_active_area && (main_picture_active_area->width % 2)) {
- notes.push_back({
- VerificationNote::Type::ERROR,
- VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
- String::compose("width %1 is not a multiple of 2", main_picture_active_area->width),
- cpl->file().get()
- });
+ context.error(
+ VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
+ String::compose("width %1 is not a multiple of 2", main_picture_active_area->width),
+ cpl->file().get()
+ );
+ active_area_ok = false;
}
if (main_picture_active_area && (main_picture_active_area->height % 2)) {
- notes.push_back({
- VerificationNote::Type::ERROR,
- VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
- String::compose("height %1 is not a multiple of 2", main_picture_active_area->height),
- cpl->file().get()
- });
+ context.error(
+ VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA,
+ String::compose("height %1 is not a multiple of 2", main_picture_active_area->height),
+ cpl->file().get()
+ );
+ active_area_ok = false;
+ }
+
+ if (main_picture_active_area && active_area_ok) {
+ context.ok(
+ VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA, String::compose("%1x%2", main_picture_active_area->width, main_picture_active_area->height),
+ cpl->file().get()
+ );
}
int64_t frame = 0;
for (auto reel: cpl->reels()) {
- stage("Checking reel", optional<boost::filesystem::path>());
+ context.stage("Checking reel", optional<boost::filesystem::path>());
verify_reel(
- dcp,
- cpl,
+ context,
reel,
frame,
main_picture_active_area,
- stage,
- xsd_dtd_directory,
- progress,
- options,
- notes,
- state,
&have_main_subtitle,
&have_no_main_subtitle,
&most_closed_captions,
@@ -1695,51 +1705,50 @@ verify_cpl(
frame += reel->duration();
}
- verify_text_details(dcp->standard().get_value_or(dcp::Standard::SMPTE), cpl->reels(), notes);
+ verify_text_details(context, cpl->reels());
- if (dcp->standard() == Standard::SMPTE) {
+ if (context.dcp->standard() == Standard::SMPTE) {
if (auto msc = cpl->main_sound_configuration()) {
- if (state.audio_channels && msc->channels() != *state.audio_channels) {
- notes.push_back({
- VerificationNote::Type::ERROR,
- VerificationNote::Code::INVALID_MAIN_SOUND_CONFIGURATION,
- String::compose("MainSoundConfiguration has %1 channels but sound assets have %2", msc->channels(), *state.audio_channels),
- cpl->file().get()
- });
+ if (context.audio_channels && msc->channels() != *context.audio_channels) {
+ context.error(
+ VerificationNote::Code::INVALID_MAIN_SOUND_CONFIGURATION,
+ String::compose("MainSoundConfiguration has %1 channels but sound assets have %2", msc->channels(), *context.audio_channels),
+ cpl->file().get()
+ );
}
}
if (have_main_subtitle && have_no_main_subtitle) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS});
+ context.bv21_error(VerificationNote::Code::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS);
}
if (fewest_closed_captions != most_closed_captions) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS});
+ context.bv21_error(VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS);
}
if (cpl->content_kind() == ContentKind::FEATURE) {
if (markers_seen.find(Marker::FFEC) == markers_seen.end()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_FFEC_IN_FEATURE});
+ context.bv21_error(VerificationNote::Code::MISSING_FFEC_IN_FEATURE);
}
if (markers_seen.find(Marker::FFMC) == markers_seen.end()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_FFMC_IN_FEATURE});
+ context.bv21_error(VerificationNote::Code::MISSING_FFMC_IN_FEATURE);
}
}
auto ffoc = markers_seen.find(Marker::FFOC);
if (ffoc == markers_seen.end()) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::MISSING_FFOC});
+ context.warning(VerificationNote::Code::MISSING_FFOC);
} else if (ffoc->second.e != 1) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::INCORRECT_FFOC, raw_convert<string>(ffoc->second.e)});
+ context.warning(VerificationNote::Code::INCORRECT_FFOC, raw_convert<string>(ffoc->second.e));
}
auto lfoc = markers_seen.find(Marker::LFOC);
if (lfoc == markers_seen.end()) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::MISSING_LFOC});
+ context.warning(VerificationNote::Code::MISSING_LFOC);
} else {
auto lfoc_time = lfoc->second.as_editable_units_ceil(lfoc->second.tcr);
if (lfoc_time != (cpl->reels().back()->duration() - 1)) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::INCORRECT_LFOC, raw_convert<string>(lfoc_time)});
+ context.warning(VerificationNote::Code::INCORRECT_LFOC, raw_convert<string>(lfoc_time));
}
}
@@ -1751,12 +1760,12 @@ verify_cpl(
}
if (result.line_count_exceeded) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::INVALID_SUBTITLE_LINE_COUNT});
+ context.warning(VerificationNote::Code::INVALID_SUBTITLE_LINE_COUNT);
}
if (result.error_length_exceeded) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::INVALID_SUBTITLE_LINE_LENGTH});
+ context.warning(VerificationNote::Code::INVALID_SUBTITLE_LINE_LENGTH);
} else if (result.warning_length_exceeded) {
- notes.push_back({VerificationNote::Type::WARNING, VerificationNote::Code::NEARLY_INVALID_SUBTITLE_LINE_LENGTH});
+ context.warning(VerificationNote::Code::NEARLY_INVALID_SUBTITLE_LINE_LENGTH);
}
result = LinesCharactersResult();
@@ -1769,26 +1778,26 @@ verify_cpl(
}
if (result.line_count_exceeded) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_COUNT});
+ context.bv21_error(VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_COUNT);
}
if (result.error_length_exceeded) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_LENGTH});
+ context.bv21_error(VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_LENGTH);
}
if (!cpl->read_composition_metadata()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get()});
+ context.bv21_error(VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get());
} else if (!cpl->version_number()) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::MISSING_CPL_METADATA_VERSION_NUMBER, cpl->id(), cpl->file().get()});
+ context.bv21_error(VerificationNote::Code::MISSING_CPL_METADATA_VERSION_NUMBER, cpl->file().get());
}
- verify_extension_metadata(cpl, notes);
+ verify_extension_metadata(context, cpl);
if (cpl->any_encrypted()) {
cxml::Document doc("CompositionPlaylist");
DCP_ASSERT(cpl->file());
doc.read_file(dcp::filesystem::fix_long_path(cpl->file().get()));
if (!doc.optional_node_child("Signature")) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, cpl->id(), cpl->file().get()});
+ context.bv21_error(VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, cpl->file().get());
}
}
}
@@ -1797,27 +1806,22 @@ verify_cpl(
static
void
-verify_pkl(
- shared_ptr<const DCP> dcp,
- shared_ptr<const PKL> pkl,
- boost::filesystem::path xsd_dtd_directory,
- vector<VerificationNote>& notes
- )
+verify_pkl(Context& context, shared_ptr<const PKL> pkl)
{
- validate_xml(pkl->file().get(), xsd_dtd_directory, notes);
+ validate_xml(context, pkl->file().get());
- if (pkl_has_encrypted_assets(dcp, pkl)) {
+ if (pkl_has_encrypted_assets(context.dcp, pkl)) {
cxml::Document doc("PackingList");
doc.read_file(dcp::filesystem::fix_long_path(pkl->file().get()));
if (!doc.optional_node_child("Signature")) {
- notes.push_back({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, pkl->id(), pkl->file().get()});
+ context.bv21_error(VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, pkl->id(), pkl->file().get());
}
}
set<string> uuid_set;
for (auto asset: pkl->assets()) {
if (!uuid_set.insert(asset->id()).second) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL, pkl->id(), pkl->file().get()});
+ context.error(VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL, pkl->id(), pkl->file().get());
break;
}
}
@@ -1827,28 +1831,24 @@ verify_pkl(
static
void
-verify_assetmap(
- shared_ptr<const DCP> dcp,
- boost::filesystem::path xsd_dtd_directory,
- vector<VerificationNote>& notes
- )
+verify_assetmap(Context& context, shared_ptr<const DCP> dcp)
{
auto asset_map = dcp->asset_map();
DCP_ASSERT(asset_map);
- validate_xml(asset_map->file().get(), xsd_dtd_directory, notes);
+ validate_xml(context, asset_map->file().get());
set<string> uuid_set;
for (auto const& asset: asset_map->assets()) {
if (!uuid_set.insert(asset.id()).second) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::DUPLICATE_ASSET_ID_IN_ASSETMAP, asset_map->id(), asset_map->file().get()});
+ context.error(VerificationNote::Code::DUPLICATE_ASSET_ID_IN_ASSETMAP, asset_map->id(), asset_map->file().get());
break;
}
}
}
-vector<VerificationNote>
+dcp::VerificationResult
dcp::verify (
vector<boost::filesystem::path> directories,
vector<dcp::DecryptedKDM> kdms,
@@ -1864,7 +1864,7 @@ dcp::verify (
*xsd_dtd_directory = filesystem::canonical(*xsd_dtd_directory);
vector<VerificationNote> notes;
- State state{};
+ Context context(notes, *xsd_dtd_directory, stage, progress, options);
vector<shared_ptr<DCP>> dcps;
for (auto i: directories) {
@@ -1873,22 +1873,25 @@ dcp::verify (
for (auto dcp: dcps) {
stage ("Checking DCP", dcp->directory());
+
+ context.dcp = dcp;
+
bool carry_on = true;
try {
dcp->read (&notes, true);
} catch (MissingAssetmapError& e) {
- notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
+ context.error(VerificationNote::Code::FAILED_READ, string(e.what()));
carry_on = false;
} catch (ReadError& e) {
- notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
+ context.error(VerificationNote::Code::FAILED_READ, string(e.what()));
} catch (XMLError& e) {
- notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
+ context.error(VerificationNote::Code::FAILED_READ, string(e.what()));
} catch (MXFFileError& e) {
- notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
+ context.error(VerificationNote::Code::FAILED_READ, string(e.what()));
} catch (BadURNUUIDError& e) {
- notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
+ context.error(VerificationNote::Code::FAILED_READ, string(e.what()));
} catch (cxml::Error& e) {
- notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
+ context.error(VerificationNote::Code::FAILED_READ, string(e.what()));
}
if (!carry_on) {
@@ -1905,16 +1908,9 @@ dcp::verify (
for (auto cpl: dcp->cpls()) {
try {
- verify_cpl(
- dcp,
- cpl,
- stage,
- *xsd_dtd_directory,
- progress,
- options,
- notes,
- state
- );
+ context.cpl = cpl;
+ verify_cpl(context, cpl);
+ context.cpl.reset();
} catch (ReadError& e) {
notes.push_back({VerificationNote::Type::ERROR, VerificationNote::Code::FAILED_READ, string(e.what())});
}
@@ -1922,23 +1918,23 @@ dcp::verify (
for (auto pkl: dcp->pkls()) {
stage("Checking PKL", pkl->file());
- verify_pkl(dcp, pkl, *xsd_dtd_directory, notes);
+ verify_pkl(context, pkl);
}
if (dcp->asset_map_file()) {
stage("Checking ASSETMAP", dcp->asset_map_file().get());
- verify_assetmap(dcp, *xsd_dtd_directory, notes);
+ verify_assetmap(context, dcp);
} else {
- notes.push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_ASSETMAP});
+ context.error(VerificationNote::Code::MISSING_ASSETMAP);
}
}
- return notes;
+ return { notes, dcps };
}
string
-dcp::note_to_string (VerificationNote note)
+dcp::note_to_string(VerificationNote note, function<string (string)> process_string, function<string (string)> process_filename)
{
/** These strings should say what is wrong, incorporating any extra details (ID, filenames etc.).
*
@@ -1950,238 +1946,267 @@ dcp::note_to_string (VerificationNote note)
* End messages with a full stop.
* Messages should not mention whether or not their errors are a part of Bv2.1.
*/
+
+ auto filename = [note, process_filename]() {
+ return process_filename(note.file()->filename().string());
+ };
+
+#define compose(format, ...) String::compose(process_string(format), __VA_ARGS__)
+
switch (note.code()) {
case VerificationNote::Code::FAILED_READ:
- return *note.note();
+ return process_string(*note.note());
+ case VerificationNote::Code::MATCHING_CPL_HASHES:
+ return process_string("The hash of the CPL in the PKL matches the CPL file.");
case VerificationNote::Code::MISMATCHED_CPL_HASHES:
- return String::compose("The hash (%1) of the CPL (%2) in the PKL does not agree with the CPL file (%3).", note.reference_hash().get(), note.note().get(), note.calculated_hash().get());
+ return compose("The hash (%1) of the CPL (%2) in the PKL does not agree with the CPL file (%3).", note.reference_hash().get(), note.cpl_id().get(), note.calculated_hash().get());
case VerificationNote::Code::INVALID_PICTURE_FRAME_RATE:
- return String::compose("The picture in a reel has an invalid frame rate %1.", note.note().get());
+ return compose("The picture in a reel has an invalid frame rate %1.", note.note().get());
case VerificationNote::Code::INCORRECT_PICTURE_HASH:
- return String::compose("The hash (%1) of the picture asset %2 does not agree with the PKL file (%3).", note.calculated_hash().get(), note.file()->filename(), note.reference_hash().get());
+ return compose("The hash (%1) of the picture asset %2 does not agree with the PKL file (%3).", note.calculated_hash().get(), filename(), note.reference_hash().get());
+ case VerificationNote::Code::CORRECT_PICTURE_HASH:
+ return compose("The picture asset %1 has the expected hashes in the CPL and PKL.", filename());
case VerificationNote::Code::MISMATCHED_PICTURE_HASHES:
- return String::compose("The PKL and CPL hashes differ for the picture asset %1.", note.file()->filename());
+ return compose("The PKL and CPL hashes differ for the picture asset %1.", filename());
case VerificationNote::Code::INCORRECT_SOUND_HASH:
- return String::compose("The hash (%1) of the sound asset %2 does not agree with the PKL file (%3).", note.calculated_hash().get(), note.file()->filename(), note.reference_hash().get());
+ return compose("The hash (%1) of the sound asset %2 does not agree with the PKL file (%3).", note.calculated_hash().get(), filename(), note.reference_hash().get());
case VerificationNote::Code::MISMATCHED_SOUND_HASHES:
- return String::compose("The PKL and CPL hashes differ for the sound asset %1.", note.file()->filename());
+ return compose("The PKL and CPL hashes differ for the sound asset %1.", filename());
case VerificationNote::Code::EMPTY_ASSET_PATH:
- return "The asset map contains an empty asset path.";
+ return process_string("The asset map contains an empty asset path.");
case VerificationNote::Code::MISSING_ASSET:
- return String::compose("The file %1 for an asset in the asset map cannot be found.", note.file()->filename());
+ return compose("The file %1 for an asset in the asset map cannot be found.", filename());
case VerificationNote::Code::MISMATCHED_STANDARD:
- return "The DCP contains both SMPTE and Interop parts.";
+ return process_string("The DCP contains both SMPTE and Interop parts.");
case VerificationNote::Code::INVALID_XML:
- return String::compose("An XML file is badly formed: %1 (%2:%3)", note.note().get(), note.file()->filename(), note.line().get());
+ return compose("An XML file is badly formed: %1 (%2:%3)", note.note().get(), filename(), note.line().get());
case VerificationNote::Code::MISSING_ASSETMAP:
- return "No valid ASSETMAP or ASSETMAP.xml was found.";
+ return process_string("No valid ASSETMAP or ASSETMAP.xml was found.");
case VerificationNote::Code::INVALID_INTRINSIC_DURATION:
- return String::compose("The intrinsic duration of the asset %1 is less than 1 second.", note.note().get());
+ return compose("The intrinsic duration of the asset %1 is less than 1 second.", note.note().get());
case VerificationNote::Code::INVALID_DURATION:
- return String::compose("The duration of the asset %1 is less than 1 second.", note.note().get());
+ return compose("The duration of the asset %1 is less than 1 second.", note.note().get());
+ case VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES:
+ return compose("Each frame of the picture asset %1 has a bit rate safely under the limit of 250Mbit/s.", filename());
case VerificationNote::Code::INVALID_PICTURE_FRAME_SIZE_IN_BYTES:
- return String::compose(
+ return compose(
"Frame %1 (timecode %2) in asset %3 has an instantaneous bit rate that is larger than the limit of 250Mbit/s.",
note.frame().get(),
dcp::Time(note.frame().get(), note.frame_rate().get(), note.frame_rate().get()).as_string(dcp::Standard::SMPTE),
- note.file()->filename()
+ filename()
);
case VerificationNote::Code::NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES:
- return String::compose(
+ return compose(
"Frame %1 (timecode %2) in asset %3 has an instantaneous bit rate that is close to the limit of 250Mbit/s.",
note.frame().get(),
dcp::Time(note.frame().get(), note.frame_rate().get(), note.frame_rate().get()).as_string(dcp::Standard::SMPTE),
- note.file()->filename()
+ filename()
);
case VerificationNote::Code::EXTERNAL_ASSET:
- return String::compose("The asset %1 that this DCP refers to is not included in the DCP. It may be a VF.", note.note().get());
+ return compose("The asset %1 that this DCP refers to is not included in the DCP. It may be a VF.", note.note().get());
case VerificationNote::Code::THREED_ASSET_MARKED_AS_TWOD:
- return String::compose("The asset %1 is 3D but its MXF is marked as 2D.", note.file()->filename());
+ return compose("The asset %1 is 3D but its MXF is marked as 2D.", filename());
case VerificationNote::Code::INVALID_STANDARD:
return "This DCP does not use the SMPTE standard.";
case VerificationNote::Code::INVALID_LANGUAGE:
- return String::compose("The DCP specifies a language '%1' which does not conform to the RFC 5646 standard.", note.note().get());
+ return compose("The DCP specifies a language '%1' which does not conform to the RFC 5646 standard.", note.note().get());
+ case VerificationNote::Code::VALID_RELEASE_TERRITORY:
+ return compose("Valid release territory %1.", note.note().get());
case VerificationNote::Code::INVALID_PICTURE_SIZE_IN_PIXELS:
- return String::compose("The size %1 of picture asset %2 is not allowed.", note.note().get(), note.file()->filename());
+ return compose("The size %1 of picture asset %2 is not allowed.", note.note().get(), filename());
case VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_2K:
- return String::compose("The frame rate %1 of picture asset %2 is not allowed for 2K DCPs.", note.note().get(), note.file()->filename());
+ return compose("The frame rate %1 of picture asset %2 is not allowed for 2K DCPs.", note.note().get(), filename());
case VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_4K:
- return String::compose("The frame rate %1 of picture asset %2 is not allowed for 4K DCPs.", note.note().get(), note.file()->filename());
+ return compose("The frame rate %1 of picture asset %2 is not allowed for 4K DCPs.", note.note().get(), filename());
case VerificationNote::Code::INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D:
- return "3D 4K DCPs are not allowed.";
+ return process_string("3D 4K DCPs are not allowed.");
case VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES:
- return String::compose("The size %1 of the closed caption asset %2 is larger than the 256KB maximum.", note.note().get(), note.file()->filename());
+ return compose("The size %1 of the closed caption asset %2 is larger than the 256KB maximum.", note.note().get(), filename());
case VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES:
- return String::compose("The size %1 of the timed text asset %2 is larger than the 115MB maximum.", note.note().get(), note.file()->filename());
+ return compose("The size %1 of the timed text asset %2 is larger than the 115MB maximum.", note.note().get(), filename());
case VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES:
- return String::compose("The size %1 of the fonts in timed text asset %2 is larger than the 10MB maximum.", note.note().get(), note.file()->filename());
+ return compose("The size %1 of the fonts in timed text asset %2 is larger than the 10MB maximum.", note.note().get(), filename());
case VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE:
- return String::compose("The XML for the SMPTE subtitle asset %1 has no <Language> tag.", note.file()->filename());
+ return compose("The XML for the SMPTE subtitle asset %1 has no <Language> tag.", filename());
case VerificationNote::Code::MISMATCHED_SUBTITLE_LANGUAGES:
- return "Some subtitle assets have different <Language> tags than others";
+ return process_string("Some subtitle assets have different <Language> tags than others");
case VerificationNote::Code::MISSING_SUBTITLE_START_TIME:
- return String::compose("The XML for the SMPTE subtitle asset %1 has no <StartTime> tag.", note.file()->filename());
+ return compose("The XML for the SMPTE subtitle asset %1 has no <StartTime> tag.", filename());
case VerificationNote::Code::INVALID_SUBTITLE_START_TIME:
- return String::compose("The XML for a SMPTE subtitle asset %1 has a non-zero <StartTime> tag.", note.file()->filename());
+ return compose("The XML for a SMPTE subtitle asset %1 has a non-zero <StartTime> tag.", filename());
case VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME:
- return "The first subtitle or closed caption is less than 4 seconds from the start of the DCP.";
+ return process_string("The first subtitle or closed caption is less than 4 seconds from the start of the DCP.");
case VerificationNote::Code::INVALID_SUBTITLE_DURATION:
- return "At least one subtitle lasts less than 15 frames.";
+ return process_string("At least one subtitle lasts less than 15 frames.");
case VerificationNote::Code::INVALID_SUBTITLE_SPACING:
- return "At least one pair of subtitles is separated by less than 2 frames.";
+ return process_string("At least one pair of subtitles is separated by less than 2 frames.");
case VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY:
- return "At least one subtitle extends outside of its reel.";
+ return process_string("At least one subtitle extends outside of its reel.");
case VerificationNote::Code::INVALID_SUBTITLE_LINE_COUNT:
- return "There are more than 3 subtitle lines in at least one place in the DCP.";
+ return process_string("There are more than 3 subtitle lines in at least one place in the DCP.");
case VerificationNote::Code::NEARLY_INVALID_SUBTITLE_LINE_LENGTH:
- return "There are more than 52 characters in at least one subtitle line.";
+ return process_string("There are more than 52 characters in at least one subtitle line.");
case VerificationNote::Code::INVALID_SUBTITLE_LINE_LENGTH:
- return "There are more than 79 characters in at least one subtitle line.";
+ return process_string("There are more than 79 characters in at least one subtitle line.");
case VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_COUNT:
- return "There are more than 3 closed caption lines in at least one place.";
+ return process_string("There are more than 3 closed caption lines in at least one place.");
case VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_LENGTH:
- return "There are more than 32 characters in at least one closed caption line.";
+ return process_string("There are more than 32 characters in at least one closed caption line.");
case VerificationNote::Code::INVALID_SOUND_FRAME_RATE:
- return String::compose("The sound asset %1 has a sampling rate of %2", note.file()->filename(), note.note().get());
+ return compose("The sound asset %1 has a sampling rate of %2", filename(), note.note().get());
case VerificationNote::Code::MISSING_CPL_ANNOTATION_TEXT:
- return String::compose("The CPL %1 has no <AnnotationText> tag.", note.note().get());
+ return compose("The CPL %1 has no <AnnotationText> tag.", note.cpl_id().get());
case VerificationNote::Code::MISMATCHED_CPL_ANNOTATION_TEXT:
- return String::compose("The CPL %1 has an <AnnotationText> which differs from its <ContentTitleText>.", note.note().get());
+ return compose("The CPL %1 has an <AnnotationText> which differs from its <ContentTitleText>.", note.cpl_id().get());
+ case VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT:
+ return compose("Valid CPL annotation text %1", note.note().get());
case VerificationNote::Code::MISMATCHED_ASSET_DURATION:
- return "All assets in a reel do not have the same duration.";
+ return process_string("All assets in a reel do not have the same duration.");
case VerificationNote::Code::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS:
- return "At least one reel contains a subtitle asset, but some reel(s) do not.";
+ return process_string("At least one reel contains a subtitle asset, but some reel(s) do not.");
case VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS:
- return "At least one reel has closed captions, but reels have different numbers of closed caption assets.";
+ return process_string("At least one reel has closed captions, but reels have different numbers of closed caption assets.");
case VerificationNote::Code::MISSING_SUBTITLE_ENTRY_POINT:
- return String::compose("The subtitle asset %1 has no <EntryPoint> tag.", note.note().get());
+ return compose("The subtitle asset %1 has no <EntryPoint> tag.", note.note().get());
case VerificationNote::Code::INCORRECT_SUBTITLE_ENTRY_POINT:
- return String::compose("The subtitle asset %1 has an <EntryPoint> other than 0.", note.note().get());
+ return compose("The subtitle asset %1 has an <EntryPoint> other than 0.", note.note().get());
case VerificationNote::Code::MISSING_CLOSED_CAPTION_ENTRY_POINT:
- return String::compose("The closed caption asset %1 has no <EntryPoint> tag.", note.note().get());
+ return compose("The closed caption asset %1 has no <EntryPoint> tag.", note.note().get());
case VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ENTRY_POINT:
- return String::compose("The closed caption asset %1 has an <EntryPoint> other than 0.", note.note().get());
+ return compose("The closed caption asset %1 has an <EntryPoint> other than 0.", note.note().get());
case VerificationNote::Code::MISSING_HASH:
- return String::compose("The asset %1 has no <Hash> tag in the CPL.", note.note().get());
+ return compose("The asset %1 has no <Hash> tag in the CPL.", note.note().get());
case VerificationNote::Code::MISSING_FFEC_IN_FEATURE:
- return "The DCP is marked as a Feature but there is no FFEC (first frame of end credits) marker.";
+ return process_string("The DCP is marked as a Feature but there is no FFEC (first frame of end credits) marker.");
case VerificationNote::Code::MISSING_FFMC_IN_FEATURE:
- return "The DCP is marked as a Feature but there is no FFMC (first frame of moving credits) marker.";
+ return process_string("The DCP is marked as a Feature but there is no FFMC (first frame of moving credits) marker.");
case VerificationNote::Code::MISSING_FFOC:
- return "There should be a FFOC (first frame of content) marker.";
+ return process_string("There should be a FFOC (first frame of content) marker.");
case VerificationNote::Code::MISSING_LFOC:
- return "There should be a LFOC (last frame of content) marker.";
+ return process_string("There should be a LFOC (last frame of content) marker.");
case VerificationNote::Code::INCORRECT_FFOC:
- return String::compose("The FFOC marker is %1 instead of 1", note.note().get());
+ return compose("The FFOC marker is %1 instead of 1", note.note().get());
case VerificationNote::Code::INCORRECT_LFOC:
- return String::compose("The LFOC marker is %1 instead of 1 less than the duration of the last reel.", note.note().get());
+ return compose("The LFOC marker is %1 instead of 1 less than the duration of the last reel.", note.note().get());
case VerificationNote::Code::MISSING_CPL_METADATA:
- return String::compose("The CPL %1 has no <CompositionMetadataAsset> tag.", note.note().get());
+ return compose("The CPL %1 has no <CompositionMetadataAsset> tag.", note.cpl_id().get());
case VerificationNote::Code::MISSING_CPL_METADATA_VERSION_NUMBER:
- return String::compose("The CPL %1 has no <VersionNumber> in its <CompositionMetadataAsset>.", note.note().get());
+ return compose("The CPL %1 has no <VersionNumber> in its <CompositionMetadataAsset>.", note.cpl_id().get());
case VerificationNote::Code::MISSING_EXTENSION_METADATA:
- return String::compose("The CPL %1 has no <ExtensionMetadata> in its <CompositionMetadataAsset>.", note.note().get());
+ return compose("The CPL %1 has no <ExtensionMetadata> in its <CompositionMetadataAsset>.", note.cpl_id().get());
case VerificationNote::Code::INVALID_EXTENSION_METADATA:
- return String::compose("The CPL %1 has a malformed <ExtensionMetadata> (%2).", note.file()->filename(), note.note().get());
+ return compose("The CPL %1 has a malformed <ExtensionMetadata> (%2).", filename(), note.note().get());
case VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT:
- return String::compose("The CPL %1, which has encrypted content, is not signed.", note.note().get());
+ return compose("The CPL %1, which has encrypted content, is not signed.", note.cpl_id().get());
case VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT:
- return String::compose("The PKL %1, which has encrypted content, is not signed.", note.note().get());
+ return compose("The PKL %1, which has encrypted content, is not signed.", note.note().get());
case VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL:
- return String::compose("The PKL %1 has only one CPL but its <AnnotationText> does not match the CPL's <ContentTitleText>.", note.note().get());
+ return compose("The PKL %1 has only one CPL but its <AnnotationText> does not match the CPL's <ContentTitleText>.", note.note().get());
+ case VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL:
+ return process_string("The PKL and CPL annotation texts match.");
+ case VerificationNote::Code::ALL_ENCRYPTED:
+ return process_string("All the assets are encrypted.");
+ case VerificationNote::Code::NONE_ENCRYPTED:
+ return process_string("All the assets are unencrypted.");
case VerificationNote::Code::PARTIALLY_ENCRYPTED:
- return "Some assets are encrypted but some are not.";
+ return process_string("Some assets are encrypted but some are not.");
case VerificationNote::Code::INVALID_JPEG2000_CODESTREAM:
- return String::compose(
+ return compose(
"Frame %1 (timecode %2) has an invalid JPEG2000 codestream (%3).",
note.frame().get(),
dcp::Time(note.frame().get(), note.frame_rate().get(), note.frame_rate().get()).as_string(dcp::Standard::SMPTE),
note.note().get()
);
case VerificationNote::Code::INVALID_JPEG2000_GUARD_BITS_FOR_2K:
- return String::compose("The JPEG2000 codestream uses %1 guard bits in a 2K image instead of 1.", note.note().get());
+ return compose("The JPEG2000 codestream uses %1 guard bits in a 2K image instead of 1.", note.note().get());
case VerificationNote::Code::INVALID_JPEG2000_GUARD_BITS_FOR_4K:
- return String::compose("The JPEG2000 codestream uses %1 guard bits in a 4K image instead of 2.", note.note().get());
+ return compose("The JPEG2000 codestream uses %1 guard bits in a 4K image instead of 2.", note.note().get());
case VerificationNote::Code::INVALID_JPEG2000_TILE_SIZE:
- return "The JPEG2000 tile size is not the same as the image size.";
+ return process_string("The JPEG2000 tile size is not the same as the image size.");
case VerificationNote::Code::INVALID_JPEG2000_CODE_BLOCK_WIDTH:
- return String::compose("The JPEG2000 codestream uses a code block width of %1 instead of 32.", note.note().get());
+ return compose("The JPEG2000 codestream uses a code block width of %1 instead of 32.", note.note().get());
case VerificationNote::Code::INVALID_JPEG2000_CODE_BLOCK_HEIGHT:
- return String::compose("The JPEG2000 codestream uses a code block height of %1 instead of 32.", note.note().get());
+ return compose("The JPEG2000 codestream uses a code block height of %1 instead of 32.", note.note().get());
case VerificationNote::Code::INCORRECT_JPEG2000_POC_MARKER_COUNT_FOR_2K:
- return String::compose("%1 POC markers found in 2K JPEG2000 codestream instead of 0.", note.note().get());
+ return compose("%1 POC markers found in 2K JPEG2000 codestream instead of 0.", note.note().get());
case VerificationNote::Code::INCORRECT_JPEG2000_POC_MARKER_COUNT_FOR_4K:
- return String::compose("%1 POC markers found in 4K JPEG2000 codestream instead of 1.", note.note().get());
+ return compose("%1 POC markers found in 4K JPEG2000 codestream instead of 1.", note.note().get());
case VerificationNote::Code::INCORRECT_JPEG2000_POC_MARKER:
- return String::compose("Incorrect POC marker content found (%1).", note.note().get());
+ return compose("Incorrect POC marker content found (%1).", note.note().get());
case VerificationNote::Code::INVALID_JPEG2000_POC_MARKER_LOCATION:
- return "POC marker found outside main header.";
+ return process_string("POC marker found outside main header.");
case VerificationNote::Code::INVALID_JPEG2000_TILE_PARTS_FOR_2K:
- return String::compose("The JPEG2000 codestream has %1 tile parts in a 2K image instead of 3.", note.note().get());
+ return compose("The JPEG2000 codestream has %1 tile parts in a 2K image instead of 3.", note.note().get());
case VerificationNote::Code::INVALID_JPEG2000_TILE_PARTS_FOR_4K:
- return String::compose("The JPEG2000 codestream has %1 tile parts in a 4K image instead of 6.", note.note().get());
+ return compose("The JPEG2000 codestream has %1 tile parts in a 4K image instead of 6.", note.note().get());
case VerificationNote::Code::MISSING_JPEG200_TLM_MARKER:
- return "No TLM marker was found in a JPEG2000 codestream.";
+ return process_string("No TLM marker was found in a JPEG2000 codestream.");
case VerificationNote::Code::MISMATCHED_TIMED_TEXT_RESOURCE_ID:
- return "The Resource ID in a timed text MXF did not match the ID of the contained XML.";
+ return process_string("The Resource ID in a timed text MXF did not match the ID of the contained XML.");
case VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID:
- return "The Asset ID in a timed text MXF is the same as the Resource ID or that of the contained XML.";
+ return process_string("The Asset ID in a timed text MXF is the same as the Resource ID or that of the contained XML.");
case VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION:
{
vector<string> parts;
boost::split (parts, note.note().get(), boost::is_any_of(" "));
DCP_ASSERT (parts.size() == 2);
- return String::compose("The reel duration of some timed text (%1) is not the same as the ContainerDuration of its MXF (%2).", parts[0], parts[1]);
+ return compose("The reel duration of some timed text (%1) is not the same as the ContainerDuration of its MXF (%2).", parts[0], parts[1]);
}
case VerificationNote::Code::MISSED_CHECK_OF_ENCRYPTED:
- return "Some aspect of this DCP could not be checked because it is encrypted.";
+ return process_string("Some aspect of this DCP could not be checked because it is encrypted.");
case VerificationNote::Code::EMPTY_TEXT:
- return "There is an empty <Text> node in a subtitle or closed caption.";
+ return process_string("There is an empty <Text> node in a subtitle or closed caption.");
case VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_VALIGN:
- return "Some closed <Text> or <Image> nodes have different vertical alignments within a <Subtitle>.";
+ return process_string("Some closed <Text> or <Image> nodes have different vertical alignments within a <Subtitle>.");
case VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ORDERING:
- return "Some closed captions are not listed in the order of their vertical position.";
+ return process_string("Some closed captions are not listed in the order of their vertical position.");
case VerificationNote::Code::UNEXPECTED_ENTRY_POINT:
- return "There is an <EntryPoint> node inside a <MainMarkers>.";
+ return process_string("There is an <EntryPoint> node inside a <MainMarkers>.");
case VerificationNote::Code::UNEXPECTED_DURATION:
- return "There is an <Duration> node inside a <MainMarkers>.";
+ return process_string("There is an <Duration> node inside a <MainMarkers>.");
case VerificationNote::Code::INVALID_CONTENT_KIND:
- return String::compose("<ContentKind> has an invalid value %1.", note.note().get());
+ return compose("<ContentKind> has an invalid value %1.", note.note().get());
+ case VerificationNote::Code::VALID_CONTENT_KIND:
+ return compose("Valid <ContentKind> %1.", note.note().get());
case VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA:
- return String::compose("<MainPictureActiveaArea> has an invalid value: %1", note.note().get());
+ return compose("<MainPictureActiveaArea> has an invalid value: %1", note.note().get());
+ case VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA:
+ return compose("<MainPictureActiveaArea> %1 is valid", note.note().get());
case VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL:
- return String::compose("The PKL %1 has more than one asset with the same ID.", note.note().get());
+ return compose("The PKL %1 has more than one asset with the same ID.", note.note().get());
case VerificationNote::Code::DUPLICATE_ASSET_ID_IN_ASSETMAP:
- return String::compose("The ASSETMAP %1 has more than one asset with the same ID.", note.note().get());
+ return compose("The ASSETMAP %1 has more than one asset with the same ID.", note.note().get());
case VerificationNote::Code::MISSING_SUBTITLE:
- return String::compose("The subtitle asset %1 has no subtitles.", note.note().get());
+ return compose("The subtitle asset %1 has no subtitles.", note.note().get());
case VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE:
- return String::compose("<IssueDate> has an invalid value: %1", note.note().get());
+ return compose("<IssueDate> has an invalid value: %1", note.note().get());
case VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS:
- return String::compose("The sound assets do not all have the same channel count; the first to differ is %1", note.file()->filename());
+ return compose("The sound assets do not all have the same channel count; the first to differ is %1", filename());
case VerificationNote::Code::INVALID_MAIN_SOUND_CONFIGURATION:
- return String::compose("<MainSoundConfiguration> has an invalid value: %1", note.note().get());
+ return compose("<MainSoundConfiguration> has an invalid value: %1", note.note().get());
case VerificationNote::Code::MISSING_FONT:
- return String::compose("The font file for font ID \"%1\" was not found, or was not referred to in the ASSETMAP.", note.note().get());
+ return compose("The font file for font ID \"%1\" was not found, or was not referred to in the ASSETMAP.", note.note().get());
case VerificationNote::Code::INVALID_JPEG2000_TILE_PART_SIZE:
- return String::compose(
+ return compose(
"Frame %1 has an image component that is too large (component %2 is %3 bytes in size).",
note.frame().get(), note.component().get(), note.size().get()
);
case VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT:
- return String::compose("The XML in the subtitle asset %1 has more than one namespace declaration.", note.note().get());
+ return compose("The XML in the subtitle asset %1 has more than one namespace declaration.", note.note().get());
case VerificationNote::Code::MISSING_LOAD_FONT_FOR_FONT:
- return String::compose("A subtitle or closed caption refers to a font with ID %1 that does not have a corresponding <LoadFont> node", note.id().get());
+ return compose("A subtitle or closed caption refers to a font with ID %1 that does not have a corresponding <LoadFont> node", note.id().get());
case VerificationNote::Code::MISSING_LOAD_FONT:
- return String::compose("The SMPTE subtitle asset %1 has <Text> nodes but no <LoadFont> node", note.id().get());
+ return compose("The SMPTE subtitle asset %1 has <Text> nodes but no <LoadFont> node", note.id().get());
case VerificationNote::Code::MISMATCHED_ASSET_MAP_ID:
- return String::compose("The asset with ID %1 in the asset map actually has an id of %2", note.id().get(), note.other_id().get());
+ return compose("The asset with ID %1 in the asset map actually has an id of %2", note.id().get(), note.other_id().get());
case VerificationNote::Code::EMPTY_CONTENT_VERSION_LABEL_TEXT:
- return String::compose("The <LabelText> in a <ContentVersion> in CPL %1 is empty", note.id().get());
+ return compose("The <LabelText> in a <ContentVersion> in CPL %1 is empty", note.cpl_id().get());
+ case VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT:
+ return compose("CPL has valid <ContentVersion> %1", note.note().get());
case VerificationNote::Code::INVALID_CPL_NAMESPACE:
- return String::compose("The namespace %1 in CPL %2 is invalid", note.note().get(), note.file()->filename());
+ return compose("The namespace %1 in CPL %2 is invalid", note.note().get(), note.cpl_id().get());
case VerificationNote::Code::MISSING_CPL_CONTENT_VERSION:
- return String::compose("The CPL %1 has no <ContentVersion> tag", note.note().get());
+ return compose("The CPL %1 has no <ContentVersion> tag", note.cpl_id().get());
}
return "";
@@ -2202,12 +2227,20 @@ dcp::operator== (dcp::VerificationNote const& a, dcp::VerificationNote const& b)
a.id() == b.id() &&
a.other_id() == b.other_id() &&
a.frame_rate() == b.frame_rate() &&
+ a.cpl_id() == b.cpl_id() &&
a.reference_hash() == b.reference_hash() &&
a.calculated_hash() == b.calculated_hash();
}
bool
+dcp::operator!=(dcp::VerificationNote const& a, dcp::VerificationNote const& b)
+{
+ return !(a == b);
+}
+
+
+bool
dcp::operator< (dcp::VerificationNote const& a, dcp::VerificationNote const& b)
{
if (a.type() != b.type()) {
diff --git a/src/verify.h b/src/verify.h
index b5d913bd..b9e3623f 100644
--- a/src/verify.h
+++ b/src/verify.h
@@ -58,16 +58,20 @@
namespace dcp {
+class DCP;
+
+
class VerificationNote
{
public:
enum class Type {
+ OK,
ERROR,
BV21_ERROR, ///< may not always be considered an error, but violates a "shall" requirement of Bv2.1
WARNING
};
- /** Codes for errors or warnings from verifying DCPs.
+ /** Codes for successful checks, errors or warnings from verifying DCPs.
*
* The names should (in general) answer the question "what is wrong?" with an answer that begins "There is a ..."
* e.g. "There is a INCORRECT_CPL_HASH"
@@ -98,6 +102,7 @@ public:
* note contains (probably technical) details
*/
FAILED_READ,
+ MATCHING_CPL_HASHES,
/** The hash of the CPL in the PKL does not agree with the CPL file
* note contains CPL ID
* file contains CPL filename
@@ -109,6 +114,7 @@ public:
* note contains the invalid frame rate as "<numerator>/<denominator>"
*/
INVALID_PICTURE_FRAME_RATE,
+ CORRECT_PICTURE_HASH,
/** The hash of a main picture asset does not agree with the PKL file
* file contains the picture asset filename
* calculated_hash contains the current hash of the picture MXF
@@ -153,6 +159,7 @@ public:
* note contains asset ID
*/
INVALID_DURATION,
+ VALID_PICTURE_FRAME_SIZES_IN_BYTES,
/** The JPEG2000 data in at least one picture frame is larger than the equivalent of 250Mbit/s
* file contains the picture asset filename
*/
@@ -175,6 +182,7 @@ public:
* note contains the invalid language
*/
INVALID_LANGUAGE,
+ VALID_RELEASE_TERRITORY,
/** A picture asset does not have one of the required Bv2.1 sizes (in pixels) [Bv2.1_7.1]
* note contains the incorrect size as "<width>x<height>"
* file contains the asset filename
@@ -257,6 +265,7 @@ public:
* file contains the CPL filename
*/
MISMATCHED_CPL_ANNOTATION_TEXT,
+ VALID_CPL_ANNOTATION_TEXT,
/** At least one asset in a reel does not have the same duration as the others */
MISMATCHED_ASSET_DURATION,
/** If one reel has a _MainSubtitle_, all must have them */
@@ -334,6 +343,11 @@ public:
* file contains the PKL filename
*/
MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL,
+ MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL,
+ /** All content is encrypted */
+ ALL_ENCRYPTED,
+ /** No content is encrypted */
+ NONE_ENCRYPTED,
/** Some, but not all content, is encrypted */
PARTIALLY_ENCRYPTED,
/** General error during JPEG2000 codestream verification
@@ -406,11 +420,13 @@ public:
UNEXPECTED_DURATION,
/** A <ContentKind> has been specified with either no scope or the SMPTE 429-7 scope, but which is not one of those allowed */
INVALID_CONTENT_KIND,
+ VALID_CONTENT_KIND,
/** Either the width or height of a <MainPictureActiveArea> in a CPL is either not an even number, or bigger than the corresponding asset dimension.
* note contains details of what is wrong
* file contains the CPL filename
*/
INVALID_MAIN_PICTURE_ACTIVE_AREA,
+ VALID_MAIN_PICTURE_ACTIVE_AREA,
/** A PKL has more than one asset with the same ID
* note contains the PKL ID
* file contains the PKL filename
@@ -475,13 +491,13 @@ public:
* file contains the CPL filename
*/
EMPTY_CONTENT_VERSION_LABEL_TEXT,
+ VALID_CONTENT_VERSION_LABEL_TEXT,
/** The CPL namespace is not valid.
* note contains the invalid namespace
* file contains the CPL filename
*/
INVALID_CPL_NAMESPACE,
/** A SMPTE CPL does not contain a _<ContentVersion>_ tag
- * note contains the CPL ID
* file contains the CPL filename
*/
MISSING_CPL_CONTENT_VERSION
@@ -542,6 +558,7 @@ private:
ID,
OTHER_ID,
FRAME_RATE,
+ CPL_ID,
CALCULATED_HASH,
REFERENCE_HASH
};
@@ -641,6 +658,15 @@ public:
return data<std::string>(Data::REFERENCE_HASH);
}
+ VerificationNote& set_cpl_id(std::string id) {
+ _data[Data::CPL_ID] = id;
+ return *this;
+ }
+
+ boost::optional<std::string> cpl_id() const {
+ return data<std::string>(Data::CPL_ID);
+ }
+
private:
Type _type;
Code _code;
@@ -658,18 +684,30 @@ struct VerificationOptions
};
-std::vector<VerificationNote> verify (
+struct VerificationResult
+{
+ std::vector<VerificationNote> notes;
+ std::vector<std::shared_ptr<dcp::DCP>> dcps;
+};
+
+
+VerificationResult verify(
std::vector<boost::filesystem::path> directories,
std::vector<dcp::DecryptedKDM> kdms,
- boost::function<void (std::string, boost::optional<boost::filesystem::path>)> stage,
- boost::function<void (float)> progress,
+ std::function<void (std::string, boost::optional<boost::filesystem::path>)> stage,
+ std::function<void (float)> progress,
VerificationOptions options = {},
boost::optional<boost::filesystem::path> xsd_dtd_directory = boost::optional<boost::filesystem::path>()
);
-std::string note_to_string (dcp::VerificationNote note);
+std::string note_to_string(
+ dcp::VerificationNote note,
+ std::function<std::string (std::string)> process_string = [](std::string s) { return s; },
+ std::function<std::string (std::string)> process_filename = [](std::string s) { return s; }
+ );
bool operator== (dcp::VerificationNote const& a, dcp::VerificationNote const& b);
+bool operator!=(dcp::VerificationNote const& a, dcp::VerificationNote const& b);
bool operator< (dcp::VerificationNote const& a, dcp::VerificationNote const& b);
std::ostream& operator<<(std::ostream& s, dcp::VerificationNote const& note);
diff --git a/src/verify_j2k.h b/src/verify_j2k.h
index 58c8f4b7..dbfc488b 100644
--- a/src/verify_j2k.h
+++ b/src/verify_j2k.h
@@ -37,8 +37,8 @@
*/
-#ifndef LIBDCP_VERIFY_J2K
-#define LIBDCP_VERIFY_J2K
+#ifndef LIBDCP_VERIFY_J2K_H
+#define LIBDCP_VERIFY_J2K_H
#include "verify.h"
diff --git a/src/verify_report.cc b/src/verify_report.cc
new file mode 100644
index 00000000..2201b8fa
--- /dev/null
+++ b/src/verify_report.cc
@@ -0,0 +1,144 @@
+/*
+ Copyright (C) 2018-2021 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "compose.hpp"
+#include "cpl.h"
+#include "dcp.h"
+#include "file.h"
+#include "reel.h"
+#include "reel_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
+#include "verify.h"
+#include "verify_report.h"
+
+
+using std::shared_ptr;
+using std::string;
+using std::vector;
+using boost::optional;
+using namespace dcp;
+
+
+void write_line(File& file, string format)
+{
+ file.puts(string(format + "\n").c_str());
+}
+
+
+template <typename... Args>
+void write_line(File& file, string format, Args... args)
+{
+ file.puts(String::compose(format + "\n", std::forward<Args>(args)...).c_str());
+}
+
+
+void
+dcp::verify_report(dcp::VerificationResult const& result, Formatter& formatter)
+{
+ auto document = formatter.document();
+ auto body = formatter.body();
+
+ formatter.heading("DCP verification report");
+
+ if (result.dcps.size() > 1) {
+ formatter.subheading("DCPs");
+ } else {
+ formatter.subheading("DCP");
+ }
+
+ auto reel_asset_details = [&formatter](shared_ptr<dcp::ReelAsset> asset) {
+ formatter.list_item(String::compose("UUID: %1", asset->id()));
+ formatter.list_item(String::compose("Intrinsic duration: %1", asset->intrinsic_duration()));
+ formatter.list_item(String::compose("Entry point: %1", asset->entry_point().get_value_or(0)));
+ formatter.list_item(String::compose("Duration: %1", asset->duration().get_value_or(0)));
+ if (asset->annotation_text()) {
+ formatter.list_item(String::compose("Annotation text: %1", *asset->annotation_text()));
+ }
+ };
+
+ auto write_notes = [&formatter](dcp::VerificationResult const& result, optional<string> cpl_id) {
+ for (auto note: result.notes) {
+ if (note.cpl_id() == cpl_id) {
+ auto const note_as_string = dcp::note_to_string(note, formatter.process_string(), formatter.process_filename());
+ if (note.type() == dcp::VerificationNote::Type::OK) {
+ formatter.list_item(note_as_string, string("ok"));
+ } else if (note.type() == dcp::VerificationNote::Type::WARNING) {
+ formatter.list_item(note_as_string, string("warning"));
+ } else if (note.type() == dcp::VerificationNote::Type::ERROR) {
+ formatter.list_item(note_as_string, string("error"));
+ }
+ }
+ }
+ };
+
+ for (auto dcp: result.dcps) {
+ auto ul = formatter.unordered_list();
+ for (auto cpl: dcp->cpls()) {
+ formatter.list_item(String::compose("CPL ID: %1", cpl->id()));
+ int reel_index = 1;
+ for (auto reel: cpl->reels()) {
+ formatter.list_item(String::compose("Reel: %1", reel_index++));
+ auto ul2 = formatter.unordered_list();
+ if (auto pic = reel->main_picture()) {
+ formatter.list_item("Main picture");
+ auto ul3 = formatter.unordered_list();
+ reel_asset_details(pic);
+ formatter.list_item(String::compose("Frame rate: %1", pic->frame_rate().numerator));
+ formatter.list_item(String::compose("Screen aspect ratio: %1x%2", pic->screen_aspect_ratio().numerator, pic->screen_aspect_ratio().denominator));
+ }
+ if (auto sound = reel->main_sound()) {
+ formatter.list_item("Main sound");
+ auto ul3 = formatter.unordered_list();
+ reel_asset_details(sound);
+ }
+ if (auto sub = reel->main_subtitle()) {
+ formatter.list_item("Main subtitle");
+ auto ul3 = formatter.unordered_list();
+ reel_asset_details(sub);
+ if (sub->language()) {
+ formatter.list_item(String::compose("Language: %1", *sub->language()));
+ }
+ }
+ }
+ write_notes(result, cpl->id());
+ }
+ }
+
+ if (std::count_if(result.notes.begin(), result.notes.end(), [](VerificationNote const& note) { return !note.cpl_id(); }) > 0) {
+ formatter.subheading("Report");
+ write_notes(result, {});
+ }
+}
+
diff --git a/src/verify_report.h b/src/verify_report.h
new file mode 100644
index 00000000..b8ca5516
--- /dev/null
+++ b/src/verify_report.h
@@ -0,0 +1,237 @@
+/*
+ Copyright (C) 2022 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "compose.hpp"
+#include "file.h"
+#include "verify.h"
+#include <boost/filesystem.hpp>
+#include <vector>
+
+
+namespace dcp {
+
+
+class Formatter
+{
+public:
+ Formatter(boost::filesystem::path file)
+ : _file(file, "w")
+ {}
+
+ class Wrap
+ {
+ public:
+ Wrap() = default;
+
+ Wrap(Formatter* formatter, std::string const& close)
+ : _formatter(formatter)
+ , _close(close)
+ {}
+
+ Wrap(Formatter* formatter, std::string const& close, std::function<void ()> closer)
+ : _formatter(formatter)
+ , _close(close)
+ , _closer(closer)
+ {}
+
+ Wrap(Wrap&& other)
+ {
+ std::swap(_formatter, other._formatter);
+ std::swap(_close, other._close);
+ std::swap(_closer, other._closer);
+ }
+
+ ~Wrap()
+ {
+ if (_formatter) {
+ _formatter->file().puts(_close.c_str());
+ }
+ if (_closer) {
+ _closer();
+ }
+ }
+
+ private:
+ Formatter* _formatter = nullptr;
+ std::string _close;
+ std::function<void ()> _closer = nullptr;
+ };
+
+ virtual Wrap document() { return {}; }
+
+ virtual void heading(std::string const& text) = 0;
+ virtual void subheading(std::string const& text) = 0;
+ virtual Wrap body() { return {}; }
+
+ virtual Wrap unordered_list() = 0;
+ virtual void list_item(std::string const& text, boost::optional<std::string> type = {}) = 0;
+
+ virtual std::function<std::string (std::string)> process_string() = 0;
+ virtual std::function<std::string (std::string)> process_filename() = 0;
+
+ dcp::File& file() {
+ return _file;
+ }
+
+protected:
+ dcp::File _file;
+};
+
+
+class TextFormatter : public Formatter
+{
+public:
+ TextFormatter(boost::filesystem::path file)
+ : Formatter(file)
+ {}
+
+ void heading(std::string const& text) override {
+ print(text);
+ }
+
+ void subheading(std::string const& text) override {
+ print("");
+ print(text);
+ }
+
+ Wrap unordered_list() override {
+ _indent++;
+ return Wrap(this, "", [this]() { _indent--; });
+ }
+
+ void list_item(std::string const& text, boost::optional<std::string> type = {}) override {
+ LIBDCP_UNUSED(type);
+ for (int i = 0; i < _indent * 2; ++i) {
+ _file.puts(" ");
+ }
+ _file.puts("* ");
+ print(text);
+ }
+
+ std::function<std::string (std::string)> process_string() override {
+ return [](std::string s) {
+ return s;
+ };
+ }
+
+ std::function<std::string (std::string)> process_filename() override {
+ return [](std::string s) {
+ return s;
+ };
+ }
+
+private:
+ void print(std::string const& text) {
+ _file.puts(text.c_str());
+ _file.puts("\n");
+ }
+
+ int _indent = 0;
+};
+
+
+class HTMLFormatter : public Formatter
+{
+public:
+ HTMLFormatter(boost::filesystem::path file)
+ : Formatter(file)
+ {}
+
+ void heading(std::string const& text) override {
+ tagged("h1", text);
+ }
+
+ void subheading(std::string const& text) override {
+ tagged("h2", text);
+ }
+
+ Wrap document() override {
+ auto html = wrapped("html");
+ auto head = wrapped("head");
+ auto style = wrapped("style");
+ _file.puts("li {\n"
+ " margin: 2px;\n"
+ " padding: 2px 2px 2px 1em;\n"
+ "}\n"
+ );
+ _file.puts("li.ok {\n"
+ " background-color: #00ff00;\n"
+ "}\n"
+ "li.warning {\n"
+ " background-color: #ffa500;\n"
+ "}\n"
+ "li.error {\n"
+ " background-color: #ff0000;\n"
+ "}\n"
+ "ul {\n"
+ " list-style: none;\n"
+ "}\n"
+ );
+ return html;
+ }
+
+ Wrap body() override {
+ return wrapped("body");
+ }
+
+ Wrap unordered_list() override {
+ return wrapped("ul");
+ }
+
+ void list_item(std::string const& text, boost::optional<std::string> type = {}) override {
+ if (type) {
+ _file.puts(dcp::String::compose("<li class=\"%1\">%2", *type, text).c_str());
+ } else {
+ _file.puts(dcp::String::compose("<li>%1", text).c_str());
+ }
+ }
+
+ std::function<std::string (std::string)> process_string() override {
+ return [](std::string s) {
+ boost::replace_all(s, "<", "&lt;");
+ boost::replace_all(s, ">", "&gt;");
+ return s;
+ };
+ }
+
+ std::function<std::string (std::string)> process_filename() override {
+ return [](std::string s) {
+ return String::compose("<code>%1</code>", s);
+ };
+ }
+
+private:
+ void tagged(std::string tag, std::string content) {
+ _file.puts(String::compose("<%1>%2</%3>\n", tag, content, tag).c_str());
+ };
+
+ Wrap wrapped(std::string const& tag) {
+ _file.puts(String::compose("<%1>", tag).c_str());
+ return Wrap(this, String::compose("</%1>", tag));
+ };
+};
+
+
+extern void verify_report(dcp::VerificationResult const& result, Formatter& formatter);
+
+
+}
+
diff --git a/src/wscript b/src/wscript
index c2d499c8..1793aa72 100644
--- a/src/wscript
+++ b/src/wscript
@@ -36,14 +36,14 @@ def build(bld):
source = """
array_data.cc
asset.cc
- asset_map.cc
asset_factory.cc
+ asset_map.cc
asset_writer.cc
atmos_asset.cc
atmos_asset_writer.cc
bitstream.cc
- certificate_chain.cc
certificate.cc
+ certificate_chain.cc
chromaticity.cc
colour_conversion.cc
combine.cc
@@ -58,6 +58,7 @@ def build(bld):
exceptions.cc
file.cc
filesystem.cc
+ ffmpeg_image.cc
font_asset.cc
fsk.cc
gamma_transfer_function.cc
@@ -65,6 +66,8 @@ def build(bld):
identity_transfer_function.cc
interop_load_font_node.cc
interop_subtitle_asset.cc
+ j2k_picture_asset.cc
+ j2k_picture_asset_writer.cc
j2k_transcode.cc
key.cc
language_tag.cc
@@ -72,15 +75,20 @@ def build(bld):
locale_convert.cc
metadata.cc
modified_gamma_transfer_function.cc
- mono_picture_asset.cc
- mono_picture_asset_writer.cc
- mono_picture_frame.cc
+ mono_j2k_picture_asset.cc
+ mono_j2k_picture_asset_writer.cc
+ mono_j2k_picture_frame.cc
+ mono_mpeg2_picture_asset.cc
+ mono_mpeg2_picture_asset_writer.cc
+ mono_mpeg2_picture_frame.cc
+ mpeg2_picture_asset.cc
+ mpeg2_picture_asset_writer.cc
+ mpeg2_transcode.cc
mxf.cc
name_format.cc
object.cc
openjpeg_image.cc
picture_asset.cc
- picture_asset_writer.cc
pkl.cc
rating.cc
raw_convert.cc
@@ -91,9 +99,9 @@ def build(bld):
reel_file_asset.cc
reel_interop_closed_caption_asset.cc
reel_interop_subtitle_asset.cc
+ reel_markers_asset.cc
reel_mono_picture_asset.cc
reel_picture_asset.cc
- reel_markers_asset.cc
reel_smpte_closed_caption_asset.cc
reel_smpte_subtitle_asset.cc
reel_sound_asset.cc
@@ -109,9 +117,9 @@ def build(bld):
sound_asset.cc
sound_asset_writer.cc
sound_frame.cc
- stereo_picture_asset.cc
- stereo_picture_asset_writer.cc
- stereo_picture_frame.cc
+ stereo_j2k_picture_asset.cc
+ stereo_j2k_picture_asset_writer.cc
+ stereo_j2k_picture_frame.cc
subtitle.cc
subtitle_asset.cc
subtitle_asset_internal.cc
@@ -125,6 +133,7 @@ def build(bld):
v_align.cc
verify.cc
verify_j2k.cc
+ verify_report.cc
version.cc
"""
@@ -139,8 +148,9 @@ def build(bld):
atmos_asset_reader.h
atmos_asset_writer.h
atmos_frame.h
- certificate_chain.h
+ behaviour.h
certificate.h
+ certificate_chain.h
chromaticity.h
colour_conversion.h
combine.h
@@ -161,12 +171,16 @@ def build(bld):
filesystem.h
font_asset.h
frame.h
+ frame_info.h
fsk.h
gamma_transfer_function.h
h_align.h
identity_transfer_function.h
interop_load_font_node.h
interop_subtitle_asset.h
+ ffmpeg_image.h
+ j2k_picture_asset.h
+ j2k_picture_asset_writer.h
j2k_transcode.h
key.h
language_tag.h
@@ -174,22 +188,27 @@ def build(bld):
local_time.h
locale_convert.h
metadata.h
- mono_picture_asset.h
- mono_picture_asset_reader.h
- mono_picture_asset_writer.h
- mono_picture_frame.h
+ mpeg2_picture_asset_writer.h
modified_gamma_transfer_function.h
+ mono_j2k_picture_asset.h
+ mono_j2k_picture_asset_reader.h
+ mono_j2k_picture_asset_writer.h
+ mono_j2k_picture_frame.h
+ mono_mpeg2_picture_asset.h
+ mono_mpeg2_picture_asset_reader.h
+ mono_mpeg2_picture_asset_writer.h
+ mono_mpeg2_picture_frame.h
+ mpeg2_picture_asset.h
+ mpeg2_transcode.h
mxf.h
name_format.h
object.h
openjpeg_image.h
picture_asset.h
- picture_asset_writer.h
piecewise_lut.h
pkl.h
rating.h
raw_convert.h
- rgb_xyz.h
reel.h
reel_asset.h
reel_atmos_asset.h
@@ -200,26 +219,27 @@ def build(bld):
reel_markers_asset.h
reel_mono_picture_asset.h
reel_picture_asset.h
- reel_sound_asset.h
reel_smpte_closed_caption_asset.h
reel_smpte_subtitle_asset.h
+ reel_sound_asset.h
reel_stereo_picture_asset.h
reel_subtitle_asset.h
ref.h
+ rgb_xyz.h
ruby.h
s_gamut3_transfer_function.h
scope_guard.h
search.h
smpte_load_font_node.h
smpte_subtitle_asset.h
- sound_frame.h
sound_asset.h
sound_asset_reader.h
sound_asset_writer.h
- stereo_picture_asset.h
- stereo_picture_asset_reader.h
- stereo_picture_asset_writer.h
- stereo_picture_frame.h
+ sound_frame.h
+ stereo_j2k_picture_asset.h
+ stereo_j2k_picture_asset_reader.h
+ stereo_j2k_picture_asset_writer.h
+ stereo_j2k_picture_frame.h
subtitle.h
subtitle_asset.h
subtitle_image.h
@@ -232,6 +252,7 @@ def build(bld):
v_align.h
verify.h
verify_j2k.h
+ verify_report.h
version.h
warnings.h
"""
@@ -244,7 +265,7 @@ def build(bld):
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 ASDCPLIB_CTH XERCES'
+ obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1 ASDCPLIB_DCPOMATIC XERCES AVCODEC AVUTIL'
obj.source = source
# Library for gcov
@@ -256,7 +277,7 @@ def build(bld):
obj.name = 'libdcp%s_gcov' % bld.env.API_VERSION
obj.target = 'dcp%s_gcov' % bld.env.API_VERSION
obj.export_includes = ['.']
- obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1 ASDCPLIB_CTH XERCES'
+ obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 BOOST_DATETIME OPENSSL SIGC++ LIBXML++ OPENJPEG CXML XMLSEC1 ASDCPLIB_DCPOMATIC XERCES AVCODEC AVUTIL'
obj.use = 'libkumu-libdcp%s libasdcp-libdcp%s' % (bld.env.API_VERSION, bld.env.API_VERSION)
obj.source = source
obj.cppflags = ['-fprofile-arcs', '-ftest-coverage', '-fno-inline', '-fno-default-inline', '-fno-elide-constructors', '-g', '-O0']
diff --git a/test/combine_test.cc b/test/combine_test.cc
index 12cbb6e2..a5f6a57f 100644
--- a/test/combine_test.cc
+++ b/test/combine_test.cc
@@ -87,10 +87,12 @@ check_no_errors (boost::filesystem::path path)
{
vector<boost::filesystem::path> directories;
directories.push_back (path);
- auto notes = dcp::verify(directories, {}, &stage, &progress, {}, xsd_test);
+ auto notes = dcp::verify(directories, {}, &stage, &progress, {}, xsd_test).notes;
vector<dcp::VerificationNote> filtered_notes;
std::copy_if (notes.begin(), notes.end(), std::back_inserter(filtered_notes), [](dcp::VerificationNote const& i) {
- return i.code() != dcp::VerificationNote::Code::INVALID_STANDARD && i.code() != dcp::VerificationNote::Code::INVALID_SUBTITLE_DURATION;
+ return i.type() != dcp::VerificationNote::Type::OK &&
+ i.code() != dcp::VerificationNote::Code::INVALID_STANDARD &&
+ i.code() != dcp::VerificationNote::Code::INVALID_SUBTITLE_DURATION;
});
dump_notes (filtered_notes);
BOOST_CHECK (filtered_notes.empty());
@@ -475,10 +477,12 @@ BOOST_AUTO_TEST_CASE(combine_multi_reel_subtitles)
check_combined({in}, out);
- auto notes = dcp::verify({out}, {}, &stage, &progress, {}, xsd_test);
+ auto notes = dcp::verify({out}, {}, &stage, &progress, {}, xsd_test).notes;
vector<dcp::VerificationNote> filtered_notes;
std::copy_if(notes.begin(), notes.end(), std::back_inserter(filtered_notes), [](dcp::VerificationNote const& i) {
- return i.code() != dcp::VerificationNote::Code::INVALID_STANDARD && i.code() != dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL;
+ return i.type() != dcp::VerificationNote::Type::OK &&
+ i.code() != dcp::VerificationNote::Code::INVALID_STANDARD &&
+ i.code() != dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL;
});
dump_notes(filtered_notes);
BOOST_CHECK(filtered_notes.empty());
diff --git a/test/cpl_sar_test.cc b/test/cpl_sar_test.cc
index 0ecc87e0..ab1ef182 100644
--- a/test/cpl_sar_test.cc
+++ b/test/cpl_sar_test.cc
@@ -33,7 +33,7 @@
#include "cpl.h"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
#include "reel_mono_picture_asset.h"
#include "warnings.h"
#include <libcxml/cxml.h>
@@ -68,7 +68,7 @@ check (shared_ptr<dcp::ReelMonoPictureAsset> pa, dcp::Fraction frac, string sar)
BOOST_AUTO_TEST_CASE (cpl_sar)
{
auto pa = make_shared<dcp::ReelMonoPictureAsset>(
- make_shared<dcp::MonoPictureAsset>("test/ref/DCP/dcp_test1/video.mxf"), 0
+ make_shared<dcp::MonoJ2KPictureAsset>("test/ref/DCP/dcp_test1/video.mxf"), 0
);
/* Easy ones */
diff --git a/test/data/text_formatter.txt b/test/data/text_formatter.txt
new file mode 100644
index 00000000..8861db99
--- /dev/null
+++ b/test/data/text_formatter.txt
@@ -0,0 +1,8 @@
+Heading
+
+Subheading
+ * Foo
+ * Bar
+ * Fred
+ * Jim
+ * Sheila
diff --git a/test/data/text_formatter_windows.txt b/test/data/text_formatter_windows.txt
new file mode 100644
index 00000000..16d78d84
--- /dev/null
+++ b/test/data/text_formatter_windows.txt
@@ -0,0 +1,8 @@
+Heading
+
+Subheading
+ * Foo
+ * Bar
+ * Fred
+ * Jim
+ * Sheila
diff --git a/test/dcp_test.cc b/test/dcp_test.cc
index 5456092c..63de990f 100644
--- a/test/dcp_test.cc
+++ b/test/dcp_test.cc
@@ -38,8 +38,8 @@
#include "dcp.h"
#include "equality_options.h"
#include "metadata.h"
-#include "mono_picture_asset.h"
-#include "picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
+#include "j2k_picture_asset_writer.h"
#include "reel.h"
#include "reel_atmos_asset.h"
#include "reel_markers_asset.h"
@@ -49,7 +49,7 @@
#include "reel_stereo_picture_asset.h"
#include "sound_asset.h"
#include "sound_asset_writer.h"
-#include "stereo_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
#include "test.h"
#include <asdcp/KM_util.h>
#include <sndfile.h>
@@ -105,9 +105,9 @@ BOOST_AUTO_TEST_CASE (dcp_test2)
cpl->set_issue_date ("2012-07-17T04:45:18+00:00");
cpl->set_annotation_text ("A Test DCP");
- auto mp = make_shared<dcp::StereoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto mp = make_shared<dcp::StereoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
mp->set_metadata (mxf_meta);
- auto picture_writer = mp->start_write("build/test/DCP/dcp_test2/video.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto picture_writer = mp->start_write("build/test/DCP/dcp_test2/video.mxf", dcp::Behaviour::MAKE_NEW);
dcp::ArrayData j2c ("test/data/flat_red.j2c");
for (int i = 0; i < 24; ++i) {
/* Left */
@@ -203,10 +203,10 @@ test_rewriting_sound(string name, bool modify)
dcp::DCP B ("build/test/" + name);
auto reel = make_shared<dcp::Reel>();
- BOOST_REQUIRE (A_picture->mono_asset());
- BOOST_REQUIRE (A_picture->mono_asset()->file());
- copy_file (A_picture->mono_asset()->file().get(), path("build") / "test" / name / picture);
- reel->add(make_shared<dcp::ReelMonoPictureAsset>(make_shared<dcp::MonoPictureAsset>(path("build") / "test" / name / picture), 0));
+ BOOST_REQUIRE(A_picture->mono_j2k_asset());
+ BOOST_REQUIRE(A_picture->mono_j2k_asset()->file());
+ copy_file(A_picture->mono_j2k_asset()->file().get(), path("build") / "test" / name / picture);
+ reel->add(make_shared<dcp::ReelMonoPictureAsset>(make_shared<dcp::MonoJ2KPictureAsset>(path("build") / "test" / name / picture), 0));
auto reader = A_sound->asset()->start_read();
auto sound = make_shared<dcp::SoundAsset>(A_sound->asset()->edit_rate(), A_sound->asset()->sampling_rate(), A_sound->asset()->channels(), dcp::LanguageTag("en-US"), dcp::Standard::SMPTE);
@@ -290,9 +290,9 @@ BOOST_AUTO_TEST_CASE (dcp_test5)
cpl->set_issue_date ("2012-07-17T04:45:18+00:00");
cpl->set_annotation_text ("A Test DCP");
- auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
mp->set_metadata (mxf_meta);
- auto picture_writer = mp->start_write("build/test/DCP/dcp_test5/video.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto picture_writer = mp->start_write("build/test/DCP/dcp_test5/video.mxf", dcp::Behaviour::MAKE_NEW);
dcp::ArrayData j2c ("test/data/flat_red.j2c");
for (int i = 0; i < 24; ++i) {
picture_writer->write (j2c.data (), j2c.size ());
@@ -510,8 +510,8 @@ BOOST_AUTO_TEST_CASE(hashes_preserved_when_loading_corrupted_dcp)
auto dcp = make_simple(dir / "1");
dcp->write_xml();
- auto asset_1_id = dcp::MonoPictureAsset(dir / "1" / "video.mxf").id();
- auto asset_1_hash = dcp::MonoPictureAsset(dir / "1" / "video.mxf").hash();
+ auto asset_1_id = dcp::MonoJ2KPictureAsset(dir / "1" / "video.mxf").id();
+ auto asset_1_hash = dcp::MonoJ2KPictureAsset(dir / "1" / "video.mxf").hash();
/* Replace the hash in the CPL (the one that corresponds to the actual file)
* with an incorrect one new_hash.
diff --git a/test/decryption_test.cc b/test/decryption_test.cc
index 8f3dbff7..1aadc461 100644
--- a/test/decryption_test.cc
+++ b/test/decryption_test.cc
@@ -36,11 +36,11 @@
#include "dcp.h"
#include "decrypted_kdm.h"
#include "encrypted_kdm.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_reader.h"
-#include "mono_picture_frame.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_reader.h"
+#include "mono_j2k_picture_frame.h"
#include "openjpeg_image.h"
-#include "picture_asset_writer.h"
+#include "j2k_picture_asset_writer.h"
#include "reel.h"
#include "reel_file_asset.h"
#include "reel_mono_picture_asset.h"
@@ -80,7 +80,7 @@ get_frame (dcp::DCP const & dcp)
auto picture = reel->main_picture()->asset();
BOOST_CHECK (picture);
- auto mono_picture = dynamic_pointer_cast<const dcp::MonoPictureAsset>(picture);
+ auto mono_picture = dynamic_pointer_cast<const dcp::MonoJ2KPictureAsset>(picture);
auto reader = mono_picture->start_read();
auto j2k_frame = reader->get_frame(0);
auto xyz = j2k_frame->xyz_image();
@@ -152,10 +152,10 @@ BOOST_AUTO_TEST_CASE (decryption_test2)
auto context_id = dcp::make_uuid();
dcp::Key key;
- auto picture_asset = std::make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
+ auto picture_asset = std::make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
picture_asset->set_key (key);
picture_asset->set_context_id (context_id);
- auto picture_writer = picture_asset->start_write(dir / "picture.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto picture_writer = picture_asset->start_write(dir / "picture.mxf", dcp::Behaviour::MAKE_NEW);
dcp::ArrayData picture("test/data/flat_red.j2c");
for (int i = 0; i < 24; ++i) {
picture_writer->write(picture);
diff --git a/test/encryption_test.cc b/test/encryption_test.cc
index 358a3fd9..a927a5df 100644
--- a/test/encryption_test.cc
+++ b/test/encryption_test.cc
@@ -37,8 +37,8 @@
#include "certificate_chain.h"
#include "cpl.h"
#include "filesystem.h"
-#include "mono_picture_asset.h"
-#include "picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
+#include "j2k_picture_asset_writer.h"
#include "sound_asset_writer.h"
#include "sound_asset.h"
#include "reel.h"
@@ -90,11 +90,11 @@ BOOST_AUTO_TEST_CASE (encryption_test)
dcp::Key key;
- auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
mp->set_metadata (mxf_metadata);
mp->set_key (key);
- auto writer = mp->start_write("build/test/DCP/encryption_test/video.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto writer = mp->start_write("build/test/DCP/encryption_test/video.mxf", dcp::Behaviour::MAKE_NEW);
dcp::ArrayData j2c ("test/data/flat_red.j2c");
for (int i = 0; i < 24; ++i) {
writer->write (j2c.data (), j2c.size ());
diff --git a/test/frame_info_hash_test.cc b/test/frame_info_hash_test.cc
index c19172c6..331eabf1 100644
--- a/test/frame_info_hash_test.cc
+++ b/test/frame_info_hash_test.cc
@@ -33,8 +33,8 @@
#include "j2k_transcode.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_writer.h"
#include "openjpeg_image.h"
#include <boost/random.hpp>
#include <boost/test/unit_test.hpp>
@@ -47,7 +47,7 @@ using std::string;
static void
-check (shared_ptr<dcp::PictureAssetWriter> writer, boost::random::uniform_int_distribution<>& dist, boost::random::mt19937& rng, string hash)
+check (shared_ptr<dcp::J2KPictureAssetWriter> writer, boost::random::uniform_int_distribution<>& dist, boost::random::mt19937& rng, string hash)
{
auto xyz = make_shared<dcp::OpenJPEGImage>(dcp::Size(1998, 1080));
for (int c = 0; c < 3; ++c) {
@@ -66,14 +66,14 @@ check (shared_ptr<dcp::PictureAssetWriter> writer, boost::random::uniform_int_di
/** Test the hashing of data written to JPEG2000 MXFs with some random inputs */
BOOST_AUTO_TEST_CASE (frame_info_hash_test)
{
- auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
- auto writer = mp->start_write("build/test/frame_info_hash_test.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto writer = mp->start_write("build/test/frame_info_hash_test.mxf", dcp::Behaviour::MAKE_NEW);
boost::random::mt19937 rng(1);
boost::random::uniform_int_distribution<> dist(0, 4095);
/* Check a few random frames */
- check(writer, dist, rng, "a9e772602a2fd3135d940cfd727ab8ff");
- check(writer, dist, rng, "b075369922e42b23e1852a586ec43224");
- check(writer, dist, rng, "402395e76152db05b03c8f24ddfd7732");
+ check(writer, dist, rng, "8f3dc7321d6dff3d5691011de31fc713");
+ check(writer, dist, rng, "a305b83a40367fda1b5cf0efa096fd18");
+ check(writer, dist, rng, "1abc71e011ced46d9928a4b2d22e20f6");
}
diff --git a/test/kdm_test.cc b/test/kdm_test.cc
index 6f06b4c9..75a6019e 100644
--- a/test/kdm_test.cc
+++ b/test/kdm_test.cc
@@ -36,8 +36,8 @@
#include "cpl.h"
#include "decrypted_kdm.h"
#include "encrypted_kdm.h"
-#include "mono_picture_asset.h"
-#include "picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
+#include "j2k_picture_asset_writer.h"
#include "reel.h"
#include "reel_mono_picture_asset.h"
#include "reel_sound_asset.h"
@@ -256,9 +256,9 @@ BOOST_AUTO_TEST_CASE (validity_period_test1)
auto signer = make_shared<dcp::CertificateChain>(dcp::file_to_string("test/data/certificate_chain"));
signer->set_key(dcp::file_to_string("test/data/private.key"));
- auto asset = make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
+ auto asset = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
asset->set_key (dcp::Key());
- auto writer = asset->start_write("build/test/validity_period_test1.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto writer = asset->start_write("build/test/validity_period_test1.mxf", dcp::Behaviour::MAKE_NEW);
dcp::ArrayData frame ("test/data/flat_red.j2c");
writer->write (frame.data(), frame.size());
writer->finalize ();
@@ -320,7 +320,7 @@ BOOST_AUTO_TEST_CASE (vf_kdm_test)
ov->write_xml ();
auto ov_reel = ov->cpls()[0]->reels()[0];
- auto ov_reel_picture = make_shared<dcp::ReelMonoPictureAsset>(dynamic_pointer_cast<dcp::ReelMonoPictureAsset>(ov_reel->main_picture())->mono_asset(), 0);
+ auto ov_reel_picture = make_shared<dcp::ReelMonoPictureAsset>(dynamic_pointer_cast<dcp::ReelMonoPictureAsset>(ov_reel->main_picture())->mono_j2k_asset(), 0);
auto ov_reel_sound = make_shared<dcp::ReelSoundAsset>(ov_reel->main_sound()->asset(), 0);
/* Make VF */
@@ -376,7 +376,7 @@ BOOST_AUTO_TEST_CASE (vf_kdm_test)
BOOST_REQUIRE_EQUAL(reload_vf.cpls()[0]->reels().size(), 1U);
BOOST_REQUIRE(reload_vf.cpls()[0]->reels()[0]->main_picture());
BOOST_REQUIRE(reload_vf.cpls()[0]->reels()[0]->main_picture()->asset());
- auto mono_asset = dynamic_pointer_cast<dcp::MonoPictureAsset>(reload_vf.cpls()[0]->reels()[0]->main_picture()->asset());
+ auto mono_asset = dynamic_pointer_cast<dcp::MonoJ2KPictureAsset>(reload_vf.cpls()[0]->reels()[0]->main_picture()->asset());
BOOST_REQUIRE(mono_asset);
auto reader = mono_asset->start_read();
reader->set_check_hmac(false);
diff --git a/test/mca_test.cc b/test/mca_test.cc
index bdfc9484..1cd95732 100644
--- a/test/mca_test.cc
+++ b/test/mca_test.cc
@@ -168,7 +168,8 @@ check_mca_descriptors(int suffix, vector<dcp::Channel> extra_active_channels, ve
/* Check MXF */
- auto reader = new ASDCP::PCM::MXFReader();
+ Kumu::FileReaderFactory factory;
+ auto reader = new ASDCP::PCM::MXFReader(factory);
reader->OpenRead(boost::filesystem::path(dir / "mxf.mxf").string());
list<ASDCP::MXF::InterchangeObject*> channels;
diff --git a/test/mono_mpeg2_picture_read_test.cc b/test/mono_mpeg2_picture_read_test.cc
new file mode 100644
index 00000000..f0d4aac0
--- /dev/null
+++ b/test/mono_mpeg2_picture_read_test.cc
@@ -0,0 +1,62 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mono_mpeg2_picture_asset.h"
+#include "mpeg2_transcode.h"
+#include "test.h"
+#include <boost/test/unit_test.hpp>
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+}
+
+
+BOOST_AUTO_TEST_CASE(mpeg_mono_picture_read_test)
+{
+ dcp::MonoMPEG2PictureAsset asset(private_test / "data" / "mas" / "r2.mxf" );
+ std::cout << "frame rate " << asset.frame_rate().numerator << "\n";
+ std::cout << "duration " << asset.intrinsic_duration() << "\n";
+
+ auto reader = asset.start_read();
+
+ dcp::MPEG2Decompressor decompressor;
+ for (auto i = 0; i < asset.intrinsic_duration(); ++i) {
+ auto images = decompressor.decompress_frame(reader->get_frame(i));
+ BOOST_CHECK_EQUAL(images.size(), i == 0 ? 0U : 1U);
+ }
+
+ auto images = decompressor.flush();
+ BOOST_CHECK_EQUAL(images.size(), 1U);
+}
+
diff --git a/test/mono_mpeg2_picture_write_test.cc b/test/mono_mpeg2_picture_write_test.cc
new file mode 100644
index 00000000..44ce5ae4
--- /dev/null
+++ b/test/mono_mpeg2_picture_write_test.cc
@@ -0,0 +1,101 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "mono_mpeg2_picture_asset.h"
+#include "mpeg2_transcode.h"
+#include "test.h"
+#include <boost/test/unit_test.hpp>
+
+extern "C" {
+#include <libavcodec/avcodec.h>
+}
+
+
+BOOST_AUTO_TEST_CASE(mpeg_mono_picture_write_test)
+{
+ boost::filesystem::path dir = "build/test/mpeg2_mono_picture_write_test";
+
+ boost::system::error_code ec;
+ boost::filesystem::remove_all(dir);
+ boost::filesystem::create_directories(dir);
+
+ dcp::MonoMPEG2PictureAsset asset(dcp::Fraction{24, 1});
+ auto writer = asset.start_write(dir / "test.mxf", dcp::Behaviour::MAKE_NEW);
+
+ dcp::MPEG2Compressor compressor({1920, 1080}, 24, 50000000);
+ dcp::FFmpegImage image(int64_t(0));
+ for (auto y = 0; y < 1080; ++y) {
+ uint8_t* py = image.y() + y * image.y_stride();
+ for (auto x = 0; x < 1920; ++x) {
+ if (x < 640) {
+ *py++ = 76;
+ } else if (x < 1280) {
+ *py++ = 149;
+ } else {
+ *py++ = 29;
+ }
+ }
+ }
+
+ for (auto y = 0; y < 540; ++y) {
+ uint8_t* pu = image.u() + y * image.u_stride();
+ uint8_t* pv = image.v() + y * image.v_stride();
+ for (auto x = 0; x < 960; ++x) {
+ if (x < 320) {
+ *pu++ = 84;
+ *pv++ = 255;
+ } else if (x < 640) {
+ *pu++ = 43;
+ *pv++ = 21;
+ } else {
+ *pu++ = 255;
+ *pv++ = 107;
+ }
+ }
+ }
+
+ for (auto i = 0; i < 24; ++i) {
+ image.set_pts(int64_t(i));
+ if (auto compressed = compressor.compress_frame(image)) {
+ writer->write(compressed->first->data(), compressed->first->size());
+ }
+ }
+
+ if (auto compressed = compressor.flush()) {
+ writer->write(compressed->first->data(), compressed->first->size());
+ }
+
+ writer->finalize();
+}
+
diff --git a/test/recovery_test.cc b/test/recovery_test.cc
index eaf34f81..327c248a 100644
--- a/test/recovery_test.cc
+++ b/test/recovery_test.cc
@@ -32,8 +32,8 @@
*/
-#include "mono_picture_asset_writer.h"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
#include "test.h"
#include <asdcp/KM_util.h>
#include <boost/filesystem.hpp>
@@ -55,10 +55,10 @@ BOOST_AUTO_TEST_CASE (recovery)
boost::filesystem::remove_all ("build/test/baz");
boost::filesystem::create_directories ("build/test/baz");
- auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
- auto writer = mp->start_write("build/test/baz/video1.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto writer = mp->start_write("build/test/baz/video1.mxf", dcp::Behaviour::MAKE_NEW);
- int written_size = 0;
+ uint64_t written_size = 0;
for (int i = 0; i < 24; ++i) {
auto info = writer->write (data.data(), data.size());
BOOST_CHECK_EQUAL (info.hash, "c3c9a3adec09baf2b0bcb65806fbeac8");
@@ -82,13 +82,13 @@ BOOST_AUTO_TEST_CASE (recovery)
Kumu::ResetTestRNG ();
- mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
- writer = mp->start_write("build/test/baz/video2.mxf", dcp::PictureAsset::Behaviour::OVERWRITE_EXISTING);
+ mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ writer = mp->start_write("build/test/baz/video2.mxf", dcp::Behaviour::OVERWRITE_EXISTING);
writer->write (data.data(), data.size());
for (int i = 1; i < 4; ++i) {
- writer->fake_write (written_size);
+ writer->fake_write(dcp::J2KFrameInfo{0, written_size, "xxx"});
}
for (int i = 4; i < 24; ++i) {
diff --git a/test/ref/DCP/dcp_test1/ASSETMAP.xml b/test/ref/DCP/dcp_test1/ASSETMAP.xml
index 4e0d1e5a..dc811f79 100644
--- a/test/ref/DCP/dcp_test1/ASSETMAP.xml
+++ b/test/ref/DCP/dcp_test1/ASSETMAP.xml
@@ -37,7 +37,7 @@
<Path>video.mxf</Path>
<VolumeIndex>1</VolumeIndex>
<Offset>0</Offset>
- <Length>49240</Length>
+ <Length>31648</Length>
</Chunk>
</ChunkList>
</Asset>
diff --git a/test/ref/DCP/dcp_test1/audio.mxf b/test/ref/DCP/dcp_test1/audio.mxf
index 5e08f74f..1f5f7987 100644
--- a/test/ref/DCP/dcp_test1/audio.mxf
+++ b/test/ref/DCP/dcp_test1/audio.mxf
Binary files differ
diff --git a/test/ref/DCP/dcp_test1/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml b/test/ref/DCP/dcp_test1/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
index 15cda9a1..26d41070 100644
--- a/test/ref/DCP/dcp_test1/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
+++ b/test/ref/DCP/dcp_test1/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
@@ -37,7 +37,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>wUmt8G+cFFKMGt0ueS9+F1S4uhc=</Hash>
+ <Hash>vsVjRV9vhTBPUWfE/TT1o2vdQsI=</Hash>
<FrameRate>24 1</FrameRate>
<ScreenAspectRatio>1998 1080</ScreenAspectRatio>
</MainPicture>
@@ -47,7 +47,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>KcJb7S2K5cNm8RG4kfQD5FTeS0A=</Hash>
+ <Hash>3M7YTgvFKXXMEGLkIbV4miC90FE=</Hash>
</MainSound>
<meta:CompositionMetadataAsset xmlns:meta="http://www.smpte-ra.org/schemas/429-16/2014/CPL-Metadata">
<Id>urn:uuid:dd015243-ab77-435c-a13d-690566885121</Id>
diff --git a/test/ref/DCP/dcp_test1/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml b/test/ref/DCP/dcp_test1/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml
index cedbb15b..6a1392f3 100644
--- a/test/ref/DCP/dcp_test1/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml
+++ b/test/ref/DCP/dcp_test1/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml
@@ -9,7 +9,7 @@
<Asset>
<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab</Id>
<AnnotationText>6affb8ee-0020-4dff-a53c-17652f6358ab</AnnotationText>
- <Hash>tfX1mVIKJCVr1m7Y32Nzxf0+Rpw=</Hash>
+ <Hash>skI+5b/9LA/y6h0mcyxysJYanxI=</Hash>
<Size>8559</Size>
<Type>text/xml</Type>
<OriginalFileName>cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml</OriginalFileName>
@@ -17,15 +17,15 @@
<Asset>
<Id>urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54</Id>
<AnnotationText>5407b210-4441-4e97-8b16-8bdc7c12da54</AnnotationText>
- <Hash>wUmt8G+cFFKMGt0ueS9+F1S4uhc=</Hash>
- <Size>49240</Size>
+ <Hash>vsVjRV9vhTBPUWfE/TT1o2vdQsI=</Hash>
+ <Size>31648</Size>
<Type>application/mxf</Type>
<OriginalFileName>video.mxf</OriginalFileName>
</Asset>
<Asset>
<Id>urn:uuid:97f0f352-5b77-48ee-a558-9df37717f4fa</Id>
<AnnotationText>97f0f352-5b77-48ee-a558-9df37717f4fa</AnnotationText>
- <Hash>KcJb7S2K5cNm8RG4kfQD5FTeS0A=</Hash>
+ <Hash>3M7YTgvFKXXMEGLkIbV4miC90FE=</Hash>
<Size>881326</Size>
<Type>application/mxf</Type>
<OriginalFileName>audio.mxf</OriginalFileName>
diff --git a/test/ref/DCP/dcp_test1/video.mxf b/test/ref/DCP/dcp_test1/video.mxf
index 27ba41cf..cd0e43af 100644
--- a/test/ref/DCP/dcp_test1/video.mxf
+++ b/test/ref/DCP/dcp_test1/video.mxf
Binary files differ
diff --git a/test/ref/DCP/dcp_test2/audio.mxf b/test/ref/DCP/dcp_test2/audio.mxf
index e8bd446f..6a95baf3 100644
--- a/test/ref/DCP/dcp_test2/audio.mxf
+++ b/test/ref/DCP/dcp_test2/audio.mxf
Binary files differ
diff --git a/test/ref/DCP/dcp_test2/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml b/test/ref/DCP/dcp_test2/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
index 52a7779a..0e233325 100644
--- a/test/ref/DCP/dcp_test2/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
+++ b/test/ref/DCP/dcp_test2/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
@@ -22,7 +22,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>NzWhEbTccUIh1sSXIbU+8POVui0=</Hash>
+ <Hash>X+4lOvviLTQeP28hyzhCOGjraiE=</Hash>
</MainSound>
<msp-cpl:MainStereoscopicPicture xmlns:msp-cpl="http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL">
<Id>urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54</Id>
@@ -30,7 +30,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>BUpeFS6X9j+X0z2TZWSsLMT4pE0=</Hash>
+ <Hash>dU+tcR6bZ5BQ/TXKtBY03ejjUmc=</Hash>
<FrameRate>48 1</FrameRate>
<ScreenAspectRatio>1998 1080</ScreenAspectRatio>
</msp-cpl:MainStereoscopicPicture>
diff --git a/test/ref/DCP/dcp_test2/pkl_8577c7c0-be29-4eb5-a449-1e3870a42bbd.xml b/test/ref/DCP/dcp_test2/pkl_8577c7c0-be29-4eb5-a449-1e3870a42bbd.xml
index 061e8a6a..794cfb85 100644
--- a/test/ref/DCP/dcp_test2/pkl_8577c7c0-be29-4eb5-a449-1e3870a42bbd.xml
+++ b/test/ref/DCP/dcp_test2/pkl_8577c7c0-be29-4eb5-a449-1e3870a42bbd.xml
@@ -9,7 +9,7 @@
<Asset>
<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab</Id>
<AnnotationText>6affb8ee-0020-4dff-a53c-17652f6358ab</AnnotationText>
- <Hash>zaAcrAcv0oOzOa3etTP6xDfzQko=</Hash>
+ <Hash>2jp5+JDLOh5CqzQ8goZTzBEWsPo=</Hash>
<Size>1686</Size>
<Type>text/xml</Type>
<OriginalFileName>cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml</OriginalFileName>
@@ -17,7 +17,7 @@
<Asset>
<Id>urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54</Id>
<AnnotationText>5407b210-4441-4e97-8b16-8bdc7c12da54</AnnotationText>
- <Hash>BUpeFS6X9j+X0z2TZWSsLMT4pE0=</Hash>
+ <Hash>dU+tcR6bZ5BQ/TXKtBY03ejjUmc=</Hash>
<Size>63160</Size>
<Type>application/mxf</Type>
<OriginalFileName>video.mxf</OriginalFileName>
@@ -25,7 +25,7 @@
<Asset>
<Id>urn:uuid:fc843acc-1ad9-4808-b9ed-33f5319e047d</Id>
<AnnotationText>fc843acc-1ad9-4808-b9ed-33f5319e047d</AnnotationText>
- <Hash>NzWhEbTccUIh1sSXIbU+8POVui0=</Hash>
+ <Hash>X+4lOvviLTQeP28hyzhCOGjraiE=</Hash>
<Size>161326</Size>
<Type>application/mxf</Type>
<OriginalFileName>audio.mxf</OriginalFileName>
diff --git a/test/ref/DCP/dcp_test2/video.mxf b/test/ref/DCP/dcp_test2/video.mxf
index 3b670708..6200297c 100644
--- a/test/ref/DCP/dcp_test2/video.mxf
+++ b/test/ref/DCP/dcp_test2/video.mxf
Binary files differ
diff --git a/test/ref/DCP/dcp_test5/audio.mxf b/test/ref/DCP/dcp_test5/audio.mxf
index 947865e1..fc55b975 100644
--- a/test/ref/DCP/dcp_test5/audio.mxf
+++ b/test/ref/DCP/dcp_test5/audio.mxf
Binary files differ
diff --git a/test/ref/DCP/dcp_test5/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml b/test/ref/DCP/dcp_test5/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
index 5fa3643b..0dbd0198 100644
--- a/test/ref/DCP/dcp_test5/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
+++ b/test/ref/DCP/dcp_test5/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
@@ -22,7 +22,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>o3VmpdFsNUgF11oadcaGJ/IfO0M=</Hash>
+ <Hash>w7xIWU3Q+QnEQMq7BcOhsWO+OU0=</Hash>
<FrameRate>24 1</FrameRate>
<ScreenAspectRatio>1998 1080</ScreenAspectRatio>
</MainPicture>
@@ -32,7 +32,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>l+XLgxe2fMZDgY+0QYzDfGhvTQM=</Hash>
+ <Hash>5ANfi1KoyGiZ8hQIhDHm5f/OvQY=</Hash>
</MainSound>
<axd:AuxData xmlns:axd="http://www.dolby.com/schemas/2012/AD">
<Id>urn:uuid:b68febcc-5ddf-489a-84a7-924f29fa2afd</Id>
diff --git a/test/ref/DCP/dcp_test5/pkl_d76fdaaf-8316-42dc-a87e-1719ad6ca3ca.xml b/test/ref/DCP/dcp_test5/pkl_d76fdaaf-8316-42dc-a87e-1719ad6ca3ca.xml
index 49fd579b..e9b1e802 100644
--- a/test/ref/DCP/dcp_test5/pkl_d76fdaaf-8316-42dc-a87e-1719ad6ca3ca.xml
+++ b/test/ref/DCP/dcp_test5/pkl_d76fdaaf-8316-42dc-a87e-1719ad6ca3ca.xml
@@ -9,7 +9,7 @@
<Asset>
<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab</Id>
<AnnotationText>6affb8ee-0020-4dff-a53c-17652f6358ab</AnnotationText>
- <Hash>eqEIVxSAbJL+SROmqrDHbr9sb+A=</Hash>
+ <Hash>4zHV3/AhGYo5WjNmyuxeRSPOVwk=</Hash>
<Size>2024</Size>
<Type>text/xml</Type>
<OriginalFileName>cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml</OriginalFileName>
@@ -17,7 +17,7 @@
<Asset>
<Id>urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54</Id>
<AnnotationText>5407b210-4441-4e97-8b16-8bdc7c12da54</AnnotationText>
- <Hash>o3VmpdFsNUgF11oadcaGJ/IfO0M=</Hash>
+ <Hash>w7xIWU3Q+QnEQMq7BcOhsWO+OU0=</Hash>
<Size>40144</Size>
<Type>application/mxf</Type>
<OriginalFileName>video.mxf</OriginalFileName>
@@ -25,7 +25,7 @@
<Asset>
<Id>urn:uuid:97f0f352-5b77-48ee-a558-9df37717f4fa</Id>
<AnnotationText>97f0f352-5b77-48ee-a558-9df37717f4fa</AnnotationText>
- <Hash>l+XLgxe2fMZDgY+0QYzDfGhvTQM=</Hash>
+ <Hash>5ANfi1KoyGiZ8hQIhDHm5f/OvQY=</Hash>
<Size>161326</Size>
<Type>application/mxf</Type>
<OriginalFileName>audio.mxf</OriginalFileName>
diff --git a/test/ref/DCP/dcp_test5/video.mxf b/test/ref/DCP/dcp_test5/video.mxf
index f3e7588b..3ec65a51 100644
--- a/test/ref/DCP/dcp_test5/video.mxf
+++ b/test/ref/DCP/dcp_test5/video.mxf
Binary files differ
diff --git a/test/ref/DCP/dcp_test7/ASSETMAP b/test/ref/DCP/dcp_test7/ASSETMAP
index 86a6ff6a..e52b4b11 100644
--- a/test/ref/DCP/dcp_test7/ASSETMAP
+++ b/test/ref/DCP/dcp_test7/ASSETMAP
@@ -37,7 +37,7 @@
<Path>video.mxf</Path>
<VolumeIndex>1</VolumeIndex>
<Offset>0</Offset>
- <Length>49240</Length>
+ <Length>31648</Length>
</Chunk>
</ChunkList>
</Asset>
diff --git a/test/ref/DCP/dcp_test7/audio.mxf b/test/ref/DCP/dcp_test7/audio.mxf
index 5e08f74f..1f5f7987 100644
--- a/test/ref/DCP/dcp_test7/audio.mxf
+++ b/test/ref/DCP/dcp_test7/audio.mxf
Binary files differ
diff --git a/test/ref/DCP/dcp_test7/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml b/test/ref/DCP/dcp_test7/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
index b73ef84c..13aecd8a 100644
--- a/test/ref/DCP/dcp_test7/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
+++ b/test/ref/DCP/dcp_test7/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
@@ -37,7 +37,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>wUmt8G+cFFKMGt0ueS9+F1S4uhc=</Hash>
+ <Hash>vsVjRV9vhTBPUWfE/TT1o2vdQsI=</Hash>
<FrameRate>24 1</FrameRate>
<ScreenAspectRatio>1.85</ScreenAspectRatio>
</MainPicture>
@@ -47,7 +47,7 @@
<IntrinsicDuration>24</IntrinsicDuration>
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
- <Hash>KcJb7S2K5cNm8RG4kfQD5FTeS0A=</Hash>
+ <Hash>3M7YTgvFKXXMEGLkIbV4miC90FE=</Hash>
</MainSound>
</AssetList>
</Reel>
diff --git a/test/ref/DCP/dcp_test7/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml b/test/ref/DCP/dcp_test7/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml
index 4180eb8d..9d251109 100644
--- a/test/ref/DCP/dcp_test7/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml
+++ b/test/ref/DCP/dcp_test7/pkl_d199d58b-5ef8-4d49-b270-07e590ccb280.xml
@@ -9,7 +9,7 @@
<Asset>
<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab</Id>
<AnnotationText>6affb8ee-0020-4dff-a53c-17652f6358ab</AnnotationText>
- <Hash>Vsre14v3AhK6X2gUzeYF9G8GKo0=</Hash>
+ <Hash>SgCEvehTaji0MCWOJTVioOcNndY=</Hash>
<Size>1965</Size>
<Type>text/xml;asdcpKind=CPL</Type>
<OriginalFileName>cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml</OriginalFileName>
@@ -17,15 +17,15 @@
<Asset>
<Id>urn:uuid:5407b210-4441-4e97-8b16-8bdc7c12da54</Id>
<AnnotationText>5407b210-4441-4e97-8b16-8bdc7c12da54</AnnotationText>
- <Hash>wUmt8G+cFFKMGt0ueS9+F1S4uhc=</Hash>
- <Size>49240</Size>
+ <Hash>vsVjRV9vhTBPUWfE/TT1o2vdQsI=</Hash>
+ <Size>31648</Size>
<Type>application/x-smpte-mxf;asdcpKind=Picture</Type>
<OriginalFileName>video.mxf</OriginalFileName>
</Asset>
<Asset>
<Id>urn:uuid:97f0f352-5b77-48ee-a558-9df37717f4fa</Id>
<AnnotationText>97f0f352-5b77-48ee-a558-9df37717f4fa</AnnotationText>
- <Hash>KcJb7S2K5cNm8RG4kfQD5FTeS0A=</Hash>
+ <Hash>3M7YTgvFKXXMEGLkIbV4miC90FE=</Hash>
<Size>881326</Size>
<Type>application/x-smpte-mxf;asdcpKind=Sound</Type>
<OriginalFileName>audio.mxf</OriginalFileName>
diff --git a/test/ref/DCP/dcp_test7/video.mxf b/test/ref/DCP/dcp_test7/video.mxf
index 27ba41cf..cd0e43af 100644
--- a/test/ref/DCP/dcp_test7/video.mxf
+++ b/test/ref/DCP/dcp_test7/video.mxf
Binary files differ
diff --git a/test/ref/DCP/encryption_test/audio.mxf b/test/ref/DCP/encryption_test/audio.mxf
index a4f89ae9..505b7f13 100644
--- a/test/ref/DCP/encryption_test/audio.mxf
+++ b/test/ref/DCP/encryption_test/audio.mxf
Binary files differ
diff --git a/test/ref/DCP/encryption_test/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml b/test/ref/DCP/encryption_test/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
index e8e24467..6203c884 100644
--- a/test/ref/DCP/encryption_test/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
+++ b/test/ref/DCP/encryption_test/cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml
@@ -23,7 +23,7 @@
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
<KeyId>urn:uuid:ac8d301c-e5d9-4343-b6f3-ba2668adbe56</KeyId>
- <Hash>AVtX8wz76uG2Uw0Qbc9+DKnHUfw=</Hash>
+ <Hash>Q0GMntXvEqVQsiv+YkfhMrXdw0w=</Hash>
<FrameRate>24 1</FrameRate>
<ScreenAspectRatio>1998 1080</ScreenAspectRatio>
</MainPicture>
@@ -34,7 +34,7 @@
<EntryPoint>0</EntryPoint>
<Duration>24</Duration>
<KeyId>urn:uuid:7ab6c77b-6648-44b9-8549-a5290ada6238</KeyId>
- <Hash>3o02UpYqrl6w0NQbFvrB2tKxaIk=</Hash>
+ <Hash>v0SCdh2xnKNzGC7Sk5pS2q5Q/wQ=</Hash>
</MainSound>
</AssetList>
</Reel>
@@ -57,15 +57,15 @@
<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
- <dsig:DigestValue>X3YkODMLyEJsAz5v3S/uT+xDD7c=</dsig:DigestValue>
+ <dsig:DigestValue>DBBENxFb5Qv377fb86n0KgUQ7go=</dsig:DigestValue>
</dsig:Reference>
</dsig:SignedInfo>
- <dsig:SignatureValue>jH02vGxlTTi9T94KCIfMkafmdO0wluP9cvh+u5HyYoZo/D7O1Ki202t5uHRp0wcu
-OfBFuu1Hw3Ooy/VEa2l4l/UDfE7lI+D79e0VfA8HwFB+c21GF7Q2FRV5ddu9ODgz
-rk6kC5fZSLxc7cpK6jPNnT285O3nHfjk6MQ0fgGfNbvMefgeEWVKj8qcyFgN6H4e
-wr1omcjbdw/HVQaOW84//pBRSRdMJGe1u2iUE2RwxBLzP4BepzkMv9Asm6uDo1YG
-X1d60g2aCUdxAg9fjyTaOss1nRp1YdPlb3SHUhKXgTT/eAPkmmr7bs3jJtp2BN9U
-4Izz2GR/3Uyf0NP20mZgNQ==</dsig:SignatureValue>
+ <dsig:SignatureValue>rhF1QacGUhxm1jfcgyBjAo2BmD4QxBl7c6Bzt8rjXXhR+NVT4ITeyxi39+94WwBx
+Yp8iQhF46bE2QGZAr+HnZZJGVG3ajeaQ4uvPp2KRC8sHpBlZ2rGGtyjXAflYjepw
+c1cLvRoAKbxOMW+ESxjyYOKgT0Bke0GhbzZ8+w+hGZLHxK9oTokIG9YDnRNUKN5W
+n6avbxuaT8wtZgVwD4qfKzMeJlYW3yDFo/2apQA5K+oCj/gfrS1habYqBoNo9kO1
+fWkQ7LIeRrYuzNlr5K4e/LyIm7SHwb9EGcA7K8WbDrHKvaJmTs/T01QhU9f+huk2
+ZGJMMCGHhiwcbVtqVhgJSQ==</dsig:SignatureValue>
<dsig:KeyInfo>
<dsig:X509Data>
<dsig:X509IssuerSerial>
diff --git a/test/ref/DCP/encryption_test/pkl_5203f3d4-9d62-4062-8bf1-7a114eff99df.xml b/test/ref/DCP/encryption_test/pkl_5203f3d4-9d62-4062-8bf1-7a114eff99df.xml
index 4d49b259..fb0313ab 100644
--- a/test/ref/DCP/encryption_test/pkl_5203f3d4-9d62-4062-8bf1-7a114eff99df.xml
+++ b/test/ref/DCP/encryption_test/pkl_5203f3d4-9d62-4062-8bf1-7a114eff99df.xml
@@ -9,7 +9,7 @@
<Asset>
<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab</Id>
<AnnotationText>6affb8ee-0020-4dff-a53c-17652f6358ab</AnnotationText>
- <Hash>Zd9zaFAGx/4W2B3vSZkAqTzcDZ0=</Hash>
+ <Hash>sLWF9OcgdkvBUH1VcNiwseLA3sA=</Hash>
<Size>9226</Size>
<Type>text/xml</Type>
<OriginalFileName>cpl_6affb8ee-0020-4dff-a53c-17652f6358ab.xml</OriginalFileName>
@@ -17,7 +17,7 @@
<Asset>
<Id>urn:uuid:9a7fbb03-4078-4944-90b1-0d8a21c9d793</Id>
<AnnotationText>9a7fbb03-4078-4944-90b1-0d8a21c9d793</AnnotationText>
- <Hash>AVtX8wz76uG2Uw0Qbc9+DKnHUfw=</Hash>
+ <Hash>Q0GMntXvEqVQsiv+YkfhMrXdw0w=</Hash>
<Size>44008</Size>
<Type>application/mxf</Type>
<OriginalFileName>video.mxf</OriginalFileName>
@@ -25,7 +25,7 @@
<Asset>
<Id>urn:uuid:ce300880-a425-40a6-adac-eb1e3f5643fc</Id>
<AnnotationText>ce300880-a425-40a6-adac-eb1e3f5643fc</AnnotationText>
- <Hash>3o02UpYqrl6w0NQbFvrB2tKxaIk=</Hash>
+ <Hash>v0SCdh2xnKNzGC7Sk5pS2q5Q/wQ=</Hash>
<Size>165454</Size>
<Type>application/mxf</Type>
<OriginalFileName>audio.mxf</OriginalFileName>
@@ -49,15 +49,15 @@
<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
- <dsig:DigestValue>0F1ZXfoRDPIQHlRG0MC1uXkahG8=</dsig:DigestValue>
+ <dsig:DigestValue>OU1UpJxBmpxK8SE5yfe8aJsqoIw=</dsig:DigestValue>
</dsig:Reference>
</dsig:SignedInfo>
- <dsig:SignatureValue>u98MLscN/Fn3YxGFMw6kP7fIWUj05FPxQvIYvsIpP68UP3FX9rdP6nh3Olyv194d
-A1fQJu4ZamTcYN2O2E5vdGjxxHlPNXfFPckWc9Sy1i3V8u+EFdOggjMY4snvPot6
-kMyzAICuKzTJs4l+O/BzJAJSFSxrEtBCYEFxrtyKntDxSUE7ePSqPwcim6+5BzDO
-QOsIp3wjJHlp7u4QqU3knIiaM7SibIXqtIBF7TOrChWZjFImKePNib9/DXvnE2WL
-Y+5wJjGhImQR+2U2DDpSCLkl0kVgDrYfKcNg4lXUDZGEKo0Yqz0+1Rszz/DqsC+J
-6mYxqMMvRXeh9pViSpgKaA==</dsig:SignatureValue>
+ <dsig:SignatureValue>ypg6tt5iJi7YEUJQfEQmZeigXzcm2xn/J59tqqYBqwmAch1ia//Khyo6m7/HpQJl
+2Y5swUI8MtmzdV3gj3urd8WuQsDWFLflIHHiIanYE/XCdFZ8lV/nvyCkAaf/AH2V
+W7bWD8/fYXJD2G9a2tRiWTjzfgpsTk+ox+C12Y/SebWAQ97sSLIMwwmQIYK2kTnh
+nbKSuhk+v+V2ObpYl48zXu3za3Yt77rCdcGgPwYr/NUI47ascpnueNw48clDtjp+
+775jeA5ZG5lBR3VGTLwvoOXT3CH/FgG0DPSLmYbRnOzEShVUt7xFgbxMgNTYOGQJ
+3ipS6qmHgWHjX3/fo6isgg==</dsig:SignatureValue>
<dsig:KeyInfo>
<dsig:X509Data>
<dsig:X509IssuerSerial>
diff --git a/test/ref/DCP/encryption_test/video.mxf b/test/ref/DCP/encryption_test/video.mxf
index 2fbfacdd..e6ddbadb 100644
--- a/test/ref/DCP/encryption_test/video.mxf
+++ b/test/ref/DCP/encryption_test/video.mxf
Binary files differ
diff --git a/test/round_trip_test.cc b/test/round_trip_test.cc
index 028accbe..ffba5cbd 100644
--- a/test/round_trip_test.cc
+++ b/test/round_trip_test.cc
@@ -35,15 +35,15 @@
#include "decrypted_kdm.h"
#include "encrypted_kdm.h"
#include "certificate_chain.h"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
#include "sound_asset.h"
#include "reel.h"
#include "test.h"
#include "cpl.h"
-#include "mono_picture_frame.h"
+#include "mono_j2k_picture_frame.h"
#include "certificate_chain.h"
-#include "mono_picture_asset_writer.h"
-#include "mono_picture_asset_reader.h"
+#include "mono_j2k_picture_asset_writer.h"
+#include "mono_j2k_picture_asset_reader.h"
#include "reel_picture_asset.h"
#include "reel_mono_picture_asset.h"
#include "openjpeg_image.h"
@@ -70,8 +70,8 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
boost::filesystem::path work_dir = "build/test/round_trip_test";
boost::filesystem::create_directory (work_dir);
- auto asset_A = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
- auto writer = asset_A->start_write(work_dir / "video.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto asset_A = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto writer = asset_A->start_write(work_dir / "video.mxf", dcp::Behaviour::MAKE_NEW);
dcp::ArrayData j2c ("test/data/flat_red.j2c");
for (int i = 0; i < 24; ++i) {
writer->write (j2c.data (), j2c.size ());
@@ -123,7 +123,7 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
}
/* Reload the picture asset */
- auto asset_B = make_shared<dcp::MonoPictureAsset>(work_dir / "video.mxf");
+ auto asset_B = make_shared<dcp::MonoJ2KPictureAsset>(work_dir / "video.mxf");
BOOST_CHECK (!kdm_B.keys().empty ());
asset_B->set_key (kdm_B.keys().front().key());
diff --git a/test/shared_subtitle_test.cc b/test/shared_subtitle_test.cc
index 7ac20e10..22ee7177 100644
--- a/test/shared_subtitle_test.cc
+++ b/test/shared_subtitle_test.cc
@@ -175,13 +175,13 @@ BOOST_AUTO_TEST_CASE (format_xml_test1)
{
xmlpp::Document doc;
auto root = doc.create_root_node("Foo");
- root->add_child("Empty");
- root->add_child("Text")->add_child_text("Hello world");
- root->add_child("Font")->add_child("Text")->add_child_text("Say what");
- auto fred = root->add_child("Text")->add_child("Font");
+ cxml::add_child(root, "Empty");
+ cxml::add_text_child(root, "Text", "Hello world");
+ cxml::add_text_child(cxml::add_child(root, "Font"), "Text", "Say what");
+ auto fred = cxml::add_child(cxml::add_child(root, "Text"), "Font");
fred->set_attribute("bob", "job");
fred->add_child_text("Fred");
- fred->add_child("Text")->add_child_text("Jim");
+ cxml::add_text_child(fred, "Text", "Jim");
fred->add_child_text("Sheila");
BOOST_REQUIRE_EQUAL (dcp::SubtitleAsset::format_xml(doc, make_pair(string{}, string{"fred"})),
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
@@ -210,7 +210,7 @@ BOOST_AUTO_TEST_CASE (format_xml_entities_test)
{
xmlpp::Document doc;
auto root = doc.create_root_node("Foo");
- root->add_child("Bar")->add_child_text("Don't panic &amp; xml \"is\" 'great' & < > —");
+ cxml::add_text_child(root, "Bar", "Don't panic &amp; xml \"is\" 'great' & < > —");
BOOST_REQUIRE_EQUAL(dcp::SubtitleAsset::format_xml(doc, {}),
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<Foo>\n"
diff --git a/test/stream_operators.cc b/test/stream_operators.cc
index 0ed0d05f..348abd2f 100644
--- a/test/stream_operators.cc
+++ b/test/stream_operators.cc
@@ -214,6 +214,9 @@ ostream&
dcp::operator<< (ostream& s, VerificationNote::Type t)
{
switch (t) {
+ case VerificationNote::Type::OK:
+ s << "check";
+ break;
case VerificationNote::Type::ERROR:
s << "error";
break;
diff --git a/test/test.cc b/test/test.cc
index d384bdfa..51a631d2 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -39,11 +39,11 @@
#include "interop_subtitle_asset.h"
#include "file.h"
#include "j2k_transcode.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
#include "openjpeg_image.h"
-#include "picture_asset_writer.h"
-#include "picture_asset_writer.h"
+#include "j2k_picture_asset_writer.h"
+#include "j2k_picture_asset_writer.h"
#include "reel.h"
#include "reel_asset.h"
#include "reel_interop_closed_caption_asset.h"
@@ -122,7 +122,7 @@ check_xml (xmlpp::Element* ref, xmlpp::Element* test, vector<string> ignore_tags
BOOST_CHECK_EQUAL (ref->get_name (), test->get_name ());
BOOST_CHECK_EQUAL (ref->get_namespace_prefix (), test->get_namespace_prefix ());
- if (find(ignore_tags.begin(), ignore_tags.end(), ref->get_name()) != ignore_tags.end()) {
+ if (find(ignore_tags.begin(), ignore_tags.end(), std::string(ref->get_name())) != ignore_tags.end()) {
return;
}
@@ -260,18 +260,18 @@ check_file (boost::filesystem::path ref, boost::filesystem::path check)
RNGFixer::RNGFixer ()
{
- Kumu::cth_test = true;
+ Kumu::dcpomatic_test = true;
Kumu::FortunaRNG().Reset();
}
RNGFixer::~RNGFixer ()
{
- Kumu::cth_test = false;
+ Kumu::dcpomatic_test = false;
}
-shared_ptr<dcp::MonoPictureAsset>
+shared_ptr<dcp::MonoJ2KPictureAsset>
simple_picture (boost::filesystem::path path, string suffix, int frames, optional<dcp::Key> key)
{
dcp::MXFMetadata mxf_meta;
@@ -279,12 +279,12 @@ simple_picture (boost::filesystem::path path, string suffix, int frames, optiona
mxf_meta.product_name = "OpenDCP";
mxf_meta.product_version = "0.0.25";
- auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
mp->set_metadata (mxf_meta);
if (key) {
mp->set_key (*key);
}
- auto picture_writer = mp->start_write(path / dcp::String::compose("video%1.mxf", suffix), dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto picture_writer = mp->start_write(path / dcp::String::compose("video%1.mxf", suffix), dcp::Behaviour::MAKE_NEW);
dcp::Size const size (1998, 1080);
auto image = make_shared<dcp::OpenJPEGImage>(size);
@@ -530,10 +530,10 @@ black_picture_asset (boost::filesystem::path dir, int frames)
auto frame = dcp::compress_j2k (image, 100000000, 24, false, false);
BOOST_REQUIRE (frame.size() < 230000000 / (24 * 8));
- auto asset = make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
+ auto asset = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
asset->set_metadata (dcp::MXFMetadata("libdcp", "libdcp", "1.6.4devel"));
boost::filesystem::create_directories (dir);
- auto writer = asset->start_write(dir / "pic.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto writer = asset->start_write(dir / "pic.mxf", dcp::Behaviour::MAKE_NEW);
for (int i = 0; i < frames; ++i) {
writer->write (frame.data(), frame.size());
}
@@ -567,7 +567,11 @@ Editor::Editor(boost::filesystem::path path)
Editor::~Editor()
{
- auto f = fopen(_path.string().c_str(), "w");
+ /* Open this binary so that text files are re-written with Unix endings even on Windows,
+ * so that if we subsequently get hashes of edited files the hashes are the same on
+ * all platforms.
+ */
+ auto f = fopen(_path.string().c_str(), "wb");
BOOST_REQUIRE (f);
fwrite (_content.c_str(), _content.length(), 1, f);
fclose (f);
diff --git a/test/test.h b/test/test.h
index bacb9311..d3fded87 100644
--- a/test/test.h
+++ b/test/test.h
@@ -34,7 +34,7 @@ namespace xmlpp {
namespace dcp {
class DCP;
- class MonoPictureAsset;
+ class MonoJ2KPictureAsset;
class SoundAsset;
}
@@ -44,7 +44,7 @@ extern boost::filesystem::path xsd_test;
extern void check_xml (xmlpp::Element* ref, xmlpp::Element* test, std::vector<std::string> ignore_tags, bool ignore_whitespace = false);
extern void check_xml (std::string ref, std::string test, std::vector<std::string> ignore, bool ignore_whitespace = false);
extern void check_file (boost::filesystem::path ref, boost::filesystem::path check);
-extern std::shared_ptr<dcp::MonoPictureAsset> simple_picture (
+extern std::shared_ptr<dcp::MonoJ2KPictureAsset> simple_picture (
boost::filesystem::path path,
std::string suffix,
int frames = 24,
diff --git a/test/verify_report_test.cc b/test/verify_report_test.cc
new file mode 100644
index 00000000..6b288891
--- /dev/null
+++ b/test/verify_report_test.cc
@@ -0,0 +1,67 @@
+/*
+ Copyright (C) 2022 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic 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.
+
+ DCP-o-matic 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 DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "verify.h"
+#include "verify_report.h"
+#include <boost/test/unit_test.hpp>
+#include "test.h"
+
+
+BOOST_AUTO_TEST_CASE(verify_report_basically_ok)
+{
+ dcp::HTMLFormatter formatter("build/test/verify_report_basically_ok.html");
+ dcp::verify_report(
+ dcp::verify(
+ { private_test / "TONEPLATES-SMPTE-PLAINTEXT_TST_F_XX-XX_ITL-TD_51-XX_2K_WOE_20111001_WOE_OV" },
+ {},
+ [](std::string, boost::optional<boost::filesystem::path>) {},
+ [](float) {},
+ {},
+ xsd_test
+ ),
+ formatter
+ );
+}
+
+
+BOOST_AUTO_TEST_CASE(text_formatter)
+{
+ {
+ dcp::TextFormatter fmt("build/test/text_formatter.txt");
+
+ fmt.heading("Heading");
+ fmt.subheading("Subheading");
+ auto A = fmt.unordered_list();
+ fmt.list_item("Foo");
+ fmt.list_item("Bar");
+ auto B = fmt.unordered_list();
+ fmt.list_item("Fred");
+ fmt.list_item("Jim");
+ fmt.list_item("Sheila");
+ }
+
+#ifdef LIBDCP_WINDOWS
+ check_file("test/data/text_formatter_windows.txt", "build/test/text_formatter.txt");
+#else
+ check_file("test/data/text_formatter.txt", "build/test/text_formatter.txt");
+#endif
+}
+
diff --git a/test/verify_test.cc b/test/verify_test.cc
index 5a9489fe..80d0490e 100644
--- a/test/verify_test.cc
+++ b/test/verify_test.cc
@@ -38,8 +38,8 @@
#include "file.h"
#include "interop_subtitle_asset.h"
#include "j2k_transcode.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_writer.h"
#include "openjpeg_image.h"
#include "raw_convert.h"
#include "reel.h"
@@ -52,7 +52,7 @@
#include "reel_smpte_closed_caption_asset.h"
#include "reel_smpte_subtitle_asset.h"
#include "smpte_subtitle_asset.h"
-#include "stereo_picture_asset.h"
+#include "stereo_j2k_picture_asset.h"
#include "stream_operators.h"
#include "test.h"
#include "util.h"
@@ -63,6 +63,7 @@
#include <boost/test/unit_test.hpp>
#include <cstdio>
#include <iostream>
+#include <tuple>
using std::list;
@@ -148,6 +149,43 @@ prepare_directory (path path)
}
+static
+path
+find_prefix(path dir, string prefix)
+{
+ auto iter = std::find_if(directory_iterator(dir), directory_iterator(), [prefix](path const& p) {
+ return boost::starts_with(p.filename().string(), prefix);
+ });
+
+ BOOST_REQUIRE(iter != directory_iterator());
+ return iter->path();
+}
+
+
+static
+path
+find_cpl(path dir)
+{
+ return find_prefix(dir, "cpl_");
+}
+
+
+static
+path
+find_pkl(path dir)
+{
+ return find_prefix(dir, "pkl_");
+}
+
+
+static
+path
+find_asset_map(path dir)
+{
+ return find_prefix(dir, "ASSETMAP");
+}
+
+
/** Copy dcp_test{reference_number} to build/test/verify_test{verify_test_suffix}
* to make a new sacrificial test DCP.
*/
@@ -196,53 +234,85 @@ LIBDCP_ENABLE_WARNINGS
static
+string
+to_string(dcp::VerificationNote const& note)
+{
+ string s = note_to_string(note) + dcp::String::compose(
+ "\n [%1 %2 %3 %4 %5 %6 ",
+ static_cast<int>(note.type()),
+ static_cast<int>(note.code()),
+ note.note().get_value_or("<none>"),
+ note.file().get_value_or("<none>"),
+ note.line().get_value_or(0),
+ note.frame().get_value_or(0)
+ );
+
+ s += dcp::String::compose(
+ "%1 %2 %3 %4 %5]\n",
+ note.id().get_value_or("<none>"),
+ note.other_id().get_value_or("<none>"),
+ note.cpl_id().get_value_or("<none>"),
+ note.reference_hash().get_value_or("<none>"),
+ note.calculated_hash().get_value_or("<none>")
+ );
+
+ return s;
+}
+
+
+static
void
-check_verify_result(vector<path> dir, vector<dcp::DecryptedKDM> kdm, vector<dcp::VerificationNote> test_notes)
+check_verify_result(vector<dcp::VerificationNote> notes, vector<dcp::VerificationNote> test_notes)
{
- auto notes = dcp::verify({dir}, kdm, &stage, &progress, {}, xsd_test);
- std::sort (notes.begin(), notes.end());
- std::sort (test_notes.begin(), test_notes.end());
+ std::sort(notes.begin(), notes.end());
+ std::sort(test_notes.begin(), test_notes.end());
- string message = "\nVerification notes from test:\n";
- for (auto i: notes) {
- message += " " + note_to_string(i) + "\n";
- message += dcp::String::compose(
- " [%1 %2 %3 %4 %5 %6 %7]\n",
- static_cast<int>(i.type()),
- static_cast<int>(i.code()),
- i.note().get_value_or("<none>"),
- i.file().get_value_or("<none>"),
- i.line().get_value_or(0),
- i.reference_hash().get_value_or("<none>"),
- i.calculated_hash().get_value_or("<none>")
- );
+ string message = "\n";
+
+ vector<dcp::VerificationNote> not_expected;
+ for (auto note: notes) {
+ auto iter = std::find_if(test_notes.begin(), test_notes.end(), [note](dcp::VerificationNote const& n) { return note.type() == n.type() && note.code() == n.code(); });
+ if (iter != test_notes.end() && *iter != note) {
+ message += "Wrong details:\n --seen " + to_string(note) + " --expected " + to_string(*iter) + "\n";
+ } else if (iter == test_notes.end()) {
+ not_expected.push_back(note);
+ }
}
- message += "Expected:\n";
- for (auto i: test_notes) {
- message += " " + note_to_string(i) + "\n";
- message += dcp::String::compose(
- " [%1 %2 %3 %4 %5 %6 %7]\n",
- static_cast<int>(i.type()),
- static_cast<int>(i.code()),
- i.note().get_value_or("<none>"),
- i.file().get_value_or("<none>"),
- i.line().get_value_or(0),
- i.reference_hash().get_value_or("<none>"),
- i.calculated_hash().get_value_or("<none>")
- );
+
+ vector<dcp::VerificationNote> not_seen;
+ for (auto note: test_notes) {
+ auto iter = std::find_if(notes.begin(), notes.end(), [note](dcp::VerificationNote const& n) { return note.type() == n.type() && note.code() == n.code(); });
+ if (iter == notes.end()) {
+ not_seen.push_back(note);
+ }
+ }
+
+ for (auto note: not_expected) {
+ message += "Not expected:\n" + to_string(note) + "\n";
}
- BOOST_REQUIRE_MESSAGE (notes == test_notes, message);
+ for (auto note: not_seen) {
+ message += "Not seen:\n" + to_string(note) + "\n";
+ }
+
+ BOOST_REQUIRE_MESSAGE(notes == test_notes, message);
+}
+
+
+static
+void
+check_verify_result(vector<path> dir, vector<dcp::DecryptedKDM> kdm, vector<dcp::VerificationNote> test_notes)
+{
+ check_verify_result(dcp::verify({dir}, kdm, &stage, &progress, {}, xsd_test).notes, test_notes);
}
/* Copy dcp_test1 to build/test/verify_test{suffix} then edit a file found by the functor 'file',
- * replacing from with to. Verify the resulting DCP and check that the results match the given
- * list of codes.
+ * replacing from with to.
*/
static
void
-check_verify_result_after_replace (string suffix, boost::function<path (string)> file, string from, string to, vector<dcp::VerificationNote::Code> codes)
+replace(string suffix, boost::function<path (string)> file, string from, string to)
{
auto dir = setup (1, suffix);
@@ -250,17 +320,6 @@ check_verify_result_after_replace (string suffix, boost::function<path (string)>
Editor e (file(suffix));
e.replace (from, to);
}
-
- auto notes = dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test);
-
- BOOST_REQUIRE_EQUAL (notes.size(), codes.size());
- auto i = notes.begin();
- auto j = codes.begin();
- while (i != notes.end()) {
- BOOST_CHECK_EQUAL (i->code(), *j);
- ++i;
- ++j;
- }
}
@@ -295,11 +354,44 @@ private:
};
+static
+dcp::VerificationNote
+ok(dcp::VerificationNote::Code code, shared_ptr<const dcp::CPL> cpl)
+{
+ return dcp::VerificationNote(dcp::VerificationNote::Type::OK, code).set_cpl_id(cpl->id());
+}
+
+
+static
+dcp::VerificationNote
+ok(dcp::VerificationNote::Code code, string note, shared_ptr<const dcp::CPL> cpl)
+{
+ return dcp::VerificationNote(dcp::VerificationNote::Type::OK, code, note).set_cpl_id(cpl->id());
+}
+
+
+static
+dcp::VerificationNote
+ok(dcp::VerificationNote::Code code, boost::filesystem::path path, shared_ptr<const dcp::CPL> cpl)
+{
+ return dcp::VerificationNote(dcp::VerificationNote::Type::OK, code, path).set_cpl_id(cpl->id());
+}
+
+
+void
+add(vector<dcp::VerificationNote>& notes, vector<dcp::VerificationNote> const& add)
+{
+ for (auto i: add) {
+ notes.push_back(i);
+ }
+}
+
+
BOOST_AUTO_TEST_CASE (verify_no_error)
{
stages.clear ();
auto dir = setup (1, "no_error");
- auto notes = dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test);
+ auto notes = dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes;
path const cpl_file = dir / dcp_test1_cpl();
path const pkl_file = dir / dcp_test1_pkl();
@@ -342,7 +434,9 @@ BOOST_AUTO_TEST_CASE (verify_no_error)
++st;
BOOST_REQUIRE (st == stages.end());
- BOOST_CHECK_EQUAL (notes.size(), 0U);
+ for (auto note: notes) {
+ BOOST_CHECK(note.type() == dcp::VerificationNote::Type::OK);
+ }
}
@@ -351,21 +445,22 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_picture_sound_hash)
using namespace boost::filesystem;
auto dir = setup (1, "incorrect_picture_sound_hash");
+ auto cpl = make_shared<dcp::CPL>(find_cpl(dir));
auto video_path = path(dir / "video.mxf");
HashCalculator video_calc(video_path);
auto mod = fopen(video_path.string().c_str(), "r+b");
BOOST_REQUIRE (mod);
- fseek (mod, 4096, SEEK_SET);
+ BOOST_REQUIRE_EQUAL(fseek(mod, -16, SEEK_END), 0);
int x = 42;
- fwrite (&x, sizeof(x), 1, mod);
+ BOOST_REQUIRE(fwrite(&x, sizeof(x), 1, mod) == 1);
fclose (mod);
auto audio_path = path(dir / "audio.mxf");
HashCalculator audio_calc(audio_path);
mod = fopen(audio_path.string().c_str(), "r+b");
BOOST_REQUIRE (mod);
- BOOST_REQUIRE_EQUAL (fseek(mod, -64, SEEK_END), 0);
+ BOOST_REQUIRE_EQUAL(fseek(mod, 0, SEEK_END), 0);
BOOST_REQUIRE (fwrite (&x, sizeof(x), 1, mod) == 1);
fclose (mod);
@@ -374,12 +469,25 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_picture_sound_hash)
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(dcp_test1_cpl_id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INCORRECT_PICTURE_HASH, canonical(video_path)
- ).set_reference_hash(video_calc.old_hash()).set_calculated_hash(video_calc.new_hash()),
+ ).set_cpl_id(dcp_test1_cpl_id()).set_reference_hash(video_calc.old_hash()).set_calculated_hash(video_calc.new_hash()),
dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INCORRECT_SOUND_HASH, canonical(audio_path)
- ).set_reference_hash(audio_calc.old_hash()).set_calculated_hash(audio_calc.new_hash()),
+ ).set_cpl_id(dcp_test1_cpl_id()).set_reference_hash(audio_calc.old_hash()).set_calculated_hash(audio_calc.new_hash()),
});
}
@@ -389,6 +497,7 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_picture_sound_hashes)
using namespace boost::filesystem;
auto dir = setup (1, "mismatched_picture_sound_hashes");
+ auto cpl = make_shared<dcp::CPL>(find_cpl(dir));
HashCalculator calc(dir / dcp_test1_cpl());
@@ -401,14 +510,30 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_picture_sound_hashes)
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(dir / dcp_test1_cpl())
+ ).set_cpl_id(dcp_test1_cpl_id()).set_reference_hash("x" + calc.old_hash()).set_calculated_hash(calc.old_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_PICTURE_HASHES, canonical(dir / "video.mxf")
+ ).set_cpl_id(dcp_test1_cpl_id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, dcp_test1_cpl_id(), canonical(dir / dcp_test1_cpl())
- ).set_reference_hash("x" + calc.old_hash()).set_calculated_hash(calc.old_hash()),
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_PICTURE_HASHES, canonical(dir / "video.mxf") },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_SOUND_HASHES, canonical(dir / "audio.mxf") },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xKcJb7S2K5cNm8RG4kfQD5FTeS0A=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl()), 28 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xtfX1mVIKJCVr1m7Y32Nzxf0+Rpw=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl()), 12 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xwUmt8G+cFFKMGt0ueS9+F1S4uhc=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl()), 20 },
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_SOUND_HASHES, canonical(dir / "audio.mxf")
+ ).set_cpl_id(dcp_test1_cpl_id()),
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'x3M7YTgvFKXXMEGLkIbV4miC90FE=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl()), 28 },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xskI+5b/9LA/y6h0mcyxysJYanxI=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl()), 12 },
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "value 'xvsVjRV9vhTBPUWfE/TT1o2vdQsI=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl()), 20 },
});
}
@@ -424,21 +549,37 @@ BOOST_AUTO_TEST_CASE (verify_failed_read_content_kind)
e.replace ("<ContentKind>", "<ContentKind>x");
}
+ auto cpl = std::make_shared<dcp::CPL>(find_cpl(dir));
+
check_verify_result (
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(dir / dcp_test1_cpl())
+ ).set_cpl_id(dcp_test1_cpl_id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, dcp_test1_cpl_id(), canonical(dir / dcp_test1_cpl())
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_CONTENT_KIND, string("xtrailer") }
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_CONTENT_KIND, string("xtrailer")
+ ).set_cpl_id(dcp_test1_cpl_id())
});
}
static
path
-cpl (string suffix)
+dcp_test1_cpl_path(string suffix)
{
return dcp::String::compose("build/test/verify_test%1/%2", suffix, dcp_test1_cpl());
}
@@ -446,7 +587,7 @@ cpl (string suffix)
static
path
-pkl (string suffix)
+dcp_test1_pkl_path(string suffix)
{
return dcp::String::compose("build/test/verify_test%1/%2", suffix, dcp_test1_pkl());
}
@@ -462,22 +603,64 @@ asset_map (string suffix)
BOOST_AUTO_TEST_CASE (verify_invalid_picture_frame_rate)
{
- check_verify_result_after_replace (
- "invalid_picture_frame_rate", &cpl,
- "<FrameRate>24 1", "<FrameRate>99 1",
- { dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES,
- dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE }
- );
+ auto const suffix = "invalid_picture_frame_rate";
+
+ replace(suffix, &dcp_test1_cpl_path, "<FrameRate>24 1", "<FrameRate>99 1");
+
+ auto const dir = dcp::String::compose("build/test/verify_test%1", suffix);
+ auto const cpl_path = find_cpl(dir);
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
+ std::vector<dcp::VerificationNote> expected =
+ {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(cpl_path)
+ ).set_cpl_id(cpl->id()).set_calculated_hash("7n7GQ2TbxQbmHYuAR8ml7XDOep8=").set_reference_hash("skI+5b/9LA/y6h0mcyxysJYanxI="),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE, string{"99/1"}
+ ).set_cpl_id(cpl->id())
+ };
+
+ check_verify_result(dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes, expected);
}
+
BOOST_AUTO_TEST_CASE (verify_missing_asset)
{
auto dir = setup (1, "missing_asset");
remove (dir / "video.mxf");
+
+ auto cpl = std::make_shared<dcp::CPL>(find_cpl(dir));
+
check_verify_result (
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
{ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_ASSET, canonical(dir) / "video.mxf" }
});
}
@@ -485,71 +668,236 @@ BOOST_AUTO_TEST_CASE (verify_missing_asset)
BOOST_AUTO_TEST_CASE (verify_empty_asset_path)
{
- check_verify_result_after_replace (
- "empty_asset_path", &asset_map,
- "<Path>video.mxf</Path>", "<Path></Path>",
- { dcp::VerificationNote::Code::EMPTY_ASSET_PATH }
- );
+ auto const suffix = "empty_asset_path";
+
+ replace("empty_asset_path", &asset_map, "<Path>video.mxf</Path>", "<Path></Path>");
+
+ auto const dir = dcp::String::compose("build/test/verify_test%1", suffix);
+ auto const cpl_path = find_cpl(dir);
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_ASSET_PATH }
+ };
+
+ check_verify_result(dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes, expected);
}
BOOST_AUTO_TEST_CASE (verify_mismatched_standard)
{
- check_verify_result_after_replace (
- "mismatched_standard", &cpl,
- "http://www.smpte-ra.org/schemas/429-7/2006/CPL", "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#",
- { dcp::VerificationNote::Code::MISMATCHED_STANDARD,
- dcp::VerificationNote::Code::INVALID_XML,
- dcp::VerificationNote::Code::INVALID_XML,
- dcp::VerificationNote::Code::INVALID_XML,
- dcp::VerificationNote::Code::INVALID_XML,
- dcp::VerificationNote::Code::INVALID_XML,
- dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES }
- );
+ auto const suffix = "mismatched_standard";
+
+ replace(suffix, &dcp_test1_cpl_path, "http://www.smpte-ra.org/schemas/429-7/2006/CPL", "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#");
+
+ auto const dir = dcp::String::compose("build/test/verify_test%1", suffix);
+ auto const cpl_path = find_cpl(dir);
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_STANDARD },
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "invalid character encountered", canonical(cpl_path), 42
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "no declaration found for element 'Id'", canonical(cpl_path), 53
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "no declaration found for element 'EditRate'", canonical(cpl_path), 54
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, "no declaration found for element 'IntrinsicDuration'", canonical(cpl_path), 55
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML,
+ "element 'Id' is not allowed for content model '(Id,AnnotationText?,EditRate,IntrinsicDuration,"
+ "EntryPoint?,Duration?,FullContentTitleText,ReleaseTerritory?,VersionNumber?,Chain?,Distributor?,"
+ "Facility?,AlternateContentVersionList?,Luminance?,MainSoundConfiguration,MainSoundSampleRate,"
+ "MainPictureStoredArea,MainPictureActiveArea,MainSubtitleLanguageList?,ExtensionMetadataList?,)'",
+ canonical(cpl_path), 149
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(cpl_path)
+ ).set_cpl_id(cpl->id()).set_reference_hash("skI+5b/9LA/y6h0mcyxysJYanxI=").set_calculated_hash("FZ9E7L/pOuJ6aZfbiaANTv8BFOo=")
+ };
+
+ check_verify_result(dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes, expected);
}
BOOST_AUTO_TEST_CASE (verify_invalid_xml_cpl_id)
{
+ auto const suffix = "invalid_xml_cpl_id";
+
/* There's no MISMATCHED_CPL_HASHES error here because it can't find the correct hash by ID (since the ID is wrong) */
- check_verify_result_after_replace (
- "invalid_xml_cpl_id", &cpl,
- "<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab", "<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358a",
- { dcp::VerificationNote::Code::INVALID_XML }
- );
+ replace("invalid_xml_cpl_id", &dcp_test1_cpl_path, "<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358ab", "<Id>urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358a");
+
+ auto const dir = dcp::String::compose("build/test/verify_test%1", suffix);
+ auto const cpl_path = find_cpl(dir);
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML,
+ "value 'urn:uuid:6affb8ee-0020-4dff-a53c-17652f6358a' does not match regular expression "
+ "facet 'urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'", canonical(cpl_path), 3
+ ).set_cpl_id(cpl->id())
+ };
+
+ check_verify_result(dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes, expected);
}
BOOST_AUTO_TEST_CASE (verify_invalid_xml_issue_date)
{
- check_verify_result_after_replace (
- "invalid_xml_issue_date", &cpl,
- "<IssueDate>", "<IssueDate>x",
- { dcp::VerificationNote::Code::INVALID_XML,
- dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES }
- );
+ auto const suffix = "invalid_xml_issue_date";
+
+ replace("invalid_xml_issue_date", &dcp_test1_cpl_path, "<IssueDate>", "<IssueDate>x");
+
+ auto const dir = dcp::String::compose("build/test/verify_test%1", suffix);
+ auto const cpl_path = find_cpl(dir);
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(cpl_path)
+ ).set_cpl_id(cpl->id()).set_reference_hash("skI+5b/9LA/y6h0mcyxysJYanxI=").set_calculated_hash("sz3BeIugJ567q3HMnA62JeRw4TE="),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML,
+ "invalid character encountered",
+ canonical(cpl_path), 5
+ ).set_cpl_id(cpl->id()),
+ };
+
+ check_verify_result(dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes, expected);
}
BOOST_AUTO_TEST_CASE (verify_invalid_xml_pkl_id)
{
- check_verify_result_after_replace (
- "invalid_xml_pkl_id", &pkl,
- "<Id>urn:uuid:" + dcp_test1_pkl_id().substr(0, 3),
- "<Id>urn:uuid:x" + dcp_test1_pkl_id().substr(1, 2),
- { dcp::VerificationNote::Code::INVALID_XML }
- );
+ auto const suffix = "invalid_xml_pkl_id";
+
+ replace("invalid_xml_pkl_id", &dcp_test1_pkl_path, "<Id>urn:uuid:" + dcp_test1_pkl_id().substr(0, 3), "<Id>urn:uuid:x" + dcp_test1_pkl_id().substr(1, 2));
+
+ auto const dir = dcp::String::compose("build/test/verify_test%1", suffix);
+ auto const pkl_path = find_pkl(dir);
+ auto const cpl_path = find_cpl(dir);
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML,
+ "value 'urn:uuid:x199d58b-5ef8-4d49-b270-07e590ccb280' does not match regular "
+ "expression facet 'urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'",
+ canonical(pkl_path), 3
+ ),
+ };
+
+ check_verify_result(dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes, expected);
}
BOOST_AUTO_TEST_CASE (verify_invalid_xml_asset_map_id)
{
- check_verify_result_after_replace (
- "invalid_xml_asset_map_id", &asset_map,
- "<Id>urn:uuid:" + dcp_test1_asset_map_id.substr(0, 3),
- "<Id>urn:uuid:x" + dcp_test1_asset_map_id.substr(1, 2),
- { dcp::VerificationNote::Code::INVALID_XML }
- );
+ auto const suffix = "invalid_xml_asset_map_id";
+
+ replace("invalid_xml_asset_map_id", &asset_map, "<Id>urn:uuid:" + dcp_test1_asset_map_id.substr(0, 3), "<Id>urn:uuid:x" + dcp_test1_asset_map_id.substr(1, 2));
+
+ auto const dir = dcp::String::compose("build/test/verify_test%1", suffix);
+ auto const cpl_path = find_cpl(dir);
+ auto const asset_map_path = find_asset_map(dir);
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML,
+ "value 'urn:uuid:x17b3de4-6dda-408d-b19b-6711354b0bc3' does not match regular "
+ "expression facet 'urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'",
+ canonical(asset_map_path), 3
+ ),
+ };
+
+ check_verify_result(dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes, expected);
}
@@ -557,11 +905,12 @@ BOOST_AUTO_TEST_CASE (verify_invalid_standard)
{
stages.clear ();
auto dir = setup (3, "verify_invalid_standard");
- auto notes = dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test);
+ auto notes = dcp::verify({dir}, {}, &stage, &progress, {}, xsd_test).notes;
path const cpl_file = dir / "cpl_cbfd2bc0-21cf-4a8f-95d8-9cddcbe51296.xml";
path const pkl_file = dir / "pkl_d87a950c-bd6f-41f6-90cc-56ccd673e131.xml";
path const assetmap_file = dir / "ASSETMAP";
+ auto cpl = std::make_shared<dcp::CPL>(cpl_file);
auto st = stages.begin();
BOOST_CHECK_EQUAL (st->first, "Checking DCP");
@@ -601,13 +950,26 @@ BOOST_AUTO_TEST_CASE (verify_invalid_standard)
++st;
BOOST_REQUIRE (st == stages.end());
- BOOST_REQUIRE_EQUAL (notes.size(), 2U);
- auto i = notes.begin ();
- BOOST_CHECK_EQUAL (i->type(), dcp::VerificationNote::Type::BV21_ERROR);
- BOOST_CHECK_EQUAL (i->code(), dcp::VerificationNote::Code::INVALID_STANDARD);
- ++i;
- BOOST_CHECK_EQUAL (i->type(), dcp::VerificationNote::Type::BV21_ERROR);
- BOOST_CHECK_EQUAL (i->code(), dcp::VerificationNote::Code::INVALID_JPEG2000_GUARD_BITS_FOR_2K);
+ vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"feature"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "j2c_c6035f97-b07d-4e1c-944d-603fc2ddc242.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "j2c_c6035f97-b07d-4e1c-944d-603fc2ddc242.mxf"), cpl)
+ };
+
+ for (int j = 0; j < 24; ++j) {
+ expected.push_back(
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_JPEG2000_GUARD_BITS_FOR_2K, string("2")
+ ).set_cpl_id(cpl->id())
+ );
+ }
+
+ check_verify_result(notes, expected);
}
/* DCP with a short asset */
@@ -620,22 +982,42 @@ BOOST_AUTO_TEST_CASE (verify_invalid_duration)
BOOST_REQUIRE(dcp.cpls().size() == 1);
auto cpl = dcp.cpls()[0];
- check_verify_result (
- { dir },
- {},
- {
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_DURATION, string("d7576dcb-a361-4139-96b8-267f5f8d7f91") },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_INTRINSIC_DURATION, string("d7576dcb-a361-4139-96b8-267f5f8d7f91") },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_DURATION, string("a2a87f5d-b749-4a7e-8d0c-9d48a4abf626") },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_INTRINSIC_DURATION, string("a2a87f5d-b749-4a7e-8d0c-9d48a4abf626") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_JPEG2000_GUARD_BITS_FOR_2K, string("2") },
+ vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"feature"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "j2c_d7576dcb-a361-4139-96b8-267f5f8d7f91.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "j2c_d7576dcb-a361-4139-96b8-267f5f8d7f91.mxf"), cpl),
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_DURATION, string("d7576dcb-a361-4139-96b8-267f5f8d7f91")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_INTRINSIC_DURATION, string("d7576dcb-a361-4139-96b8-267f5f8d7f91")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_DURATION, string("a2a87f5d-b749-4a7e-8d0c-9d48a4abf626")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_INTRINSIC_DURATION, string("a2a87f5d-b749-4a7e-8d0c-9d48a4abf626")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING,
+ dcp::VerificationNote::Code::EMPTY_CONTENT_VERSION_LABEL_TEXT,
+ cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ };
+
+ for (int i = 0; i < 23; ++i) {
+ expected.push_back(
dcp::VerificationNote(
- dcp::VerificationNote::Type::WARNING,
- dcp::VerificationNote::Code::EMPTY_CONTENT_VERSION_LABEL_TEXT,
- cpl->file().get()
- ).set_id("d74fda30-d5f4-4c5f-870f-ebc089d97eb7")
- });
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_JPEG2000_GUARD_BITS_FOR_2K, string("2")
+ ).set_cpl_id(cpl->id())
+ );
+ }
+
+ check_verify_result({ dir }, {}, expected);
}
@@ -643,9 +1025,9 @@ static
shared_ptr<dcp::CPL>
dcp_from_frame (dcp::ArrayData const& frame, path dir)
{
- auto asset = make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
+ auto asset = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
create_directories (dir);
- auto writer = asset->start_write(dir / "pic.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto writer = asset->start_write(dir / "pic.mxf", dcp::Behaviour::MAKE_NEW);
for (int i = 0; i < 24; ++i) {
writer->write (frame.data(), frame.size());
}
@@ -674,12 +1056,21 @@ BOOST_AUTO_TEST_CASE (verify_invalid_picture_frame_size_in_bytes)
prepare_directory (dir);
auto cpl = dcp_from_frame (oversized_frame, dir);
- vector<dcp::VerificationNote> expected;
+ vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "pic.mxf"), cpl),
+ };
+
for (auto i = 0; i < 24; ++i) {
expected.push_back(
dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_JPEG2000_CODESTREAM, string("missing marker start byte")
- ).set_frame(i).set_frame_rate(24)
+ ).set_frame(i).set_frame_rate(24).set_cpl_id(cpl->id())
);
}
@@ -687,13 +1078,15 @@ BOOST_AUTO_TEST_CASE (verify_invalid_picture_frame_size_in_bytes)
expected.push_back(
dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_SIZE_IN_BYTES, canonical(dir / "pic.mxf")
- ).set_frame(i).set_frame_rate(24)
+ ).set_frame(i).set_frame_rate(24).set_cpl_id(cpl->id())
);
}
expected.push_back(
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
- );
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ );
check_verify_result({ dir }, {}, expected);
}
@@ -717,13 +1110,21 @@ BOOST_AUTO_TEST_CASE (verify_nearly_invalid_picture_frame_size_in_bytes)
prepare_directory (dir);
auto cpl = dcp_from_frame (oversized_frame, dir);
- vector<dcp::VerificationNote> expected;
+ vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "pic.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ };
for (auto i = 0; i < 24; ++i) {
expected.push_back(
dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_JPEG2000_CODESTREAM, string("missing marker start byte")
- ).set_frame(i).set_frame_rate(24)
+ ).set_frame(i).set_frame_rate(24).set_cpl_id(cpl->id())
);
}
@@ -731,13 +1132,15 @@ BOOST_AUTO_TEST_CASE (verify_nearly_invalid_picture_frame_size_in_bytes)
expected.push_back(
dcp::VerificationNote(
dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES, canonical(dir / "pic.mxf")
- ).set_frame(i).set_frame_rate(24)
+ ).set_frame(i).set_frame_rate(24).set_cpl_id(cpl->id())
);
}
expected.push_back(
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
- );
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ );
check_verify_result ({ dir }, {}, expected);
}
@@ -754,7 +1157,20 @@ BOOST_AUTO_TEST_CASE (verify_valid_picture_frame_size_in_bytes)
prepare_directory (dir);
auto cpl = dcp_from_frame (frame, dir);
- check_verify_result({ dir }, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ { dir },
+ {},
+ {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "pic.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "pic.mxf"), cpl),
+ dcp::VerificationNote(dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()).set_cpl_id(cpl->id())
+ });
}
@@ -765,14 +1181,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_interop_subtitles)
copy_file ("test/data/subs1.xml", dir / "subs.xml");
auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
- write_dcp_with_single_asset (dir, reel_asset, dcp::Standard::INTEROP);
+ auto cpl = write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
check_verify_result (
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"} }
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -784,14 +1207,21 @@ BOOST_AUTO_TEST_CASE(verify_catch_missing_font_file_with_interop_ccap)
copy_file("test/data/subs1.xml", dir / "ccap.xml");
auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "ccap.xml");
auto reel_asset = make_shared<dcp::ReelInteropClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
- write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
+ auto cpl = write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
check_verify_result (
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"} }
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -805,7 +1235,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_interop_subtitles)
copy_file ("test/data/subs1.xml", dir / "subs.xml");
auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
- write_dcp_with_single_asset (dir, reel_asset, dcp::Standard::INTEROP);
+ auto cpl = write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
{
Editor e (dir / "subs.xml");
@@ -816,16 +1246,25 @@ BOOST_AUTO_TEST_CASE (verify_invalid_interop_subtitles)
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'Foo'"), path(), 5 },
- {
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'Foo'"), path(), 5
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR,
dcp::VerificationNote::Code::INVALID_XML,
string("element 'Foo' is not allowed for content model '(SubtitleID,MovieTitle,ReelNumber,Language,LoadFont*,Font*,Subtitle*)'"),
path(),
29
- },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"} }
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -837,15 +1276,24 @@ BOOST_AUTO_TEST_CASE(verify_interop_subtitle_asset_with_no_subtitles)
copy_file("test/data/subs4.xml", dir / "subs.xml");
auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
- write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
+ auto cpl = write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
check_verify_result (
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE, asset->id(), boost::filesystem::canonical(asset->file().get()) },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"} }
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE, asset->id(), boost::filesystem::canonical(asset->file().get())
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"theFontId"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -858,14 +1306,21 @@ BOOST_AUTO_TEST_CASE(verify_interop_subtitle_asset_with_single_space_subtitle)
copy_file("test/data/subs5.xml", dir / "subs.xml");
auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
- write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
+ auto cpl = write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
check_verify_result (
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"Arial"} }
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"Arial"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -884,9 +1339,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_smpte_subtitles)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-04-14T13:19:14.000+02:00"} },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id() }
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-04-14T13:19:14.000+02:00"}
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id()
+ ).set_cpl_id(cpl->id()),
});
}
@@ -907,18 +1374,34 @@ BOOST_AUTO_TEST_CASE (verify_invalid_smpte_subtitles)
{ dir },
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'Foo'"), path(), 2 },
- {
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'Foo'"), path(), 2
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR,
dcp::VerificationNote::Code::INVALID_XML,
string("element 'Foo' is not allowed for content model '(Id,ContentTitleText,AnnotationText?,IssueDate,ReelNumber?,Language?,EditRate,TimeCodeRate,StartTime?,DisplayType?,LoadFont*,SubtitleList)'"),
path(),
2
- },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2020-05-09T00:29:21.000+02:00"} },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id() }
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2020-05-09T00:29:21.000+02:00"}
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id()
+ ).set_cpl_id(cpl->id()),
});
}
@@ -936,12 +1419,30 @@ BOOST_AUTO_TEST_CASE (verify_empty_text_node_in_subtitles)
{ dir },
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_TEXT },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-08-09T18:34:46.000+02:00"} },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id() }
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_TEXT
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2021-08-09T18:34:46.000+02:00"}
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, asset->id()
+ ).set_cpl_id(cpl->id())
});
}
@@ -960,8 +1461,15 @@ BOOST_AUTO_TEST_CASE (verify_empty_text_node_in_subtitles_with_child_nodes)
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"font0"} }
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"font0"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -980,10 +1488,21 @@ BOOST_AUTO_TEST_CASE (verify_empty_text_node_in_subtitles_with_empty_child_nodes
{ dir },
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE, asset->id(), boost::filesystem::canonical(asset->file().get()) },
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE, asset->id(), boost::filesystem::canonical(asset->file().get())
+ ).set_cpl_id(cpl->id()),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_TEXT },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"font0"} },
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_TEXT
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_FONT, string{"font0"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -1011,8 +1530,16 @@ BOOST_AUTO_TEST_CASE (verify_external_asset)
{ vf_dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
{ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EXTERNAL_ASSET, picture->asset()->id() },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1047,38 +1574,6 @@ BOOST_AUTO_TEST_CASE (verify_valid_cpl_metadata)
}
-path
-find_prefix(path dir, string prefix)
-{
- auto iter = std::find_if(directory_iterator(dir), directory_iterator(), [prefix](path const& p) {
- return boost::starts_with(p.filename().string(), prefix);
- });
-
- BOOST_REQUIRE(iter != directory_iterator());
- return iter->path();
-}
-
-
-path find_cpl (path dir)
-{
- return find_prefix(dir, "cpl_");
-}
-
-
-path
-find_pkl(path dir)
-{
- return find_prefix(dir, "pkl_");
-}
-
-
-path
-find_asset_map(path dir)
-{
- return find_prefix(dir, "ASSETMAP");
-}
-
-
/* DCP with invalid CompositionMetadataAsset */
BOOST_AUTO_TEST_CASE (verify_invalid_cpl_metadata_bad_tag)
{
@@ -1115,9 +1610,26 @@ BOOST_AUTO_TEST_CASE (verify_invalid_cpl_metadata_bad_tag)
{ dir },
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:MainSoundXConfiguration'"), canonical(cpl->file().get()), 50 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:MainSoundXSampleRate'"), canonical(cpl->file().get()), 51 },
- {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "pic.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1440x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "pic.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:MainSoundXConfiguration'"), canonical(cpl->file().get()), 50
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:MainSoundXSampleRate'"), canonical(cpl->file().get()), 51
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR,
dcp::VerificationNote::Code::INVALID_XML,
string("element 'meta:MainSoundXConfiguration' is not allowed for content model "
@@ -1127,11 +1639,10 @@ BOOST_AUTO_TEST_CASE (verify_invalid_cpl_metadata_bad_tag)
"MainSoundSampleRate,MainPictureStoredArea,MainPictureActiveArea,MainSubtitleLanguageList?,"
"ExtensionMetadataList?,)'"),
canonical(cpl->file().get()),
- 71
- },
+ 71).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), canonical(cpl->file().get())
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash())
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash())
});
}
@@ -1185,9 +1696,21 @@ BOOST_AUTO_TEST_CASE (verify_invalid_language1)
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("badlang") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("wrong-andbad") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("badlang")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("wrong-andbad")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1209,9 +1732,21 @@ BOOST_AUTO_TEST_CASE (verify_invalid_language2)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("badlang") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("wrong-andbad") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("badlang")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("wrong-andbad")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1252,16 +1787,38 @@ BOOST_AUTO_TEST_CASE (verify_invalid_language3)
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("this-is-wrong") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("andso-is-this") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("fred-jim") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("frobozz") },
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "videofoo.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1440x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "videofoo.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("this-is-wrong")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("andso-is-this")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("fred-jim")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_LANGUAGE, string("frobozz")
+ ).set_cpl_id(cpl->id()),
});
}
static
-vector<dcp::VerificationNote>
+std::tuple<vector<dcp::VerificationNote>, shared_ptr<dcp::CPL>, boost::filesystem::path>
check_picture_size (int width, int height, int frame_rate, bool three_d)
{
using namespace boost::filesystem;
@@ -1269,13 +1826,13 @@ check_picture_size (int width, int height, int frame_rate, bool three_d)
path dcp_path = "build/test/verify_picture_test";
prepare_directory (dcp_path);
- shared_ptr<dcp::PictureAsset> mp;
+ shared_ptr<dcp::J2KPictureAsset> mp;
if (three_d) {
- mp = make_shared<dcp::StereoPictureAsset>(dcp::Fraction(frame_rate, 1), dcp::Standard::SMPTE);
+ mp = make_shared<dcp::StereoJ2KPictureAsset>(dcp::Fraction(frame_rate, 1), dcp::Standard::SMPTE);
} else {
- mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction(frame_rate, 1), dcp::Standard::SMPTE);
+ mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction(frame_rate, 1), dcp::Standard::SMPTE);
}
- auto picture_writer = mp->start_write(dcp_path / "video.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto picture_writer = mp->start_write(dcp_path / "video.mxf", dcp::Behaviour::MAKE_NEW);
auto image = black_image (dcp::Size(width, height));
auto j2c = dcp::compress_j2k (image, 100000000, frame_rate, three_d, width > 2048);
@@ -1298,9 +1855,9 @@ check_picture_size (int width, int height, int frame_rate, bool three_d)
auto reel = make_shared<dcp::Reel>();
if (three_d) {
- reel->add (make_shared<dcp::ReelStereoPictureAsset>(std::dynamic_pointer_cast<dcp::StereoPictureAsset>(mp), 0));
+ reel->add (make_shared<dcp::ReelStereoPictureAsset>(std::dynamic_pointer_cast<dcp::StereoJ2KPictureAsset>(mp), 0));
} else {
- reel->add (make_shared<dcp::ReelMonoPictureAsset>(std::dynamic_pointer_cast<dcp::MonoPictureAsset>(mp), 0));
+ reel->add (make_shared<dcp::ReelMonoPictureAsset>(std::dynamic_pointer_cast<dcp::MonoJ2KPictureAsset>(mp), 0));
}
reel->add (simple_markers(frame_rate));
@@ -1311,7 +1868,8 @@ check_picture_size (int width, int height, int frame_rate, bool three_d)
d->set_annotation_text("A Test DCP");
d->write_xml();
- return dcp::verify({dcp_path}, {}, &stage, &progress, {}, xsd_test);
+ /* It seems that for the Ubuntu 16.04 compiler we can't use an initializer list here */
+ return std::tuple<vector<dcp::VerificationNote>, shared_ptr<dcp::CPL>, boost::filesystem::path>{ dcp::verify({dcp_path}, {}, &stage, &progress, {}, xsd_test).notes, cpl, dcp_path };
}
@@ -1319,8 +1877,28 @@ static
void
check_picture_size_ok (int width, int height, int frame_rate, bool three_d)
{
- auto notes = check_picture_size(width, height, frame_rate, three_d);
- BOOST_CHECK_EQUAL (notes.size(), 0U);
+ vector<dcp::VerificationNote> notes;
+ shared_ptr<dcp::CPL> cpl;
+ boost::filesystem::path dir;
+ std::tie(notes, cpl, dir) = check_picture_size(width, height, frame_rate, three_d);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ dcp::String::compose("%1x%2", width, height),
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl)
+ };
+ check_verify_result(notes, expected);
}
@@ -1328,10 +1906,31 @@ static
void
check_picture_size_bad_frame_size (int width, int height, int frame_rate, bool three_d)
{
- auto notes = check_picture_size(width, height, frame_rate, three_d);
- BOOST_REQUIRE_EQUAL (notes.size(), 1U);
- BOOST_CHECK_EQUAL (notes.front().type(), dcp::VerificationNote::Type::BV21_ERROR);
- BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::Code::INVALID_PICTURE_SIZE_IN_PIXELS);
+ vector<dcp::VerificationNote> notes;
+ shared_ptr<dcp::CPL> cpl;
+ boost::filesystem::path dir;
+ std::tie(notes, cpl, dir) = check_picture_size(width, height, frame_rate, three_d);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ dcp::String::compose("%1x%2", width, height),
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_SIZE_IN_PIXELS, dcp::String::compose("%1x%2", width, height), canonical(dir / "video.mxf")
+ ).set_cpl_id(cpl->id())
+ };
+ check_verify_result(notes, expected);
}
@@ -1339,10 +1938,35 @@ static
void
check_picture_size_bad_2k_frame_rate (int width, int height, int frame_rate, bool three_d)
{
- auto notes = check_picture_size(width, height, frame_rate, three_d);
- BOOST_REQUIRE_EQUAL (notes.size(), 2U);
- BOOST_CHECK_EQUAL (notes.back().type(), dcp::VerificationNote::Type::BV21_ERROR);
- BOOST_CHECK_EQUAL (notes.back().code(), dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_2K);
+ vector<dcp::VerificationNote> notes;
+ shared_ptr<dcp::CPL> cpl;
+ boost::filesystem::path dir;
+ std::tie(notes, cpl, dir) = check_picture_size(width, height, frame_rate, three_d);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ dcp::String::compose("%1x%2", width, height),
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE, dcp::String::compose("%1/1", frame_rate * (three_d ? 2 : 1))
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_2K, dcp::String::compose("%1/1", frame_rate), canonical(dir / "video.mxf")
+ ).set_cpl_id(cpl->id())
+ };
+
+ check_verify_result(notes, expected);
}
@@ -1350,10 +1974,32 @@ static
void
check_picture_size_bad_4k_frame_rate (int width, int height, int frame_rate, bool three_d)
{
- auto notes = check_picture_size(width, height, frame_rate, three_d);
- BOOST_REQUIRE_EQUAL (notes.size(), 1U);
- BOOST_CHECK_EQUAL (notes.front().type(), dcp::VerificationNote::Type::BV21_ERROR);
- BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_4K);
+ vector<dcp::VerificationNote> notes;
+ shared_ptr<dcp::CPL> cpl;
+ boost::filesystem::path dir;
+ std::tie(notes, cpl, dir) = check_picture_size(width, height, frame_rate, three_d);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ dcp::String::compose("%1x%2", width, height),
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_RATE_FOR_4K, dcp::String::compose("%1/1", frame_rate), canonical(dir / "video.mxf")
+ ).set_cpl_id(cpl->id())
+ };
+
+ check_verify_result(notes, expected);
}
@@ -1399,10 +2045,28 @@ BOOST_AUTO_TEST_CASE (verify_picture_size)
check_picture_size_bad_4k_frame_rate (3996, 2160, 48, false);
/* No 4K 3D */
- auto notes = check_picture_size(3996, 2160, 24, true);
- BOOST_REQUIRE_EQUAL (notes.size(), 1U);
- BOOST_CHECK_EQUAL (notes.front().type(), dcp::VerificationNote::Type::BV21_ERROR);
- BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::Code::INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D);
+ vector<dcp::VerificationNote> notes;
+ shared_ptr<dcp::CPL> cpl;
+ boost::filesystem::path dir;
+ std::tie(notes, cpl, dir) = check_picture_size(3996, 2160, 24, true);
+
+ std::vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"3996x2160"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D },
+ };
}
@@ -1458,15 +2122,27 @@ BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_xml_size_in_bytes)
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
- {
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
dcp::VerificationNote::Type::BV21_ERROR,
dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES,
string("419371"),
canonical(dir / "subs.mxf")
- },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1503,11 +2179,30 @@ verify_timed_text_asset_too_large (string name)
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695488"), canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, string("121634816"), canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121698284"), canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR,
+ dcp::VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES,
+ dcp::raw_convert<string>(121634816),
+ canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1554,15 +2249,34 @@ BOOST_AUTO_TEST_CASE (verify_missing_subtitle_language)
subs->write (dir / "subs.mxf");
auto reel_subs = make_shared<dcp::ReelSMPTESubtitleAsset>(subs, dcp::Fraction(24, 1), 106, 0);
- dcp->cpls()[0]->reels()[0]->add(reel_subs);
+ auto cpl = dcp->cpls()[0];
+ cpl->reels()[0]->add(reel_subs);
dcp->write_xml();
check_verify_result (
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME }
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id())
});
}
@@ -1600,9 +2314,31 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_subtitle_languages)
{ path },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs1.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs2.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_SUBTITLE_LANGUAGES }
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video0.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "video0.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "video1.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs1.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs2.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_SUBTITLE_LANGUAGES
+ ).set_cpl_id(cpl->id()),
});
}
@@ -1640,8 +2376,28 @@ BOOST_AUTO_TEST_CASE (verify_multiple_closed_caption_languages_allowed)
{ path },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs1.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs2.mxf") }
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video0.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "video0.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "video1.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs1.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(path / "subs2.mxf")
+ ).set_cpl_id(cpl->id())
});
}
@@ -1681,15 +2437,34 @@ BOOST_AUTO_TEST_CASE (verify_missing_subtitle_start_time)
subs->write (dir / "subs.mxf");
auto reel_subs = make_shared<dcp::ReelSMPTESubtitleAsset>(subs, dcp::Fraction(24, 1), 106, 0);
- dcp->cpls()[0]->reels()[0]->add(reel_subs);
+ auto cpl = dcp->cpls()[0];
+ cpl->reels()[0]->add(reel_subs);
dcp->write_xml();
check_verify_result (
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME }
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id())
});
}
@@ -1730,15 +2505,34 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_start_time)
subs->write (dir / "subs.mxf");
auto reel_subs = make_shared<dcp::ReelSMPTESubtitleAsset>(subs, dcp::Fraction(24, 1), 106, 0);
- dcp->cpls().front()->reels().front()->add(reel_subs);
+ auto cpl = dcp->cpls()[0];
+ cpl->reels().front()->add(reel_subs);
dcp->write_xml();
check_verify_result (
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_SUBTITLE_START_TIME, canonical(dir / "subs.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id())
});
}
@@ -1831,8 +2625,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_first_text_time)
{ dir },
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1843,7 +2647,20 @@ BOOST_AUTO_TEST_CASE (verify_valid_subtitle_first_text_time)
auto const dir = path("build/test/verify_valid_subtitle_first_text_time");
/* Just late enough */
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (dir, {{ 4 * 24, 5 * 24 }});
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -1888,7 +2705,20 @@ BOOST_AUTO_TEST_CASE (verify_valid_subtitle_first_text_time_on_second_reel)
dcp->set_annotation_text("hello");
dcp->write_xml();
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -1905,8 +2735,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_spacing)
{dir},
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_SPACING },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_SPACING
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1920,7 +2760,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_subtitle_spacing)
{ 4 * 24, 5 * 24 },
{ 5 * 24 + 16, 8 * 24 },
});
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -1932,8 +2786,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_duration)
{dir},
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_DURATION },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_DURATION
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1942,7 +2806,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_subtitle_duration)
{
auto const dir = path("build/test/verify_valid_subtitle_duration");
auto cpl = dcp_with_text<dcp::ReelSMPTESubtitleAsset> (dir, {{ 4 * 24, 4 * 24 + 17 }});
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -1963,10 +2841,24 @@ BOOST_AUTO_TEST_CASE (verify_subtitle_overlapping_reel_boundary)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "72 96", boost::filesystem::canonical(asset->file().get()) },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "72 96", boost::filesystem::canonical(asset->file().get())
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::SUBTITLE_OVERLAPS_REEL_BOUNDARY
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -1987,8 +2879,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_line_count1)
{dir},
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_LINE_COUNT },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_LINE_COUNT
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2003,7 +2905,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_subtitle_line_count1)
{ 96, 200, 0.1, dcp::VAlign::CENTER, "have" },
{ 96, 200, 0.2, dcp::VAlign::CENTER, "four" },
});
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -2022,8 +2938,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_line_count2)
{dir},
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_LINE_COUNT },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_LINE_COUNT
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2039,7 +2965,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_subtitle_line_count2)
{ 150, 180, 0.2, dcp::VAlign::CENTER, "four" },
{ 190, 250, 0.3, dcp::VAlign::CENTER, "lines" }
});
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -2055,8 +2995,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_line_length1)
{dir},
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::NEARLY_INVALID_SUBTITLE_LINE_LENGTH },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::NEARLY_INVALID_SUBTITLE_LINE_LENGTH
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2073,8 +3023,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_subtitle_line_length2)
{dir},
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_LINE_LENGTH },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_LINE_LENGTH
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2094,8 +3054,18 @@ BOOST_AUTO_TEST_CASE (verify_valid_closed_caption_line_count1)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_COUNT},
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_COUNT
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2110,7 +3080,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_closed_caption_line_count2)
{ 96, 200, 0.1, dcp::VAlign::CENTER, "have" },
{ 96, 200, 0.2, dcp::VAlign::CENTER, "four" },
});
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -2129,8 +3113,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_line_count3)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_COUNT},
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_COUNT
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2146,7 +3140,21 @@ BOOST_AUTO_TEST_CASE (verify_valid_closed_caption_line_count4)
{ 150, 180, 0.2, dcp::VAlign::CENTER, "four" },
{ 190, 250, 0.3, dcp::VAlign::CENTER, "lines" }
});
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -2158,11 +3166,20 @@ BOOST_AUTO_TEST_CASE (verify_valid_closed_caption_line_length)
{
{ 96, 300, 0.0, dcp::VAlign::CENTER, "01234567890123456789012345678901" }
});
+
check_verify_result (
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2179,8 +3196,18 @@ BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_line_length)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_LENGTH },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_LINE_LENGTH
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2199,7 +3226,15 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_closed_caption_valign1)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2218,8 +3253,18 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_closed_caption_valign2)
{dir},
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_VALIGN },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_VALIGN
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2234,11 +3279,20 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering1)
{ 96, 300, 0.1, dcp::VAlign::TOP, "is" },
{ 96, 300, 0.2, dcp::VAlign::TOP, "fine" },
});
- check_verify_result (
+
+ check_verify_result(
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2253,11 +3307,20 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering2)
{ 96, 300, 0.1, dcp::VAlign::BOTTOM, "is" },
{ 96, 300, 0.0, dcp::VAlign::BOTTOM, "also fine" },
});
- check_verify_result (
+
+ check_verify_result(
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2270,8 +3333,18 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering3)
{dir},
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ORDERING },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ORDERING
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2280,11 +3353,20 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_closed_caption_ordering4)
{
auto const dir = path ("build/test/verify_incorrect_closed_caption_ordering4");
auto cpl = dcp_with_text_from_file<dcp::ReelSMPTEClosedCaptionAsset> (dir, "test/data/verify_incorrect_closed_caption_ordering4.xml");
- check_verify_result (
+
+ check_verify_result(
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2314,8 +3396,20 @@ BOOST_AUTO_TEST_CASE (verify_invalid_sound_frame_rate)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_SOUND_FRAME_RATE, string("96000"), canonical(dir / "audiofoo.mxf") },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "videofoo.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "videofoo.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_SOUND_FRAME_RATE, string("96000"), canonical(dir / "audiofoo.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2342,10 +3436,24 @@ BOOST_AUTO_TEST_CASE (verify_missing_cpl_annotation_text)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_ANNOTATION_TEXT, cpl->id(), canonical(cpl->file().get()) },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_ANNOTATION_TEXT, canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), canonical(cpl->file().get())
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash())
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash())
});
}
@@ -2371,10 +3479,24 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_cpl_annotation_text)
{dir},
{},
{
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISMATCHED_CPL_ANNOTATION_TEXT, cpl->id(), canonical(cpl->file().get()) },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), canonical(cpl->file().get())
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash())
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISMATCHED_CPL_ANNOTATION_TEXT, canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(cpl->file().get())
+ ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()).set_cpl_id(cpl->id())
});
}
@@ -2386,7 +3508,7 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_asset_duration)
shared_ptr<dcp::DCP> dcp (new dcp::DCP(dir));
auto cpl = make_shared<dcp::CPL>("A Test DCP", dcp::ContentKind::TRAILER, dcp::Standard::SMPTE);
- shared_ptr<dcp::MonoPictureAsset> mp = simple_picture (dir, "", 24);
+ shared_ptr<dcp::MonoJ2KPictureAsset> mp = simple_picture (dir, "", 24);
shared_ptr<dcp::SoundAsset> ms = simple_sound (dir, "", dcp::MXFMetadata(), "en-US", 25);
auto reel = make_shared<dcp::Reel>(
@@ -2405,8 +3527,20 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_asset_duration)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_ASSET_DURATION },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), canonical(cpl->file().get()) }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_ASSET_DURATION
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id())
});
}
@@ -2477,8 +3611,22 @@ BOOST_AUTO_TEST_CASE (verify_missing_main_subtitle_from_some_reels)
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video2.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2486,13 +3634,47 @@ BOOST_AUTO_TEST_CASE (verify_missing_main_subtitle_from_some_reels)
{
path dir ("build/test/verify_subtitles_must_be_in_all_reels2");
auto cpl = verify_subtitles_must_be_in_all_reels_check (dir, true, true);
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video2.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
{
path dir ("build/test/verify_subtitles_must_be_in_all_reels1");
auto cpl = verify_subtitles_must_be_in_all_reels_check (dir, false, false);
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video2.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
}
@@ -2561,21 +3743,69 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_closed_caption_asset_counts)
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
{
path dir ("build/test/verify_closed_captions_must_be_in_all_reels2");
auto cpl = verify_closed_captions_must_be_in_all_reels_check (dir, 4, 4);
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
{
path dir ("build/test/verify_closed_captions_must_be_in_all_reels3");
auto cpl = verify_closed_captions_must_be_in_all_reels_check (dir, 0, 0);
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
}
@@ -2618,8 +3848,20 @@ verify_text_entry_point_check (path dir, dcp::VerificationNote::Code code, boost
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, code, subs->id() },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, code, subs->id()
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2686,10 +3928,25 @@ BOOST_AUTO_TEST_CASE (verify_missing_hash)
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_HASH, asset_id }
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_HASH, asset_id
+ ).set_cpl_id(cpl->id())
});
}
@@ -2703,14 +3960,36 @@ verify_markers_test (
)
{
auto dcp = make_simple (dir);
- dcp->cpls()[0]->set_content_kind (dcp::ContentKind::FEATURE);
+ auto cpl = dcp->cpls()[0];
+ cpl->set_content_kind(dcp::ContentKind::FEATURE);
auto markers_asset = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), 24);
for (auto const& i: markers) {
markers_asset->set (i.first, i.second);
}
- dcp->cpls()[0]->reels()[0]->add(markers_asset);
+ cpl->reels()[0]->add(markers_asset);
dcp->write_xml();
+ for (auto& note: test_notes) {
+ note.set_cpl_id(cpl->id());
+ }
+
+ test_notes.push_back(ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl));
+ test_notes.push_back(ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl));
+ test_notes.push_back(ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl));
+ test_notes.push_back(ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl));
+ test_notes.push_back(
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ );
+ test_notes.push_back(ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"feature"}, cpl));
+ test_notes.push_back(ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl));
+ test_notes.push_back(ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl));
+ test_notes.push_back(ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl));
+
check_verify_result({dir}, {}, test_notes);
}
@@ -2807,7 +4086,28 @@ BOOST_AUTO_TEST_CASE (verify_missing_cpl_metadata_version_number)
cpl->unset_version_number();
dcp->write_xml();
- check_verify_result({dir}, {}, {{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA_VERSION_NUMBER, cpl->id(), cpl->file().get() }});
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA_VERSION_NUMBER, cpl->file().get()
+ ).set_cpl_id(cpl->id())
+ });
}
@@ -2831,10 +4131,25 @@ BOOST_AUTO_TEST_CASE (verify_missing_extension_metadata1)
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_EXTENSION_METADATA, cpl->id(), cpl->file().get() }
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_EXTENSION_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2858,10 +4173,25 @@ BOOST_AUTO_TEST_CASE (verify_missing_extension_metadata2)
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_EXTENSION_METADATA, cpl->id(), cpl->file().get() }
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_EXTENSION_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2886,11 +4216,27 @@ BOOST_AUTO_TEST_CASE (verify_invalid_xml_cpl_extension_metadata3)
{dir},
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:NameX'"), cpl->file().get(), 70 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:NameX' is not allowed for content model '(Name,PropertyList?,)'"), cpl->file().get(), 77 },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:NameX'"), cpl->file().get(), 70
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:NameX' is not allowed for content model '(Name,PropertyList?,)'"), cpl->file().get(), 77).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
});
}
@@ -2914,10 +4260,25 @@ BOOST_AUTO_TEST_CASE (verify_invalid_extension_metadata1)
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_EXTENSION_METADATA, string("<Name> should be 'Application'"), cpl->file().get() },
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_EXTENSION_METADATA, string("<Name> should be 'Application'"), cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2941,10 +4302,25 @@ BOOST_AUTO_TEST_CASE (verify_invalid_extension_metadata2)
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_EXTENSION_METADATA, string("<Name> property should be 'DCP Constraints Profile'"), cpl->file().get() },
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_EXTENSION_METADATA, string("<Name> property should be 'DCP Constraints Profile'"), cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -2969,11 +4345,28 @@ BOOST_AUTO_TEST_CASE (verify_invalid_xml_cpl_extension_metadata6)
{dir},
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:ValueX'"), cpl->file().get(), 74 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:ValueX' is not allowed for content model '(Name,Value)'"), cpl->file().get(), 75 },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:ValueX'"), cpl->file().get(), 74
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:ValueX' is not allowed for content model '(Name,Value)'"), cpl->file().get(), 75
+ ).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash())
});
}
@@ -2997,10 +4390,25 @@ BOOST_AUTO_TEST_CASE (verify_invalid_xml_cpl_extension_metadata7)
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_EXTENSION_METADATA, string("<Value> property should be 'SMPTE-RDD-52:2020-Bv2.1'"), cpl->file().get() },
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_EXTENSION_METADATA, string("<Value> property should be 'SMPTE-RDD-52:2020-Bv2.1'"), cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -3025,11 +4433,27 @@ BOOST_AUTO_TEST_CASE (verify_invalid_xml_cpl_extension_metadata8)
{dir},
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:PropertyX'"), cpl->file().get(), 72 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:PropertyX' is not allowed for content model '(Property+)'"), cpl->file().get(), 76 },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:PropertyX'"), cpl->file().get(), 72
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:PropertyX' is not allowed for content model '(Property+)'"), cpl->file().get(), 76).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
});
}
@@ -3054,11 +4478,28 @@ BOOST_AUTO_TEST_CASE (verify_invalid_xml_cpl_extension_metadata9)
{dir},
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:PropertyListX'"), cpl->file().get(), 71 },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:PropertyListX' is not allowed for content model '(Name,PropertyList?,)'"), cpl->file().get(), 77 },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("no declaration found for element 'meta:PropertyListX'"), cpl->file().get(), 71
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_XML, string("element 'meta:PropertyListX' is not allowed for content model '(Name,PropertyList?,)'"), cpl->file().get(), 77
+ ).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl->file().get()
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
});
}
@@ -3066,36 +4507,58 @@ BOOST_AUTO_TEST_CASE (verify_invalid_xml_cpl_extension_metadata9)
BOOST_AUTO_TEST_CASE (verify_unsigned_cpl_with_encrypted_content)
{
- path dir = "build/test/verify_unsigned_cpl_with_encrypted_content";
+ path const dir = "build/test/verify_unsigned_cpl_with_encrypted_content";
prepare_directory (dir);
for (auto i: directory_iterator("test/ref/DCP/encryption_test")) {
copy_file (i.path(), dir / i.path().filename());
}
- path const pkl = dir / ( "pkl_" + encryption_test_pkl_id() + ".xml" );
- path const cpl = dir / ( "cpl_" + encryption_test_cpl_id() + ".xml");
+ path const pkl = dir / ( "pkl_" + encryption_test_pkl_id() + ".xml");
+ path const cpl_path = dir / ( "cpl_" + encryption_test_cpl_id() + ".xml");
- HashCalculator calc(cpl);
+ HashCalculator calc(cpl_path);
{
- Editor e (cpl);
+ Editor e(cpl_path);
e.delete_lines ("<dsig:Signature", "</dsig:Signature>");
}
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
check_verify_result (
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::ALL_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"feature"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(cpl_path)
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, encryption_test_pkl_id(), canonical(pkl)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFEC_IN_FEATURE
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFMC_IN_FEATURE
+ ).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, encryption_test_cpl_id(), canonical(cpl)
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, encryption_test_pkl_id(), canonical(pkl), },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFEC_IN_FEATURE },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFMC_IN_FEATURE },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_FFOC },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_LFOC },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, encryption_test_cpl_id(), canonical(cpl) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, encryption_test_cpl_id(), canonical(cpl) }
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_FFOC
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_LFOC
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, canonical(cpl_path)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, canonical(cpl_path)
+ ).set_cpl_id(cpl->id())
});
}
@@ -3108,24 +4571,47 @@ BOOST_AUTO_TEST_CASE (verify_unsigned_pkl_with_encrypted_content)
copy_file (i.path(), dir / i.path().filename());
}
- path const cpl = dir / ("cpl_" + encryption_test_cpl_id() + ".xml");
+ path const cpl_path = dir / ("cpl_" + encryption_test_cpl_id() + ".xml");
path const pkl = dir / ("pkl_" + encryption_test_pkl_id() + ".xml");
{
Editor e (pkl);
e.delete_lines ("<dsig:Signature", "</dsig:Signature>");
}
+ auto cpl = std::make_shared<dcp::CPL>(cpl_path);
+
check_verify_result (
{dir},
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, encryption_test_pkl_id(), canonical(pkl) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFEC_IN_FEATURE },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFMC_IN_FEATURE },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_FFOC },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_LFOC },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, encryption_test_cpl_id(), canonical(cpl) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, encryption_test_pkl_id(), canonical(pkl) },
+ ok(dcp::VerificationNote::Code::ALL_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"feature"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, encryption_test_pkl_id(), canonical(pkl)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFEC_IN_FEATURE
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFMC_IN_FEATURE
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_FFOC
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_LFOC
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, canonical(cpl_path)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, encryption_test_pkl_id(), canonical(pkl)
+ )
});
}
@@ -3143,7 +4629,27 @@ BOOST_AUTO_TEST_CASE (verify_unsigned_pkl_with_unencrypted_content)
e.delete_lines ("<dsig:Signature", "</dsig:Signature>");
}
- check_verify_result({dir}, {}, {});
+ auto cpl = make_shared<dcp::CPL>(find_cpl(dir));
+
+ check_verify_result(
+ {dir},
+ {},
+ {
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ });
}
@@ -3164,10 +4670,10 @@ BOOST_AUTO_TEST_CASE (verify_partially_encrypted)
dcp::Key key;
- auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
+ auto mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction (24, 1), dcp::Standard::SMPTE);
mp->set_key (key);
- auto writer = mp->start_write(dir / "video.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto writer = mp->start_write(dir / "video.mxf", dcp::Behaviour::MAKE_NEW);
dcp::ArrayData j2c ("test/data/flat_red.j2c");
for (int i = 0; i < 24; ++i) {
writer->write (j2c.data(), j2c.size());
@@ -3210,7 +4716,22 @@ BOOST_AUTO_TEST_CASE (verify_partially_encrypted)
{dir},
{},
{
- {dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::PARTIALLY_ENCRYPTED},
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1440x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::PARTIALLY_ENCRYPTED
+ ).set_cpl_id(cpl->id())
});
}
@@ -3218,22 +4739,22 @@ BOOST_AUTO_TEST_CASE (verify_partially_encrypted)
BOOST_AUTO_TEST_CASE (verify_jpeg2000_codestream_2k)
{
vector<dcp::VerificationNote> notes;
- dcp::MonoPictureAsset picture (find_file(private_test / "data" / "JourneyToJah_TLR-1_F_EN-DE-FR_CH_51_2K_LOK_20140225_DGL_SMPTE_OV", "j2c.mxf"));
+ dcp::MonoJ2KPictureAsset picture (find_file(private_test / "data" / "JourneyToJah_TLR-1_F_EN-DE-FR_CH_51_2K_LOK_20140225_DGL_SMPTE_OV", "j2c.mxf"));
auto reader = picture.start_read ();
auto frame = reader->get_frame (0);
verify_j2k(frame, 0, 0, 24, notes);
- BOOST_REQUIRE_EQUAL (notes.size(), 0U);
+ BOOST_CHECK(notes.empty());
}
BOOST_AUTO_TEST_CASE (verify_jpeg2000_codestream_4k)
{
vector<dcp::VerificationNote> notes;
- dcp::MonoPictureAsset picture (find_file(private_test / "data" / "sul", "TLR"));
+ dcp::MonoJ2KPictureAsset picture (find_file(private_test / "data" / "sul", "TLR"));
auto reader = picture.start_read ();
auto frame = reader->get_frame (0);
verify_j2k(frame, 0, 0, 24, notes);
- BOOST_REQUIRE_EQUAL (notes.size(), 0U);
+ BOOST_CHECK(notes.empty());
}
@@ -3244,11 +4765,11 @@ BOOST_AUTO_TEST_CASE (verify_jpeg2000_codestream_libdcp)
auto dcp = make_simple (dir);
dcp->write_xml ();
vector<dcp::VerificationNote> notes;
- dcp::MonoPictureAsset picture (find_file(dir, "video"));
+ dcp::MonoJ2KPictureAsset picture (find_file(dir, "video"));
auto reader = picture.start_read ();
auto frame = reader->get_frame (0);
verify_j2k(frame, 0, 0, 24, notes);
- BOOST_REQUIRE_EQUAL (notes.size(), 0U);
+ BOOST_CHECK(notes.empty());
}
@@ -3310,10 +4831,24 @@ BOOST_AUTO_TEST_CASE (verify_mismatched_subtitle_resource_id)
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "240 0", boost::filesystem::canonical(subs_mxf) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_RESOURCE_ID },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "240 0", boost::filesystem::canonical(subs_mxf)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_RESOURCE_ID
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id())
});
}
@@ -3376,11 +4911,27 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_timed_text_id)
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "240 0", boost::filesystem::canonical(subs_mxf) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2018-10-02T12:25:14+02:00"} }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISMATCHED_TIMED_TEXT_DURATION , "240 0", boost::filesystem::canonical(subs_mxf)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INCORRECT_TIMED_TEXT_ASSET_ID
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE, string{"2018-10-02T12:25:14+02:00"}
+ ).set_cpl_id(cpl->id())
});
}
@@ -3388,18 +4939,29 @@ BOOST_AUTO_TEST_CASE (verify_incorrect_timed_text_id)
/** Check a DCP with a 3D asset marked as 2D */
BOOST_AUTO_TEST_CASE (verify_threed_marked_as_twod)
{
+ auto const path = private_test / "data" / "xm";
+
+ auto cpl = std::make_shared<dcp::CPL>(find_prefix(path, "CPL_"));
+ BOOST_REQUIRE(cpl);
+
check_verify_result (
- { private_test / "data" / "xm" },
+ { path },
{},
{
- {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "0d6f57e6-adac-4e1d-bfbe-d162bf13e2cd_j2c.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "0d6f57e6-adac-4e1d-bfbe-d162bf13e2cd_j2c.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ dcp::VerificationNote(
dcp::VerificationNote::Type::WARNING,
- dcp::VerificationNote::Code::THREED_ASSET_MARKED_AS_TWOD, boost::filesystem::canonical(find_file(private_test / "data" / "xm", "j2c"))
- },
- {
+ dcp::VerificationNote::Code::THREED_ASSET_MARKED_AS_TWOD, boost::filesystem::canonical(find_file(path, "j2c"))
+ ),
+ dcp::VerificationNote(
dcp::VerificationNote::Type::BV21_ERROR,
dcp::VerificationNote::Code::INVALID_STANDARD
- },
+ )
});
}
@@ -3422,17 +4984,34 @@ BOOST_AUTO_TEST_CASE (verify_unexpected_things_in_main_markers)
);
}
- dcp::CPL cpl (find_cpl(dir));
+ auto cpl = make_shared<dcp::CPL>(find_cpl(dir));
check_verify_result (
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl.id(), canonical(find_cpl(dir))
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::UNEXPECTED_ENTRY_POINT },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::UNEXPECTED_DURATION },
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::UNEXPECTED_ENTRY_POINT
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::UNEXPECTED_DURATION
+ ).set_cpl_id(cpl->id())
});
}
@@ -3451,16 +5030,30 @@ BOOST_AUTO_TEST_CASE(verify_invalid_content_kind)
e.replace("trailer", "trip");
}
- dcp::CPL cpl (find_cpl(dir));
+ auto cpl = std::make_shared<dcp::CPL>(find_cpl(dir));
check_verify_result (
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl.id(), canonical(find_cpl(dir))
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_CONTENT_KIND, string("trip") }
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_CONTENT_KIND, string("trip")
+ ).set_cpl_id(cpl->id()),
});
}
@@ -3480,17 +5073,28 @@ BOOST_AUTO_TEST_CASE(verify_valid_content_kind)
e.replace("<ContentKind>trailer</ContentKind>", "<ContentKind scope=\"http://bobs.contents/\">trip</ContentKind>");
}
- dcp::CPL cpl (find_cpl(dir));
+ auto cpl = std::make_shared<dcp::CPL>(find_cpl(dir));
check_verify_result (
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl.id(), canonical(find_cpl(dir))
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
});
-
}
@@ -3513,17 +5117,28 @@ BOOST_AUTO_TEST_CASE(verify_invalid_main_picture_active_area_1)
}
dcp::PKL pkl(find_pkl(dir));
- dcp::CPL cpl(find_cpl(dir));
+ auto cpl = std::make_shared<dcp::CPL>(find_cpl(dir));
check_verify_result(
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "width 1997 is not a multiple of 2", canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl.id(), canonical(find_cpl(dir))
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "width 1997 is not a multiple of 2", canonical(find_cpl(dir)) },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 4080 is bigger than the asset height 1080", canonical(find_cpl(dir)) },
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 4080 is bigger than the asset height 1080", canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()),
});
}
@@ -3547,18 +5162,31 @@ BOOST_AUTO_TEST_CASE(verify_invalid_main_picture_active_area_2)
}
dcp::PKL pkl(find_pkl(dir));
- dcp::CPL cpl(find_cpl(dir));
+ auto cpl = std::make_shared<dcp::CPL>(find_cpl(dir));
check_verify_result(
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
dcp::VerificationNote(
- dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, cpl.id(), canonical(find_cpl(dir))
- ).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 5125 is not a multiple of 2", canonical(find_cpl(dir)) },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "width 9900 is bigger than the asset width 1998", canonical(find_cpl(dir)) },
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 5125 is bigger than the asset height 1080", canonical(find_cpl(dir)) },
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_CPL_HASHES, canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()).set_reference_hash(calc.old_hash()).set_calculated_hash(calc.new_hash()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 5125 is not a multiple of 2", canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "width 9900 is bigger than the asset width 1998", canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_PICTURE_ACTIVE_AREA, "height 5125 is bigger than the asset height 1080", canonical(find_cpl(dir))
+ ).set_cpl_id(cpl->id())
});
}
@@ -3578,11 +5206,24 @@ BOOST_AUTO_TEST_CASE(verify_duplicate_pkl_asset_ids)
}
dcp::PKL pkl(find_pkl(dir));
+ auto cpl = std::make_shared<dcp::CPL>(find_cpl(dir));
check_verify_result(
{ dir },
{},
{
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
{ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::DUPLICATE_ASSET_ID_IN_PKL, pkl.id(), canonical(find_pkl(dir)) },
});
}
@@ -3604,13 +5245,30 @@ BOOST_AUTO_TEST_CASE(verify_duplicate_assetmap_asset_ids)
dcp::PKL pkl(find_pkl(dir));
dcp::AssetMap asset_map(find_asset_map(dir));
+ auto cpl = make_shared<dcp::CPL>(find_cpl(dir));
check_verify_result(
{ dir },
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::DUPLICATE_ASSET_ID_IN_ASSETMAP, asset_map.id(), canonical(find_asset_map(dir)) },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EXTERNAL_ASSET, string("5407b210-4441-4e97-8b16-8bdc7c12da54") },
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::DUPLICATE_ASSET_ID_IN_ASSETMAP, asset_map.id(), canonical(find_asset_map(dir))
+ ),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EXTERNAL_ASSET, string("5407b210-4441-4e97-8b16-8bdc7c12da54")
+ )
});
}
@@ -3683,7 +5341,25 @@ BOOST_AUTO_TEST_CASE(verify_mismatched_sound_channel_counts)
{ path },
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS, canonical(find_file(path, "audio2")) },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "video2.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS, canonical(find_file(path, "audio2"))
+ ).set_cpl_id(cpl->id())
});
}
@@ -3734,7 +5410,23 @@ BOOST_AUTO_TEST_CASE(verify_invalid_main_sound_configuration)
{ path },
{},
{
- { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_SOUND_CONFIGURATION, std::string{"MainSoundConfiguration has 6 channels but sound assets have 2"}, canonical(find_cpl(path)) },
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(path / "video1.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_MAIN_SOUND_CONFIGURATION, std::string{"MainSoundConfiguration has 6 channels but sound assets have 2"}, canonical(find_cpl(path))
+ ).set_cpl_id(cpl->id())
});
}
@@ -3748,8 +5440,8 @@ BOOST_AUTO_TEST_CASE(verify_invalid_tile_part_size)
boost::filesystem::remove_all(path);
boost::filesystem::create_directories(path);
- auto mp = make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
- auto picture_writer = mp->start_write(path / "video.mxf", dcp::PictureAsset::Behaviour::MAKE_NEW);
+ auto mp = make_shared<dcp::MonoJ2KPictureAsset>(dcp::Fraction(24, 1), dcp::Standard::SMPTE);
+ auto picture_writer = mp->start_write(path / "video.mxf", dcp::Behaviour::MAKE_NEW);
dcp::Size const size(1998, 1080);
auto image = make_shared<dcp::OpenJPEGImage>(size);
@@ -3789,20 +5481,40 @@ BOOST_AUTO_TEST_CASE(verify_invalid_tile_part_size)
dcp->set_annotation_text("A Test DCP");
dcp->write_xml();
- vector<dcp::VerificationNote> expected;
+ vector<dcp::VerificationNote> expected = {
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(path / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_FFOC
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_LFOC
+ ).set_cpl_id(cpl->id())
+ };
for (auto frame = 0; frame < 24; frame++) {
expected.push_back(
dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_PICTURE_FRAME_SIZE_IN_BYTES, canonical(path / "video.mxf")
- ).set_frame(frame).set_frame_rate(24)
+ ).set_frame(frame).set_frame_rate(24).set_cpl_id(cpl->id())
);
}
int component_sizes[] = {
- 1321721,
- 1294364,
- 1289952,
+ 1321816,
+ 1294414,
+ 1289881,
};
for (auto frame = 0; frame < 24; frame++) {
@@ -3810,19 +5522,11 @@ BOOST_AUTO_TEST_CASE(verify_invalid_tile_part_size)
expected.push_back(
dcp::VerificationNote(
dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_JPEG2000_TILE_PART_SIZE
- ).set_frame(frame).set_component(component).set_size(component_sizes[component])
+ ).set_frame(frame).set_component(component).set_size(component_sizes[component]).set_cpl_id(cpl->id())
);
}
}
- expected.push_back(
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_FFOC }
- );
-
- expected.push_back(
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_LFOC }
- );
-
check_verify_result({ path }, {}, expected);
}
@@ -3830,16 +5534,41 @@ BOOST_AUTO_TEST_CASE(verify_invalid_tile_part_size)
BOOST_AUTO_TEST_CASE(verify_too_many_subtitle_namespaces)
{
boost::filesystem::path const dir = "test/ref/DCP/subtitle_namespace_test";
+ dcp::DCP dcp(dir);
+ dcp.read();
+ BOOST_REQUIRE(!dcp.cpls().empty());
+ auto cpl = dcp.cpls()[0];
+
check_verify_result(
{ dir },
{},
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFEC_IN_FEATURE },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFMC_IN_FEATURE },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(find_file(dir, "sub_")) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, "fc815694-7977-4a27-a8b3-32b9d4075e4c", canonical(find_file(dir, "cpl_")) },
- { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, std::string{"315de731-1173-484c-9a35-bdacf5a9d99d"} }
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"feature"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"Dcp_FTR-1_F_XX-XX_MOS_2K_20230407_SMPTE_OV"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "j2c_42b34dcd-caa5-4c7b-aa0f-66a590947ba1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "j2c_42b34dcd-caa5-4c7b-aa0f-66a590947ba1.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFEC_IN_FEATURE
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_FFMC_IN_FEATURE
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_LANGUAGE, canonical(find_file(dir, "sub_"))
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, canonical(find_file(dir, "cpl_"))
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INCORRECT_SUBTITLE_NAMESPACE_COUNT, std::string{"315de731-1173-484c-9a35-bdacf5a9d99d"}
+ ).set_cpl_id(cpl->id()),
});
}
@@ -3855,14 +5584,19 @@ BOOST_AUTO_TEST_CASE(verify_missing_load_font_for_font)
}
auto asset = make_shared<dcp::InteropSubtitleAsset>(dir / "subs.xml");
auto reel_asset = make_shared<dcp::ReelInteropSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
- write_dcp_with_single_asset (dir, reel_asset, dcp::Standard::INTEROP);
+ auto cpl = write_dcp_with_single_asset(dir, reel_asset, dcp::Standard::INTEROP);
check_verify_result (
{dir},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
{ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_STANDARD },
- dcp::VerificationNote(dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_LOAD_FONT_FOR_FONT).set_id("theFontId")
+ dcp::VerificationNote(dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_LOAD_FONT_FOR_FONT).set_id("theFontId").set_cpl_id(cpl->id())
});
}
@@ -3903,14 +5637,29 @@ BOOST_AUTO_TEST_CASE(verify_missing_load_font)
subs->write(dir / "subs.mxf");
auto reel_subs = make_shared<dcp::ReelSMPTESubtitleAsset>(subs, dcp::Fraction(24, 1), 202, 0);
- dcp->cpls()[0]->reels()[0]->add(reel_subs);
+ auto cpl = dcp->cpls()[0];
+ cpl->reels()[0]->add(reel_subs);
dcp->write_xml();
check_verify_result (
{ dir },
{},
{
- dcp::VerificationNote(dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_LOAD_FONT).set_id(reel_subs->id())
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISSING_LOAD_FONT).set_id(reel_subs->id()).set_cpl_id(cpl->id())
});
}
@@ -3922,12 +5671,13 @@ BOOST_AUTO_TEST_CASE(verify_spots_wrong_asset)
auto dcp1 = make_simple(dir / "1");
dcp1->write_xml();
+ auto cpl = dcp1->cpls()[0];
- auto const asset_1 = dcp::MonoPictureAsset(dir / "1" / "video.mxf").id();
+ auto const asset_1 = dcp::MonoJ2KPictureAsset(dir / "1" / "video.mxf").id();
auto dcp2 = make_simple(dir / "2");
dcp2->write_xml();
- auto const asset_2 = dcp::MonoPictureAsset(dir / "2" / "video.mxf").id();
+ auto const asset_2 = dcp::MonoJ2KPictureAsset(dir / "2" / "video.mxf").id();
boost::filesystem::remove(dir / "1" / "video.mxf");
boost::filesystem::copy_file(dir / "2" / "video.mxf", dir / "1" / "video.mxf");
@@ -3936,6 +5686,18 @@ BOOST_AUTO_TEST_CASE(verify_spots_wrong_asset)
{dir / "1"},
{},
{
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
dcp::VerificationNote(dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_ASSET_MAP_ID).set_id(asset_1).set_other_id(asset_2)
});
}
@@ -3956,7 +5718,20 @@ BOOST_AUTO_TEST_CASE(verify_cpl_content_version_label_text_empty)
{dir},
{},
{
- dcp::VerificationNote(dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_CONTENT_VERSION_LABEL_TEXT, cpl->file().get()).set_id(cpl->id())
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::OK,
+ dcp::VerificationNote::Code::VALID_MAIN_PICTURE_ACTIVE_AREA,
+ string{"1998x1080"},
+ cpl->file().get()
+ ).set_cpl_id(cpl->id()),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"A Test DCP"}, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "video.mxf"), cpl),
+ dcp::VerificationNote(dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::EMPTY_CONTENT_VERSION_LABEL_TEXT, cpl->file().get()).set_cpl_id(cpl->id())
});
}
@@ -3979,9 +5754,21 @@ BOOST_AUTO_TEST_CASE(verify_encrypted_smpte_dcp)
{ dir },
{ kdm },
{
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, cpl->id(), canonical(cpl_file) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, cpl->id(), canonical(cpl_file) },
- { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, filename_to_id(pkl_file.filename()), canonical(pkl_file) }
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"trailer"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"hello"}, cpl),
+ ok(dcp::VerificationNote::Code::ALL_ENCRYPTED, cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, canonical(cpl_file)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, canonical(cpl_file)
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, filename_to_id(pkl_file.filename()), canonical(pkl_file)
+ )
});
}
diff --git a/test/wscript b/test/wscript
index d2cac0b3..64b3ed59 100644
--- a/test/wscript
+++ b/test/wscript
@@ -53,7 +53,7 @@ def configure(conf):
def build(bld):
obj = bld(features='cxx cxxprogram')
obj.name = 'tests'
- obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM BOOST_DATETIME OPENJPEG CXML XMLSEC1 SNDFILE OPENMP ASDCPLIB_CTH LIBXML++ OPENSSL XERCES DL'
+ obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM BOOST_DATETIME OPENJPEG CXML XMLSEC1 SNDFILE OPENMP ASDCPLIB_DCPOMATIC LIBXML++ OPENSSL XERCES DL AVCODEC AVUTIL'
obj.cppflags = ['-fno-inline', '-fno-elide-constructors', '-g', '-O0']
if bld.env['CXX_NAME'] == 'gcc':
obj.cppflags.append('-fno-default-inline')
@@ -94,6 +94,8 @@ def build(bld):
make_digest_test.cc
markers_test.cc
mca_test.cc
+ mono_mpeg2_picture_read_test.cc
+ mono_mpeg2_picture_write_test.cc
kdm_test.cc
key_test.cc
language_tag_test.cc
@@ -117,13 +119,14 @@ def build(bld):
utf8_test.cc
v_align_test.cc
verify_test.cc
+ verify_report_test.cc
"""
obj.target = 'tests'
obj.install_path = ''
obj = bld(features='cxx cxxprogram')
obj.name = 'subs_in_out'
- obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_CTH XMLSEC1 OPENSSL DL LIBXML++'
+ obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC XMLSEC1 OPENSSL DL LIBXML++ AVCODEC AVUTIL'
obj.cppflags = ['-fno-inline', '-fno-elide-constructors', '-g', '-O0']
if bld.env['CXX_NAME'] == 'gcc':
obj.cppflags.append('-fno-default-inline')
@@ -140,7 +143,7 @@ def build(bld):
obj = bld(features='cxx cxxprogram')
obj.name = 'rewrite_subs'
- obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_CTH XMLSEC1 OPENSSL DL LIBXML++'
+ obj.uselib = 'BOOST_TEST BOOST_FILESYSTEM OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC XMLSEC1 OPENSSL DL LIBXML++ AVCODEC AVUTIL'
obj.cppflags = ['-fno-inline', '-fno-elide-constructors', '-g', '-O0']
if bld.env['CXX_NAME'] == 'gcc':
obj.cppflags.append('-fno-default-inline')
diff --git a/tools/dcpdecryptmxf.cc b/tools/dcpdecryptmxf.cc
index 451a4d34..1145d77d 100644
--- a/tools/dcpdecryptmxf.cc
+++ b/tools/dcpdecryptmxf.cc
@@ -41,8 +41,8 @@
#include "encrypted_kdm.h"
#include "exceptions.h"
#include "key.h"
-#include "mono_picture_asset.h"
-#include "mono_picture_asset_writer.h"
+#include "mono_j2k_picture_asset.h"
+#include "mono_j2k_picture_asset_writer.h"
#include "sound_asset.h"
#include "sound_asset_writer.h"
#include "util.h"
@@ -232,10 +232,10 @@ main (int argc, char* argv[])
}
case Type::PICTURE:
{
- dcp::MonoPictureAsset in (input_file);
+ dcp::MonoJ2KPictureAsset in (input_file);
add_key (in, decrypted_kdm);
- dcp::MonoPictureAsset out (in.edit_rate(), dcp::Standard::SMPTE);
- auto writer = out.start_write(output_file.get(), dcp::PictureAsset::Behaviour::MAKE_NEW);
+ dcp::MonoJ2KPictureAsset out (in.edit_rate(), dcp::Standard::SMPTE);
+ auto writer = out.start_write(output_file.get(), dcp::Behaviour::MAKE_NEW);
copy (in, writer, ignore_hmac);
break;
}
diff --git a/tools/dcpdumpimage.cc b/tools/dcpdumpimage.cc
index 728e42c7..0ddf2d62 100644
--- a/tools/dcpdumpimage.cc
+++ b/tools/dcpdumpimage.cc
@@ -35,7 +35,7 @@
#include "colour_conversion.h"
#include "cpl.h"
#include "dcp.h"
-#include "mono_picture_asset.h"
+#include "mono_j2k_picture_asset.h"
#include "openjpeg_image.h"
#include "reel_picture_asset.h"
#include "raw_convert.h"
@@ -152,7 +152,7 @@ main(int argc, char* argv[])
if (frame_index >= duration) {
frame_index -= duration;
} else {
- auto reader = dynamic_pointer_cast<dcp::MonoPictureAsset>(reel->main_picture()->asset())->start_read();
+ auto reader = dynamic_pointer_cast<dcp::MonoJ2KPictureAsset>(reel->main_picture()->asset())->start_read();
auto frame = reader->get_frame(frame_index);
auto xyz = frame->xyz_image();
std::vector<uint8_t> rgba(xyz->size().width * xyz->size().height * 4);
diff --git a/tools/dcpinfo.cc b/tools/dcpinfo.cc
index e812afe4..f68fac24 100644
--- a/tools/dcpinfo.cc
+++ b/tools/dcpinfo.cc
@@ -41,8 +41,8 @@
#include "exceptions.h"
#include "filesystem.h"
#include "interop_subtitle_asset.h"
-#include "mono_picture_asset.h"
-#include "picture_asset.h"
+#include "mono_j2k_picture_asset.h"
+#include "j2k_picture_asset.h"
#include "reel.h"
#include "reel_picture_asset.h"
#include "reel_sound_asset.h"
@@ -158,12 +158,12 @@ main_picture (vector<string> const& only, shared_ptr<Reel> reel, bool analyse, b
OUTPUT_PICTURE("\n Picture: %1x%2\n", mp->asset()->size().width, mp->asset()->size().height);
}
- shared_ptr<MonoPictureAsset> ma = dynamic_pointer_cast<MonoPictureAsset>(mp->asset());
+ shared_ptr<MonoJ2KPictureAsset> ma = dynamic_pointer_cast<MonoJ2KPictureAsset>(mp->asset());
if (analyse && ma) {
- shared_ptr<MonoPictureAssetReader> reader = ma->start_read ();
+ shared_ptr<MonoJ2KPictureAssetReader> reader = ma->start_read ();
pair<int, int> j2k_size_range (INT_MAX, 0);
for (int64_t i = 0; i < ma->intrinsic_duration(); ++i) {
- shared_ptr<const MonoPictureFrame> frame = reader->get_frame (i);
+ shared_ptr<const MonoJ2KPictureFrame> frame = reader->get_frame (i);
if (SHOULD_PICTURE) {
printf("Frame %" PRId64 " J2K size %7d", i, frame->size());
}
diff --git a/tools/dcpverify.cc b/tools/dcpverify.cc
index 0ef256eb..88f0d705 100644
--- a/tools/dcpverify.cc
+++ b/tools/dcpverify.cc
@@ -37,6 +37,7 @@
#include "filesystem.h"
#include "raw_convert.h"
#include "verify.h"
+#include "verify_report.h"
#include "version.h"
#include <boost/bind/bind.hpp>
#include <boost/filesystem.hpp>
@@ -68,6 +69,7 @@ help (string n)
<< " --ignore-bv21-smpte don't give the SMPTE Bv2.1 error about a DCP not being SMPTE\n"
<< " --no-asset-hash-check don't check asset hashes\n"
<< " --asset-hash-check-maximum-size <size-in-MB> only check hashes for assets smaller than this size (in MB)\n"
+ << " -o <filename> write HTML report to filename\n"
<< " -q, --quiet don't report progress\n";
}
@@ -80,6 +82,7 @@ main (int argc, char* argv[])
bool ignore_missing_assets = false;
bool ignore_bv21_smpte = false;
bool quiet = false;
+ boost::optional<boost::filesystem::path> report_filename;
dcp::VerificationOptions verification_options;
@@ -96,7 +99,7 @@ main (int argc, char* argv[])
{ 0, 0, 0, 0 }
};
- int c = getopt_long (argc, argv, "VhABCD:q", long_options, &option_index);
+ int c = getopt_long (argc, argv, "VhABCD:qo:", long_options, &option_index);
if (c == -1) {
break;
@@ -126,6 +129,9 @@ main (int argc, char* argv[])
case 'q':
quiet = true;
break;
+ case 'o':
+ report_filename = optarg;
+ break;
}
}
@@ -173,8 +179,8 @@ main (int argc, char* argv[])
vector<boost::filesystem::path> directories;
directories.push_back (argv[optind]);
- auto notes = dcp::verify(directories, {}, stage, progress, verification_options);
- dcp::filter_notes (notes, ignore_missing_assets);
+ auto result = dcp::verify(directories, {}, stage, progress, verification_options);
+ dcp::filter_notes(result.notes, ignore_missing_assets);
if (!quiet) {
cout << "\n";
@@ -183,11 +189,13 @@ main (int argc, char* argv[])
bool failed = false;
bool bv21_failed = false;
bool warned = false;
- for (auto i: notes) {
+ for (auto i: result.notes) {
if (ignore_bv21_smpte && i.code() == dcp::VerificationNote::Code::INVALID_STANDARD) {
continue;
}
switch (i.type()) {
+ case dcp::VerificationNote::Type::OK:
+ break;
case dcp::VerificationNote::Type::ERROR:
cout << "Error: " << note_to_string(i) << "\n";
failed = true;
@@ -215,5 +223,10 @@ main (int argc, char* argv[])
}
}
+ if (report_filename) {
+ dcp::HTMLFormatter formatter(*report_filename);
+ dcp::verify_report(result, formatter);
+ }
+
exit (failed ? EXIT_FAILURE : EXIT_SUCCESS);
}
diff --git a/tools/wscript b/tools/wscript
index 3ee04e94..d282c88c 100644
--- a/tools/wscript
+++ b/tools/wscript
@@ -32,7 +32,7 @@
#
def build(bld):
- uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES DL MAGICK'
+ uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_DCPOMATIC BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL XERCES DL MAGICK AVCODEC AVUTIL'
for f in ['diff', 'info', 'verify']:
obj = bld(features='cxx cxxprogram')
diff --git a/wscript b/wscript
index ba74aa0f..89026bcd 100644
--- a/wscript
+++ b/wscript
@@ -59,7 +59,7 @@ def options(opt):
opt.add_option('--target-windows-64', action='store_true', default=False, help='set up to do a cross-compile to Windows 64-bit')
opt.add_option('--target-windows-32', action='store_true', default=False, help='set up to do a cross-compile to Windows 32-bit')
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 statically, and link statically to openjpeg, cxml, asdcplib-carl')
+ opt.add_option('--static', action='store_true', default=False, help='build libdcp statically, and link statically to openjpeg, cxml, asdcplib-dcpomatic')
opt.add_option('--disable-tests', action='store_true', default=False, help='disable building of tests')
opt.add_option('--disable-benchmarks', action='store_true', default=False, help='disable building of benchmarks')
opt.add_option('--enable-gcov', action='store_true', default=False, help='use gcov in tests')
@@ -67,11 +67,20 @@ def options(opt):
opt.add_option('--disable-dumpimage', action='store_true', default=False, help='disable building of dcpdumpimage')
opt.add_option('--enable-openmp', action='store_true', default=False, help='enable use of OpenMP')
opt.add_option('--openmp', default='gomp', help='specify OpenMP Library to use: omp, gomp (default), iomp')
+ opt.add_option('--c++17', action='store_true', default=False, help='build with C++17 and libxml++-4.0')
def configure(conf):
conf.load('compiler_cxx')
conf.load('clang_compilation_database', tooldir=['waf-tools'])
- conf.env.append_value('CXXFLAGS', ['-Wall', '-Wextra', '-D_FILE_OFFSET_BITS=64', '-D__STDC_FORMAT_MACROS', '-std=c++11'])
+
+ if vars(conf.options)['c++17']:
+ cpp_std = '17'
+ conf.env.XMLPP_API = '4.0'
+ else:
+ cpp_std = '11'
+ conf.env.XMLPP_API = '2.6'
+
+ conf.env.append_value('CXXFLAGS', ['-Wall', '-Wextra', '-D_FILE_OFFSET_BITS=64', '-D__STDC_FORMAT_MACROS', '-std=c++' + cpp_std])
gcc = conf.env['CC_VERSION']
if int(gcc[0]) >= 4 and int(gcc[1]) > 1:
conf.env.append_value('CXXFLAGS', ['-Wno-maybe-uninitialized'])
@@ -118,7 +127,7 @@ def configure(conf):
conf.check(lib='dl', uselib_store='DL', msg='Checking for library dl')
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='libxml++-' + conf.env.XMLPP_API, 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]
@@ -153,20 +162,20 @@ def configure(conf):
if not patched_openjpeg:
# We don't have our patched version so we need 2.5.0 to get the GUARD_BITS option
- conf.check_cfg(package='libopenjp2', args='libopenjp2 >= 2.5.0', uselib_store='OPENJPEG', mandatory=True, msg='Checking for libopenjp2 >= 2.5.0')
+ conf.check_cfg(package='libopenjp2', args='libopenjp2 >= 2.5.0 --cflags --libs', uselib_store='OPENJPEG', mandatory=True, msg='Checking for libopenjp2 >= 2.5.0')
if conf.options.static:
conf.env.STLIB_OPENJPEG = ['openjp2']
- conf.check_cfg(package='libasdcp-carl', args='libasdcp-carl >= 0.1.3 --cflags', uselib_store='ASDCPLIB_CTH', mandatory=True)
- conf.env.HAVE_ASDCPLIB_CTH = 1
- conf.env.STLIB_ASDCPLIB_CTH = ['asdcp-carl', 'kumu-carl']
+ conf.check_cfg(package='libasdcp-dcpomatic', args='libasdcp-dcpomatic >= 0.1.3 --cflags', uselib_store='ASDCPLIB_DCPOMATIC', mandatory=True)
+ conf.env.HAVE_ASDCPLIB_DCPOMATIC = 1
+ conf.env.STLIB_ASDCPLIB_DCPOMATIC = ['asdcp-dcpomatic', 'kumu-dcpomatic']
conf.env.HAVE_CXML = 1
- conf.env.LIB_CXML = ['xml++-2.6', 'glibmm-2.4']
+ conf.env.LIB_CXML = ['xml++-' + conf.env.XMLPP_API, 'glibmm-2.4']
conf.env.STLIB_CXML = ['cxml']
conf.check_cfg(package='xerces-c', args='--cflags', uselib_store='XERCES', mandatory=True)
conf.env.LIB_XERCES = ['xerces-c', 'icuuc', 'curl']
else:
- conf.check_cfg(package='libasdcp-carl', args='libasdcp-carl >= 0.1.3 --cflags --libs', uselib_store='ASDCPLIB_CTH', mandatory=True)
+ conf.check_cfg(package='libasdcp-dcpomatic', args='libasdcp-dcpomatic >= 0.1.3 --cflags --libs', uselib_store='ASDCPLIB_DCPOMATIC', mandatory=True)
conf.check_cfg(package='libcxml', args='libcxml >= 0.17.0 --cflags --libs', uselib_store='CXML', mandatory=True)
conf.check_cfg(package='xerces-c', args='--cflags --libs', uselib_store='XERCES', mandatory=True)
@@ -239,6 +248,9 @@ def configure(conf):
lib=['boost_date_time%s' % boost_lib_suffix, 'boost_system%s' % boost_lib_suffix],
uselib_store='BOOST_DATETIME')
+ conf.check_cfg(package='libavcodec', args='--cflags --libs', uselib_store='AVCODEC', mandatory=True)
+ conf.check_cfg(package='libavutil', args='--cflags --libs', uselib_store='AVUTIL', mandatory=True)
+
if not conf.env.DISABLE_TESTS:
conf.recurse('test')
if conf.options.enable_gcov:
@@ -263,7 +275,8 @@ def build(bld):
version=VERSION,
includedir='%s/include/libdcp%s' % (bld.env.PREFIX, bld.env.API_VERSION),
libs=libs,
- install_path='${LIBDIR}/pkgconfig')
+ install_path='${LIBDIR}/pkgconfig',
+ xmlpp_api=bld.env.XMLPP_ABI)
bld.recurse('src')
bld.recurse('tools')