Tidy up parameters in VerificationNote.
authorCarl Hetherington <cth@carlh.net>
Tue, 19 Jan 2021 22:36:27 +0000 (23:36 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 19 Jan 2021 22:36:27 +0000 (23:36 +0100)
src/dcp.cc
src/verify.cc
src/verify.h
test/verify_test.cc

index ee1a64ed6211907d34799eb1d08730863910a08e..11721b78232816bc94237d545e7ab572303867bc 100644 (file)
@@ -192,14 +192,14 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m
                           claims to come from ClipsterDCI 5.10.0.5.
                        */
                        if (notes) {
-                               notes->push_back (VerificationNote(VerificationNote::VERIFY_WARNING, VerificationNote::EMPTY_ASSET_PATH));
+                               notes->push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::EMPTY_ASSET_PATH});
                        }
                        continue;
                }
 
                if (!boost::filesystem::exists(path)) {
                        if (notes) {
-                               notes->push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::MISSING_ASSET, path));
+                               notes->push_back ({VerificationNote::VERIFY_ERROR, VerificationNote::MISSING_ASSET, path});
                        }
                        continue;
                }
@@ -235,7 +235,7 @@ DCP::read (vector<dcp::VerificationNote>* notes, bool ignore_incorrect_picture_m
                        if (root == "CompositionPlaylist") {
                                auto cpl = make_shared<CPL>(path);
                                if (_standard && cpl->standard() && cpl->standard().get() != _standard.get() && notes) {
-                                       notes->push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::MISMATCHED_STANDARD));
+                                       notes->push_back ({VerificationNote::VERIFY_ERROR, VerificationNote::MISMATCHED_STANDARD});
                                }
                                _cpls.push_back (cpl);
                        } else if (root == "DCSubtitle") {
index 0fcb88353979764a5d5a2d4749041e839f891237..37bad761ca9dc30670650d8e423dc55d27a56bf6 100644 (file)
@@ -343,15 +343,13 @@ validate_xml (T xml, boost::filesystem::path xsd_dtd_directory, vector<Verificat
        XMLPlatformUtils::Terminate ();
 
        for (auto i: error_handler.errors()) {
-               notes.push_back (
-                       VerificationNote(
-                               VerificationNote::VERIFY_ERROR,
-                               VerificationNote::INVALID_XML,
-                               i.message(),
-                               boost::trim_copy(i.public_id() + " " + i.system_id()),
-                               i.line()
-                               )
-                       );
+               notes.push_back ({
+                       VerificationNote::VERIFY_ERROR,
+                       VerificationNote::INVALID_XML,
+                       i.message(),
+                       boost::trim_copy(i.public_id() + " " + i.system_id()),
+                       i.line()
+               });
        }
 }
 
@@ -507,18 +505,14 @@ verify_main_picture_asset (
        auto const pr = verify_picture_asset (reel_asset, progress);
        switch (pr) {
                case VERIFY_PICTURE_ASSET_RESULT_BAD:
-                       notes.push_back (
-                               VerificationNote(
-                                       VerificationNote::VERIFY_ERROR, VerificationNote::INVALID_PICTURE_FRAME_SIZE_IN_BYTES, file
-                                       )
-                               );
+                       notes.push_back ({
+                               VerificationNote::VERIFY_ERROR, VerificationNote::INVALID_PICTURE_FRAME_SIZE_IN_BYTES, file
+                       });
                        break;
                case VERIFY_PICTURE_ASSET_RESULT_FRAME_NEARLY_TOO_LARGE:
-                       notes.push_back (
-                               VerificationNote(
-                                       VerificationNote::VERIFY_WARNING, VerificationNote::NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES, file
-                                       )
-                               );
+                       notes.push_back ({
+                               VerificationNote::VERIFY_WARNING, VerificationNote::NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES, file
+                       });
                        break;
                default:
                        break;
@@ -574,6 +568,7 @@ verify_main_picture_asset (
                                VerificationNote(
                                        VerificationNote::VERIFY_BV21_ERROR,
                                        VerificationNote::INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D,
+                                       String::compose("%1/%2", asset->edit_rate().numerator, asset->edit_rate().denominator),
                                        file
                                        )
                                );
@@ -621,7 +616,7 @@ verify_main_sound_asset (
        if (asset->sampling_rate() != 48000) {
                notes.push_back (
                        VerificationNote(
-                               VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_SOUND_FRAME_RATE, *asset->file()
+                               VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_SOUND_FRAME_RATE, raw_convert<string>(asset->sampling_rate()), *asset->file()
                                )
                        );
        }
@@ -637,9 +632,9 @@ verify_main_subtitle_reel (shared_ptr<const ReelSubtitleAsset> reel_asset, vecto
        }
 
        if (!reel_asset->entry_point()) {
-               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_SUBTITLE_ENTRY_POINT });
+               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_SUBTITLE_ENTRY_POINT, reel_asset->id() });
        } else if (reel_asset->entry_point().get()) {
-               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INCORRECT_SUBTITLE_ENTRY_POINT });
+               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INCORRECT_SUBTITLE_ENTRY_POINT, reel_asset->id() });
        }
 }
 
@@ -653,9 +648,9 @@ verify_closed_caption_reel (shared_ptr<const ReelClosedCaptionAsset> reel_asset,
        }
 
        if (!reel_asset->entry_point()) {
-               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CLOSED_CAPTION_ENTRY_POINT });
+               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CLOSED_CAPTION_ENTRY_POINT, reel_asset->id() });
        } else if (reel_asset->entry_point().get()) {
-               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INCORRECT_CLOSED_CAPTION_ENTRY_POINT });
+               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INCORRECT_CLOSED_CAPTION_ENTRY_POINT, reel_asset->id() });
        }
 }
 
@@ -685,8 +680,11 @@ verify_smpte_subtitle_asset (
        } else {
                notes.push_back ({ VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_SUBTITLE_LANGUAGE, *asset->file() });
        }
-       if (boost::filesystem::file_size(asset->file().get()) > 115 * 1024 * 1024) {
-               notes.push_back ({ VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_TIMED_TEXT_SIZE_IN_BYTES, *asset->file() });
+       auto const size = boost::filesystem::file_size(asset->file().get());
+       if (size > 115 * 1024 * 1024) {
+               notes.push_back (
+                       { VerificationNote::VERIFY_BV21_ERROR, VerificationNote::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"
         * but I'm hoping that checking for the total size of all fonts being <= 10MB will do.
@@ -697,7 +695,7 @@ verify_smpte_subtitle_asset (
                total_size += i.second.size();
        }
        if (total_size > 10 * 1024 * 1024) {
-               notes.push_back ({ VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, asset->file().get() });
+               notes.push_back ({ VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, raw_convert<string>(total_size), asset->file().get() });
        }
 
        if (!asset->start_time()) {
@@ -744,7 +742,7 @@ verify_closed_caption_asset (
        if (asset->raw_xml().size() > 256 * 1024) {
                notes.push_back (
                        VerificationNote(
-                               VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, *asset->file()
+                               VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, raw_convert<string>(asset->raw_xml().size()), *asset->file()
                                )
                        );
        }
@@ -814,27 +812,21 @@ check_text_timing (
        }
 
        if (too_early) {
-               notes.push_back(
-                       VerificationNote(
-                               VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_FIRST_TEXT_TIME
-                               )
-                       );
+               notes.push_back({
+                       VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_FIRST_TEXT_TIME
+               });
        }
 
        if (too_short) {
-               notes.push_back (
-                       VerificationNote(
-                               VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_DURATION
-                               )
-                       );
+               notes.push_back ({
+                       VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_DURATION
+               });
        }
 
        if (too_close) {
-               notes.push_back (
-                       VerificationNote(
-                               VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_SPACING
-                               )
-                       );
+               notes.push_back ({
+                       VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_SPACING
+               });
        }
 }
 
@@ -1032,9 +1024,9 @@ check_extension_metadata (shared_ptr<CPL> cpl, vector<VerificationNote>& notes)
        }
 
        if (missing) {
-               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_EXTENSION_METADATA});
+               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_EXTENSION_METADATA, cpl->id(), cpl->file().get()});
        } else if (!malformed.empty()) {
-               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_EXTENSION_METADATA, malformed});
+               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_EXTENSION_METADATA, malformed, cpl->file().get()});
        }
 }
 
