On Tue, Aug 19, 2025 at 06:33:03PM +0300, [email protected] wrote:
> The branch, master has been updated
>        via  4c3f94f2651ce4d6834fbef10e5c287f25720ac9 (commit)
>        via  fe496b0308f1911138698b92bbafac582fa455d7 (commit) <----- we are 
> here
>        via  535a07d14e16eb2930d2b1e16605eafa95959139 (commit)
>        via  8132ee046d1a03c5913759c50fce7beda8d3d627 (commit)
>        via  5d4f873ff31f86f9ae1927f37ca0fcb78da70512 (commit)
>        via  1e816ebefee0ef479fa76bd2a1fb9ec5d5e807df (commit)
>        via  93a8091015978c44462626409af71789080bbef4 (commit)
>        via  303f60684f25ce63951480ef0f759acf41aac938 (commit)
>        via  5caaadee7954f2014d9e0a17d1edfb961893bcf1 (commit)
>        via  d3190a64c366a79091fe47fddf93c09a7d988802 (commit)
>        via  44af3829796427b89c4b76b56652cc5932ada616 (commit)
>        via  f5ad1c910c168d05cb01315773ab0bd094c9372f (commit)
>        via  e3aa1154aab2656c91ce61915f79516d9b563b61 (commit)
>        via  c6cc2115f45ac26ae42442f8796996eb410f4028 (commit)
>        via  52dba25661305e3c4a6209d46aea43cd327c960e (commit)
>        via  bfb17d26306592c85cf0c4e909099c621177b062 (commit)
>        via  ba2ea285e0f270a0a885b414cafaace6a89b9a91 (commit)
>        via  ad77345a5d14862f4701e5ad422b03b14934a5b9 (commit)
>        via  bb90b262d6d23f1bca3587a48abc15b951cbbf05 (commit)
>        via  a99fff4e2d4058c57599ba0b968862af82bdad5b (commit)
>       from  a6b5a382dd7ecdd27c5d0ebba688e1db409d18fd (commit)
> 
> 

