From 62300afa32e5ccacb49856c5d4f3ca6c6636359b Mon Sep 17 00:00:00 2001
From: CaiYuHan <240947104@qq.com>
Date: Wed, 15 Sep 2021 10:27:16 +0800
Subject: [PATCH] libavcodec/h264_slice.c:Add SVC decoding function based on
 Temporal scalability for H.264/AVC

Signed-off-by: CaiYuHan <240947104@qq.com>
---
 libavcodec/h264_slice.c | 252 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 250 insertions(+), 2 deletions(-)
 mode change 100644 => 100755 libavcodec/h264_slice.c

diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
old mode 100644
new mode 100755
index 201b224..37d6fc4
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -2032,6 +2032,232 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
 
     return 0;
 }
+/**
+ *Add SVC decoding function based on Temporal scalability for H.264/AVC
+*/
+#if SVC_DEC_H264
+/*G.7.3.3.4 See ITU H264-201304*/
+static int h264_slice_header_in_scalable_ext_parse(const H264Context *h, H264SliceContext *sl,
+                                   const H2645NAL *nal)
+{
+	const SPS *sps;
+    const PPS *pps;
+    int ret;
+    unsigned int slice_type, tmp, i;
+    int field_pic_flag, bottom_field_flag;
+    int first_slice = sl == h->slice_ctx && !h->current_slice;
+    int picture_structure;
+	int base_pred_weight_table_flag;
+	int store_ref_base_pic_flag;
+
+
+    if (first_slice)
+        av_assert0(!h->setup_finished);
+
+    sl->first_mb_addr = get_ue_golomb_long(&sl->gb);
+
+    slice_type = get_ue_golomb_31(&sl->gb);
+    if (slice_type > 9) {
+        av_log(h->avctx, AV_LOG_ERROR,
+               "slice type %d too large at %d\n",
+               slice_type, sl->first_mb_addr);
+        return AVERROR_INVALIDDATA;
+    }
+    if (slice_type > 4) {
+        slice_type -= 5;
+        sl->slice_type_fixed = 1;
+    } else
+        sl->slice_type_fixed = 0;
+
+    slice_type         = ff_h264_golomb_to_pict_type[slice_type];
+    sl->slice_type     = slice_type;
+    sl->slice_type_nos = slice_type & 3;
+
+    if (nal->type  == H264_NAL_IDR_SLICE &&
+        sl->slice_type_nos != AV_PICTURE_TYPE_I) {
+        av_log(h->avctx, AV_LOG_ERROR, "A non-intra slice in an IDR NAL unit.\n");
+        return AVERROR_INVALIDDATA;
+    }
+
+    sl->pps_id = get_ue_golomb(&sl->gb);
+    if (sl->pps_id >= MAX_PPS_COUNT) {
+        av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", sl->pps_id);
+        return AVERROR_INVALIDDATA;
+    }
+    if (!h->ps.pps_list[sl->pps_id]) {
+        av_log(h->avctx, AV_LOG_ERROR,
+               "non-existing PPS %u referenced\n",
+               sl->pps_id);
+        return AVERROR_INVALIDDATA;
+    }
+    pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;
+
+    if (!h->ps.sps_list[pps->sps_id]) {
+        av_log(h->avctx, AV_LOG_ERROR,
+               "non-existing SPS %u referenced\n", pps->sps_id);
+        return AVERROR_INVALIDDATA;
+    }
+    sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data;
+
+    sl->frame_num = get_bits(&sl->gb, sps->log2_max_frame_num);
+    if (!first_slice) {
+        if (h->poc.frame_num != sl->frame_num) {
+            av_log(h->avctx, AV_LOG_ERROR, "Frame num change from %d to %d\n",
+                   h->poc.frame_num, sl->frame_num);
+            return AVERROR_INVALIDDATA;
+        }
+    }
+
+    sl->mb_mbaff       = 0;
+
+    if (sps->frame_mbs_only_flag) {
+        picture_structure = PICT_FRAME;
+    } else {
+        if (!sps->direct_8x8_inference_flag && slice_type == AV_PICTURE_TYPE_B) {
+            av_log(h->avctx, AV_LOG_ERROR, "This stream was generated by a broken encoder, invalid 8x8 inference\n");
+            return -1;
+        }
+        field_pic_flag = get_bits1(&sl->gb);
+        if (field_pic_flag) {
+            bottom_field_flag = get_bits1(&sl->gb);
+            picture_structure = PICT_TOP_FIELD + bottom_field_flag;
+        } else {
+            picture_structure = PICT_FRAME;
+        }
+    }
+    sl->picture_structure      = picture_structure;
+    sl->mb_field_decoding_flag = picture_structure != PICT_FRAME;
+
+    if (picture_structure == PICT_FRAME) {
+        sl->curr_pic_num = sl->frame_num;
+        sl->max_pic_num  = 1 << sps->log2_max_frame_num;
+    } else {
+        sl->curr_pic_num = 2 * sl->frame_num + 1;
+        sl->max_pic_num  = 1 << (sps->log2_max_frame_num + 1);
+    }
+
+	if(nal->idr_flag==1) //judge idr_flag for svc ext
+        get_ue_golomb_long(&sl->gb); /* idr_pic_id */
+
+    if (sps->poc_type == 0) {
+        sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb);
+
+        if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME)
+            sl->delta_poc_bottom = get_se_golomb(&sl->gb);
+    }
+
+    if (sps->poc_type == 1 && !sps->delta_pic_order_always_zero_flag) {
+        sl->delta_poc[0] = get_se_golomb(&sl->gb);
+
+        if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME)
+            sl->delta_poc[1] = get_se_golomb(&sl->gb);
+    }
+
+    sl->redundant_pic_count = 0;
+    if (pps->redundant_pic_cnt_present)
+        sl->redundant_pic_count = get_ue_golomb(&sl->gb);
+
+	if(nal->quality_id==0)
+	{
+		if (sl->slice_type_nos == AV_PICTURE_TYPE_B)
+			sl->direct_spatial_mv_pred = get_bits1(&sl->gb);
+
+		ret = ff_h264_parse_ref_count(&sl->list_count, sl->ref_count,
+									  &sl->gb, pps, sl->slice_type_nos,
+									  picture_structure, h->avctx);
+		if (ret < 0)
+			return ret;
+
+		if (sl->slice_type_nos != AV_PICTURE_TYPE_I) {
+		   ret = ff_h264_decode_ref_pic_list_reordering(sl, h->avctx); //not need fix for svc
+		   if (ret < 0) {
+			   sl->ref_count[1] = sl->ref_count[0] = 0;
+			   return ret;
+		   }
+		}
+
+		sl->pwt.use_weight = 0;
+		for (i = 0; i < 2; i++) {
+			sl->pwt.luma_weight_flag[i]   = 0;
+			sl->pwt.chroma_weight_flag[i] = 0;
+		}
+		if ((pps->weighted_pred && sl->slice_type_nos == AV_PICTURE_TYPE_P) ||
+			(pps->weighted_bipred_idc == 1 &&
+			 sl->slice_type_nos == AV_PICTURE_TYPE_B))
+			{
+				if( !(nal->no_inter_layer_pred_flag))
+					base_pred_weight_table_flag = get_bits1(&sl->gb);//base_pred_weight_table_flag
+				if( nal->no_inter_layer_pred_flag || !base_pred_weight_table_flag)
+						ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count,
+                                  sl->slice_type_nos, &sl->pwt,
+                                  picture_structure, h->avctx);
+			}
+		sl->explicit_ref_marking = 0;
+		if (nal->ref_idc) {
+			ret = ff_h264_decode_ref_pic_marking(sl, &sl->gb, nal, h->avctx);
+			if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
+				return AVERROR_INVALIDDATA;
+			
+			if( !(sps->slice_header_restriction_flag))
+			{
+				store_ref_base_pic_flag = get_bits1(&sl->gb);//store_ref_base_pic_flag
+				if( (nal->use_ref_base_pic_flag || store_ref_base_pic_flag) && !(nal->idr_flag))
+					ff_h264_decode_ref_base_pic_marking(sl, &sl->gb, nal, h->avctx);
+				}
+			}
+	}
+
+    if (sl->slice_type_nos != AV_PICTURE_TYPE_I && pps->cabac) {
+        tmp = get_ue_golomb_31(&sl->gb);//cabac_init_idc
+        if (tmp > 2) {
+            av_log(h->avctx, AV_LOG_ERROR, "cabac_init_idc %u overflow\n", tmp);
+            return AVERROR_INVALIDDATA;
+        }
+        sl->cabac_init_idc = tmp;
+    }
+
+    sl->last_qscale_diff = 0;
+    tmp = pps->init_qp + get_se_golomb(&sl->gb);
+    if (tmp > 51 + 6 * (sps->bit_depth_luma - 8)) {
+        av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp);
+        return AVERROR_INVALIDDATA;
+    }
+    sl->qscale       = tmp;
+    sl->chroma_qp[0] = get_chroma_qp(pps, 0, sl->qscale);
+    sl->chroma_qp[1] = get_chroma_qp(pps, 1, sl->qscale);
+
+    sl->deblocking_filter     = 1;
+    sl->slice_alpha_c0_offset = 0;
+    sl->slice_beta_offset     = 0;
+    if (pps->deblocking_filter_parameters_present) {
+        tmp = get_ue_golomb_31(&sl->gb);
+        if (tmp > 2) {
+            av_log(h->avctx, AV_LOG_ERROR,
+                   "deblocking_filter_idc %u out of range\n", tmp);
+            return AVERROR_INVALIDDATA;
+        }
+        sl->deblocking_filter = tmp;
+        if (sl->deblocking_filter < 2)
+            sl->deblocking_filter ^= 1; // 1<->0
+
+        if (sl->deblocking_filter) {
+            sl->slice_alpha_c0_offset = get_se_golomb(&sl->gb) * 2;
+            sl->slice_beta_offset     = get_se_golomb(&sl->gb) * 2;
+            if (sl->slice_alpha_c0_offset >  12 ||
+                sl->slice_alpha_c0_offset < -12 ||
+                sl->slice_beta_offset >  12     ||
+                sl->slice_beta_offset < -12) {
+                av_log(h->avctx, AV_LOG_ERROR,
+                       "deblocking filter parameters %d %d out of range\n",
+                       sl->slice_alpha_c0_offset, sl->slice_beta_offset);
+                return AVERROR_INVALIDDATA;
+            }
+        }
+    }
+
+    return 0;
+}
+#endif
 
 /* do all the per-slice initialization needed before we can start decoding the
  * actual MBs */