@@ -1133,9 +1125,9 @@ dcp::verify (
 
                        if (dcp->standard() == SMPTE) {
                                if (!cpl->annotation_text()) {
-                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CPL_ANNOTATION_TEXT));
+                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CPL_ANNOTATION_TEXT, cpl->id(), cpl->file().get()});
                                } else if (cpl->annotation_text().get() != cpl->content_title_text()) {
-                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_WARNING, VerificationNote::MISMATCHED_CPL_ANNOTATION_TEXT));
+                                       notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::MISMATCHED_CPL_ANNOTATION_TEXT, cpl->id(), cpl->file().get()});
                                }
                        }
 
@@ -1143,7 +1135,7 @@ dcp::verify (
                                /* Check that the CPL's hash corresponds to the PKL */
                                optional<string> h = i->hash(cpl->id());
                                if (h && make_digest(ArrayData(*cpl->file())) != *h) {
-                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::MISMATCHED_CPL_HASHES));
+                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get()));
                                }
 
                                /* Check that any PKL with a single CPL has its AnnotationText the same as the CPL's ContentTitleText */
@@ -1164,7 +1156,7 @@ dcp::verify (
                                }
 
                                if (required_annotation_text && i->annotation_text() != required_annotation_text) {
-                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, i->file().get()});
+                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, i->id(), i->file().get()});
                                }
                        }
 
@@ -1200,7 +1192,7 @@ dcp::verify (
                                                if (!duration) {
                                                        duration = i->actual_duration();
                                                } else if (*duration != i->actual_duration()) {
-                                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISMATCHED_ASSET_DURATION));
+                                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISMATCHED_ASSET_DURATION});
                                                        break;
                                                }
                                        }
@@ -1217,7 +1209,11 @@ dcp::verify (
                                             frame_rate.numerator != 50 &&
                                             frame_rate.numerator != 60 &&
                                             frame_rate.numerator != 96)) {
-                                               notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::INVALID_PICTURE_FRAME_RATE));
+                                               notes.push_back ({
+                                                       VerificationNote::VERIFY_ERROR,
+                                                       VerificationNote::INVALID_PICTURE_FRAME_RATE,
+                                                       String::compose("%1/%2", frame_rate.numerator, frame_rate.denominator)
+                                               });
                                        }
                                        /* Check asset */
                                        if (reel->main_picture()->asset_ref().resolved()) {
@@ -1279,14 +1275,17 @@ dcp::verify (
                                if (ffoc == markers_seen.end()) {
                                        notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::MISSING_FFOC});
                                } else if (ffoc->second.e != 1) {
-                                       notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::INCORRECT_FFOC});
+                                       notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::INCORRECT_FFOC, raw_convert<string>(ffoc->second.e)});
                                }
 
                                auto lfoc = markers_seen.find(Marker::LFOC);
                                if (lfoc == markers_seen.end()) {
                                        notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::MISSING_LFOC});
-                               } else if (lfoc->second.as_editable_units(lfoc->second.tcr) != (cpl->reels().back()->duration() - 1)) {
-                                       notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::INCORRECT_LFOC});
+                               } else {
+                                       auto lfoc_time = lfoc->second.as_editable_units(lfoc->second.tcr);
+                                       if (lfoc_time != (cpl->reels().back()->duration() - 1)) {
+                                               notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::INCORRECT_LFOC, raw_convert<string>(lfoc_time)});
+                                       }
                                }
 
                                check_text_timing (cpl->reels(), notes);
@@ -1299,7 +1298,7 @@ dcp::verify (
                                }
 
                                if (result.line_count_exceeded) {
-                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_LINE_COUNT));
+                                       notes.push_back ({VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_LINE_COUNT});
                                }
                                if (result.error_length_exceeded) {
                                        notes.push_back (VerificationNote(VerificationNote::VERIFY_WARNING, VerificationNote::INVALID_SUBTITLE_LINE_LENGTH));
@@ -1317,19 +1316,19 @@ dcp::verify (
                                }
 
                                if (result.line_count_exceeded) {
-                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_CLOSED_CAPTION_LINE_COUNT));
+                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_CLOSED_CAPTION_LINE_COUNT});
                                }
                                if (result.error_length_exceeded) {
-                                       notes.push_back (VerificationNote(VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_CLOSED_CAPTION_LINE_LENGTH));
+                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::INVALID_CLOSED_CAPTION_LINE_LENGTH});
                                }
 
                                if (!cpl->full_content_title_text()) {
                                        /* Since FullContentTitleText is assumed always to exist if there's a CompositionMetadataAsset we
                                         * can use it as a proxy for CompositionMetadataAsset's existence.
                                         */
-                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CPL_METADATA});
+                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get()});
                                } else if (!cpl->version_number()) {
-                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CPL_METADATA_VERSION_NUMBER});
+                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::MISSING_CPL_METADATA_VERSION_NUMBER, cpl->id(), cpl->file().get()});
                                }
 
                                check_extension_metadata (cpl, notes);
@@ -1339,7 +1338,7 @@ dcp::verify (
                                        DCP_ASSERT (cpl->file());
                                        doc.read_file (cpl->file().get());
                                        if (!doc.optional_node_child("Signature")) {
-                                               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, cpl->file().get()});
+                                               notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, cpl->id(), cpl->file().get()});
                                        }
                                }
                        }
@@ -1352,7 +1351,7 @@ dcp::verify (
                                cxml::Document doc ("PackingList");
                                doc.read_file (pkl->file().get());
                                if (!doc.optional_node_child("Signature")) {
-                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, pkl->file().get()});
+                                       notes.push_back ({VerificationNote::VERIFY_BV21_ERROR, VerificationNote::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, pkl->id(), pkl->file().get()});
                                }
                        }
                }
index 11f879ff7979dde167b263a4d4b76692e2b33a08..ad733b01aaef2a4f5537c37bc19da5cb36d068fd 100644 (file)
@@ -73,68 +73,127 @@ public:
         *
         *  Comments should clarify meaning and also say which of the optional fields (e.g. file)
         *  are filled in when this code is used.
