From 6f23b55a7783f93549115a133ca2e6e938bd0cd1 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 13 Oct 2015 11:30:30 +0100 Subject: [PATCH] Some attempts to block referencing of DCPs when it is not possible. --- hacks/fft.py | 50 +++++++++++ src/lib/dcp_content.cc | 69 ++++++++++++++-- src/lib/dcp_content.h | 8 ++ src/lib/dcpomatic_time.h | 2 +- src/lib/overlaps.h | 39 +++++++++ src/lib/referenced_reel_asset.h | 32 ++++++++ src/wx/audio_panel.cc | 21 ++++- src/wx/subtitle_panel.cc | 27 ++++-- src/wx/timeline.cc | 15 ++-- src/wx/video_panel.cc | 21 ++++- test/fft.py | 17 ++++ test/reels_test.cc | 141 ++++++++++++++++++++++++++++++++ test/vf_test.cc | 66 +++++++++++++++ test/wscript | 1 + 14 files changed, 486 insertions(+), 23 deletions(-) create mode 100644 hacks/fft.py create mode 100644 src/lib/overlaps.h create mode 100644 src/lib/referenced_reel_asset.h create mode 100644 test/fft.py create mode 100644 test/reels_test.cc create mode 100644 test/vf_test.cc diff --git a/hacks/fft.py b/hacks/fft.py new file mode 100644 index 000000000..ab700a5ec --- /dev/null +++ b/hacks/fft.py @@ -0,0 +1,50 @@ +#!/usr/bin/python + +import wave +import sys +import struct +from pylab import * +import numpy + +f = wave.open(sys.argv[1], 'rb') +width = f.getsampwidth() +peak = pow(2, width * 8) / 2 +channels = f.getnchannels() +frames = f.getnframes() +print '%d bytes per sample' % width +print '%d channels' % channels +print '%d frames' % frames +data = [] +for i in range(0, channels): + data.append([]) + +for i in range(0, frames): + frame = f.readframes(1) + for j in range(0, channels): + v = 0 + for k in range(0, width): + v |= ord(frame[j * width + k]) << (k * 8) + if v >= peak: + v = v - 2 * peak + data[j].append(v) + +f.close() + +names = ['L', 'R', 'C', 'Lfe', 'Ls', 'Rs'] +dyn_range = 20 * log10(pow(2, 23)) + +for i in range(0, channels): + s = numpy.fft.fft(data[i]) +# subplot(channels, 1, i + 1) + # 138.5 is a fudge factor: + semilogx(arange(0, frames / 2, 0.5), 20 * log10(abs(s) + 0.1) - dyn_range, label = names[i]) + xlim(100, frames / 4) +plt.gca().xaxis.grid(True, which='major') +plt.gca().xaxis.grid(True, which='minor') +plt.gca().yaxis.grid(True) +legend(loc = 'lower right') +show() + +#plot(abs(numpy.fft.fft(data[0]))) +#plot(data[0]) +#show() diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc index f39b2fb4a..747216f3c 100644 --- a/src/lib/dcp_content.cc +++ b/src/lib/dcp_content.cc @@ -22,6 +22,7 @@ #include "job.h" #include "film.h" #include "config.h" +#include "overlaps.h" #include "compose.hpp" #include "dcp_decoder.h" #include @@ -250,19 +251,75 @@ DCPContent::set_reference_subtitle (bool r) signal_changed (DCPContentProperty::REFERENCE_SUBTITLE); } +list +DCPContent::reels () const +{ + list p; + DCPDecoder decoder (shared_from_this(), false); + + shared_ptr film = _film.lock (); + DCPOMATIC_ASSERT (film); + DCPTime from = position (); + BOOST_FOREACH (shared_ptr i, decoder.reels()) { + DCPTime const to = from + DCPTime::from_frames (i->main_picture()->duration(), film->video_frame_rate()); + p.push_back (DCPTimePeriod (from, to)); + from = to; + } + + return p; +} + list DCPContent::reel_split_points () const { list s; - DCPDecoder decoder (shared_from_this(), false); - DCPTime t = position(); + BOOST_FOREACH (DCPTimePeriod i, reels()) { + s.push_back (i.from); + } + return s; +} +template +bool +DCPContent::can_reference (string overlapping, list& why_not) const +{ shared_ptr film = _film.lock (); DCPOMATIC_ASSERT (film); - BOOST_FOREACH (shared_ptr k, decoder.reels()) { - s.push_back (t); - t += DCPTime::from_frames (k->main_picture()->duration(), film->video_frame_rate()); + + list const fr = film->reels (); + /* fr must contain reels(). It can also contain other reels, but it must at + least contain reels(). + */ + BOOST_FOREACH (DCPTimePeriod i, reels()) { + if (find (fr.begin(), fr.end(), i) == fr.end ()) { + why_not.push_back (_("Reel lengths in the project differ from those in the DCP; set the reel mode to `split by video content'.")); + return false; + } } - return s; + list > a = overlaps (film->content(), position(), end()); + if (a.size() != 1 || a.front().get() != this) { + why_not.push_back (overlapping); + return false; + } + + return true; +} + +bool +DCPContent::can_reference_video (list& why_not) const +{ + return can_reference (_("There is other video content overlapping this DCP; remove it."), why_not); +} + +bool +DCPContent::can_reference_audio (list& why_not) const +{ + return can_reference (_("There is other audio content overlapping this DCP; remove it."), why_not); +} + +bool +DCPContent::can_reference_subtitle (list& why_not) const +{ + return can_reference (_("There is other subtitle content overlapping this DCP; remove it."), why_not); } diff --git a/src/lib/dcp_content.h b/src/lib/dcp_content.h index be12ba534..78c97bec5 100644 --- a/src/lib/dcp_content.h +++ b/src/lib/dcp_content.h @@ -104,6 +104,8 @@ public: return _reference_video; } + bool can_reference_video (std::list &) const; + void set_reference_audio (bool r); bool reference_audio () const { @@ -111,6 +113,8 @@ public: return _reference_audio; } + bool can_reference_audio (std::list &) const; + void set_reference_subtitle (bool r); bool reference_subtitle () const { @@ -118,11 +122,15 @@ public: return _reference_subtitle; } + bool can_reference_subtitle (std::list &) const; + protected: void add_properties (std::list >& p) const; private: void read_directory (boost::filesystem::path); + std::list reels () const; + template bool can_reference (std::string overlapping, std::list& why_not) const; std::string _name; bool _has_subtitles; diff --git a/src/lib/dcpomatic_time.h b/src/lib/dcpomatic_time.h index 496f54d8e..90e79de0a 100644 --- a/src/lib/dcpomatic_time.h +++ b/src/lib/dcpomatic_time.h @@ -258,7 +258,7 @@ public: return (from <= other && other < to); } - bool operator== (TimePeriod const & other) { + bool operator== (TimePeriod const & other) const { return from == other.from && to == other.to; } }; diff --git a/src/lib/overlaps.h b/src/lib/overlaps.h new file mode 100644 index 000000000..6018af15f --- /dev/null +++ b/src/lib/overlaps.h @@ -0,0 +1,39 @@ +/* + Copyright (C) 2013-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @return Pieces of content type C that overlap a specified time range in the given ContentList */ +template +std::list > +overlaps (ContentList cl, DCPTime from, DCPTime to) +{ + std::list > overlaps; + DCPTimePeriod period (from, to); + for (typename ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) { + boost::shared_ptr c = boost::dynamic_pointer_cast (*i); + if (!c) { + continue; + } + + if (DCPTimePeriod(c->position(), c->end()).overlaps (period)) { + overlaps.push_back (c); + } + } + + return overlaps; +} diff --git a/src/lib/referenced_reel_asset.h b/src/lib/referenced_reel_asset.h new file mode 100644 index 000000000..5f5421283 --- /dev/null +++ b/src/lib/referenced_reel_asset.h @@ -0,0 +1,32 @@ +/* + Copyright (C) 2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +class ReferencedReelAsset +{ +public: + ReferencedReelAsset (boost::shared_ptr asset_, DCPTimePeriod period_) + : asset (asset_) + , period (period_) + {} + + /** The asset */ + boost::shared_ptr asset; + /** Period that this asset covers in the DCP */ + DCPTimePeriod period; +}; diff --git a/src/wx/audio_panel.cc b/src/wx/audio_panel.cc index a4976b8c1..9632b5235 100644 --- a/src/wx/audio_panel.cc +++ b/src/wx/audio_panel.cc @@ -141,6 +141,8 @@ AudioPanel::film_changed (Film::Property property) case Film::VIDEO_FRAME_RATE: setup_description (); break; + case Film::REEL_TYPE: + setup_sensitivity (); default: break; } @@ -238,7 +240,24 @@ void AudioPanel::setup_sensitivity () { AudioContentList sel = _parent->selected_audio (); - _reference->Enable (sel.size() == 1 && dynamic_pointer_cast (sel.front ())); + + shared_ptr dcp; + if (sel.size() == 1) { + dcp = dynamic_pointer_cast (sel.front ()); + } + + list why_not; + bool const can_reference = dcp && dcp->can_reference_audio (why_not); + _reference->Enable (can_reference); + + wxString s; + if (!can_reference) { + s = _("Cannot reference this DCP. "); + BOOST_FOREACH (string i, why_not) { + s += std_to_wx(i) + wxT(" "); + } + } + _reference->SetToolTip (s); if (_reference->GetValue ()) { _gain->wrapped()->Enable (false); diff --git a/src/wx/subtitle_panel.cc b/src/wx/subtitle_panel.cc index f3083b194..757a302a1 100644 --- a/src/wx/subtitle_panel.cc +++ b/src/wx/subtitle_panel.cc @@ -36,6 +36,7 @@ using std::vector; using std::string; +using std::list; using boost::shared_ptr; using boost::lexical_cast; using boost::dynamic_pointer_cast; @@ -133,7 +134,7 @@ SubtitlePanel::SubtitlePanel (ContentPanel* p) void SubtitlePanel::film_changed (Film::Property property) { - if (property == Film::CONTENT) { + if (property == Film::CONTENT || property == Film::REEL_TYPE) { setup_sensitivity (); } } @@ -219,7 +220,8 @@ SubtitlePanel::setup_sensitivity () int ffmpeg_subs = 0; int subrip_or_dcp_subs = 0; int image_subs = 0; - BOOST_FOREACH (shared_ptr i, _parent->selected_subtitle ()) { + SubtitleContentList sel = _parent->selected_subtitle (); + BOOST_FOREACH (shared_ptr i, sel) { shared_ptr fc = boost::dynamic_pointer_cast (i); shared_ptr sc = boost::dynamic_pointer_cast (i); shared_ptr dsc = boost::dynamic_pointer_cast (i); @@ -242,6 +244,24 @@ SubtitlePanel::setup_sensitivity () } } + shared_ptr dcp; + if (sel.size() == 1) { + dcp = dynamic_pointer_cast (sel.front ()); + } + + list why_not; + bool const can_reference = dcp && dcp->can_reference_subtitle (why_not); + _reference->Enable (can_reference); + + wxString s; + if (!can_reference) { + s = _("Cannot reference this DCP. "); + BOOST_FOREACH (string i, why_not) { + s += std_to_wx(i) + wxT(" "); + } + } + _reference->SetToolTip (s); + bool const reference = _reference->GetValue (); _use->Enable (!reference && any_subs > 0); @@ -255,9 +275,6 @@ SubtitlePanel::setup_sensitivity () _stream->Enable (!reference && ffmpeg_subs == 1); _subtitle_view_button->Enable (!reference && subrip_or_dcp_subs == 1); _fonts_dialog_button->Enable (!reference && subrip_or_dcp_subs == 1); - - ContentList sel = _parent->selected (); - _reference->Enable (sel.size() == 1 && dynamic_pointer_cast (sel.front ())); } void diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index c1afdd369..f91d2937f 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -168,6 +168,7 @@ Timeline::assign_tracks () } shared_ptr content = cv->content(); + DCPTimePeriod content_period (content->position(), content->end()); int t = 0; while (true) { @@ -182,11 +183,7 @@ Timeline::assign_tracks () shared_ptr test_content = test->content(); if (test && test->track() && test->track().get() == t) { - bool const no_overlap = - (content->position() < test_content->position() && content->end() < test_content->position()) || - (content->position() > test_content->end() && content->end() > test_content->end()); - - if (!no_overlap) { + if (content_period.overlaps (DCPTimePeriod(test_content->position(), test_content->end()))) { /* we have an overlap on track `t' */ ++t; break; @@ -367,7 +364,7 @@ Timeline::set_position_from_event (wxMouseEvent& ev) if (_snap) { - DCPTime const new_end = new_position + _down_view->content()->length_after_trim () - DCPTime (1); + DCPTime const new_end = new_position + _down_view->content()->length_after_trim(); /* Signed `distance' to nearest thing (i.e. negative is left on the timeline, positive is right). */ @@ -381,9 +378,9 @@ Timeline::set_position_from_event (wxMouseEvent& ev) } maybe_snap (cv->content()->position(), new_position, nearest_distance); - maybe_snap (cv->content()->position(), new_end + DCPTime (1), nearest_distance); - maybe_snap (cv->content()->end() + DCPTime (1), new_position, nearest_distance); - maybe_snap (cv->content()->end() + DCPTime (1), new_end, nearest_distance); + maybe_snap (cv->content()->position(), new_end, nearest_distance); + maybe_snap (cv->content()->end(), new_position, nearest_distance); + maybe_snap (cv->content()->end(), new_end, nearest_distance); } if (nearest_distance) { diff --git a/src/wx/video_panel.cc b/src/wx/video_panel.cc index dd9bb5848..79ea9dbfa 100644 --- a/src/wx/video_panel.cc +++ b/src/wx/video_panel.cc @@ -246,6 +246,8 @@ VideoPanel::film_changed (Film::Property property) case Film::RESOLUTION: setup_description (); break; + case Film::REEL_TYPE: + setup_sensitivity (); default: break; } @@ -434,7 +436,24 @@ void VideoPanel::setup_sensitivity () { ContentList sel = _parent->selected (); - _reference->Enable (sel.size() == 1 && dynamic_pointer_cast (sel.front ())); + + shared_ptr dcp; + if (sel.size() == 1) { + dcp = dynamic_pointer_cast (sel.front ()); + } + + list why_not; + bool const can_reference = dcp && dcp->can_reference_video(why_not); + _reference->Enable (can_reference); + + wxString s; + if (!can_reference) { + s = _("Cannot reference this DCP. "); + BOOST_FOREACH (string i, why_not) { + s += std_to_wx(i) + wxT(" "); + } + } + _reference->SetToolTip (s); if (_reference->GetValue ()) { _frame_type->wrapped()->Enable (false); diff --git a/test/fft.py b/test/fft.py new file mode 100644 index 000000000..bc6509f6c --- /dev/null +++ b/test/fft.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +from pylab import * +import numpy + +f = open('build/test/lpf_ir') +ir = [] +while True: + l = f.readline() + if l == "": + break + + ir.append(float(l.strip())) + +#plot(abs(numpy.fft.fft(ir))) +plot(ir) +show() diff --git a/test/reels_test.cc b/test/reels_test.cc new file mode 100644 index 000000000..85a9d07a9 --- /dev/null +++ b/test/reels_test.cc @@ -0,0 +1,141 @@ +/* + Copyright (C) 2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "lib/film.h" +#include "lib/ratio.h" +#include "lib/ffmpeg_content.h" +#include "lib/image_content.h" +#include "lib/dcp_content_type.h" +#include "lib/dcp_content.h" +#include "test.h" +#include + +using std::list; +using boost::shared_ptr; + +/** Test Film::reels() */ +BOOST_AUTO_TEST_CASE (reels_test1) +{ + shared_ptr film = new_test_film ("reels_test1"); + film->set_container (Ratio::from_id ("185")); + shared_ptr A (new FFmpegContent (film, "test/data/test.mp4")); + film->examine_and_add_content (A); + shared_ptr B (new FFmpegContent (film, "test/data/test.mp4")); + film->examine_and_add_content (B); + wait_for_jobs (); + BOOST_CHECK_EQUAL (A->full_length(), DCPTime (288000)); + + film->set_reel_type (REELTYPE_SINGLE); + list r = film->reels (); + BOOST_CHECK_EQUAL (r.size(), 1); + BOOST_CHECK_EQUAL (r.front().from, DCPTime (0)); + BOOST_CHECK_EQUAL (r.front().to, DCPTime (288000 * 2)); + + film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT); + r = film->reels (); + BOOST_CHECK_EQUAL (r.size(), 2); + BOOST_CHECK_EQUAL (r.front().from, DCPTime (0)); + BOOST_CHECK_EQUAL (r.front().to, DCPTime (288000)); + BOOST_CHECK_EQUAL (r.back().from, DCPTime (288000)); + BOOST_CHECK_EQUAL (r.back().to, DCPTime (288000 * 2)); + + film->set_j2k_bandwidth (100000000); + film->set_reel_type (REELTYPE_BY_LENGTH); + /* This is just over 2.5s at 100Mbit/s; should correspond to 60 frames */ + film->set_reel_length (31253154); + r = film->reels (); + BOOST_CHECK_EQUAL (r.size(), 3); + list::const_iterator i = r.begin (); + BOOST_CHECK_EQUAL (i->from, DCPTime (0)); + BOOST_CHECK_EQUAL (i->to, DCPTime::from_frames (60, 24)); + ++i; + BOOST_CHECK_EQUAL (i->from, DCPTime::from_frames (60, 24)); + BOOST_CHECK_EQUAL (i->to, DCPTime::from_frames (120, 24)); + ++i; + BOOST_CHECK_EQUAL (i->from, DCPTime::from_frames (120, 24)); + BOOST_CHECK_EQUAL (i->to, DCPTime::from_frames (144, 24)); +} + +/** Make a short DCP with multi reels split by video content, then import + * this into a new project and make a new DCP referencing it. + */ +BOOST_AUTO_TEST_CASE (reels_test2) +{ + shared_ptr film = new_test_film ("reels_test2"); + film->set_name ("reels_test2"); + film->set_container (Ratio::from_id ("185")); + film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test")); + + { + shared_ptr c (new ImageContent (film, "test/data/flat_red.png")); + film->examine_and_add_content (c); + wait_for_jobs (); + c->set_video_length (24); + } + + { + shared_ptr c (new ImageContent (film, "test/data/flat_green.png")); + film->examine_and_add_content (c); + wait_for_jobs (); + c->set_video_length (24); + } + + { + shared_ptr c (new ImageContent (film, "test/data/flat_blue.png")); + film->examine_and_add_content (c); + wait_for_jobs (); + c->set_video_length (24); + } + + film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT); + wait_for_jobs (); + + film->make_dcp (); + wait_for_jobs (); + + check_dcp ("test/data/reels_test2", film->dir (film->dcp_name())); + + shared_ptr film2 = new_test_film ("reels_test3"); + film2->set_name ("reels_test3"); + film2->set_container (Ratio::from_id ("185")); + film2->set_dcp_content_type (DCPContentType::from_pretty_name ("Test")); + film2->set_reel_type (REELTYPE_BY_VIDEO_CONTENT); + + shared_ptr c (new DCPContent (film2, film->dir (film->dcp_name ()))); + film2->examine_and_add_content (c); + wait_for_jobs (); + + list r = film2->reels (); + BOOST_CHECK_EQUAL (r.size(), 3); + list::const_iterator i = r.begin (); + BOOST_CHECK_EQUAL (i->from, DCPTime (0)); + BOOST_CHECK_EQUAL (i->to, DCPTime (96000)); + ++i; + BOOST_CHECK_EQUAL (i->from, DCPTime (96000)); + BOOST_CHECK_EQUAL (i->to, DCPTime (96000 * 2)); + ++i; + BOOST_CHECK_EQUAL (i->from, DCPTime (96000 * 2)); + BOOST_CHECK_EQUAL (i->to, DCPTime (96000 * 3)); + + c->set_reference_video (true); + c->set_reference_audio (true); + + film2->make_dcp (); + wait_for_jobs (); +} diff --git a/test/vf_test.cc b/test/vf_test.cc new file mode 100644 index 000000000..904f1d559 --- /dev/null +++ b/test/vf_test.cc @@ -0,0 +1,66 @@ +/* + Copyright (C) 2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "lib/film.h" +#include "lib/dcp_content.h" +#include "lib/ffmpeg_content.h" +#include "test.h" +#include + +using std::list; +using std::string; +using boost::shared_ptr; + +/** Test the logic which decides whether a DCP can be referenced or not */ +BOOST_AUTO_TEST_CASE (vf_test1) +{ + shared_ptr film = new_test_film ("vf_test1"); + shared_ptr dcp (new DCPContent (film, "test/data/reels_test2")); + film->examine_and_add_content (dcp); + wait_for_jobs (); + + /* Multi-reel DCP can't be referenced if we are using a single reel for the project */ + film->set_reel_type (REELTYPE_SINGLE); + list why_not; + BOOST_CHECK (!dcp->can_reference_video(why_not)); + BOOST_CHECK (!dcp->can_reference_audio(why_not)); + BOOST_CHECK (!dcp->can_reference_subtitle(why_not)); + + /* Multi-reel DCP can be referenced if we are using by-video-content */ + film->set_reel_type (REELTYPE_BY_VIDEO_CONTENT); + BOOST_CHECK (dcp->can_reference_video(why_not)); + BOOST_CHECK (dcp->can_reference_audio(why_not)); + BOOST_CHECK (dcp->can_reference_subtitle(why_not)); + + shared_ptr other (new FFmpegContent (film, "test/data/test.mp4")); + film->examine_and_add_content (other); + wait_for_jobs (); + + /* Not possible if there is overlap */ + other->set_position (DCPTime (0)); + BOOST_CHECK (!dcp->can_reference_video(why_not)); + BOOST_CHECK (!dcp->can_reference_audio(why_not)); + BOOST_CHECK (!dcp->can_reference_subtitle(why_not)); + + /* This should not be considered an overlap */ + other->set_position (dcp->end ()); + BOOST_CHECK (dcp->can_reference_video(why_not)); + BOOST_CHECK (dcp->can_reference_audio(why_not)); + BOOST_CHECK (dcp->can_reference_subtitle(why_not)); +} diff --git a/test/wscript b/test/wscript index 89f84e836..5cbc327e1 100644 --- a/test/wscript +++ b/test/wscript @@ -85,6 +85,7 @@ def build(bld): update_checker_test.cc upmixer_a_test.cc util_test.cc + vf_test.cc video_content_scale_test.cc video_decoder_fill_test.cc xml_subtitle_test.cc -- 2.30.2