[FFmpeg-devel] [PATCH v8 2/2] fftools/ffmpeg: add exif orientation support per frame's metadata

Jun Li junli1026 at gmail.com
Sat Jun 8 00:45:23 EEST 2019


On Fri, Jun 7, 2019 at 11:54 AM Michael Niedermayer <michael at niedermayer.cc>
wrote:

> On Thu, Jun 06, 2019 at 08:28:15PM -0700, Jun Li wrote:
> > Fix #6945
> > Rotate or/and flip frame according to frame's metadata orientation
> > ---
> >  fftools/ffmpeg.c        |  5 +++--
> >  fftools/ffmpeg.h        |  8 ++++++++
> >  fftools/ffmpeg_filter.c | 36 +++++++++++++++++++++++++++++++-----
> >  3 files changed, 42 insertions(+), 7 deletions(-)
> >
> > diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> > index 01f04103cf..bc0cece59d 100644
> > --- a/fftools/ffmpeg.c
> > +++ b/fftools/ffmpeg.c
> > @@ -2141,8 +2141,9 @@ static int ifilter_send_frame(InputFilter
> *ifilter, AVFrame *frame)
> >                         ifilter->channel_layout != frame->channel_layout;
> >          break;
> >      case AVMEDIA_TYPE_VIDEO:
> > -        need_reinit |= ifilter->width  != frame->width ||
> > -                       ifilter->height != frame->height;
> > +        need_reinit |= ifilter->width       != frame->width ||
> > +                       ifilter->height      != frame->height ||
> > +                       ifilter->orientation !=
> get_frame_orientation(frame);
> >          break;
> >      }
> >
> > diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> > index 7b6f802082..7324813ce3 100644
> > --- a/fftools/ffmpeg.h
> > +++ b/fftools/ffmpeg.h
> > @@ -232,6 +232,12 @@ typedef struct OptionsContext {
> >      int        nb_enc_time_bases;
> >  } OptionsContext;
> >
> > +enum OrientationType {
> > +    ORIENTATION_NONE,
> > +    ORIENTATION_AUTO_FLIP,
> > +    ORIENTATION_AUTO_TRANSPOSE
> > +};
> > +
> >  typedef struct InputFilter {
> >      AVFilterContext    *filter;
> >      struct InputStream *ist;
> > @@ -245,6 +251,7 @@ typedef struct InputFilter {
> >      int format;
> >
> >      int width, height;
> > +    enum OrientationType orientation;
> >      AVRational sample_aspect_ratio;
> >
> >      int sample_rate;
> > @@ -649,6 +656,7 @@ int init_complex_filtergraph(FilterGraph *fg);
> >  void sub2video_update(InputStream *ist, AVSubtitle *sub);
> >
> >  int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame
> *frame);
> > +enum OrientationType get_frame_orientation(const AVFrame* frame);
> >
> >  int ffmpeg_parse_options(int argc, char **argv);
> >
> > diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
> > index 72838de1e2..790751f47f 100644
> > --- a/fftools/ffmpeg_filter.c
> > +++ b/fftools/ffmpeg_filter.c
> > @@ -743,6 +743,28 @@ static int sub2video_prepare(InputStream *ist,
> InputFilter *ifilter)
> >      return 0;
> >  }
> >
> > +enum OrientationType get_frame_orientation(const AVFrame *frame)
> > +{
> > +    AVDictionaryEntry *entry = NULL;
> > +    int orientation = 0;
> > +
> > +    // read exif orientation data
> > +    entry = av_dict_get(frame->metadata, "Orientation", NULL, 0);
> > +    if (entry && entry->value)
> > +        orientation = atoi(entry->value);
>
> what if entry->value equals "The cow says moo" ?
> This is of course a silly example but the following code would not detect
> it as an error
> as atoi would return 0
> or is there something that prevents this case ?
>

Hi Michael,
The question is like how to validate a integer number, or maybe partially
validate a number.
In this case, I can do a simple check before call atoi,  but need to cover
the following case:
  "      +2"   // start with space,  with or without sign

Something might be like:
  int i = 0;
  char *pos = NULL;
  if (entry && entry->value) {
      while(entry->value[i] && entry->value[i] == ' ') // eat white-space
           i++;
      if (entry->value[i]) {
          if (entry->value[i] == '+')   // eat '+'
             i++;

          if (entry->value[i] && entry->value[i] >= '0' && entry->value <=
'8')
              pos = entry->value + i;
      }
  }

  if (pos) {
     orientation = atoi(pos);
  }

But the validation is *NOT COMPLETE* although it covers the case your
mentioned.
Like "3.4" is valid and converted to orientation 3, even "3     4" is a
valid orientation.
I think a complete validation should be creating a function like "atodigit"
, string to digit, instead of using atoi,

If you prefer a complete solution, I can send a new version to validate the
value.
What do you think ?

Best Regards,
Jun


> > +
> > +    if (orientation > 8 || orientation < 0) {
> > +        av_log(NULL, AV_LOG_WARNING, "Invalid frame orientation: %i,
> skip it.\n", orientation);
> > +        return ORIENTATION_NONE;
> > +    } else if (orientation <= 1) {
> > +        return ORIENTATION_NONE;
> > +    } else if (orientation <= 4) {
> > +        return ORIENTATION_AUTO_FLIP;
> > +    } else {
> > +        return ORIENTATION_AUTO_TRANSPOSE;
> > +    }
> > +}
>
> [...]
> --
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
>
> "Nothing to hide" only works if the folks in power share the values of
> you and everyone you know entirely and always will -- Tom Scott
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list