-        *  XXX: this needs checking.
         */
        enum Code {
-               /** An error when reading the DCP.  note contains (probably technical) details. */
+               /** An error when reading the DCP.
+                *  note contains (probably technical) details.
+                */
                FAILED_READ,
-               /** The hash of the CPL in the PKL does not agree with the CPL file */
+               /** The hash of the CPL in the PKL does not agree with the CPL file.
+                *  note contains CPL ID.
+                *  file contains CPL filename.
+                */
                MISMATCHED_CPL_HASHES,
-               /** Frame rate given in a reel for the main picture is not 24, 25, 30, 48, 50 or 60 */
+               /** Frame rate given in a reel for the main picture is not 24, 25, 30, 48, 50 or 60.
+                *  note contains the invalid frame rate as "<numerator>/<denominator>"
+                */
                INVALID_PICTURE_FRAME_RATE,
-               /** The hash of a main picture asset does not agree with the PKL file.  file contains the picture asset filename. */
+               /** The hash of a main picture asset does not agree with the PKL file.
+                *  file contains the picture asset filename.
+                */
                INCORRECT_PICTURE_HASH,
-               /** The hash of a main picture is different in the CPL and PKL */
+               /** The hash of a main picture is different in the CPL and PKL.
+                *  file contains the picture asset filename.
+                */
                MISMATCHED_PICTURE_HASHES,
-               /** The hash of a main sound asset does not agree with the PKL file.  file contains the sound asset filename. */
+               /** The hash of a main sound asset does not agree with the PKL file.
+                *  file contains the sound asset filename.
+                */
                INCORRECT_SOUND_HASH,
-               /** The hash of a main sound is different in the CPL and PKL */
+               /** The hash of a main sound is different in the CPL and PKL.
+                *  file contains the sound asset filename.
+                */
                MISMATCHED_SOUND_HASHES,
-               /** An assetmap's <Path> entry is empty */
+               /** An assetmap's <Path> entry is empty. */
                EMPTY_ASSET_PATH,
-               /** A file mentioned in an asset map cannot be found */
+               /** A file mentioned in an asset map cannot be found.
+                *  file contains the filename that is missing.
+                */
                MISSING_ASSET,
                /** The DCP contains both SMPTE and Interop-standard components */
                MISMATCHED_STANDARD,
-               /** Some XML fails to validate against the XSD/DTD */
+               /** Some XML fails to validate against the XSD/DTD.
+                *  note contains the (probably technical) details.
+                *  file contains the invalid filename.
+                *  line contains the line number.
+                */
                INVALID_XML,
                /** No ASSETMAP{.xml} was found */
                MISSING_ASSETMAP,
-               /** An asset's IntrinsicDuration is less than 1 second */
+               /** An asset's IntrinsicDuration is less than 1 second.
+                *  note contains asset ID.
+                */
                INVALID_INTRINSIC_DURATION,
-               /** An asset's Duration is less than 1 second */
+               /** An asset's Duration is less than 1 second.
+                *  note contains asset ID.
+                */
                INVALID_DURATION,
-               /** The JPEG2000 data in at least one picture frame is larger than the equivalent of 250Mbit/s */
+               /** The JPEG2000 data in at least one picture frame is larger than the equivalent of 250Mbit/s.
+                *  file contains the picture asset filename.
+                */
                INVALID_PICTURE_FRAME_SIZE_IN_BYTES,
-               /** The JPEG2000 data in at least one picture frame is larger than the equivalent of 230Mbit/s */
+               /** The JPEG2000 data in at least one picture frame is larger than the equivalent of 230Mbit/s.
+                *  file contains the picture asset filename.
+                */
                NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES,
-               /** An asset that the CPL requires is not in this DCP; the DCP may be a VF */
+               /** An asset that the CPL requires is not in this DCP; the DCP may be a VF.
+                *  note contains the asset ID.
+                */
                EXTERNAL_ASSET,
                /** DCP is Interop, not SMPTE [Bv2.1_6.1] */
                INVALID_STANDARD,
-               /** A language or territory does not conform to RFC 5646 [Bv2.1_6.2.1] */
+               /** A language or territory does not conform to RFC 5646 [Bv2.1_6.2.1].
+                *  note contains the invalid language.
+                */
                INVALID_LANGUAGE,
-               /** A picture asset does not have one of the required Bv2.1 sizes (in pixels) [Bv2.1_7.1] */
+               /** 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.
+                */
                INVALID_PICTURE_SIZE_IN_PIXELS,
-               /** A picture asset is 2K but is not at 24, 25 or 48 fps as required by Bv2.1 [Bv2.1_7.1] */
+               /** A picture asset is 2K but is not at 24, 25 or 48 fps as required by Bv2.1 [Bv2.1_7.1].
+                *  note contains the invalid frame rate as "<numerator>/<denominator>"
+                *  file contains the asset filename.
+                */
                INVALID_PICTURE_FRAME_RATE_FOR_2K,
-               /** A picture asset is 4K but is not at 24fps as required by Bv2.1 [Bv2.1_7.1] */
+               /** A picture asset is 4K but is not at 24fps as required by Bv2.1 [Bv2.1_7.1]
+                *  note contains the invalid frame rate as "<numerator>/<denominator>"
+                *  file contains the asset filename.
+                */
                INVALID_PICTURE_FRAME_RATE_FOR_4K,
-               /** A picture asset is 4K but is 3D which is not allowed by Bv2.1 [Bv2.1_7.1] */
+               /** A picture asset is 4K but is 3D which is not allowed by Bv2.1 [Bv2.1_7.1]
+                *  note contains the invalid frame rate as "<numerator>/<denominator>"
+                *  file contains the asset filename.
+                */
                INVALID_PICTURE_ASSET_RESOLUTION_FOR_3D,
-               /** A closed caption's XML file is larger than 256KB [Bv2.1_7.2.1] */
+               /** A closed caption's XML file is larger than 256KB [Bv2.1_7.2.1].
+                *  note contains the invalid size in bytes.
+                *  file contains the asset filename.
+                */
                INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES,
-               /** Any timed text asset's total files is larger than 115MB [Bv2.1_7.2.1] */
+               /** Any timed text asset's total files is larger than 115MB [Bv2.1_7.2.1]
+                *  note contains the invalid size in bytes.
+                *  file contains the asset filename.
+                */
                INVALID_TIMED_TEXT_SIZE_IN_BYTES,
-               /** The total size of all a timed text asset's fonts is larger than 10MB [Bv2.1_7.2.1] */
+               /** The total size of all a timed text asset's fonts is larger than 10MB [Bv2.1_7.2.1]
+                *  note contains the invalid size in bytes.
+                *  file contains the asset filename.
+                */
                INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES,
-               /** Some SMPTE subtitle XML has no <Language> tag [Bv2.1_7.2.2] */
+               /** Some SMPTE subtitle XML has no <Language> tag [Bv2.1_7.2.2]
+                *  file contains the asset filename.
+                */
                MISSING_SUBTITLE_LANGUAGE,
                /** Not all subtitle assets specify the same <Language> tag [Bv2.1_7.2.2] */
                MISMATCHED_SUBTITLE_LANGUAGES,
-               /** Some SMPTE subtitle XML has no <StartTime> tag [Bv2.1_7.2.3] */
+               /** Some SMPTE subtitle XML has no <StartTime> tag [Bv2.1_7.2.3]
+                *  file contains the asset filename.
+                */
                MISSING_SUBTITLE_START_TIME,
-               /** Some SMPTE subtitle XML has a non-zero <StartTime> tag [Bv2.1_7.2.3] */
+               /** Some SMPTE subtitle XML has a non-zero <StartTime> tag [Bv2.1_7.2.3]
+                *  file contains the asset filename.
+                */
                INVALID_SUBTITLE_START_TIME,
                /** The first subtitle or closed caption happens before 4s into the first reel [Bv2.1_7.2.4] */
                INVALID_SUBTITLE_FIRST_TEXT_TIME,
@@ -152,11 +211,20 @@ public:
                INVALID_CLOSED_CAPTION_LINE_COUNT,
                /** There are more than 32 characters in at least one closed caption line [Bv2.1_7.2.6] */
                INVALID_CLOSED_CAPTION_LINE_LENGTH,
-               /** The audio sampling rate must be 48kHz [Bv2.1_7.3] */
+               /** The audio sampling rate must be 48kHz [Bv2.1_7.3].
+                *  note contains the invalid frame rate.
+                *  file contains the asset filename.
+                */
                INVALID_SOUND_FRAME_RATE,
-               /** The CPL has no <AnnotationText> tag [Bv2.1_8.1] */
+               /** The CPL has no <AnnotationText> tag [Bv2.1_8.1]
+                *  note contains the CPL ID.
+                *  file contains the CPL filename.
+                */
                MISSING_CPL_ANNOTATION_TEXT,
-               /** The <AnnotationText> is not the same as the <ContentTitleText> [Bv2.1_8.1] */
+               /** The <AnnotationText> is not the same as the <ContentTitleText> [Bv2.1_8.1]
+                *  note contains the CPL ID.
+                *  file contains the CPL filename.
+                */
                MISMATCHED_CPL_ANNOTATION_TEXT,
                /** At least one asset in a reel does not have the same duration as the others */
                MISMATCHED_ASSET_DURATION,
@@ -164,15 +232,25 @@ public:
                MISSING_MAIN_SUBTITLE_FROM_SOME_REELS,
                /** If one reel has at least one ClosedCaption, all reels must have the same number of ClosedCaptions */
                MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS,
-               /** MainSubtitle in reels must have <EntryPoint> Bv2.1_8.3.2 */
+               /** MainSubtitle in reels must have <EntryPoint> Bv2.1_8.3.2
+                *  note contains the asset ID
+                */
                MISSING_SUBTITLE_ENTRY_POINT,
-               /** MainSubtitle <EntryPoint> must be zero Bv2.1_8.3.2 */
+               /** MainSubtitle <EntryPoint> must be zero Bv2.1_8.3.2
+                *  note contains the asset ID
+                */
                INCORRECT_SUBTITLE_ENTRY_POINT,
-               /** Closed caption in reels must have <EntryPoint> Bv2.1_8.3.2 */
+               /** Closed caption in reels must have <EntryPoint> Bv2.1_8.3.2
+                *  note contains the asset ID
+                */
                MISSING_CLOSED_CAPTION_ENTRY_POINT,
-               /** Closed caption MainSubtitle <EntryPoint> must be zero Bv2.1_8.3.2 */
+               /** Closed caption MainSubtitle <EntryPoint> must be zero Bv2.1_8.3.2
+                *  note contains the asset ID
+                */
                INCORRECT_CLOSED_CAPTION_ENTRY_POINT,
-               /** <Hash> must be present for assets in CPLs */
+               /** <Hash> must be present for assets in CPLs.
+                * note contains the asset ID
+                */
                MISSING_HASH,
                /** If ContentKind is Feature there must be a FFEC marker */
                MISSING_FFEC_IN_FEATURE,
@@ -182,23 +260,48 @@ public:
                MISSING_FFOC,
                /** There should be a LFOC */
                MISSING_LFOC,
-               /** The FFOC should be 1 */
+               /** The FFOC should be 1.
+                *  note contains the incorrect value.
+                */
                INCORRECT_FFOC,
-               /** The LFOC should be the last frame in the reel */
+               /** The LFOC should be the last frame in the reel
+                *  note contains the incorrect value.
+                */
                INCORRECT_LFOC,
-               /** There must be a <CompositionMetadataAsset> */
+               /** There must be a <CompositionMetadataAsset>
+                *  note contains the CPL ID.
+                *  file contains the CPL filename.
+                */
                MISSING_CPL_METADATA,
-               /** CPL metadata should contain <VersionNumber> of 1, at least */
+               /** CPL metadata should contain <VersionNumber> of 1, at least
+                *  note contains the CPL ID.
+                *  file contains the CPL filename.
+                */
                MISSING_CPL_METADATA_VERSION_NUMBER,
-               /** There must be an <ExtensionMetadata> in <CompositionMetadataAsset> Bv2.1_8.6.3 */
+               /** There must be an <ExtensionMetadata> in <CompositionMetadataAsset> Bv2.1_8.6.3
+                *  note contains the CPL ID.
+                *  file contains the CPL filename.
+                */
                MISSING_EXTENSION_METADATA,
-               /** <ExtensionMetadata> must have a particular form Bv2.1_8.6.3 */
+               /** <ExtensionMetadata> must have a particular form Bv2.1_8.6.3
+                *  note contains details of what's wrong
+                *  file contains the CPL filename.
+                */
                INVALID_EXTENSION_METADATA,
-               /** CPLs containing encrypted content must be signed Bv2.1_8.7 */
+               /** CPLs containing encrypted content must be signed Bv2.1_8.7
+                *  note contains the CPL ID.
+                *  file contains the CPL filename.
+                */
                UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT,
-               /** PKLs containing encrypted content must be signed Bv2.1_8.7 */
+               /** PKLs containing encrypted content must be signed Bv2.1_8.7
+                *  note contains the PKL ID.
+                *  file contains the PKL filename.
+                */
                UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT,
-               /** If a PKL has one CPL its <ContentTitleText> must be the same as the PKL's <AnnotationText> */
+               /** If a PKL has one CPL its <ContentTitleText> must be the same as the PKL's <AnnotationText>.
+                *  note contains the PKL ID.
+                *  file contains the PKL filename.
+                */
                MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL,
                /** If any content is encrypted, everything must be encrypted */
                PARTIALLY_ENCRYPTED,
index 85b5aa2f42b1d441bc960d615f2a2151cf032f4b..5336ba158740a5cbc91b70923c410442ccc892a9 100644 (file)
@@ -51,6 +51,7 @@
 #include "reel_markers_asset.h"
 #include "compose.hpp"
 #include "test.h"
+#include "raw_convert.h"
 #include <boost/test/unit_test.hpp>
 #include <boost/foreach.hpp>
 #include <boost/algorithm/string.hpp>
@@ -70,7 +71,8 @@ using std::shared_ptr;
 
 static list<pair<string, optional<path>>> stages;
 static string const dcp_test1_pkl = "pkl_2b9b857f-ab4a-440e-a313-1ace0f1cfc95.xml";
-static string const dcp_test1_cpl = "cpl_81fb54df-e1bf-4647-8788-ea7ba154375b.xml";
+static string const dcp_test1_cpl_id = "81fb54df-e1bf-4647-8788-ea7ba154375b";
+static string const dcp_test1_cpl = "cpl_" + dcp_test1_cpl_id + ".xml";
 
 static void
 stage (string s, optional<path> p)
@@ -107,7 +109,7 @@ setup (int reference_number, int verify_test_number)
 
 
 static
-void
+shared_ptr<dcp::CPL>
 write_dcp_with_single_asset (path dir, shared_ptr<dcp::ReelAsset> reel_asset, dcp::Standard standard = dcp::SMPTE)
 {
        auto reel = make_shared<dcp::Reel>();
@@ -125,6 +127,8 @@ write_dcp_with_single_asset (path dir, shared_ptr<dcp::ReelAsset> reel_asset, dc
                dcp::LocalTime().as_string(),
                "hello"
                );
+
+       return cpl;
 }
 
 
@@ -197,7 +201,6 @@ void
 check_verify_result (vector<path> dir, vector<dcp::VerificationNote> test_notes)
 {
        auto notes = dcp::verify ({dir}, &stage, &progress, xsd_test);
-       dump_notes (notes);
        BOOST_REQUIRE_EQUAL (notes.size(), test_notes.size());
        for (auto i = 0U; i < notes.size(); ++i) {
                BOOST_REQUIRE_EQUAL (notes[i], test_notes[i]);
@@ -329,7 +332,7 @@ BOOST_AUTO_TEST_CASE (verify_test3)
        check_verify_result (
                directories,
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, dcp_test1_cpl_id, canonical(dir / dcp_test1_cpl) },
                        { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_PICTURE_HASHES, canonical(dir / "video.mxf") },
                        { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_SOUND_HASHES, canonical(dir / "audio.mxf") },
                        { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, "value 'xxz+gUPoPMdbFlAewvWIq8BRhBmA=' is invalid Base64-encoded binary", canonical(dir / dcp_test1_pkl), 12 },
@@ -548,7 +551,7 @@ BOOST_AUTO_TEST_CASE (verify_test14)
 
 
 static
-void
+shared_ptr<dcp::CPL>
 dcp_from_frame (dcp::ArrayData const& frame, path dir)
 {
        auto asset = make_shared<dcp::MonoPictureAsset>(dcp::Fraction(24, 1), dcp::SMPTE);
@@ -560,7 +563,7 @@ dcp_from_frame (dcp::ArrayData const& frame, path dir)
        writer->finalize ();
 
        auto reel_asset = make_shared<dcp::ReelMonoPictureAsset>(asset, 0);
-       write_dcp_with_single_asset (dir, reel_asset);
+       return write_dcp_with_single_asset (dir, reel_asset);
 }
 
 
@@ -581,13 +584,13 @@ BOOST_AUTO_TEST_CASE (verify_test15)
 
        path const dir("build/test/verify_test15");
        prepare_directory (dir);
-       dcp_from_frame (oversized_frame, dir);
+       auto cpl = dcp_from_frame (oversized_frame, dir);
 
        check_verify_result (
                { dir },
                {
                        { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_PICTURE_FRAME_SIZE_IN_BYTES, canonical(dir / "pic.mxf") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -609,13 +612,13 @@ BOOST_AUTO_TEST_CASE (verify_test16)
 
        path const dir("build/test/verify_test16");
        prepare_directory (dir);
-       dcp_from_frame (oversized_frame, dir);
+       auto cpl = dcp_from_frame (oversized_frame, dir);
 
        check_verify_result (
                { dir },
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::NEARLY_INVALID_PICTURE_FRAME_SIZE_IN_BYTES, canonical(dir / "pic.mxf") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -630,9 +633,9 @@ BOOST_AUTO_TEST_CASE (verify_test17)
 
        path const dir("build/test/verify_test17");
        prepare_directory (dir);
-       dcp_from_frame (frame, dir);
+       auto cpl = dcp_from_frame (frame, dir);
 
-       check_verify_result ({ dir }, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({ dir }, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
@@ -691,9 +694,9 @@ BOOST_AUTO_TEST_CASE (verify_test20)
        copy_file ("test/data/subs.mxf", dir / "subs.mxf");
        auto asset = make_shared<dcp::SMPTESubtitleAsset>(dir / "subs.mxf");
        auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
-       write_dcp_with_single_asset (dir, reel_asset);
+       auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
@@ -707,7 +710,7 @@ BOOST_AUTO_TEST_CASE (verify_test21)
        copy_file ("test/data/broken_smpte.mxf", dir / "subs.mxf");
        auto asset = make_shared<dcp::SMPTESubtitleAsset>(dir / "subs.mxf");
        auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
-       write_dcp_with_single_asset (dir, reel_asset);
+       auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result (
                { dir },
@@ -721,7 +724,7 @@ BOOST_AUTO_TEST_CASE (verify_test21)
                                2
                        },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -744,13 +747,13 @@ BOOST_AUTO_TEST_CASE (verify_test22)
        prepare_directory (vf_dir);
 
        auto picture = ov.cpls()[0]->reels()[0]->main_picture();
-       write_dcp_with_single_asset (vf_dir, picture);
+       auto cpl = write_dcp_with_single_asset (vf_dir, picture);
 
        check_verify_result (
                { vf_dir },
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::EXTERNAL_ASSET, picture->asset()->id() },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -787,7 +790,7 @@ BOOST_AUTO_TEST_CASE (verify_test23)
                "hello"
                );
 
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
@@ -856,7 +859,7 @@ BOOST_AUTO_TEST_CASE (verify_test24)
                                canonical(cpl->file().get()),
                                75
                        },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), canonical(cpl->file().get()) },
                });
 }
 
@@ -909,14 +912,14 @@ BOOST_AUTO_TEST_CASE (verify_test26)
        asset->write (dir / "subs.mxf");
        auto reel_asset = make_shared<dcp::ReelSubtitleAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
        reel_asset->_language = "badlang";
-       write_dcp_with_single_asset (dir, reel_asset);
+       auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result (
                { dir },
                {
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_LANGUAGE, string("badlang") },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_LANGUAGE, string("wrong-andbad") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -932,14 +935,14 @@ BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_languages)
        asset->write (dir / "subs.mxf");
        auto reel_asset = make_shared<dcp::ReelClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
        reel_asset->_language = "badlang";
-       write_dcp_with_single_asset (dir, reel_asset);
+       auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result (
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_LANGUAGE, string("badlang") },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_LANGUAGE, string("wrong-andbad") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1186,15 +1189,20 @@ BOOST_AUTO_TEST_CASE (verify_closed_caption_xml_too_large)
        asset->set_language (dcp::LanguageTag("de-DE"));
        asset->write (dir / "subs.mxf");
        auto reel_asset = make_shared<dcp::ReelClosedCaptionAsset>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
-       write_dcp_with_single_asset (dir, reel_asset);
+       auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result (
                { dir },
                {
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES, canonical(dir / "subs.mxf") },
+                       {
+                               dcp::VerificationNote::VERIFY_BV21_ERROR,
+                               dcp::VerificationNote::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES,
+                               string("413262"),
+                               canonical(dir / "subs.mxf")
+                       },
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_FIRST_TEXT_TIME },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -1225,16 +1233,16 @@ verify_timed_text_asset_too_large (string name)
        asset->write (dir / "subs.mxf");
 
        auto reel_asset = make_shared<T>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
-       write_dcp_with_single_asset (dir, reel_asset);
+       auto cpl = write_dcp_with_single_asset (dir, reel_asset);
 
        check_verify_result (
                { dir },
                {
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_TIMED_TEXT_SIZE_IN_BYTES, canonical(dir / "subs.mxf") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, canonical(dir / "subs.mxf") },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121696411"), canonical(dir / "subs.mxf") },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, string("121634816"), canonical(dir / "subs.mxf") },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_FIRST_TEXT_TIME },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -1466,7 +1474,7 @@ public:
 
 
 template <class T>
-void
+shared_ptr<dcp::CPL>
 dcp_with_text (path dir, vector<TestText> subs)
 {
        prepare_directory (dir);
@@ -1479,7 +1487,7 @@ dcp_with_text (path dir, vector<TestText> subs)
        asset->write (dir / "subs.mxf");
 
        auto reel_asset = make_shared<T>(asset, dcp::Fraction(24, 1), 16 * 24, 0);
-       write_dcp_with_single_asset (dir, reel_asset);
+       return write_dcp_with_single_asset (dir, reel_asset);
 }
 
 
@@ -1487,12 +1495,12 @@ BOOST_AUTO_TEST_CASE (verify_text_too_early)
 {
        auto const dir = path("build/test/verify_text_too_early");
        /* Just too early */
-       dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24 - 1, 5 * 24 }});
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24 - 1, 5 * 24 }});
        check_verify_result (
                { dir },
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_FIRST_TEXT_TIME },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 
 }
