[pitivi] assets: Take into account media files rotation information
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] assets: Take into account media files rotation information
- Date: Tue, 13 Aug 2019 22:01:48 +0000 (UTC)
commit 43bc581efaae224bb3de8f814df57a5d02134bbb
Author: Thibault Saunier <tsaunier igalia com>
Date: Fri Aug 9 10:59:06 2019 -0400
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 https://gitlab.gnome.org/GNOME/pitivi/issues/2317
pitivi/check.py | 21 +++-----------
pitivi/dialogs/clipmediaprops.py | 8 +++---
pitivi/editorperspective.py | 4 +--
pitivi/mediafilespreviewer.py | 4 +--
pitivi/project.py | 4 +--
pitivi/timeline/elements.py | 8 +++---
pitivi/timeline/previewers.py | 32 ++++++---------------
pitivi/utils/misc.py | 62 ++++++++++++++++++++++++++++++++++++++++
pitivi/utils/ui.py | 4 +--
9 files changed, 91 insertions(+), 56 deletions(-)
---
diff --git a/pitivi/check.py b/pitivi/check.py
index 9765e480..f45e2471 100644
--- a/pitivi/check.py
+++ b/pitivi/check.py
@@ -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"
diff --git a/pitivi/dialogs/clipmediaprops.py b/pitivi/dialogs/clipmediaprops.py
index d929338f..da8fb1f9 100644
--- a/pitivi/dialogs/clipmediaprops.py
+++ b/pitivi/dialogs/clipmediaprops.py
@@ -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())
diff --git a/pitivi/editorperspective.py b/pitivi/editorperspective.py
index 3a630bb5..0ff72c30 100644
--- a/pitivi/editorperspective.py
+++ b/pitivi/editorperspective.py
@@ -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
diff --git a/pitivi/mediafilespreviewer.py b/pitivi/mediafilespreviewer.py
index da463860..4218540e 100644
--- a/pitivi/mediafilespreviewer.py
+++ b/pitivi/mediafilespreviewer.py
@@ -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
diff --git a/pitivi/project.py b/pitivi/project.py
index 6cceefd7..e6b7993f 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -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(),
diff --git a/pitivi/timeline/elements.py b/pitivi/timeline/elements.py
index 073f63eb..0b5de8fd 100644
--- a/pitivi/timeline/elements.py
+++ b/pitivi/timeline/elements.py
@@ -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
diff --git a/pitivi/timeline/previewers.py b/pitivi/timeline/previewers.py
index 1b87069c..56c21425 100644
--- a/pitivi/timeline/previewers.py
+++ b/pitivi/timeline/previewers.py
@@ -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 ! "
diff --git a/pitivi/utils/misc.py b/pitivi/utils/misc.py
index dc59bdc7..1368e1de 100644
--- a/pitivi/utils/misc.py
+++ b/pitivi/utils/misc.py
@@ -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
diff --git a/pitivi/utils/ui.py b/pitivi/utils/ui.py
index fe447b4f..fea22797 100644
--- a/pitivi/utils/ui.py
+++ b/pitivi/utils/ui.py
@@ -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×%d <i>pixels</i> at %s <i>fps</i>")
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]