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

Gyan ffmpeg at gyani.pro
Wed May 8 09:40:29 EEST 2019



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.

"


> ---
>   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.

Gyan


More information about the ffmpeg-devel mailing list