Skip to content

Commit 89645b9

Browse files
jc-kynesimpopcornmix
authored andcommitted
media: rpivid: Make slice ctrl dynamic
Allows the user to submit a whole frames worth of slice headers in one lump along with a single bitstream dmabuf for the whole lot. This saves potentially a lot of bitstream copying. Signed-off-by: John Cox <jc@kynesim.co.uk>
1 parent 9e0facd commit 89645b9

File tree

3 files changed

+99
-74
lines changed

3 files changed

+99
-74
lines changed

drivers/staging/media/rpivid/rpivid.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,11 @@ static const struct rpivid_control rpivid_ctrls[] = {
6363
},
6464
{
6565
.cfg = {
66+
.name = "Slice param array",
6667
.id = V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS,
68+
.type = V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS,
69+
.flags = V4L2_CTRL_FLAG_DYNAMIC_ARRAY,
70+
.dims = { 0x1000 },
6771
},
6872
.required = true,
6973
},

drivers/staging/media/rpivid/rpivid_dec.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,34 @@ void rpivid_device_run(void *priv)
4646

4747
switch (ctx->src_fmt.pixelformat) {
4848
case V4L2_PIX_FMT_HEVC_SLICE:
49+
{
50+
const struct v4l2_ctrl *ctrl;
51+
4952
run.h265.sps =
5053
rpivid_find_control_data(ctx,
5154
V4L2_CID_MPEG_VIDEO_HEVC_SPS);
5255
run.h265.pps =
5356
rpivid_find_control_data(ctx,
5457
V4L2_CID_MPEG_VIDEO_HEVC_PPS);
55-
run.h265.slice_params =
56-
rpivid_find_control_data(ctx,
57-
V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
5858
run.h265.dec =
5959
rpivid_find_control_data(ctx,
6060
V4L2_CID_MPEG_VIDEO_HEVC_DECODE_PARAMS);
61+
62+
ctrl = rpivid_find_ctrl(ctx,
63+
V4L2_CID_MPEG_VIDEO_HEVC_SLICE_PARAMS);
64+
if (!ctrl || !ctrl->elems) {
65+
v4l2_err(&dev->v4l2_dev, "%s: Missing slice params\n",
66+
__func__);
67+
goto fail;
68+
}
69+
run.h265.slice_ents = ctrl->elems;
70+
run.h265.slice_params = ctrl->p_cur.p;
71+
6172
run.h265.scaling_matrix =
6273
rpivid_find_control_data(ctx,
6374
V4L2_CID_MPEG_VIDEO_HEVC_SCALING_MATRIX);
6475
break;
76+
}
6577

6678
default:
6779
break;

drivers/staging/media/rpivid/rpivid_h265.c

Lines changed: 80 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,6 @@ struct rpivid_dec_state {
245245

246246
// Slice vars
247247
unsigned int slice_idx;
248-
bool frame_end;
249248
bool slice_temporal_mvp; /* Slice flag but constant for frame */
250249

251250
// Temp vars per run - don't actually need to persist
@@ -740,7 +739,8 @@ static void new_slice_segment(struct rpivid_dec_env *const de,
740739
V4L2_HEVC_PPS_FLAG_CONSTRAINED_INTRA_PRED))
741740
<< 24));
742741

743-
if ((sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) != 0)
742+
if (!s->start_ts &&
743+
(sps->flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED) != 0)
744744
write_scaling_factors(de);
745745