@@ -1502,8 +1510,8 @@ BOOST_AUTO_TEST_CASE (verify_text_not_too_early)
 {
        auto const dir = path("build/test/verify_text_not_too_early");
        /* Just late enough */
-       dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24, 5 * 24 }});
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24, 5 * 24 }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
@@ -1552,14 +1560,14 @@ BOOST_AUTO_TEST_CASE (verify_text_early_on_second_reel)
                );
 
 
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
 BOOST_AUTO_TEST_CASE (verify_text_too_close)
 {
        auto const dir = path("build/test/verify_text_too_close");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 4 * 24,     5 * 24 },
@@ -1569,7 +1577,7 @@ BOOST_AUTO_TEST_CASE (verify_text_too_close)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_SPACING },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1577,25 +1585,25 @@ BOOST_AUTO_TEST_CASE (verify_text_too_close)
 BOOST_AUTO_TEST_CASE (verify_text_not_too_close)
 {
        auto const dir = path("build/test/verify_text_not_too_close");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 4 * 24,      5 * 24 },
                        { 5 * 24 + 16, 8 * 24 },
                });
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
 BOOST_AUTO_TEST_CASE (verify_text_too_short)
 {
        auto const dir = path("build/test/verify_text_too_short");
-       dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24, 4 * 24 + 1 }});
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24, 4 * 24 + 1 }});
        check_verify_result (
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_DURATION },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1603,15 +1611,15 @@ BOOST_AUTO_TEST_CASE (verify_text_too_short)
 BOOST_AUTO_TEST_CASE (verify_text_not_too_short)
 {
        auto const dir = path("build/test/verify_text_not_too_short");
-       dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24, 4 * 24 + 17 }});
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (dir, {{ 4 * 24, 4 * 24 + 17 }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
 BOOST_AUTO_TEST_CASE (verify_too_many_subtitle_lines1)
 {
        auto const dir = path ("build/test/verify_too_many_subtitle_lines1");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 96, 200, 0.0, "We" },
@@ -1623,7 +1631,7 @@ BOOST_AUTO_TEST_CASE (verify_too_many_subtitle_lines1)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_LINE_COUNT },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1631,21 +1639,21 @@ BOOST_AUTO_TEST_CASE (verify_too_many_subtitle_lines1)
 BOOST_AUTO_TEST_CASE (verify_not_too_many_subtitle_lines1)
 {
        auto const dir = path ("build/test/verify_not_too_many_subtitle_lines1");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 96, 200, 0.0, "We" },
                        { 96, 200, 0.1, "have" },
                        { 96, 200, 0.2, "four" },
                });
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
 BOOST_AUTO_TEST_CASE (verify_too_many_subtitle_lines2)
 {
        auto const dir = path ("build/test/verify_too_many_subtitle_lines2");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 96, 300, 0.0, "We" },
