#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 <dcp/cpl.h>
#include <dcp/dcp.h>
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;
}
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<shared_ptr<dcpomatic::Font>> 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;
+ } 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());
- _active_audio_channels = std::max(_active_audio_channels.get_value_or(0), asset->active_channels());
+ 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<dcpomatic::Font>(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<dcpomatic::Font>(font.first, font.second)});
+ }
}
}
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<dcpomatic::Font>(font.first, font.second));
+ auto asset = ccap->asset();
+ for (auto const& font: asset->font_data()) {
+ _fonts.push_back({reel_index, asset->id(), make_shared<dcpomatic::Font>(font.first, font.second)});
+ }
}
}
_reel_lengths.push_back(reel->atmos()->actual_duration());
}
- if (reel_fonts.empty()) {
- reel_fonts.push_back(make_shared<dcpomatic::Font>(""));
- }
-
- _fonts.push_back(reel_fonts);
+ ++reel_index;
}
_encrypted = selected_cpl->any_encrypted();
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<dcp::MonoPictureAsset>(pic);
- auto stereo = dynamic_pointer_cast<dcp::StereoPictureAsset>(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<dcp::MonoPictureAsset>(pic);
+ auto stereo = dynamic_pointer_cast<dcp::StereoPictureAsset>(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<dcp::MXF>(sub);
if (mxf_sub && mxf_sub->encrypted() && !mxf_sub->key()) {
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) {
}
_standard = selected_cpl->standard();
- _three_d = !selected_cpl->reels().empty() && selected_cpl->reels().front()->main_picture() &&
- dynamic_pointer_cast<dcp::StereoPictureAsset>(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<dcp::StereoPictureAsset>(first_reel->main_picture()->asset());
+ }
_ratings = selected_cpl->ratings();
for (auto version: selected_cpl->content_versions()) {
_content_versions.push_back(version.label_text);
_cpl = selected_cpl->id();
}
+
+
+void
+DCPExaminer::add_fonts(shared_ptr<TextContent> 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<dcpomatic::Font>(*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<dcpomatic::Font>(font_id_allocator.default_font_id(), default_font_file()));
+ }
+}
+