Fix #6945 '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 | 63 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-)
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index 01f04103cf..73f185a2d1 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2341,6 +2341,64 @@ 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) +{ + AVDictionaryEntry *entry = NULL; + int orientation = 0, size = 0; + int32_t* sd = NULL; + + sd = (int32_t*)av_stream_get_side_data(ist->st, AV_PKT_DATA_DISPLAYMATRIX, &size); + if (sd) // stream already contains display matrix + return 0; + + // read exif orientation data + entry = av_dict_get(frame->metadata, "Orientation", NULL, 0); + 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 +2481,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) -- 2.17.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".