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_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
index 0870da7..59ce85f 100644
--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -31,7 +31,7 @@
#include "../aml_vcodec_vfm.h"
#include "aml_hevc_parser.h"
-#define NAL_TYPE(value) ((value) & 0x1F)
+#define HEVC_NAL_TYPE(value) ((value >> 1) & 0x3F)
#define HEADER_BUFFER_SIZE (32 * 1024)
/**
@@ -93,10 +93,11 @@ struct vdec_hevc_vsi {
int head_offset;
struct vdec_hevc_dec_info dec;
struct vdec_pic_info pic;
+ struct vdec_pic_info cur_pic;
struct v4l2_rect crop;
bool is_combine;
int nalu_pos;
- struct HEVCParamSets ps;
+ struct h265_param_sets ps;
};
/**
@@ -111,59 +112,9 @@ struct vdec_hevc_inst {
struct aml_vdec_adapt vdec;
struct vdec_hevc_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct completion comp;
};
-#if 0
-#define DUMP_FILE_NAME "/data/dump/dump.tmp"
-static struct file *filp;
-static loff_t file_pos;
-
-void dump_write(const char __user *buf, size_t count)
-{
- mm_segment_t old_fs;
-
- if (!filp)
- return;
-
- old_fs = get_fs();
- set_fs(KERNEL_DS);
-
- if (count != vfs_write(filp, buf, count, &file_pos))
- pr_err("Failed to write file\n");
-
- set_fs(old_fs);
-}
-
-void dump_init(void)
-{
- filp = filp_open(DUMP_FILE_NAME, O_CREAT | O_RDWR, 0644);
- if (IS_ERR(filp)) {
- pr_err("open dump file failed\n");
- filp = NULL;
- }
-}
-
-void dump_deinit(void)
-{
- if (filp) {
- filp_close(filp, current->files);
- filp = NULL;
- file_pos = 0;
- }
-}
-
-void swap_uv(void *uv, int size)
-{
- int i;
- __u16 *p = uv;
-
- size /= 2;
-
- for (i = 0; i < size; i++, p++)
- *p = __swab16(*p);
-}
-#endif
-
static void get_pic_info(struct vdec_hevc_inst *inst,
struct vdec_pic_info *pic)
{
@@ -189,22 +140,10 @@ static void get_crop_info(struct vdec_hevc_inst *inst, struct v4l2_rect *cr)
static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz)
{
- *dpb_sz = 20;//inst->vsi->dec.dpb_sz;
+ *dpb_sz = inst->vsi->dec.dpb_sz;
aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
}
-static int find_start_code(unsigned char *data, unsigned int data_sz)
-{
- if (data_sz > 3 && data[0] == 0 && data[1] == 0 && data[2] == 1)
- return 3;
-
- if (data_sz > 4 && data[0] == 0 && data[1] == 0 && data[2] == 0 &&
- data[3] == 1)
- return 4;
-
- return -1;
-}
-
static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_hevc_inst *inst = NULL;
@@ -216,7 +155,7 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->ctx = ctx;
- inst->vdec.format = VFORMAT_HEVC;
+ inst->vdec.video_type = VFORMAT_HEVC;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.ctx = ctx;
@@ -262,6 +201,8 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->vsi->pic.c_bs_sz = 0;
inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
+ init_completion(&inst->comp);
+
aml_vcodec_debug(inst, "hevc Instance >> %p", inst);
ctx->ada_ctx = &inst->vdec;
@@ -280,31 +221,48 @@ error_free_inst:
return ret;
}
-#if 0
-static int refer_buffer_num(int level_idc, int poc_cnt,
- int mb_width, int mb_height)
+
+static int refer_buffer_num(struct h265_SPS_t *sps)
{
- return 20;
+ int used_buf_num = 0;
+ int sps_pic_buf_diff = 0;
+
+ if ((!sps->temporal_layer[0].num_reorder_pics) &&
+ (sps->temporal_layer[0].max_dec_pic_buffering)) {
+ /* the range of sps_num_reorder_pics_0 is in
+ [0, sps_max_dec_pic_buffering_minus1_0] */
+ used_buf_num = sps->temporal_layer[0].max_dec_pic_buffering;
+ } else
+ used_buf_num = sps->temporal_layer[0].num_reorder_pics;
+
+ sps_pic_buf_diff = sps->temporal_layer[0].max_dec_pic_buffering -
+ sps->temporal_layer[0].num_reorder_pics + 1;
+
+ if (sps_pic_buf_diff >= 4)
+ used_buf_num += 1;
+
+ /*need one more for multi instance, as
+ apply_ref_pic_set() has no chanch to run to
+ to clear referenced flag in some case */
+ used_buf_num++;
+
+ /* for eos add more buffer to flush.*/
+ used_buf_num++;
+
+ return used_buf_num;
}
-#endif
-//static void fill_vdec_params(struct vdec_hevc_inst *inst, struct hevc_SPS_t *sps)
-static void fill_vdec_params(struct vdec_hevc_inst *inst)
+static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_hevc_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
- unsigned int mb_w = 0, mb_h = 0, width, height;
- //unsigned int crop_unit_x = 0, crop_unit_y = 0;
- //unsigned int poc_cnt = 0;
-
- /* calc width & height. */
- width = 1920;
- height = 1080;
/* fill visible area size that be used for EGL. */
- pic->visible_width = width;
- pic->visible_height = height;
+ pic->visible_width = sps->width - (sps->output_window.left_offset +
+ sps->output_window.right_offset);
+ pic->visible_height = sps->height - (sps->output_window.top_offset +
+ sps->output_window.bottom_offset);
/* calc visible ares. */
rect->left = 0;
@@ -313,123 +271,61 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst)
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = ALIGN(mb_w, 4) << 4;
- pic->coded_height = ALIGN(mb_h, 4) << 4;
-
- pic->coded_width = 1920;
- pic->coded_height = 1088;//temp
+ pic->coded_width = ALIGN(sps->width, 32);
+ pic->coded_height = ALIGN(sps->height, 32);
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 = 20;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+ dec->dpb_sz = refer_buffer_num(sps);
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 hevc_parse_nal_header(u32 val)
+static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
{
- if (val & 0x80) {
- pr_err("the nal data is invalid.\n");
- return -1;
- }
+ int ret = 0;
+ struct aml_vdec_adapt *vdec = &inst->vdec;
- return (val & 0x7f) >> 1;
-}
+ ret = vdec_vframe_write(vdec, buf, size, 0);
+ if (ret < 0) {
+ pr_err("write frame data failed. err: %d\n", ret);
+ return ret;
+ }
-static void hevc_parse(struct HEVCParamSets *ps, u8 *buf, u32 size)
-{
- //int ret = -1;
- int i = 0, j = 0, cnt = 0;
- int pos, nal_size, nal_type;
- u8 *p = buf;
+ /* wait ucode parse ending. */
+ wait_for_completion_timeout(&inst->comp,
+ msecs_to_jiffies(1000));
- for (i = 4; i < size; i++) {
- j = find_start_code(p, i);
- if (j > 0) {
- pos = p - buf + j;
- nal_size = size - pos;
- nal_type = hevc_parse_nal_header(buf[pos]);
-
- switch (nal_type) {
- case HEVC_NAL_VPS:
- //ret = hevc_parse_nal_vps(&ps->vps, p, nal_size);
- //if (!ret)
- //ps->vps_parsed = true;
- pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type);
- break;
- case HEVC_NAL_SPS:
- //ret = hevc_parse_nal_sps(&ps->sps, p, nal_size);
- //if (!ret)
- ps->sps_parsed = true;
- pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type);
- break;
- case HEVC_NAL_PPS:
- //ret = hevc_parse_nal_pps(&ps->pps, p, nal_size);
- //if (!ret)
- //ps->sps_parsed = true;
- pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type);
- break;
- case HEVC_NAL_SEI_PREFIX:
- case HEVC_NAL_SEI_SUFFIX:
- //ret = hevc_parse_nal_sei(&ps->sei, p, nal_size);
- //if (!ret)
- //ps->sei_parsed = true;
- pr_err("------%s,%d nal type: %u\n",__func__, __LINE__,nal_type);
- break;
- default:
- pr_info("ignoring NAL type %d in extradata\n", nal_type);
- break;
- }
-
- cnt++;
- p += j;
- i = pos;
- }
- p++;
- }
+ return inst->vsi->dec.dpb_sz ? 0 : -1;
}
static int stream_parse(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
{
- //struct hevc_stream_t s;
- //struct hevc_SPS_t *sps;
- //unsigned int nal_type;
- int nal_idx = 0;
- int real_data_pos, real_data_size;
- bool is_combine = false;
-
- hevc_parse(&inst->vsi->ps, buf, size);
-
- if (!inst->vsi->ps.sps_parsed)
- return -1;
-
- /* if the st compose from csd + slice that is the combine data. */
- inst->vsi->is_combine = is_combine;
- inst->vsi->nalu_pos = nal_idx;
-
- /* start code plus nal type. */
- real_data_pos = nal_idx + 1;
- real_data_size = size - real_data_pos;
+ int ret = 0;
+ struct h265_param_sets *ps = NULL;
- //sps = kzalloc(sizeof(struct hevc_SPS_t), GFP_KERNEL);
- //if (sps == NULL)
- //return -ENOMEM;
+ ps = kzalloc(sizeof(struct h265_param_sets), GFP_KERNEL);
+ if (ps == NULL)
+ return -ENOMEM;
- /* the extra data would be parsed. */
- //hevc_stream_set(&s, &buf[real_data_pos], real_data_size);
- //hevc_sps_parse(&s, sps);
- //hevc_sps_info(sps);
+ ret = h265_decode_extradata_ps(buf, size, ps);
+ if (ret) {
+ pr_err("parse extra data failed. err: %d\n", ret);
+ goto out;
+ }
- //fill_vdec_params(inst, sps);
- fill_vdec_params(inst);
+ if (ps->sps_parsed)
+ fill_vdec_params(inst, &ps->sps);
- //kfree(sps);
+ ret = ps->sps_parsed ? 0 : -1;
+out:
+ kfree(ps);
- return 0;
+ return ret;
}
static int vdec_hevc_probe(unsigned long h_vdec,
@@ -438,7 +334,7 @@ static int vdec_hevc_probe(unsigned long h_vdec,
struct vdec_hevc_inst *inst =
(struct vdec_hevc_inst *)h_vdec;
struct stream_info *st;
- u8 *buf = (u8 *)bs->va;
+ u8 *buf = (u8 *)bs->vaddr;
u32 size = bs->size;
int ret = 0;
@@ -448,18 +344,23 @@ static int vdec_hevc_probe(unsigned long h_vdec,
if (st->magic == NORe || st->magic == NORn)
ret = stream_parse(inst, st->data, st->length);
- else
- ret = stream_parse(inst, buf, size);
+ else {
+ if (inst->ctx->param_sets_from_ucode)
+ ret = stream_parse_by_ucode(inst, buf, size);
+ else
+ ret = stream_parse(inst, buf, size);
+ }
+
+ inst->vsi->cur_pic = inst->vsi->pic;
return ret;
}
static void vdec_hevc_deinit(unsigned long h_vdec)
{
+ ulong flags;
struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
-
- if (!inst)
- return;
+ struct aml_vcodec_ctx *ctx = inst->ctx;
aml_vcodec_debug_enter(inst);
@@ -469,6 +370,7 @@ static void vdec_hevc_deinit(unsigned long h_vdec)
//dump_deinit();
+ spin_lock_irqsave(&ctx->slock, flags);
if (inst->vsi && inst->vsi->header_buf)
kfree(inst->vsi->header_buf);
@@ -476,20 +378,20 @@ static void vdec_hevc_deinit(unsigned long h_vdec)
kfree(inst->vsi);
kfree(inst);
+
+ ctx->drv_handle = 0;
+ spin_unlock_irqrestore(&ctx->slock, flags);
}
-static int vdec_hevc_get_fb(struct vdec_hevc_inst *inst, struct vdec_fb **out)
+static int vdec_hevc_get_fb(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
{
return get_fb_from_queue(inst->ctx, out);
}
-static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_fb **out)
+static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_v4l2_buffer **out)
{
struct vframe_s *vf = NULL;
- struct vdec_fb *fb = NULL;
-
- aml_vcodec_debug(inst, "%s() [%d], vfm: %p",
- __func__, __LINE__, &inst->vfm);
+ struct vdec_v4l2_buffer *fb = NULL;
vf = peek_video_frame(&inst->vfm);
if (!vf) {
@@ -507,114 +409,80 @@ static void vdec_hevc_get_vf(struct vdec_hevc_inst *inst, struct vdec_fb **out)
atomic_set(&vf->use_cnt, 1);
- aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n",
- __func__, __LINE__, vf, vf->v4l_mem_handle, vf->index);
-
- fb = (struct vdec_fb *)vf->v4l_mem_handle;
+ 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);
+ //dump_write(fb->base_y.vaddr, fb->base_y.bytes_used);
+ //dump_write(fb->base_c.vaddr, fb->base_c.bytes_used);
/* convert yuv format. */
- //swap_uv(fb->base_c.va, fb->base_c.size);
-
- aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu",
- __func__, __LINE__, fb->base_y.va,
- (unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size);
- aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu",
- __func__, __LINE__, fb->base_c.va,
- (unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size);
+ //swap_uv(fb->base_c.vaddr, fb->base_c.size);
}
static int vdec_write_nalu(struct vdec_hevc_inst *inst,
u8 *buf, u32 size, u64 ts)
{
- int ret = 0, err = 0;
+ int ret = 0;
struct aml_vdec_adapt *vdec = &inst->vdec;
- bool is_combine = true;//inst->vsi->is_combine;
- int nalu_pos;
- u32 nal_type;
-
- nalu_pos = find_start_code(buf, size);
- if (nalu_pos < 0)
- goto err;
-
- nal_type = hevc_parse_nal_header(buf[nalu_pos]);
- aml_vcodec_debug(inst, "NALU type: %d, size: %u\n", nal_type, size);
-
- if (nal_type == HEVC_NAL_SPS && !is_combine) {
- if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
- ret = -EILSEQ;
- goto err;
- }
- inst->vsi->sps_size = size;
- memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
- inst->vsi->head_offset += inst->vsi->sps_size;
- } else if (nal_type == HEVC_NAL_PPS && !is_combine) {
- //buf_sz -= nal_start_idx;
- if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
- ret = -EILSEQ;
- goto err;
- }
- inst->vsi->pps_size = size;
- memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
- inst->vsi->head_offset += inst->vsi->pps_size;
- } else if (nal_type == HEVC_NAL_SEI_PREFIX && !is_combine) {
- if (inst->vsi->head_offset + size > HEADER_BUFFER_SIZE) {
- ret = -EILSEQ;
- goto err;
- }
- inst->vsi->sei_size = size;
- memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, size);
- inst->vsi->head_offset += inst->vsi->sei_size;
- } else {
- char *write_buf = vmalloc(inst->vsi->head_offset + size);
- memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset);
- memcpy(write_buf + inst->vsi->head_offset, buf, size);
+ ret = vdec_vframe_write(vdec, buf, size, ts);
- ret = vdec_vframe_write(vdec, write_buf,
- inst->vsi->head_offset + size, ts);
+ return ret;
+}
- aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d",
- write_buf, inst->vsi->head_offset + size, ret);
+static bool monitor_res_change(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
+{
+ int ret = 0, i = 0, j = 0;
+ u8 *p = buf;
+ int len = size;
+ u32 type;
- memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE);
- inst->vsi->head_offset = 0;
- inst->vsi->sps_size = 0;
- inst->vsi->pps_size = 0;
- inst->vsi->sei_size = 0;
+ for (i = 4; i < size; i++) {
+ j = find_start_code(p, len);
+ if (j > 0) {
+ len = size - (p - buf);
+ type = HEVC_NAL_TYPE(p[j]);
+ if (type != HEVC_NAL_AUD &&
+ (type > HEVC_NAL_PPS || type < HEVC_NAL_VPS))
+ break;
- vfree(write_buf);
+ if (type == HEVC_NAL_SPS) {
+ ret = stream_parse(inst, p, len);
+ if (!ret && (inst->vsi->cur_pic.coded_width !=
+ inst->vsi->pic.coded_width ||
+ inst->vsi->cur_pic.coded_height !=
+ inst->vsi->pic.coded_height)) {
+ inst->vsi->cur_pic = inst->vsi->pic;
+ return true;
+ }
+ }
+ p += j;
+ }
+ p++;
}
- return 0;
-err:
- aml_vcodec_err(inst, "%s err(%d)", __func__, err);
-
- return err;
+ return false;
}
static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
- unsigned long int timestamp, bool *res_chg)
+ u64 timestamp, bool *res_chg)
{
struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
struct aml_vdec_adapt *vdec = &inst->vdec;
struct stream_info *st;
u8 *buf;
u32 size;
- int ret = 0;
+ int ret = -1;
/* bs NULL means flush decoder */
if (bs == NULL)
- return 0;
+ return -1;
- buf = (u8 *)bs->va;
+ buf = (u8 *)bs->vaddr;
size = bs->size;
st = (struct stream_info *)buf;
@@ -626,8 +494,13 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
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
+ else {
+ /*checked whether the resolution changes.*/
+ if ((*res_chg = monitor_res_change(inst, buf, size)))
+ return 0;
+
ret = vdec_write_nalu(inst, buf, size, timestamp);
+ }
return ret;
}
@@ -672,12 +545,80 @@ static int vdec_hevc_get_param(unsigned long h_vdec,
return ret;
}
+static void set_param_write_sync(struct vdec_hevc_inst *inst)
+{
+ complete(&inst->comp);
+}
+
+static void set_param_pic_info(struct vdec_hevc_inst *inst,
+ struct aml_vdec_pic_infos *info)
+{
+ struct vdec_pic_info *pic = &inst->vsi->pic;
+ struct vdec_hevc_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 = info->visible_width;
+ pic->visible_height = info->visible_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(info->coded_width, 64);
+ pic->coded_height = ALIGN(info->coded_height, 64);
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+
+ dec->dpb_sz = info->dpb_size;
+
+ /*wake up*/
+ complete(&inst->comp);
+
+ pr_info("Parse from ucode, crop(%d x %d), coded(%d x %d) dpb: %d\n",
+ pic->visible_width, pic->visible_height,
+ pic->coded_width, pic->coded_height,
+ dec->dpb_sz);
+}
+
+static int vdec_hevc_set_param(unsigned long h_vdec,
+ enum vdec_set_param_type type, void *in)
+{
+ int ret = 0;
+ struct vdec_hevc_inst *inst = (struct vdec_hevc_inst *)h_vdec;
+
+ if (!inst) {
+ pr_err("the hevc inst of dec is invalid.\n");
+ return -1;
+ }
+
+ switch (type) {
+ case SET_PARAM_WRITE_FRAME_SYNC:
+ set_param_write_sync(inst);
+ break;
+
+ 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_hevc_if = {
- vdec_hevc_init,
- vdec_hevc_probe,
- vdec_hevc_decode,
- vdec_hevc_get_param,
- vdec_hevc_deinit,
+ .init = vdec_hevc_init,
+ .probe = vdec_hevc_probe,
+ .decode = vdec_hevc_decode,
+ .get_param = vdec_hevc_get_param,
+ .set_param = vdec_hevc_set_param,
+ .deinit = vdec_hevc_deinit,
};
struct vdec_common_if *get_hevc_dec_comm_if(void);