Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent dwidth,dheight with EXIF orientation and video-rotate=n #15476

Open
6 tasks done
bipface opened this issue Dec 9, 2024 · 14 comments
Open
6 tasks done

Inconsistent dwidth,dheight with EXIF orientation and video-rotate=n #15476

bipface opened this issue Dec 9, 2024 · 14 comments
Labels

Comments

@bipface
Copy link

bipface commented Dec 9, 2024

Edit: this initial report was written under the assumption that the 'source' of rotation was changing the way the dwidth/dheight values were calculated. However that turned out to be wrong — the real reason is whether the rotation angle is a multiple of 90.


mpv Information

mpv v0.39.0-465-gbaf52806 Copyright © 2000-2024 mpv/MPlayer/mplayer2 projects
 built on Dec  9 2024 12:06:47
libplacebo version: v7.350.0 (v7.349.0-30-g056b852-dirty)
FFmpeg version: N-118034-gd21134313
FFmpeg library versions:
   libavcodec      61.26.100
   libavdevice     61.4.100
   libavfilter     10.6.101
   libavformat     61.9.100
   libavutil       59.49.100
   libswresample   5.4.100
   libswscale      8.12.100

Other Information

- Windows version: 10.0.19045.3570
- GPU model, driver and version: RX 7800 XT, driver 23.20.23.01-231025a-397406C-AMD-Software-Adrenalin-Edition
- Source of mpv: <https://github.com/zhongfly/mpv-winbuild/releases>

The issue is essentially that video-out-params/dw|dh|rotate is calculated differently depending on whether --video-rotate=n is used, when the file also includes EXIF rotation.
There doesn't seem to be a way to reliably read the post-rotation unscaled video dimensions, irrespective of whether rotation originates from metadata, video-rotate or both.

Reproduction Steps

  • open a file with exif rotation (such as the included example Landscape_8.jpg):
mpv --no-config --loop-file=inf Landscape_8.jpg
  • open the mpv console and gather the relevant video-*-params values:
print-text "vdp/dw:${video-dec-params/dw} vdp/r:${video-dec-params/rotate}\nvp/dw:${video-params/dw} vp/r:${video-params/rotate}\nvop/dw:${video-out-params/dw} vop/r:${video-out-params/rotate}"
  • open the same file, this time with the video-rotate option:
mpv --no-config --loop-file=inf --video-rotate=1 Landscape_8.jpg
  • open the mpv console and gather the relevant video-*-params values:
print-text "vdp/dw:${video-dec-params/dw} vdp/r:${video-dec-params/rotate}\nvp/dw:${video-params/dw} vp/r:${video-params/rotate}\nvop/dw:${video-out-params/dw} vop/r:${video-out-params/rotate}"

Expected Behavior

At least one set of params should provide the total rotation amount and unscaled video dimensions (accounting for rotation).

Actual Behavior

with --video-rotate=0:

video-dec-params/dw: 1200, video-dec-params/rotate: 270
video-params/dw: 1200, video-params/rotate: 270
video-out-params/dw: 1200, video-out-params/rotate: 270

The rotation values are consistent but none of the width values take rotation into account.

with --video-rotate=1:

video-dec-params/dw: 1200, video-dec-params/rotate: 270
video-params/dw: 1200, video-params/rotate: 271
video-out-params/dw: 1821, video-out-params/rotate: 0

In video-out-params the width does account for rotation, however the rotate value is lost for some reason.

Log File

output.txt

Sample Files

Landscape_8

I carefully read all instruction and confirm that I did the following:

  • I tested with the latest mpv version to validate that the issue is not already fixed.
  • I provided all required information including system and mpv version.
  • I produced the log file with the exact same set of files, parameters, and conditions used in "Reproduction Steps", with the addition of --log-file=output.txt.
  • I produced the log file while the behaviors described in "Actual Behavior" were actively observed.
  • I attached the full, untruncated log file.
  • I attached the backtrace in the case of a crash.
@bipface bipface added the os:win label Dec 9, 2024
@kasper93
Copy link
Contributor

kasper93 commented Dec 9, 2024

Try with vo=gpu-next, I think indeed vo=gpu doesn't update rotate of video-out-params

EDIT: Also I think 0 rotation on video-out-params makes sense, because rotate params means how image should be rotated, but once it is rotated, there is no longer rotation metadata, just image dimensions.

@bipface
Copy link
Author

bipface commented Dec 10, 2024

no difference with gpu-next

@kasper93
Copy link
Contributor

In this case it is expected behavior, target video out is not rotated. Video was rotated during rendering.

@bipface
Copy link
Author

bipface commented Dec 10, 2024

I would like to point out that metadata-based rotation and 'manual' rotation are inherently coupled because of how the video-rotate option works:

  • video-rotate=no: ignore exif rotation, and no additional rotation.
  • video-rotate=0: apply exif rotation, and no additional rotation.
  • video-rotate=1-359: apply exif rotation, and rotate a further n degrees.

