summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2024-05-24 22:58:32 +0200
committerCarl Hetherington <cth@carlh.net>2024-05-24 23:41:56 +0200
commitcc6a2fe7ee05718d549e72eb740d0eae290f8ecb (patch)
treec760229e4f187b914ec37593258172668b32b94f
parenta4930f8185f2d3f3a9dc93b938792fae758be4d7 (diff)
Check that DCPs have 24-bit audio.
-rw-r--r--src/sound_asset.cc1
-rw-r--r--src/sound_asset.h8
-rw-r--r--src/verify.cc5
-rw-r--r--src/verify.h5
-rw-r--r--test/verify_test.cc46
5 files changed, 65 insertions, 0 deletions
diff --git a/src/sound_asset.cc b/src/sound_asset.cc
index 90075278..c73255b8 100644
--- a/src/sound_asset.cc
+++ b/src/sound_asset.cc
@@ -83,6 +83,7 @@ SoundAsset::SoundAsset (boost::filesystem::path file)
}
_sampling_rate = desc.AudioSamplingRate.Denominator ? (desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator) : 0;
+ _bit_depth = desc.QuantizationBits;
_channels = desc.ChannelCount;
_edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator);
diff --git a/src/sound_asset.h b/src/sound_asset.h
index e69c3988..e5acb119 100644
--- a/src/sound_asset.h
+++ b/src/sound_asset.h
@@ -115,6 +115,13 @@ public:
return _sampling_rate;
}
+ /** @return Bit depth of samples. This should always be 24, but we return it
+ * so the verification code can check
+ */
+ int bit_depth() const {
+ return _bit_depth;
+ }
+
Fraction edit_rate () const {
return _edit_rate;
}
@@ -148,6 +155,7 @@ private:
int _channels = 0; ///< number of channels in the MXF
boost::optional<int> _active_channels; ///< estimate of the number of active channels
int _sampling_rate = 0; ///< sampling rate in Hz
+ int _bit_depth = 24;
boost::optional<std::string> _language;
};
diff --git a/src/verify.cc b/src/verify.cc
index 56e6b5b8..1f0d7790 100644
--- a/src/verify.cc
+++ b/src/verify.cc
@@ -714,6 +714,9 @@ verify_main_sound_asset(Context& context, shared_ptr<const ReelSoundAsset> reel_
if (asset->sampling_rate() != 48000) {
context.bv21_error(VerificationNote::Code::INVALID_SOUND_FRAME_RATE, raw_convert<string>(asset->sampling_rate()), file);
}
+ if (asset->bit_depth() != 24) {
+ context.error(VerificationNote::Code::INVALID_SOUND_BIT_DEPTH, raw_convert<string>(asset->bit_depth()), file);
+ }
}
@@ -2054,6 +2057,8 @@ dcp::note_to_string(VerificationNote note, function<string (string)> process_str
return process_string("There are more than 32 characters in at least one closed caption line.");
case VerificationNote::Code::INVALID_SOUND_FRAME_RATE:
return compose("The sound asset %1 has a sampling rate of %2", filename(), note.note().get());
+ case VerificationNote::Code::INVALID_SOUND_BIT_DEPTH:
+ return compose("The sound asset %1 has a bit depth of %2", filename(), note.note().get());
case VerificationNote::Code::MISSING_CPL_ANNOTATION_TEXT:
return compose("The CPL %1 has no <AnnotationText> tag.", note.cpl_id().get());
case VerificationNote::Code::MISMATCHED_CPL_ANNOTATION_TEXT:
diff --git a/src/verify.h b/src/verify.h
index b9e3623f..d8681b73 100644
--- a/src/verify.h
+++ b/src/verify.h
@@ -255,6 +255,11 @@ public:
* file contains the asset filename
*/
INVALID_SOUND_FRAME_RATE,
+ /** The audio bit depth must be 24
+ * note contains the invalid bit depth
+ * file contains the asset filename
+ */
+ INVALID_SOUND_BIT_DEPTH,
/** The CPL has no _<AnnotationText>_ tag [Bv2.1_8.1]
* note contains the CPL ID
* file contains the CPL filename
diff --git a/test/verify_test.cc b/test/verify_test.cc
index 80d0490e..a465bac4 100644
--- a/test/verify_test.cc
+++ b/test/verify_test.cc
@@ -5773,3 +5773,49 @@ BOOST_AUTO_TEST_CASE(verify_encrypted_smpte_dcp)
}
+BOOST_AUTO_TEST_CASE(verify_invalid_sound_bit_depth)
+{
+ auto const dir = private_test / "data" / "16_bit_audio";
+
+ auto cpl = make_shared<dcp::CPL>(find_prefix(dir, "CPL_"));
+
+ vector<dcp::VerificationNote> notes = {
+ ok(dcp::VerificationNote::Code::MATCHING_PKL_ANNOTATION_TEXT_WITH_CPL, cpl),
+ ok(dcp::VerificationNote::Code::MATCHING_CPL_HASHES, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_KIND, string{"Advertisement"}, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CONTENT_VERSION_LABEL_TEXT, cpl->content_version()->label_text, cpl),
+ ok(dcp::VerificationNote::Code::VALID_CPL_ANNOTATION_TEXT, string{"204794_Kitex_Scoobee_Day_Bags_30_Sec_Malayalam_220524_RADQR"}, cpl),
+ ok(dcp::VerificationNote::Code::NONE_ENCRYPTED, cpl),
+ ok(dcp::VerificationNote::Code::CORRECT_PICTURE_HASH, canonical(dir / "Video.mxf"), cpl),
+ ok(dcp::VerificationNote::Code::VALID_PICTURE_FRAME_SIZES_IN_BYTES, canonical(dir / "Video.mxf"), cpl),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::ERROR, dcp::VerificationNote::Code::INVALID_SOUND_BIT_DEPTH, "16", canonical(dir / "Audio.mxf")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_HASH, string("fd4796c2-9c84-454c-91f4-13ad127cea8a")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_HASH, string("9d5e8bc4-676b-4306-a86d-03f70c73b457")
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_CPL_METADATA, canonical(cpl->file().get())
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_FFOC
+ ).set_cpl_id(cpl->id()),
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::MISSING_LFOC
+ ).set_cpl_id(cpl->id()),
+ };
+
+ for (auto i = 0; i < 792; ++i) {
+ notes.push_back(
+ dcp::VerificationNote(
+ dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_JPEG2000_GUARD_BITS_FOR_2K, string("2")
+ ).set_cpl_id(cpl->id())
+ );
+ }
+
+ check_verify_result({ dir }, {}, notes);
+}
+