diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/verify.cc | 11 | ||||
| -rw-r--r-- | src/verify.h | 44 | ||||
| -rw-r--r-- | src/verify_j2k.cc | 16 | ||||
| -rw-r--r-- | src/verify_j2k.h | 6 |
4 files changed, 66 insertions, 11 deletions
diff --git a/src/verify.cc b/src/verify.cc index d43c7ff1..81ca0bc9 100644 --- a/src/verify.cc +++ b/src/verify.cc @@ -449,7 +449,7 @@ verify_picture_asset (shared_ptr<const ReelFileAsset> reel_file_asset, boost::fi biggest_frame = max(biggest_frame, frame->size()); if (!mono_asset->encrypted() || mono_asset->key()) { vector<VerificationNote> j2k_notes; - verify_j2k (frame, j2k_notes); + verify_j2k(frame, i, mono_asset->frame_rate().numerator, j2k_notes); check_and_add (j2k_notes); } progress (float(i) / duration); @@ -461,8 +461,8 @@ verify_picture_asset (shared_ptr<const ReelFileAsset> reel_file_asset, boost::fi biggest_frame = max(biggest_frame, max(frame->left()->size(), frame->right()->size())); if (!stereo_asset->encrypted() || stereo_asset->key()) { vector<VerificationNote> j2k_notes; - verify_j2k (frame->left(), j2k_notes); - verify_j2k (frame->right(), j2k_notes); + verify_j2k(frame->left(), i, stereo_asset->frame_rate().numerator, j2k_notes); + verify_j2k(frame->right(), i, stereo_asset->frame_rate().numerator, j2k_notes); check_and_add (j2k_notes); } progress (float(i) / duration); @@ -2014,6 +2014,11 @@ dcp::note_to_string (VerificationNote note) return String::compose("<MainSoundConfiguration> has an invalid value: %1", note.note().get()); case VerificationNote::Code::MISSING_FONT: return String::compose("The font file for font ID \"%1\" was not found, or was not referred to in the ASSETMAP.", note.note().get()); + case VerificationNote::Code::INVALID_JPEG2000_TILE_PART_SIZE: + return String::compose( + "Frame %1 has an image component that is too large (component %2 is %3 bytes in size).", + note.frame().get(), note.component().get(), note.size().get() + ); } return ""; diff --git a/src/verify.h b/src/verify.h index 8eec9749..4d65fae7 100644 --- a/src/verify.h +++ b/src/verify.h @@ -436,7 +436,13 @@ public: /** An interop subtitle file has a <LoadFont> node which refers to a font file that is not found. * note contains the <LoadFont> ID */ - MISSING_FONT + MISSING_FONT, + /** A tile part in a JPEG2000 frame is too big. + * frame contains the frame index (counted from 0) + * component contains the component index (0, 1 or 2) + * size contains the invalid size in bytes. + */ + INVALID_JPEG2000_TILE_PART_SIZE, }; VerificationNote (Type type, Code code) @@ -485,9 +491,12 @@ public: private: enum class Data { - NOTE, ///< further information about the error - FILE, ///< path of file containing the error - LINE ///< error line number within the FILE + NOTE, ///< further information about the error + FILE, ///< path of file containing the error + LINE, ///< error line number within the FILE + FRAME, + COMPONENT, + SIZE, }; template <class T> @@ -513,6 +522,33 @@ public: return data<uint64_t>(Data::LINE); } + VerificationNote& set_frame(int frame) { + _data[Data::FRAME] = frame; + return *this; + } + + boost::optional<int> frame() const { + return data<int>(Data::FRAME); + } + + VerificationNote& set_component(int component) { + _data[Data::COMPONENT] = component; + return *this; + } + + boost::optional<int> component() const { + return data<int>(Data::COMPONENT); + } + + VerificationNote& set_size(int size) { + _data[Data::SIZE] = size; + return *this; + } + + boost::optional<int> size() const { + return data<int>(Data::SIZE); + } + private: Type _type; Code _code; diff --git a/src/verify_j2k.cc b/src/verify_j2k.cc index 86ffb5b4..b9158849 100644 --- a/src/verify_j2k.cc +++ b/src/verify_j2k.cc @@ -65,8 +65,11 @@ public: void -dcp::verify_j2k (shared_ptr<const Data> j2k, vector<VerificationNote>& notes) +dcp::verify_j2k(shared_ptr<const Data> j2k, int frame_index, int frame_rate, vector<VerificationNote>& notes) { + /* See ITU-T T800 (visible on https://github.com/Ymagis/ClairMeta/issues/130) */ + unsigned int const max_tile_part_size = std::floor(200e6 / (8 * frame_rate)); + try { auto ptr = j2k->data(); auto end = ptr + j2k->size(); @@ -202,8 +205,8 @@ dcp::verify_j2k (shared_ptr<const Data> j2k, vector<VerificationNote>& notes) } else if (*marker_name == "SOT") { require_16(10, "invalid SOT size %1"); get_16(); // tile index - get_32(); // tile part length - get_8(); // tile part index + auto const tile_part_length = get_32(); + auto const tile_part_index = get_8(); auto tile_parts = get_8(); if (!fourk && tile_parts != 3) { notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_JPEG2000_TILE_PARTS_FOR_2K, raw_convert<string>(tile_parts) }); @@ -211,6 +214,13 @@ dcp::verify_j2k (shared_ptr<const Data> j2k, vector<VerificationNote>& notes) if (fourk && tile_parts != 6) { notes.push_back ({ VerificationNote::Type::BV21_ERROR, VerificationNote::Code::INVALID_JPEG2000_TILE_PARTS_FOR_4K, raw_convert<string>(tile_parts) }); } + if (tile_part_length > max_tile_part_size) { + VerificationNote note{VerificationNote::Type::ERROR, VerificationNote::Code::INVALID_JPEG2000_TILE_PART_SIZE}; + note.set_frame(frame_index); + note.set_component(tile_part_index); + note.set_size(tile_part_length); + notes.push_back(note); + } main_header_finished = true; } else if (*marker_name == "SOD") { while (ptr < (end - 1) && (ptr[0] != 0xff || ptr[1] < 0x90)) { diff --git a/src/verify_j2k.h b/src/verify_j2k.h index 3d9093dd..ac69155c 100644 --- a/src/verify_j2k.h +++ b/src/verify_j2k.h @@ -51,7 +51,11 @@ namespace dcp { class Data; -void verify_j2k (std::shared_ptr<const Data> data, std::vector<VerificationNote>& notes); +/** @param frame_index Video frame index, so that notes can say which frame contains the problem. + * @param frame_rate Video frame rate (in frames per second) to calculate how big the tile parts + * can be. + */ +void verify_j2k(std::shared_ptr<const Data> data, int frame_index, int frame_rate, std::vector<VerificationNote>& notes); } |
