Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-29 Thread Jun Li
On Sat, Jun 29, 2019 at 12:07 AM Steven Liu  wrote:

>
>
> > 在 2019年6月26日,19:32,Steven Liu  写道:
> >
> > Jun Li  于2019年6月25日周二 上午9:26写道:
> >>
> >> On Mon, Jun 17, 2019 at 5:31 PM Jun Li  wrote:
> >>
> >>>
> >>>
> >>> On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:
> >>>
> 
> 
>  On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
> 
> >
> > On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
> >
> >> Add exif orientation support and expose an option.
> >> ---
> >> libavfilter/hflip.h|   2 +
> >> libavfilter/transpose.h|  14 
> >> libavfilter/vf_hflip.c |  40 ++---
> >> libavfilter/vf_transpose.c | 168
> -
> >> 4 files changed, 192 insertions(+), 32 deletions(-)
> >>
> >> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> >> index 204090dbb4..4e89bae3fc 100644
> >> --- a/libavfilter/hflip.h
> >> +++ b/libavfilter/hflip.h
> >> @@ -35,5 +35,7 @@ typedef struct FlipContext {
> >>
> >> int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
> >> void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> >> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> >> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame
> *out,
> >> int job, int nb_jobs, int vlifp);
> >>
> >> #endif /* AVFILTER_HFLIP_H */
> >> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> >> index aa262b9487..5da08bddc0 100644
> >> --- a/libavfilter/transpose.h
> >> +++ b/libavfilter/transpose.h
> >> @@ -34,4 +34,18 @@ enum TransposeDir {
> >> TRANSPOSE_VFLIP,
> >> };
> >>
> >> +enum OrientationType {
> >> +ORIENTATION_AUTO_TRANSPOSE = -2,
> >> +ORIENTATION_AUTO_FLIP = -1,
> >> +ORIENTATION_NONE = 0,
> >> +ORIENTATION_NORMAL,
> >> +ORIENTATION_HFLIP,
> >> +ORIENTATION_ROTATE180,
> >> +ORIENTATION_VFLIP,
> >> +ORIENTATION_HFLIP_ROTATE270CW,
> >> +ORIENTATION_ROTATE90CW,
> >> +ORIENTATION_HFLIP_ROTATE90CW,
> >> +ORIENTATION_ROTATE270CW
> >> +};
> >> +
> >> #endif
> >> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> >> index b77afc77fc..d24ca5c2e7 100644
> >> --- a/libavfilter/vf_hflip.c
> >> +++ b/libavfilter/vf_hflip.c
> >> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
> >> uint8_t *ddst, int w)
> >> dst[j] = src[-j];
> >> }
> >>
> >> -static int config_props(AVFilterLink *inlink)
> >> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
> >> {
> >> -FlipContext *s = inlink->dst->priv;
> >> const AVPixFmtDescriptor *pix_desc =
> >> av_pix_fmt_desc_get(inlink->format);
> >> const int hsub = pix_desc->log2_chroma_w;
> >> const int vsub = pix_desc->log2_chroma_h;
> >> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
> >> return ff_hflip_init(s, s->max_step, nb_planes);
> >> }
> >>
> >> +static int config_props(AVFilterLink *inlink)
> >> +{
> >> +FlipContext *s = inlink->dst->priv;
> >> +return ff_hflip_config_props(s, inlink);
> >> +}
> >> +
> >> int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
> >> {
> >> int i;
> >> @@ -170,14 +175,10 @@ typedef struct ThreadData {
> >> AVFrame *in, *out;
> >> } ThreadData;
> >>
> >> -static int filter_slice(AVFilterContext *ctx, void *arg, int job,
> int
> >> nb_jobs)
> >> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame
> *out,
> >> int job, int nb_jobs, int vflip)
> >> {
> >> -FlipContext *s = ctx->priv;
> >> -ThreadData *td = arg;
> >> -AVFrame *in = td->in;
> >> -AVFrame *out = td->out;
> >> uint8_t *inrow, *outrow;
> >> -int i, plane, step;
> >> +int i, plane, step, outlinesize;
> >>
> >> for (plane = 0; plane < 4 && in->data[plane] &&
> >> in->linesize[plane]; plane++) {
> >> const int width  = s->planewidth[plane];
> >> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx,
> >> void *arg, int job, int nb_jobs)
> >>
> >> step = s->max_step[plane];
> >>
> >> -outrow = out->data[plane] + start * out->linesize[plane];
> >> -inrow  = in ->data[plane] + start * in->linesize[plane] +
> >> (width - 1) * step;
> >> +if (vflip) {
> >> +outrow = out->data[plane] + (height - start - 1)*
> >> out->linesize[plane];
> >> +outlinesize = -out->linesize[plane];
> >> +} else {
> >> +outrow = out->data[plane] + start *
> out->linesize[plane];
> >> +outlinesize = out->linesize[plane];
> >> +}
> >> +
> >> +inrow = 

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-29 Thread Steven Liu


> 在 2019年6月26日,19:32,Steven Liu  写道:
> 
> Jun Li  于2019年6月25日周二 上午9:26写道:
>> 
>> On Mon, Jun 17, 2019 at 5:31 PM Jun Li  wrote:
>> 
>>> 
>>> 
>>> On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:
>>> 
 
 
 On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
 
> 
> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
> 
>> Add exif orientation support and expose an option.
>> ---
>> libavfilter/hflip.h|   2 +
>> libavfilter/transpose.h|  14 
>> libavfilter/vf_hflip.c |  40 ++---
>> libavfilter/vf_transpose.c | 168 -
>> 4 files changed, 192 insertions(+), 32 deletions(-)
>> 
>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>> index 204090dbb4..4e89bae3fc 100644
>> --- a/libavfilter/hflip.h
>> +++ b/libavfilter/hflip.h
>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>> 
>> int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>> void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>> int job, int nb_jobs, int vlifp);
>> 
>> #endif /* AVFILTER_HFLIP_H */
>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>> index aa262b9487..5da08bddc0 100644
>> --- a/libavfilter/transpose.h
>> +++ b/libavfilter/transpose.h
>> @@ -34,4 +34,18 @@ enum TransposeDir {
>> TRANSPOSE_VFLIP,
>> };
>> 
>> +enum OrientationType {
>> +ORIENTATION_AUTO_TRANSPOSE = -2,
>> +ORIENTATION_AUTO_FLIP = -1,
>> +ORIENTATION_NONE = 0,
>> +ORIENTATION_NORMAL,
>> +ORIENTATION_HFLIP,
>> +ORIENTATION_ROTATE180,
>> +ORIENTATION_VFLIP,
>> +ORIENTATION_HFLIP_ROTATE270CW,
>> +ORIENTATION_ROTATE90CW,
>> +ORIENTATION_HFLIP_ROTATE90CW,
>> +ORIENTATION_ROTATE270CW
>> +};
>> +
>> #endif
>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>> index b77afc77fc..d24ca5c2e7 100644
>> --- a/libavfilter/vf_hflip.c
>> +++ b/libavfilter/vf_hflip.c
>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>> uint8_t *ddst, int w)
>> dst[j] = src[-j];
>> }
>> 
>> -static int config_props(AVFilterLink *inlink)
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>> {
>> -FlipContext *s = inlink->dst->priv;
>> const AVPixFmtDescriptor *pix_desc =
>> av_pix_fmt_desc_get(inlink->format);
>> const int hsub = pix_desc->log2_chroma_w;
>> const int vsub = pix_desc->log2_chroma_h;
>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>> return ff_hflip_init(s, s->max_step, nb_planes);
>> }
>> 
>> +static int config_props(AVFilterLink *inlink)
>> +{
>> +FlipContext *s = inlink->dst->priv;
>> +return ff_hflip_config_props(s, inlink);
>> +}
>> +
>> int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>> {
>> int i;
>> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>> AVFrame *in, *out;
>> } ThreadData;
>> 
>> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>> nb_jobs)
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>> int job, int nb_jobs, int vflip)
>> {
>> -FlipContext *s = ctx->priv;
>> -ThreadData *td = arg;
>> -AVFrame *in = td->in;
>> -AVFrame *out = td->out;
>> uint8_t *inrow, *outrow;
>> -int i, plane, step;
>> +int i, plane, step, outlinesize;
>> 
>> for (plane = 0; plane < 4 && in->data[plane] &&
>> in->linesize[plane]; plane++) {
>> const int width  = s->planewidth[plane];
>> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx,
>> void *arg, int job, int nb_jobs)
>> 
>> step = s->max_step[plane];
>> 
>> -outrow = out->data[plane] + start * out->linesize[plane];
>> -inrow  = in ->data[plane] + start * in->linesize[plane] +
>> (width - 1) * step;
>> +if (vflip) {
>> +outrow = out->data[plane] + (height - start - 1)*
>> out->linesize[plane];
>> +outlinesize = -out->linesize[plane];
>> +} else {
>> +outrow = out->data[plane] + start * out->linesize[plane];
>> +outlinesize = out->linesize[plane];
>> +}
>> +
>> +inrow = in->data[plane] + start * in->linesize[plane] +
>> (width - 1) * step;
>> +
>> for (i = start; i < end; i++) {
>> s->flip_line[plane](inrow, outrow, width);
>> 
>> inrow  += in ->linesize[plane];
>> -outrow += 

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-26 Thread Steven Liu
Jun Li  于2019年6月25日周二 上午9:26写道:
>
> On Mon, Jun 17, 2019 at 5:31 PM Jun Li  wrote:
>
> >
> >
> > On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:
> >
> >>
> >>
> >> On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
> >>
> >>>
> >>> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
> >>>
>  Add exif orientation support and expose an option.
>  ---
>   libavfilter/hflip.h|   2 +
>   libavfilter/transpose.h|  14 
>   libavfilter/vf_hflip.c |  40 ++---
>   libavfilter/vf_transpose.c | 168 -
>   4 files changed, 192 insertions(+), 32 deletions(-)
> 
>  diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>  index 204090dbb4..4e89bae3fc 100644
>  --- a/libavfilter/hflip.h
>  +++ b/libavfilter/hflip.h
>  @@ -35,5 +35,7 @@ typedef struct FlipContext {
> 
>   int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>   void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>  +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>  +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>  int job, int nb_jobs, int vlifp);
> 
>   #endif /* AVFILTER_HFLIP_H */
>  diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>  index aa262b9487..5da08bddc0 100644
>  --- a/libavfilter/transpose.h
>  +++ b/libavfilter/transpose.h
>  @@ -34,4 +34,18 @@ enum TransposeDir {
>   TRANSPOSE_VFLIP,
>   };
> 
>  +enum OrientationType {
>  +ORIENTATION_AUTO_TRANSPOSE = -2,
>  +ORIENTATION_AUTO_FLIP = -1,
>  +ORIENTATION_NONE = 0,
>  +ORIENTATION_NORMAL,
>  +ORIENTATION_HFLIP,
>  +ORIENTATION_ROTATE180,
>  +ORIENTATION_VFLIP,
>  +ORIENTATION_HFLIP_ROTATE270CW,
>  +ORIENTATION_ROTATE90CW,
>  +ORIENTATION_HFLIP_ROTATE90CW,
>  +ORIENTATION_ROTATE270CW
>  +};
>  +
>   #endif
>  diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>  index b77afc77fc..d24ca5c2e7 100644
>  --- a/libavfilter/vf_hflip.c
>  +++ b/libavfilter/vf_hflip.c
>  @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>  uint8_t *ddst, int w)
>   dst[j] = src[-j];
>   }
> 
>  -static int config_props(AVFilterLink *inlink)
>  +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>   {
>  -FlipContext *s = inlink->dst->priv;
>   const AVPixFmtDescriptor *pix_desc =
>  av_pix_fmt_desc_get(inlink->format);
>   const int hsub = pix_desc->log2_chroma_w;
>   const int vsub = pix_desc->log2_chroma_h;
>  @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>   return ff_hflip_init(s, s->max_step, nb_planes);
>   }
> 
>  +static int config_props(AVFilterLink *inlink)
>  +{
>  +FlipContext *s = inlink->dst->priv;
>  +return ff_hflip_config_props(s, inlink);
>  +}
>  +
>   int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>   {
>   int i;
>  @@ -170,14 +175,10 @@ typedef struct ThreadData {
>   AVFrame *in, *out;
>   } ThreadData;
> 
>  -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>  nb_jobs)
>  +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>  int job, int nb_jobs, int vflip)
>   {
>  -FlipContext *s = ctx->priv;
>  -ThreadData *td = arg;
>  -AVFrame *in = td->in;
>  -AVFrame *out = td->out;
>   uint8_t *inrow, *outrow;
>  -int i, plane, step;
>  +int i, plane, step, outlinesize;
> 
>   for (plane = 0; plane < 4 && in->data[plane] &&
>  in->linesize[plane]; plane++) {
>   const int width  = s->planewidth[plane];
>  @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx,
>  void *arg, int job, int nb_jobs)
> 
>   step = s->max_step[plane];
> 
>  -outrow = out->data[plane] + start * out->linesize[plane];
>  -inrow  = in ->data[plane] + start * in->linesize[plane] +
>  (width - 1) * step;
>  +if (vflip) {
>  +outrow = out->data[plane] + (height - start - 1)*
>  out->linesize[plane];
>  +outlinesize = -out->linesize[plane];
>  +} else {
>  +outrow = out->data[plane] + start * out->linesize[plane];
>  +outlinesize = out->linesize[plane];
>  +}
>  +
>  +inrow = in->data[plane] + start * in->linesize[plane] +
>  (width - 1) * step;
>  +
>   for (i = start; i < end; i++) {
>   s->flip_line[plane](inrow, outrow, width);
> 
>   inrow  += in ->linesize[plane];
>  -outrow += out->linesize[plane];
>  +outrow += 

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-24 Thread Jun Li
On Mon, Jun 17, 2019 at 5:31 PM Jun Li  wrote:

>
>
> On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:
>
>>
>>
>> On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
>>
>>>
>>> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
>>>
 Add exif orientation support and expose an option.
 ---
  libavfilter/hflip.h|   2 +
  libavfilter/transpose.h|  14 
  libavfilter/vf_hflip.c |  40 ++---
  libavfilter/vf_transpose.c | 168 -
  4 files changed, 192 insertions(+), 32 deletions(-)

 diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
 index 204090dbb4..4e89bae3fc 100644
 --- a/libavfilter/hflip.h
 +++ b/libavfilter/hflip.h
 @@ -35,5 +35,7 @@ typedef struct FlipContext {

  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
 +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
 +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
 int job, int nb_jobs, int vlifp);

  #endif /* AVFILTER_HFLIP_H */
 diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
 index aa262b9487..5da08bddc0 100644
 --- a/libavfilter/transpose.h
 +++ b/libavfilter/transpose.h
 @@ -34,4 +34,18 @@ enum TransposeDir {
  TRANSPOSE_VFLIP,
  };

 +enum OrientationType {
 +ORIENTATION_AUTO_TRANSPOSE = -2,
 +ORIENTATION_AUTO_FLIP = -1,
 +ORIENTATION_NONE = 0,
 +ORIENTATION_NORMAL,
 +ORIENTATION_HFLIP,
 +ORIENTATION_ROTATE180,
 +ORIENTATION_VFLIP,
 +ORIENTATION_HFLIP_ROTATE270CW,
 +ORIENTATION_ROTATE90CW,
 +ORIENTATION_HFLIP_ROTATE90CW,
 +ORIENTATION_ROTATE270CW
 +};
 +
  #endif
 diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
 index b77afc77fc..d24ca5c2e7 100644
 --- a/libavfilter/vf_hflip.c
 +++ b/libavfilter/vf_hflip.c
 @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
 uint8_t *ddst, int w)
  dst[j] = src[-j];
  }

 -static int config_props(AVFilterLink *inlink)
 +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
  {
 -FlipContext *s = inlink->dst->priv;
  const AVPixFmtDescriptor *pix_desc =
 av_pix_fmt_desc_get(inlink->format);
  const int hsub = pix_desc->log2_chroma_w;
  const int vsub = pix_desc->log2_chroma_h;
 @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
  return ff_hflip_init(s, s->max_step, nb_planes);
  }

 +static int config_props(AVFilterLink *inlink)
 +{
 +FlipContext *s = inlink->dst->priv;
 +return ff_hflip_config_props(s, inlink);
 +}
 +
  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
  {
  int i;
 @@ -170,14 +175,10 @@ typedef struct ThreadData {
  AVFrame *in, *out;
  } ThreadData;

 -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
 nb_jobs)
 +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
 int job, int nb_jobs, int vflip)
  {
 -FlipContext *s = ctx->priv;
 -ThreadData *td = arg;
 -AVFrame *in = td->in;
 -AVFrame *out = td->out;
  uint8_t *inrow, *outrow;
 -int i, plane, step;
 +int i, plane, step, outlinesize;

  for (plane = 0; plane < 4 && in->data[plane] &&
 in->linesize[plane]; plane++) {
  const int width  = s->planewidth[plane];
 @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx,
 void *arg, int job, int nb_jobs)

  step = s->max_step[plane];

 -outrow = out->data[plane] + start * out->linesize[plane];
 -inrow  = in ->data[plane] + start * in->linesize[plane] +
 (width - 1) * step;
 +if (vflip) {
 +outrow = out->data[plane] + (height - start - 1)*
 out->linesize[plane];
 +outlinesize = -out->linesize[plane];
 +} else {
 +outrow = out->data[plane] + start * out->linesize[plane];
 +outlinesize = out->linesize[plane];
 +}
 +
 +inrow = in->data[plane] + start * in->linesize[plane] +
 (width - 1) * step;
 +
  for (i = start; i < end; i++) {
  s->flip_line[plane](inrow, outrow, width);

  inrow  += in ->linesize[plane];
 -outrow += out->linesize[plane];
 +outrow += outlinesize;
  }
  }

  return 0;
  }

 +static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
 nb_jobs)
 +{
 +FlipContext *s = ctx->priv;
 +ThreadData *td = arg;
 +AVFrame *in = td->in;
 +AVFrame *out = 

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-17 Thread Jun Li
On Sat, Jun 15, 2019 at 7:09 PM Jun Li  wrote:

>
>
> On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:
>
>>
>> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
>>
>>> Add exif orientation support and expose an option.
>>> ---
>>>  libavfilter/hflip.h|   2 +
>>>  libavfilter/transpose.h|  14 
>>>  libavfilter/vf_hflip.c |  40 ++---
>>>  libavfilter/vf_transpose.c | 168 -
>>>  4 files changed, 192 insertions(+), 32 deletions(-)
>>>
>>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>>> index 204090dbb4..4e89bae3fc 100644
>>> --- a/libavfilter/hflip.h
>>> +++ b/libavfilter/hflip.h
>>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>>>
>>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>>>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>>> int job, int nb_jobs, int vlifp);
>>>
>>>  #endif /* AVFILTER_HFLIP_H */
>>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>>> index aa262b9487..5da08bddc0 100644
>>> --- a/libavfilter/transpose.h
>>> +++ b/libavfilter/transpose.h
>>> @@ -34,4 +34,18 @@ enum TransposeDir {
>>>  TRANSPOSE_VFLIP,
>>>  };
>>>
>>> +enum OrientationType {
>>> +ORIENTATION_AUTO_TRANSPOSE = -2,
>>> +ORIENTATION_AUTO_FLIP = -1,
>>> +ORIENTATION_NONE = 0,
>>> +ORIENTATION_NORMAL,
>>> +ORIENTATION_HFLIP,
>>> +ORIENTATION_ROTATE180,
>>> +ORIENTATION_VFLIP,
>>> +ORIENTATION_HFLIP_ROTATE270CW,
>>> +ORIENTATION_ROTATE90CW,
>>> +ORIENTATION_HFLIP_ROTATE90CW,
>>> +ORIENTATION_ROTATE270CW
>>> +};
>>> +
>>>  #endif
>>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>>> index b77afc77fc..d24ca5c2e7 100644
>>> --- a/libavfilter/vf_hflip.c
>>> +++ b/libavfilter/vf_hflip.c
>>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>>> uint8_t *ddst, int w)
>>>  dst[j] = src[-j];
>>>  }
>>>
>>> -static int config_props(AVFilterLink *inlink)
>>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>>>  {
>>> -FlipContext *s = inlink->dst->priv;
>>>  const AVPixFmtDescriptor *pix_desc =
>>> av_pix_fmt_desc_get(inlink->format);
>>>  const int hsub = pix_desc->log2_chroma_w;
>>>  const int vsub = pix_desc->log2_chroma_h;
>>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>>>  return ff_hflip_init(s, s->max_step, nb_planes);
>>>  }
>>>
>>> +static int config_props(AVFilterLink *inlink)
>>> +{
>>> +FlipContext *s = inlink->dst->priv;
>>> +return ff_hflip_config_props(s, inlink);
>>> +}
>>> +
>>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>>>  {
>>>  int i;
>>> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>>>  AVFrame *in, *out;
>>>  } ThreadData;
>>>
>>> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>>> nb_jobs)
>>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out,
>>> int job, int nb_jobs, int vflip)
>>>  {
>>> -FlipContext *s = ctx->priv;
>>> -ThreadData *td = arg;
>>> -AVFrame *in = td->in;
>>> -AVFrame *out = td->out;
>>>  uint8_t *inrow, *outrow;
>>> -int i, plane, step;
>>> +int i, plane, step, outlinesize;
>>>
>>>  for (plane = 0; plane < 4 && in->data[plane] &&
>>> in->linesize[plane]; plane++) {
>>>  const int width  = s->planewidth[plane];
>>> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
>>> *arg, int job, int nb_jobs)
>>>
>>>  step = s->max_step[plane];
>>>
>>> -outrow = out->data[plane] + start * out->linesize[plane];
>>> -inrow  = in ->data[plane] + start * in->linesize[plane] +
>>> (width - 1) * step;
>>> +if (vflip) {
>>> +outrow = out->data[plane] + (height - start - 1)*
>>> out->linesize[plane];
>>> +outlinesize = -out->linesize[plane];
>>> +} else {
>>> +outrow = out->data[plane] + start * out->linesize[plane];
>>> +outlinesize = out->linesize[plane];
>>> +}
>>> +
>>> +inrow = in->data[plane] + start * in->linesize[plane] +  (width
>>> - 1) * step;
>>> +
>>>  for (i = start; i < end; i++) {
>>>  s->flip_line[plane](inrow, outrow, width);
>>>
>>>  inrow  += in ->linesize[plane];
>>> -outrow += out->linesize[plane];
>>> +outrow += outlinesize;
>>>  }
>>>  }
>>>
>>>  return 0;
>>>  }
>>>
>>> +static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>>> nb_jobs)
>>> +{
>>> +FlipContext *s = ctx->priv;
>>> +ThreadData *td = arg;
>>> +AVFrame *in = td->in;
>>> +AVFrame *out = td->out;
>>> +return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
>>> +}
>>> +
>>>  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
>>>  {
>>>  AVFilterContext *ctx  = 

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-15 Thread Jun Li
On Tue, Jun 11, 2019 at 7:05 PM Jun Li  wrote:

>
> On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:
>
>> Add exif orientation support and expose an option.
>> ---
>>  libavfilter/hflip.h|   2 +
>>  libavfilter/transpose.h|  14 
>>  libavfilter/vf_hflip.c |  40 ++---
>>  libavfilter/vf_transpose.c | 168 -
>>  4 files changed, 192 insertions(+), 32 deletions(-)
>>
>> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
>> index 204090dbb4..4e89bae3fc 100644
>> --- a/libavfilter/hflip.h
>> +++ b/libavfilter/hflip.h
>> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>>
>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
>> job, int nb_jobs, int vlifp);
>>
>>  #endif /* AVFILTER_HFLIP_H */
>> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
>> index aa262b9487..5da08bddc0 100644
>> --- a/libavfilter/transpose.h
>> +++ b/libavfilter/transpose.h
>> @@ -34,4 +34,18 @@ enum TransposeDir {
>>  TRANSPOSE_VFLIP,
>>  };
>>
>> +enum OrientationType {
>> +ORIENTATION_AUTO_TRANSPOSE = -2,
>> +ORIENTATION_AUTO_FLIP = -1,
>> +ORIENTATION_NONE = 0,
>> +ORIENTATION_NORMAL,
>> +ORIENTATION_HFLIP,
>> +ORIENTATION_ROTATE180,
>> +ORIENTATION_VFLIP,
>> +ORIENTATION_HFLIP_ROTATE270CW,
>> +ORIENTATION_ROTATE90CW,
>> +ORIENTATION_HFLIP_ROTATE90CW,
>> +ORIENTATION_ROTATE270CW
>> +};
>> +
>>  #endif
>> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
>> index b77afc77fc..d24ca5c2e7 100644
>> --- a/libavfilter/vf_hflip.c
>> +++ b/libavfilter/vf_hflip.c
>> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc,
>> uint8_t *ddst, int w)
>>  dst[j] = src[-j];
>>  }
>>
>> -static int config_props(AVFilterLink *inlink)
>> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>>  {
>> -FlipContext *s = inlink->dst->priv;
>>  const AVPixFmtDescriptor *pix_desc =
>> av_pix_fmt_desc_get(inlink->format);
>>  const int hsub = pix_desc->log2_chroma_w;
>>  const int vsub = pix_desc->log2_chroma_h;
>> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>>  return ff_hflip_init(s, s->max_step, nb_planes);
>>  }
>>
>> +static int config_props(AVFilterLink *inlink)
>> +{
>> +FlipContext *s = inlink->dst->priv;
>> +return ff_hflip_config_props(s, inlink);
>> +}
>> +
>>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>>  {
>>  int i;
>> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>>  AVFrame *in, *out;
>>  } ThreadData;
>>
>> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>> nb_jobs)
>> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
>> job, int nb_jobs, int vflip)
>>  {
>> -FlipContext *s = ctx->priv;
>> -ThreadData *td = arg;
>> -AVFrame *in = td->in;
>> -AVFrame *out = td->out;
>>  uint8_t *inrow, *outrow;
>> -int i, plane, step;
>> +int i, plane, step, outlinesize;
>>
>>  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
>> plane++) {
>>  const int width  = s->planewidth[plane];
>> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
>> *arg, int job, int nb_jobs)
>>
>>  step = s->max_step[plane];
>>
>> -outrow = out->data[plane] + start * out->linesize[plane];
>> -inrow  = in ->data[plane] + start * in->linesize[plane] + (width
>> - 1) * step;
>> +if (vflip) {
>> +outrow = out->data[plane] + (height - start - 1)*
>> out->linesize[plane];
>> +outlinesize = -out->linesize[plane];
>> +} else {
>> +outrow = out->data[plane] + start * out->linesize[plane];
>> +outlinesize = out->linesize[plane];
>> +}
>> +
>> +inrow = in->data[plane] + start * in->linesize[plane] +  (width
>> - 1) * step;
>> +
>>  for (i = start; i < end; i++) {
>>  s->flip_line[plane](inrow, outrow, width);
>>
>>  inrow  += in ->linesize[plane];
>> -outrow += out->linesize[plane];
>> +outrow += outlinesize;
>>  }
>>  }
>>
>>  return 0;
>>  }
>>
>> +static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
>> nb_jobs)
>> +{
>> +FlipContext *s = ctx->priv;
>> +ThreadData *td = arg;
>> +AVFrame *in = td->in;
>> +AVFrame *out = td->out;
>> +return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
>> +}
>> +
>>  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
>>  {
>>  AVFilterContext *ctx  = inlink->dst;
>> diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
>> index dd54947bd9..05dc04a89f 100644
>> --- a/libavfilter/vf_transpose.c
>> +++ b/libavfilter/vf_transpose.c

Re: [FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-11 Thread Jun Li
On Sun, Jun 9, 2019 at 2:28 PM Jun Li  wrote:

> Add exif orientation support and expose an option.
> ---
>  libavfilter/hflip.h|   2 +
>  libavfilter/transpose.h|  14 
>  libavfilter/vf_hflip.c |  40 ++---
>  libavfilter/vf_transpose.c | 168 -
>  4 files changed, 192 insertions(+), 32 deletions(-)
>
> diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
> index 204090dbb4..4e89bae3fc 100644
> --- a/libavfilter/hflip.h
> +++ b/libavfilter/hflip.h
> @@ -35,5 +35,7 @@ typedef struct FlipContext {
>
>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
>  void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> job, int nb_jobs, int vlifp);
>
>  #endif /* AVFILTER_HFLIP_H */
> diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
> index aa262b9487..5da08bddc0 100644
> --- a/libavfilter/transpose.h
> +++ b/libavfilter/transpose.h
> @@ -34,4 +34,18 @@ enum TransposeDir {
>  TRANSPOSE_VFLIP,
>  };
>
> +enum OrientationType {
> +ORIENTATION_AUTO_TRANSPOSE = -2,
> +ORIENTATION_AUTO_FLIP = -1,
> +ORIENTATION_NONE = 0,
> +ORIENTATION_NORMAL,
> +ORIENTATION_HFLIP,
> +ORIENTATION_ROTATE180,
> +ORIENTATION_VFLIP,
> +ORIENTATION_HFLIP_ROTATE270CW,
> +ORIENTATION_ROTATE90CW,
> +ORIENTATION_HFLIP_ROTATE90CW,
> +ORIENTATION_ROTATE270CW
> +};
> +
>  #endif
> diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
> index b77afc77fc..d24ca5c2e7 100644
> --- a/libavfilter/vf_hflip.c
> +++ b/libavfilter/vf_hflip.c
> @@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t
> *ddst, int w)
>  dst[j] = src[-j];
>  }
>
> -static int config_props(AVFilterLink *inlink)
> +int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
>  {
> -FlipContext *s = inlink->dst->priv;
>  const AVPixFmtDescriptor *pix_desc =
> av_pix_fmt_desc_get(inlink->format);
>  const int hsub = pix_desc->log2_chroma_w;
>  const int vsub = pix_desc->log2_chroma_h;
> @@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
>  return ff_hflip_init(s, s->max_step, nb_planes);
>  }
>
> +static int config_props(AVFilterLink *inlink)
> +{
> +FlipContext *s = inlink->dst->priv;
> +return ff_hflip_config_props(s, inlink);
> +}
> +
>  int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
>  {
>  int i;
> @@ -170,14 +175,10 @@ typedef struct ThreadData {
>  AVFrame *in, *out;
>  } ThreadData;
>
> -static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> nb_jobs)
> +int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int
> job, int nb_jobs, int vflip)
>  {
> -FlipContext *s = ctx->priv;
> -ThreadData *td = arg;
> -AVFrame *in = td->in;
> -AVFrame *out = td->out;
>  uint8_t *inrow, *outrow;
> -int i, plane, step;
> +int i, plane, step, outlinesize;
>
>  for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane];
> plane++) {
>  const int width  = s->planewidth[plane];
> @@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void
> *arg, int job, int nb_jobs)
>
>  step = s->max_step[plane];
>
> -outrow = out->data[plane] + start * out->linesize[plane];
> -inrow  = in ->data[plane] + start * in->linesize[plane] + (width
> - 1) * step;
> +if (vflip) {
> +outrow = out->data[plane] + (height - start - 1)*
> out->linesize[plane];
> +outlinesize = -out->linesize[plane];
> +} else {
> +outrow = out->data[plane] + start * out->linesize[plane];
> +outlinesize = out->linesize[plane];
> +}
> +
> +inrow = in->data[plane] + start * in->linesize[plane] +  (width -
> 1) * step;
> +
>  for (i = start; i < end; i++) {
>  s->flip_line[plane](inrow, outrow, width);
>
>  inrow  += in ->linesize[plane];
> -outrow += out->linesize[plane];
> +outrow += outlinesize;
>  }
>  }
>
>  return 0;
>  }
>
> +static int filter_slice(AVFilterContext *ctx, void *arg, int job, int
> nb_jobs)
> +{
> +FlipContext *s = ctx->priv;
> +ThreadData *td = arg;
> +AVFrame *in = td->in;
> +AVFrame *out = td->out;
> +return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
> +}
> +
>  static int filter_frame(AVFilterLink *inlink, AVFrame *in)
>  {
>  AVFilterContext *ctx  = inlink->dst;
> diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
> index dd54947bd9..05dc04a89f 100644
> --- a/libavfilter/vf_transpose.c
> +++ b/libavfilter/vf_transpose.c
> @@ -39,6 +39,7 @@
>  #include "internal.h"
>  #include "video.h"
>  #include "transpose.h"
> +#include "hflip.h"
>
>  typedef struct TransVtable {
>  void (*transpose_8x8)(uint8_t *src, 

[FFmpeg-devel] [PATCH v10 1/2] lavf/vf_transpose: add exif orientation support

2019-06-09 Thread Jun Li
Add exif orientation support and expose an option.
---
 libavfilter/hflip.h|   2 +
 libavfilter/transpose.h|  14 
 libavfilter/vf_hflip.c |  40 ++---
 libavfilter/vf_transpose.c | 168 -
 4 files changed, 192 insertions(+), 32 deletions(-)

diff --git a/libavfilter/hflip.h b/libavfilter/hflip.h
index 204090dbb4..4e89bae3fc 100644
--- a/libavfilter/hflip.h
+++ b/libavfilter/hflip.h
@@ -35,5 +35,7 @@ typedef struct FlipContext {
 
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes);
 void ff_hflip_init_x86(FlipContext *s, int step[4], int nb_planes);
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink);
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vlifp);
 
 #endif /* AVFILTER_HFLIP_H */
diff --git a/libavfilter/transpose.h b/libavfilter/transpose.h
index aa262b9487..5da08bddc0 100644
--- a/libavfilter/transpose.h
+++ b/libavfilter/transpose.h
@@ -34,4 +34,18 @@ enum TransposeDir {
 TRANSPOSE_VFLIP,
 };
 
+enum OrientationType {
+ORIENTATION_AUTO_TRANSPOSE = -2,
+ORIENTATION_AUTO_FLIP = -1,
+ORIENTATION_NONE = 0,
+ORIENTATION_NORMAL,
+ORIENTATION_HFLIP,
+ORIENTATION_ROTATE180,
+ORIENTATION_VFLIP,
+ORIENTATION_HFLIP_ROTATE270CW,
+ORIENTATION_ROTATE90CW,
+ORIENTATION_HFLIP_ROTATE90CW,
+ORIENTATION_ROTATE270CW
+};
+
 #endif
diff --git a/libavfilter/vf_hflip.c b/libavfilter/vf_hflip.c
index b77afc77fc..d24ca5c2e7 100644
--- a/libavfilter/vf_hflip.c
+++ b/libavfilter/vf_hflip.c
@@ -125,9 +125,8 @@ static void hflip_qword_c(const uint8_t *ssrc, uint8_t 
*ddst, int w)
 dst[j] = src[-j];
 }
 
