[vlc-commits] [Git][videolan/vlc][master] 5 commits: packetizer: hevc: add hevc_get_slice_pic_output

François Cartegnie (@fcartegnie) gitlab at videolan.org
Wed Dec 13 06:59:37 UTC 2023



François Cartegnie pushed to branch master at VideoLAN / VLC


Commits:
c87eac4f by François Cartegnie at 2023-12-13T06:34:07+00:00
packetizer: hevc: add hevc_get_slice_pic_output

- - - - -
67900dd2 by François Cartegnie at 2023-12-13T06:34:07+00:00
packetizer: hevc: add hevc_get_slice_no_output_of_prior_pics_flag

- - - - -
00cdd098 by François Cartegnie at 2023-12-13T06:34:07+00:00
packetizer: h264: store IDR noprevoutput flag

- - - - -
9649db1a by François Cartegnie at 2023-12-13T06:34:07+00:00
packetizer: hevc: export poc variables

- - - - -
b5eeee71 by François Cartegnie at 2023-12-13T06:34:07+00:00
codec: videotoolbox: rework DPB closer to spec

- - - - -


8 changed files:

- modules/codec/videotoolbox/decoder.c
- modules/codec/videotoolbox/dpb.c
- modules/codec/videotoolbox/dpb.h
- modules/codec/videotoolbox/dpb_test.c
- modules/packetizer/h264_slice.c
- modules/packetizer/h264_slice.h
- modules/packetizer/hevc_nal.c
- modules/packetizer/hevc_nal.h


Changes:

=====================================
modules/codec/videotoolbox/decoder.c
=====================================
@@ -657,6 +657,16 @@ static bool FillReorderInfoHEVC(decoder_t *p_dec, const block_t *p_block,
                 p_info->b_keyframe |= (slice_type == HEVC_SLICE_TYPE_I);
             }
 
+            if( p_info->b_keyframe )
+            {
+                p_info->b_no_rasl_output = hevc_get_IRAPNoRaslOutputFlag( i_nal_type, &hevcctx->poc );
+                if ( i_nal_type == HEVC_NAL_CRA ) /* C.3.2 */
+                    p_info->b_no_output_of_prior_pics = true;
+                else
+                    p_info->b_no_output_of_prior_pics =
+                        hevc_get_slice_no_output_of_prior_pics_flag( p_sli );
+            }
+
             hevc_sequence_parameter_set_t *p_sps;
             hevc_picture_parameter_set_t *p_pps;
             hevc_video_parameter_set_t *p_vps;
@@ -677,9 +687,8 @@ static bool FillReorderInfoHEVC(decoder_t *p_dec, const block_t *p_block,
                 p_info->i_poc = POC;
                 p_info->i_foc = POC; /* clearly looks wrong :/ */
                 p_info->i_num_ts = hevc_get_num_clock_ts(p_sps, sei.p_timing);
-                uint8_t dummy;
-                hevc_get_dpb_values(p_sps, &p_info->i_max_pics_buffering, &dummy, &dummy);
-                VLC_UNUSED(dummy);
+                hevc_get_dpb_values(p_sps, &p_info->i_max_num_reorder,
+                                    &p_info->i_max_latency_pics, &p_info->i_max_pics_buffering);
                 p_info->b_flush = (POC == 0) ||
                                   (i_nal_type >= HEVC_NAL_IDR_N_LP &&
                                    i_nal_type <= HEVC_NAL_IRAP_VCL23);
@@ -703,6 +712,11 @@ static bool FillReorderInfoHEVC(decoder_t *p_dec, const block_t *p_block,
              * is likely failing to handle this case. */
             p_info->b_leading = ( i_nal_type == HEVC_NAL_RASL_N || i_nal_type == HEVC_NAL_RASL_R );
 
+            if(p_info->b_leading && p_sys->sync_state == STATE_BITSTREAM_DISCARD_LEADING)
+                p_info->b_output_needed = false;
+            else
+                p_info->b_output_needed = hevc_get_slice_pic_output(p_sli);
+
             hevc_rbsp_release_slice_header(p_sli);
             return true; /* No need to parse further NAL */
         }
@@ -788,9 +802,11 @@ static CFDictionaryRef CopyDecoderExtradataMPEG4(decoder_t *p_dec)
 static void DrainDPBLocked(decoder_t *p_dec, bool flush)
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
-    while (p_sys->dpb.i_size > 0)
+    struct dpb_s *dpb = &p_sys->dpb;
+    while (dpb->i_size > 0)
     {
-        picture_t *p_output = OutputNextFrameFromDPB(&p_sys->dpb, &p_sys->pts);
+        picture_t *p_output = DPBOutputFrame(dpb, &p_sys->pts,
+                                             dpb->p_entries);
         if(p_output)
         {
             if (flush)
@@ -798,6 +814,7 @@ static void DrainDPBLocked(decoder_t *p_dec, bool flush)
             else
                 decoder_QueueVideo(p_dec, p_output);
         }
+        RemoveDPBSlot(dpb, &dpb->p_entries);
     }
 }
 