@@ -1657,7 +1665,7 @@ BOOST_AUTO_TEST_CASE (verify_too_many_subtitle_lines2)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_LINE_COUNT },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1665,7 +1673,7 @@ BOOST_AUTO_TEST_CASE (verify_too_many_subtitle_lines2)
 BOOST_AUTO_TEST_CASE (verify_not_too_many_subtitle_lines2)
 {
        auto const dir = path ("build/test/verify_not_too_many_subtitle_lines2");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 96, 300, 0.0, "We" },
@@ -1673,14 +1681,14 @@ BOOST_AUTO_TEST_CASE (verify_not_too_many_subtitle_lines2)
                        { 150, 180, 0.2, "four" },
                        { 190, 250, 0.3, "lines" }
                });
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
 BOOST_AUTO_TEST_CASE (verify_subtitle_lines_too_long1)
 {
        auto const dir = path ("build/test/verify_subtitle_lines_too_long1");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 96, 300, 0.0, "012345678901234567890123456789012345678901234567890123" }
@@ -1689,7 +1697,7 @@ BOOST_AUTO_TEST_CASE (verify_subtitle_lines_too_long1)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::NEARLY_INVALID_SUBTITLE_LINE_LENGTH },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1697,7 +1705,7 @@ BOOST_AUTO_TEST_CASE (verify_subtitle_lines_too_long1)
 BOOST_AUTO_TEST_CASE (verify_subtitle_lines_too_long2)
 {
        auto const dir = path ("build/test/verify_subtitle_lines_too_long2");
-       dcp_with_text<dcp::ReelSubtitleAsset> (
+       auto cpl = dcp_with_text<dcp::ReelSubtitleAsset> (
                dir,
                {
                        { 96, 300, 0.0, "012345678901234567890123456789012345678901234567890123456789012345678901234567890" }
@@ -1706,7 +1714,7 @@ BOOST_AUTO_TEST_CASE (verify_subtitle_lines_too_long2)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INVALID_SUBTITLE_LINE_LENGTH },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1714,7 +1722,7 @@ BOOST_AUTO_TEST_CASE (verify_subtitle_lines_too_long2)
 BOOST_AUTO_TEST_CASE (verify_too_many_closed_caption_lines1)
 {
        auto const dir = path ("build/test/verify_too_many_closed_caption_lines1");
-       dcp_with_text<dcp::ReelClosedCaptionAsset> (
+       auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
                dir,
                {
                        { 96, 200, 0.0, "We" },
@@ -1726,7 +1734,7 @@ BOOST_AUTO_TEST_CASE (verify_too_many_closed_caption_lines1)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_CLOSED_CAPTION_LINE_COUNT},
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1734,21 +1742,21 @@ BOOST_AUTO_TEST_CASE (verify_too_many_closed_caption_lines1)
 BOOST_AUTO_TEST_CASE (verify_not_too_many_closed_caption_lines1)
 {
        auto const dir = path ("build/test/verify_not_too_many_closed_caption_lines1");
-       dcp_with_text<dcp::ReelClosedCaptionAsset> (
+       auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
                dir,
                {
                        { 96, 200, 0.0, "We" },
                        { 96, 200, 0.1, "have" },
                        { 96, 200, 0.2, "four" },
                });
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
 BOOST_AUTO_TEST_CASE (verify_too_many_closed_caption_lines2)
 {
        auto const dir = path ("build/test/verify_too_many_closed_caption_lines2");
-       dcp_with_text<dcp::ReelClosedCaptionAsset> (
+       auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
                dir,
                {
                        { 96, 300, 0.0, "We" },
@@ -1760,7 +1768,7 @@ BOOST_AUTO_TEST_CASE (verify_too_many_closed_caption_lines2)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_CLOSED_CAPTION_LINE_COUNT},
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1768,7 +1776,7 @@ BOOST_AUTO_TEST_CASE (verify_too_many_closed_caption_lines2)
 BOOST_AUTO_TEST_CASE (verify_not_too_many_closed_caption_lines2)
 {
        auto const dir = path ("build/test/verify_not_too_many_closed_caption_lines2");
-       dcp_with_text<dcp::ReelClosedCaptionAsset> (
+       auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
                dir,
                {
                        { 96, 300, 0.0, "We" },
@@ -1776,14 +1784,14 @@ BOOST_AUTO_TEST_CASE (verify_not_too_many_closed_caption_lines2)
                        { 150, 180, 0.2, "four" },
                        { 190, 250, 0.3, "lines" }
                });
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
 }
 
 
 BOOST_AUTO_TEST_CASE (verify_closed_caption_lines_too_long1)
 {
        auto const dir = path ("build/test/verify_closed_caption_lines_too_long1");
-       dcp_with_text<dcp::ReelClosedCaptionAsset> (
+       auto cpl = dcp_with_text<dcp::ReelClosedCaptionAsset> (
                dir,
                {
                        { 96, 300, 0.0, "0123456789012345678901234567890123" }
@@ -1792,7 +1800,7 @@ BOOST_AUTO_TEST_CASE (verify_closed_caption_lines_too_long1)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_CLOSED_CAPTION_LINE_LENGTH },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -1825,8 +1833,8 @@ BOOST_AUTO_TEST_CASE (verify_sound_sampling_rate_must_be_48k)
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_SOUND_FRAME_RATE, canonical(dir / "audiofoo.mxf") },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_SOUND_FRAME_RATE, string("96000"), canonical(dir / "audiofoo.mxf") },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -1845,17 +1853,19 @@ BOOST_AUTO_TEST_CASE (verify_cpl_must_have_annotation_text)
 
        BOOST_REQUIRE_EQUAL (dcp->cpls().size(), 1U);
 
+       auto const cpl = dcp->cpls()[0];
+
        {
-               BOOST_REQUIRE (dcp->cpls()[0]->file());
-               Editor e(dcp->cpls()[0]->file().get());
+               BOOST_REQUIRE (cpl->file());
+               Editor e(cpl->file().get());
                e.replace("<AnnotationText>A Test DCP</AnnotationText>", "");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_ANNOTATION_TEXT },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_ANNOTATION_TEXT, cpl->id(), canonical(cpl->file().get()) },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), canonical(cpl->file().get()) }
                });
 }
 
@@ -1873,18 +1883,19 @@ BOOST_AUTO_TEST_CASE (verify_cpl_annotation_text_should_be_same_as_content_title
                );
 
        BOOST_REQUIRE_EQUAL (dcp->cpls().size(), 1U);
+       auto const cpl = dcp->cpls()[0];
 
        {
-               BOOST_REQUIRE (dcp->cpls()[0]->file());
-               Editor e(dcp->cpls()[0]->file().get());
+               BOOST_REQUIRE (cpl->file());
+               Editor e(cpl->file().get());
                e.replace("<AnnotationText>A Test DCP</AnnotationText>", "<AnnotationText>A Test DCP 1</AnnotationText>");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::MISMATCHED_CPL_ANNOTATION_TEXT },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES }
+                       { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::MISMATCHED_CPL_ANNOTATION_TEXT, cpl->id(), canonical(cpl->file().get()) },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), canonical(cpl->file().get()) }
                });
 }
 