-static int config_props(AVFilterLink *inlink)
+int ff_hflip_config_props(FlipContext* s, AVFilterLink *inlink)
 {
-FlipContext *s = inlink->dst->priv;
 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
 const int hsub = pix_desc->log2_chroma_w;
 const int vsub = pix_desc->log2_chroma_h;
@@ -144,6 +143,12 @@ static int config_props(AVFilterLink *inlink)
 return ff_hflip_init(s, s->max_step, nb_planes);
 }
 
+static int config_props(AVFilterLink *inlink)
+{
+FlipContext *s = inlink->dst->priv;
+return ff_hflip_config_props(s, inlink);
+}
+
 int ff_hflip_init(FlipContext *s, int step[4], int nb_planes)
 {
 int i;
@@ -170,14 +175,10 @@ typedef struct ThreadData {
 AVFrame *in, *out;
 } ThreadData;
 
-static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+int ff_hflip_filter_slice(FlipContext *s, AVFrame *in, AVFrame *out, int job, 
int nb_jobs, int vflip)
 {
-FlipContext *s = ctx->priv;
-ThreadData *td = arg;
-AVFrame *in = td->in;
-AVFrame *out = td->out;
 uint8_t *inrow, *outrow;
-int i, plane, step;
+int i, plane, step, outlinesize;
 
 for (plane = 0; plane < 4 && in->data[plane] && in->linesize[plane]; 
plane++) {
 const int width  = s->planewidth[plane];
@@ -187,19 +188,36 @@ static int filter_slice(AVFilterContext *ctx, void *arg, 
int job, int nb_jobs)
 
 step = s->max_step[plane];
 
-outrow = out->data[plane] + start * out->linesize[plane];
-inrow  = in ->data[plane] + start * in->linesize[plane] + (width - 1) 
* step;
+if (vflip) {
+outrow = out->data[plane] + (height - start - 1)* 
out->linesize[plane];
+outlinesize = -out->linesize[plane];
+} else {
+outrow = out->data[plane] + start * out->linesize[plane];
+outlinesize = out->linesize[plane];
+}
+
+inrow = in->data[plane] + start * in->linesize[plane] +  (width - 1) * 
step;
+
 for (i = start; i < end; i++) {
 s->flip_line[plane](inrow, outrow, width);
 
 inrow  += in ->linesize[plane];
-outrow += out->linesize[plane];
+outrow += outlinesize;
 }
 }
 
 return 0;
 }
 
+static int filter_slice(AVFilterContext *ctx, void *arg, int job, int nb_jobs)
+{
+FlipContext *s = ctx->priv;
+ThreadData *td = arg;
+AVFrame *in = td->in;
+AVFrame *out = td->out;
+return ff_hflip_filter_slice(s, in, out, job, nb_jobs, 0);
+}
+
 static int filter_frame(AVFilterLink *inlink, AVFrame *in)
 {
 AVFilterContext *ctx  = inlink->dst;
diff --git a/libavfilter/vf_transpose.c b/libavfilter/vf_transpose.c
index dd54947bd9..05dc04a89f 100644
--- a/libavfilter/vf_transpose.c
+++ b/libavfilter/vf_transpose.c
@@ -39,6 +39,7 @@
 #include "internal.h"
 #include "video.h"
 #include "transpose.h"
+#include "hflip.h"
 
 typedef struct TransVtable {
 void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize,
@@ -48,16 +49,22 @@ typedef struct TransVtable {
 int w, int h);
 } TransVtable;
 
-typedef struct TransContext {
-const AVClass *class;
+typedef struct TransContextData {
 int hsub, vsub;
 int planes;
 int pixsteps[4];
+TransVtable vtables[4];