Skip to content

Commit e8151cd

Browse files
committed
media: staging: tegra-vde: Support V4L stateless video decoder API
Expose Tegra video decoder as a generic V4L M2M stateless video decoder. Signed-off-by: Dmitry Osipenko <[email protected]>
1 parent 4b9da96 commit e8151cd

File tree

6 files changed

+1483
-8
lines changed

6 files changed

+1483
-8
lines changed

drivers/staging/media/tegra-vde/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22
config TEGRA_VDE
33
tristate "NVIDIA Tegra Video Decoder Engine driver"
44
depends on ARCH_TEGRA || COMPILE_TEST
5+
depends on VIDEO_DEV && VIDEO_V4L2
56
select DMA_SHARED_BUFFER
67
select IOMMU_IOVA
8+
select MEDIA_CONTROLLER
9+
select MEDIA_CONTROLLER_REQUEST_API
710
select SRAM
11+
select VIDEOBUF2_DMA_CONTIG
12+
select VIDEOBUF2_DMA_SG
13+
select V4L2_H264
14+
select V4L2_MEM2MEM_DEV
815
help
916
Say Y here to enable support for the NVIDIA Tegra video decoder
1017
driver.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# SPDX-License-Identifier: GPL-2.0
2-
tegra-vde-y := vde.o iommu.o dmabuf-cache.o h264.o
2+
tegra-vde-y := vde.o iommu.o dmabuf-cache.o h264.o v4l2.o
33
obj-$(CONFIG_TEGRA_VDE) += tegra-vde.o

drivers/staging/media/tegra-vde/h264.c

Lines changed: 302 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,18 @@
1111
#include <linux/reset.h>
1212
#include <linux/slab.h>
1313

14+
#include <media/v4l2-h264.h>
15+
1416
#include "trace.h"
1517
#include "uapi.h"
1618
#include "vde.h"
1719