@@ -808,6 +825,12 @@ static frame_info_t * CreateReorderInfo(decoder_t *p_dec, const block_t *p_block
     if (!p_info)
         return NULL;
 
+    /* failsafe defaults */
+    p_info->b_output_needed = true;
+    p_info->i_max_num_reorder = 0;
+    p_info->i_max_latency_pics = 0;
+    p_info->i_latency = 0;
+
     if (p_sys->pf_fill_reorder_info)
     {
         if (!p_sys->pf_fill_reorder_info(p_dec, p_block, p_info))
@@ -879,12 +902,13 @@ static void OnDecodedFrame(decoder_t *p_dec, frame_info_t *p_info)
         }
     }
 
-    while(p_info->b_flush || p_sys->dpb.i_size >= p_sys->dpb.i_max_pics)
+    for(picture_t *p_out = DPBOutputAndRemoval(&p_sys->dpb, &p_sys->pts, p_info);
+        p_out != NULL;)
     {
-        picture_t *p_output = OutputNextFrameFromDPB(&p_sys->dpb, &p_sys->pts);
-        if(!p_output)
-            break;
-        decoder_QueueVideo(p_dec, p_output);
+        picture_t *p_pic = p_out;
+        p_out = p_out->p_next;
+        p_pic->p_next = NULL;
+        decoder_QueueVideo(p_dec, p_pic);
     }
 
     InsertIntoDPB(&p_sys->dpb, p_info);
@@ -1233,7 +1257,7 @@ static void StopVideoToolbox(decoder_t *p_dec)
 
 static void pic_pacer_Destroy(void *priv)
 {
-    pic_pacer_Clean((struct pic_pacer *) priv);
+    pic_pacer_Clean((struct pic_pacer *)priv);
 }
 
 static int
@@ -1317,6 +1341,7 @@ static int OpenDecoder(vlc_object_t *p_this)
     p_sys->videoFormatDescription = NULL;
     p_sys->dpb.i_max_pics = 4;
     p_sys->dpb.i_fields_per_buffer = 1;
+    p_sys->dpb.pf_release = picture_Release;
     p_sys->vtsession_status = VTSESSION_STATUS_OK;
     p_sys->b_cvpx_format_forced = false;
     /* will be fixed later */


=====================================
modules/codec/videotoolbox/dpb.c
=====================================
@@ -50,20 +50,50 @@ void InsertIntoDPB(struct dpb_s *dpb, frame_info_t *p_info)
                 dpb->i_size = (dpb->i_stored_fields + 1)/2;
             else
                 dpb->i_size++;
+            if(p_info->b_output_needed)
+                dpb->i_need_output_size++;
+            assert(dpb->i_need_output_size <= dpb->i_stored_fields);
             break;
         }
     }
 #ifdef DPB_DEBUG
     for (frame_info_t *p_in=dpb->p_entries; p_in; p_in = p_in->p_next)
-        printf(" %d", p_in->i_foc);
+        printf(" %d(%cl%d)", p_in->i_foc, p_in->b_output_needed ? 'N' : '_', p_in->i_latency);
     printf("\n");
 #endif
 }
 
-picture_t * OutputNextFrameFromDPB(struct dpb_s *dpb, date_t *ptsdate)
+void RemoveDPBSlot(struct dpb_s *dpb, frame_info_t **pp_info)
 {
-    frame_info_t *p_info = dpb->p_entries;
-    if (p_info == NULL)
+    assert(dpb->i_stored_fields >= dpb->i_need_output_size);
+    frame_info_t *p_info = *pp_info;
+    if(!p_info)
+        return;
+    dpb->i_stored_fields -= (p_info->b_field ? 1 : 2);
+    if(dpb->i_fields_per_buffer == 2)
+        dpb->i_size = (dpb->i_stored_fields + 1)/2;
+    else
+        dpb->i_size--;
+
+    if(p_info->b_output_needed)
+    {
+        assert(dpb->i_need_output_size);
+        dpb->i_need_output_size--;
+    }
+    if(p_info->p_picture) /* release picture */
+        dpb->pf_release(p_info->p_picture);
+    *pp_info = p_info->p_next;
+    free(p_info);
+}
+
+static void ReduceDPBSize(struct dpb_s *dpb)
+{
+    RemoveDPBSlot(dpb, &dpb->p_entries);
+}
+
+picture_t * DPBOutputFrame(struct dpb_s *dpb, date_t *ptsdate, frame_info_t *p_info)
+{
+    if(!p_info)
         return NULL;
 
     /* Asynchronous fallback time init */
@@ -101,16 +131,122 @@ picture_t * OutputNextFrameFromDPB(struct dpb_s *dpb, date_t *ptsdate)
     {
         if( p_info->p_picture->date == VLC_TICK_INVALID )
             p_info->p_picture->date = p_info->pts;
+        p_info->p_picture = NULL; /* detach picture from DPB storage */
     }
 
-    dpb->i_stored_fields -= (p_info->b_field ? 1 : 2);
-    if(dpb->i_fields_per_buffer == 2)
-        dpb->i_size = (dpb->i_stored_fields + 1)/2;
-    else
-        dpb->i_size--;
+    if(p_info->b_output_needed) /* Tag storage as not used for output */
+    {
+        assert(dpb->i_need_output_size);
+        dpb->i_need_output_size--;
+        p_info->b_output_needed = false;
+    }
+    assert(dpb->i_need_output_size <= dpb->i_stored_fields);
 
-    dpb->p_entries = p_info->p_next;
-    free(p_info);
+    return p_output;
+}
+
+static picture_t * BumpDPB(struct dpb_s *dpb, date_t *ptsdate, const frame_info_t *p_info)
+{
+    picture_t *p_output = NULL;
+    picture_t **pp_output_next = &p_output;
+
+    for(;;)
+    {
+        bool b_output = false;
+
+        if(p_info->b_flush && dpb->i_size > 0)
+            b_output = true;
+        else if(dpb->i_size >= p_info->i_max_pics_buffering)
+            b_output = true;
+        else if(p_info->i_max_num_reorder > 0 &&
+                 dpb->i_need_output_size > p_info->i_max_num_reorder)
+            b_output = true;
+        else if(p_info->i_max_latency_pics > 0 &&
+                 dpb->i_need_output_size > 0 )
+        {
+            for(const frame_info_t *p = dpb->p_entries; p; p = p->p_next)
+            {
+                if(p->b_output_needed &&
+                   p->i_latency >= p_info->i_max_latency_pics)
+                {
+                    b_output = true;
+                    break;
+                }
+            }
+        }
+
+        if(!b_output)
+            break;
+
+        *pp_output_next = DPBOutputFrame(dpb, ptsdate, dpb->p_entries);
+        if(*pp_output_next)
+            pp_output_next = &((*pp_output_next)->p_next);
+
+        ReduceDPBSize(dpb);
+    };
 
     return p_output;
 }
+
+picture_t * EmptyDPB(struct dpb_s *dpb, date_t *ptsdate)
+{
+    picture_t *output = NULL;
+    picture_t **pp_output_next = &output;
+    while(dpb->i_size > 0)
+    {
+        *pp_output_next = DPBOutputFrame(dpb, ptsdate, dpb->p_entries);
+        if(*pp_output_next)
+            pp_output_next = &((*pp_output_next)->p_next);
+        ReduceDPBSize(dpb);
+    }
+    return output;
+}
+
+picture_t * DPBOutputAndRemoval(struct dpb_s *dpb, date_t *ptsdate,
+                                const frame_info_t *p_info)
+{
+    picture_t *output = NULL;
+
+    /* C 5.2.3 Additional Bumping */
+    if(p_info->b_output_needed)
+    {
+        for(frame_info_t *p = dpb->p_entries; p; p = p->p_next)
+            if(p->b_output_needed && p->i_foc > p_info->i_foc)
+                p->i_latency++;
+    }
+
+    /* IRAP picture with NoRaslOutputFlag */
+    if(p_info->b_no_rasl_output && p_info->b_keyframe)
+    {
+        if(p_info->b_no_output_of_prior_pics)
+        {
+            /* discard everything */
+            output = EmptyDPB(dpb, ptsdate);
+        }
+        else
+        {
+            /* clean-up only non-ref && non-needed */
+            for(frame_info_t **pp_next = &dpb->p_entries; *pp_next;)
+            {
+                if(!(*pp_next)->b_output_needed)
+                    RemoveDPBSlot(dpb, pp_next);
+                else
+                    pp_next = &((*pp_next)->p_next);
+            }
+        }
+
+        while(output)
+        {
+            picture_t *next = output->p_next;
+            output->p_next = NULL;
+            dpb->pf_release(output);
+            output = next;
+        }
+    }
+    else /* Regular bump process */
+    {
+        output = BumpDPB(dpb, ptsdate, p_info);
+    }
+
+    return output;
+}


=====================================
modules/codec/videotoolbox/dpb.h
=====================================
@@ -44,8 +44,14 @@ struct frame_info_t
     bool b_field;
     bool b_progressive;
     bool b_top_field_first;
+    bool b_output_needed;
+    bool b_no_output_of_prior_pics;
+    bool b_no_rasl_output;
     uint8_t i_num_ts;
     uint8_t i_max_pics_buffering;
+    uint8_t i_max_num_reorder;
+    uint8_t i_max_latency_pics;
+    uint8_t i_latency;
     unsigned i_length;
     frame_info_t *p_next;
 };
@@ -55,15 +61,23 @@ struct dpb_s
     frame_info_t *p_entries;
     uint8_t i_size; /* number of virtual buffers used (depends on i_fields_per_buffer) */
     uint8_t i_stored_fields;
+    uint8_t i_need_output_size;
     uint8_t i_max_pics;
     uint8_t i_fields_per_buffer; /* stores 2 fields or 1 field/frame per buffer */
     bool b_strict_reorder;
     bool b_invalid_pic_reorder_max;
     bool b_poc_based_reorder;
+    void (*pf_release)(picture_t *);
 };
 
 void InsertIntoDPB(struct dpb_s *, frame_info_t *);
 
-picture_t * OutputNextFrameFromDPB(struct dpb_s *, date_t *);
+void RemoveDPBSlot(struct dpb_s *, frame_info_t **);
+
+picture_t * EmptyDPB(struct dpb_s *, date_t *);
+
+picture_t * DPBOutputFrame(struct dpb_s *, date_t *, frame_info_t *);
+
+picture_t * DPBOutputAndRemoval(struct dpb_s *, date_t *, const frame_info_t *);
 
 #endif // VIDEOTOOLBOX_DPB_H


=====================================
modules/codec/videotoolbox/dpb_test.c
=====================================
@@ -71,23 +71,29 @@ static void VaCheckOutput(picture_t *output, va_list ap)
     for(;;)
     {
         int poc = va_arg(ap, int);
+        int outpoc;
+        if(output)
+        {
+            outpoc = ((uint64_t)output->p_sys);
+            fprintf(stderr, "output %d, ", outpoc);
+        }
+        else
+        {
+            fprintf(stderr, "no output, ");
+        }
         if(poc == -1)
         {
-            fprintf(stderr, "no output expected\n");
+            fprintf(stderr, "no output was expected\n");
             assert(output == NULL);
             break;
         }
+        fprintf(stderr, "%d was expected\n", poc);
         if(output == NULL)
-        {
-            fprintf(stderr, "no output, was expected %d", poc);
             abort();
-        }
-        int outpoc = ((uint64_t)output->p_sys);
-        fprintf(stderr, "output %d, expected %d\n", outpoc, poc);
         assert(outpoc == poc);
         picture_t *next = output->p_next;
         output->p_next = NULL;
-        pic_release(output);
+        free(output);
         output = next;
     };
     assert(output == NULL);
@@ -96,15 +102,7 @@ static void VaCheckOutput(picture_t *output, va_list ap)
 static void CheckDrain(struct dpb_s *dpb, date_t *ptsdate, ...)
 {
     fprintf(stderr,"drain\n");
-    picture_t *output = NULL;
-    picture_t **next = &output;
-    while(dpb->i_size)
-    {
-        *next = OutputNextFrameFromDPB(dpb, ptsdate);
-        if(!*next)
-            break;
-        next = &((*next)->p_next);
-    }
+    picture_t *output = EmptyDPB(dpb, ptsdate);
     va_list args;
     va_start(args, ptsdate);
     VaCheckOutput(output, args);
@@ -113,18 +111,9 @@ static void CheckDrain(struct dpb_s *dpb, date_t *ptsdate, ...)
 
 static void CheckOutput(struct dpb_s *dpb, date_t *ptsdate, frame_info_t *info, ...)
 {
-    fprintf(stderr, "enqueing foc %d flush %d dpb sz %d\n", info->i_foc,
-            info->b_flush, dpb->i_size);
-    dpb->i_max_pics = info->i_max_pics_buffering;
-    picture_t *output = NULL;
-    picture_t **next = &output;
-    while(info->b_flush || dpb->i_size >= dpb->i_max_pics)
-    {
-        *next = OutputNextFrameFromDPB(dpb, ptsdate);
-        if(!*next)
-            break;
-        next = &((*next)->p_next);
-    }
+    fprintf(stderr, "enqueing foc %d flush %d dpb sz %d ndsz %d\n", info->i_foc,
+            info->b_flush, dpb->i_size, dpb->i_need_output_size);
+    picture_t *output = DPBOutputAndRemoval(dpb, ptsdate, info);
     assert(dpb->i_size < DPB_MAX_PICS);
     va_list args;
     va_start(args, info);
@@ -139,14 +128,19 @@ static void CheckDPBWithFramesTest()
     dpb.b_strict_reorder = true;
     dpb.b_poc_based_reorder = true;
     dpb.i_fields_per_buffer = 2;
+    dpb.pf_release = pic_release;
 
     frame_info_t info = {0};
     info.field_rate_num = 30000;
     info.field_rate_den = 1000;
     info.b_progressive = true;
+    info.b_output_needed = true;
     info.b_top_field_first = true;
     info.i_num_ts = 2;
     info.i_max_pics_buffering = 4;
+    info.i_max_num_reorder = 0;
+    info.i_max_latency_pics = 0;
+    info.i_latency = 0;
 
     date_t pts;
     date_Init(&pts, info.field_rate_num, info.field_rate_den);
@@ -207,6 +201,99 @@ static void CheckDPBWithFramesTest()
     assert(dpb.i_size == 1);
 
     CheckDrain(&dpb, &pts, 0, -1);
+    assert(dpb.i_size == 0);
+
+    /* dual parameters */
+    info.i_max_pics_buffering = 10;
+    info.i_max_num_reorder = 2;
+
+    info.i_foc = 4;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1);
+
+    info.i_foc = 2;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1);
+
+    info.i_foc = 8;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1); /* dpb.i_size == max_num_reorder before enqueue */
+
+    info.i_foc = 6;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), 2, -1); /* dpb.i_size > max_num_reorder before enqueue */
+
+    /* plain drained reorder output, no pre enqueue BUMP */
+    CheckDrain(&dpb, &pts, 4, 6, 8, -1);
+
+    /* RASL, non-needed slots */
+    info.i_max_pics_buffering = 10; /* let's trigger on needed output only */
+
+    info.i_foc = 22;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    info.b_output_needed = false;
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1);
+
+    info.i_foc = 20;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    info.b_output_needed = true;
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1);
+
+    info.i_foc = 24;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1);
+
+    assert(dpb.i_size < info.i_max_pics_buffering);
+    assert(dpb.i_need_output_size == info.i_max_num_reorder);
+
+    info.i_foc = 26;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1);
+
+    info.i_foc = 28;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), 20, -1);
+
+    CheckDrain(&dpb, &pts, 22, 24, 26, 28, -1);
+
+    assert(dpb.i_size == 0);
+
+    /* Max latency requirements */
+    info.i_max_pics_buffering = 10;
+    info.i_max_num_reorder = 7;
+    info.i_max_latency_pics = 3;
+    info.b_output_needed = true;
+
+    info.i_foc = 10;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1); /* latency == 0 */
+
+    info.i_foc = 8;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1); /* latency == 1 */
+
+    info.i_foc = 6;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), -1); /* latency == 2 */
+
+    info.i_foc = 2;
+    info.i_poc = info.i_foc & ~1;
+    info.b_flush = (info.i_foc == 0);
+    CheckOutput(&dpb, &pts, withpic(infocopy(&info), info.i_foc), 6, 8, 10, -1); /* 10 has latency == 3 */
+
+    CheckDrain(&dpb, &pts, 2, -1);
 
     assert(dpb.i_size == 0);
 }


