#include "exceptions.h"
#include "compose.hpp"
#include "raw_convert.h"
+#include "smpte_subtitle_asset.h"
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>
#include <xercesc/parsers/AbstractDOMParser.hpp>
using std::cout;
using std::map;
using std::max;
-using boost::shared_ptr;
+using std::shared_ptr;
using boost::optional;
using boost::function;
-using boost::dynamic_pointer_cast;
+using std::dynamic_pointer_cast;
using namespace dcp;
using namespace xercesc;
}
+void
+verify_language_tag (string tag, list<VerificationNote>& notes)
+{
+ try {
+ dcp::LanguageTag test (tag);
+ } catch (dcp::LanguageTagError &) {
+ notes.push_back (VerificationNote(VerificationNote::VERIFY_BV21_ERROR, VerificationNote::BAD_LANGUAGE, tag));
+ }
+}
+
+
enum VerifyPictureAssetResult
{
VERIFY_PICTURE_ASSET_RESULT_GOOD,
- VERIFY_PICTURE_ASSET_RESULT_FRAME_NEARLY_TOO_BIG,
+ VERIFY_PICTURE_ASSET_RESULT_FRAME_NEARLY_TOO_LARGE,
VERIFY_PICTURE_ASSET_RESULT_BAD,
};
int
biggest_frame_size (shared_ptr<const MonoPictureFrame> frame)
{
- return frame->j2k_size ();
+ return frame->size ();
}
int
biggest_frame_size (shared_ptr<const StereoPictureFrame> frame)
{
- return max(frame->left_j2k_size(), frame->right_j2k_size());
+ return max(frame->left()->size(), frame->right()->size());
}
if (biggest_frame > max_frame) {
return VERIFY_PICTURE_ASSET_RESULT_BAD;
} else if (biggest_frame > risky_frame) {
- return VERIFY_PICTURE_ASSET_RESULT_FRAME_NEARLY_TOO_BIG;
+ return VERIFY_PICTURE_ASSET_RESULT_FRAME_NEARLY_TOO_LARGE;
}
return VERIFY_PICTURE_ASSET_RESULT_GOOD;
)
);
break;
- case VERIFY_PICTURE_ASSET_RESULT_FRAME_NEARLY_TOO_BIG:
+ case VERIFY_PICTURE_ASSET_RESULT_FRAME_NEARLY_TOO_LARGE:
notes.push_back (
VerificationNote(
VerificationNote::VERIFY_WARNING, VerificationNote::PICTURE_FRAME_NEARLY_TOO_LARGE, file
list<VerificationNote>& notes
)
{
- stage ("Checking sound asset hash", reel->main_sound()->asset()->file());
+ shared_ptr<dcp::SoundAsset> asset = reel->main_sound()->asset();
+ stage ("Checking sound asset hash", asset->file());
VerifyAssetResult const r = verify_asset (dcp, reel->main_sound(), progress);
switch (r) {
case VERIFY_ASSET_RESULT_BAD:
notes.push_back (
VerificationNote(
- VerificationNote::VERIFY_ERROR, VerificationNote::SOUND_HASH_INCORRECT, *reel->main_sound()->asset()->file()
+ VerificationNote::VERIFY_ERROR, VerificationNote::SOUND_HASH_INCORRECT, *asset->file()
)
);
break;
case VERIFY_ASSET_RESULT_CPL_PKL_DIFFER:
notes.push_back (
VerificationNote(
- VerificationNote::VERIFY_ERROR, VerificationNote::PKL_CPL_SOUND_HASHES_DISAGREE, *reel->main_sound()->asset()->file()
+ VerificationNote::VERIFY_ERROR, VerificationNote::PKL_CPL_SOUND_HASHES_DISAGREE, *asset->file()
)
);
break;
default:
break;
}
+
+ stage ("Checking sound asset metadata", asset->file());
+
+ verify_language_tag (asset->language(), notes);
+}
+
+
+static void
+verify_main_subtitle_reel (shared_ptr<const ReelSubtitleAsset> reel_asset, list<VerificationNote>& notes)
+{
+ /* XXX: is Language compulsory? */
+ if (reel_asset->language()) {
+ verify_language_tag (*reel_asset->language(), notes);
+ }
}
list<VerificationNote>& notes
)
{
- shared_ptr<ReelSubtitleAsset> reel_asset = reel->main_subtitle ();
- stage ("Checking subtitle XML", reel->main_subtitle()->asset()->file());
+ shared_ptr<SubtitleAsset> asset = reel->main_subtitle()->asset();
+ stage ("Checking subtitle XML", asset->file());
/* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk
* gets passed through libdcp which may clean up and therefore hide errors.
*/
- validate_xml (reel->main_subtitle()->asset()->raw_xml(), xsd_dtd_directory, notes);
+ validate_xml (asset->raw_xml(), xsd_dtd_directory, notes);
+
+ shared_ptr<SMPTESubtitleAsset> smpte = dynamic_pointer_cast<SMPTESubtitleAsset>(asset);
+ if (smpte) {
+ if (smpte->language()) {
+ verify_language_tag (*smpte->language(), notes);
+ }
+ }
}
notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::GENERAL_READ, string(e.what())));
}
+ if (dcp->standard() != dcp::SMPTE) {
+ notes.push_back (VerificationNote(VerificationNote::VERIFY_BV21_ERROR, VerificationNote::NOT_SMPTE));
+ }
+
BOOST_FOREACH (shared_ptr<CPL> cpl, dcp->cpls()) {
stage ("Checking CPL", cpl->file());
validate_xml (cpl->file().get(), xsd_dtd_directory, notes);
/* Check that the CPL's hash corresponds to the PKL */
BOOST_FOREACH (shared_ptr<PKL> i, dcp->pkls()) {
optional<string> h = i->hash(cpl->id());
- if (h && make_digest(Data(*cpl->file())) != *h) {
+ if (h && make_digest(ArrayData(*cpl->file())) != *h) {
notes.push_back (VerificationNote(VerificationNote::VERIFY_ERROR, VerificationNote::CPL_HASH_INCORRECT));
}
}
verify_main_sound_asset (dcp, reel, stage, progress, notes);
}
- if (reel->main_subtitle() && reel->main_subtitle()->asset_ref().resolved()) {
- verify_main_subtitle_asset (reel, stage, xsd_dtd_directory, notes);
+ if (reel->main_subtitle()) {
+ verify_main_subtitle_reel (reel->main_subtitle(), notes);
+ if (reel->main_subtitle()->asset_ref().resolved()) {
+ verify_main_subtitle_asset (reel, stage, xsd_dtd_directory, notes);
+ }
}
}
}
return String::compose("The instantaneous bit rate of the picture asset %1 is close to the limit of 250Mbit/s in at least one place.", note.file()->filename());
case dcp::VerificationNote::EXTERNAL_ASSET:
return String::compose("An asset that this DCP refers to is not included in the DCP. It may be a VF. Missing asset is %1.", note.note().get());
+ case dcp::VerificationNote::NOT_SMPTE:
+ return "This DCP does not use the SMPTE standard, which is required for Bv2.1 compliance.";
+ case dcp::VerificationNote::BAD_LANGUAGE:
+ return String::compose("The DCP specifies a language '%1' which does not conform to the RFC 5646 standard.", note.note().get());
}
return "";