746746
if (!s->dependent_slice_segment_flag) {
@@ -1111,7 +1111,8 @@ static int wpp_end_previous_slice(struct rpivid_dec_env *const de,
11111111
* next chunk code simpler
11121112
*/
11131113
static int wpp_decode_slice(struct rpivid_dec_env *const de,
1114-
const struct rpivid_dec_state *const s)
1114+
const struct rpivid_dec_state *const s,
1115+
bool last_slice)
11151116
{
11161117
bool reset_qp_y = true;
11171118
const bool indep = !s->dependent_slice_segment_flag;
@@ -1150,7 +1151,7 @@ static int wpp_decode_slice(struct rpivid_dec_env *const de,
11501151
0, 0, s->start_ctb_x, s->start_ctb_y,
11511152
s->slice_qp, slice_reg_const(s));
11521153

1153-
if (s->frame_end) {
1154+
if (last_slice) {
11541155
rv = wpp_entry_fill(de, s, s->ctb_height - 1);
11551156
if (rv)
11561157
return rv;
@@ -1229,7 +1230,8 @@ static int end_previous_slice(struct rpivid_dec_env *const de,
12291230
}
12301231

12311232
static int decode_slice(struct rpivid_dec_env *const de,
1232-
const struct rpivid_dec_state *const s)
1233+
const struct rpivid_dec_state *const s,
1234+
bool last_slice)
12331235
{
12341236
bool reset_qp_y;
12351237
unsigned int tile_x = ctb_to_tile_x(s, s->start_ctb_x);
@@ -1275,7 +1277,7 @@ static int decode_slice(struct rpivid_dec_env *const de,
12751277
* now, otherwise this will be done at the start of the next slice
12761278
* when it will be known where this slice finishes
12771279
*/
1278-
if (s->frame_end) {
1280+
if (last_slice) {
12791281
rv = tile_entry_fill(de, s,
12801282
s->tile_width - 1,
12811283
s->tile_height - 1);
@@ -1670,11 +1672,13 @@ static u32 mk_config2(const struct rpivid_dec_state *const s)
16701672
static void rpivid_h265_setup(struct rpivid_ctx *ctx, struct rpivid_run *run)
16711673
{
16721674
struct rpivid_dev *const dev = ctx->dev;
1673-
const struct v4l2_ctrl_hevc_slice_params *const sh =
1674-
run->h265.slice_params;
16751675
const struct v4l2_ctrl_hevc_decode_params *const dec =
16761676
run->h265.dec;
1677-
// const struct v4l2_hevc_pred_weight_table *pred_weight_table;
1677+
/* sh0 used where slice header contents should be constant over all
1678+
* slices, or first slice of frame
1679+
*/
1680+
const struct v4l2_ctrl_hevc_slice_params *const sh0 =
1681+
run->h265.slice_params;
16781682
struct rpivid_q_aux *dpb_q_aux[V4L2_HEVC_DPB_ENTRIES_NUM_MAX];
16791683
struct rpivid_dec_state *const s = ctx->state;
16801684
struct vb2_queue *vq;
@@ -1684,20 +1688,18 @@ static void rpivid_h265_setup(struct rpivid_ctx *ctx, struct rpivid_run *run)
16841688
int use_aux;
16851689
int rv;
16861690
bool slice_temporal_mvp;
1691+
bool frame_end;
16871692

16881693
xtrace_in(dev, de);
1694+
s->sh = NULL; // Avoid use until in the slice loop
16891695

1690-
// pred_weight_table = &sh->pred_weight_table;
1691-
1692-
s->frame_end =
1696+
frame_end =
16931697
((run->src->flags & V4L2_BUF_FLAG_M2M_HOLD_CAPTURE_BUF) == 0);
16941698

1695-
slice_temporal_mvp = (sh->flags &
1699+
slice_temporal_mvp = (sh0->flags &
16961700
V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_TEMPORAL_MVP_ENABLED);
16971701

16981702
if (de && de->state != RPIVID_DECODE_END) {
1699-
++s->slice_idx;
1700-
17011703
switch (de->state) {
17021704
case RPIVID_DECODE_SLICE_CONTINUE:
17031705
// Expected state
@@ -1830,7 +1832,7 @@ static void rpivid_h265_setup(struct rpivid_ctx *ctx, struct rpivid_run *run)
18301832
de->rpi_config2 = mk_config2(s);
18311833
de->rpi_framesize = (s->sps.pic_height_in_luma_samples << 16) |
18321834
s->sps.pic_width_in_luma_samples;
1833-
de->rpi_currpoc = sh->slice_pic_order_cnt;
1835+
de->rpi_currpoc = sh0->slice_pic_order_cnt;
18341836

18351837
if (s->sps.flags &
18361838
V4L2_HEVC_SPS_FLAG_SPS_TEMPORAL_MVP_ENABLED) {
@@ -1839,17 +1841,17 @@ static void rpivid_h265_setup(struct rpivid_ctx *ctx, struct rpivid_run *run)
18391841

18401842
s->slice_idx = 0;
18411843

1842-
if (sh->slice_segment_addr != 0) {
1844+
if (sh0->slice_segment_addr != 0) {
18431845
v4l2_warn(&dev->v4l2_dev,
18441846
"New frame but segment_addr=%d\n",
1845-
sh->slice_segment_addr);
1847+
sh0->slice_segment_addr);
18461848
goto fail;
18471849
}
18481850

18491851
/* Allocate a bitbuf if we need one - don't need one if single
18501852
* slice as we can use the src buf directly
18511853
*/
1852-
if (!s->frame_end && !de->bit_copy_gptr->ptr) {
1854+
if (!frame_end && !de->bit_copy_gptr->ptr) {
18531855
size_t bits_alloc;
18541856
bits_alloc = rpivid_bit_buf_size(s->sps.pic_width_in_luma_samples,
18551857
s->sps.pic_height_in_luma_samples,
@@ -1873,21 +1875,7 @@ static void rpivid_h265_setup(struct rpivid_ctx *ctx, struct rpivid_run *run)
18731875
s->src_addr = 0;
18741876
s->src_buf = NULL;
18751877

1876-
if (run->src->planes[0].bytesused < (sh->bit_size + 7) / 8) {
1877-
v4l2_warn(&dev->v4l2_dev,
1878-
"Bit size %d > bytesused %d\n",
1879-
sh->bit_size, run->src->planes[0].bytesused);
1880-
goto fail;
1881-
}
1882-
if (sh->data_bit_offset >= sh->bit_size ||
1883-
sh->bit_size - sh->data_bit_offset < 8) {
1884-
v4l2_warn(&dev->v4l2_dev,
1885-
"Bit size %d < Bit offset %d + 8\n",
1886-
sh->bit_size, sh->data_bit_offset);
1887-
goto fail;
1888-
}
1889-
1890-
if (s->frame_end)
1878+
if (frame_end)
18911879
s->src_addr = vb2_dma_contig_plane_dma_addr(&run->src->vb2_buf,
18921880
0);
18931881
if (!s->src_addr)
@@ -1898,44 +1886,65 @@ static void rpivid_h265_setup(struct rpivid_ctx *ctx, struct rpivid_run *run)
18981886
}
18991887

19001888
// Pre calc a few things
1901-
s->sh = sh;
19021889
s->dec = dec;
1903-
s->slice_qp = 26 + s->pps.init_qp_minus26 + s->sh->slice_qp_delta;
1904-
s->max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ?
1890+
for (i = 0; i != run->h265.slice_ents; ++i) {
1891+
const struct v4l2_ctrl_hevc_slice_params *const sh = sh0 + i;
1892+
const bool last_slice = frame_end && i + 1 == run->h265.slice_ents;
1893+
1894+
s->sh = sh;
1895+
1896+
if (run->src->planes[0].bytesused < (sh->bit_size + 7) / 8) {
1897+
v4l2_warn(&dev->v4l2_dev,
1898+
"Bit size %d > bytesused %d\n",
1899+
sh->bit_size, run->src->planes[0].bytesused);
1900+
goto fail;
1901+
}
1902+
if (sh->data_bit_offset >= sh->bit_size ||
1903+
sh->bit_size - sh->data_bit_offset < 8) {
1904+
v4l2_warn(&dev->v4l2_dev,
1905+
"Bit size %d < Bit offset %d + 8\n",
1906+
sh->bit_size, sh->data_bit_offset);
1907+
goto fail;
1908+
}
1909+
1910+
s->slice_qp = 26 + s->pps.init_qp_minus26 + sh->slice_qp_delta;
1911+
s->max_num_merge_cand = sh->slice_type == HEVC_SLICE_I ?
1912+
0 :
1913+
(5 - sh->five_minus_max_num_merge_cand);
1914+
s->dependent_slice_segment_flag =
1915+
((sh->flags &
1916+
V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT) != 0);
1917+
1918+
s->nb_refs[0] = (sh->slice_type == HEVC_SLICE_I) ?
19051919
0 :
1906-
(5 - sh->five_minus_max_num_merge_cand);
1907-
// * SH DSS flag invented by me - but clearly needed
1908-
s->dependent_slice_segment_flag =
1909-
((sh->flags &
1910-
V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT) != 0);
1911-
1912-
s->nb_refs[0] = (sh->slice_type == HEVC_SLICE_I) ?
1913-
0 :
1914-
sh->num_ref_idx_l0_active_minus1 + 1;
1915-
s->nb_refs[1] = (sh->slice_type != HEVC_SLICE_B) ?
1916-
0 :
1917-
sh->num_ref_idx_l1_active_minus1 + 1;
1918-
1919-
if (s->sps.flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED)
1920-
populate_scaling_factors(run, de, s);
1921-
1922-
// Calc all the random coord info to avoid repeated conversion in/out
1923-
s->start_ts = s->ctb_addr_rs_to_ts[sh->slice_segment_addr];
1924-
s->start_ctb_x = sh->slice_segment_addr % de->pic_width_in_ctbs_y;
1925-
s->start_ctb_y = sh->slice_segment_addr / de->pic_width_in_ctbs_y;
1926-
// Last CTB of previous slice
1927-
prev_rs = !s->start_ts ? 0 : s->ctb_addr_ts_to_rs[s->start_ts - 1];
1928-
s->prev_ctb_x = prev_rs % de->pic_width_in_ctbs_y;
1929-
s->prev_ctb_y = prev_rs / de->pic_width_in_ctbs_y;
1930-
1931-
if ((s->pps.flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED))
1932-
rv = wpp_decode_slice(de, s);
1933-
else
1934-
rv = decode_slice(de, s);
1935-
if (rv)
1936-
goto fail;
1920+
sh->num_ref_idx_l0_active_minus1 + 1;
1921+
s->nb_refs[1] = (sh->slice_type != HEVC_SLICE_B) ?
1922+
0 :
1923+
sh->num_ref_idx_l1_active_minus1 + 1;
1924+
1925+
if (s->sps.flags & V4L2_HEVC_SPS_FLAG_SCALING_LIST_ENABLED)
1926+
populate_scaling_factors(run, de, s);
1927+
1928+
/* Calc all the random coord info to avoid repeated conversion in/out */
1929+
s->start_ts = s->ctb_addr_rs_to_ts[sh->slice_segment_addr];
1930+
s->start_ctb_x = sh->slice_segment_addr % de->pic_width_in_ctbs_y;
1931+
s->start_ctb_y = sh->slice_segment_addr / de->pic_width_in_ctbs_y;
1932+
/* Last CTB of previous slice */
1933+
prev_rs = !s->start_ts ? 0 : s->ctb_addr_ts_to_rs[s->start_ts - 1];
1934+
s->prev_ctb_x = prev_rs % de->pic_width_in_ctbs_y;
1935+
s->prev_ctb_y = prev_rs / de->pic_width_in_ctbs_y;
1936+
1937+
if ((s->pps.flags & V4L2_HEVC_PPS_FLAG_ENTROPY_CODING_SYNC_ENABLED))
1938+
rv = wpp_decode_slice(de, s, last_slice);
1939+
else
1940+
rv = decode_slice(de, s, last_slice);
1941+
if (rv)
1942+
goto fail;
1943+
1944+
++s->slice_idx;
1945+
}
19371946

1938-
if (!s->frame_end) {
1947+
if (!frame_end) {
19391948
xtrace_ok(dev, de);
19401949
return;
19411950
}
@@ -2054,8 +2063,8 @@ static void rpivid_h265_setup(struct rpivid_ctx *ctx, struct rpivid_run *run)
20542063
fail:
20552064
if (de)
20562065
// Actual error reporting happens in Trigger
2057-
de->state = s->frame_end ? RPIVID_DECODE_ERROR_DONE :
2058-
RPIVID_DECODE_ERROR_CONTINUE;
2066+
de->state = frame_end ? RPIVID_DECODE_ERROR_DONE :
2067+
RPIVID_DECODE_ERROR_CONTINUE;
20592068
xtrace_fail(dev, de);
20602069
}
20612070

0 commit comments

Comments
 (0)