X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fdcp_examiner.cc;h=d9c904720efd09b229ec336f91c37c2f43a533ef;hb=a75cac36969942d1fcb43dadfdf60434c840af54;hp=e369b46ff08171be8ec699b2d03ee612d4b2e1b6;hpb=d860d9de91607aad3561e087fe83c2290ec5d42c;p=dcpomatic.git diff --git a/src/lib/dcp_examiner.cc b/src/lib/dcp_examiner.cc index e369b46ff..d9c904720 100644 --- a/src/lib/dcp_examiner.cc +++ b/src/lib/dcp_examiner.cc @@ -20,11 +20,14 @@ #include "config.h" +#include "constants.h" #include "dcp_content.h" #include "dcp_examiner.h" #include "dcpomatic_log.h" #include "exceptions.h" +#include "font_id_allocator.h" #include "image.h" +#include "text_content.h" #include "util.h" #include #include @@ -81,7 +84,7 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) for (auto cpl: cpls) { int unsatisfied = 0; - for (auto reel: cpl->reels()) { + for (auto const& reel: cpl->reels()) { if (reel->main_picture() && !reel->main_picture()->asset_ref().resolved()) { ++unsatisfied; } @@ -128,89 +131,86 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) LOG_GENERAL("Looking at %1 reels", selected_cpl->reels().size()); + int reel_index = 0; for (auto reel: selected_cpl->reels()) { LOG_GENERAL("Reel %1", reel->id()); - vector> reel_fonts; if (reel->main_picture()) { + /* This will mean a VF can be displayed in the timeline even if its picture asset + * is yet be resolved. + */ + _has_video = true; + _video_length += reel->main_picture()->actual_duration(); + if (!reel->main_picture()->asset_ref().resolved()) { - /* We are missing this asset so we can't continue; examination will be repeated later */ - _needs_assets = true; LOG_GENERAL("Main picture %1 of reel %2 is missing", reel->main_picture()->id(), reel->id()); - return; - } - - LOG_GENERAL("Main picture %1 of reel %2 found", reel->main_picture()->id(), reel->id()); - - auto const frac = reel->main_picture()->edit_rate(); - float const fr = float(frac.numerator) / frac.denominator; - if (!_video_frame_rate) { - _video_frame_rate = fr; - } else if (_video_frame_rate.get() != fr) { - throw DCPError (_("Mismatched frame rates in DCP")); - } + _needs_assets = true; + /* Use a dummy value here; it will be replaced when the VF is re-examined. */ + _video_size = dcp::Size(1998, 1080); + } else { + LOG_GENERAL("Main picture %1 of reel %2 found", reel->main_picture()->id(), reel->id()); + + auto const frac = reel->main_picture()->edit_rate(); + float const fr = float(frac.numerator) / frac.denominator; + if (!_video_frame_rate) { + _video_frame_rate = fr; + } else if (_video_frame_rate.get() != fr) { + throw DCPError (_("Mismatched frame rates in DCP")); + } - _has_video = true; - auto asset = reel->main_picture()->asset(); - if (!_video_size) { - _video_size = asset->size (); - } else if (_video_size.get() != asset->size ()) { - throw DCPError (_("Mismatched video sizes in DCP")); + auto asset = reel->main_picture()->asset(); + if (!_video_size) { + _video_size = asset->size (); + } else if (_video_size.get() != asset->size ()) { + throw DCPError (_("Mismatched video sizes in DCP")); + } } - - _video_length += reel->main_picture()->actual_duration(); } if (reel->main_sound()) { + _has_audio = true; + _audio_length += reel->main_sound()->actual_duration(); + if (!reel->main_sound()->asset_ref().resolved()) { - /* We are missing this asset so we can't continue; examination will be repeated later */ - _needs_assets = true; LOG_GENERAL("Main sound %1 of reel %2 is missing", reel->main_sound()->id(), reel->id()); - return; - } + _needs_assets = true; + } else { + LOG_GENERAL("Main sound %1 of reel %2 found", reel->main_sound()->id(), reel->id()); - LOG_GENERAL("Main sound %1 of reel %2 found", reel->main_sound()->id(), reel->id()); + auto asset = reel->main_sound()->asset(); - _has_audio = true; - auto asset = reel->main_sound()->asset(); + if (!_audio_channels) { + _audio_channels = asset->channels(); + } else if (_audio_channels.get() != asset->channels()) { + throw DCPError (_("Mismatched audio channel counts in DCP")); + } - if (!_audio_channels) { - _audio_channels = asset->channels(); - } else if (_audio_channels.get() != asset->channels()) { - throw DCPError (_("Mismatched audio channel counts in DCP")); - } + _active_audio_channels = std::max(_active_audio_channels.get_value_or(0), asset->active_channels()); - if (!_active_audio_channels) { - _active_audio_channels = asset->active_channels(); - } else if (_active_audio_channels.get() != asset->active_channels()) { - throw DCPError(_("Mismatched active audio channel counts in DCP")); - } + if (!_audio_frame_rate) { + _audio_frame_rate = asset->sampling_rate (); + } else if (_audio_frame_rate.get() != asset->sampling_rate ()) { + throw DCPError (_("Mismatched audio sample rates in DCP")); + } - if (!_audio_frame_rate) { - _audio_frame_rate = asset->sampling_rate (); - } else if (_audio_frame_rate.get() != asset->sampling_rate ()) { - throw DCPError (_("Mismatched audio sample rates in DCP")); + _audio_language = try_to_parse_language (asset->language()); } - - _audio_length += reel->main_sound()->actual_duration(); - _audio_language = try_to_parse_language (asset->language()); } if (reel->main_subtitle()) { if (!reel->main_subtitle()->asset_ref().resolved()) { - /* We are missing this asset so we can't continue; examination will be repeated later */ - _needs_assets = true; LOG_GENERAL("Main subtitle %1 of reel %2 is missing", reel->main_subtitle()->id(), reel->id()); - return; - } - - LOG_GENERAL("Main subtitle %1 of reel %2 found", reel->main_subtitle()->id(), reel->id()); + _needs_assets = true; + } else { + LOG_GENERAL("Main subtitle %1 of reel %2 found", reel->main_subtitle()->id(), reel->id()); - _text_count[TextType::OPEN_SUBTITLE] = 1; - _open_subtitle_language = try_to_parse_language(reel->main_subtitle()->language()); + _text_count[TextType::OPEN_SUBTITLE] = 1; + _open_subtitle_language = try_to_parse_language(reel->main_subtitle()->language()); - for (auto const& font: reel->main_subtitle()->asset()->font_data()) { - reel_fonts.push_back(make_shared(font.first, font.second)); + auto asset = reel->main_subtitle()->asset(); + for (auto const& font: asset->font_data()) { + _fonts.push_back({reel_index, asset->id(), make_shared(font.first, font.second)}); + } } } @@ -228,16 +228,18 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) for (auto ccap: reel->closed_captions()) { if (!ccap->asset_ref().resolved()) { - /* We are missing this asset so we can't continue; examination will be repeated later */ - _needs_assets = true; LOG_GENERAL("Closed caption %1 of reel %2 is missing", ccap->id(), reel->id()); - return; - } - - LOG_GENERAL("Closed caption %1 of reel %2 found", ccap->id(), reel->id()); + _needs_assets = true; + } else { + LOG_GENERAL("Closed caption %1 of reel %2 found", ccap->id(), reel->id()); - for (auto const& font: ccap->asset()->font_data()) { - reel_fonts.push_back(make_shared(font.first, font.second)); + auto asset = ccap->asset(); + for (auto const& font: asset->font_data()) { + _fonts.push_back({reel_index, asset->id(), make_shared(font.first, font.second)}); + } + if (asset->font_data().empty()) { + _fonts.push_back({reel_index, asset->id(), make_shared("")}); + } } } @@ -267,11 +269,7 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) _reel_lengths.push_back(reel->atmos()->actual_duration()); } - if (reel_fonts.empty()) { - reel_fonts.push_back(make_shared("")); - } - - _fonts.push_back(reel_fonts); + ++reel_index; } _encrypted = selected_cpl->any_encrypted(); @@ -287,38 +285,40 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) try { for (auto i: selected_cpl->reels()) { LOG_GENERAL ("Reel %1", i->id()); - auto pic = i->main_picture()->asset(); - if (pic->encrypted() && !pic->key()) { - _kdm_valid = false; - LOG_GENERAL_NC ("Picture has no key"); - break; - } - auto mono = dynamic_pointer_cast(pic); - auto stereo = dynamic_pointer_cast(pic); - - if (mono) { - auto reader = mono->start_read(); - reader->set_check_hmac (false); - reader->get_frame(0)->xyz_image(); - } else { - auto reader = stereo->start_read(); - reader->set_check_hmac (false); - reader->get_frame(0)->xyz_image(dcp::Eye::LEFT); + if (i->main_picture() && i->main_picture()->asset_ref().resolved()) { + auto pic = i->main_picture()->asset(); + if (pic->encrypted() && !pic->key()) { + _kdm_valid = false; + LOG_GENERAL_NC ("Picture has no key"); + break; + } + auto mono = dynamic_pointer_cast(pic); + auto stereo = dynamic_pointer_cast(pic); + + if (mono) { + auto reader = mono->start_read(); + reader->set_check_hmac (false); + reader->get_frame(0)->xyz_image(); + } else { + auto reader = stereo->start_read(); + reader->set_check_hmac (false); + reader->get_frame(0)->xyz_image(dcp::Eye::LEFT); + } } - if (i->main_sound()) { - auto sound = i->main_sound()->asset (); + if (i->main_sound() && i->main_sound()->asset_ref().resolved()) { + auto sound = i->main_sound()->asset(); if (sound->encrypted() && !sound->key()) { _kdm_valid = false; LOG_GENERAL_NC ("Sound has no key"); break; } - auto reader = i->main_sound()->asset()->start_read(); + auto reader = sound->start_read(); reader->set_check_hmac (false); reader->get_frame(0); } - if (i->main_subtitle()) { + if (i->main_subtitle() && i->main_subtitle()->asset_ref().resolved()) { auto sub = i->main_subtitle()->asset(); auto mxf_sub = dynamic_pointer_cast(sub); if (mxf_sub && mxf_sub->encrypted() && !mxf_sub->key()) { @@ -329,16 +329,17 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) sub->subtitles (); } - if (i->atmos()) { - auto atmos = i->atmos()->asset(); - if (atmos->encrypted() && !atmos->key()) { - _kdm_valid = false; - LOG_GENERAL_NC ("ATMOS sound has no key"); - break; + if (i->atmos() && i->atmos()->asset_ref().resolved()) { + if (auto atmos = i->atmos()->asset()) { + if (atmos->encrypted() && !atmos->key()) { + _kdm_valid = false; + LOG_GENERAL_NC ("ATMOS sound has no key"); + break; + } + auto reader = atmos->start_read(); + reader->set_check_hmac (false); + reader->get_frame(0); } - auto reader = atmos->start_read(); - reader->set_check_hmac (false); - reader->get_frame(0); } } } catch (dcp::ReadError& e) { @@ -350,8 +351,10 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) } _standard = selected_cpl->standard(); - _three_d = !selected_cpl->reels().empty() && selected_cpl->reels().front()->main_picture() && - dynamic_pointer_cast(selected_cpl->reels().front()->main_picture()->asset()); + if (!selected_cpl->reels().empty()) { + auto first_reel = selected_cpl->reels()[0]; + _three_d = first_reel->main_picture() && first_reel->main_picture()->asset_ref().resolved() && dynamic_pointer_cast(first_reel->main_picture()->asset()); + } _ratings = selected_cpl->ratings(); for (auto version: selected_cpl->content_versions()) { _content_versions.push_back(version.label_text); @@ -359,3 +362,27 @@ DCPExaminer::DCPExaminer (shared_ptr content, bool tolerant) _cpl = selected_cpl->id(); } + + +void +DCPExaminer::add_fonts(shared_ptr content) +{ + FontIDAllocator font_id_allocator; + + for (auto const& font: _fonts) { + font_id_allocator.add_font(font.reel_index, font.asset_id, font.font->id()); + } + + font_id_allocator.allocate(); + + for (auto const& font: _fonts) { + auto font_copy = make_shared(*font.font); + font_copy->set_id(font_id_allocator.font_id(font.reel_index, font.asset_id, font.font->id())); + content->add_font(font_copy); + } + + if (!font_id_allocator.has_default_font()) { + content->add_font(make_shared(font_id_allocator.default_font_id(), default_font_file())); + } +} +