Skip to content

Commit b44f07f

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 0b75aa1 commit b44f07f

File tree

6 files changed

+1439
-8
lines changed

6 files changed

+1439
-8
lines changed

drivers/staging/media/tegra-vde/Kconfig

+7
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.
+1-1
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

+282-2
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,275 @@ 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 & 0x7fffff;
743+
}
744+
745+
if (to_vb2_v4l2_buffer(vb)->flags & V4L2_BUF_FLAG_BFRAME)
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;
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_ctx_h264 *h = &ctx->h264;
767+
struct v4l2_h264_reflist_builder b;
768+
struct h264_reflists reflists;
769+
struct vb2_buffer *ref;
770+
unsigned int i;
771+
u8 *dpb_id;
772+
int err;
773+
774+
v4l2_m2m_buf_copy_metadata(src, dst, true);
775+
776+
err = tegra_vde_h264_setup_frame(ctx, h264, NULL, &dst->vb2_buf, 0,
777+
h264->dpb_frames_nb++);
778+
if (err)
779+
return err;
780+
781+
if (dst->flags & V4L2_BUF_FLAG_KEYFRAME)
782+
return 0;
783+
784+
v4l2_h264_init_reflist_builder(&b, h->decode_params, h->sps, dpb);
785+
786+
if (dst->flags & V4L2_BUF_FLAG_BFRAME) {
787+
v4l2_h264_build_b_ref_lists(&b, reflists.b0, reflists.b1);
788+
dpb_id = reflists.b0;
789+
} else {
790+
v4l2_h264_build_p_ref_list(&b, reflists.p);
791+
dpb_id = reflists.p;
792+
}
793+
794+
for (i = 0; i < b.num_valid; i++) {
795+
ref = get_ref_buf(ctx, dst, dpb_id[i]);
796+
797+
err = tegra_vde_h264_setup_frame(ctx, h264, &b, ref, dpb_id[i],
798+
h264->dpb_frames_nb++);
799+
if (err)
800+
return err;
801+
802+
if (b.refs[dpb_id[i]].pic_order_count < b.cur_pic_order_count)
803+
h264->dpb_ref_frames_with_earlier_poc_nb++;
804+
}
805+
806+
return 0;
807+
}
808+
809+
static unsigned int to_tegra_vde_h264_level_idc(unsigned int level_idc)
810+
{
811+
switch (level_idc) {
812+
case 11:
813+
return 2;
814+
case 12:
815+
return 3;
816+
case 13:
817+
return 4;
818+
case 20:
819+
return 5;
820+
case 21:
821+
return 6;
822+
case 22:
823+
return 7;
824+
case 30:
825+
return 8;
826+
case 31:
827+
return 9;
828+
case 32:
829+
return 10;
830+
case 40:
831+
return 11;
832+
case 41:
833+
return 12;
834+
case 42:
835+
return 13;
836+
case 50:
837+
return 14;
838+
default:
839+
break;
840+
}
841+
842+
return 15;
843+
}
844+
845+
static int tegra_vde_h264_setup_context(struct tegra_ctx *ctx,
846+
struct tegra_vde_h264_decoder_ctx *h264)
847+
{
848+
struct tegra_ctx_h264 *h = &ctx->h264;
849+
struct tegra_vde *vde = ctx->vde;
850+
struct device *dev = vde->dev;
851+
int err;
852+
853+
memset(h264, 0, sizeof(*h264));
854+
memset(vde->frames, 0, sizeof(vde->frames));
855+
856+
tegra_vde_prepare_control_data(ctx, V4L2_CID_STATELESS_H264_DECODE_PARAMS);
857+
tegra_vde_prepare_control_data(ctx, V4L2_CID_STATELESS_H264_SPS);
858+
tegra_vde_prepare_control_data(ctx, V4L2_CID_STATELESS_H264_PPS);
859+
860+
/* CABAC unsupported by hardware, requires software preprocessing */
861+
if (h->pps->flags & V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE)
862+
return -EOPNOTSUPP;
863+
864+
if (h->sps->profile_idc == 66)
865+
h264->baseline_profile = 1;
866+
867+
if (h->sps->flags & V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE)
868+
h264->direct_8x8_inference_flag = 1;
869+
870+
if (h->pps->flags & V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED)
871+
h264->constrained_intra_pred_flag = 1;
872+
873+
if (h->pps->flags & V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT)
874+
h264->deblocking_filter_control_present_flag = 1;
875+
876+
if (h->pps->flags & V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT)
877+
h264->pic_order_present_flag = 1;
878+
879+
h264->level_idc = to_tegra_vde_h264_level_idc(h->sps->level_idc);
880+
h264->log2_max_pic_order_cnt_lsb = h->sps->log2_max_pic_order_cnt_lsb_minus4 + 4;
881+
h264->log2_max_frame_num = h->sps->log2_max_frame_num_minus4 + 4;
882+
h264->pic_order_cnt_type = h->sps->pic_order_cnt_type;
883+
h264->pic_width_in_mbs = h->sps->pic_width_in_mbs_minus1 + 1;
884+
h264->pic_height_in_mbs = h->sps->pic_height_in_map_units_minus1 + 1;
885+
886+
h264->num_ref_idx_l0_active_minus1 = h->pps->num_ref_idx_l0_default_active_minus1;
887+
h264->num_ref_idx_l1_active_minus1 = h->pps->num_ref_idx_l1_default_active_minus1;
888+
h264->chroma_qp_index_offset = h->pps->chroma_qp_index_offset & 0x1f;
889+
h264->pic_init_qp = h->pps->pic_init_qp_minus26 + 26;
890+
891+
err = tegra_vde_h264_setup_frames(ctx, h264);
892+
if (err)
893+
return err;
894+
895+
err = tegra_vde_validate_h264_ctx(dev, h264);
896+
if (err)
897+
return err;
898+
899+
return 0;
900+
}
901+
902+
int tegra_vde_h264_decode_run(struct tegra_ctx *ctx)
903+
{
904+
struct vb2_v4l2_buffer *src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
905+
struct tegra_m2m_buffer *bitstream = vb_to_tegra_buf(&src->vb2_buf);
906+
size_t bitstream_size = vb2_get_plane_payload(&src->vb2_buf, 0);
907+
struct tegra_vde_h264_decoder_ctx h264;
908+
struct tegra_vde *vde = ctx->vde;
909+
int err;
910+
911+
err = tegra_vde_h264_setup_context(ctx, &h264);
912+
if (err)
913+
return err;
914+
915+
err = tegra_vde_decode_begin(vde, &h264, vde->frames,
916+
bitstream->dma_addr[0],
917+
bitstream_size);
918+
if (err)
919+
return err;
920+
921+
return 0;
922+
}
923+
924+
int tegra_vde_h264_decode_wait(struct tegra_ctx *ctx)
925+
{
926+
return tegra_vde_decode_end(ctx->vde);
927+
}

0 commit comments

Comments
 (0)