summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/state_trackers/omx/vid_dec.h3
-rw-r--r--src/gallium/state_trackers/omx/vid_dec_h265.c215
2 files changed, 216 insertions, 2 deletions
diff --git a/src/gallium/state_trackers/omx/vid_dec.h b/src/gallium/state_trackers/omx/vid_dec.h
index 20b595852a4..ef57711a31a 100644
--- a/src/gallium/state_trackers/omx/vid_dec.h
+++ b/src/gallium/state_trackers/omx/vid_dec.h
@@ -97,7 +97,10 @@ DERIVEDCLASS(vid_dec_PrivateType, omx_base_filter_PrivateType)
struct { \
unsigned temporal_id; \
unsigned level_idc; \
+ bool IdrPicFlag; \
+ int slice_prev_poc; \
void *ref_pic_set_list; \
+ void *rps; \
struct pipe_h265_sps sps[16]; \
struct pipe_h265_pps pps[64]; \
struct list_head dpb_list; \
diff --git a/src/gallium/state_trackers/omx/vid_dec_h265.c b/src/gallium/state_trackers/omx/vid_dec_h265.c
index b3b13578a57..4bc9b2cb7c1 100644
--- a/src/gallium/state_trackers/omx/vid_dec_h265.c
+++ b/src/gallium/state_trackers/omx/vid_dec_h265.c
@@ -72,6 +72,20 @@ struct ref_pic_set {
bool used[MAX_NUM_REF_PICS];
};
+static bool is_idr_picture(unsigned nal_unit_type)
+{
+ return (nal_unit_type == NAL_UNIT_TYPE_IDR_W_RADL ||
+ nal_unit_type == NAL_UNIT_TYPE_IDR_N_LP);
+}
+
+/* broken link access picture */
+static bool is_bla_picture(unsigned nal_unit_type)
+{
+ return (nal_unit_type == NAL_UNIT_TYPE_BLA_W_LP ||
+ nal_unit_type == NAL_UNIT_TYPE_BLA_W_RADL ||
+ nal_unit_type == NAL_UNIT_TYPE_BLA_N_LP);
+}
+
/* random access point picture */
static bool is_rap_picture(unsigned nal_unit_type)
{
@@ -85,6 +99,24 @@ static bool is_slice_picture(unsigned nal_unit_type)
is_rap_picture(nal_unit_type));
}
+static void set_poc(vid_dec_PrivateType *priv,
+ unsigned nal_unit_type, int i)
+{
+ priv->picture.h265.CurrPicOrderCntVal = i;
+
+ if (priv->codec_data.h265.temporal_id == 0 &&
+ (nal_unit_type == NAL_UNIT_TYPE_TRAIL_R ||
+ nal_unit_type == NAL_UNIT_TYPE_TSA_R ||
+ nal_unit_type == NAL_UNIT_TYPE_STSA_R ||
+ is_rap_picture(nal_unit_type)))
+ priv->codec_data.h265.slice_prev_poc = i;
+}
+
+static unsigned get_poc(vid_dec_PrivateType *priv)
+{
+ return priv->picture.h265.CurrPicOrderCntVal;
+}
+
static void profile_tier(struct vl_rbsp *rbsp)
{
int i;
@@ -450,6 +482,7 @@ static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv)
return;
entry->buffer = priv->target;
+ entry->poc = get_poc(priv);
LIST_ADDTAIL(&entry->list, &priv->codec_data.h265.dpb_list);
++priv->codec_data.h265.dpb_num;
@@ -464,6 +497,159 @@ static void vid_dec_h265_EndFrame(vid_dec_PrivateType *priv)
priv->frame_finished = priv->in_buffers[0]->pInputPortPrivate != NULL;
}
+static void slice_header(vid_dec_PrivateType *priv, struct vl_rbsp *rbsp,
+ unsigned nal_unit_type)
+{
+ struct pipe_h265_pps *pps;
+ struct pipe_h265_sps *sps;
+ bool first_slice_segment_in_pic_flag;
+ bool dependent_slice_segment_flag = false;
+ struct ref_pic_set *rps = NULL;
+ unsigned poc_lsb, poc_msb, slice_prev_poc;
+ unsigned max_poc_lsb, prev_poc_lsb, prev_poc_msb;
+ unsigned num_st_rps;
+ int i;
+
+ if (priv->picture.h265.IDRPicFlag != is_idr_picture(nal_unit_type))
+ vid_dec_h265_EndFrame(priv);
+
+ priv->picture.h265.IDRPicFlag = is_idr_picture(nal_unit_type);
+
+ first_slice_segment_in_pic_flag = vl_rbsp_u(rbsp, 1);
+
+ if (is_rap_picture(nal_unit_type))
+ /* no_output_of_prior_pics_flag */
+ vl_rbsp_u(rbsp, 1);
+
+ pps = pic_parameter_set_id(priv, rbsp);
+ if (!pps)
+ return;
+
+ sps = pps->sps;
+ if (!sps)
+ return;
+
+ if (pps != priv->picture.h265.pps)
+ vid_dec_h265_EndFrame(priv);
+
+ priv->picture.h265.pps = pps;
+
+ if (priv->picture.h265.RAPPicFlag != is_rap_picture(nal_unit_type))
+ vid_dec_h265_EndFrame(priv);
+ priv->picture.h265.RAPPicFlag = is_rap_picture(nal_unit_type);
+
+ num_st_rps = sps->num_short_term_ref_pic_sets;
+
+ if (priv->picture.h265.CurrRpsIdx != num_st_rps)
+ vid_dec_h265_EndFrame(priv);
+ priv->picture.h265.CurrRpsIdx = num_st_rps;
+
+ if (!first_slice_segment_in_pic_flag) {
+ int size, num;
+ int bits_slice_segment_address = 0;
+
+ if (pps->dependent_slice_segments_enabled_flag)
+ dependent_slice_segment_flag = vl_rbsp_u(rbsp, 1);
+
+ size = 1 << (sps->log2_min_luma_coding_block_size_minus3 + 3 +
+ sps->log2_diff_max_min_luma_coding_block_size);
+
+ num = ((sps->pic_width_in_luma_samples + size - 1) / size) *
+ ((sps->pic_height_in_luma_samples + size - 1) / size);
+
+ while (num > (1 << bits_slice_segment_address))
+ bits_slice_segment_address++;
+
+ /* slice_segment_address */
+ vl_rbsp_u(rbsp, bits_slice_segment_address);
+ }
+
+ if (dependent_slice_segment_flag)
+ return;
+
+ for (i = 0; i < pps->num_extra_slice_header_bits; ++i)
+ /* slice_reserved_flag */
+ vl_rbsp_u(rbsp, 1);
+
+ /* slice_type */
+ vl_rbsp_ue(rbsp);
+
+ if (pps->output_flag_present_flag)
+ /* pic output flag */
+ vl_rbsp_u(rbsp, 1);
+
+ if (sps->separate_colour_plane_flag)
+ /* colour_plane_id */
+ vl_rbsp_u(rbsp, 2);
+
+ if (is_idr_picture(nal_unit_type)) {
+ set_poc(priv, nal_unit_type, 0);
+ return;
+ }
+
+ /* slice_pic_order_cnt_lsb */
+ poc_lsb =
+ vl_rbsp_u(rbsp, sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
+
+ slice_prev_poc = (int)priv->codec_data.h265.slice_prev_poc;
+ max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4);
+
+ prev_poc_lsb = slice_prev_poc & (max_poc_lsb - 1);
+ prev_poc_msb = slice_prev_poc - prev_poc_lsb;
+
+ if ((poc_lsb < prev_poc_lsb) &&
+ ((prev_poc_lsb - poc_lsb ) >= (max_poc_lsb / 2)))
+ poc_msb = prev_poc_msb + max_poc_lsb;
+
+ else if ((poc_lsb > prev_poc_lsb ) &&
+ ((poc_lsb - prev_poc_lsb) > (max_poc_lsb / 2)))
+ poc_msb = prev_poc_msb - max_poc_lsb;
+
+ else
+ poc_msb = prev_poc_msb;
+
+ if (is_bla_picture(nal_unit_type))
+ poc_msb = 0;
+
+ if (get_poc(priv) != poc_msb + poc_lsb)
+ vid_dec_h265_EndFrame(priv);
+
+ set_poc(priv, nal_unit_type, (poc_msb + poc_lsb));
+
+ /* short_term_ref_pic_set_sps_flag */
+ if (!vl_rbsp_u(rbsp, 1)) {
+ rps = (struct ref_pic_set *)
+ priv->codec_data.h265.ref_pic_set_list + num_st_rps;
+ st_ref_pic_set();
+
+ } else if (num_st_rps > 1) {
+ int num_bits = 0;
+ unsigned idx;
+
+ while ((1 << num_bits) < num_st_rps)
+ num_bits++;
+
+ if (num_bits > 0)
+ /* short_term_ref_pic_set_idx */
+ idx = vl_rbsp_u(rbsp, num_bits);
+ else
+ idx = 0;
+
+ rps = (struct ref_pic_set *)
+ priv->codec_data.h265.ref_pic_set_list + idx;
+ }
+
+ if (is_bla_picture(nal_unit_type)) {
+ rps->num_neg_pics = 0;
+ rps->num_pos_pics = 0;
+ rps->num_pics = 0;
+ }
+
+ priv->codec_data.h265.rps = rps;
+
+ return;
+}
+
static void vid_dec_h265_Decode(vid_dec_PrivateType *priv,
struct vl_vlc *vlc,
unsigned min_bits_left)
@@ -521,9 +707,34 @@ static void vid_dec_h265_Decode(vid_dec_PrivateType *priv,
vl_rbsp_init(&rbsp, vlc, ~0);
picture_parameter_set(priv, &rbsp);
- }
+ } else if (is_slice_picture(nal_unit_type)) {
+ unsigned bits = vl_vlc_valid_bits(vlc);
+ unsigned bytes = bits / 8 + 5;
+ struct vl_rbsp rbsp;
+ uint8_t buf[9];
+ const void *ptr = buf;
+ unsigned i;
- /* TODO */
+ buf[0] = 0x0;
+ buf[1] = 0x0;
+ buf[2] = 0x1;
+ buf[3] = nal_unit_type << 1 | nuh_layer_id >> 5;
+ buf[4] = nuh_layer_id << 3 | nuh_temporal_id_plus1;
+ for (i = 5; i < bytes; ++i)
+ buf[i] = vl_vlc_peekbits(vlc, bits) >> ((bytes - i - 1) * 8);
+
+ priv->bytes_left = (vl_vlc_bits_left(vlc) - bits) / 8;
+ priv->slice = vlc->data;
+
+ vl_rbsp_init(&rbsp, vlc, 128);
+ slice_header(priv, &rbsp, nal_unit_type);
+
+ vid_dec_h265_BeginFrame(priv);
+
+ priv->codec->decode_bitstream(priv->codec, priv->target,
+ &priv->picture.base, 1,
+ &ptr, &bytes);
+ }
/* resync to byte boundary */
vl_vlc_eatbits(vlc, vl_vlc_valid_bits(vlc) % 8);