20+
struct h264_reflists {
21+
u8 p[V4L2_H264_NUM_DPB_ENTRIES];
22+
u8 b0[V4L2_H264_NUM_DPB_ENTRIES];
23+
u8 b1[V4L2_H264_NUM_DPB_ENTRIES];
24+
};
25+
1826
static int tegra_vde_wait_mbe(struct tegra_vde *vde)
1927
{
2028
u32 tmp;
@@ -125,8 +133,8 @@ static void tegra_vde_setup_frameid(struct tegra_vde *vde,
125133
u32 y_addr = frame ? frame->y_addr : 0x6CDEAD00;
126134
u32 cb_addr = frame ? frame->cb_addr : 0x6CDEAD00;
127135
u32 cr_addr = frame ? frame->cr_addr : 0x6CDEAD00;
128-
u32 value1 = frame ? ((mbs_width << 16) | mbs_height) : 0;
129-
u32 value2 = frame ? ((((mbs_width + 1) >> 1) << 6) | 1) : 0;
136+
u32 value1 = frame ? ((frame->luma_atoms_pitch << 16) | mbs_height) : 0;
137+
u32 value2 = frame ? ((frame->chroma_atoms_pitch << 6) | 1) : 0;
130138

131139
tegra_vde_writel(vde, y_addr >> 8, vde->frameid, 0x000 + frameid * 4);
132140
tegra_vde_writel(vde, cb_addr >> 8, vde->frameid, 0x100 + frameid * 4);
@@ -645,3 +653,295 @@ int tegra_vde_decode_h264(struct tegra_vde *vde,
645653

646654
return tegra_vde_decode_end(vde);
647655
}
656+
657+
static struct vb2_buffer *get_ref_buf(struct tegra_ctx *ctx,
658+
struct vb2_v4l2_buffer *dst,
659+
unsigned int dpb_idx)
660+
{
661+
const struct v4l2_h264_dpb_entry *dpb = ctx->h264.decode_params->dpb;
662+
struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q;
663+
int buf_idx = -1;
664+
665+
if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
666+
buf_idx = vb2_find_timestamp(cap_q,
667+
dpb[dpb_idx].reference_ts, 0);
668+
669+
/*
670+
* If a DPB entry is unused or invalid, address of current destination
671+
* buffer is returned.
672+
*/
673+
if (buf_idx < 0)
674+
return &dst->vb2_buf;
675+
676+
return vb2_get_buffer(cap_q, buf_idx);
677+
}
678+
679+
static int tegra_vde_validate_vb_size(struct tegra_ctx *ctx,
680+
struct vb2_buffer *vb,
681+
unsigned int plane_id,
682+
size_t min_size)
683+
{
684+
u64 offset = vb->planes[plane_id].data_offset;
685+
struct device *dev = ctx->vde->dev;
686+
687+
if (offset + min_size > vb2_plane_size(vb, plane_id)) {
688+
dev_err(dev, "Too small plane[%u] size %lu @0x%llX, should be at least %zu\n",
689+
plane_id, vb2_plane_size(vb, plane_id), offset, min_size);
690+
return -EINVAL;
691+
}
692+
693+
return 0;
694+
}
695+
696+
static int tegra_vde_h264_setup_frame(struct tegra_ctx *ctx,
697+
struct tegra_vde_h264_decoder_ctx *h264,
698+
struct v4l2_h264_reflist_builder *b,
699+
struct vb2_buffer *vb,
700+
unsigned int ref_id,
701+
unsigned int id)
702+
{
703+
struct v4l2_pix_format_mplane *pixfmt = &ctx->decoded_fmt.fmt.pix_mp;
704+
struct tegra_m2m_buffer *tb = vb_to_tegra_buf(vb);
705+
struct tegra_ctx_h264 *h = &ctx->h264;
706+
struct tegra_vde *vde = ctx->vde;
707+
struct device *dev = vde->dev;
708+
unsigned int cstride, lstride;
709+
unsigned int flags = 0;
710+
size_t lsize, csize;
711+
int err, frame_num;
712+
713+
lsize = h264->pic_width_in_mbs * 16 * h264->pic_height_in_mbs * 16;
714+
csize = h264->pic_width_in_mbs * 8 * h264->pic_height_in_mbs * 8;
715+
lstride = pixfmt->plane_fmt[0].bytesperline;
716+
cstride = pixfmt->plane_fmt[1].bytesperline;
717+
718+
err = tegra_vde_validate_vb_size(ctx, vb, 0, lsize);
719+
if (err)
720+
return err;
721+
722+
err = tegra_vde_validate_vb_size(ctx, vb, 1, csize);
723+
if (err)
724+
return err;
725+
726+
err = tegra_vde_validate_vb_size(ctx, vb, 2, csize);
727+
if (err)
728+
return err;
729+
730+
if (!tb->aux || tb->aux->size < csize) {
731+
dev_err(dev, "Too small aux size %zd, should be at least %zu\n",
732+
tb->aux ? tb->aux->size : -1, csize);
733+
return -EINVAL;
734+
}
735+
736+
if (id == 0) {
737+
frame_num = h->decode_params->frame_num;
738+
739+
if (h->decode_params->nal_ref_idc)
740+
flags |= FLAG_REFERENCE;
741+
} else {
742+
frame_num = b->refs[ref_id].frame_num;
743+
}
744+
745+
if (tb->b_frame)
746+
flags |= FLAG_B_FRAME;
747+
748+
vde->frames[id].flags = flags;
749+
vde->frames[id].y_addr = tb->dma_addr[0];
750+
vde->frames[id].cb_addr = tb->dma_addr[1];
751+
vde->frames[id].cr_addr = tb->dma_addr[2];
752+
vde->frames[id].aux_addr = tb->aux->dma_addr;
753+
vde->frames[id].frame_num = frame_num & 0x7fffff;
754+
vde->frames[id].luma_atoms_pitch = lstride / VDE_ATOM;
755+
vde->frames[id].chroma_atoms_pitch = cstride / VDE_ATOM;
756+
757+
return 0;
758+
}
759+
760+
static int tegra_vde_h264_setup_frames(struct tegra_ctx *ctx,
761+
struct tegra_vde_h264_decoder_ctx *h264)
762+
{
763+
struct vb2_v4l2_buffer *src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
764+
struct vb2_v4l2_buffer *dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
765+
const struct v4l2_h264_dpb_entry *dpb = ctx->h264.decode_params->dpb;
766+
struct tegra_m2m_buffer *tb = vb_to_tegra_buf(&dst->vb2_buf);
767+
struct tegra_ctx_h264 *h = &ctx->h264;
768+
struct v4l2_h264_reflist_builder b;
769+
struct h264_reflists reflists;
770+
struct vb2_buffer *ref;
771+
unsigned int i;
772+
u8 *dpb_id;
773+
int err;
774+
775+
/*
776+
* Tegra hardware requires information about frame's type, assuming
777+
* that frame consists of the same type slices. Userspace must tag
778+
* frame's type appropriately.
779+
*
780+
* Decoding of a non-uniform frames isn't supported by hardware and
781+
* require software preprocessing that we don't implement. Decoding
782+
* is expected to fail in this case. Such video streams are rare in
783+
* practice, so not a big deal.
784+
*
785+
* If userspace doesn't tell us frame's type, then we will try decode
786+
* as-is.
787+
*/
788+
v4l2_m2m_buf_copy_metadata(src, dst, true);
789+
790+
if (h->decode_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BFRAME)
791+
tb->b_frame = true;
792+
else
793+
tb->b_frame = false;
794+
795+
err = tegra_vde_h264_setup_frame(ctx, h264, NULL, &dst->vb2_buf, 0,
796+
h264->dpb_frames_nb++);
797+
if (err)
798+
return err;
799+
800+
if (!(h->decode_params->flags & (V4L2_H264_DECODE_PARAM_FLAG_PFRAME |
801+
V4L2_H264_DECODE_PARAM_FLAG_BFRAME)))
802+
return 0;
803+
804+
v4l2_h264_init_reflist_builder(&b, h->decode_params, h->sps, dpb);
805+
806+
if (h->decode_params->flags & V4L2_H264_DECODE_PARAM_FLAG_BFRAME) {
807+
v4l2_h264_build_b_ref_lists(&b, reflists.b0, reflists.b1);
808+
dpb_id = reflists.b0;
809+
} else {
810+
v4l2_h264_build_p_ref_list(&b, reflists.p);
811+
dpb_id = reflists.p;
812+
}
813+
814+
for (i = 0; i < b.num_valid; i++) {
815+
ref = get_ref_buf(ctx, dst, dpb_id[i]);
816+
817+
err = tegra_vde_h264_setup_frame(ctx, h264, &b, ref, dpb_id[i],
818+
h264->dpb_frames_nb++);
819+
if (err)
820+
return err;
821+
822+
if (b.refs[dpb_id[i]].pic_order_count < b.cur_pic_order_count)
823+
h264->dpb_ref_frames_with_earlier_poc_nb++;
824+
}
825+
826+
return 0;
827+
}
828+
829+
static unsigned int to_tegra_vde_h264_level_idc(unsigned int level_idc)
830+
{
831+
switch (level_idc) {
832+
case 11:
833+
return 2;
834+
case 12:
835+
return 3;
836+
case 13:
837+
return 4;
838+
case 20:
839+
return 5;
840+
case 21:
841+
return 6;
842+
case 22:
843+
return 7;
844+
case 30:
845+
return 8;
846+
case 31:
847+
return 9;
848+
case 32:
849+
return 10;
850+
case 40:
851+
return 11;
852+
case 41:
853+
return 12;
854+
case 42:
855+
return 13;
856+
case 50:
857+
return 14;
858+
default:
859+
break;
860+
}
861+
862+
return 15;
863+
}
864+
865+
static int tegra_vde_h264_setup_context(struct tegra_ctx *ctx,
866+
struct tegra_vde_h264_decoder_ctx *h264)
867+
{
868+
struct tegra_ctx_h264 *h = &ctx->h264;
869+
struct tegra_vde *vde = ctx->vde;
870+
struct device *dev = vde->dev;
871+
int err;
872+
873+
memset(h264, 0, sizeof(*h264));
874+
memset(vde->frames, 0, sizeof(vde->frames));
875+
876+
tegra_vde_prepare_control_data(ctx, V4L2_CID_STATELESS_H264_DECODE_PARAMS);
877+
tegra_vde_prepare_control_data(ctx, V4L2_CID_STATELESS_H264_SPS);
878+
tegra_vde_prepare_control_data(ctx, V4L2_CID_STATELESS_H264_PPS);
879+
880+
/* CABAC unsupported by hardware, requires software preprocessing */
881+
if (h->pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
882+
return -EOPNOTSUPP;
883+
884+
if (h->sps->profile_idc == 66)
885+
h264->baseline_profile = 1;
886+
887+
if (h->sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)
888+
h264->direct_8x8_inference_flag = 1;
889+
890+
if (h->pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)
891+
h264->constrained_intra_pred_flag = 1;
892+
893+
if (h->pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT)
894+
h264->deblocking_filter_control_present_flag = 1;
895+
896+
if (h->pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT)
897+
h264->pic_order_present_flag = 1;
898+
899+
h264->level_idc = to_tegra_vde_h264_level_idc(h->sps->level_idc);
900+
h264->log2_max_pic_order_cnt_lsb = h->sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
901+
h264->log2_max_frame_num = h->sps->log2_max_frame_num_minus4 + 4;
902+
h264->pic_order_cnt_type = h->sps->pic_order_cnt_type;
903+
h264->pic_width_in_mbs = h->sps->pic_width_in_mbs_minus1 + 1;
904+
h264->pic_height_in_mbs = h->sps->pic_height_in_map_units_minus1 + 1;
905+
906+
h264->num_ref_idx_l0_active_minus1 = h->pps->num_ref_idx_l0_default_active_minus1;
907+
h264->num_ref_idx_l1_active_minus1 = h->pps->num_ref_idx_l1_default_active_minus1;
908+
h264->chroma_qp_index_offset = h->pps->chroma_qp_index_offset & 0x1f;
909+
h264->pic_init_qp = h->pps->pic_init_qp_minus26 + 26;
910+
911+
err = tegra_vde_h264_setup_frames(ctx, h264);
912+
if (err)
913+
return err;
914+
915+
err = tegra_vde_validate_h264_ctx(dev, h264);
916+
if (err)
917+
return err;
918+
919+
return 0;
920+
}
921+
922+
int tegra_vde_h264_decode_run(struct tegra_ctx *ctx)
923+
{
924+
struct vb2_v4l2_buffer *src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
925+
struct tegra_m2m_buffer *bitstream = vb_to_tegra_buf(&src->vb2_buf);
926+
size_t bitstream_size = vb2_get_plane_payload(&src->vb2_buf, 0);
927+
struct tegra_vde_h264_decoder_ctx h264;
928+
struct tegra_vde *vde = ctx->vde;
929+
int err;
930+
931+
err = tegra_vde_h264_setup_context(ctx, &h264);
932+
if (err)
933+
return err;
934+
935+
err = tegra_vde_decode_begin(vde, &h264, vde->frames,
936+
bitstream->dma_addr[0],
937+
bitstream_size);
938+
if (err)
939+
return err;
940+
941+
return 0;
942+
}
943+
944+
int tegra_vde_h264_decode_wait(struct tegra_ctx *ctx)
945+
{
946+
return tegra_vde_decode_end(ctx->vde);
947+
}

0 commit comments

Comments
 (0)