Merge.
[dcpomatic.git] / src / lib / player_video_frame.cc
1 /*
2     Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <libdcp/raw_convert.h>
21 #include "player_video_frame.h"
22 #include "image.h"
23 #include "image_proxy.h"
24 #include "scaler.h"
25
26 using std::string;
27 using std::cout;
28 using boost::shared_ptr;
29 using libdcp::raw_convert;
30
31 PlayerVideoFrame::PlayerVideoFrame (
32         shared_ptr<const ImageProxy> in,
33         Crop crop,
34         libdcp::Size inter_size,
35         libdcp::Size out_size,
36         Scaler const * scaler,
37         Eyes eyes,
38         Part part,
39         ColourConversion colour_conversion
40         )
41         : _in (in)
42         , _crop (crop)
43         , _inter_size (inter_size)
44         , _out_size (out_size)
45         , _scaler (scaler)
46         , _eyes (eyes)
47         , _part (part)
48         , _colour_conversion (colour_conversion)
49 {
50
51 }
52
53 PlayerVideoFrame::PlayerVideoFrame (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket, shared_ptr<Log> log)
54 {
55         _crop = Crop (node);
56
57         _inter_size = libdcp::Size (node->number_child<int> ("InterWidth"), node->number_child<int> ("InterHeight"));
58         _out_size = libdcp::Size (node->number_child<int> ("OutWidth"), node->number_child<int> ("OutHeight"));
59         _scaler = Scaler::from_id (node->string_child ("Scaler"));
60         _eyes = (Eyes) node->number_child<int> ("Eyes");
61         _part = (Part) node->number_child<int> ("Part");
62         _colour_conversion = ColourConversion (node);
63
64         _in = image_proxy_factory (node->node_child ("In"), socket, log);
65
66         if (node->optional_number_child<int> ("SubtitleX")) {
67                 
68                 _subtitle_position = Position<int> (node->number_child<int> ("SubtitleX"), node->number_child<int> ("SubtitleY"));
69
70                 shared_ptr<Image> image (
71                         new Image (PIX_FMT_RGBA, libdcp::Size (node->number_child<int> ("SubtitleWidth"), node->number_child<int> ("SubtitleHeight")), true)
72                         );
73                 
74                 image->read_from_socket (socket);
75                 _subtitle_image = image;
76         }
77 }
78
79 void
80 PlayerVideoFrame::set_subtitle (shared_ptr<const Image> image, Position<int> pos)
81 {
82         _subtitle_image = image;
83         _subtitle_position = pos;
84 }
85
86 shared_ptr<Image>
87 PlayerVideoFrame::image () const
88 {
89         shared_ptr<Image> im = _in->image ();
90         
91         Crop total_crop = _crop;
92         switch (_part) {
93         case PART_LEFT_HALF:
94                 total_crop.right += im->size().width / 2;
95                 break;
96         case PART_RIGHT_HALF:
97                 total_crop.left += im->size().width / 2;
98                 break;
99         case PART_TOP_HALF:
100                 total_crop.bottom += im->size().height / 2;
101                 break;
102         case PART_BOTTOM_HALF:
103                 total_crop.top += im->size().height / 2;
104                 break;
105         default:
106                 break;
107         }
108                 
109         shared_ptr<Image> out = im->crop_scale_window (total_crop, _inter_size, _out_size, _scaler, PIX_FMT_RGB24, false);
110
111         Position<int> const container_offset ((_out_size.width - _inter_size.width) / 2, (_out_size.height - _inter_size.width) / 2);
112
113         if (_subtitle_image) {
114                 out->alpha_blend (_subtitle_image, _subtitle_position);
115         }
116
117         return out;
118 }
119
120 void
121 PlayerVideoFrame::add_metadata (xmlpp::Node* node) const
122 {
123         _crop.as_xml (node);
124         _in->add_metadata (node->add_child ("In"));
125         node->add_child("InterWidth")->add_child_text (raw_convert<string> (_inter_size.width));
126         node->add_child("InterHeight")->add_child_text (raw_convert<string> (_inter_size.height));
127         node->add_child("OutWidth")->add_child_text (raw_convert<string> (_out_size.width));
128         node->add_child("OutHeight")->add_child_text (raw_convert<string> (_out_size.height));
129         node->add_child("Scaler")->add_child_text (_scaler->id ());
130         node->add_child("Eyes")->add_child_text (raw_convert<string> (_eyes));
131         node->add_child("Part")->add_child_text (raw_convert<string> (_part));
132         _colour_conversion.as_xml (node);
133         if (_subtitle_image) {
134                 node->add_child ("SubtitleWidth")->add_child_text (raw_convert<string> (_subtitle_image->size().width));
135                 node->add_child ("SubtitleHeight")->add_child_text (raw_convert<string> (_subtitle_image->size().height));
136                 node->add_child ("SubtitleX")->add_child_text (raw_convert<string> (_subtitle_position.x));
137                 node->add_child ("SubtitleY")->add_child_text (raw_convert<string> (_subtitle_position.y));
138         }
139 }
140
141 void
142 PlayerVideoFrame::send_binary (shared_ptr<Socket> socket) const
143 {
144         _in->send_binary (socket);
145         if (_subtitle_image) {
146                 _subtitle_image->write_to_socket (socket);
147         }
148 }