You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	avfilter/vf_rotate: add >8 bit depth support
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
		| @@ -60,7 +60,7 @@ enum var_name { | ||||
|     VAR_VARS_NB | ||||
| }; | ||||
|  | ||||
| typedef struct { | ||||
| typedef struct RotContext { | ||||
|     const AVClass *class; | ||||
|     double angle; | ||||
|     char *angle_expr_str;   ///< expression for the angle | ||||
| @@ -77,6 +77,9 @@ typedef struct { | ||||
|     double var_values[VAR_VARS_NB]; | ||||
|     FFDrawContext draw; | ||||
|     FFDrawColor color; | ||||
|     uint8_t *(*interpolate_bilinear)(uint8_t *dst_color, | ||||
|                                     const uint8_t *src, int src_linesize, int src_linestep, | ||||
|                                     int x, int y, int max_x, int max_y); | ||||
| } RotContext; | ||||
|  | ||||
| typedef struct ThreadData { | ||||
| @@ -142,6 +145,14 @@ static int query_formats(AVFilterContext *ctx) | ||||
|         AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUVJ444P, | ||||
|         AV_PIX_FMT_YUV420P,  AV_PIX_FMT_YUVJ420P, | ||||
|         AV_PIX_FMT_YUVA444P, AV_PIX_FMT_YUVA420P, | ||||
|         AV_PIX_FMT_YUV420P10LE, AV_PIX_FMT_YUVA420P10LE, | ||||
|         AV_PIX_FMT_YUV444P10LE, AV_PIX_FMT_YUVA444P10LE, | ||||
|         AV_PIX_FMT_YUV420P12LE, | ||||
|         AV_PIX_FMT_YUV444P12LE, | ||||
|         AV_PIX_FMT_YUV444P16LE, AV_PIX_FMT_YUVA444P16LE, | ||||
|         AV_PIX_FMT_YUV420P16LE, AV_PIX_FMT_YUVA420P16LE, | ||||
|         AV_PIX_FMT_YUV444P9LE, AV_PIX_FMT_YUVA444P9LE, | ||||
|         AV_PIX_FMT_YUV420P9LE, AV_PIX_FMT_YUVA420P9LE, | ||||
|         AV_PIX_FMT_NONE | ||||
|     }; | ||||
|  | ||||
| @@ -187,6 +198,93 @@ static const char * const func1_names[] = { | ||||
|     NULL | ||||
| }; | ||||
|  | ||||
| #define FIXP (1<<16) | ||||
| #define FIXP2 (1<<20) | ||||
| #define INT_PI 3294199 //(M_PI * FIXP2) | ||||
|  | ||||
| /** | ||||
|  * Compute the sin of a using integer values. | ||||
|  * Input is scaled by FIXP2 and output values are scaled by FIXP. | ||||
|  */ | ||||
| static int64_t int_sin(int64_t a) | ||||
| { | ||||
|     int64_t a2, res = 0; | ||||
|     int i; | ||||
|     if (a < 0) a = INT_PI-a; // 0..inf | ||||
|     a %= 2 * INT_PI;         // 0..2PI | ||||
|  | ||||
|     if (a >= INT_PI*3/2) a -= 2*INT_PI;  // -PI/2 .. 3PI/2 | ||||
|     if (a >= INT_PI/2  ) a = INT_PI - a; // -PI/2 ..  PI/2 | ||||
|  | ||||
|     /* compute sin using Taylor series approximated to the fifth term */ | ||||
|     a2 = (a*a)/(FIXP2); | ||||
|     for (i = 2; i < 11; i += 2) { | ||||
|         res += a; | ||||
|         a = -a*a2 / (FIXP2*i*(i+1)); | ||||
|     } | ||||
|     return (res + 8)>>4; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Interpolate the color in src at position x and y using bilinear | ||||
|  * interpolation. | ||||
|  */ | ||||
| static uint8_t *interpolate_bilinear8(uint8_t *dst_color, | ||||
|                                       const uint8_t *src, int src_linesize, int src_linestep, | ||||
|                                       int x, int y, int max_x, int max_y) | ||||
| { | ||||
|     int int_x = av_clip(x>>16, 0, max_x); | ||||
|     int int_y = av_clip(y>>16, 0, max_y); | ||||
|     int frac_x = x&0xFFFF; | ||||
|     int frac_y = y&0xFFFF; | ||||
|     int i; | ||||
|     int int_x1 = FFMIN(int_x+1, max_x); | ||||
|     int int_y1 = FFMIN(int_y+1, max_y); | ||||
|  | ||||
|     for (i = 0; i < src_linestep; i++) { | ||||
|         int s00 = src[src_linestep * int_x  + i + src_linesize * int_y ]; | ||||
|         int s01 = src[src_linestep * int_x1 + i + src_linesize * int_y ]; | ||||
|         int s10 = src[src_linestep * int_x  + i + src_linesize * int_y1]; | ||||
|         int s11 = src[src_linestep * int_x1 + i + src_linesize * int_y1]; | ||||
|         int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01); | ||||
|         int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11); | ||||
|  | ||||
|         dst_color[i] = ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32; | ||||
|     } | ||||
|  | ||||
|     return dst_color; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Interpolate the color in src at position x and y using bilinear | ||||
|  * interpolation. | ||||
|  */ | ||||
| static uint8_t *interpolate_bilinear16(uint8_t *dst_color, | ||||
|                                        const uint8_t *src, int src_linesize, int src_linestep, | ||||
|                                        int x, int y, int max_x, int max_y) | ||||
| { | ||||
|     int int_x = av_clip(x>>16, 0, max_x); | ||||
|     int int_y = av_clip(y>>16, 0, max_y); | ||||
|     int frac_x = x&0xFFFF; | ||||
|     int frac_y = y&0xFFFF; | ||||
|     int i; | ||||
|     int int_x1 = FFMIN(int_x+1, max_x); | ||||
|     int int_y1 = FFMIN(int_y+1, max_y); | ||||
|  | ||||
|     for (i = 0; i < src_linestep; i+=2) { | ||||
|         int s00 = AV_RL16(&src[src_linestep * int_x  + i + src_linesize * int_y ]); | ||||
|         int s01 = AV_RL16(&src[src_linestep * int_x1 + i + src_linesize * int_y ]); | ||||
|         int s10 = AV_RL16(&src[src_linestep * int_x  + i + src_linesize * int_y1]); | ||||
|         int s11 = AV_RL16(&src[src_linestep * int_x1 + i + src_linesize * int_y1]); | ||||
|         int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01); | ||||
|         int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11); | ||||
|  | ||||
|         AV_WL16(&dst_color[i], ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32); | ||||
|     } | ||||
|  | ||||
|     return dst_color; | ||||
| } | ||||
|  | ||||
| static int config_props(AVFilterLink *outlink) | ||||
| { | ||||
|     AVFilterContext *ctx = outlink->src; | ||||
| @@ -203,6 +301,11 @@ static int config_props(AVFilterLink *outlink) | ||||
|     rot->hsub = pixdesc->log2_chroma_w; | ||||
|     rot->vsub = pixdesc->log2_chroma_h; | ||||
|  | ||||
|     if (pixdesc->comp[0].depth == 8) | ||||
|         rot->interpolate_bilinear = interpolate_bilinear8; | ||||
|     else | ||||
|         rot->interpolate_bilinear = interpolate_bilinear16; | ||||
|  | ||||
|     rot->var_values[VAR_IN_W] = rot->var_values[VAR_IW] = inlink->w; | ||||
|     rot->var_values[VAR_IN_H] = rot->var_values[VAR_IH] = inlink->h; | ||||
|     rot->var_values[VAR_HSUB] = 1<<rot->hsub; | ||||
| @@ -255,63 +358,6 @@ static int config_props(AVFilterLink *outlink) | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| #define FIXP (1<<16) | ||||
| #define FIXP2 (1<<20) | ||||
| #define INT_PI 3294199 //(M_PI * FIXP2) | ||||
|  | ||||
| /** | ||||
|  * Compute the sin of a using integer values. | ||||
|  * Input is scaled by FIXP2 and output values are scaled by FIXP. | ||||
|  */ | ||||
| static int64_t int_sin(int64_t a) | ||||
| { | ||||
|     int64_t a2, res = 0; | ||||
|     int i; | ||||
|     if (a < 0) a = INT_PI-a; // 0..inf | ||||
|     a %= 2 * INT_PI;         // 0..2PI | ||||
|  | ||||
|     if (a >= INT_PI*3/2) a -= 2*INT_PI;  // -PI/2 .. 3PI/2 | ||||
|     if (a >= INT_PI/2  ) a = INT_PI - a; // -PI/2 ..  PI/2 | ||||
|  | ||||
|     /* compute sin using Taylor series approximated to the fifth term */ | ||||
|     a2 = (a*a)/(FIXP2); | ||||
|     for (i = 2; i < 11; i += 2) { | ||||
|         res += a; | ||||
|         a = -a*a2 / (FIXP2*i*(i+1)); | ||||
|     } | ||||
|     return (res + 8)>>4; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Interpolate the color in src at position x and y using bilinear | ||||
|  * interpolation. | ||||
|  */ | ||||
| static uint8_t *interpolate_bilinear(uint8_t *dst_color, | ||||
|                                      const uint8_t *src, int src_linesize, int src_linestep, | ||||
|                                      int x, int y, int max_x, int max_y) | ||||
| { | ||||
|     int int_x = av_clip(x>>16, 0, max_x); | ||||
|     int int_y = av_clip(y>>16, 0, max_y); | ||||
|     int frac_x = x&0xFFFF; | ||||
|     int frac_y = y&0xFFFF; | ||||
|     int i; | ||||
|     int int_x1 = FFMIN(int_x+1, max_x); | ||||
|     int int_y1 = FFMIN(int_y+1, max_y); | ||||
|  | ||||
|     for (i = 0; i < src_linestep; i++) { | ||||
|         int s00 = src[src_linestep * int_x  + i + src_linesize * int_y ]; | ||||
|         int s01 = src[src_linestep * int_x1 + i + src_linesize * int_y ]; | ||||
|         int s10 = src[src_linestep * int_x  + i + src_linesize * int_y1]; | ||||
|         int s11 = src[src_linestep * int_x1 + i + src_linesize * int_y1]; | ||||
|         int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01); | ||||
|         int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11); | ||||
|  | ||||
|         dst_color[i] = ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*s1) >> 32; | ||||
|     } | ||||
|  | ||||
|     return dst_color; | ||||
| } | ||||
|  | ||||
| static av_always_inline void copy_elem(uint8_t *pout, const uint8_t *pin, int elem_size) | ||||
| { | ||||
|     int v; | ||||
| @@ -421,9 +467,9 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) | ||||
|                 uint8_t inp_inv[4]; /* interpolated input value */ | ||||
|                 pout = out->data[plane] + j * out->linesize[plane] + i * rot->draw.pixelstep[plane]; | ||||
|                 if (rot->use_bilinear) { | ||||
|                     pin = interpolate_bilinear(inp_inv, | ||||
|                                                in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane], | ||||
|                                                x, y, inw-1, inh-1); | ||||
|                     pin = rot->interpolate_bilinear(inp_inv, | ||||
|                                                     in->data[plane], in->linesize[plane], rot->draw.pixelstep[plane], | ||||
|                                                     x, y, inw-1, inh-1); | ||||
|                 } else { | ||||
|                     int x2 = av_clip(x1, 0, inw-1); | ||||
|                     int y2 = av_clip(y1, 0, inh-1); | ||||
| @@ -434,7 +480,8 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs) | ||||
|                     *pout = *pin; | ||||
|                     break; | ||||
|                 case 2: | ||||
|                     *((uint16_t *)pout) = *((uint16_t *)pin); | ||||
|                     v = AV_RL16(pin); | ||||
|                     AV_WL16(pout, v); | ||||
|                     break; | ||||
|                 case 3: | ||||
|                     v = AV_RB24(pin); | ||||
|   | ||||
| @@ -13,8 +13,22 @@ rgb24               f4438057d046e6d98ade4e45294b21be | ||||
| rgba                b6e1b441c365e03b5ffdf9b7b68d9a0c | ||||
| yuv410p             5d4d992a7728431aa4e0700f87fb7fd8 | ||||
| yuv420p             a014c7eb7a8385d1dd092b7a583f1bff | ||||
| yuv420p10le         15c83294ef560d57f25d16ae6e0fc70c | ||||
| yuv420p12le         c19a477a07fcf88e37ab37b416d064c0 | ||||
| yuv420p16le         dae8da9edd4255051e3e546ae7ed9bd3 | ||||
| yuv420p9le          83a6d32c91c15a3bc334bb9abf920654 | ||||
| yuv444p             8f90fb3a757878c545a8bfe5d19a9bab | ||||
| yuv444p10le         6d736fa464ff2de2b07e0a56af8444b7 | ||||
| yuv444p12le         08a81b2ea9c7c8b447e40ef8f4a46a4a | ||||
| yuv444p16le         781c22317c02b3dd4225709000bdb847 | ||||
| yuv444p9le          caef947b8aff5b52285385c6ae9b2439 | ||||
| yuva420p            b227672e56215e184e702c02a771d7f3 | ||||
| yuva420p10le        01e94ee605714396e69b013c11dda348 | ||||
| yuva420p16le        b1930ab28ffe031c78ca28d3406311c8 | ||||
| yuva420p9le         0e9c9803aaaddc9f38e419de587793c2 | ||||
| yuva444p            459fad5abfd16db9bb6a52761dc74cc1 | ||||
| yuva444p10le        92f820d3481b7ebcb48b98a73e7b4c90 | ||||
| yuva444p16le        2ed56ea50fafda4d226c9b133755dad8 | ||||
| yuva444p9le         4eeb5988df0740fea720da1e31bbb829 | ||||
| yuvj420p            8f3d8f1b4577d11082d5ab8a901e048d | ||||
| yuvj444p            b161e6d5a941e2a4bb7bc56ef8af623f | ||||
|   | ||||
		Reference in New Issue
	
	Block a user