@@ -1920,14 +1931,14 @@ BOOST_AUTO_TEST_CASE (verify_reel_assets_durations_must_match)
                {dir},
                {
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISMATCHED_ASSET_DURATION },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), canonical(cpl->file().get()) }
                });
 }
 
 
 
 static
-void
+shared_ptr<dcp::CPL>
 verify_subtitles_must_be_in_all_reels_check (path dir, bool add_to_reel1, bool add_to_reel2)
 {
        prepare_directory (dir);
@@ -1979,6 +1990,8 @@ verify_subtitles_must_be_in_all_reels_check (path dir, bool add_to_reel1, bool a
                dcp::LocalTime().as_string(),
                "A Test DCP"
                );
+
+       return cpl;
 }
 
 
@@ -1986,32 +1999,32 @@ BOOST_AUTO_TEST_CASE (verify_subtitles_must_be_in_all_reels)
 {
        {
                path dir ("build/test/verify_subtitles_must_be_in_all_reels1");
-               verify_subtitles_must_be_in_all_reels_check (dir, true, false);
+               auto cpl = verify_subtitles_must_be_in_all_reels_check (dir, true, false);
                check_verify_result (
                        { dir },
                        {
                                { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_MAIN_SUBTITLE_FROM_SOME_REELS },
-                               { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                               { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                        });
 
        }
 
        {
                path dir ("build/test/verify_subtitles_must_be_in_all_reels2");
-               verify_subtitles_must_be_in_all_reels_check (dir, true, true);
-               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+               auto cpl = verify_subtitles_must_be_in_all_reels_check (dir, true, true);
+               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
        }
 
        {
                path dir ("build/test/verify_subtitles_must_be_in_all_reels1");
-               verify_subtitles_must_be_in_all_reels_check (dir, false, false);
-               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+               auto cpl = verify_subtitles_must_be_in_all_reels_check (dir, false, false);
+               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
        }
 }
 
 
 static
-void
+shared_ptr<dcp::CPL>
 verify_closed_captions_must_be_in_all_reels_check (path dir, int caps_in_reel1, int caps_in_reel2)
 {
        prepare_directory (dir);
@@ -2062,6 +2075,8 @@ verify_closed_captions_must_be_in_all_reels_check (path dir, int caps_in_reel1,
                dcp::LocalTime().as_string(),
                "A Test DCP"
                );
+
+       return cpl;
 }
 
 
@@ -2069,25 +2084,25 @@ BOOST_AUTO_TEST_CASE (verify_closed_captions_must_be_in_all_reels)
 {
        {
                path dir ("build/test/verify_closed_captions_must_be_in_all_reels1");
-               verify_closed_captions_must_be_in_all_reels_check (dir, 3, 4);
+               auto cpl = verify_closed_captions_must_be_in_all_reels_check (dir, 3, 4);
                check_verify_result (
                        {dir},
                        {
                                { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISMATCHED_CLOSED_CAPTION_ASSET_COUNTS },
-                               { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                               { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                        });
        }
 
        {
                path dir ("build/test/verify_closed_captions_must_be_in_all_reels2");
-               verify_closed_captions_must_be_in_all_reels_check (dir, 4, 4);
-               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+               auto cpl = verify_closed_captions_must_be_in_all_reels_check (dir, 4, 4);
+               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
        }
 
        {
                path dir ("build/test/verify_closed_captions_must_be_in_all_reels3");
-               verify_closed_captions_must_be_in_all_reels_check (dir, 0, 0);
-               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }});
+               auto cpl = verify_closed_captions_must_be_in_all_reels_check (dir, 0, 0);
+               check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }});
        }
 }
 
