--- libavcodec/h264_parser.c.orig	2023-11-11 01:25:17.000000000 +0100
+++ libavcodec/h264_parser.c	2024-05-30 01:09:42.571921235 +0200
@@ -67,6 +67,103 @@
     int last_frame_num, last_picture_structure;
 } H264ParseContext;
 
+#include "ff_spsinfo.h" // MEANX
+#include <assert.h>
+ // MEANX
+int ff_h264_info(AVCodecParserContext *parser, int ticksPerFrame, ffSpsInfo *info);
+/**
+    \fn AVCodecParserContext
+    \brief find a valid sps, take the 1st one that looks ok
+*/
+static const SPS *findValidSPS(H264ParamSets *ps)
+{
+    int i;
+    if(!ps)
+    {
+        av_log(NULL, AV_LOG_ERROR, "findValidSPS called with invalid data\n");
+        return NULL;
+    }
+    for (i = 0; i<MAX_SPS_COUNT; i++)
+    {
+        const SPS *sps = ps->sps_list[i];
+        if (sps && sps->mb_width)
+            return sps;
+    }
+    av_log(NULL, AV_LOG_ERROR, "findValidSPS no valid SPS found\n");
+    return NULL;
+}
+/**
+ * 
+ * @param parser
+ * @param info
+ * @return 
+ */
+int ff_h264_info(AVCodecParserContext *parser, int ticksPerFrame, ffSpsInfo *info)
+{
+    H264ParseContext *ctx = parser->priv_data;
+    int f;
+    const SPS *sps;
+    memset(info,0,sizeof(*info));
+    sps=findValidSPS(&(ctx->ps));
+    if(!sps)
+    {
+        return 0;
+    }
+    info->width=sps->mb_width  * 16;
+    info->height=sps->mb_height * 16;
+    if(sps->timing_info_present_flag)
+    {
+        float scale=sps->time_scale ;
+        float ticks=sps->num_units_in_tick;
+        float fps = scale/ticks;
+        if(ticksPerFrame>1)
+            fps /= ticksPerFrame;
+        info->fps1000 = (uint32_t)(fps * 1000.);
+#undef printf
+        printf("Scale : %d, tick=%d, fps=%d\n",(int)scale,(int)ticks,(int)info->fps1000);
+    }else
+    {
+        printf("[H264] No timing information\n");
+    }
+    // D.2.2 SEI Timing present if CpbDbpDelayPresentFlag=1 or pictStructPresent=1
+    // CpbDbpDelayPresentFlag =1 if nal_hdr or vcl_hrd or ???
+    f=sps->nal_hrd_parameters_present_flag | sps->vcl_hrd_parameters_present_flag;
+    info->hasStructInfo=f | sps->pic_struct_present_flag;
+    // Check whether POC is explicitely set in slice header
+    info->hasPocInfo=!sps->poc_type;
+    // While decoding SEI, if CpbDpbDelaysPresentFlags is there we skip cpb_removal_delay + dpb_output_delay
+
+    info->CpbDpbToSkip=0;
+    if(f)
+    {
+        info->CpbDpbToSkip=sps->cpb_removal_delay_length+sps->dpb_output_delay_length;
+    }
+    info->log2MaxFrameNum=sps->log2_max_frame_num;
+    info->log2MaxPocLsb=sps->log2_max_poc_lsb;
+    // Needed to determine the offset of poc_lsb
+    info->frameMbsOnlyFlag=sps->frame_mbs_only_flag;
+    //#warning fixme sar vs dar
+    if(sps->vui_parameters_present_flag)
+    {
+        info->darNum = sps->vui.sar.num;
+        info->darDen = sps->vui.sar.den;
+    }else
+    {
+        info->darNum = info->darDen = 1;
+    }
+    if(sps->crop_left || sps->crop_right || sps->crop_top || sps->crop_bottom)
+    {
+        printf("Taking crop into account, left: %u, right: %u, top: %u, bottom: %u\n",
+            sps->crop_left, sps->crop_right, sps->crop_top, sps->crop_bottom);
+        // frame_cropping_flag and frame_mbs_only_flag have been taken into account by libavcodec already
+        info->width  -= sps->crop_left + sps->crop_right;
+        info->height -= sps->crop_top  + sps->crop_bottom;
+    }
+    info->refFrames=sps->ref_frame_count;
+    return 1;
+}
+// /MEANX
+
 static int find_start_code(const uint8_t *buf, int buf_size,
                                   int buf_index, int next_avc)
 {
