summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2019-05-24 23:29:39 +0100
committerCarl Hetherington <cth@carlh.net>2019-05-24 23:29:39 +0100
commit92784c9c28c48859578cd6e75aa01d5657d0c341 (patch)
tree595a34ecd2c59bf9d3dbcfa0c6f0a91b17ecfa5b /src/lib
parent6c78f6d31a457ad34fb14b7c926fb418b4d6790d (diff)
Basic ability to set video range (JPEG/MPEG) at least for YUV content. May not work for RGB. See #1509.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/dcp_examiner.h4
-rw-r--r--src/lib/ffmpeg_examiner.cc13
-rw-r--r--src/lib/ffmpeg_examiner.h2
-rw-r--r--src/lib/image.cc6
-rw-r--r--src/lib/image.h2
-rw-r--r--src/lib/image_examiner.h3
-rw-r--r--src/lib/player.cc2
-rw-r--r--src/lib/player_video.cc13
-rw-r--r--src/lib/player_video.h4
-rw-r--r--src/lib/types.h6
-rw-r--r--src/lib/video_content.cc25
-rw-r--r--src/lib/video_content.h11
-rw-r--r--src/lib/video_examiner.h1
-rw-r--r--src/lib/video_mxf_examiner.h3
14 files changed, 83 insertions, 12 deletions
diff --git a/src/lib/dcp_examiner.h b/src/lib/dcp_examiner.h
index 199ac3985..da9092411 100644
--- a/src/lib/dcp_examiner.h
+++ b/src/lib/dcp_examiner.h
@@ -55,6 +55,10 @@ public:
return false;
}
+ VideoRange range () const {
+ return VIDEO_RANGE_FULL;
+ }
+
std::string name () const {
return _name;
}
diff --git a/src/lib/ffmpeg_examiner.cc b/src/lib/ffmpeg_examiner.cc
index a4c5eb128..3fb9a53e4 100644
--- a/src/lib/ffmpeg_examiner.cc
+++ b/src/lib/ffmpeg_examiner.cc
@@ -388,3 +388,16 @@ FFmpegExaminer::has_video () const
{
return static_cast<bool> (_video_stream);
}
+
+VideoRange
+FFmpegExaminer::range () const
+{
+ switch (color_range()) {
+ case AVCOL_RANGE_MPEG:
+ case AVCOL_RANGE_UNSPECIFIED:
+ return VIDEO_RANGE_VIDEO;
+ case AVCOL_RANGE_JPEG:
+ default:
+ return VIDEO_RANGE_FULL;
+ }
+}
diff --git a/src/lib/ffmpeg_examiner.h b/src/lib/ffmpeg_examiner.h
index 1c0dad3dc..9ffb8421b 100644
--- a/src/lib/ffmpeg_examiner.h
+++ b/src/lib/ffmpeg_examiner.h
@@ -53,6 +53,8 @@ public:
return _first_video;
}
+ VideoRange range () const;
+
AVColorRange color_range () const {
return video_codec_context()->color_range;
}
diff --git a/src/lib/image.cc b/src/lib/image.cc
index c176c2d65..b473403e4 100644
--- a/src/lib/image.cc
+++ b/src/lib/image.cc
@@ -129,7 +129,7 @@ Image::planes () const
*/
shared_ptr<Image>
Image::crop_scale_window (
- Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool out_aligned, bool fast
+ Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, VideoRange video_range, AVPixelFormat out_format, bool out_aligned, bool fast
) const
{
/* Empirical testing suggests that sws_scale() will crash if
@@ -198,8 +198,8 @@ Image::crop_scale_window (
*/
sws_setColorspaceDetails (
scale_context,
- sws_getCoefficients (lut[yuv_to_rgb]), 0,
- sws_getCoefficients (lut[yuv_to_rgb]), 0,
+ sws_getCoefficients (lut[yuv_to_rgb]), video_range == VIDEO_RANGE_VIDEO ? 0 : 1,
+ sws_getCoefficients (lut[yuv_to_rgb]), 1,
0, 1 << 16, 1 << 16
);
diff --git a/src/lib/image.h b/src/lib/image.h
index dbcb38cc7..4b059ff36 100644
--- a/src/lib/image.h
+++ b/src/lib/image.h
@@ -63,7 +63,7 @@ public:
boost::shared_ptr<Image> convert_pixel_format (dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool aligned, bool fast) const;
boost::shared_ptr<Image> scale (dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool aligned, bool fast) const;
boost::shared_ptr<Image> crop_scale_window (
- Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, AVPixelFormat out_format, bool aligned, bool fast
+ Crop crop, dcp::Size inter_size, dcp::Size out_size, dcp::YUVToRGB yuv_to_rgb, VideoRange video_range, AVPixelFormat out_format, bool aligned, bool fast
) const;
void make_black ();
diff --git a/src/lib/image_examiner.h b/src/lib/image_examiner.h
index 2e743a82e..ca8ecf9c8 100644
--- a/src/lib/image_examiner.h
+++ b/src/lib/image_examiner.h
@@ -36,6 +36,9 @@ public:
return _video_length;
}
bool yuv () const;
+ VideoRange range () const {
+ return VIDEO_RANGE_FULL;
+ }
private:
boost::weak_ptr<const Film> _film;
diff --git a/src/lib/player.cc b/src/lib/player.cc
index e44edd8dc..f79e379d2 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -332,6 +332,7 @@ Player::black_player_video_frame (Eyes eyes) const
eyes,
PART_WHOLE,
PresetColourConversion::all().front().conversion,
+ VIDEO_RANGE_FULL,
boost::weak_ptr<Content>(),
boost::optional<Frame>()
)
@@ -826,6 +827,7 @@ Player::video (weak_ptr<Piece> wp, ContentVideo video)
video.eyes,
video.part,
piece->content->video->colour_conversion(),
+ piece->content->video->range(),
piece->content,
video.frame
)
diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc
index e36eb1984..75479136f 100644
--- a/src/lib/player_video.cc
+++ b/src/lib/player_video.cc
@@ -52,6 +52,7 @@ PlayerVideo::PlayerVideo (
Eyes eyes,
Part part,
optional<ColourConversion> colour_conversion,
+ VideoRange video_range,
weak_ptr<Content> content,
optional<Frame> video_frame
)
@@ -63,6 +64,7 @@ PlayerVideo::PlayerVideo (
, _eyes (eyes)
, _part (part)
, _colour_conversion (colour_conversion)
+ , _video_range (video_range)
, _content (content)
, _video_frame (video_frame)
{
@@ -78,6 +80,7 @@ PlayerVideo::PlayerVideo (shared_ptr<cxml::Node> node, shared_ptr<Socket> socket
_out_size = dcp::Size (node->number_child<int> ("OutWidth"), node->number_child<int> ("OutHeight"));
_eyes = (Eyes) node->number_child<int> ("Eyes");
_part = (Part) node->number_child<int> ("Part");
+ _video_range = (VideoRange) node->number_child<int>("VideoRange");
/* Assume that the ColourConversion uses the current state version */
_colour_conversion = ColourConversion::from_xml (node, Film::current_state_version);
@@ -166,7 +169,7 @@ PlayerVideo::make_image (function<AVPixelFormat (AVPixelFormat)> pixel_format, b
}
_image = im->crop_scale_window (
- total_crop, _inter_size, _out_size, yuv_to_rgb, pixel_format (im->pixel_format()), aligned, fast
+ total_crop, _inter_size, _out_size, yuv_to_rgb, _video_range, pixel_format (im->pixel_format()), aligned, fast
);
if (_text) {
@@ -192,6 +195,7 @@ PlayerVideo::add_metadata (xmlpp::Node* node) const
node->add_child("OutHeight")->add_child_text (raw_convert<string> (_out_size.height));
node->add_child("Eyes")->add_child_text (raw_convert<string> (static_cast<int> (_eyes)));
node->add_child("Part")->add_child_text (raw_convert<string> (static_cast<int> (_part)));
+ node->add_child("VideoRange")->add_child_text(raw_convert<string>(static_cast<int>(_video_range)));
if (_colour_conversion) {
_colour_conversion.get().as_xml (node);
}
@@ -249,7 +253,8 @@ PlayerVideo::same (shared_ptr<const PlayerVideo> other) const
_out_size != other->_out_size ||
_eyes != other->_eyes ||
_part != other->_part ||
- _colour_conversion != other->_colour_conversion) {
+ _colour_conversion != other->_colour_conversion ||
+ _video_range != other->_video_range) {
return false;
}
@@ -310,13 +315,14 @@ PlayerVideo::shallow_copy () const
_eyes,
_part,
_colour_conversion,
+ _video_range,
_content,
_video_frame
)
);
}
-/** Re-read crop, fade, inter/out size and colour conversion from our content.
+/** Re-read crop, fade, inter/out size, colour conversion and video range from our content.
* @return true if this was possible, false if not.
*/
bool
@@ -332,6 +338,7 @@ PlayerVideo::reset_metadata (shared_ptr<const Film> film, dcp::Size video_contai
_inter_size = content->video->scale().size(content->video, video_container_size, film_frame_size);
_out_size = video_container_size;
_colour_conversion = content->video->colour_conversion();
+ _video_range = content->video->range();
return true;
}
diff --git a/src/lib/player_video.h b/src/lib/player_video.h
index c38d60641..3cd559409 100644
--- a/src/lib/player_video.h
+++ b/src/lib/player_video.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -54,6 +54,7 @@ public:
Eyes,
Part,
boost::optional<ColourConversion>,
+ VideoRange video_range,
boost::weak_ptr<Content>,
boost::optional<Frame>
);
@@ -117,6 +118,7 @@ private:
Eyes _eyes;
Part _part;
boost::optional<ColourConversion> _colour_conversion;
+ VideoRange _video_range;
boost::optional<PositionImage> _text;
/** Content that we came from. This is so that reset_metadata() can work, and also
* for variant:swaroop's non-skippable ads.
diff --git a/src/lib/types.h b/src/lib/types.h
index 94e101a3d..c9f68a21c 100644
--- a/src/lib/types.h
+++ b/src/lib/types.h
@@ -136,6 +136,12 @@ enum ChangeType
CHANGE_TYPE_CANCELLED
};
+enum VideoRange
+{
+ VIDEO_RANGE_FULL, ///< full, or "JPEG" (0-255 for 8-bit)
+ VIDEO_RANGE_VIDEO ///< video, or "MPEG" (16-235 for 8-bit)
+};
+
/** Type of captions.
*
* The generally accepted definitions seem to be:
diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc
index d8d8adbf8..4eda7d967 100644
--- a/src/lib/video_content.cc
+++ b/src/lib/video_content.cc
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -46,6 +46,7 @@ int const VideoContentProperty::SCALE = 3;
int const VideoContentProperty::COLOUR_CONVERSION = 4;
int const VideoContentProperty::FADE_IN = 5;
int const VideoContentProperty::FADE_OUT = 6;
+int const VideoContentProperty::RANGE = 7;
using std::string;
using std::setprecision;
@@ -71,6 +72,7 @@ VideoContent::VideoContent (Content* parent)
, _yuv (true)
, _fade_in (0)
, _fade_out (0)
+ , _range (VIDEO_RANGE_FULL)
{
}
@@ -152,6 +154,11 @@ VideoContent::VideoContent (Content* parent, cxml::ConstNodePtr node, int versio
} else {
_fade_in = _fade_out = 0;
}
+
+ _range = VIDEO_RANGE_FULL;
+ if (node->optional_string_child("Range").get_value_or("full") == "video") {
+ _range = VIDEO_RANGE_VIDEO;
+ }
}
VideoContent::VideoContent (Content* parent, vector<shared_ptr<Content> > c)
@@ -202,6 +209,7 @@ VideoContent::VideoContent (Content* parent, vector<shared_ptr<Content> > c)
_colour_conversion = ref->colour_conversion ();
_fade_in = ref->fade_in ();
_fade_out = ref->fade_out ();
+ _range = ref->range ();
}
void
@@ -223,6 +231,7 @@ VideoContent::as_xml (xmlpp::Node* node) const
node->add_child("YUV")->add_child_text (_yuv ? "1" : "0");
node->add_child("FadeIn")->add_child_text (raw_convert<string> (_fade_in));
node->add_child("FadeOut")->add_child_text (raw_convert<string> (_fade_out));
+ node->add_child("Range")->add_child_text(_range == VIDEO_RANGE_FULL ? "full" : "video");
}
void
@@ -233,10 +242,12 @@ VideoContent::take_from_examiner (shared_ptr<VideoExaminer> d)
Frame vl = d->video_length ();
optional<double> const ar = d->sample_aspect_ratio ();
bool const yuv = d->yuv ();
+ VideoRange const range = d->range ();
ChangeSignaller<Content> cc1 (_parent, VideoContentProperty::SIZE);
ChangeSignaller<Content> cc2 (_parent, VideoContentProperty::SCALE);
ChangeSignaller<Content> cc3 (_parent, ContentProperty::LENGTH);
+ ChangeSignaller<Content> cc4 (_parent, VideoContentProperty::RANGE);
{
boost::mutex::scoped_lock lm (_mutex);
@@ -244,6 +255,7 @@ VideoContent::take_from_examiner (shared_ptr<VideoExaminer> d)
_length = vl;
_sample_aspect_ratio = ar;
_yuv = yuv;
+ _range = range;
if (Config::instance()->default_scale_to ()) {
_scale = VideoContentScale (Config::instance()->default_scale_to ());
@@ -268,14 +280,15 @@ VideoContent::identifier () const
{
char buffer[256];
snprintf (
- buffer, sizeof(buffer), "%d_%d_%d_%d_%s_%" PRId64 "_%" PRId64,
+ buffer, sizeof(buffer), "%d_%d_%d_%d_%s_%" PRId64 "_%" PRId64 "_%d",
crop().left,
crop().right,
crop().top,
crop().bottom,
scale().id().c_str(),
_fade_in,
- _fade_out
+ _fade_out,
+ _range == VIDEO_RANGE_FULL ? 0 : 1
);
string s (buffer);
@@ -526,6 +539,12 @@ VideoContent::set_fade_out (Frame t)
}
void
+VideoContent::set_range (VideoRange r)
+{
+ maybe_set (_range, r, VideoContentProperty::RANGE);
+}
+
+void
VideoContent::take_settings_from (shared_ptr<const VideoContent> c)
{
if (c->_colour_conversion) {
diff --git a/src/lib/video_content.h b/src/lib/video_content.h
index 3d07a0947..f5fb6c9ac 100644
--- a/src/lib/video_content.h
+++ b/src/lib/video_content.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
@@ -46,6 +46,7 @@ public:
static int const COLOUR_CONVERSION;
static int const FADE_IN;
static int const FADE_OUT;
+ static int const RANGE;
};
class VideoContent : public ContentPart, public boost::enable_shared_from_this<VideoContent>
@@ -92,6 +93,8 @@ public:
void set_fade_in (Frame);
void set_fade_out (Frame);
+ void set_range (VideoRange);
+
VideoFrameType frame_type () const {
boost::mutex::scoped_lock lm (_mutex);
return _frame_type;
@@ -153,6 +156,11 @@ public:
return _fade_out;
}
+ VideoRange range () const {
+ boost::mutex::scoped_lock lm (_mutex);
+ return _range;
+ }
+
dcp::Size size_after_3d_split () const;
dcp::Size size_after_crop () const;
@@ -194,6 +202,7 @@ private:
bool _yuv;
Frame _fade_in;
Frame _fade_out;
+ VideoRange _range;
};
#endif
diff --git a/src/lib/video_examiner.h b/src/lib/video_examiner.h
index dd5d08c9e..4e5c6dc0a 100644
--- a/src/lib/video_examiner.h
+++ b/src/lib/video_examiner.h
@@ -48,4 +48,5 @@ public:
}
/** @return true if this video is in YUV; must not be called if has_video() == false */
virtual bool yuv () const = 0;
+ virtual VideoRange range () const = 0;
};
diff --git a/src/lib/video_mxf_examiner.h b/src/lib/video_mxf_examiner.h
index 205daa361..ec2933c27 100644
--- a/src/lib/video_mxf_examiner.h
+++ b/src/lib/video_mxf_examiner.h
@@ -39,6 +39,9 @@ public:
Frame video_length () const;
boost::optional<double> sample_aspect_ratio () const;
bool yuv () const;
+ VideoRange range () const {
+ return VIDEO_RANGE_FULL;
+ }
private:
boost::shared_ptr<dcp::PictureAsset> _asset;