Supporters update.
[dcpomatic.git] / src / lib / referenced_reel_asset.cc
1 /*
2     Copyright (C) 2015 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 #include "dcp_content.h"
23 #include "dcp_decoder.h"
24 #include "dcpomatic_assert.h"
25 #include "film.h"
26 #include "playlist.h"
27 #include "referenced_reel_asset.h"
28 #include <dcp/reel.h>
29 #include <dcp/reel_asset.h>
30 #include <dcp/reel_closed_caption_asset.h>
31 #include <dcp/reel_picture_asset.h>
32 #include <dcp/reel_sound_asset.h>
33 #include <dcp/reel_subtitle_asset.h>
34 #include <cmath>
35
36
37 using std::list;
38 using std::max;
39 using std::min;
40 using std::shared_ptr;
41 using boost::dynamic_pointer_cast;
42 using boost::scoped_ptr;
43 using namespace dcpomatic;
44
45
46 static void
47 maybe_add_asset (list<ReferencedReelAsset>& a, shared_ptr<dcp::ReelAsset> r, Frame reel_trim_start, Frame reel_trim_end, DCPTime from, int const ffr)
48 {
49         DCPOMATIC_ASSERT (r);
50         r->set_entry_point (r->entry_point().get_value_or(0) + reel_trim_start);
51         r->set_duration (r->actual_duration() - reel_trim_start - reel_trim_end);
52         if (r->actual_duration() > 0) {
53                 a.push_back (
54                         ReferencedReelAsset(r, DCPTimePeriod(from, from + DCPTime::from_frames(r->actual_duration(), ffr)))
55                         );
56         }
57 }
58
59
60
61 /** @return Details of all the DCP assets in a playlist that are marked to refer to */
62 list<ReferencedReelAsset>
63 get_referenced_reel_assets(shared_ptr<const Film> film, shared_ptr<const Playlist> playlist)
64 {
65         list<ReferencedReelAsset> reel_assets;
66
67         for (auto content: playlist->content()) {
68                 auto dcp = dynamic_pointer_cast<DCPContent>(content);
69                 if (!dcp) {
70                         continue;
71                 }
72
73                 if (!dcp->reference_video() && !dcp->reference_audio() && !dcp->reference_text(TextType::OPEN_SUBTITLE) && !dcp->reference_text(TextType::CLOSED_CAPTION)) {
74                         continue;
75                 }
76
77                 scoped_ptr<DCPDecoder> decoder;
78                 try {
79                         decoder.reset(new DCPDecoder(film, dcp, false, false, shared_ptr<DCPDecoder>()));
80                 } catch (...) {
81                         return reel_assets;
82                 }
83
84                 auto const frame_rate = film->video_frame_rate();
85                 DCPOMATIC_ASSERT (dcp->video_frame_rate());
86                 /* We should only be referencing if the DCP rate is the same as the film rate */
87                 DCPOMATIC_ASSERT (std::round(dcp->video_frame_rate().get()) == frame_rate);
88
89                 Frame const trim_start = dcp->trim_start().frames_round(frame_rate);
90                 Frame const trim_end = dcp->trim_end().frames_round(frame_rate);
91
92                 /* position in the asset from the start */
93                 int64_t offset_from_start = 0;
94                 /* position i the asset from the end */
95                 int64_t offset_from_end = 0;
96                 for (auto reel: decoder->reels()) {
97                         /* Assume that main picture duration is the length of the reel */
98                         offset_from_end += reel->main_picture()->actual_duration();
99                 }
100
101                 for (auto reel: decoder->reels()) {
102
103                         /* Assume that main picture duration is the length of the reel */
104                         int64_t const reel_duration = reel->main_picture()->actual_duration();
105
106                         /* See doc/design/trim_reels.svg */
107                         Frame const reel_trim_start = min(reel_duration, max(int64_t(0), trim_start - offset_from_start));
108                         Frame const reel_trim_end =   min(reel_duration, max(int64_t(0), reel_duration - (offset_from_end - trim_end)));
109
110                         auto const from = content->position() + std::max(DCPTime(), DCPTime::from_frames(offset_from_start - trim_start, frame_rate));
111                         if (dcp->reference_video()) {
112                                 maybe_add_asset (reel_assets, reel->main_picture(), reel_trim_start, reel_trim_end, from, frame_rate);
113                         }
114
115                         if (dcp->reference_audio()) {
116                                 maybe_add_asset (reel_assets, reel->main_sound(), reel_trim_start, reel_trim_end, from, frame_rate);
117                         }
118
119                         if (dcp->reference_text(TextType::OPEN_SUBTITLE)) {
120                                 maybe_add_asset (reel_assets, reel->main_subtitle(), reel_trim_start, reel_trim_end, from, frame_rate);
121                         }
122
123                         if (dcp->reference_text(TextType::CLOSED_CAPTION)) {
124                                 for (auto caption: reel->closed_captions()) {
125                                         maybe_add_asset (reel_assets, caption, reel_trim_start, reel_trim_end, from, frame_rate);
126                                 }
127                         }
128
129                         offset_from_start += reel_duration;
130                         offset_from_end -= reel_duration;
131                 }
132         }
133
134         return reel_assets;
135 }
136