summaryrefslogtreecommitdiff
Diffstat
-rw-r--r--drivers/amvdec_ports/Makefile13
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c22
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h3
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c534
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.h39
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c57
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h11
-rw-r--r--drivers/amvdec_ports/aml_vcodec_util.c18
-rw-r--r--drivers/amvdec_ports/aml_vcodec_util.h8
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.c9
-rw-r--r--drivers/amvdec_ports/aml_vcodec_vfm.h6
-rw-r--r--drivers/amvdec_ports/decoder/aml_h264_parser.c662
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_h264_parser.h226
-rw-r--r--drivers/amvdec_ports/decoder/aml_hevc_parser.c1274
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_hevc_parser.h137
-rw-r--r--drivers/amvdec_ports/decoder/aml_mjpeg_parser.c397
-rw-r--r--drivers/amvdec_ports/decoder/aml_mjpeg_parser.h163
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg12_parser.c198
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg12_parser.h74
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg4_parser.c1233
-rw-r--r--drivers/amvdec_ports/decoder/aml_mpeg4_parser.h250
-rw-r--r--drivers/amvdec_ports/decoder/aml_vp9_parser.c299
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/aml_vp9_parser.h279
-rw-r--r--drivers/amvdec_ports/decoder/h264_parse.c389
-rw-r--r--drivers/amvdec_ports/decoder/h264_parse.h141
-rw-r--r--drivers/amvdec_ports/decoder/h264_stream.c111
-rw-r--r--drivers/amvdec_ports/decoder/h264_stream.h39
-rw-r--r--drivers/amvdec_ports/decoder/vdec_h264_if.c357
-rw-r--r--drivers/amvdec_ports/decoder/vdec_hevc_if.c477
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mjpeg_if.c498
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg12_if.c490
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg4_if.c499
-rw-r--r--drivers/amvdec_ports/decoder/vdec_vp9_if.c461
-rw-r--r--[-rwxr-xr-x]drivers/amvdec_ports/decoder/vdec_vp9_trigger.h0
-rw-r--r--drivers/amvdec_ports/test/vcodec_m2m_test.c18
-rw-r--r--drivers/amvdec_ports/utils/common.c221
-rw-r--r--drivers/amvdec_ports/utils/common.h72
-rw-r--r--drivers/amvdec_ports/utils/get_bits.h590
-rw-r--r--drivers/amvdec_ports/utils/golomb.c147
-rw-r--r--drivers/amvdec_ports/utils/golomb.h500
-rw-r--r--drivers/amvdec_ports/utils/pixfmt.h470
-rw-r--r--drivers/amvdec_ports/utils/put_bits.h323
-rw-r--r--drivers/amvdec_ports/vdec_drv_base.h11
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.c45
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.h10
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c219
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c308
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c334
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c233
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c317
-rw-r--r--drivers/frame_provider/decoder/utils/Makefile1
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_input.c19
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c131
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h22
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c388
55 files changed, 11471 insertions, 2282 deletions
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
new file mode 100644
index 0000000..7a40a4a
--- a/dev/null
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
@@ -0,0 +1,499 @@
+/*
+* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*
+* Description:
+*/
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <uapi/linux/swab.h>
+#include "../vdec_drv_if.h"
+#include "../aml_vcodec_util.h"
+#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_adapt.h"
+#include "../vdec_drv_base.h"
+#include "../aml_vcodec_vfm.h"
+#include "aml_mpeg4_parser.h"
+
+#define NAL_TYPE(value) ((value) & 0x1F)
+#define HEADER_BUFFER_SIZE (32 * 1024)
+
+/**
+ * struct mpeg4_fb - mpeg4 decode frame buffer information
+ * @vdec_fb_va : virtual address of struct vdec_fb
+ * @y_fb_dma : dma address of Y frame buffer (luma)
+ * @c_fb_dma : dma address of C frame buffer (chroma)
+ * @poc : picture order count of frame buffer
+ * @reserved : for 8 bytes alignment
+ */
+struct mpeg4_fb {
+ uint64_t vdec_fb_va;
+ uint64_t y_fb_dma;
+ uint64_t c_fb_dma;
+ int32_t poc;
+ uint32_t reserved;
+};
+
+/**
+ * struct vdec_mpeg4_dec_info - decode information
+ * @dpb_sz : decoding picture buffer size
+ * @resolution_changed : resoltion change happen
+ * @reserved : for 8 bytes alignment
+ * @bs_dma : Input bit-stream buffer dma address
+ * @y_fb_dma : Y frame buffer dma address
+ * @c_fb_dma : C frame buffer dma address
+ * @vdec_fb_va : VDEC frame buffer struct virtual address
+ */
+struct vdec_mpeg4_dec_info {
+ uint32_t dpb_sz;
+ uint32_t resolution_changed;
+ uint32_t reserved;
+ uint64_t bs_dma;
+ uint64_t y_fb_dma;
+ uint64_t c_fb_dma;
+ uint64_t vdec_fb_va;
+};
+
+/**
+ * struct vdec_mpeg4_vsi - shared memory for decode information exchange
+ * between VPU and Host.
+ * The memory is allocated by VPU then mapping to Host
+ * in vpu_dec_init() and freed in vpu_dec_deinit()
+ * by VPU.
+ * AP-W/R : AP is writer/reader on this item
+ * VPU-W/R: VPU is write/reader on this item
+ * @hdr_buf : Header parsing buffer (AP-W, VPU-R)
+ * @list_free : free frame buffer ring list (AP-W/R, VPU-W)
+ * @list_disp : display frame buffer ring list (AP-R, VPU-W)
+ * @dec : decode information (AP-R, VPU-W)
+ * @pic : picture information (AP-R, VPU-W)
+ * @crop : crop information (AP-R, VPU-W)
+ */
+struct vdec_mpeg4_vsi {
+ char *header_buf;
+ int sps_size;
+ int pps_size;
+ int sei_size;
+ int head_offset;
+ struct vdec_mpeg4_dec_info dec;
+ struct vdec_pic_info pic;
+ struct v4l2_rect crop;
+ bool is_combine;
+ int nalu_pos;
+ //struct mpeg4ParamSets ps;
+};
+
+/**
+ * struct vdec_mpeg4_inst - mpeg4 decoder instance
+ * @num_nalu : how many nalus be decoded
+ * @ctx : point to aml_vcodec_ctx
+ * @vsi : VPU shared information
+ */
+struct vdec_mpeg4_inst {
+ unsigned int num_nalu;
+ struct aml_vcodec_ctx *ctx;
+ struct aml_vdec_adapt vdec;
+ struct vdec_mpeg4_vsi *vsi;
+ struct vcodec_vfm_s vfm;
+};
+
+static void get_pic_info(struct vdec_mpeg4_inst *inst,
+ struct vdec_pic_info *pic)
+{
+ *pic = inst->vsi->pic;
+
+ aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
+ pic->visible_width, pic->visible_height,
+ pic->coded_width, pic->coded_height);
+ aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
+ pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
+}
+
+static void get_crop_info(struct vdec_mpeg4_inst *inst, struct v4l2_rect *cr)
+{
+ cr->left = inst->vsi->crop.left;
+ cr->top = inst->vsi->crop.top;
+ cr->width = inst->vsi->crop.width;
+ cr->height = inst->vsi->crop.height;
+
+ aml_vcodec_debug(inst, "l=%d, t=%d, w=%d, h=%d",
+ cr->left, cr->top, cr->width, cr->height);
+}
+
+static void get_dpb_size(struct vdec_mpeg4_inst *inst, unsigned int *dpb_sz)
+{
+ *dpb_sz = 9;//inst->vsi->dec.dpb_sz;
+ aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
+}
+
+static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
+{
+ struct vdec_mpeg4_inst *inst = NULL;
+ int ret = -1;
+
+ inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+ if (!inst)
+ return -ENOMEM;
+
+ inst->ctx = ctx;
+
+ inst->vdec.video_type = VFORMAT_MPEG4;
+ inst->vdec.format = VIDEO_DEC_FORMAT_MPEG4_5;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.ctx = ctx;
+
+ /* set play mode.*/
+ if (ctx->is_drm_mode)
+ inst->vdec.port.flag |= PORT_FLAG_DRM;
+
+ /* to eable mpeg4 hw.*/
+ inst->vdec.port.type = PORT_TYPE_VIDEO;
+
+ /* init vfm */
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
+ vcodec_vfm_init(&inst->vfm);
+
+ ret = video_decoder_init(&inst->vdec);
+ if (ret) {
+ aml_vcodec_err(inst, "vdec_mpeg4 init err=%d", ret);
+ goto error_free_inst;
+ }
+
+ /* probe info from the stream */
+ inst->vsi = kzalloc(sizeof(struct vdec_mpeg4_vsi), GFP_KERNEL);
+ if (!inst->vsi) {
+ ret = -ENOMEM;
+ goto error_free_inst;
+ }
+
+ /* alloc the header buffer to be used cache sps or spp etc.*/
+ inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
+ if (!inst->vsi) {
+ ret = -ENOMEM;
+ goto error_free_vsi;
+ }
+
+ inst->vsi->pic.visible_width = 1920;
+ inst->vsi->pic.visible_height = 1080;
+ inst->vsi->pic.coded_width = 1920;
+ inst->vsi->pic.coded_height = 1088;
+ inst->vsi->pic.y_bs_sz = 0;
+ inst->vsi->pic.y_len_sz = (1920 * 1088);
+ inst->vsi->pic.c_bs_sz = 0;
+ inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
+
+ aml_vcodec_debug(inst, "mpeg4 Instance >> %p", inst);
+
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
+
+ //dump_init();
+
+ return 0;
+
+error_free_vsi:
+ kfree(inst->vsi);
+error_free_inst:
+ kfree(inst);
+ *h_vdec = 0;
+
+ return ret;
+}
+
+#if 0
+static int refer_buffer_num(int level_idc, int poc_cnt,
+ int mb_width, int mb_height)
+{
+ return 20;
+}
+#endif
+
+static void fill_vdec_params(struct vdec_mpeg4_inst *inst,
+ struct mpeg4_dec_param *dec_ps)
+{
+ struct vdec_pic_info *pic = &inst->vsi->pic;
+ struct vdec_mpeg4_dec_info *dec = &inst->vsi->dec;
+ struct v4l2_rect *rect = &inst->vsi->crop;
+
+ /* fill visible area size that be used for EGL. */
+ pic->visible_width = dec_ps->m.width;
+ pic->visible_height = dec_ps->m.height;
+
+ /* calc visible ares. */
+ rect->left = 0;
+ rect->top = 0;
+ rect->width = pic->visible_width;
+ rect->height = pic->visible_height;
+
+ /* config canvas size that be used for decoder. */
+ pic->coded_width = ALIGN(dec_ps->m.width, 64);
+ pic->coded_height = ALIGN(dec_ps->m.height, 64);
+
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+
+ /* calc DPB size */
+ dec->dpb_sz = 9;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+
+ pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
+ inst->ctx->id, pic->coded_width, pic->coded_height,
+ pic->visible_width, pic->visible_height, dec->dpb_sz);
+}
+
+static int stream_parse(struct vdec_mpeg4_inst *inst, u8 *buf, u32 size)
+{
+ int ret = 0;
+ struct mpeg4_param_sets *ps = NULL;
+
+ ps = kzalloc(sizeof(struct mpeg4_param_sets), GFP_KERNEL);
+ if (ps == NULL)
+ return -ENOMEM;
+
+ ret = mpeg4_decode_extradata_ps(buf, size, ps);
+ if (ret) {
+ pr_err("parse extra data failed. err: %d\n", ret);
+ goto out;
+ }
+
+ if (ps->head_parsed)
+ fill_vdec_params(inst, &ps->dec_ps);
+
+ ret = ps->head_parsed ? 0 : -1;
+out:
+ kfree(ps);
+
+ return ret;
+}
+
+static int vdec_mpeg4_probe(unsigned long h_vdec,
+ struct aml_vcodec_mem *bs, void *out)
+{
+ struct vdec_mpeg4_inst *inst =
+ (struct vdec_mpeg4_inst *)h_vdec;
+ struct stream_info *st;
+ u8 *buf = (u8 *)bs->vaddr;
+ u32 size = bs->size;
+ int ret = 0;
+
+ st = (struct stream_info *)buf;
+ if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
+ return 0;
+
+ if (st->magic == NORe || st->magic == NORn)
+ ret = stream_parse(inst, st->data, st->length);
+ else
+ ret = stream_parse(inst, buf, size);
+
+ return ret;
+}
+
+static void vdec_mpeg4_deinit(unsigned long h_vdec)
+{
+ struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+
+ if (!inst)
+ return;
+
+ aml_vcodec_debug_enter(inst);
+
+ video_decoder_release(&inst->vdec);
+
+ vcodec_vfm_release(&inst->vfm);
+
+ //dump_deinit();
+
+ if (inst->vsi && inst->vsi->header_buf)
+ kfree(inst->vsi->header_buf);
+
+ if (inst->vsi)
+ kfree(inst->vsi);
+
+ kfree(inst);
+}
+
+static int vdec_mpeg4_get_fb(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out)
+{
+ return get_fb_from_queue(inst->ctx, out);
+}
+
+static void vdec_mpeg4_get_vf(struct vdec_mpeg4_inst *inst, struct vdec_v4l2_buffer **out)
+{
+ struct vframe_s *vf = NULL;
+ struct vdec_v4l2_buffer *fb = NULL;
+
+ vf = peek_video_frame(&inst->vfm);
+ if (!vf) {
+ aml_vcodec_debug(inst, "there is no vframe.");
+ *out = NULL;
+ return;
+ }
+
+ vf = get_video_frame(&inst->vfm);
+ if (!vf) {
+ aml_vcodec_debug(inst, "the vframe is avalid.");
+ *out = NULL;
+ return;
+ }
+
+ atomic_set(&vf->use_cnt, 1);
+
+ fb = (struct vdec_v4l2_buffer *)vf->v4l_mem_handle;
+ fb->vf_handle = (unsigned long)vf;
+ fb->status = FB_ST_DISPLAY;
+
+ *out = fb;
+
+ //pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
+ //dump_write(fb->base_y.va, fb->base_y.bytes_used);
+ //dump_write(fb->base_c.va, fb->base_c.bytes_used);
+
+ /* convert yuv format. */
+ //swap_uv(fb->base_c.va, fb->base_c.size);
+}
+
+static int vdec_write_nalu(struct vdec_mpeg4_inst *inst,
+ u8 *buf, u32 size, u64 ts)
+{
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+
+ ret = vdec_vframe_write(vdec, buf, size, ts);
+
+ return ret;
+}
+
+static int vdec_mpeg4_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
+ u64 timestamp, bool *res_chg)
+{
+ struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
+ struct stream_info *st;
+ u8 *buf;
+ u32 size;
+ int ret = 0;
+
+ /* bs NULL means flush decoder */
+ if (bs == NULL)
+ return 0;
+
+ buf = (u8 *)bs->vaddr;
+ size = bs->size;
+ st = (struct stream_info *)buf;
+
+ if (inst->ctx->is_drm_mode && (st->magic == DRMe || st->magic == DRMn))
+ ret = vdec_vbuf_write(vdec, st->m.buf, sizeof(st->m.drm));
+ else if (st->magic == NORe)
+ ret = vdec_vbuf_write(vdec, st->data, st->length);
+ else if (st->magic == NORn)
+ ret = vdec_write_nalu(inst, st->data, st->length, timestamp);
+ else if (inst->ctx->is_stream_mode)
+ ret = vdec_vbuf_write(vdec, buf, size);
+ else
+ ret = vdec_write_nalu(inst, buf, size, timestamp);
+
+ return ret;
+}
+
+static int vdec_mpeg4_get_param(unsigned long h_vdec,
+ enum vdec_get_param_type type, void *out)
+{
+ int ret = 0;
+ struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+
+ if (!inst) {
+ pr_err("the mpeg4 inst of dec is invalid.\n");
+ return -1;
+ }
+
+ switch (type) {
+ case GET_PARAM_DISP_FRAME_BUFFER:
+ vdec_mpeg4_get_vf(inst, out);
+ break;
+
+ case GET_PARAM_FREE_FRAME_BUFFER:
+ ret = vdec_mpeg4_get_fb(inst, out);
+ break;
+
+ case GET_PARAM_PIC_INFO:
+ get_pic_info(inst, out);
+ break;
+
+ case GET_PARAM_DPB_SIZE:
+ get_dpb_size(inst, out);
+ break;
+
+ case GET_PARAM_CROP_INFO:
+ get_crop_info(inst, out);
+ break;
+
+ default:
+ aml_vcodec_err(inst, "invalid get parameter type=%d", type);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static void set_param_pic_info(struct vdec_mpeg4_inst *inst,
+ struct aml_vdec_pic_infos *info)
+{
+ pr_info("---%s, %d\n", __func__, __LINE__);
+}
+
+static int vdec_mpeg4_set_param(unsigned long h_vdec,
+ enum vdec_set_param_type type, void *in)
+{
+ int ret = 0;
+ struct vdec_mpeg4_inst *inst = (struct vdec_mpeg4_inst *)h_vdec;
+
+ if (!inst) {
+ pr_err("the mpeg4 inst of dec is invalid.\n");
+ return -1;
+ }
+
+ switch (type) {
+ case SET_PARAM_PIC_INFO:
+ set_param_pic_info(inst, in);
+ break;
+
+ default:
+ aml_vcodec_err(inst, "invalid set parameter type=%d", type);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static struct vdec_common_if vdec_mpeg4_if = {
+ .init = vdec_mpeg4_init,
+ .probe = vdec_mpeg4_probe,
+ .decode = vdec_mpeg4_decode,
+ .get_param = vdec_mpeg4_get_param,
+ .set_param = vdec_mpeg4_set_param,
+ .deinit = vdec_mpeg4_deinit,
+};
+
+struct vdec_common_if *get_mpeg4_dec_comm_if(void);
+
+struct vdec_common_if *get_mpeg4_dec_comm_if(void)
+{
+ return &vdec_mpeg4_if;
+}