[FFmpeg-devel] [PATCH v4 2/2] fftools/ffmpeg: Add stream metadata from first frame's metadata

Jun Li junli1026 at gmail.com
Wed May 8 09:55:32 EEST 2019


On Tue, May 7, 2019 at 11:40 PM Gyan <ffmpeg at gyani.pro> wrote:

>
>
> On 08-05-2019 11:54 AM, Jun Li wrote:
> > Fix #6945
> > Exif extension has 'Orientaion' field for image flip and rotation.
> > This change is to add the first frame's exif into stream so that
> > autorotation would use the info to adjust the frames.
>
> Suggest commit msg should be
>
> "
>
> 'Orientation' field from EXIF tags in first decoded frame is extracted
>   as stream side data so that ffmpeg can apply auto-rotation.
>
> "
>

Sure, will address that in next iteration.


>
> > ---
> >   fftools/ffmpeg.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++-
> >   1 file changed, 56 insertions(+), 1 deletion(-)
> >
> > diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
> > index 01f04103cf..98ccaf0732 100644
> > --- a/fftools/ffmpeg.c
> > +++ b/fftools/ffmpeg.c
> > @@ -2341,6 +2341,58 @@ static int decode_audio(InputStream *ist,
> AVPacket *pkt, int *got_output,
> >       return err < 0 ? err : ret;
> >   }
> >
> > +static int set_metadata_from_1stframe(InputStream* ist, AVFrame* frame)
> > +{
> > +    // read exif Orientation data
> > +    AVDictionaryEntry *entry = av_dict_get(frame->metadata,
> "Orientation", NULL, 0);
> > +    int orientation = 0;
> > +    int32_t* sd = NULL;
> > +    if (entry) {
> > +        orientation = atoi(entry->value);
> > +        sd = (int32_t*)av_stream_new_side_data(ist->st,
> AV_PKT_DATA_DISPLAYMATRIX, 4 * 9);
> > +        if (!sd)
> > +            return AVERROR(ENOMEM);
> > +        memset(sd, 0, 4 * 9);
> > +        switch (orientation)
> > +        {
> > +            case 1: // horizontal (normal)
> > +                av_display_rotation_set(sd, 0.0);
> > +                break;
> > +            case 2: // mirror horizontal
> > +                av_display_rotation_set(sd, 0.0);
> > +                av_display_matrix_flip(sd, 1, 0);
> > +                break;
> > +            case 3: // rotate 180
> > +                av_display_rotation_set(sd, 180.0);
> > +                break;
> > +            case 4: // mirror vertical
> > +                av_display_rotation_set(sd, 0.0);
> > +                av_display_matrix_flip(sd, 0, 1);
> > +                break;
> > +            case 5: // mirror horizontal and rotate 270 CW
> > +                av_display_rotation_set(sd, 270.0);
> > +                av_display_matrix_flip(sd, 0, 1);
> > +                break;
> > +            case 6: // rotate 90 CW
> > +                av_display_rotation_set(sd, 90.0);
> > +                break;
> > +            case 7: // mirror horizontal and rotate 90 CW
> > +                av_display_rotation_set(sd, 90.0);
> > +                av_display_matrix_flip(sd, 0, 1);
> > +                break;
> > +            case 8: // rotate 270 CW
> > +                av_display_rotation_set(sd, 270.0);
> > +                break;
> > +            default:
> > +                av_display_rotation_set(sd, 0.0);
> > +                av_log(ist->dec_ctx, AV_LOG_WARNING,
> > +                    "Exif orientation data out of range: %i. Set to
> default value: horizontal(normal).\n", orientation);
> > +                break;
> > +        }
> > +    }
> > +    return 0;
> > +}
> > +
> >   static int decode_video(InputStream *ist, AVPacket *pkt, int
> *got_output, int64_t *duration_pts, int eof,
> >                           int *decode_failed)
> >   {
> > @@ -2423,7 +2475,10 @@ static int decode_video(InputStream *ist,
> AVPacket *pkt, int *got_output, int64_
> >           decoded_frame->top_field_first = ist->top_field_first;
> >
> >       ist->frames_decoded++;
> > -
> > +    if (ist->frames_decoded == 1 &&
> > +        ((err = set_metadata_from_1stframe(ist, decoded_frame)) < 0))
> > +        goto fail;
> > +
> >       if (ist->hwaccel_retrieve_data && decoded_frame->format ==
> ist->hwaccel_pix_fmt) {
> >           err = ist->hwaccel_retrieve_data(ist->dec_ctx, decoded_frame);
> >           if (err < 0)
>
> Also, is there a chance that there may be multiple sources for
> orientation data available for a given stream? If yes, what's the
> interaction? It looks like you append a new SD element.
>

Thanks Gyan for review !
Nicolas George asked the same question before. :)

Yes, this patch can't handle the case every frame has its own orientation.
>From a technical perspective, it is absolutely possible, for example a
motion jpeg stream with different orientation value
on every frame. I think an ideal solution for this case is a filter doing
transformation per orientation every frame.

But based on my limited experience, I think this kind of content is rare.
What do you think ?
Maybe someone in the community met this kind of content before ?

Gyan
> _______________________________________________
> 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