@@ -2171,15 +2397,24 @@ static int h264_slice_init(H264Context *h, H264SliceContext *sl,
     return 0;
 }
 
-int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal)
+int ff_h264_queue_decode_slice(H264Context *h, /*const*/ H2645NAL *nal)
 {
     H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued;
     int first_slice = sl == h->slice_ctx && !h->current_slice;
     int ret;
 
     sl->gb = nal->gb;
-
+/**
+ *Add SVC decoding function based on Temporal scalability for H.264/AVC
+*/
+#if SVC_DEC_H264 //7.3.2.13 see ITU H264-201304
+    if(nal->type==H264_NAL_EXTEN_SLICE && nal->svc_ext_flag==1)
+		ret = h264_slice_header_in_scalable_ext_parse(h, sl, nal);
+	else
+		ret = h264_slice_header_parse(h, sl, nal);
+#else
     ret = h264_slice_header_parse(h, sl, nal);
+#endif
     if (ret < 0)
         return ret;
 
@@ -2188,6 +2423,19 @@ int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal)
         sl->ref_count[0] = sl->ref_count[1] = 0;
         return 0;
     }
+/**
+ *Add SVC decoding function based on Temporal scalability for H.264/AVC
+*/
+#if SVC_DEC_H264 //used for svc
+	if(nal->type==H264_NAL_EXTEN_SLICE && nal->svc_ext_flag==1 && nal->idr_flag==1)
+	{
+		nal->type = H264_NAL_IDR_SLICE;
+	}
+	else if (nal->type==H264_NAL_EXTEN_SLICE && nal->svc_ext_flag==1 && nal->idr_flag==0)
+	{
+		nal->type = H264_NAL_SLICE;
+	}
+#endif
 
     if (sl->first_mb_addr == 0 || !h->current_slice) {
         if (h->setup_finished) {
-- 
2.29.2