@@ -2131,8 +2146,8 @@ verify_text_entry_point_check (path dir, dcp::VerificationNote::Code code, boost
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, code },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, code, subs->id() },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -2188,17 +2203,18 @@ BOOST_AUTO_TEST_CASE (verify_assets_must_have_hashes)
                );
 
        BOOST_REQUIRE_EQUAL (dcp->cpls().size(), 1U);
+       auto const cpl = dcp->cpls()[0];
 
        {
-               BOOST_REQUIRE (dcp->cpls()[0]->file());
-               Editor e(dcp->cpls()[0]->file().get());
+               BOOST_REQUIRE (cpl->file());
+               Editor e(cpl->file().get());
                e.replace("<Hash>XGhFVrqZqapOJx5Fh2SLjj48Yjg=</Hash>", "");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_HASH, string("1fab8bb0-cfaf-4225-ad6d-01768bc10470") }
                });
 }
@@ -2297,7 +2313,7 @@ BOOST_AUTO_TEST_CASE (verify_markers)
                        { dcp::Marker::LFOC, dcp::Time(23, 24, 24) }
                },
                {
-                       { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INCORRECT_FFOC }
+                       { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INCORRECT_FFOC, string("3") }
                });
 
        verify_markers_test (
@@ -2309,7 +2325,7 @@ BOOST_AUTO_TEST_CASE (verify_markers)
                        { dcp::Marker::LFOC, dcp::Time(18, 24, 24) }
                },
                {
-                       { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INCORRECT_LFOC }
+                       { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::INCORRECT_LFOC, string("18") }
                });
 }
 
@@ -2319,7 +2335,8 @@ BOOST_AUTO_TEST_CASE (verify_cpl_metadata_version)
        path dir = "build/test/verify_cpl_metadata_version";
        prepare_directory (dir);
        auto dcp = make_simple (dir);
-       dcp->cpls()[0]->unset_version_number();
+       auto cpl = dcp->cpls()[0];
+       cpl->unset_version_number();
        dcp->write_xml (
                dcp::SMPTE,
                dcp::String::compose("libdcp %1", dcp::version),
@@ -2328,7 +2345,7 @@ BOOST_AUTO_TEST_CASE (verify_cpl_metadata_version)
                "A Test DCP"
                );
 
-       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA_VERSION_NUMBER }});
+       check_verify_result ({dir}, {{ dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA_VERSION_NUMBER, cpl->id(), cpl->file().get() }});
 }
 
 
@@ -2344,16 +2361,18 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata1)
                "A Test DCP"
                );
 
+       auto cpl = dcp->cpls()[0];
+
        {
-               Editor e (dcp->cpls()[0]->file().get());
+               Editor e (cpl->file().get());
                e.delete_lines ("<meta:ExtensionMetadataList>", "</meta:ExtensionMetadataList>");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_EXTENSION_METADATA }
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_EXTENSION_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -2370,16 +2389,18 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata2)
                "A Test DCP"
                );
 
+       auto cpl = dcp->cpls()[0];
+
        {
-               Editor e (dcp->cpls()[0]->file().get());
+               Editor e (cpl->file().get());
                e.delete_lines ("<meta:ExtensionMetadata scope=\"http://isdcf.com/ns/cplmd/app\">", "</meta:ExtensionMetadata>");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_EXTENSION_METADATA }
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_EXTENSION_METADATA, cpl->id(), cpl->file().get() }
                });
 }
 
@@ -2396,10 +2417,10 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata3)
                "A Test DCP"
                );
 
-       path const cpl = dcp->cpls()[0]->file().get();
+       auto const cpl = dcp->cpls()[0];
 
        {
-               Editor e (cpl);
+               Editor e (cpl->file().get());
                e.replace ("<meta:Name>A", "<meta:NameX>A");
                e.replace ("n</meta:Name>", "n</meta:NameX>");
        }
