Commit 43bc581e authored by Thibault Saunier's avatar Thibault Saunier

assets: Take into account media files rotation information

And make sure that rotation is applied to proxies.
Remove `ThumbnailBin` as we are not using it at all.

Fixes #2317
parent 390b6951
......@@ -341,22 +341,6 @@ def require_version(modulename, version):
exit(1)
def get_square_width(video_info):
"""Applies the pixel aspect ratio to the width of the video info.
Args:
video_info (GstPbutils.DiscovererVideoInfo): The video info.
Returns:
int: The width calculated exactly as GStreamer does.
"""
width = video_info.get_width()
par_num = video_info.get_par_num()
par_denom = video_info.get_par_denom()
# We observed GStreamer does a simple int(), so we leave it like this.
return int(width * par_num / par_denom)
def initialize_modules():
"""Initializes the modules.
......@@ -393,10 +377,13 @@ def initialize_modules():
require_version("GstPbutils", GST_API_VERSION)
from gi.repository import GstPbutils
from pitivi.utils.misc import video_info_get_natural_height, video_info_get_natural_width, video_info_get_rotation
# Monky patch a helper method for retrieving the size of a video
# when using square pixels.
GstPbutils.DiscovererVideoInfo.get_square_width = get_square_width
GstPbutils.DiscovererVideoInfo.get_natural_width = video_info_get_natural_width
GstPbutils.DiscovererVideoInfo.get_natural_height = video_info_get_natural_height
GstPbutils.DiscovererVideoInfo.get_rotation = video_info_get_rotation
if not os.environ.get("GES_DISCOVERY_TIMEOUT"):
os.environ["GES_DISCOVERY_TIMEOUT"] = "5"
......
......@@ -82,8 +82,8 @@ class ClipMediaPropsDialog(object):
break
for stream in self.video_streams:
self.size_width.set_text(str(stream.get_square_width()))
self.size_height.set_text(str(stream.get_height()))
self.size_width.set_text(str(stream.get_natural_width()))
self.size_height.set_text(str(stream.get_natural_height()))
self.is_image = stream.is_image()
if not self.is_image:
num = stream.get_framerate_num()
......@@ -138,8 +138,8 @@ class ClipMediaPropsDialog(object):
# This also handles the case where the video is a still image
video = self.video_streams[0]
if self.size_checkbutton.get_active():
project.videowidth = video.get_square_width()
project.videoheight = video.get_height()
project.videowidth = video.get_natural_width()
project.videoheight = video.get_natural_height()
if self.framerate_checkbutton.get_active() and not self.is_image:
project.videorate = Gst.Fraction(video.get_framerate_num(),
video.get_framerate_denom())
......
......@@ -840,8 +840,8 @@ class PreviewAssetWindow(Gtk.Window):
# For videos and images, automatically resize the window
# Try to keep it 1:1 if it can fit within 85% of the parent window
video = video_streams[0]
img_width = video.get_square_width()
img_height = video.get_height()
img_width = video.get_natural_width()
img_height = video.get_natural_height()
mainwindow_width, mainwindow_height = self.app.gui.get_size()
max_width = 0.85 * mainwindow_width
max_height = 0.85 * mainwindow_height
......
......@@ -256,8 +256,8 @@ class PreviewWidget(Gtk.Grid, Loggable):
self.player.uri = self.current_selected_uri
self.player.setState(Gst.State.PAUSED)
self.pos_adj.props.upper = duration
video_width = video.get_square_width()
video_height = video.get_height()
video_width = video.get_natural_width()
video_height = video.get_natural_height()
w, h = self.__get_best_size(video_width, video_height)
self.preview_video.set_size_request(w, h)
self.preview_video.props.ratio = video_width / video_height
......
......@@ -1884,8 +1884,8 @@ class Project(Loggable, GES.Project):
if video_streams and self._has_default_video_settings:
video = video_streams[0]
if not video.is_image():
self.videowidth = video.get_square_width()
self.videoheight = video.get_height()
self.videowidth = video.get_natural_width()
self.videoheight = video.get_natural_height()
if video.get_framerate_num() > 0:
# The asset has a non-variable framerate.
self.videorate = Gst.Fraction(video.get_framerate_num(),
......
......@@ -898,8 +898,8 @@ class VideoSource(TimelineElement):
video_source = self._ges_elem
sinfo = video_source.get_asset().get_stream_info()
asset_width = sinfo.get_square_width()
asset_height = sinfo.get_height()
asset_width = sinfo.get_natural_width()
asset_height = sinfo.get_natural_height()
parent = video_source.get_parent()
if parent and not self.__videoflip:
for track_element in parent.find_track_elements(
......@@ -918,8 +918,8 @@ class VideoSource(TimelineElement):
res, method = self.__videoflip.get_child_property("method")
assert res
if "clockwise" in method.value_nick and self.__videoflip.props.active:
asset_width = sinfo.get_height()
asset_height = sinfo.get_square_width()
asset_width = sinfo.get_natural_height()
asset_height = sinfo.get_natural_width()
# Find the biggest size of the video inside the
# final view (project size) keeping the aspect ratio
......
......@@ -94,7 +94,7 @@ class PreviewerBin(Gst.Bin, Loggable):
"""Finalizes the previewer, saving data to the disk if needed."""
class ThumbnailBin(PreviewerBin):
class TeedThumbnailBin(PreviewerBin):
"""Bin to generate and save thumbnails to an SQLite database."""
__gproperties__ = {
......@@ -105,12 +105,13 @@ class ThumbnailBin(PreviewerBin):
GObject.ParamFlags.READWRITE),
}
def __init__(self, bin_desc="videoconvert ! videorate ! "
"videoscale method=lanczos ! "
"capsfilter caps=video/x-raw,format=(string)RGBA,"
"height=(int)%d,pixel-aspect-ratio=(fraction)1/1,"
"framerate=2/1 ! gdkpixbufsink name=gdkpixbufsink " %
THUMB_HEIGHT):
def __init__(self, bin_desc="videoconvert ! videoflip method=automatic ! tee name=t ! queue "
"max-size-buffers=0 max-size-bytes=0 max-size-time=0 ! "
"videoconvert ! videorate ! videoscale method=lanczos ! "
"capsfilter caps=video/x-raw,format=(string)RGBA,height=(int)%d,"
"pixel-aspect-ratio=(fraction)1/1,"
"framerate=2/1 ! gdkpixbufsink name=gdkpixbufsink "
"t. ! queue " % THUMB_HEIGHT):
PreviewerBin.__init__(self, bin_desc)
self.uri = None
......@@ -156,20 +157,6 @@ class ThumbnailBin(PreviewerBin):
raise AttributeError('unknown property %s' % prop.name)
class TeedThumbnailBin(ThumbnailBin):
"""Bin to generate and save thumbnails to an SQLite database."""
def __init__(self):
ThumbnailBin.__init__(
self, bin_desc="tee name=t ! queue "
"max-size-buffers=0 max-size-bytes=0 max-size-time=0 ! "
"videoconvert ! videorate ! videoscale method=lanczos ! "
"capsfilter caps=video/x-raw,format=(string)RGBA,height=(int)%d,"
"pixel-aspect-ratio=(fraction)1/1,"
"framerate=2/1 ! gdkpixbufsink name=gdkpixbufsink "
"t. ! queue " % THUMB_HEIGHT)
# pylint: disable=too-many-instance-attributes
class WaveformPreviewer(PreviewerBin):
"""Bin to generate and save waveforms as a .npy file."""
......@@ -290,8 +277,6 @@ class WaveformPreviewer(PreviewerBin):
Gst.Element.register(None, "waveformbin", Gst.Rank.NONE,
WaveformPreviewer)
Gst.Element.register(None, "thumbnailbin", Gst.Rank.NONE,
ThumbnailBin)
Gst.Element.register(None, "teedthumbnailbin", Gst.Rank.NONE,
TeedThumbnailBin)
......@@ -620,6 +605,7 @@ class AssetPreviewer(Previewer, Loggable):
"uridecodebin uri={uri} name=decode ! "
"videoconvert ! "
"videorate ! "
"videoflip method=automatic ! "
"videoscale method=lanczos ! "
"capsfilter caps=video/x-raw,format=(string)RGBA,height=(int){height},"
"pixel-aspect-ratio=(fraction)1/1,framerate={thumbs_per_second}/1 ! "
......
......@@ -409,3 +409,65 @@ def fixate_caps_with_default_values(template, restrictions, default_values,
res = res.fixate()
log.debug("utils", "Fixated %s", res)
return res
# GstDiscovererInfo helpers
def _get_square_width(video_info):
width = video_info.get_width()
par_num = video_info.get_par_num()
par_denom = video_info.get_par_denom()
# We observed GStreamer does a simple int(), so we leave it like this.
return int(width * par_num / par_denom)
def video_info_get_rotation(video_info):
tags = video_info.get_tags()
if not tags:
return 0
is_rotated, rotation_string = tags.get_string(Gst.TAG_IMAGE_ORIENTATION)
if is_rotated:
try:
return int(rotation_string.replace('rotate-', ''))
except ValueError as e:
log.error("utils", "Did not understand orientation: %s (%s)", rotation_string, e)
return 0
return 0
def video_info_get_natural_width(video_info):
"""Applies the pixel aspect ratio and rotation information
to the width of the video info.
Args:
video_info (GstPbutils.DiscovererVideoInfo): The video info.
Returns:
int: The width calculated exactly as GStreamer does.
"""
rotation = video_info.get_rotation()
if rotation in [90, 270]:
width = video_info.get_height()
par_num = video_info.get_par_num()
par_denom = video_info.get_par_denom()
# We observed GStreamer does a simple int(), so we leave it like this.
return int(width * par_num / par_denom)
return _get_square_width(video_info)
def video_info_get_natural_height(video_info):
"""Applies the rotation information to the height of the video.
Args:
video_info (GstPbutils.DiscovererVideoInfo): The video info.
Returns:
int: The height calculated exactly as GStreamer does.
"""
rotation = video_info.get_rotation()
if rotation in [90, 270]:
return _get_square_width(video_info)
return video_info.get_height()
\ No newline at end of file
......@@ -505,8 +505,8 @@ def beautify_stream(stream):
elif type(stream) is DiscovererVideoInfo:
par = stream.get_par_num() / stream.get_par_denom()
width = stream.get_width()
height = stream.get_height()
width = stream.get_natural_width()
height = stream.get_natural_height()
if not stream.is_image():
fps = format_framerate_value(stream)
templ = _("<b>Video:</b> %%d <i>pixels</i> at %s <i>fps</i>")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment