[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