vlc-video: Fix video rotation and aspect ratio

Fixes #5250 and #3843.
Gets dimensions, aspect ratio and orientation/rotation from source video track.
This commit is contained in:
Paul Mc Galey 2021-09-16 00:35:01 +01:00 committed by Jim
parent 8bd4ef61a0
commit 59bdac1569
3 changed files with 73 additions and 14 deletions

View File

@ -24,8 +24,10 @@ LIBVLC_MEDIA_NEW_PATH libvlc_media_new_path_;
LIBVLC_MEDIA_NEW_LOCATION libvlc_media_new_location_;
LIBVLC_MEDIA_ADD_OPTION libvlc_media_add_option_;
LIBVLC_MEDIA_RELEASE libvlc_media_release_;
LIBVLC_MEDIA_RELEASE libvlc_media_retain_;
LIBVLC_MEDIA_RETAIN libvlc_media_retain_;
LIBVLC_MEDIA_GET_META libvlc_media_get_meta_;
LIBVLC_MEDIA_TRACKS_GET libvlc_media_tracks_get_;
LIBVLC_MEDIA_TRACKS_RELEASE libvlc_media_tracks_release_;
/* libvlc media player */
LIBVLC_MEDIA_PLAYER_NEW libvlc_media_player_new_;
@ -104,6 +106,8 @@ static bool load_vlc_funcs(void)
LOAD_VLC_FUNC(libvlc_media_release);
LOAD_VLC_FUNC(libvlc_media_retain);
LOAD_VLC_FUNC(libvlc_media_get_meta);
LOAD_VLC_FUNC(libvlc_media_tracks_get);
LOAD_VLC_FUNC(libvlc_media_tracks_release);
/* libvlc media player */
LOAD_VLC_FUNC(libvlc_media_player_new);

View File

@ -38,6 +38,10 @@ typedef void (*LIBVLC_MEDIA_RETAIN)(libvlc_media_t *p_md);
typedef void (*LIBVLC_MEDIA_RELEASE)(libvlc_media_t *p_md);
typedef char *(*LIBVLC_MEDIA_GET_META)(libvlc_media_t *p_md,
libvlc_meta_t e_meta);
typedef unsigned (*LIBVLC_MEDIA_TRACKS_GET)(libvlc_media_t *p_md,
libvlc_media_track_t ***pp_es);
typedef void (*LIBVLC_MEDIA_TRACKS_RELEASE)(libvlc_media_track_t **p_tracks,
unsigned i_count);
/* libvlc media player */
typedef libvlc_media_player_t *(*LIBVLC_MEDIA_PLAYER_NEW)(
@ -125,6 +129,8 @@ extern LIBVLC_MEDIA_ADD_OPTION libvlc_media_add_option_;
extern LIBVLC_MEDIA_RELEASE libvlc_media_release_;
extern LIBVLC_MEDIA_RETAIN libvlc_media_retain_;
extern LIBVLC_MEDIA_GET_META libvlc_media_get_meta_;
extern LIBVLC_MEDIA_TRACKS_GET libvlc_media_tracks_get_;
extern LIBVLC_MEDIA_TRACKS_RELEASE libvlc_media_tracks_release_;
/* libvlc media player */
extern LIBVLC_MEDIA_PLAYER_NEW libvlc_media_player_new_;

View File

@ -382,6 +382,62 @@ static void vlcs_video_display(void *data, void *picture)
UNUSED_PARAMETER(picture);
}
static void calculate_display_size(struct vlc_source *c, unsigned *width,
unsigned *height)
{
libvlc_media_t *media = libvlc_media_player_get_media_(c->media_player);
if (!media)
return;
libvlc_media_track_t **tracks;
unsigned count = libvlc_media_tracks_get_(media, &tracks);
if (count > 0) {
for (unsigned i = 0; i < count; i++) {
libvlc_media_track_t *track = tracks[i];
if (track->i_type != libvlc_track_video)
continue;
int display_width = track->video->i_width;
int display_height = track->video->i_height;
if (display_width == 0 || display_height == 0)
continue;
/* Adjust for Sample Aspect Ratio (SAR) */
if (track->video->i_sar_num > 0 &&
track->video->i_sar_den > 0) {
display_width = display_width *
track->video->i_sar_num /
track->video->i_sar_den;
}
switch (track->video->i_orientation) {
case libvlc_video_orient_left_top:
case libvlc_video_orient_left_bottom:
case libvlc_video_orient_right_top:
case libvlc_video_orient_right_bottom:
/* orientation swaps height and width */
*width = display_height;
*height = display_width;
break;
default:
/* height and width not swapped */
*width = display_width;
*height = display_height;
break;
}
}
libvlc_media_tracks_release_(tracks, count);
}
libvlc_media_release_(media);
}
static unsigned vlcs_video_format(void **p_data, char *chroma, unsigned *width,
unsigned *height, unsigned *pitches,
unsigned *lines)
@ -396,19 +452,12 @@ static unsigned vlcs_video_format(void **p_data, char *chroma, unsigned *width,
new_format = convert_vlc_video_format(chroma, &new_range);
/* This is used because VLC will by default try to use a different
* scaling than what the file uses (probably for optimization reasons).
* For example, if the file is 1920x1080, it will try to render it by
* 1920x1088, which isn't what we want. Calling libvlc_video_get_size
* gets the actual video file's size, and thus fixes the problem.
* However this doesn't work with URLs, so if it returns a 0 value, it
* shouldn't be used. */
libvlc_video_get_size_(c->media_player, 0, &new_width, &new_height);
if (new_width && new_height) {
*width = new_width;
*height = new_height;
}
/* The width and height passed from VLC are the buffer size rather than
* the correct video display size, and may be the next multiple of 32
* up from the original dimension, e.g. 1080 would become 1088. VLC 4.0
* will pass the correct display size in *(width+1) and *(height+1) but
* for now we need to calculate it ourselves. */
calculate_display_size(c, width, height);
/* don't allocate a new frame if format/width/height hasn't changed */
if (c->frame.format != new_format || c->frame.width != *width ||