Add check for mismatched sound channel counts.
authorCarl Hetherington <cth@carlh.net>
Sun, 2 Apr 2023 21:10:39 +0000 (23:10 +0200)
committerCarl Hetherington <cth@carlh.net>
Tue, 4 Apr 2023 21:37:44 +0000 (23:37 +0200)
src/verify.cc
src/verify.h
test/verify_test.cc

index 7cc6d3572b69fcc5897e6cf4a7262586f404fd29..1cab0423bfda14d9614107e301224179e31fa38d 100644 (file)
@@ -572,6 +572,13 @@ verify_main_picture_asset (
 }
 
 
+struct State
+{
+       boost::optional<string> subtitle_language;
+       boost::optional<int> audio_channels;
+};
+
+
 static void
 verify_main_sound_asset (
        shared_ptr<const DCP> dcp,
@@ -579,7 +586,8 @@ verify_main_sound_asset (
        function<void (string, optional<boost::filesystem::path>)> stage,
        function<void (float)> progress,
        VerificationOptions options,
-       vector<VerificationNote>& notes
+       vector<VerificationNote>& notes,
+       State& state
        )
 {
        auto asset = reel_asset->asset();
@@ -600,6 +608,12 @@ verify_main_sound_asset (
                }
        }
 
+       if (!state.audio_channels) {
+               state.audio_channels = asset->channels();
+       } else if (*state.audio_channels != asset->channels()) {
+               notes.push_back({ VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS, file });
+       }
+
        stage ("Checking sound asset metadata", file);
 
        if (auto lang = asset->language()) {
@@ -643,12 +657,6 @@ verify_closed_caption_reel (shared_ptr<const ReelClosedCaptionAsset> reel_asset,
 }
 
 
-struct State
-{
-       boost::optional<string> subtitle_language;
-};
-
-
 /** Verify stuff that is common to both subtitles and closed captions */
 void
 verify_smpte_timed_text_asset (
@@ -1385,7 +1393,7 @@ verify_reel(
        }
 
        if (reel->main_sound() && reel->main_sound()->asset_ref().resolved()) {
-               verify_main_sound_asset(dcp, reel->main_sound(), stage, progress, options, notes);
+               verify_main_sound_asset(dcp, reel->main_sound(), stage, progress, options, notes, state);
        }
 
        if (reel->main_subtitle()) {
@@ -1986,6 +1994,8 @@ dcp::note_to_string (VerificationNote note)
                return String::compose("The subtitle asset %1 has no subtitles", note.note().get());
        case VerificationNote::Code::INVALID_SUBTITLE_ISSUE_DATE:
                return String::compose("<IssueDate> has an invalid value: %1", note.note().get());
+       case VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS:
+               return String::compose("The sound assets do not all have the same channel count; the first to differ is %1", note.file()->filename());
        }
 
        return "";
index 77fc28b39d671e78dd1586ddf5c5703c0bb307ff..d05c92ebc8b713596c7cd895b6509ef05205907e 100644 (file)
@@ -421,7 +421,11 @@ public:
                 *  specifications require it and their QC will fail DCPs that don't have it.
                 *  note contains the incorrect <IssueDate>
                 */
-               INVALID_SUBTITLE_ISSUE_DATE
+               INVALID_SUBTITLE_ISSUE_DATE,
+               /** The sound assets in the CPL do not have the same audio channel count.
+                *  file contains the filename of the first asset to differ
+                */
+               MISMATCHED_SOUND_CHANNEL_COUNTS
        };
 
        VerificationNote (Type type, Code code)
index d853bc810d896462d61c2b82fd0e8336eb55bfc7..a0786d9c9377f5a2001e5c49d82b570b442727a0 100644 (file)
@@ -3445,3 +3445,74 @@ BOOST_AUTO_TEST_CASE(verify_duplicate_assetmap_asset_ids)
                });
 }
 
+
+BOOST_AUTO_TEST_CASE(verify_mismatched_sound_channel_counts)
+{
+       boost::filesystem::path const path = "build/test/verify_mismatched_sound_channel_counts";
+
+       dcp::MXFMetadata mxf_meta;
+       mxf_meta.company_name = "OpenDCP";
+       mxf_meta.product_name = "OpenDCP";
+       mxf_meta.product_version = "0.0.25";
+
+       auto constexpr sample_rate = 48000;
+       auto constexpr frames = 240;
+
+       boost::filesystem::remove_all(path);
+       boost::filesystem::create_directories(path);
+       auto dcp = make_shared<dcp::DCP>(path);
+       auto cpl = make_shared<dcp::CPL>("hello", dcp::ContentKind::TRAILER, dcp::Standard::SMPTE);
+       cpl->set_annotation_text("hello");
+       cpl->set_main_sound_configuration(dcp::MainSoundConfiguration("51/L,R"));
+       cpl->set_main_sound_sample_rate(sample_rate);
+       cpl->set_main_picture_stored_area(dcp::Size(1998, 1080));
+       cpl->set_main_picture_active_area(dcp::Size(1998, 1080));
+       cpl->set_version_number(1);
+
+       {
+
+               /* Reel with 2 channels of audio */
+
+               auto mp = simple_picture(path, "1", frames, {});
+               auto ms = simple_sound(path, "1", mxf_meta, "en-US", frames, sample_rate, {}, 2);
+
+               auto reel = make_shared<dcp::Reel>(
+                       std::make_shared<dcp::ReelMonoPictureAsset>(mp, 0),
+                       std::make_shared<dcp::ReelSoundAsset>(ms, 0)
+                       );
+
+               auto markers = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), frames);
+               markers->set(dcp::Marker::FFOC, dcp::Time(0, 0, 0, 1, 24));
+               reel->add(markers);
+
+               cpl->add(reel);
+       }
+
+       {
+               /* Reel with 6 channels of audio */
+
+               auto mp = simple_picture(path, "2", frames, {});
+               auto ms = simple_sound(path, "2", mxf_meta, "en-US", frames, sample_rate, {}, 6);
+
+               auto reel = make_shared<dcp::Reel>(
+                       std::make_shared<dcp::ReelMonoPictureAsset>(mp, 0),
+                       std::make_shared<dcp::ReelSoundAsset>(ms, 0)
+                       );
+
+               auto markers = make_shared<dcp::ReelMarkersAsset>(dcp::Fraction(24, 1), frames);
+               markers->set(dcp::Marker::LFOC, dcp::Time(0, 0, 0, frames - 1, 24));
+               reel->add(markers);
+
+               cpl->add(reel);
+       }
+
+       dcp->add(cpl);
+       dcp->set_annotation_text("hello");
+       dcp->write_xml();
+
+       check_verify_result(
+               { path },
+               {
+                       { dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::MISMATCHED_SOUND_CHANNEL_COUNTS, canonical(find_file(path, "audio2")) },
+               });
+}