> commit fe496b0308f1911138698b92bbafac582fa455d7
> Author:     Leo Izen <[email protected]>
> AuthorDate: Sun Apr 13 05:47:54 2025 -0400
> Commit:     Leo Izen <[email protected]>
> CommitDate: Tue Aug 19 11:26:48 2025 -0400
> 
>     avcodec/libjxlenc: apply displaymatrix side data orientation to output
>     
>     If the output is tagged with AV_FRAME_DATA_DISPLAYMATRIX we will read
>     it and apply it to the output file.
>     
>     Signed-off-by: Leo Izen <[email protected]>
> 
> diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c
> index 40d5f760b1..4f05f015e2 100644
> --- a/libavcodec/libjxlenc.c
> +++ b/libavcodec/libjxlenc.c
> @@ -28,6 +28,7 @@
>  
>  #include "libavutil/avutil.h"
>  #include "libavutil/csp.h"
> +#include "libavutil/display.h"
>  #include "libavutil/error.h"
>  #include "libavutil/frame.h"
>  #include "libavutil/libm.h"
> @@ -40,6 +41,7 @@
>  #include "avcodec.h"
>  #include "encode.h"
>  #include "codec_internal.h"
> +#include "exif_internal.h"
>  
>  #include <jxl/encode.h>
>  #include <jxl/thread_parallel_runner.h>
> @@ -322,10 +324,14 @@ static int libjxl_preprocess_stream(AVCodecContext 
> *avctx, const AVFrame *frame,
>  {
>      LibJxlEncodeContext *ctx = avctx->priv_data;
>      AVFrameSideData *sd;
> +    int32_t *matrix = (int32_t[9]){ 0 };
> +    int ret = 0;
>      const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(frame->format);
>      JxlBasicInfo info;
>      JxlPixelFormat *jxl_fmt = &ctx->jxl_fmt;
>      int bits_per_sample;
> +    int orientation;
> +    AVBufferRef *exif_buffer = NULL;
>  #if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
>      JxlBitDepth jxl_bit_depth;
>  #endif
> @@ -368,8 +374,51 @@ static int libjxl_preprocess_stream(AVCodecContext 
> *avctx, const AVFrame *frame,
>      /* bitexact lossless requires there to be no XYB transform */
>      info.uses_original_profile = ctx->distance == 0.0 || !ctx->xyb;
>  
> -    /* libjxl doesn't support negative linesizes so we use orientation to 
> work around this */
> -    info.orientation = frame->linesize[0] >= 0 ? JXL_ORIENT_IDENTITY : 
> JXL_ORIENT_FLIP_VERTICAL;
> +    sd = av_frame_get_side_data(frame, AV_FRAME_DATA_EXIF);
> +    if (sd) {
> +        AVExifMetadata ifd = { 0 };
> +        AVExifEntry *orient = NULL;
> +        uint16_t tag = av_exif_get_tag_id("Orientation");
> +        ret = av_exif_parse_buffer(avctx, sd->data, sd->size, &ifd, 
> AV_EXIF_TIFF_HEADER);
> +        if (ret >= 0)
> +            ret = ff_exif_sanitize_ifd(avctx, frame, &ifd);
> +        if (ret >= 0)
> +            ret = av_exif_get_entry(avctx, &ifd, tag, 0, &orient);
> +        if (ret >= 0 && orient && orient->value.uint[0] >= 1 && 
> orient->value.uint[0] <= 8) {
> +            av_exif_orientation_to_matrix(matrix, orient->value.uint[0]);

This reads value.uint[0] without checking the tags type


> +            ret = av_exif_remove_entry(avctx, &ifd, tag, 0);
> +        } else {
> +            av_exif_orientation_to_matrix(matrix, 1);
> +        }
> +        if (ret >= 0)
> +            ret = av_exif_write(avctx, &ifd, &exif_buffer, 
> AV_EXIF_TIFF_HEADER);
> +        if (ret < 0)
> +            av_log(avctx, AV_LOG_WARNING, "unable to process EXIF frame 
> data\n");
> +    } else {
> +        sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
> +        if (sd)
> +            matrix = (int32_t *) sd->data;
> +        else
> +            av_exif_orientation_to_matrix(matrix, 1);
> +    }

This does not fallback to AV_FRAME_DATA_DISPLAYMATRIX when AV_FRAME_DATA_EXIF 
exists but fails
in some way


> +
> +    /* av_display_matrix_flip is a right-multipilcation */
> +    /* i.e. flip is applied before the previous matrix */
> +    if (frame->linesize < 0)
> +        av_display_matrix_flip(matrix, 0, 1);

frame->linesize is an array, "frame->linesize < 0" makes no sense



> +
> +    orientation = av_exif_matrix_to_orientation(matrix);

this replace a full matrix by a 3bit orientation. This 3 bit orientation
may be a very poor representation of the matrix


> +    /* JPEG XL orientation flag agrees with EXIF for values 1-8 */
> +    if (orientation) {
> +        info.orientation = orientation;
> +    } else {
> +        av_log(avctx, AV_LOG_WARNING, "singular displaymatrix data\n");
> +        info.orientation = frame->linesize[0] >= 0 ? JXL_ORIENT_IDENTITY : 
> JXL_ORIENT_FLIP_VERTICAL;
> +    }

> +
> +    /* restore the previous value */
> +    if (frame->linesize < 0)
> +        av_display_matrix_flip(matrix, 0, 1);

frame->linesize is still an array


>  
>      if (animated) {
>          info.have_animation = 1;
> @@ -382,7 +431,8 @@ static int libjxl_preprocess_stream(AVCodecContext 
> *avctx, const AVFrame *frame,
>  
>      if (JxlEncoderSetBasicInfo(ctx->encoder, &info) != JXL_ENC_SUCCESS) {
>          av_log(avctx, AV_LOG_ERROR, "Failed to set JxlBasicInfo\n");
> -        return AVERROR_EXTERNAL;
> +        ret = AVERROR_EXTERNAL;
> +        goto end;
>      }
>  
>      sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE);
> @@ -399,6 +449,11 @@ static int libjxl_preprocess_stream(AVCodecContext 
> *avctx, const AVFrame *frame,
>          av_log(avctx, AV_LOG_WARNING, "Failed to set JxlBitDepth\n");
>  #endif
>  
> +    if (exif_buffer) {
> +        if (JxlEncoderUseBoxes(ctx->encoder) != JXL_ENC_SUCCESS)
> +            av_log(avctx, AV_LOG_WARNING, "Couldn't enable UseBoxes\n");
> +    }
> +
>      /* depending on basic info, level 10 might
>       * be required instead of level 5 */
>      if (JxlEncoderGetRequiredCodestreamLevel(ctx->encoder) > 5) {
> @@ -406,7 +461,9 @@ static int libjxl_preprocess_stream(AVCodecContext 
> *avctx, const AVFrame *frame,
>              av_log(avctx, AV_LOG_WARNING, "Could not increase codestream 
> level\n");
>      }
>  
> -    return 0;
> +end:
> +    av_buffer_unref(&exif_buffer);

is the build exif data ever passed into jxl ?
i see code allocating and building and code freeing it but no code actually
using it

thx

[...]

-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

During times of universal deceit, telling the truth becomes a
revolutionary act. -- George Orwell

Attachment: signature.asc
Description: PGP signature

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to