=====================================
modules/packetizer/h264_slice.c
=====================================
@@ -185,7 +185,12 @@ bool h264_decode_slice( const uint8_t *p_buffer, size_t i_buffer,
     }
 
     /* dec_ref_pic_marking() */
-    if( p_slice->i_nal_type != 5 ) /* IdrFlag */
+    if( p_slice->i_nal_type == 5 ) /* IdrFlag */
+    {
+        p_slice->no_output_of_prior_pics_flag = bs_read1( &s );
+        bs_skip( &s, 1 ); /* long_term_reference_flag */
+    }
+    else
     {
         if( bs_read1( &s ) ) /* adaptive_ref_pic_marking_mode_flag */
         {


=====================================
modules/packetizer/h264_slice.h
=====================================
@@ -51,6 +51,7 @@ typedef struct
     int i_delta_pic_order_cnt0;
     int i_delta_pic_order_cnt1;
 
+    bool no_output_of_prior_pics_flag;
     bool has_mmco5;
 } h264_slice_t;
 


=====================================
modules/packetizer/hevc_nal.c
=====================================
@@ -1041,6 +1041,11 @@ uint8_t hevc_get_slice_pps_id( const hevc_slice_segment_header_t *p_slice )
     return p_slice->slice_pic_parameter_set_id;
 }
 