If I wanted to work-around the issue by reading the exif metadata and performing the arithmetic myself, I can't — there's no way to "ignore exif rotation, and rotate n degrees", unless I find a different means of achieving rotation. (Please correct me if I'm wrong).

This is why I believe it's important for the video-out-params values to be seamless regardless of how the rotation angle is determined.

@guidocella
Copy link
Contributor

The final image dimensions are in osd-dimensions. w - ml - mr is the width and h - mt - mb is the height.

@bipface
Copy link
Author

bipface commented Dec 10, 2024

The final image dimensions are in osd-dimensions. w - ml - mr is the width and h - mt - mb is the height.

osd-dimensions gives you the dimensions after scaling has been applied (i.e. video-zoom). video-out-params gives you dimensions after rotation but before scaling.

@kasper93
Copy link
Contributor

I would like to point out that metadata-based rotation and 'manual' rotation are inherently coupled because of how the video-rotate option works:

* `video-rotate=no`: ignore exif rotation, and no additional rotation.

* `video-rotate=0`: apply exif rotation, and no additional rotation.

* `video-rotate=1-359`: apply exif rotation, and rotate a further `n` degrees.

If I wanted to work-around the issue by reading the exif metadata and performing the arithmetic myself, I can't — there's no way to "ignore exif rotation, and rotate n degrees", unless I find a different means of achieving rotation. (Please correct me if I'm wrong).

You can set rotate value to negate any metadata rotation and arrive at your expected rotation.

You can also override rotation metadata with --vf=format=rotate=n, see https://mpv.io/manual/master/#video-filters-%3Crotate%3E

@bipface
Copy link
Author

bipface commented Dec 10, 2024

You can set rotate value to negate any metadata rotation and arrive at your expected rotation.

That only works in cases where I want a different angle than what is specified in metadata.

You can also override rotation metadata with --vf=format=rotate=n, see https://mpv.io/manual/master/#video-filters-%3Crotate%3E

I will check this out, thanks.

@kasper93
Copy link
Contributor

kasper93 commented Dec 10, 2024

At least one set of params should provide the total rotation amount

You can calculate it yourself by adding metadata and custom rotation.

and unscaled video dimensions (accounting for rotation).

It's not a separate step, unscaled rotated image doesn't exist and therefore there is no poperies like that. You can easily calculate it yourself.

@bipface
Copy link
Author

bipface commented Dec 10, 2024

are you implying that there's nothing wrong with the current behaviour?

@kasper93
Copy link
Contributor

kasper93 commented Dec 10, 2024

are you implying that there's nothing wrong with the current behaviour?

I'm not implying. I'm saying it is correct.

unrotated video with rotation metadata:

video-params/dw: 1200, video-params/rotate: 271

rotated video. width/height has been transformed according to rotate value, rotate value is now 0, because it was already applied to the video:

video-out-params/dw: 1821, video-out-params/rotate: 0

rotate metadata is saying how video should be displayed, not how it was rotated. Imagine you do rotation in filter, the value of rotate has to be updated so it is not applied again by next step in pipeline.

@bipface
Copy link
Author

bipface commented Dec 10, 2024

are you implying that there's nothing wrong with the current behaviour?

I'm not implying. I'm saying it is correct.

I strongly disagree, I think I've made a compelling case as to why the current behaviour isn't appropriate.
Even ignoring the /rotate values, the fact remains that video-out-params/dw|dh values may or may not take rotation into account depending on how the angle was determined. I suspect that any script using these params has a high risk of bugs unless it is aware of this particular edge-case.

@kasper93
Copy link
Contributor

kasper93 commented Dec 10, 2024

VO like gpu/gpu-next does support rotation only in 90 degrees steps. If rotation value is not a multiple of 90, the rotation filter will be inserted instead. That's why you see already rotated parameters in video-out-params.

The difference is where the rotation is applied, video-out-params are params after filtering, before the image is sent to VO. If video-out-params has rotate != 0 that's means it has not been rotated yet and will be during displaying the image. If video-out-params has rotate == 0 that means the video has been rotated or not, depending if video-params had rotation metadata.

In other words, if you want to see video params before and after rotate you can compare video-*-params. Note that last step video-target-params will always have rotate==0, because at this point it has been rotated fully, no matter what.

I suspect that any script using these params has a high risk of bugs unless it is aware of this particular edge-case.

I see where you coming from, but all information is there, on each step of processing. video-out-params directly says what video is injected into VO.

Could you reiterate what information do you need, we can think how to obtain it correctly for your use-case.

@bipface
Copy link
Author

bipface commented Dec 11, 2024

It seems I had the wrong impression: the issue has nothing to do with exif vs. video-rotate=, it's entirely about whether the angle is a multiple of 90, as you pointed out.

90° rotation being treated as a special case is somewhat understandable,
however I do still think it creates a minor pitfall with the video-out-params values.
Perhaps some kind of clarification or warning in the documentation would be enough to address this? Just something to make users aware that rotation may be performed in earlier or later stages of processing depending on whether the angle is a multiple of 90.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants