[vlc-devel] [PATCH 2/9] Add transform helper functions.
Rémi Denis-Courmont
remi at remlab.net
Wed Mar 5 18:12:29 CET 2014
Le mercredi 5 mars 2014, 17:01:23 Matthias Keiser a écrit :
> ---
> include/vlc_es.h | 48 +++++++++++++
> src/misc/es_format.c | 196
> +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 244
> insertions(+)
>
> diff --git a/include/vlc_es.h b/include/vlc_es.h
> index 38d63da..d7e43e7 100644
> --- a/include/vlc_es.h
> +++ b/include/vlc_es.h
> @@ -153,6 +153,8 @@ typedef enum video_orientation_t
> ORIENT_RIGHT_BOTTOM, /**< Anti-transposed */
>
> ORIENT_NORMAL = ORIENT_TOP_LEFT,
> + ORIENT_TRANSPOSED = ORIENT_LEFT_TOP,
> + ORIENT_ANTI_TRANSPOSED = ORIENT_RIGHT_BOTTOM,
> ORIENT_HFLIPPED = ORIENT_TOP_RIGHT,
> ORIENT_VFLIPPED = ORIENT_BOTTOM_LEFT,
> ORIENT_ROTATED_180 = ORIENT_BOTTOM_RIGHT,
> @@ -174,6 +176,18 @@ typedef enum video_orientation_t
> /** Applies horizontal flip to an orientation */
> #define ORIENT_ROTATE_180(orient) ((orient) ^ 3)
>
> +typedef enum video_transform_t
> +{
> + TRANSFORM_IDENTIY = 0,
> + TRANSFORM_HFLIP,
> + TRANSFORM_VFLIP,
> + TRANSFORM_R90,
> + TRANSFORM_R180,
> + TRANSFORM_R270,
> + TRANSFORM_TRANSPOSE,
> + TRANSFORM_ANTI_TRANSPOSE
> +} video_transform_t;
> +
I don't understand why you need a second identical enumeration.
> /**
> * video format description
> */
> @@ -265,6 +279,28 @@ VLC_API void video_format_CopyCrop( video_format_t *,
> const video_format_t * ); VLC_API void video_format_ScaleCropAr(
> video_format_t *, const video_format_t * );
>
> /**
> + * This function "normalizes" the formats orientation, by switching the a/r
> according to the orientation, + * producing a format whose orientation is
> ORIENT_NORMAL. It makes a shallow copy (pallette is not alloc'ed). + */
> +VLC_API void video_format_ApplyRotation(const video_format_t * restrict in,
> video_format_t * restrict out); +
> +/**
> + * This function applies the transform operation to fmt.
> + */
> +VLC_API void video_format_TransformBy(video_format_t *fmt,
> video_transform_t transform); +
> +/**
> + * This function applies the transforms necessary to fmt so that the
> resulting fmt + * has the dst_orientation.
> + */
> +VLC_API void video_format_TransformTo(video_format_t *fmt,
> video_orientation_t dst_orientation); +
> +/**
> + * Returns the operation required to transform src into dst.
> + */
> +VLC_API video_transform_t orientation_GetTransform(video_orientation_t src,
> video_orientation_t dst);
Please do not add to the existing shared object prefix namespace pollution.
> +
> +/**
> * This function will check if the first video format is similar
> * to the second one.
> */
> @@ -275,6 +311,18 @@ VLC_API bool video_format_IsSimilar( const
> video_format_t *, const video_format_ */
> VLC_API void video_format_Print( vlc_object_t *, const char *, const
> video_format_t * );
>
> +
> +static inline video_transform_t transform_Inverse( video_transform_t
> transform ) +{
> + switch ( transform ) {
> + case TRANSFORM_R90:
> + return TRANSFORM_R270;
> + case TRANSFORM_R270:
> + return TRANSFORM_R90;
> + default:
> + return transform;
> + }
> +}
> /**
> * subtitles format description
> */
> diff --git a/src/misc/es_format.c b/src/misc/es_format.c
> index 8936414..101974b 100644
> --- a/src/misc/es_format.c
> +++ b/src/misc/es_format.c
> @@ -244,6 +244,202 @@ void video_format_ScaleCropAr( video_format_t *p_dst,
> const video_format_t *p_sr p_dst->i_sar_num, p_dst->i_sar_den, 65536);
> }
>
> +//Simplify transforms to have something more managable. Order: angle,
> hflip. +void transform_GetBasicOps( video_transform_t transform, int
> *angle, int *hflip ) { +
> + *angle = 0;
> + *hflip = 0;
> +
> + switch ( transform ) {
> +
> + case TRANSFORM_R90:
> + *angle = 90;
> + break;
> + case TRANSFORM_R180:
> + *angle = 180;
> + break;
> + case TRANSFORM_R270:
> + *angle = 270;
> + break;
> + case TRANSFORM_HFLIP:
> + *hflip = 1;
> + break;
> + case TRANSFORM_VFLIP:
> + *angle = 180;
> + *hflip = 1;
> + break;
> + case TRANSFORM_TRANSPOSE:
> + *angle = 90;
> + *hflip = 1;
> + break;
> + case TRANSFORM_ANTI_TRANSPOSE:
> + *angle = 270;
> + *hflip = 1;
> + break;
> + }
> +}
> +
> +video_transform_t transform_FromBasicOps( int angle, int hflip )
> +{
> + switch ( angle ) {
> + case 0:
> + return hflip ? TRANSFORM_HFLIP : TRANSFORM_IDENTIY;
> + case 90:
> + return hflip ? TRANSFORM_TRANSPOSE : TRANSFORM_R90;
> + case 180:
> + return hflip ? TRANSFORM_VFLIP : TRANSFORM_R180;
> + case 270:
> + return hflip ? TRANSFORM_ANTI_TRANSPOSE : TRANSFORM_R270;
> + default:
> + return TRANSFORM_IDENTIY;
> + }
> +}
> +
> +video_transform_t orientation_GetNormalTransform( video_orientation_t
> orient ) +{
> + switch( orient ) {
> +
> + case ORIENT_ROTATED_90:
> + return TRANSFORM_R90;
> + case ORIENT_ROTATED_180:
> + return TRANSFORM_R180;
> + case ORIENT_ROTATED_270:
> + return TRANSFORM_R270;
> + case ORIENT_HFLIPPED:
> + return TRANSFORM_HFLIP;
> + case ORIENT_VFLIPPED:
> + return TRANSFORM_VFLIP;
> + case ORIENT_TRANSPOSED:
> + return TRANSFORM_TRANSPOSE;
> + case ORIENT_ANTI_TRANSPOSED:
> + return TRANSFORM_ANTI_TRANSPOSE;
> + default:
> + return TRANSFORM_IDENTIY;
> + }
> +}
> +
> +video_transform_t orientation_GetTransform( video_orientation_t src,
> video_orientation_t dst ) +{
> + int angle1 = 0;
> + int hflip1 = 0;
> +
> + transform_GetBasicOps( orientation_GetNormalTransform( src ), &angle1,
> &hflip1 ); +
> + int angle2 = 0;
> + int hflip2 = 0;
> +
> + transform_GetBasicOps( transform_Inverse(
> orientation_GetNormalTransform( dst )), &angle2, &hflip2 ); +
> + int angle = (angle1 + angle2) % 360;
> + int hflip = (hflip1 + hflip2) % 2;
> +
> + return transform_FromBasicOps(angle, hflip);
> +}
> +
> +void video_format_TransformTo( video_format_t *fmt, video_orientation_t
> dst_orientation ) +{
> + video_transform_t transform =
> orientation_GetTransform(fmt->orientation, dst_orientation); +
> + video_format_TransformBy(fmt, transform);
> +}
> +
> +void video_format_TransformBy( video_format_t *fmt, video_transform_t
> transform ) +{
> + /* Get destination orientation */
> +
> + int angle1 = 0;
> + int hflip1 = 0;
> +
> + transform_GetBasicOps( transform, &angle1, &hflip1 );
> +
> + int angle2 = 0;
> + int hflip2 = 0;
> +
> + transform_GetBasicOps( orientation_GetNormalTransform( fmt->orientation
> ), &angle2, &hflip2 ); +
> + int angle = (angle2 - angle1 + 360) % 360;
> + int hflip = (hflip2 - hflip1 + 2) % 2;
> +
> + video_orientation_t dst_orient = ORIENT_NORMAL;
> +
> + if( hflip ) {
> +
> + if( angle == 0 )
> + dst_orient = ORIENT_HFLIPPED;
> + else if( angle == 90 )
> + dst_orient = ORIENT_ANTI_TRANSPOSED;
> + else if( angle == 180 )
> + dst_orient = ORIENT_VFLIPPED;
> + else if( angle == 270 )
> + dst_orient = ORIENT_TRANSPOSED;
> + }
> + else {
> +
> + if( angle == 90 )
> + dst_orient = ORIENT_ROTATED_90;
> + else if( angle == 180 )
> + dst_orient = ORIENT_ROTATED_180;
> + else if( angle == 270 )
> + dst_orient = ORIENT_ROTATED_270;
> + }
> +
> + /* Apply transform */
> +
> + video_format_t scratch = *fmt;
> +
> + if( ORIENT_IS_SWAP( fmt->orientation ) != ORIENT_IS_SWAP( dst_orient ))
> { +
> + fmt->i_width = scratch.i_height;
> + fmt->i_visible_width = scratch.i_visible_height;
> + fmt->i_height = scratch.i_width;
> + fmt->i_visible_height = scratch.i_visible_width;
> + fmt->i_sar_num = scratch.i_sar_den;
> + fmt->i_sar_den = scratch.i_sar_num;
> + }
> +
> + unsigned int delta_y = scratch.i_height - scratch.i_visible_height -
> scratch.i_y_offset; + unsigned int delta_x = scratch.i_width -
> scratch.i_visible_width - scratch.i_x_offset; +
> + switch ( transform )
> + {
> + case TRANSFORM_R90:
> + fmt->i_x_offset = delta_y;
> + fmt->i_y_offset = scratch.i_x_offset;
> + break;
> + case TRANSFORM_R180:
> + fmt->i_x_offset = delta_x;
> + fmt->i_y_offset = delta_y;
> + break;
> + case TRANSFORM_R270:
> + fmt->i_x_offset = scratch.i_y_offset;
> + fmt->i_y_offset = delta_x;
> + break;
> + case TRANSFORM_HFLIP:
> + fmt->i_x_offset = delta_x;
> + break;
> + case TRANSFORM_VFLIP:
> + fmt->i_y_offset = delta_y;
> + break;
> + case TRANSFORM_TRANSPOSE:
> + fmt->i_x_offset = scratch.i_y_offset;
> + fmt->i_y_offset = scratch.i_x_offset;
> + break;
> + case TRANSFORM_ANTI_TRANSPOSE:
> + fmt->i_x_offset = delta_y;
> + fmt->i_y_offset = delta_x;
> + break;
> + }
> +
> + fmt->orientation = dst_orient;
> +}
> +
> +void video_format_ApplyRotation( const video_format_t * restrict in,
> video_format_t * restrict out ) +{
> + *out = *in;
> +
> + video_format_TransformTo(out, ORIENT_NORMAL);
> +}
> +
> bool video_format_IsSimilar( const video_format_t *p_fmt1, const
> video_format_t *p_fmt2 ) {
> video_format_t v1 = *p_fmt1;
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list