+bool hevc_get_slice_no_output_of_prior_pics_flag( const hevc_slice_segment_header_t *p_slice )
+{
+    return p_slice->no_output_of_prior_pics_flag;
+}
+
 bool hevc_get_sps_profile_tier_level( const hevc_sequence_parameter_set_t *p_sps,
                                       uint8_t *pi_profile, uint8_t *pi_level)
 {
@@ -1341,6 +1346,11 @@ bool hevc_get_slice_type( const hevc_slice_segment_header_t *p_sli, enum hevc_sl
     return false;
 }
 
+bool hevc_get_slice_pic_output( const hevc_slice_segment_header_t *p_sli )
+{
+    return p_sli->pic_output_flag;
+}
+
 bool hevc_get_profile_level(const es_format_t *p_fmt, uint8_t *pi_profile,
                             uint8_t *pi_level, uint8_t *pi_nal_length_size)
 {
@@ -1558,6 +1568,24 @@ uint8_t * hevc_create_dcr( const struct hevc_dcr_params *p_params,
 #undef HEVC_DCR_ADD_NALS
 #undef HEVC_DCR_ADD_SIZES
 
+bool hevc_NAL_IsIRAP( uint8_t i_nal_type )
+{
+    return ( i_nal_type >= HEVC_NAL_BLA_W_LP &&
+             i_nal_type <= HEVC_NAL_IRAP_VCL23 );
+}
+
+bool hevc_get_IRAPNoRaslOutputFlag( uint8_t i_nal_type,
+                                    const hevc_poc_ctx_t *p_ctx )
+{
+    /* if( IRAP ) NoRaslOutputFlag = first || IDR || BLA || after(EOSNAL) */
+    return ( p_ctx->first_picture ||
+             i_nal_type == HEVC_NAL_IDR_N_LP ||
+             i_nal_type == HEVC_NAL_IDR_W_RADL ||
+             i_nal_type == HEVC_NAL_BLA_W_LP ||
+             i_nal_type == HEVC_NAL_BLA_W_RADL ||
+             i_nal_type == HEVC_NAL_BLA_N_LP ||
+             p_ctx->HandleCraAsBlaFlag );
+}
 
 /*
  * 8.3.1 Decoding process for POC
@@ -1572,25 +1600,9 @@ int hevc_compute_picture_order_count( const hevc_sequence_parameter_set_t *p_sps
         int msb;
     } prevPicOrderCnt;
     int pocMSB;
-    bool NoRaslOutputFlag;
-    bool IsIRAP = ( p_slice->nal_type >= HEVC_NAL_BLA_W_LP &&
-                    p_slice->nal_type <= HEVC_NAL_IRAP_VCL23 );
-
-    if( IsIRAP )
-    {
-        /* if( IRAP ) NoRaslOutputFlag = first || IDR || BLA || after(EOSNAL) */
-        NoRaslOutputFlag =(p_ctx->first_picture ||
-                           p_slice->nal_type == HEVC_NAL_IDR_N_LP ||
-                           p_slice->nal_type == HEVC_NAL_IDR_W_RADL ||
-                           p_slice->nal_type == HEVC_NAL_BLA_W_LP ||
-                           p_slice->nal_type == HEVC_NAL_BLA_W_RADL ||
-                           p_slice->nal_type == HEVC_NAL_BLA_N_LP ||
-                           p_ctx->HandleCraAsBlaFlag );
-    }
-    else
-    {
-        NoRaslOutputFlag = false;
-    }
+    const bool IsIRAP = hevc_NAL_IsIRAP( p_slice->nal_type );
+    const bool NoRaslOutputFlag =
+        IsIRAP ? hevc_get_IRAPNoRaslOutputFlag( p_slice->nal_type, p_ctx ) : false;
 
 #ifdef HEVC_POC_DEBUG
     printf("slice lsb=%"PRIu32" irap=%d norasl=%d tid=%d msb=%d lsb=%d",


=====================================
modules/packetizer/hevc_nal.h
=====================================
@@ -277,6 +277,7 @@ void hevc_rbsp_release_slice_header( hevc_slice_segment_header_t * );
 uint8_t hevc_get_sps_vps_id( const hevc_sequence_parameter_set_t * );
 uint8_t hevc_get_pps_sps_id( const hevc_picture_parameter_set_t * );
 uint8_t hevc_get_slice_pps_id( const hevc_slice_segment_header_t * );
+bool hevc_get_slice_no_output_of_prior_pics_flag( const hevc_slice_segment_header_t * );
 
 bool hevc_get_xps_id(const uint8_t *p_nalbuf, size_t i_nalbuf, uint8_t *pi_id);
 bool hevc_get_sps_profile_tier_level( const hevc_sequence_parameter_set_t *,
@@ -302,6 +303,7 @@ bool hevc_get_colorimetry( const hevc_sequence_parameter_set_t *p_sps,
 void hevc_get_dpb_values( const hevc_sequence_parameter_set_t *, uint8_t *num_reorder_pics,
                           uint8_t *max_latency_pics, uint8_t *max_dec_pic_buffering );
 bool hevc_get_slice_type( const hevc_slice_segment_header_t *, enum hevc_slice_type_e * );
+bool hevc_get_slice_pic_output( const hevc_slice_segment_header_t * );
 
 /* Get level and Profile from DecoderConfigurationRecord */
 bool hevc_get_profile_level(const es_format_t *p_fmt, uint8_t *pi_profile,
@@ -376,6 +378,10 @@ static inline void hevc_poc_cxt_init( hevc_poc_ctx_t *p_ctx )
 int hevc_compute_picture_order_count( const hevc_sequence_parameter_set_t *p_sps,
                                        const hevc_slice_segment_header_t *slice,
                                        hevc_poc_ctx_t *ctx );
+bool hevc_NAL_IsIRAP( uint8_t i_nal_type );
+bool hevc_get_IRAPNoRaslOutputFlag( uint8_t nal_type,
+                                    const hevc_poc_ctx_t *);
+
 
 typedef struct hevc_sei_pic_timing_t hevc_sei_pic_timing_t;
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9bc7ded0f0e3a06b8ad4b00fdcadca1debf1ca9f...b5eeee7108ad8d5052387300f6a3880769526862

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/9bc7ded0f0e3a06b8ad4b00fdcadca1debf1ca9f...b5eeee7108ad8d5052387300f6a3880769526862
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list