@@ -2407,9 +2428,9 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata3)
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:NameX'"), cpl, 75 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:NameX' is not allowed for content model '(Name,PropertyList?,)'"), cpl, 82 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:NameX'"), cpl->file().get(), 75 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:NameX' is not allowed for content model '(Name,PropertyList?,)'"), cpl->file().get(), 82 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -2426,16 +2447,18 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata4)
                "A Test DCP"
                );
 
+       auto cpl = dcp->cpls()[0];
+
        {
-               Editor e (dcp->cpls()[0]->file().get());
+               Editor e (cpl->file().get());
                e.replace ("Application", "Fred");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_EXTENSION_METADATA, string("<Name> should be 'Application'") },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_EXTENSION_METADATA, string("<Name> should be 'Application'"), cpl->file().get() },
                });
 }
 
@@ -2451,16 +2474,19 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata5)
                dcp::LocalTime().as_string(),
                "A Test DCP"
                );
+
+       auto cpl = dcp->cpls()[0];
+
        {
-               Editor e (dcp->cpls()[0]->file().get());
+               Editor e (cpl->file().get());
                e.replace ("DCP Constraints Profile", "Fred");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_EXTENSION_METADATA, string("<Name> property should be 'DCP Constraints Profile'") },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_EXTENSION_METADATA, string("<Name> property should be 'DCP Constraints Profile'"), cpl->file().get() },
                });
 }
 
@@ -2477,10 +2503,10 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata6)
                "A Test DCP"
                );
 
-       path const cpl = dcp->cpls()[0]->file().get();
+       auto const cpl = dcp->cpls()[0];
 
        {
-               Editor e (cpl);
+               Editor e (cpl->file().get());
                e.replace ("<meta:Value>", "<meta:ValueX>");
                e.replace ("</meta:Value>", "</meta:ValueX>");
        }
@@ -2488,9 +2514,9 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata6)
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:ValueX'"), cpl, 79 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:ValueX' is not allowed for content model '(Name,Value)'"), cpl, 80 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:ValueX'"), cpl->file().get(), 79 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:ValueX' is not allowed for content model '(Name,Value)'"), cpl->file().get(), 80 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -2506,16 +2532,19 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata7)
                dcp::LocalTime().as_string(),
                "A Test DCP"
                );
+
+       auto const cpl = dcp->cpls()[0];
+
        {
-               Editor e (dcp->cpls()[0]->file().get());
+               Editor e (cpl->file().get());
                e.replace ("SMPTE-RDD-52:2020-Bv2.1", "Fred");
        }
 
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_EXTENSION_METADATA, string("<Value> property should be 'SMPTE-RDD-52:2020-Bv2.1'") },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::INVALID_EXTENSION_METADATA, string("<Value> property should be 'SMPTE-RDD-52:2020-Bv2.1'"), cpl->file().get() },
                });
 }
 
@@ -2532,10 +2561,10 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata8)
                "A Test DCP"
                );
 
-       path const cpl = dcp->cpls()[0]->file().get();
+       auto const cpl = dcp->cpls()[0];
 
        {
-               Editor e (cpl);
+               Editor e (cpl->file().get());
                e.replace ("<meta:Property>", "<meta:PropertyX>");
                e.replace ("</meta:Property>", "</meta:PropertyX>");
        }
@@ -2543,9 +2572,9 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata8)
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:PropertyX'"), cpl, 77 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:PropertyX' is not allowed for content model '(Property+)'"), cpl, 81 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:PropertyX'"), cpl->file().get(), 77 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:PropertyX' is not allowed for content model '(Property+)'"), cpl->file().get(), 81 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -2562,10 +2591,10 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata9)
                "A Test DCP"
                );
 
-       path const cpl = dcp->cpls()[0]->file().get();
+       auto const cpl = dcp->cpls()[0];
 
        {
-               Editor e (cpl);
+               Editor e (cpl->file().get());
                e.replace ("<meta:PropertyList>", "<meta:PropertyListX>");
                e.replace ("</meta:PropertyList>", "</meta:PropertyListX>");
        }
@@ -2573,9 +2602,9 @@ BOOST_AUTO_TEST_CASE (verify_cpl_extension_metadata9)
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:PropertyListX'"), cpl, 76 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:PropertyListX' is not allowed for content model '(Name,PropertyList?,)'"), cpl, 82 },
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("no declaration found for element 'meta:PropertyListX'"), cpl->file().get(), 76 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::INVALID_XML, string("element 'meta:PropertyListX' is not allowed for content model '(Name,PropertyList?,)'"), cpl->file().get(), 82 },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl->id(), cpl->file().get() },
                });
 }
 
@@ -2589,8 +2618,10 @@ BOOST_AUTO_TEST_CASE (verify_encrypted_cpl_is_signed)
                copy_file (i.path(), dir / i.path().filename());
        }
 
-       path const pkl = dir / "pkl_93182bd2-b1e8-41a3-b5c8-6e6564273bff.xml";
-       path const cpl = dir / "cpl_81fb54df-e1bf-4647-8788-ea7ba154375b.xml";
+       string const pkl_id = "93182bd2-b1e8-41a3-b5c8-6e6564273bff";
+       path const pkl = dir / ( "pkl_" + pkl_id + ".xml" );
+       string const cpl_id = "81fb54df-e1bf-4647-8788-ea7ba154375b";
+       path const cpl = dir / ( "cpl_" + cpl_id + ".xml");
 
        {
                Editor e (cpl);
@@ -2600,14 +2631,14 @@ BOOST_AUTO_TEST_CASE (verify_encrypted_cpl_is_signed)
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, canonical(pkl), },
+                       { dcp::VerificationNote::VERIFY_ERROR, dcp::VerificationNote::MISMATCHED_CPL_HASHES, cpl_id, canonical(cpl) },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, pkl_id, canonical(pkl), },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFEC_IN_FEATURE },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFMC_IN_FEATURE },
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::MISSING_FFOC },
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::MISSING_LFOC },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, canonical(cpl) }
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl_id, canonical(cpl) },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::UNSIGNED_CPL_WITH_ENCRYPTED_CONTENT, cpl_id, canonical(cpl) }
                });
 }
 
@@ -2620,7 +2651,10 @@ BOOST_AUTO_TEST_CASE (verify_encrypted_pkl_is_signed)
                copy_file (i.path(), dir / i.path().filename());
        }
 
-       path const pkl = dir / "pkl_93182bd2-b1e8-41a3-b5c8-6e6564273bff.xml";
+       string const cpl_id = "81fb54df-e1bf-4647-8788-ea7ba154375b";
+       path const cpl = dir / ("cpl_" + cpl_id + ".xml");
+       string const pkl_id = "93182bd2-b1e8-41a3-b5c8-6e6564273bff";
+       path const pkl = dir / ("pkl_" + pkl_id + ".xml");
        {
                Editor e (pkl);
                e.delete_lines ("<dsig:Signature", "</dsig:Signature>");
@@ -2629,13 +2663,13 @@ BOOST_AUTO_TEST_CASE (verify_encrypted_pkl_is_signed)
        check_verify_result (
                {dir},
                {
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, canonical(pkl) },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISMATCHED_PKL_ANNOTATION_TEXT_WITH_CPL, pkl_id, canonical(pkl) },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFEC_IN_FEATURE },
                        { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_FFMC_IN_FEATURE },
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::MISSING_FFOC },
                        { dcp::VerificationNote::VERIFY_WARNING, dcp::VerificationNote::MISSING_LFOC },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA },
-                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, canonical(pkl) },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::MISSING_CPL_METADATA, cpl_id, canonical(cpl) },
+                       { dcp::VerificationNote::VERIFY_BV21_ERROR, dcp::VerificationNote::UNSIGNED_PKL_WITH_ENCRYPTED_CONTENT, pkl_id, canonical(pkl) },
                });
 }