summaryrefslogtreecommitdiff
authorNanxin Qin <nanxin.qin@amlogic.com>2019-10-29 14:08:34 (GMT)
committer Zhi Zhou <zhi.zhou@amlogic.com>2019-11-23 14:50:21 (GMT)
commit75803959aeeed0e6e5e529078e33bbced5e00e5e (patch)
tree6a7365cd8518916b6e1f54186d52c61b5933cc54
parente8335f3266cead9dff3b939d3e579d56bb8d2257 (diff)
downloadmedia_modules-75803959aeeed0e6e5e529078e33bbced5e00e5e.zip
media_modules-75803959aeeed0e6e5e529078e33bbced5e00e5e.tar.gz
media_modules-75803959aeeed0e6e5e529078e33bbced5e00e5e.tar.bz2
v4l: fixed some issues for v4l codec. [3/3]
PD#SWPL-5313 Problem: Decoder V4L2 interface Phase3(AFBC&MMU Support) Solution: 1. opitimize the event of notify eos when play end, need not alloc more buffer to dispatch ending event. 2. opitimize the interface of get buffs from m2m pool. 3. v4l2 vf video display support. 4. support config parms for v4l codec. 5. add afbc an dw for h265, vp9. 6. fixed the box and memory leak. 7. support report hdr infos from v4l codec. 8. opitimize the event of report resolution change. Verify: U212 Change-Id: I446f9bb3f3b64a66540f6dd32af2cd7e71d0a280 Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
Diffstat
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.c14
-rw-r--r--drivers/amvdec_ports/aml_vcodec_adapt.h1
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.c248
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec.h32
-rw-r--r--drivers/amvdec_ports/aml_vcodec_dec_drv.c196
-rw-r--r--drivers/amvdec_ports/aml_vcodec_drv.h57
-rw-r--r--drivers/amvdec_ports/decoder/aml_h264_parser.c4
-rw-r--r--drivers/amvdec_ports/decoder/vdec_h264_if.c160
-rw-r--r--drivers/amvdec_ports/decoder/vdec_hevc_if.c182
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mjpeg_if.c24
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg12_if.c28
-rw-r--r--drivers/amvdec_ports/decoder/vdec_mpeg4_if.c32
-rw-r--r--drivers/amvdec_ports/decoder/vdec_vp9_if.c220
-rw-r--r--drivers/amvdec_ports/vdec_drv_if.h4
-rw-r--r--drivers/frame_provider/decoder/h264_multi/vmh264.c104
-rw-r--r--drivers/frame_provider/decoder/h265/vh265.c496
-rw-r--r--drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c7
-rw-r--r--drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c7
-rw-r--r--drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c7
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_bmmu_box.c47
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_bmmu_box.h3
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_mmu_box.c55
-rw-r--r--drivers/frame_provider/decoder/utils/decoder_mmu_box.h2
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c102
-rw-r--r--drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h8
-rw-r--r--drivers/frame_provider/decoder/vp9/vvp9.c338
26 files changed, 1770 insertions, 608 deletions
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.c b/drivers/amvdec_ports/aml_vcodec_adapt.c
index f4bfc55..a307a2b 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.c
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.c
@@ -511,6 +511,11 @@ static void set_vdec_properity(struct vdec_s *vdec,
vdec->port->flag = vdec->port_flag;
ada_ctx->vfm_path = vdec->frame_base_video_path;
+
+ vdec->config_len = ada_ctx->config.length >
+ PAGE_SIZE ? PAGE_SIZE : ada_ctx->config.length;
+ memcpy(vdec->config, ada_ctx->config.buf, vdec->config_len);
+
ada_ctx->vdec = vdec;
}
@@ -742,3 +747,12 @@ int vdec_frame_number(struct aml_vdec_adapt *ada_ctx)
else
return -1;
}
+
+void v4l2_config_vdec_parm(struct aml_vdec_adapt *ada_ctx, u8 *data, u32 len)
+{
+ struct vdec_s *vdec = ada_ctx->vdec;
+
+ vdec->config_len = len > PAGE_SIZE ? PAGE_SIZE : len;
+ memcpy(vdec->config, data, vdec->config_len);
+}
+
diff --git a/drivers/amvdec_ports/aml_vcodec_adapt.h b/drivers/amvdec_ports/aml_vcodec_adapt.h
index 5a69312..b591699 100644
--- a/drivers/amvdec_ports/aml_vcodec_adapt.h
+++ b/drivers/amvdec_ports/aml_vcodec_adapt.h
@@ -38,6 +38,7 @@ struct aml_vdec_adapt {
struct vdec_s *vdec;
struct stream_port_s port;
struct dec_sysinfo dec_prop;
+ struct v4l2_config_parm config;
int video_type;
char *recv_name;
int vfm_path;
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.c b/drivers/amvdec_ports/aml_vcodec_dec.c
index 9c34b49..7774522 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec.c
@@ -34,6 +34,8 @@
#include <linux/spinlock.h>
#include "aml_vcodec_vfm.h"
+#include "../frame_provider/decoder/utils/decoder_bmmu_box.h"
+#include "../frame_provider/decoder/utils/decoder_mmu_box.h"
#define OUT_FMT_IDX 0 //default h264
#define CAP_FMT_IDX 8 //capture nv21
@@ -157,6 +159,9 @@ static const struct aml_codec_framesizes aml_vdec_framesizes[] = {
extern bool multiplanar;
+extern int dmabuf_fd_install_data(int fd, void* data, u32 size);
+extern bool is_v4l2_buf_file(struct file *file);
+
static ulong aml_vcodec_ctx_lock(struct aml_vcodec_ctx *ctx)
{
ulong flags;
@@ -255,6 +260,33 @@ static void aml_vdec_pic_info_update(struct aml_vcodec_ctx *ctx)
ctx->picinfo = ctx->last_decoded_picinfo;
}
+void vdec_frame_buffer_release(void *data)
+{
+ struct file_privdata *priv_data =
+ (struct file_privdata *) data;
+ struct vframe_s *vf = &priv_data->vf;
+
+ if (decoder_bmmu_box_valide_check(vf->mm_box.bmmu_box)) {
+ decoder_bmmu_box_free_idx(vf->mm_box.bmmu_box,
+ vf->mm_box.bmmu_idx);
+ decoder_bmmu_try_to_release_box(vf->mm_box.bmmu_box);
+ }
+
+ if (decoder_mmu_box_valide_check(vf->mm_box.mmu_box)) {
+ decoder_mmu_box_free_idx(vf->mm_box.mmu_box,
+ vf->mm_box.mmu_idx);
+ decoder_mmu_try_to_release_box(vf->mm_box.mmu_box);
+ }
+
+ aml_v4l2_debug(2, "%s vf idx: %d, bmmu idx: %d, bmmu_box: %p",
+ __func__, vf->index, vf->mm_box.bmmu_idx, vf->mm_box.bmmu_box);
+ aml_v4l2_debug(2, "%s vf idx: %d, mmu_idx: %d, mmu_box: %p",
+ __func__, vf->index, vf->mm_box.mmu_idx, vf->mm_box.mmu_box);
+
+ memset(data, 0, sizeof(struct file_privdata));
+ kfree(data);
+}
+
int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer **out_fb)
{
ulong flags;
@@ -435,8 +467,8 @@ void trans_vframe_to_user(struct aml_vcodec_ctx *ctx, struct vdec_v4l2_buffer *f
if (dstbuf->vb.vb2_buf.state == VB2_BUF_STATE_ACTIVE) {
/* binding vframe handle. */
- if (fb->mem_type == VDEC_SCATTER_MEMORY_TYPE)
- dstbuf->vb.private = fb->m.vf_fd;
+ vf->flag |= VFRAME_FLAG_VIDEO_LINEAR;
+ dstbuf->privdata.vf = *vf;
v4l2_m2m_buf_done(&dstbuf->vb, VB2_BUF_STATE_DONE);
}
@@ -498,19 +530,6 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx)
}
if (ctx->state == AML_STATE_PROBE) {
- int buf_ready_num;
-
- /* is there enough dst bufs for decoding? */
- buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
- if ((buf_ready_num + ctx->buf_used_count) < ctx->dpb_size) {
- aml_v4l2_debug(4, "[%d] Not enough dst bufs, num: %d.",
- ctx->id, buf_ready_num);
- v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
- v4l2_m2m_try_schedule(ctx->m2m_ctx);
- msleep(60);
- return 0;
- }
-
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_PROBE) {
ctx->state = AML_STATE_READY;
@@ -533,6 +552,18 @@ static int is_vdec_ready(struct aml_vcodec_ctx *ctx)
}
mutex_unlock(&ctx->state_lock);
+ if (!ctx->v4l_codec_dpb_ready) {
+ int buf_ready_num;
+
+ /* is there enough dst bufs for decoding? */
+ buf_ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+ if ((buf_ready_num + ctx->buf_used_count) >= ctx->dpb_size)
+ ctx->v4l_codec_dpb_ready = true;
+ aml_v4l2_debug(2, "[%d] %s() dpb: %d, ready: %d, used: %d",
+ ctx->id, __func__, ctx->dpb_size,
+ buf_ready_num, ctx->buf_used_count);
+ }
+
return 1;
}
@@ -548,6 +579,25 @@ static bool is_enough_work_items(struct aml_vcodec_ctx *ctx)
return true;
}
+static void aml_wait_dpb_ready(struct aml_vcodec_ctx *ctx)
+{
+ ulong expires;
+
+ expires = jiffies + msecs_to_jiffies(1000);
+ while (!ctx->v4l_codec_dpb_ready) {
+ u32 ready_num = 0;
+
+ if (time_after(jiffies, expires)) {
+ pr_err("the DPB state has not ready.\n");
+ break;
+ }
+
+ ready_num = v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx);
+ if ((ready_num + ctx->buf_used_count) >= ctx->dpb_size)
+ ctx->v4l_codec_dpb_ready = true;
+ }
+}
+
static void aml_vdec_worker(struct work_struct *work)
{
struct aml_vcodec_ctx *ctx =
@@ -589,22 +639,31 @@ static void aml_vdec_worker(struct work_struct *work)
if (src_buf_info->lastframe) {
/*the empty data use to flushed the decoder.*/
- aml_v4l2_debug(3, "[%d] Got empty flush input buffer.", ctx->id);
+ aml_v4l2_debug(2, "[%d] Got empty flush input buffer.", ctx->id);
- src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
- v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
-
- /* sets eos data for vdec input. */
- aml_vdec_flush_decoder(ctx);
+ /*
+ * when inputs a small amount of src buff, then soon to
+ * switch state FLUSHING, must to wait the DBP to be ready.
+ */
+ if (!ctx->v4l_codec_dpb_ready) {
+ v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+ goto out;
+ }
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_ACTIVE) {
ctx->state = AML_STATE_FLUSHING;// prepare flushing
- aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)",
+ aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-END)",
ctx->id, __func__);
}
mutex_unlock(&ctx->state_lock);
+ src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+ v4l2_m2m_job_finish(dev->m2m_dev_dec, ctx->m2m_ctx);
+
+ /* sets eos data for vdec input. */
+ aml_vdec_flush_decoder(ctx);
+
goto out;
}
@@ -643,6 +702,9 @@ static void aml_vdec_worker(struct work_struct *work)
aml_v4l2_err("[%d] %s() error processing src data. %d.",
ctx->id, __func__, ret);
} else if (res_chg) {
+ /* wait the DPB state to be ready. */
+ aml_wait_dpb_ready(ctx);
+
src_buf_info->used = false;
aml_vdec_pic_info_update(ctx);
/*
@@ -651,11 +713,10 @@ static void aml_vdec_worker(struct work_struct *work)
* remaining buffers from before the resolution change
* point, so call flush decode here
*/
- aml_vdec_flush_decoder(ctx);
mutex_lock(&ctx->state_lock);
if (ctx->state == AML_STATE_ACTIVE) {
ctx->state = AML_STATE_FLUSHING;// prepare flushing
- aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING)",
+ aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_FLUSHING-RESCHG)",
ctx->id, __func__);
}
mutex_unlock(&ctx->state_lock);
@@ -663,6 +724,8 @@ static void aml_vdec_worker(struct work_struct *work)
ctx->q_data[AML_Q_DATA_SRC].resolution_changed = true;
v4l2_m2m_job_pause(dev->m2m_dev_dec, ctx->m2m_ctx);
+ aml_vdec_flush_decoder(ctx);
+
goto out;
}
@@ -708,6 +771,10 @@ static void aml_vdec_reset(struct aml_vcodec_ctx *ctx)
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_PROBE)",
ctx->id, __func__);
+ aml_v4l2_debug(0, "[%d] %s() dpb: %d, ready: %d, used: %d",
+ ctx->id, __func__, ctx->dpb_size,
+ v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx), ctx->buf_used_count);
+
/* vdec has ready to decode subsequence data of new resolution. */
ctx->q_data[AML_Q_DATA_SRC].resolution_changed = false;
v4l2_m2m_job_resume(ctx->dev->m2m_dev_dec, ctx->m2m_ctx);
@@ -860,7 +927,7 @@ static int vidioc_decoder_cmd(struct file *file, void *priv,
if (ret)
return ret;
- aml_v4l2_debug(3, "[%d] %s() [%d], cmd: %u",
+ aml_v4l2_debug(2, "[%d] %s() [%d], cmd: %u",
ctx->id, __func__, __LINE__, cmd->cmd);
dst_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
multiplanar ? V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
@@ -887,9 +954,6 @@ static int vidioc_decoder_cmd(struct file *file, void *priv,
v4l2_m2m_buf_queue(ctx->m2m_ctx, &ctx->empty_flush_buf->vb);
v4l2_m2m_try_schedule(ctx->m2m_ctx);//pay attention
- /* remark cmd use to distinguish stop or seek. */
- ctx->receive_cmd_stop = true;
-
break;
case V4L2_DEC_CMD_START:
@@ -910,42 +974,43 @@ static int vidioc_decoder_streamon(struct file *file, void *priv,
struct v4l2_fh *fh = file->private_data;
struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
struct vb2_queue *q;
- int ret = 0;
-
- ret = v4l2_m2m_ioctl_streamon(file, priv, i);
q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
-
if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
- mutex_lock(&ctx->state_lock);
-
- /*
- * if receive the cmd is not V4L2_DEC_CMD_STOP
- * that request should be seek not stop, thus igorn status
- * AML_STATE_FLUSHING and AML_STATE_FLUSHED.
- */
-
- if (ctx->state == AML_STATE_FLUSHED ||
- ctx->state == AML_STATE_FLUSHING || //????
- (ctx->state == AML_STATE_ACTIVE &&
- !ctx->receive_cmd_stop)) {
- if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
- /*the short source will be fasted into flushing state.
- then switch to abort state that caused seek failed.*/
- if (ctx->state == AML_STATE_FLUSHING)
- ctx->receive_cmd_stop = false;
-
+ if (ctx->is_stream_off) {
+ mutex_lock(&ctx->state_lock);
+ if (ctx->state == AML_STATE_ACTIVE ||
+ ctx->state == AML_STATE_FLUSHING ||
+ ctx->state == AML_STATE_FLUSHED) {
ctx->state = AML_STATE_RESET;
ctx->v4l_codec_ready = false;
+ ctx->v4l_codec_dpb_ready = false;
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_RESET)",
ctx->id, __func__);
aml_vdec_reset(ctx);
}
+ mutex_unlock(&ctx->state_lock);
+
+ ctx->is_stream_off = false;
}
- mutex_unlock(&ctx->state_lock);
}
- return ret;
+ return v4l2_m2m_ioctl_streamon(file, priv, i);
+}
+
+static int vidioc_decoder_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type i)
+{
+ struct v4l2_fh *fh = file->private_data;
+ struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+ struct vb2_queue *q;
+
+ q = v4l2_m2m_get_vq(fh->m2m_ctx, i);
+ if (!V4L2_TYPE_IS_OUTPUT(q->type)) {
+ ctx->is_stream_off = true;
+ }
+
+ return v4l2_m2m_ioctl_streamoff(file, priv, i);
}
static int vidioc_decoder_reqbufs(struct file *file, void *priv,
@@ -966,6 +1031,7 @@ void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx)
{
ctx->state = AML_STATE_ABORT;
ctx->v4l_codec_ready = false;
+ ctx->v4l_codec_dpb_ready = false;
aml_v4l2_debug(1, "[%d] %s() vcodec state (AML_STATE_ABORT)",
ctx->id, __func__);
@@ -1041,6 +1107,7 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
struct v4l2_buffer *buf)
{
struct aml_vcodec_ctx *ctx = fh_to_ctx(priv);
+ int ret;
if (ctx->state == AML_STATE_ABORT) {
aml_v4l2_err("[%d] Call on DQBUF after unrecoverable error, type = %s",
@@ -1050,7 +1117,32 @@ static int vidioc_vdec_dqbuf(struct file *file, void *priv,
return -EIO;
}
- return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+ ret = v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+
+ if (!ret && !V4L2_TYPE_IS_OUTPUT(buf->type)) {
+ struct vb2_queue *vq;
+ struct vb2_v4l2_buffer *vb2_v4l2 = NULL;
+ struct aml_video_dec_buf *aml_buf = NULL;
+ struct file *file = NULL;
+
+ mutex_lock(&ctx->lock);
+ vq = v4l2_m2m_get_vq(ctx->m2m_ctx, buf->type);
+ vb2_v4l2 = to_vb2_v4l2_buffer(vq->bufs[buf->index]);
+ aml_buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
+
+ file = fget(vb2_v4l2->private);
+ if (is_v4l2_buf_file(file) &&
+ !aml_buf->privdata.is_install) {
+ dmabuf_fd_install_data(vb2_v4l2->private,
+ (void*)&aml_buf->privdata,
+ sizeof(struct file_privdata));
+ aml_buf->privdata.is_install = true;
+ }
+ fput(file);
+ mutex_unlock(&ctx->lock);
+ }
+
+ return ret;
}
static int vidioc_vdec_querycap(struct file *file, void *priv,
@@ -1584,7 +1676,7 @@ static void vb2ops_vdec_buf_queue(struct vb2_buffer *vb)
__func__, __LINE__, buf->frame_buffer.m.mem[0].addr,
buf->frame_buffer.vf_handle, buf->frame_buffer.status);
- if (!buf->que_in_m2m && buf->frame_buffer.status == FB_ST_NORMAL) {
+ if (!buf->que_in_m2m) {
aml_v4l2_debug(2, "[%d] enque capture buf idx %d, %p",
ctx->id, vb->index, vb);
v4l2_m2m_buf_queue(ctx->m2m_ctx, vb2_v4l2);
@@ -1810,21 +1902,21 @@ static void vb2ops_vdec_stop_streaming(struct vb2_queue *q)
while ((vb2_v4l2 = v4l2_m2m_src_buf_remove(ctx->m2m_ctx)))
v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
} else {
- while ((vb2_v4l2 = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx)))
- v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
-
for (i = 0; i < q->num_buffers; ++i) {
vb2_v4l2 = to_vb2_v4l2_buffer(q->bufs[i]);
buf = container_of(vb2_v4l2, struct aml_video_dec_buf, vb);
buf->frame_buffer.status = FB_ST_NORMAL;
buf->que_in_m2m = false;
+ buf->privdata.is_install = false;
+
+ if (vb2_v4l2->vb2_buf.state == VB2_BUF_STATE_ACTIVE)
+ v4l2_m2m_buf_done(vb2_v4l2, VB2_BUF_STATE_ERROR);
/*pr_info("idx: %d, state: %d\n",
q->bufs[i]->index, q->bufs[i]->state);*/
}
-
- ctx->buf_used_count = 0;
}
+ ctx->buf_used_count = 0;
}
static void m2mops_vdec_device_run(void *priv)
@@ -1955,6 +2047,39 @@ err:
return ret;
}
+static int vidioc_vdec_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+ struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ if (vdec_if_get_param(ctx, GET_PARAM_CONFIG_INFO,
+ &ctx->config.parm.dec)) {
+ pr_err("[%d] GET_PARAM_CONFIG_INFO err\n", ctx->id);
+ return -1;
+ }
+ memcpy(a->parm.raw_data, ctx->config.parm.data,
+ sizeof(a->parm.raw_data));
+ }
+
+ return 0;
+}
+
+static int vidioc_vdec_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *a)
+{
+ struct aml_vcodec_ctx *ctx = fh_to_ctx(fh);
+
+ if (a->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+ ctx->config.type = V4L2_CONFIG_PARM_DECODE;
+ ctx->config.length = sizeof(a->parm.raw_data);
+ memcpy(ctx->config.parm.data, a->parm.raw_data,
+ sizeof(a->parm.raw_data));
+ }
+
+ return 0;
+}
+
static void m2mops_vdec_lock(void *m2m_priv)
{
struct aml_vcodec_ctx *ctx = m2m_priv;
@@ -1993,7 +2118,7 @@ static const struct vb2_ops aml_vdec_vb2_ops = {
const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
.vidioc_streamon = vidioc_decoder_streamon,
- .vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
+ .vidioc_streamoff = vidioc_decoder_streamoff,
.vidioc_reqbufs = vidioc_decoder_reqbufs,
.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,//??
@@ -2032,6 +2157,9 @@ const struct v4l2_ioctl_ops aml_vdec_ioctl_ops = {
.vidioc_decoder_cmd = vidioc_decoder_cmd,
.vidioc_try_decoder_cmd = vidioc_try_decoder_cmd,
+
+ .vidioc_g_parm = vidioc_vdec_g_parm,
+ .vidioc_s_parm = vidioc_vdec_s_parm,
};
int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
diff --git a/drivers/amvdec_ports/aml_vcodec_dec.h b/drivers/amvdec_ports/aml_vcodec_dec.h
index 19923c0..c465857 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec.h
+++ b/drivers/amvdec_ports/aml_vcodec_dec.h
@@ -39,6 +39,25 @@
#define AML_V4L2_SET_DECMODE (V4L2_CID_USER_AMLOGIC_BASE + 0)
+/* codec types of get/set parms. */
+#define V4L2_CONFIG_PARM_ENCODE (0)
+#define V4L2_CONFIG_PARM_DECODE (1)
+
+/* types of decode parms. */
+#define V4L2_CONFIG_PARM_DECODE_COMMON (1 << 0)
+#define V4L2_CONFIG_PARM_DECODE_PICINFO (1 << 1)
+#define V4L2_CONFIG_PARM_DECODE_HDRINFO (1 << 2)
+
+/* for video composer metafd private_data struct */
+struct file_privdata {
+ struct vframe_s vf;
+ struct vframe_s *vf_p;
+ bool is_keep;
+ int keep_id;
+ int keep_head_id;
+ bool is_install;
+};
+
/**
* struct vdec_fb - decoder frame buffer
* @mem_type : gather or scatter memory.
@@ -83,6 +102,7 @@ struct aml_video_dec_buf {
struct list_head list;
struct vdec_v4l2_buffer frame_buffer;
+ struct file_privdata privdata;
struct codec_mm_s *mem[2];
char mem_onwer[32];
bool used;
@@ -94,18 +114,9 @@ struct aml_video_dec_buf {
bool error;
};
-struct aml_vdec_pic_infos {
- u32 visible_width;
- u32 visible_height;
- u32 coded_width;
- u32 coded_height;
- int dpb_size;
-};
-
extern const struct v4l2_ioctl_ops aml_vdec_ioctl_ops;
extern const struct v4l2_m2m_ops aml_vdec_m2m_ops;
-
/*
* aml_vdec_lock/aml_vdec_unlock are for ctx instance to
* get/release lock before/after access decoder hw.
@@ -119,9 +130,7 @@ int aml_vcodec_dec_queue_init(void *priv, struct vb2_queue *src_vq,
void aml_vcodec_dec_set_default_params(struct aml_vcodec_ctx *ctx);
void aml_vcodec_dec_release(struct aml_vcodec_ctx *ctx);
int aml_vcodec_dec_ctrls_setup(struct aml_vcodec_ctx *ctx);
-
void vdec_device_vf_run(struct aml_vcodec_ctx *ctx);
-
void try_to_capture(struct aml_vcodec_ctx *ctx);
void aml_thread_notify(struct aml_vcodec_ctx *ctx,
enum aml_thread_type type);
@@ -129,5 +138,6 @@ int aml_thread_start(struct aml_vcodec_ctx *ctx, aml_thread_func func,
enum aml_thread_type type, const char *thread_name);
void aml_thread_stop(struct aml_vcodec_ctx *ctx);
void wait_vcodec_ending(struct aml_vcodec_ctx *ctx);
+void vdec_frame_buffer_release(void *data);
#endif /* _AML_VCODEC_DEC_H_ */
diff --git a/drivers/amvdec_ports/aml_vcodec_dec_drv.c b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
index a50f9b1..6307e5b 100644
--- a/drivers/amvdec_ports/aml_vcodec_dec_drv.c
+++ b/drivers/amvdec_ports/aml_vcodec_dec_drv.c
@@ -35,12 +35,20 @@
#include "aml_vcodec_dec_pm.h"
#include "aml_vcodec_util.h"
#include "aml_vcodec_vfm.h"
+#include <linux/file.h>
+#include <linux/anon_inodes.h>
#define VDEC_HW_ACTIVE 0x10
#define VDEC_IRQ_CFG 0x11
#define VDEC_IRQ_CLR 0x10
#define VDEC_IRQ_CFG_REG 0xa4
+#define V4LVIDEO_IOC_MAGIC 'I'
+#define V4LVIDEO_IOCTL_ALLOC_FD _IOW(V4LVIDEO_IOC_MAGIC, 0x02, int)
+#define V4LVIDEO_IOCTL_CHECK_FD _IOW(V4LVIDEO_IOC_MAGIC, 0x03, int)
+#define V4LVIDEO_IOCTL_SET_CONFIG_PARAMS _IOWR(V4LVIDEO_IOC_MAGIC, 0x04, struct v4l2_config_parm)
+#define V4LVIDEO_IOCTL_GET_CONFIG_PARAMS _IOWR(V4LVIDEO_IOC_MAGIC, 0x05, struct v4l2_config_parm)
+
bool scatter_mem_enable;
bool param_sets_from_ucode;
@@ -68,7 +76,6 @@ static int fops_vcodec_open(struct file *file)
file->private_data = &ctx->fh;
v4l2_fh_add(&ctx->fh);
INIT_LIST_HEAD(&ctx->list);
- INIT_LIST_HEAD(&ctx->capture_list);
INIT_LIST_HEAD(&ctx->vdec_thread_list);
dev->filp = file;
ctx->dev = dev;
@@ -159,12 +166,197 @@ static int fops_vcodec_release(struct file *file)
return 0;
}
+static int v4l2video_file_release(struct inode *inode, struct file *file)
+{
+ aml_v4l2_debug(2,"%s: file: 0x%p, data: %p",
+ __func__, file, file->private_data);
+
+ if (file->private_data)
+ vdec_frame_buffer_release(file->private_data);
+
+ return 0;
+}
+
+const struct file_operations v4l2_file_fops = {
+ .release = v4l2video_file_release,
+};
+
+int v4l2_alloc_fd(int *fd)
+{
+ struct file *file = NULL;
+ int file_fd = get_unused_fd_flags(O_CLOEXEC);
+
+ if (file_fd < 0) {
+ pr_err("%s: get unused fd fail\n", __func__);
+ return -ENODEV;
+ }
+
+ file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0);
+ if (IS_ERR(file)) {
+ put_unused_fd(file_fd);
+ pr_err("%s: anon_inode_getfile fail\n", __func__);
+ return -ENODEV;
+ }
+
+ file->private_data =
+ kzalloc(sizeof(struct file_privdata), GFP_KERNEL);
+ if (!file->private_data) {
+ pr_err("%s: alloc priv data faild.\n", __func__);
+ return -ENOMEM;
+ }
+
+ aml_v4l2_debug(2, "%s: fd %d, file %p", __func__, file_fd, file);
+
+ fd_install(file_fd, file);
+ *fd = file_fd;
+
+ return 0;
+}
+
+extern const struct file_operations v4l2_file_fops;
+bool is_v4l2_buf_file(struct file *file)
+{
+ return file->f_op == &v4l2_file_fops;
+}
+
+int v4l2_check_fd(int fd)
+{
+ struct file *file;
+
+ file = fget(fd);
+
+ if (!file) {
+ pr_err("%s: fget fd %d fail!\n", __func__, fd);
+ return -EBADF;
+ }
+
+ if (!is_v4l2_buf_file(file)) {
+ fput(file);
+ pr_err("%s: is_v4l2_buf_file fail!\n", __func__);
+ return -1;
+ }
+
+ fput(file);
+
+ aml_v4l2_debug(5, "%s: ioctl ok, comm %s, pid %d",
+ __func__, current->comm, current->pid);
+
+ return 0;
+}
+
+int dmabuf_fd_install_data(int fd, void* data, u32 size)
+{
+ struct file *file;
+
+ file = fget(fd);
+
+ if (!file) {
+ pr_err("%s: fget fd %d fail!, comm %s, pid %d\n",
+ __func__, fd, current->comm, current->pid);
+ return -EBADF;
+ }
+
+ if (!is_v4l2_buf_file(file)) {
+ fput(file);
+ pr_err("%s the buf file checked fail!\n", __func__);
+ return -EBADF;
+ }
+
+ memcpy(file->private_data, data, size);
+
+ fput(file);
+
+ return 0;
+}
+
+static long v4l2_vcodec_ioctl(struct file *file,
+ unsigned int cmd,
+ ulong arg)
+{
+ long ret = 0;
+ void __user *argp = (void __user *)arg;
+
+ switch (cmd) {
+ case V4LVIDEO_IOCTL_ALLOC_FD:
+ {
+ u32 v4lvideo_fd = 0;
+
+ ret = v4l2_alloc_fd(&v4lvideo_fd);
+ if (ret != 0)
+ break;
+ put_user(v4lvideo_fd, (u32 __user *)argp);
+ aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_ALLOC_FD fd %d",
+ __func__, v4lvideo_fd);
+ break;
+ }
+ case V4LVIDEO_IOCTL_CHECK_FD:
+ {
+ u32 v4lvideo_fd = 0;
+
+ get_user(v4lvideo_fd, (u32 __user *)argp);
+ ret = v4l2_check_fd(v4lvideo_fd);
+ if (ret != 0)
+ break;
+ aml_v4l2_debug(4, "%s: V4LVIDEO_IOCTL_CHECK_FD fd %d",
+ __func__, v4lvideo_fd);
+ break;
+ }
+ case V4LVIDEO_IOCTL_SET_CONFIG_PARAMS:
+ {
+ struct aml_vcodec_ctx *ctx = NULL;
+
+ if (is_v4l2_buf_file(file))
+ break;
+
+ ctx = fh_to_ctx(file->private_data);
+ if (copy_from_user((void *)&ctx->config,
+ (void *)argp, sizeof(ctx->config))) {
+ pr_err("[%s],set config parm err\n", __func__);
+ return -EFAULT;
+ }
+ break;
+ }
+ case V4LVIDEO_IOCTL_GET_CONFIG_PARAMS:
+ {
+ struct aml_vcodec_ctx *ctx = NULL;
+
+ if (is_v4l2_buf_file(file))
+ break;
+
+ ctx = fh_to_ctx(file->private_data);
+ if (copy_to_user((void *)argp,
+ (void *)&ctx->config, sizeof(ctx->config))) {
+ pr_err("[%s],get config parm err\n", __func__);
+ return -EFAULT;
+ }
+ break;
+ }
+ default:
+ return video_ioctl2(file, cmd, arg);
+ }
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+static long v4l2_compat_ioctl(struct file *file,
+ unsigned int cmd, ulong arg)
+{
+ long ret = 0;
+
+ ret = v4l2_vcodec_ioctl(file, cmd, (ulong)compat_ptr(arg));
+ return ret;
+}
+#endif
+
static const struct v4l2_file_operations aml_vcodec_fops = {
.owner = THIS_MODULE,
.open = fops_vcodec_open,
.release = fops_vcodec_release,
.poll = v4l2_m2m_fop_poll,
- .unlocked_ioctl = video_ioctl2,
+ .unlocked_ioctl = v4l2_vcodec_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = v4l2_compat_ioctl,
+#endif
.mmap = v4l2_m2m_fop_mmap,
};
diff --git a/drivers/amvdec_ports/aml_vcodec_drv.h b/drivers/amvdec_ports/aml_vcodec_drv.h
index a7c9aaf..21a1ab2 100644
--- a/drivers/amvdec_ports/aml_vcodec_drv.h
+++ b/drivers/amvdec_ports/aml_vcodec_drv.h
@@ -26,6 +26,7 @@
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-core.h>
+#include <linux/amlogic/media/vfm/vframe.h>
#include "aml_vcodec_util.h"
#define AML_VCODEC_DRV_NAME "aml_vcodec_drv"
@@ -235,6 +236,58 @@ struct vdec_pic_info {
unsigned int c_len_sz;
};
+struct aml_vdec_pic_infos {
+ u32 visible_width;
+ u32 visible_height;
+ u32 coded_width;
+ u32 coded_height;
+ u32 dpb_size;
+};
+
+struct aml_vdec_hdr_infos {
+ /*
+ * bit 29 : present_flag
+ * bit 28-26: video_format "component", "PAL", "NTSC", "SECAM", "MAC", "unspecified"
+ * bit 25 : range "limited", "full_range"
+ * bit 24 : color_description_present_flag
+ * bit 23-16: color_primaries "unknown", "bt709", "undef", "bt601",
+ * "bt470m", "bt470bg", "smpte170m", "smpte240m", "film", "bt2020"
+ * bit 15-8 : transfer_characteristic unknown", "bt709", "undef", "bt601",
+ * "bt470m", "bt470bg", "smpte170m", "smpte240m",
+ * "linear", "log100", "log316", "iec61966-2-4",
+ * "bt1361e", "iec61966-2-1", "bt2020-10", "bt2020-12",
+ * "smpte-st-2084", "smpte-st-428"
+ * bit 7-0 : matrix_coefficient "GBR", "bt709", "undef", "bt601",
+ * "fcc", "bt470bg", "smpte170m", "smpte240m",
+ * "YCgCo", "bt2020nc", "bt2020c"
+ */
+ u32 signal_type;
+ struct vframe_master_display_colour_s color_parms;
+};
+
+struct aml_dec_params {
+ u32 dec_parms_status;
+ u32 es_need_header;
+ u32 double_write_mode;
+ u32 buffer_mode;
+ u32 buffer_width;
+ u32 buffer_height;
+ u32 buffer_margin;
+ struct aml_vdec_pic_infos pic;
+ struct aml_vdec_hdr_infos hdr;
+};
+
+struct v4l2_config_parm {
+ u32 type;
+ u32 length;
+ union {
+ struct aml_dec_params dec;
+ struct aml_enc_params enc;
+ u8 data[200];
+ } parm;
+ u8 buf[4096];
+};
+
enum aml_thread_type {
AML_THREAD_OUTPUT,
AML_THREAD_CAPTURE,
@@ -335,7 +388,6 @@ struct aml_vcodec_ctx {
struct mutex lock;
struct completion comp;
bool has_receive_eos;
- struct list_head capture_list;
struct list_head vdec_thread_list;
bool is_drm_mode;
bool is_stream_mode;
@@ -344,8 +396,11 @@ struct aml_vcodec_ctx {
bool scatter_mem_enable;
bool param_sets_from_ucode;
bool v4l_codec_ready;
+ bool v4l_codec_dpb_ready;
wait_queue_head_t wq;
spinlock_t slock;
+ struct v4l2_config_parm config;
+ bool is_stream_off;
};
/**
diff --git a/drivers/amvdec_ports/decoder/aml_h264_parser.c b/drivers/amvdec_ports/decoder/aml_h264_parser.c
index cf4e0e8..d5d1d91 100644
--- a/drivers/amvdec_ports/decoder/aml_h264_parser.c
+++ b/drivers/amvdec_ports/decoder/aml_h264_parser.c
@@ -100,10 +100,10 @@ static int decode_scaling_list(struct get_bits_context *gb,
for (i = 0; i < size; i++) {
if (next) {
int v = get_se_golomb(gb);
- if (v < -128 || v > 127) {
+ /*if (v < -128 || v > 127) { //JM19 has not check.
pr_err( "delta scale %d is invalid\n", v);
return -1;
- }
+ }*/
next = (last + v) & 0xff;
}
if (!i && !next) { /* matrix not written, we use the preset one */
diff --git a/drivers/amvdec_ports/decoder/vdec_h264_if.c b/drivers/amvdec_ports/decoder/vdec_h264_if.c
index 02848b8..7bf4d5e 100644
--- a/drivers/amvdec_ports/decoder/vdec_h264_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_h264_if.c
@@ -27,6 +27,7 @@
#include "../vdec_drv_if.h"
#include "../aml_vcodec_util.h"
#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
#include "../aml_vcodec_adapt.h"
#include "../vdec_drv_base.h"
#include "../aml_vcodec_vfm.h"
@@ -150,6 +151,7 @@ struct vdec_h264_inst {
struct aml_vdec_adapt vdec;
struct vdec_h264_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
struct completion comp;
};
@@ -244,6 +246,46 @@ static void skip_aud_data(u8 **data, u32 *size)
}
}
+static u32 vdec_config_default_parms(u8 *parm)
+{
+ u8 *pbuf = parm;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "mh264_double_write_mode:16;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+
+ return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_h264_inst *inst)
+{
+ struct aml_vcodec_ctx *ctx = inst->ctx;
+
+ if (!ctx->config.length) {
+ ctx->config.type = V4L2_CONFIG_PARM_DECODE;
+ ctx->config.parm.dec.double_write_mode = 16;
+ inst->parms = ctx->config.parm.dec;
+
+ ctx->config.length =
+ vdec_config_default_parms(ctx->config.buf);
+ } else {
+ u8 *pbuf = ctx->config.buf;
+
+ inst->parms = ctx->config.parm.dec;
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "mh264_double_write_mode:%d;",
+ inst->parms.double_write_mode);
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+ inst->parms.buffer_margin);
+ ctx->config.length = pbuf - ctx->config.buf;
+ }
+
+ inst->vdec.config = ctx->config;
+
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_COMMON;
+}
+
static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_h264_inst *inst = NULL;
@@ -253,20 +295,21 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
+ inst->vdec.video_type = VFORMAT_H264;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
- inst->vdec.video_type = VFORMAT_H264;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ vdec_parser_parms(inst);
/* set play mode.*/
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
ret = video_decoder_init(&inst->vdec);
@@ -289,21 +332,12 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
-
init_completion(&inst->comp);
aml_vcodec_debug(inst, "H264 Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
@@ -388,11 +422,32 @@ static int refer_buffer_num(int level_idc, int max_poc_cnt,
}
#endif
+static void vdec_config_dw_mode(struct vdec_pic_info *pic, int dw_mode)
+{
+ switch (dw_mode) {
+ case 0x1: /* (w x h) + (w/2 x h) */
+ pic->coded_width += pic->coded_width >> 1;
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+ break;
+ case 0x2: /* (w x h) + (w/2 x h/2) */
+ pic->coded_width += pic->coded_width >> 1;
+ pic->coded_height += pic->coded_height >> 1;
+ pic->y_len_sz = pic->coded_width * pic->coded_height;
+ pic->c_len_sz = pic->y_len_sz >> 1;
+ break;
+ default: /* nothing to do */
+ break;
+ }
+}
+
static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_h264_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
+ int dw = inst->parms.double_write_mode;
+ int margin = inst->parms.buffer_margin;
u32 mb_w, mb_h, width, height;
mb_w = sps->mb_width;
@@ -421,11 +476,18 @@ static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps
pic->c_len_sz = pic->y_len_sz >> 1;
/* calc DPB size */
- dec->dpb_sz = sps->ref_frame_count;
+ dec->dpb_sz = sps->num_reorder_frames + 1 + margin;
- aml_vcodec_debug(inst, "[%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);
+ vdec_config_dw_mode(pic, dw);
+
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PICINFO;
+
+ aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+ inst->ctx->id,inst->parms.double_write_mode,
+ pic->coded_width, pic->coded_height,
+ pic->visible_width, pic->visible_height,
+ dec->dpb_sz - margin + 1, margin);
}
static bool check_frame_combine(u8 *buf, u32 size, int *pos)
@@ -453,6 +515,24 @@ static bool check_frame_combine(u8 *buf, u32 size, int *pos)
return combine;
}
+static int vdec_search_startcode(u8 *buf, u32 range)
+{
+ int pos = -1;
+ int i = 0, j = 0;
+ u8 *p = buf;
+
+ for (i = 4; i < range; i++) {
+ j = find_start_code(p, 7);
+ if (j > 0) {
+ pos = p - buf + j;
+ break;
+ }
+ p++;
+ }
+
+ return pos;
+}
+
static int stream_parse_by_ucode(struct vdec_h264_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
@@ -475,7 +555,6 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size)
{
int ret = 0;
struct h264_param_sets *ps;
- u32 nal_type;
int nal_idx = 0;
bool is_combine = false;
@@ -483,10 +562,6 @@ static int stream_parse(struct vdec_h264_inst *inst, u8 *buf, u32 size)
if (nal_idx < 0)
return -1;
- nal_type = AVC_NAL_TYPE(buf[nal_idx]);
- if (nal_type != NAL_H264_SPS)
- 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;
@@ -618,7 +693,9 @@ static int vdec_write_nalu(struct vdec_h264_inst *inst,
int nalu_pos;
u32 nal_type;
- nalu_pos = find_start_code(buf, size);
+ /*print_hex_debug(buf, size, 32);*/
+
+ nalu_pos = vdec_search_startcode(buf, 16);
if (nalu_pos < 0)
goto err;
@@ -754,6 +831,14 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
return ret;
}
+static void get_param_config_info(struct vdec_h264_inst *inst,
+ struct aml_dec_params *parms)
+{
+ *parms = inst->parms;
+
+ aml_vcodec_debug(inst, "parms status: %u", parms->dec_parms_status);
+}
+
static int vdec_h264_get_param(unsigned long h_vdec,
enum vdec_get_param_type type, void *out)
{
@@ -786,6 +871,9 @@ static int vdec_h264_get_param(unsigned long h_vdec,
get_crop_info(inst, out);
break;
+ case GET_PARAM_CONFIG_INFO:
+ get_param_config_info(inst, out);
+ break;
default:
aml_vcodec_err(inst, "invalid get parameter type=%d", type);
ret = -EINVAL;
@@ -824,6 +912,9 @@ static void set_param_pic_info(struct vdec_h264_inst *inst,
dec->dpb_sz = info->dpb_size;
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PICINFO;
+
/*wake up*/
complete(&inst->comp);
@@ -833,6 +924,16 @@ static void set_param_pic_info(struct vdec_h264_inst *inst,
info->dpb_size);
}
+static void set_param_hdr_info(struct vdec_h264_inst *inst,
+ struct aml_vdec_hdr_infos *hdr)
+{
+ inst->parms.hdr = *hdr;
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_HDRINFO;
+
+ //pr_info("H264 set HDR infos\n");
+}
+
static int vdec_h264_set_param(unsigned long h_vdec,
enum vdec_set_param_type type, void *in)
{
@@ -853,6 +954,9 @@ static int vdec_h264_set_param(unsigned long h_vdec,
set_param_pic_info(inst, in);
break;
+ case SET_PARAM_HDR_INFO:
+ set_param_hdr_info(inst, in);
+ break;
default:
aml_vcodec_err(inst, "invalid set parameter type=%d", type);
ret = -EINVAL;
diff --git a/drivers/amvdec_ports/decoder/vdec_hevc_if.c b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
index 59ce85f..fb3fce7 100644
--- a/drivers/amvdec_ports/decoder/vdec_hevc_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_hevc_if.c
@@ -26,6 +26,7 @@
#include "../vdec_drv_if.h"
#include "../aml_vcodec_util.h"
#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
#include "../aml_vcodec_adapt.h"
#include "../vdec_drv_base.h"
#include "../aml_vcodec_vfm.h"
@@ -112,6 +113,7 @@ struct vdec_hevc_inst {
struct aml_vdec_adapt vdec;
struct vdec_hevc_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
struct completion comp;
};
@@ -144,6 +146,55 @@ static void get_dpb_size(struct vdec_hevc_inst *inst, unsigned int *dpb_sz)
aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
}
+static u32 vdec_config_default_parms(u8 *parm)
+{
+ u8 *pbuf = parm;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+ pbuf += sprintf(pbuf, "hevc_double_write_mode:16;");
+ pbuf += sprintf(pbuf, "hevc_buf_width:4096;");
+ pbuf += sprintf(pbuf, "hevc_buf_height:2304;");
+ pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+
+ return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_hevc_inst *inst)
+{
+ struct aml_vcodec_ctx *ctx = inst->ctx;
+
+ if (!ctx->config.length) {
+ ctx->config.type = V4L2_CONFIG_PARM_DECODE;
+ ctx->config.parm.dec.double_write_mode = 16;
+ inst->parms = ctx->config.parm.dec;
+
+ ctx->config.length =
+ vdec_config_default_parms(ctx->config.buf);
+ } else {
+ u8 *pbuf = ctx->config.buf;
+
+ inst->parms = ctx->config.parm.dec;
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+ inst->parms.buffer_margin);
+ pbuf += sprintf(pbuf, "hevc_double_write_mode:%d;",
+ inst->parms.double_write_mode);
+ pbuf += sprintf(pbuf, "hevc_buf_width:%d;",
+ inst->parms.buffer_width);
+ pbuf += sprintf(pbuf, "hevc_buf_height:%d;",
+ inst->parms.buffer_height);
+ pbuf += sprintf(pbuf, "save_buffer_mode:%d;",
+ inst->parms.buffer_mode);
+ ctx->config.length = pbuf - ctx->config.buf;
+ }
+
+ inst->vdec.config = ctx->config;
+
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_COMMON;
+}
+
static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_hevc_inst *inst = NULL;
@@ -153,12 +204,13 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
+ inst->vdec.video_type = VFORMAT_HEVC;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
- inst->vdec.video_type = VFORMAT_HEVC;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ vdec_parser_parms(inst);
/* set play mode.*/
if (ctx->is_drm_mode)
@@ -168,8 +220,8 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->vdec.port.type = PORT_TYPE_HEVC;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
ret = video_decoder_init(&inst->vdec);
@@ -192,21 +244,12 @@ static int vdec_hevc_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
-
init_completion(&inst->comp);
aml_vcodec_debug(inst, "hevc Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
@@ -252,17 +295,76 @@ static int refer_buffer_num(struct h265_SPS_t *sps)
return used_buf_num;
}
+static int vdec_get_dw_mode(struct vdec_hevc_inst *inst, int dw_mode)
+{
+ u32 valid_dw_mode = inst->parms.double_write_mode;
+ int w = inst->parms.buffer_width;
+ int h = inst->parms.buffer_height;
+ u32 dw = 0x1; /*1:1*/
+
+ switch (valid_dw_mode) {
+ case 0x100:
+ if (w > 1920 && h > 1088)
+ dw = 0x4; /*1:2*/
+ break;
+ case 0x200:
+ if (w > 1920 && h > 1088)
+ dw = 0x2; /*1:4*/
+ break;
+ case 0x300:
+ if (w > 1280 && h > 720)
+ dw = 0x4; /*1:2*/
+ break;
+ default:
+ dw = valid_dw_mode;
+ break;
+ }
+
+ return dw;
+}
+
+static int vdec_pic_scale(struct vdec_hevc_inst *inst, int length, int dw_mode)
+{
+ int ret = 64;
+
+ switch (vdec_get_dw_mode(inst, dw_mode)) {
+ case 0x0: /* only afbc, output afbc */
+ ret = 64;
+ break;
+ case 0x1: /* afbc and (w x h), output YUV420 */
+ ret = length;
+ break;
+ case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
+ case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
+ ret = length >> 2;
+ break;
+ case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
+ ret = length >> 1;
+ break;
+ case 0x10: /* (w x h), output YUV420-8bit)*/
+ default:
+ ret = length;
+ break;
+ }
+
+ return ret;
+}
+
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;
+ int dw = inst->parms.double_write_mode;
+ int margin = inst->parms.buffer_margin;
/* fill visible area size that be used for EGL. */
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);
+ pic->visible_width = vdec_pic_scale(inst, pic->visible_width, dw);
+ pic->visible_height = vdec_pic_scale(inst, pic->visible_height, dw);
/* calc visible ares. */
rect->left = 0;
@@ -271,18 +373,23 @@ static void fill_vdec_params(struct vdec_hevc_inst *inst, struct h265_SPS_t *sps
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = ALIGN(sps->width, 32);
- pic->coded_height = ALIGN(sps->height, 32);
+ pic->coded_width = vdec_pic_scale(inst, ALIGN(sps->width, 32), dw);
+ pic->coded_height = vdec_pic_scale(inst, ALIGN(sps->height, 32), dw);
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 = refer_buffer_num(sps);
+ dec->dpb_sz = refer_buffer_num(sps) + margin;
- 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);
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PICINFO;
+
+ pr_info("[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+ inst->ctx->id, inst->parms.double_write_mode,
+ pic->coded_width, pic->coded_height,
+ pic->visible_width, pic->visible_height,
+ dec->dpb_sz - margin, margin);
}
static int stream_parse_by_ucode(struct vdec_hevc_inst *inst, u8 *buf, u32 size)
@@ -505,6 +612,14 @@ static int vdec_hevc_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
return ret;
}
+ static void get_param_config_info(struct vdec_hevc_inst *inst,
+ struct aml_dec_params *parms)
+ {
+ *parms = inst->parms;
+
+ aml_vcodec_debug(inst, "parms status: %u", parms->dec_parms_status);
+ }
+
static int vdec_hevc_get_param(unsigned long h_vdec,
enum vdec_get_param_type type, void *out)
{
@@ -537,6 +652,9 @@ static int vdec_hevc_get_param(unsigned long h_vdec,
get_crop_info(inst, out);
break;
+ case GET_PARAM_CONFIG_INFO:
+ get_param_config_info(inst, out);
+ break;
default:
aml_vcodec_err(inst, "invalid get parameter type=%d", type);
ret = -EINVAL;
@@ -575,6 +693,9 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst,
dec->dpb_sz = info->dpb_size;
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PICINFO;
+
/*wake up*/
complete(&inst->comp);
@@ -584,6 +705,16 @@ static void set_param_pic_info(struct vdec_hevc_inst *inst,
dec->dpb_sz);
}
+static void set_param_hdr_info(struct vdec_hevc_inst *inst,
+ struct aml_vdec_hdr_infos *hdr)
+{
+ inst->parms.hdr = *hdr;
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_HDRINFO;
+
+ //pr_info("H265 set HDR infos\n");
+}
+
static int vdec_hevc_set_param(unsigned long h_vdec,
enum vdec_set_param_type type, void *in)
{
@@ -604,6 +735,9 @@ static int vdec_hevc_set_param(unsigned long h_vdec,
set_param_pic_info(inst, in);
break;
+ case SET_PARAM_HDR_INFO:
+ set_param_hdr_info(inst, in);
+ break;
default:
aml_vcodec_err(inst, "invalid set parameter type=%d", type);
ret = -EINVAL;
diff --git a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
index 8bc5faa..09bfd5e 100644
--- a/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mjpeg_if.c
@@ -151,12 +151,12 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
-
- inst->vdec.video_type = VFORMAT_MJPEG;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ inst->vdec.video_type = VFORMAT_MJPEG;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.config = ctx->config;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
/* set play mode.*/
if (ctx->is_drm_mode)
@@ -194,15 +194,15 @@ static int vdec_mjpeg_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
+ 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, "mjpeg Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
index cdde95b..cf69aa9 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg12_if.c
@@ -151,12 +151,12 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
-
- inst->vdec.video_type = VFORMAT_MPEG12;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ inst->vdec.video_type = VFORMAT_MPEG12;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.config = ctx->config;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
/* set play mode.*/
if (ctx->is_drm_mode)
@@ -166,8 +166,8 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->vdec.port.type = PORT_TYPE_VIDEO;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
ret = video_decoder_init(&inst->vdec);
@@ -194,15 +194,15 @@ static int vdec_mpeg12_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
+ 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, "mpeg12 Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
diff --git a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
index 7a40a4a..a78c904 100644
--- a/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_mpeg4_if.c
@@ -151,24 +151,24 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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;
+ 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.config = ctx->config;
+ inst->vdec.ctx = ctx;
+ inst->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;
+ inst->vdec.port.type = PORT_TYPE_VIDEO;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
ret = video_decoder_init(&inst->vdec);
@@ -195,15 +195,15 @@ static int vdec_mpeg4_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
+ 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;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
//dump_init();
diff --git a/drivers/amvdec_ports/decoder/vdec_vp9_if.c b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
index 5b3bbab..6aa8bd8 100644
--- a/drivers/amvdec_ports/decoder/vdec_vp9_if.c
+++ b/drivers/amvdec_ports/decoder/vdec_vp9_if.c
@@ -26,6 +26,7 @@
#include "../vdec_drv_if.h"
#include "../aml_vcodec_util.h"
#include "../aml_vcodec_dec.h"
+#include "../aml_vcodec_drv.h"
#include "../aml_vcodec_adapt.h"
#include "../vdec_drv_base.h"
#include "../aml_vcodec_vfm.h"
@@ -120,6 +121,7 @@ struct vdec_vp9_inst {
struct aml_vdec_adapt vdec;
struct vdec_vp9_vsi *vsi;
struct vcodec_vfm_s vfm;
+ struct aml_dec_params parms;
struct completion comp;
};
@@ -155,6 +157,89 @@ static void get_dpb_size(struct vdec_vp9_inst *inst, unsigned int *dpb_sz)
aml_vcodec_debug(inst, "sz=%d", *dpb_sz);
}
+static u32 vdec_config_default_parms(u8 *parm)
+{
+ u8 *pbuf = parm;
+
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:7;");
+ pbuf += sprintf(pbuf, "vp9_double_write_mode:16;");
+ pbuf += sprintf(pbuf, "vp9_buf_width:1920;");
+ pbuf += sprintf(pbuf, "vp9_buf_height:1088;");
+ pbuf += sprintf(pbuf, "vp9_max_pic_w:4096;");
+ pbuf += sprintf(pbuf, "vp9_max_pic_h:2304;");
+ pbuf += sprintf(pbuf, "save_buffer_mode:0;");
+ pbuf += sprintf(pbuf, "no_head:0;");
+
+ return parm - pbuf;
+}
+
+static void vdec_parser_parms(struct vdec_vp9_inst *inst)
+{
+ struct aml_vcodec_ctx *ctx = inst->ctx;
+
+ if (!ctx->config.length) {
+ ctx->config.type = V4L2_CONFIG_PARM_DECODE;
+ ctx->config.parm.dec.double_write_mode = 16;
+ inst->parms = ctx->config.parm.dec;
+
+ ctx->config.length =
+ vdec_config_default_parms(ctx->config.buf);
+ } else {
+ u8 *pbuf = ctx->config.buf;
+
+ inst->parms = ctx->config.parm.dec;
+ pbuf += sprintf(pbuf, "parm_v4l_codec_enable:1;");
+ pbuf += sprintf(pbuf, "parm_v4l_buffer_margin:%d;",
+ inst->parms.buffer_margin);
+ pbuf += sprintf(pbuf, "vp9_double_write_mode:%d;",
+ inst->parms.double_write_mode);
+ pbuf += sprintf(pbuf, "vp9_buf_width:%d;",
+ inst->parms.buffer_width);
+ pbuf += sprintf(pbuf, "vp9_buf_height:%d;",
+ inst->parms.buffer_height);
+ pbuf += sprintf(pbuf, "save_buffer_mode:%d;",
+ inst->parms.buffer_mode);
+ pbuf += sprintf(pbuf, "no_head:0;");
+
+ if ((ctx->config.parm.dec.dec_parms_status &
+ V4L2_CONFIG_PARM_DECODE_HDRINFO) &&
+ inst->parms.hdr.color_parms.present_flag) {
+ pbuf += sprintf(pbuf, "mG.x:%d;",
+ inst->parms.hdr.color_parms.primaries[0][0]);
+ pbuf += sprintf(pbuf, "mG.y:%d;",
+ inst->parms.hdr.color_parms.primaries[0][1]);
+ pbuf += sprintf(pbuf, "mB.x:%d;",
+ inst->parms.hdr.color_parms.primaries[1][0]);
+ pbuf += sprintf(pbuf, "mB.y:%d;",
+ inst->parms.hdr.color_parms.primaries[1][1]);
+ pbuf += sprintf(pbuf, "mR.x:%d;",
+ inst->parms.hdr.color_parms.primaries[2][0]);
+ pbuf += sprintf(pbuf, "mR.y:%d;",
+ inst->parms.hdr.color_parms.primaries[2][1]);
+ pbuf += sprintf(pbuf, "mW.x:%d;",
+ inst->parms.hdr.color_parms.white_point[0]);
+ pbuf += sprintf(pbuf, "mW.y:%d;",
+ inst->parms.hdr.color_parms.white_point[1]);
+ pbuf += sprintf(pbuf, "mMaxDL:%d;",
+ inst->parms.hdr.color_parms.luminance[0] / 1000);
+ pbuf += sprintf(pbuf, "mMinDL:%d;",
+ inst->parms.hdr.color_parms.luminance[1]);
+ pbuf += sprintf(pbuf, "mMaxCLL:%d;",
+ inst->parms.hdr.color_parms.content_light_level.max_content);
+ pbuf += sprintf(pbuf, "mMaxFALL:%d;",
+ inst->parms.hdr.color_parms.content_light_level.max_pic_average);
+ }
+
+ ctx->config.length = pbuf - ctx->config.buf;
+ }
+
+ inst->vdec.config = ctx->config;
+
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_COMMON;
+}
+
static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_vp9_inst *inst = NULL;
@@ -164,23 +249,24 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
if (!inst)
return -ENOMEM;
- inst->ctx = ctx;
+ inst->vdec.video_type = VFORMAT_VP9;
+ inst->vdec.dev = ctx->dev->vpu_plat_dev;
+ inst->vdec.filp = ctx->dev->filp;
+ inst->vdec.ctx = ctx;
+ inst->ctx = ctx;
- inst->vdec.video_type = VFORMAT_VP9;
- inst->vdec.dev = ctx->dev->vpu_plat_dev;
- inst->vdec.filp = ctx->dev->filp;
- inst->vdec.ctx = ctx;
+ vdec_parser_parms(inst);
/* set play mode.*/
if (ctx->is_drm_mode)
inst->vdec.port.flag |= PORT_FLAG_DRM;
/* to eable vp9 hw.*/
- inst->vdec.port.type = PORT_TYPE_HEVC;
+ inst->vdec.port.type = PORT_TYPE_HEVC;
/* init vfm */
- inst->vfm.ctx = ctx;
- inst->vfm.ada_ctx = &inst->vdec;
+ inst->vfm.ctx = ctx;
+ inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
/* probe info from the stream */
@@ -197,21 +283,12 @@ static int vdec_vp9_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
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);
-
init_completion(&inst->comp);
aml_vcodec_debug(inst, "vp9 Instance >> %p", inst);
- ctx->ada_ctx = &inst->vdec;
- *h_vdec = (unsigned long)inst;
+ ctx->ada_ctx = &inst->vdec;
+ *h_vdec = (unsigned long)inst;
/* init decoder. */
ret = video_decoder_init(&inst->vdec);
@@ -241,16 +318,73 @@ static int refer_buffer_num(int level_idc, int poc_cnt,
}
#endif
+static int vdec_get_dw_mode(struct vdec_vp9_inst *inst, int dw_mode)
+{
+ u32 valid_dw_mode = inst->parms.double_write_mode;
+ int w = inst->parms.buffer_width;
+ int h = inst->parms.buffer_height;
+ u32 dw = 0x1; /*1:1*/
+
+ switch (valid_dw_mode) {
+ case 0x100:
+ if (w > 1920 && h > 1088)
+ dw = 0x4; /*1:2*/
+ break;
+ case 0x200:
+ if (w > 1920 && h > 1088)
+ dw = 0x2; /*1:4*/
+ break;
+ case 0x300:
+ if (w > 1280 && h > 720)
+ dw = 0x4; /*1:2*/
+ break;
+ default:
+ dw = valid_dw_mode;
+ break;
+ }
+
+ return dw;
+}
+
+static int vdec_pic_scale(struct vdec_vp9_inst *inst, int length, int dw_mode)
+{
+ int ret = 64;
+
+ switch (vdec_get_dw_mode(inst, dw_mode)) {
+ case 0x0: /* only afbc, output afbc */
+ ret = 64;
+ break;
+ case 0x1: /* afbc and (w x h), output YUV420 */
+ ret = length;
+ break;
+ case 0x2: /* afbc and (w/4 x h/4), output YUV420 */
+ case 0x3: /* afbc and (w/4 x h/4), output afbc and YUV420 */
+ ret = length >> 2;
+ break;
+ case 0x4: /* afbc and (w/2 x h/2), output YUV420 */
+ ret = length >> 1;
+ break;
+ case 0x10: /* (w x h), output YUV420-8bit) */
+ default:
+ ret = length;
+ break;
+ }
+
+ return ret;
+}
+
static void fill_vdec_params(struct vdec_vp9_inst *inst,
struct VP9Context *vp9_ctx)
{
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_vp9_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
+ int dw = inst->parms.double_write_mode;
+ int margin = inst->parms.buffer_margin;
/* fill visible area size that be used for EGL. */
- pic->visible_width = vp9_ctx->render_width;
- pic->visible_height = vp9_ctx->render_height;
+ pic->visible_width = vdec_pic_scale(inst, vp9_ctx->render_width, dw);
+ pic->visible_height = vdec_pic_scale(inst, vp9_ctx->render_height, dw);
/* calc visible ares. */
rect->left = 0;
@@ -259,18 +393,23 @@ static void fill_vdec_params(struct vdec_vp9_inst *inst,
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
- pic->coded_width = ALIGN(vp9_ctx->width, 32);
- pic->coded_height = ALIGN(vp9_ctx->height, 32);
+ pic->coded_width = vdec_pic_scale(inst, ALIGN(vp9_ctx->width, 32), dw);
+ pic->coded_height = vdec_pic_scale(inst, ALIGN(vp9_ctx->height, 32), dw);
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 = 5;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+ dec->dpb_sz = 5 + margin;//refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
+
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PICINFO;
- aml_vcodec_debug(inst, "[%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);
+ aml_vcodec_debug(inst, "[%d] The stream infos, dw: %d, coded:(%d x %d), visible:(%d x %d), DPB: %d, margin: %d\n",
+ inst->ctx->id, inst->parms.double_write_mode,
+ pic->coded_width, pic->coded_height,
+ pic->visible_width, pic->visible_height,
+ dec->dpb_sz - margin, margin);
}
static int stream_parse_by_ucode(struct vdec_vp9_inst *inst, u8 *buf, u32 size)
@@ -577,6 +716,14 @@ static int vdec_vp9_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
return ret;
}
+ static void get_param_config_info(struct vdec_vp9_inst *inst,
+ struct aml_dec_params *parms)
+ {
+ *parms = inst->parms;
+
+ aml_vcodec_debug(inst, "parms status: %u", parms->dec_parms_status);
+ }
+
static int vdec_vp9_get_param(unsigned long h_vdec,
enum vdec_get_param_type type, void *out)
{
@@ -609,6 +756,9 @@ static int vdec_vp9_get_param(unsigned long h_vdec,
get_crop_info(inst, out);
break;
+ case GET_PARAM_CONFIG_INFO:
+ get_param_config_info(inst, out);
+ break;
default:
aml_vcodec_err(inst, "invalid get parameter type=%d", type);
ret = -EINVAL;
@@ -649,6 +799,9 @@ static void set_param_pic_info(struct vdec_vp9_inst *inst,
/* calc DPB size */
dec->dpb_sz = 5;
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_PICINFO;
+
/*wake up*/
complete(&inst->comp);
@@ -658,6 +811,16 @@ static void set_param_pic_info(struct vdec_vp9_inst *inst,
info->dpb_size);
}
+static void set_param_hdr_info(struct vdec_vp9_inst *inst,
+ struct aml_vdec_hdr_infos *hdr)
+{
+ inst->parms.hdr = *hdr;
+ inst->parms.dec_parms_status |=
+ V4L2_CONFIG_PARM_DECODE_HDRINFO;
+
+ //pr_info("VP9 set HDR infos\n");
+}
+
static int vdec_vp9_set_param(unsigned long h_vdec,
enum vdec_set_param_type type, void *in)
{
@@ -678,6 +841,9 @@ static int vdec_vp9_set_param(unsigned long h_vdec,
set_param_pic_info(inst, in);
break;
+ case SET_PARAM_HDR_INFO:
+ set_param_hdr_info(inst, in);
+ break;
default:
aml_vcodec_err(inst, "invalid set parameter type=%d", type);
ret = -EINVAL;
diff --git a/drivers/amvdec_ports/vdec_drv_if.h b/drivers/amvdec_ports/vdec_drv_if.h
index 29e48d3..8b029fe 100644
--- a/drivers/amvdec_ports/vdec_drv_if.h
+++ b/drivers/amvdec_ports/vdec_drv_if.h
@@ -68,7 +68,8 @@ enum vdec_get_param_type {
GET_PARAM_FREE_FRAME_BUFFER,
GET_PARAM_PIC_INFO,
GET_PARAM_CROP_INFO,
- GET_PARAM_DPB_SIZE
+ GET_PARAM_DPB_SIZE,
+ GET_PARAM_CONFIG_INFO
};
/*
@@ -77,6 +78,7 @@ enum vdec_get_param_type {
enum vdec_set_param_type {
SET_PARAM_WRITE_FRAME_SYNC,
SET_PARAM_PIC_INFO,
+ SET_PARAM_HDR_INFO
};
/**
diff --git a/drivers/frame_provider/decoder/h264_multi/vmh264.c b/drivers/frame_provider/decoder/h264_multi/vmh264.c
index 3230c07..29c3015 100644
--- a/drivers/frame_provider/decoder/h264_multi/vmh264.c
+++ b/drivers/frame_provider/decoder/h264_multi/vmh264.c
@@ -117,6 +117,7 @@
#define H264_MMU
#define VIDEO_SIGNAL_TYPE_AVAILABLE_MASK 0x20000000
+#define INVALID_IDX -1 /* Invalid buffer index.*/
static int mmu_enable;
/*mmu do not support mbaff*/
@@ -845,6 +846,7 @@ struct vdec_h264_hw_s {
bool new_iframe_flag;
bool ref_err_flush_dpb_flag;
unsigned int first_i_policy;
+ u32 reorder_dpb_size_margin;
};
static u32 again_threshold;
@@ -947,11 +949,10 @@ static int hevc_alloc_mmu(struct vdec_h264_hw_s *hw, int pic_idx,
}
return decoder_mmu_box_alloc_idx(
- hw->mmu_box,
- cur_buf_idx,
- cur_mmu_4k_number,
- mmu_index_adr);
-
+ hw->mmu_box,
+ cur_buf_idx,
+ cur_mmu_4k_number,
+ mmu_index_adr);
}
static int compute_losless_comp_body_size(int width,
@@ -1654,7 +1655,7 @@ static int alloc_one_buf_spec(struct vdec_h264_hw_s *hw, int i)
if (IS_VDEC_DW(hw) == 1)
buf_size += (hw->mb_total << 7) + (hw->mb_total << 6);
else if (IS_VDEC_DW(hw) == 2)
- buf_size += (hw->mb_total << 6) + (hw->mb_total << 6);
+ buf_size += (hw->mb_total << 6) + (hw->mb_total << 5);
#endif
if (hw->buffer_spec[i].cma_alloc_addr)
return 0;
@@ -1798,7 +1799,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
(hw->mb_total << 8) + (hw->mb_total << 7));
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] get fb fail.\n", ctx->id);
return ret;
@@ -2611,18 +2612,6 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->buffer_spec[buffer_index].cma_alloc_addr;
- if (hw->mmu_enable) {
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- dpb_print(DECODE_ID(hw),
- PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
- }
- dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l mem handle: 0x%x\n",
- ((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
- __func__, vf->v4l_mem_handle);
}
if (hw->mmu_enable) {
@@ -2760,7 +2749,8 @@ int notify_v4l_eos(struct vdec_s *vdec)
struct vdec_h264_hw_s *hw = (struct vdec_h264_hw_s *)vdec->private;
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
struct vframe_s *vf = NULL;
- struct vdec_v4l2_buffer *fb = NULL;
+ int index = INVALID_IDX;
+ ulong expires;
if (hw->is_used_v4l && hw->eos) {
if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
@@ -2770,15 +2760,21 @@ int notify_v4l_eos(struct vdec_s *vdec)
return -1;
}
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
- pr_err("[%d] get fb fail.\n", ctx->id);
+ expires = jiffies + msecs_to_jiffies(2000);
+ while (INVALID_IDX == (index = get_free_buf_idx(vdec))) {
+ if (time_after(jiffies, expires))
+ break;
+ }
+
+ if (index == INVALID_IDX) {
+ pr_err("[%d] EOS get free buff fail.\n", ctx->id);
return -1;
}
- vf->type |= VIDTYPE_V4L_EOS;
- vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
- vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->type |= VIDTYPE_V4L_EOS;
+ vf->timestamp = ULONG_MAX;
+ vf->v4l_mem_handle = hw->buffer_spec[index].cma_alloc_addr;
+ vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
@@ -3905,6 +3901,21 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
"%s (%d,%d) dur %d, vf %p, index %d\n", __func__,
hw->frame_width, hw->frame_height, hw->frame_dur, vf, index);
+ /* signal_type */
+ if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK) {
+ vf->signal_type = hw->video_signal_from_vui;
+ if (hw->is_used_v4l) {
+ struct aml_vdec_hdr_infos hdr;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.signal_type = hw->video_signal_from_vui;
+ vdec_v4l_set_hdr_infos(ctx, &hdr);
+ }
+ } else
+ vf->signal_type = 0;
+
vf->width = hw->frame_width;
vf->height = hw->frame_height;
if (force_rate) {
@@ -3918,8 +3929,10 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
(min(hw->h264_ar, (u32) DISP_RATIO_ASPECT_RATIO_MAX)) <<
DISP_RATIO_ASPECT_RATIO_BIT;
vf->orientation = hw->vh264_rotation;
+
if (hw->mmu_enable)
return;
+
vf->canvas0Addr = vf->canvas1Addr = -1;
#ifdef NV21
vf->plane_num = 2;
@@ -3945,12 +3958,6 @@ static void set_frame_info(struct vdec_h264_hw_s *hw, struct vframe_s *vf,
#ifndef NV21
vf->canvas1_config[2] = p_canvas_config[2];
#endif
- /* signal_type */
- if (hw->video_signal_from_vui & VIDEO_SIGNAL_TYPE_AVAILABLE_MASK)
- vf->signal_type = hw->video_signal_from_vui;
- else
- vf->signal_type = 0;
-
}
static void get_picture_qos_info(struct StorablePicture *picture)
@@ -4455,7 +4462,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
unsigned int chroma_format_idc, chroma444;
unsigned int crop_infor, crop_bottom, crop_right;
unsigned int used_reorder_dpb_size_margin
- = reorder_dpb_size_margin;
+ = hw->reorder_dpb_size_margin;
u8 *colocate_vaddr = NULL;
#ifdef CONFIG_AMLOGIC_MEDIA_ENHANCEMENT_DOLBYVISION
@@ -4634,7 +4641,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
if (hw->is_used_v4l) {
if (i != -1) {
- pr_info("alloc the buf of v4l when it is about to decoding.\n");
+ pr_info("v4l: delay alloc the buffer.\n");
}
} else {
if ((i != -1) && alloc_one_buf_spec(hw, i) >= 0)
@@ -4726,7 +4733,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
i = get_buf_spec_by_canvas_pos(hw, j);
if (hw->is_used_v4l) {
- pr_info("alloc the buf of v4l when it is about to decoding.\n");
+ pr_info("v4l: delay alloc the buffer.\n");
break;
} else if (alloc_one_buf_spec(hw, i) < 0)
break;
@@ -8204,8 +8211,10 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (ctx->param_sets_from_ucode &&
!ctx->v4l_codec_ready &&
- hw->v4l_params_parsed)
+ hw->v4l_params_parsed) {
ret = 0; /*the params has parsed.*/
+ } else if (!ctx->v4l_codec_dpb_ready)
+ ret = 0;
}
}
#endif
@@ -8791,16 +8800,6 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
if (pdata->sys_info)
hw->vh264_amstream_dec_info = *pdata->sys_info;
- hw->is_used_v4l = (((unsigned long)
- hw->vh264_amstream_dec_info.param & 0x80) >> 7);
- if (hw->is_used_v4l) {
- hw->mmu_enable = (((unsigned long)
- hw->vh264_amstream_dec_info.param & 0x100) >> 8);
- dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "%s v4: enable mmu %d.\n",
- __func__, hw->mmu_enable);
- }
-
if (force_enable_mmu && pdata->sys_info &&
(get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX) &&
(get_cpu_major_id() != AM_MESON_CPU_MAJOR_ID_GXLX) &&
@@ -8828,9 +8827,22 @@ static int ammvdec_h264_probe(struct platform_device *pdev)
hw->double_write_mode = config_val;
else
hw->double_write_mode = double_write_mode;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_codec_enable",
+ &config_val) == 0)
+ hw->is_used_v4l = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ hw->reorder_dpb_size_margin = config_val;
} else
hw->double_write_mode = double_write_mode;
+ if (!hw->is_used_v4l)
+ hw->reorder_dpb_size_margin = reorder_dpb_size_margin;
+
if (hw->mmu_enable)
hw->double_write_mode &= 0xffff;
diff --git a/drivers/frame_provider/decoder/h265/vh265.c b/drivers/frame_provider/decoder/h265/vh265.c
index 58e2c2b..86055bf 100644
--- a/drivers/frame_provider/decoder/h265/vh265.c
+++ b/drivers/frame_provider/decoder/h265/vh265.c
@@ -128,6 +128,7 @@
#define IS_4K_SIZE(w, h) (((w) * (h)) > (1920*1088))
#define SEI_UserDataITU_T_T35 4
+#define INVALID_IDX -1 /* Invalid buffer index.*/
static struct semaphore h265_sema;
@@ -1301,11 +1302,13 @@ enum SliceType {
/*USE_BUF_BLOCK*/
struct BUF_s {
- unsigned long start_adr;
- unsigned int size;
- int used_flag;
- unsigned int y_size;
- ulong v4l_ref_buf_addr;
+ ulong start_adr;
+ u32 size;
+ u32 luma_size;
+ ulong header_addr;
+ u32 header_size;
+ int used_flag;
+ ulong v4l_ref_buf_addr;
} /*BUF_t */;
/* level 6, 6.1 maximum slice number is 800; other is 200 */
@@ -1396,6 +1399,8 @@ struct PIC_s {
int max_mv;
int min_mv;
int avg_mv;
+
+ bool vframe_bound;
} /*PIC_t */;
#define MAX_TILE_COL_NUM 10
@@ -2140,8 +2145,6 @@ static void hevc_init_stru(struct hevc_state_s *hevc,
else
hevc->ignore_bufmgr_error = 0x0;
- hevc->dec_result = DEC_RESULT_FREE_CANVAS;
- vdec_schedule_work(&hevc->work);
/*for (i = 0; i < MAX_REF_PIC_NUM; i++)
hevc->m_PIC[i] = NULL;*/
@@ -2575,6 +2578,31 @@ static void get_rpm_param(union param_u *params)
}
}
+static int get_free_buf_idx(struct hevc_state_s *hevc)
+{
+ int index = INVALID_IDX;
+ struct PIC_s *pic;
+ int i;
+
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ pic = hevc->m_PIC[i];
+ if (pic == NULL ||
+ pic->index == -1 ||
+ pic->BUF_index == -1)
+ continue;
+
+ if (pic->output_mark == 0 &&
+ pic->referenced == 0 &&
+ pic->output_ready == 0) {
+ pic->output_ready = 1;
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+}
+
static struct PIC_s *get_pic_by_POC(struct hevc_state_s *hevc, int POC)
{
int i;
@@ -2643,8 +2671,62 @@ static unsigned int log2i(unsigned int val)
}
static int init_buf_spec(struct hevc_state_s *hevc);
+
+static bool v4l_is_there_vframe_bound(struct hevc_state_s *hevc)
+{
+ int i;
+
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (pic && pic->vframe_bound)
+ return true;
+ }
+
+ return false;
+}
+
+static void v4l_mmu_buffer_release(struct hevc_state_s *hevc)
+{
+ int i;
+
+ /* release workspace */
+ if (hevc->bmmu_box)
+ decoder_bmmu_box_free_idx(hevc->bmmu_box,
+ BMMU_WORKSPACE_ID);
+ /*
+ * it's only when vframe get back to driver, right now we can be sure
+ * that vframe and fd are related. if the playback exits, the capture
+ * requires the upper app to release when the fd is closed, and others
+ * buffers drivers are released by driver.
+ */
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (pic && !pic->vframe_bound) {
+ if (hevc->bmmu_box)
+ decoder_bmmu_box_free_idx(hevc->bmmu_box,
+ VF_BUFFER_IDX(i));
+ if (hevc->mmu_box)
+ decoder_mmu_box_free_idx(hevc->mmu_box, i);
+
+ hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
+ "%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
+ __func__, i, hevc->bmmu_box, hevc->mmu_box);
+ }
+ }
+}
+
static void uninit_mmu_buffers(struct hevc_state_s *hevc)
{
+ if (hevc->is_used_v4l &&
+ v4l_is_there_vframe_bound(hevc)) {
+ if (get_double_write_mode(hevc) != 0x10) {
+ v4l_mmu_buffer_release(hevc);
+ return;
+ }
+ }
+
if (hevc->mmu_box)
decoder_mmu_box_free(hevc->mmu_box);
hevc->mmu_box = NULL;
@@ -2733,7 +2815,6 @@ static void dealloc_mv_bufs(struct hevc_state_s *hevc)
if (hevc->m_PIC[i] != NULL)
hevc->m_PIC[i]->mv_buf_index = -1;
}
-
}
static int alloc_mv_buf(struct hevc_state_s *hevc, int i)
@@ -2963,15 +3044,70 @@ static int cal_current_buf_size(struct hevc_state_s *hevc,
return buf_size;
}
+static int v4l_alloc_buf(struct hevc_state_s *hevc)
+{
+ int i;
+ int ret = -1;
+ struct vdec_v4l2_buffer *fb = NULL;
+
+ if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM)
+ return ret;
+
+ ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb);
+ if (ret < 0) {
+ hevc_print(hevc, 0, "[%d] H265 get buffer fail.\n",
+ ((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id);
+ return ret;
+ }
+
+ for (i = 0; i < BUF_POOL_SIZE; i++)
+ if (hevc->m_BUF[i].start_adr == 0)
+ break;
+
+ if (hevc->mmu_enable) {
+ if ((get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_SM1) &&
+ (IS_8K_SIZE(hevc->pic_w, hevc->pic_h)))
+ hevc->m_BUF[i].header_size =
+ ALIGN(MMU_COMPRESS_8K_HEADER_SIZE, 0x10000);
+ else
+ hevc->m_BUF[i].header_size =
+ ALIGN(MMU_COMPRESS_HEADER_SIZE, 0x10000);
+
+ ret = decoder_bmmu_box_alloc_buf_phy(hevc->bmmu_box,
+ VF_BUFFER_IDX(i), hevc->m_BUF[i].header_size,
+ DRIVER_NAME, &hevc->m_BUF[i].header_addr);
+ if (ret < 0) {
+ hevc_print(hevc, PRINT_FLAG_ERROR,
+ "%s[%d], header size: %d, no mem fatal err\n",
+ __func__, i, hevc->m_BUF[i].header_size);
+ return ret;
+ }
+ }
+
+ hevc->m_BUF[i].used_flag = 0;
+ hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
+ if (fb->num_planes == 1) {
+ hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ hevc->m_BUF[i].size = fb->m.mem[0].size;
+ hevc->m_BUF[i].luma_size = fb->m.mem[0].offset;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ } else if (fb->num_planes == 2) {
+ hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ hevc->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size;
+ hevc->m_BUF[i].luma_size = fb->m.mem[0].size;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ fb->m.mem[1].bytes_used = fb->m.mem[1].size;
+ }
+
+ return ret;
+}
+
static int alloc_buf(struct hevc_state_s *hevc)
{
int i;
int ret = -1;
int buf_size = cal_current_buf_size(hevc, NULL);
- if (hevc->is_used_v4l)
- return 0;
-
if (hevc->fatal_error & DECODER_FATAL_ERROR_NO_MEM)
return ret;
@@ -2981,9 +3117,6 @@ static int alloc_buf(struct hevc_state_s *hevc)
}
if (i < BUF_POOL_SIZE) {
if (buf_size > 0) {
- /*get_cma_alloc_ref();*/ /*DEBUG_TMP*/
- /*alloc compress header first*/
-
ret = decoder_bmmu_box_alloc_buf_phy
(hevc->bmmu_box,
VF_BUFFER_IDX(i), buf_size,
@@ -3043,6 +3176,7 @@ static int alloc_buf(struct hevc_state_s *hevc)
} else
ret = 0;
}
+
if (ret >= 0) {
if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) {
hevc_print(hevc, 0,
@@ -3088,7 +3222,6 @@ static void dealloc_unused_buf(struct hevc_state_s *hevc)
hevc->m_BUF[i].size = 0;
}
}
-
}
static void dealloc_pic_buf(struct hevc_state_s *hevc,
@@ -3174,6 +3307,46 @@ static int get_alloc_pic_count(struct hevc_state_s *hevc)
return alloc_pic_count;
}
+static int v4l_config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
+{
+ int i;
+ int dw_mode = get_double_write_mode(hevc);
+
+ for (i = 0; i < BUF_POOL_SIZE; i++) {
+ if (hevc->m_BUF[i].start_adr != 0 &&
+ hevc->m_BUF[i].used_flag == 0) {
+ hevc->m_BUF[i].used_flag = 1;
+ break;
+ }
+ }
+
+ if (i >= BUF_POOL_SIZE)
+ return -1;
+
+ if (hevc->mmu_enable)
+ pic->header_adr = hevc->m_BUF[i].header_addr;
+
+ pic->BUF_index = i;
+ pic->POC = INVALID_POC;
+ pic->mc_canvas_y = pic->index;
+ pic->mc_canvas_u_v = pic->index;
+
+ if (dw_mode & 0x10) {
+ pic->mc_y_adr = hevc->m_BUF[i].start_adr;
+ pic->mc_u_v_adr = pic->mc_y_adr + hevc->m_BUF[i].luma_size;
+ pic->mc_canvas_y = (pic->index << 1);
+ pic->mc_canvas_u_v = (pic->index << 1) + 1;
+
+ pic->dw_y_adr = pic->mc_y_adr;
+ pic->dw_u_v_adr = pic->mc_u_v_adr;
+ } else if (dw_mode) {
+ pic->dw_y_adr = hevc->m_BUF[i].start_adr;
+ pic->dw_u_v_adr = pic->dw_y_adr + hevc->m_BUF[i].luma_size;
+ }
+
+ return 0;
+}
+
static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
{
int ret = -1;
@@ -3189,45 +3362,8 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
struct buf_stru_s buf_stru;
int buf_size = cal_current_buf_size(hevc, &buf_stru);
int dw_mode = get_double_write_mode(hevc);
- struct vdec_v4l2_buffer *fb = NULL;
-
- if (hevc->is_used_v4l)
- buf_size = 0;
for (i = 0; i < BUF_POOL_SIZE; i++) {
- if (hevc->is_used_v4l && !hevc->m_BUF[i].start_adr) {
- ret = vdec_v4l_get_buffer(hevc->v4l2_ctx, &fb);
- if (ret) {
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "[%d] get fb fail.\n",
- ((struct aml_vcodec_ctx *)
- (hevc->v4l2_ctx))->id);
- return ret;
- }
-
- hevc->m_BUF[i].used_flag = 0;
- hevc->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
- if (fb->num_planes == 1) {
- hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
- hevc->m_BUF[i].size = fb->m.mem[0].size;
- hevc->m_BUF[i].y_size = fb->m.mem[0].offset;
- fb->m.mem[0].bytes_used = fb->m.mem[0].size;
- } else if (fb->num_planes == 2) {
- hevc->m_BUF[i].start_adr = fb->m.mem[0].addr;
- hevc->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size;
- hevc->m_BUF[i].y_size = fb->m.mem[0].size;
- fb->m.mem[0].bytes_used = fb->m.mem[0].size;
- fb->m.mem[1].bytes_used = fb->m.mem[1].size;
- }
-
- pic->BUF_index = i;
-
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l ref buf addr: 0x%x\n",
- ((struct aml_vcodec_ctx *)
- (hevc->v4l2_ctx))->id, __func__, fb);
- }
-
if (hevc->m_BUF[i].start_adr != 0 &&
hevc->m_BUF[i].used_flag == 0 &&
buf_size <= hevc->m_BUF[i].size) {
@@ -3251,8 +3387,7 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
} else
y_adr = hevc->m_BUF[i].start_adr;
- if (!hevc->is_used_v4l)
- y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/
+ y_adr = ((y_adr + 0xffff) >> 16) << 16; /*64k alignment*/
pic->POC = INVALID_POC;
/*ensure get_pic_by_POC()
@@ -3268,15 +3403,9 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
pic->mc_canvas_y = pic->index;
pic->mc_canvas_u_v = pic->index;
if (dw_mode & 0x10) {
- if (hevc->is_used_v4l) {
- pic->mc_y_adr = y_adr;
- pic->mc_u_v_adr = y_adr + hevc->m_BUF[i].y_size;
- } else {
- pic->mc_y_adr = y_adr;
- pic->mc_u_v_adr = y_adr +
- ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
- }
-
+ pic->mc_y_adr = y_adr;
+ pic->mc_u_v_adr = y_adr +
+ ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
pic->mc_canvas_y = (pic->index << 1);
pic->mc_canvas_u_v = (pic->index << 1) + 1;
@@ -3285,10 +3414,9 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
} else if (dw_mode) {
pic->dw_y_adr = y_adr;
pic->dw_u_v_adr = pic->dw_y_adr +
- ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
+ ((buf_stru.mc_buffer_size_u_v_h << 16) << 1);
}
-
if (get_dbg_flag(hevc) & H265_DEBUG_BUFMGR) {
hevc_print(hevc, 0,
"%s index %d BUF_index %d mc_y_adr %x\n",
@@ -3299,8 +3427,6 @@ static int config_pic(struct hevc_state_s *hevc, struct PIC_s *pic)
hevc_print(hevc, 0,
"mmu double write adr %ld\n",
pic->cma_alloc_addr);
-
-
}
ret = 0;
@@ -3313,30 +3439,36 @@ static void init_pic_list(struct hevc_state_s *hevc)
int init_buf_num = get_work_pic_num(hevc);
int dw_mode = get_double_write_mode(hevc);
struct vdec_s *vdec = hw_to_vdec(hevc);
- /*alloc decoder buf*/
- for (i = 0; i < init_buf_num; i++) {
- if (alloc_buf(hevc) < 0) {
- if (i <= 8) {
- /*if alloced (i+1)>=9
- don't send errors.*/
- hevc->fatal_error |=
- DECODER_FATAL_ERROR_NO_MEM;
+ /*alloc decoder buf will be delay if work on v4l. */
+ if (!hevc->is_used_v4l) {
+ for (i = 0; i < init_buf_num; i++) {
+ if (alloc_buf(hevc) < 0) {
+ if (i <= 8) {
+ /*if alloced (i+1)>=9
+ don't send errors.*/
+ hevc->fatal_error |=
+ DECODER_FATAL_ERROR_NO_MEM;
+ }
+ break;
}
- break;
}
}
for (i = 0; i < init_buf_num; i++) {
- struct PIC_s *pic =
- vmalloc(sizeof(struct PIC_s));
- if (pic == NULL) {
- hevc_print(hevc, 0,
- "%s: alloc pic %d fail!!!\n",
- __func__, i);
- break;
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (!pic) {
+ pic = vmalloc(sizeof(struct PIC_s));
+ if (pic == NULL) {
+ hevc_print(hevc, 0,
+ "%s: alloc pic %d fail!!!\n",
+ __func__, i);
+ break;
+ }
+ hevc->m_PIC[i] = pic;
}
memset(pic, 0, sizeof(struct PIC_s));
- hevc->m_PIC[i] = pic;
+
pic->index = i;
pic->BUF_index = -1;
pic->mv_buf_index = -1;
@@ -3349,6 +3481,7 @@ static void init_pic_list(struct hevc_state_s *hevc)
pic->height = hevc->pic_h;
pic->double_write_mode = dw_mode;
+ /*config canvas will be delay if work on v4l. */
if (!hevc->is_used_v4l) {
if (config_pic(hevc, pic) < 0) {
if (get_dbg_flag(hevc))
@@ -3365,16 +3498,20 @@ static void init_pic_list(struct hevc_state_s *hevc)
}
for (; i < MAX_REF_PIC_NUM; i++) {
- struct PIC_s *pic =
- vmalloc(sizeof(struct PIC_s));
- if (pic == NULL) {
- hevc_print(hevc, 0,
- "%s: alloc pic %d fail!!!\n",
- __func__, i);
- break;
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (!pic) {
+ pic = vmalloc(sizeof(struct PIC_s));
+ if (pic == NULL) {
+ hevc_print(hevc, 0,
+ "%s: alloc pic %d fail!!!\n",
+ __func__, i);
+ break;
+ }
+ hevc->m_PIC[i] = pic;
}
memset(pic, 0, sizeof(struct PIC_s));
- hevc->m_PIC[i] = pic;
+
pic->index = -1;
pic->BUF_index = -1;
if (vdec->parallel_dec == 1) {
@@ -5436,14 +5573,20 @@ static struct PIC_s *get_new_pic(struct hevc_state_s *hevc,
return NULL;
if (new_pic->BUF_index < 0) {
- if (alloc_buf(hevc) < 0)
+ ret = hevc->is_used_v4l ?
+ v4l_alloc_buf(hevc) :
+ alloc_buf(hevc);
+ if (ret < 0)
+ return NULL;
+
+ ret = hevc->is_used_v4l ?
+ v4l_config_pic(hevc, new_pic) :
+ config_pic(hevc, new_pic);
+ if (ret < 0) {
+ dealloc_pic_buf(hevc, new_pic);
return NULL;
- else {
- if (config_pic(hevc, new_pic) < 0) {
- dealloc_pic_buf(hevc, new_pic);
- return NULL;
- }
}
+
new_pic->width = hevc->pic_w;
new_pic->height = hevc->pic_h;
set_canvas(hevc, new_pic);
@@ -7127,17 +7270,17 @@ static int H265_alloc_mmu(struct hevc_state_s *hevc, struct PIC_s *new_pic,
return -1;
}
ret = decoder_mmu_box_alloc_idx(
- hevc->mmu_box,
- cur_buf_idx,
- cur_mmu_4k_number,
- mmu_index_adr);
+ hevc->mmu_box,
+ cur_buf_idx,
+ cur_mmu_4k_number,
+ mmu_index_adr);
if (ret == 0)
new_pic->scatter_alloc = 1;
+
hevc_print(hevc, H265_DEBUG_BUFMGR_MORE,
- "%s pic index %d page count(%d) ret =%d\n",
- __func__, cur_buf_idx,
- cur_mmu_4k_number,
- ret);
+ "%s pic index %d page count(%d) ret =%d\n",
+ __func__, cur_buf_idx,
+ cur_mmu_4k_number, ret);
return ret;
}
@@ -7355,10 +7498,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_config_ex(pic->y_canvas_index,
pic->dw_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
canvas_config_ex(pic->uv_canvas_index, pic->dw_u_v_adr,
canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
#ifdef MULTI_INSTANCE_SUPPORT
pic->canvas_config[0].phy_addr =
pic->dw_y_adr;
@@ -7368,7 +7511,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_h;
pic->canvas_config[0].block_mode =
blkmode;
- pic->canvas_config[0].endian = 7;
+ pic->canvas_config[0].endian = hevc->is_used_v4l ? 0 : 7;
pic->canvas_config[1].phy_addr =
pic->dw_u_v_adr;
@@ -7378,7 +7521,7 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_h;
pic->canvas_config[1].block_mode =
blkmode;
- pic->canvas_config[1].endian = 7;
+ pic->canvas_config[1].endian = hevc->is_used_v4l ? 0 : 7;
#endif
} else {
if (!hevc->mmu_enable) {
@@ -7394,10 +7537,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_config_ex(pic->y_canvas_index,
pic->mc_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
}
}
#else
@@ -7413,10 +7556,10 @@ static void set_canvas(struct hevc_state_s *hevc, struct PIC_s *pic)
canvas_config_ex(pic->y_canvas_index, pic->mc_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
canvas_config_ex(pic->uv_canvas_index, pic->mc_u_v_adr,
canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, hevc->is_used_v4l ? 0 : 7);
#endif
}
@@ -7732,6 +7875,20 @@ static void set_frame_info(struct hevc_state_s *hevc, struct vframe_s *vf,
vf_dp->content_light_level.present_flag = 1;
} else
vf_dp->content_light_level.present_flag = 0;
+
+ if (hevc->is_used_v4l &&
+ ((hevc->sei_present_flag & SEI_HDR10PLUS_MASK) ||
+ (vf_dp->present_flag) ||
+ (vf_dp->content_light_level.present_flag))) {
+ struct aml_vdec_hdr_infos hdr;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(hevc->v4l2_ctx);
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.signal_type = vf->signal_type;
+ hdr.color_parms = *vf_dp;
+ vdec_v4l_set_hdr_infos(ctx, &hdr);
+ }
}
static int vh265_vf_states(struct vframe_states *states, void *op_arg)
@@ -7962,6 +8119,8 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg)
if (index_top != 0xff
&& index_top < MAX_REF_PIC_NUM
&& hevc->m_PIC[index_top]) {
+ if (hevc->is_used_v4l)
+ hevc->m_PIC[index_top]->vframe_bound = true;
if (hevc->m_PIC[index_top]->vf_ref > 0) {
hevc->m_PIC[index_top]->vf_ref--;
@@ -7978,6 +8137,8 @@ static void vh265_vf_put(struct vframe_s *vf, void *op_arg)
if (index_bot != 0xff
&& index_bot < MAX_REF_PIC_NUM
&& hevc->m_PIC[index_bot]) {
+ if (hevc->is_used_v4l)
+ hevc->m_PIC[index_bot]->vframe_bound = true;
if (hevc->m_PIC[index_bot]->vf_ref > 0) {
hevc->m_PIC[index_bot]->vf_ref--;
@@ -8310,16 +8471,11 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
vf->v4l_mem_handle
= hevc->m_BUF[pic->BUF_index].v4l_ref_buf_addr;
if (hevc->mmu_enable) {
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
+ vf->mm_box.bmmu_box = hevc->bmmu_box;
+ vf->mm_box.bmmu_idx = VF_BUFFER_IDX(pic->BUF_index);
+ vf->mm_box.mmu_box = hevc->mmu_box;
+ vf->mm_box.mmu_idx = pic->index;
}
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l mem handle: 0x%lx\n",
- ((struct aml_vcodec_ctx *)(hevc->v4l2_ctx))->id,
- __func__, vf->v4l_mem_handle);
}
#ifdef MULTI_INSTANCE_SUPPORT
@@ -8454,6 +8610,7 @@ static int prepare_display_buf(struct hevc_state_s *hevc, struct PIC_s *pic)
if (pic->double_write_mode) {
vf->type = VIDTYPE_PROGRESSIVE | VIDTYPE_VIU_FIELD;
vf->type |= VIDTYPE_VIU_NV21;
+
if ((pic->double_write_mode == 3) &&
(!(IS_8K_SIZE(pic->width, pic->height)))) {
vf->type |= VIDTYPE_COMPRESS;
@@ -8841,7 +8998,8 @@ static int notify_v4l_eos(struct vdec_s *vdec)
struct hevc_state_s *hw = (struct hevc_state_s *)vdec->private;
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
struct vframe_s *vf = NULL;
- struct vdec_v4l2_buffer *fb = NULL;
+ int index = INVALID_IDX;
+ ulong expires;
if (hw->is_used_v4l && hw->eos) {
if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
@@ -8851,15 +9009,21 @@ static int notify_v4l_eos(struct vdec_s *vdec)
return -1;
}
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
- pr_err("[%d] get fb fail.\n", ctx->id);
+ expires = jiffies + msecs_to_jiffies(2000);
+ while (INVALID_IDX == (index = get_free_buf_idx(hw))) {
+ if (time_after(jiffies, expires))
+ break;
+ }
+
+ if (index == INVALID_IDX) {
+ pr_err("[%d] EOS get free buff fail.\n", ctx->id);
return -1;
}
- vf->type |= VIDTYPE_V4L_EOS;
- vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
- vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->type |= VIDTYPE_V4L_EOS;
+ vf->timestamp = ULONG_MAX;
+ vf->v4l_mem_handle = hw->m_BUF[index].v4l_ref_buf_addr;
+ vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
vf_notify_receiver(vdec->vf_provider_name,
@@ -11275,7 +11439,7 @@ static unsigned char is_new_pic_available(struct hevc_state_s *hevc)
/*decode. all reference frames are removed and setting error flag.*/
/*3 represents 2 filed are needed for back-end display and 1 filed is needed for decoding*/
/*when file is interlace.*/
- if ((new_pic == NULL) &&
+ if ((!hevc->is_used_v4l) && (new_pic == NULL) &&
(ref_pic >=
get_work_pic_num(hevc) -
hevc->sps_num_reorder_pics_0 - 3)) {
@@ -11335,6 +11499,14 @@ static int vmh265_stop(struct hevc_state_s *hevc)
hevc_local_uninit(hevc);
+ hevc->init_flag = 0;
+ hevc->first_sc_checked = 0;
+ cancel_work_sync(&hevc->notify_work);
+ cancel_work_sync(&hevc->set_clk_work);
+ cancel_work_sync(&hevc->timeout_work);
+
+ uninit_mmu_buffers(hevc);
+
if (use_cma) {
hevc->uninit_list = 1;
reset_process_time(hevc);
@@ -11350,13 +11522,7 @@ static int vmh265_stop(struct hevc_state_s *hevc)
msleep(20);
#endif
}
- hevc->init_flag = 0;
- hevc->first_sc_checked = 0;
- cancel_work_sync(&hevc->notify_work);
- cancel_work_sync(&hevc->set_clk_work);
cancel_work_sync(&hevc->work);
- cancel_work_sync(&hevc->timeout_work);
- uninit_mmu_buffers(hevc);
vfree(hevc->fw);
hevc->fw = NULL;
@@ -11972,11 +12138,12 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (ctx->param_sets_from_ucode &&
!ctx->v4l_codec_ready &&
- hevc->v4l_params_parsed)
+ hevc->v4l_params_parsed) {
ret = 0; /*the params has parsed.*/
+ } else if (!ctx->v4l_codec_dpb_ready)
+ ret = 0;
}
-
if (ret)
not_run_ready[hevc->index] = 0;
else
@@ -12163,6 +12330,24 @@ static void run(struct vdec_s *vdec, unsigned long mask,
hevc->stat |= STAT_VDEC_RUN;
}
+static void aml_free_canvas(struct vdec_s *vdec)
+{
+ int i;
+ struct hevc_state_s *hevc =
+ (struct hevc_state_s *)vdec->private;
+
+ for (i = 0; i < MAX_REF_PIC_NUM; i++) {
+ struct PIC_s *pic = hevc->m_PIC[i];
+
+ if (pic) {
+ if (vdec->parallel_dec == 1) {
+ vdec->free_canvas_ex(pic->y_canvas_index, vdec->id);
+ vdec->free_canvas_ex(pic->uv_canvas_index, vdec->id);
+ }
+ }
+ }
+}
+
static void reset(struct vdec_s *vdec)
{
@@ -12186,6 +12371,7 @@ static void reset(struct vdec_s *vdec)
hevc->init_flag = 0;
hevc->pic_list_init_flag = 0;
dealloc_mv_bufs(hevc);
+ aml_free_canvas(vdec);
hevc_local_uninit(hevc);
if (vh265_local_init(hevc) < 0)
pr_debug(" %s local init fail\n", __func__);
@@ -12688,6 +12874,15 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
hevc->max_pic_h = config_val;
}
+ if (get_config_int(pdata->config,
+ "parm_v4l_codec_enable",
+ &config_val) == 0)
+ hevc->is_used_v4l = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ hevc->dynamic_buf_num_margin = config_val;
#endif
} else {
if (pdata->sys_info)
@@ -12699,10 +12894,12 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
}
hevc->double_write_mode = double_write_mode;
}
- if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2)
- hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2;
- else
- hevc->dynamic_buf_num_margin = dynamic_buf_num_margin;
+ if (!hevc->is_used_v4l) {
+ if (hevc->save_buffer_mode && dynamic_buf_num_margin > 2)
+ hevc->dynamic_buf_num_margin = dynamic_buf_num_margin -2;
+ else
+ hevc->dynamic_buf_num_margin = dynamic_buf_num_margin;
+ }
if (mmu_enable_force == 0) {
if (get_cpu_major_id() < AM_MESON_CPU_MAJOR_ID_GXL)
@@ -12711,19 +12908,6 @@ static int ammvdec_h265_probe(struct platform_device *pdev)
hevc->mmu_enable = 1;
}
- hevc->is_used_v4l = (((unsigned long)
- hevc->vh265_amstream_dec_info.param & 0x80) >> 7);
- if (hevc->is_used_v4l) {
- hevc->mmu_enable = (((unsigned long) // scatter mem
- hevc->vh265_amstream_dec_info.param & 0x100) >> 8);
- if (!hevc->mmu_enable)
- hevc->double_write_mode = 0x10;
-
- hevc_print(hevc, PRINT_FLAG_V4L_DETAIL,
- "%s v4: enable mmu %d.\n",
- __func__, hevc->mmu_enable);
- }
-
if (init_mmu_buffers(hevc) < 0) {
hevc_print(hevc, 0,
"\n 265 mmu init failed!\n");
diff --git a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
index c8c3eaa..5ec3824 100644
--- a/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
+++ b/drivers/frame_provider/decoder/mjpeg/vmjpeg_multi.c
@@ -309,11 +309,6 @@ static irqreturn_t vmjpeg_isr(struct vdec_s *vdec, int irq)
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->buffer_spec[index].v4l_ref_buf_addr;
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
mmjpeg_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), v4l mem handle: 0x%lx\n",
((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
@@ -839,7 +834,7 @@ static int vmjpeg_v4l_alloc_buff_config_canvas(struct vdec_mjpeg_hw_s *hw, int i
return 0;
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
mmjpeg_debug_print(DECODE_ID(hw), 0,
"[%d] get fb fail.\n",
((struct aml_vcodec_ctx *)
diff --git a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
index 6643f41..bdeb04e 100644
--- a/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
+++ b/drivers/frame_provider/decoder/mpeg12/vmpeg12_multi.c
@@ -384,7 +384,7 @@ static int vmpeg12_v4l_alloc_buff_config_canvas(struct vdec_mpeg12_hw_s *hw, int
return 0;
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
debug_print(DECODE_ID(hw), 0,
"[%d] get fb fail.\n",
((struct aml_vcodec_ctx *)
@@ -1376,11 +1376,6 @@ static int prepare_display_buf(struct vdec_mpeg12_hw_s *hw,
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->pics[index].v4l_ref_buf_addr;
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), v4l mem handle: 0x%lx\n",
((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
diff --git a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
index 30e4072..d920436 100644
--- a/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
+++ b/drivers/frame_provider/decoder/mpeg4/vmpeg4_multi.c
@@ -345,7 +345,7 @@ static int vmpeg4_v4l_alloc_buff_config_canvas(struct vdec_mpeg4_hw_s *hw, int i
return 0;
ret = vdec_v4l_get_buffer(hw->v4l2_ctx, &fb);
- if (ret) {
+ if (ret < 0) {
mmpeg4_debug_print(DECODE_ID(hw), 0,
"[%d] get fb fail.\n",
((struct aml_vcodec_ctx *)
@@ -717,11 +717,6 @@ static int prepare_display_buf(struct vdec_mpeg4_hw_s * hw,
if (hw->is_used_v4l) {
vf->v4l_mem_handle
= hw->pic[index].v4l_ref_buf_addr;
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
mmpeg4_debug_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), v4l mem handle: 0x%lx\n",
((struct aml_vcodec_ctx *)(hw->v4l2_ctx))->id,
diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
index 590b812..461621b 100644
--- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
+++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.c
@@ -41,6 +41,7 @@ struct decoder_bmmu_box {
struct mutex mutex;
struct list_head list;
int total_size;
+ int box_ref_cnt;
int change_size_on_need_smaller;
int align2n; /*can overwite on idx alloc */
int mem_flags; /*can overwite on idx alloc */
@@ -78,6 +79,25 @@ static int decoder_bmmu_box_mgr_del_box(struct decoder_bmmu_box *box)
return 0;
}
+bool decoder_bmmu_box_valide_check(void *box)
+{
+ struct decoder_bmmu_box_mgr *mgr = get_decoder_bmmu_box_mgr();
+ struct decoder_bmmu_box *bmmu_box = NULL;
+ bool is_valide = false;
+
+ mutex_lock(&mgr->mutex);
+ list_for_each_entry(bmmu_box, &mgr->box_list, list) {
+ if (bmmu_box && bmmu_box == box) {
+ is_valide = true;
+ break;
+ }
+ }
+ mutex_unlock(&mgr->mutex);
+
+ return is_valide;
+}
+EXPORT_SYMBOL(decoder_bmmu_box_valide_check);
+
void *decoder_bmmu_box_alloc_box(const char *name,
int channel_id, int max_num,
int aligned, int mem_flags)
@@ -169,6 +189,7 @@ int decoder_bmmu_box_alloc_idx(void *handle, int idx, int size, int aligned_2n,
box->total_size += mm->buffer_size;
mm->ins_id = box->channel_id;
mm->ins_buffer_id = idx;
+ box->box_ref_cnt++;
}
}
mutex_unlock(&box->mutex);
@@ -193,6 +214,7 @@ int decoder_bmmu_box_free_idx(void *handle, int idx)
codec_mm_release(mm, box->name);
box->mm_list[idx] = NULL;
mm = NULL;
+ box->box_ref_cnt--;
}
mutex_unlock(&box->mutex);
return 0;
@@ -224,6 +246,31 @@ int decoder_bmmu_box_free(void *handle)
}
EXPORT_SYMBOL(decoder_bmmu_box_free);
+void decoder_bmmu_try_to_release_box(void *handle)
+{
+ struct decoder_bmmu_box *box = handle;
+ bool is_keep = false;
+ int i;
+
+ if (!box || box->box_ref_cnt)
+ return;
+
+ mutex_lock(&box->mutex);
+ for (i = 0; i < box->max_mm_num; i++) {
+ if (box->mm_list[i]) {
+ is_keep = true;
+ break;
+ }
+ }
+ mutex_unlock(&box->mutex);
+
+ if (!is_keep) {
+ decoder_bmmu_box_mgr_del_box(box);
+ kfree(box);
+ }
+}
+EXPORT_SYMBOL(decoder_bmmu_try_to_release_box);
+
void *decoder_bmmu_box_get_mem_handle(void *box_handle, int idx)
{
struct decoder_bmmu_box *box = box_handle;
diff --git a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
index 8744da1..778cb8e 100644
--- a/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
+++ b/drivers/frame_provider/decoder/utils/decoder_bmmu_box.h
@@ -60,6 +60,9 @@ int decoder_bmmu_box_alloc_idx_wait(
int mem_flags,
int wait_flags);
+bool decoder_bmmu_box_valide_check(void *box);
+void decoder_bmmu_try_to_release_box(void *handle);
+
int decoder_bmmu_box_init(void);
void decoder_bmmu_box_exit(void);
diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
index 5ab7c16..8389514 100644
--- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
+++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.c
@@ -34,6 +34,7 @@ struct decoder_mmu_box {
const char *name;
int channel_id;
int tvp_mode;
+ int box_ref_cnt;
struct mutex mutex;
struct list_head list;
struct codec_mm_scatter *sc_list[1];
@@ -75,6 +76,51 @@ static int decoder_mmu_box_mgr_del_box(struct decoder_mmu_box *box)
return 0;
}
+bool decoder_mmu_box_valide_check(void *box)
+{
+ struct decoder_mmu_box_mgr *mgr = get_decoder_mmu_box_mgr();
+ struct decoder_mmu_box *mmu_box = NULL;
+ bool is_valide = false;
+
+ mutex_lock(&mgr->mutex);
+ list_for_each_entry(mmu_box, &mgr->box_list, list) {
+ if (mmu_box && mmu_box == box) {
+ is_valide = true;
+ break;
+ }
+ }
+ mutex_unlock(&mgr->mutex);
+
+ return is_valide;
+}
+EXPORT_SYMBOL(decoder_mmu_box_valide_check);
+
+void decoder_mmu_try_to_release_box(void *handle)
+{
+ struct decoder_mmu_box *box = handle;
+ bool is_keep = false;
+ int i;
+
+ if (!box || box->box_ref_cnt)
+ return;
+
+ mutex_lock(&box->mutex);
+ for (i = 0; i < box->max_sc_num; i++) {
+ if (box->sc_list[i]) {
+ is_keep = true;
+ break;
+ }
+ }
+ mutex_unlock(&box->mutex);
+
+ if (!is_keep) {
+ decoder_mmu_box_mgr_del_box(box);
+ codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
+ kfree(box);
+ }
+}
+EXPORT_SYMBOL(decoder_mmu_try_to_release_box);
+
int decoder_mmu_box_sc_check(void *handle, int is_tvp)
{
struct decoder_mmu_box *box = handle;
@@ -159,6 +205,7 @@ int decoder_mmu_box_alloc_idx(
return -1;
}
box->sc_list[idx] = sc;
+ box->box_ref_cnt++;
}
for (i = 0; i < num_pages; i++)
@@ -209,7 +256,13 @@ int decoder_mmu_box_free_idx(void *handle, int idx)
if (sc && sc->page_cnt > 0) {
codec_mm_scatter_dec_owner_user(sc, 0);
box->sc_list[idx] = NULL;
- } mutex_unlock(&box->mutex);
+ box->box_ref_cnt--;
+ }
+ mutex_unlock(&box->mutex);
+
+ if (sc && box->box_ref_cnt == 0)
+ codec_mm_scatter_mgt_delay_free_swith(0, 0, 0, box->tvp_mode);
+
return 0;
}
EXPORT_SYMBOL(decoder_mmu_box_free_idx);
diff --git a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
index 9f4e098..029f91a 100644
--- a/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
+++ b/drivers/frame_provider/decoder/utils/decoder_mmu_box.h
@@ -42,6 +42,8 @@ int decoder_mmu_box_move_keep_idx(void *box_handle,
int decoder_mmu_box_free_keep(int keep_id);
int decoder_mmu_box_free_all_keep(void);
void *decoder_mmu_box_get_mem_handle(void *box_handle, int idx);
+bool decoder_mmu_box_valide_check(void *box);
+void decoder_mmu_try_to_release_box(void *handle);
int decoder_mmu_box_init(void);
void decoder_mmu_box_exit(void);
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
index 763d62e..f712696 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.c
@@ -1,94 +1,9 @@
-#include <linux/file.h>
-#include <linux/anon_inodes.h>
#include "vdec_v4l2_buffer_ops.h"
-const struct file_operations v4l2_file_fops = {};
-
-static int is_v4l2_buf_file(struct file *file)
-{
- return file->f_op == &v4l2_file_fops;
-}
-
-static int vdec_v4l_alloc_fd(void)
-{
- int fd;
- struct file *file = NULL;
-
- fd = get_unused_fd_flags(O_CLOEXEC);
- if (fd < 0) {
- pr_err("v4l: get unused fd fail\n");
- return fd;
- }
-
- file = anon_inode_getfile("v4l2_meta_file", &v4l2_file_fops, NULL, 0);
- if (IS_ERR(file)) {
- put_unused_fd(fd);
- pr_err("v4l: get file faill\n");
- return PTR_ERR(file);
- }
-
- fd_install(fd, file);
-
- pr_info("v4l: fd %d, file %p, data %p\n",
- fd, file, file->private_data);
-
- return fd;
-}
-
-static int vdec_v4l_fd_install_data(int fd, void *data)
-{
- struct file *file;
-
- file = fget(fd);
-
- if (!file) {
- pr_info("v4l: fget fd %d fail!, comm %s, pid %d\n",
- fd, current->comm, current->pid);
- return -EBADF;
- }
-
- if (!is_v4l2_buf_file(file)) {
- pr_info("v4l: v4l2 check fd fail!\n");
- return -EBADF;
- }
-
- file->private_data = data;
-
- return 0;
-}
-
-int vdec_v4l_binding_fd_and_vf(ulong v4l_handle, void *vf)
-{
- int ret = 0, fd = -1;
- struct vdec_v4l2_buffer *v4l_buf =
- (struct vdec_v4l2_buffer *) v4l_handle;
-
- if (v4l_buf->m.vf_fd > 0)
- return 0;
-
- fd = vdec_v4l_alloc_fd();
- if (fd < 0) {
- pr_err("v4l: alloc fd fail %d.\n", fd);
- return fd;
- }
-
- ret = vdec_v4l_fd_install_data(fd, vf);
- if (ret < 0) {
- put_unused_fd(fd);
- pr_err("v4l: fd install data fail %d.\n", ret);
- return ret;
- }
-
- v4l_buf->m.vf_fd = fd;
-
- return 0;
-}
-EXPORT_SYMBOL(vdec_v4l_binding_fd_and_vf);
-
int vdec_v4l_get_buffer(struct aml_vcodec_ctx *ctx,
struct vdec_v4l2_buffer **out)
{
- int ret = 0;
+ int ret = -1;
if (ctx->drv_handle == 0)
return -EIO;
@@ -115,6 +30,21 @@ int vdec_v4l_set_pic_infos(struct aml_vcodec_ctx *ctx,
}
EXPORT_SYMBOL(vdec_v4l_set_pic_infos);
+int vdec_v4l_set_hdr_infos(struct aml_vcodec_ctx *ctx,
+ struct aml_vdec_hdr_infos *hdr)
+{
+ int ret = 0;
+
+ if (ctx->drv_handle == 0)
+ return -EIO;
+
+ ret = ctx->dec_if->set_param(ctx->drv_handle,
+ SET_PARAM_HDR_INFO, hdr);
+
+ return ret;
+}
+EXPORT_SYMBOL(vdec_v4l_set_hdr_infos);
+
int vdec_v4l_write_frame_sync(struct aml_vcodec_ctx *ctx)
{
int ret = 0;
diff --git a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
index 6227a8b..b26cf51 100644
--- a/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
+++ b/drivers/frame_provider/decoder/utils/vdec_v4l2_buffer_ops.h
@@ -12,11 +12,11 @@ int vdec_v4l_set_pic_infos(
struct aml_vcodec_ctx *ctx,
struct aml_vdec_pic_infos *info);
+int vdec_v4l_set_hdr_infos(
+ struct aml_vcodec_ctx *ctx,
+ struct aml_vdec_hdr_infos *hdr);
+
int vdec_v4l_write_frame_sync(
struct aml_vcodec_ctx *ctx);
-int vdec_v4l_binding_fd_and_vf(
- ulong v4l_handle,
- void *vf);
-
#endif
diff --git a/drivers/frame_provider/decoder/vp9/vvp9.c b/drivers/frame_provider/decoder/vp9/vvp9.c
index 076d00d..a59ee93 100644
--- a/drivers/frame_provider/decoder/vp9/vvp9.c
+++ b/drivers/frame_provider/decoder/vp9/vvp9.c
@@ -291,6 +291,9 @@ struct BUF_s {
unsigned int free_start_adr;
ulong v4l_ref_buf_addr;
+ ulong header_addr;
+ u32 header_size;
+ u32 luma_size;
} /*BUF_t */;
struct MVBUF_s {
@@ -577,6 +580,8 @@ struct PIC_BUFFER_CONFIG_s {
int max_mv;
int min_mv;
int avg_mv;
+
+ bool vframe_bound;
} PIC_BUFFER_CONFIG;
enum BITSTREAM_PROFILE {
@@ -1183,6 +1188,7 @@ struct VP9Decoder_s {
int frameinfo_enable;
struct vframe_qos_s vframe_qos;
u32 mem_map_mode;
+ u32 dynamic_buf_num_margin;
};
static int vp9_print(struct VP9Decoder_s *pbi,
@@ -1221,8 +1227,8 @@ static int is_oversize(int w, int h)
return false;
}
-static int config_pic(struct VP9Decoder_s *pbi,
- struct PIC_BUFFER_CONFIG_s *pic_config);
+static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi,
+ struct PIC_BUFFER_CONFIG_s *pic);
static void resize_context_buffers(struct VP9Decoder_s *pbi,
struct VP9_Common_s *cm, int width, int height)
@@ -1246,7 +1252,7 @@ static void resize_context_buffers(struct VP9Decoder_s *pbi,
pic = &cm->buffer_pool->frame_bufs[i].buf;
pic->y_crop_width = width;
pic->y_crop_height = height;
- if (!config_pic(pbi, pic))
+ if (!v4l_alloc_and_config_pic(pbi, pic))
set_canvas(pbi, pic);
else
vp9_print(pbi, 0,
@@ -2168,7 +2174,7 @@ static int get_free_fb(struct VP9Decoder_s *pbi)
if (pbi->is_used_v4l && !pic->cma_alloc_addr) {
pic->y_crop_width = pbi->frame_width;
pic->y_crop_height = pbi->frame_height;
- if (!config_pic(pbi, pic)) {
+ if (!v4l_alloc_and_config_pic(pbi, pic)) {
set_canvas(pbi, pic);
init_pic_list_hw(pbi);
} else
@@ -4648,12 +4654,64 @@ void adapt_coef_probs(int pic_count, int prev_kf, int cur_kf, int pre_fc,
}
+static bool v4l_is_there_vframe_bound(struct VP9Decoder_s *pbi)
+{
+ int i;
+ struct VP9_Common_s *const cm = &pbi->common;
+ struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
+
+ for (i = 0; i < pbi->used_buf_num; ++i) {
+ if (frame_bufs[i].buf.vframe_bound)
+ return true;
+ }
+
+ return false;
+}
+
+static void v4l_mmu_buffer_release(struct VP9Decoder_s *pbi)
+{
+ struct VP9_Common_s *const cm = &pbi->common;
+ struct RefCntBuffer_s *frame_bufs = cm->buffer_pool->frame_bufs;
+ int i;
+
+ /* release workspace */
+ if (pbi->bmmu_box)
+ decoder_bmmu_box_free_idx(pbi->bmmu_box,
+ WORK_SPACE_BUF_ID);
+ /*
+ * it's only when vframe get back to driver, right now we can be sure
+ * that vframe and fd are related. if the playback exits, the capture
+ * requires the upper app to release when the fd is closed, and others
+ * buffers drivers are released by driver.
+ */
+ for (i = 0; i < pbi->used_buf_num; ++i) {
+ if (!frame_bufs[i].buf.vframe_bound) {
+ if (pbi->bmmu_box)
+ decoder_bmmu_box_free_idx(pbi->bmmu_box,
+ HEADER_BUFFER_IDX(i));
+ if (pbi->mmu_box)
+ decoder_mmu_box_free_idx(pbi->mmu_box, i);
+
+ vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
+ "%s free buffer[%d], bmmu_box: %p, mmu_box: %p\n",
+ __func__, i, pbi->bmmu_box, pbi->mmu_box);
+ }
+ }
+}
static void uninit_mmu_buffers(struct VP9Decoder_s *pbi)
{
#ifndef MV_USE_FIXED_BUF
dealloc_mv_bufs(pbi);
#endif
+ if (pbi->is_used_v4l &&
+ v4l_is_there_vframe_bound(pbi)) {
+ if (get_double_write_mode(pbi) != 0x10) {
+ v4l_mmu_buffer_release(pbi);
+ return;
+ }
+ }
+
if (pbi->mmu_box)
decoder_mmu_box_free(pbi->mmu_box);
pbi->mmu_box = NULL;
@@ -4663,14 +4721,118 @@ static void uninit_mmu_buffers(struct VP9Decoder_s *pbi)
pbi->bmmu_box = NULL;
}
+static int calc_luc_quantity(u32 w, u32 h)
+{
+ int lcu_size = 64; /*fixed 64*/
+ int pic_width_64 = (w + 63) & (~0x3f);
+ int pic_height_32 = (h + 31) & (~0x1f);
+ int pic_width_lcu = (pic_width_64 % lcu_size) ?
+ pic_width_64 / lcu_size + 1 : pic_width_64 / lcu_size;
+ int pic_height_lcu = (pic_height_32 % lcu_size) ?
+ pic_height_32 / lcu_size + 1 : pic_height_32 / lcu_size;
+
+ return pic_width_lcu * pic_height_lcu;
+}
+
+static int v4l_alloc_and_config_pic(struct VP9Decoder_s *pbi,
+ struct PIC_BUFFER_CONFIG_s *pic)
+{
+ int ret = -1;
+ int i = pic->index;
+ int dw_mode = get_double_write_mode_init(pbi);
+ int lcu_total = calc_luc_quantity(pbi->frame_width, pbi->frame_height);
+#ifdef MV_USE_FIXED_BUF
+ u32 mpred_mv_end = pbi->work_space_buf->mpred_mv.buf_start +
+ pbi->work_space_buf->mpred_mv.buf_size;
+#endif
+ struct vdec_v4l2_buffer *fb = NULL;
+
+ ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb);
+ if (ret < 0) {
+ vp9_print(pbi, 0, "[%d] VP9 get buffer fail.\n",
+ ((struct aml_vcodec_ctx *) (pbi->v4l2_ctx))->id);
+ return ret;
+ }
+
+ if (pbi->mmu_enable) {
+ pbi->m_BUF[i].header_addr = decoder_bmmu_box_get_phy_addr(
+ pbi->bmmu_box, HEADER_BUFFER_IDX(i));
+ if (debug & VP9_DEBUG_BUFMGR_MORE) {
+ pr_info("MMU header_adr %d: %ld\n",
+ i, pbi->m_BUF[i].header_addr);
+ }
+ }
+
+#ifdef MV_USE_FIXED_BUF
+ if ((pbi->work_space_buf->mpred_mv.buf_start +
+ (((i + 1) * lcu_total) * MV_MEM_UNIT))
+ <= mpred_mv_end) {
+#endif
+ pbi->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
+ pic->cma_alloc_addr = fb->m.mem[0].addr;
+ if (fb->num_planes == 1) {
+ pbi->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ pbi->m_BUF[i].size = fb->m.mem[0].size;
+ pbi->m_BUF[i].luma_size = fb->m.mem[0].offset;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ } else if (fb->num_planes == 2) {
+ pbi->m_BUF[i].start_adr = fb->m.mem[0].addr;
+ pbi->m_BUF[i].size = fb->m.mem[0].size + fb->m.mem[1].size;
+ pbi->m_BUF[i].luma_size = fb->m.mem[0].size;
+ fb->m.mem[0].bytes_used = fb->m.mem[0].size;
+ fb->m.mem[1].bytes_used = fb->m.mem[1].size;
+ }
+
+ /* config frame buffer */
+ if (pbi->mmu_enable)
+ pic->header_adr = pbi->m_BUF[i].header_addr;
+
+ pic->BUF_index = i;
+ pic->lcu_total = lcu_total;
+ pic->mc_canvas_y = pic->index;
+ pic->mc_canvas_u_v = pic->index;
+
+ if (dw_mode & 0x10) {
+ pic->dw_y_adr = pbi->m_BUF[i].start_adr;
+ pic->dw_u_v_adr = pic->dw_y_adr + pbi->m_BUF[i].luma_size;
+ pic->mc_canvas_y = (pic->index << 1);
+ pic->mc_canvas_u_v = (pic->index << 1) + 1;
+ } else if (dw_mode) {
+ pic->dw_y_adr = pbi->m_BUF[i].start_adr;
+ pic->dw_u_v_adr = pic->dw_y_adr + pbi->m_BUF[i].luma_size;
+ }
+
+#ifdef MV_USE_FIXED_BUF
+ pic->mpred_mv_wr_start_addr =
+ pbi->work_space_buf->mpred_mv.buf_start +
+ ((pic->index * lcu_total) * MV_MEM_UNIT);
+#endif
+ if (debug) {
+ pr_info("%s index %d BUF_index %d ",
+ __func__, pic->index,
+ pic->BUF_index);
+ pr_info("comp_body_size %x comp_buf_size %x ",
+ pic->comp_body_size,
+ pic->buf_size);
+ pr_info("mpred_mv_wr_start_adr %ld\n",
+ pic->mpred_mv_wr_start_addr);
+ pr_info("dw_y_adr %d, pic_config->dw_u_v_adr =%d\n",
+ pic->dw_y_adr,
+ pic->dw_u_v_adr);
+ }
+#ifdef MV_USE_FIXED_BUF
+ }
+#endif
+ return ret;
+}
static int config_pic(struct VP9Decoder_s *pbi,
struct PIC_BUFFER_CONFIG_s *pic_config)
{
int ret = -1;
int i;
- int pic_width = pbi->is_used_v4l ? pbi->frame_width : pbi->init_pic_w;
- int pic_height = pbi->is_used_v4l ? pbi->frame_height : pbi->init_pic_h;
+ int pic_width = pbi->init_pic_w;
+ int pic_height = pbi->init_pic_h;
int lcu_size = 64; /*fixed 64*/
int pic_width_64 = (pic_width + 63) & (~0x3f);
int pic_height_32 = (pic_height + 31) & (~0x1f);
@@ -4698,9 +4860,6 @@ static int config_pic(struct VP9Decoder_s *pbi,
int mc_buffer_size_u_v = 0;
int mc_buffer_size_u_v_h = 0;
int dw_mode = get_double_write_mode_init(pbi);
- int pic_width_align = 0;
- int pic_height_align = 0;
- struct vdec_v4l2_buffer *fb = NULL;
pbi->lcu_total = lcu_total;
@@ -4724,11 +4883,6 @@ static int config_pic(struct VP9Decoder_s *pbi,
/*64k alignment*/
buf_size = ((mc_buffer_size_u_v_h << 16) * 3);
buf_size = ((buf_size + 0xffff) >> 16) << 16;
-
- if (pbi->is_used_v4l) {
- pic_width_align = ALIGN(pic_width_dw, 32);
- pic_height_align = ALIGN(pic_height_dw, 32);
- }
}
if (mc_buffer_size & 0xffff) /*64k alignment*/
@@ -4754,35 +4908,17 @@ static int config_pic(struct VP9Decoder_s *pbi,
) {
#endif
if (buf_size > 0) {
- if (pbi->is_used_v4l) {
- ret = vdec_v4l_get_buffer(pbi->v4l2_ctx, &fb);
- if (ret) {
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "[%d] get fb fail.\n",
- ((struct aml_vcodec_ctx *)
- (pbi->v4l2_ctx))->id);
- return ret;
- }
-
- pbi->m_BUF[i].v4l_ref_buf_addr = (ulong)fb;
- pic_config->cma_alloc_addr = fb->m.mem[0].addr;
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l ref buf addr: 0x%x\n",
- ((struct aml_vcodec_ctx *)
- (pbi->v4l2_ctx))->id, __func__, fb);
- } else {
- ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box,
- VF_BUFFER_IDX(i),
- buf_size, DRIVER_NAME,
- &pic_config->cma_alloc_addr);
- if (ret < 0) {
- pr_info(
- "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
- VF_BUFFER_IDX(i),
- buf_size
- );
- return ret;
- }
+ ret = decoder_bmmu_box_alloc_buf_phy(pbi->bmmu_box,
+ VF_BUFFER_IDX(i),
+ buf_size, DRIVER_NAME,
+ &pic_config->cma_alloc_addr);
+ if (ret < 0) {
+ pr_info(
+ "decoder_bmmu_box_alloc_buf_phy idx %d size %d fail\n",
+ VF_BUFFER_IDX(i),
+ buf_size
+ );
+ return ret;
}
if (pic_config->cma_alloc_addr)
@@ -4808,27 +4944,9 @@ static int config_pic(struct VP9Decoder_s *pbi,
pic_config->mc_canvas_y = pic_config->index;
pic_config->mc_canvas_u_v = pic_config->index;
if (dw_mode & 0x10) {
- if (pbi->is_used_v4l) {
- if (fb->num_planes == 1) {
- fb->m.mem[0].bytes_used =
- pic_width_align * pic_height_align;
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = y_adr +
- fb->m.mem[0].bytes_used;
- } else if (fb->num_planes == 2) {
- fb->m.mem[0].bytes_used =
- pic_width_align * pic_height_align;
- fb->m.mem[1].bytes_used =
- fb->m.mem[1].size;
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = y_adr +
- fb->m.mem[0].bytes_used;
- }
- } else {
- pic_config->dw_y_adr = y_adr;
- pic_config->dw_u_v_adr = y_adr +
- ((mc_buffer_size_u_v_h << 16) << 1);
- }
+ pic_config->dw_y_adr = y_adr;
+ pic_config->dw_u_v_adr = y_adr +
+ ((mc_buffer_size_u_v_h << 16) << 1);
pic_config->mc_canvas_y =
(pic_config->index << 1);
@@ -6427,8 +6545,12 @@ static int vp9_local_init(struct VP9Decoder_s *pbi)
#endif
if (pbi->save_buffer_mode)
pbi->used_buf_num = MAX_BUF_NUM_SAVE_BUF;
- else
- pbi->used_buf_num = max_buf_num;
+ else {
+ if (pbi->is_used_v4l)
+ pbi->used_buf_num = 5 + pbi->dynamic_buf_num_margin;
+ else
+ pbi->used_buf_num = max_buf_num;
+ }
if (pbi->used_buf_num > MAX_BUF_NUM)
pbi->used_buf_num = MAX_BUF_NUM;
@@ -6566,10 +6688,10 @@ static void set_canvas(struct VP9Decoder_s *pbi,
canvas_config_ex(pic_config->y_canvas_index,
pic_config->dw_y_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7);
canvas_config_ex(pic_config->uv_canvas_index,
pic_config->dw_u_v_adr, canvas_w, canvas_h,
- CANVAS_ADDR_NOWRAP, blkmode, 0x7);
+ CANVAS_ADDR_NOWRAP, blkmode, pbi->is_used_v4l ? 0 : 7);
#ifdef MULTI_INSTANCE_SUPPORT
pic_config->canvas_config[0].phy_addr =
@@ -6580,7 +6702,7 @@ static void set_canvas(struct VP9Decoder_s *pbi,
canvas_h;
pic_config->canvas_config[0].block_mode =
blkmode;
- pic_config->canvas_config[0].endian = 7;
+ pic_config->canvas_config[0].endian = pbi->is_used_v4l ? 0 : 7;
pic_config->canvas_config[1].phy_addr =
pic_config->dw_u_v_adr;
@@ -6590,7 +6712,7 @@ static void set_canvas(struct VP9Decoder_s *pbi,
canvas_h;
pic_config->canvas_config[1].block_mode =
blkmode;
- pic_config->canvas_config[1].endian = 7;
+ pic_config->canvas_config[1].endian = pbi->is_used_v4l ? 0 : 7;
#endif
}
}
@@ -6609,6 +6731,16 @@ static void set_frame_info(struct VP9Decoder_s *pbi, struct vframe_s *vf)
ar = min_t(u32, pbi->frame_ar, DISP_RATIO_ASPECT_RATIO_MAX);
vf->ratio_control = (ar << DISP_RATIO_ASPECT_RATIO_BIT);
+ if (pbi->is_used_v4l && pbi->vf_dp.present_flag) {
+ struct aml_vdec_hdr_infos hdr;
+ struct aml_vcodec_ctx *ctx =
+ (struct aml_vcodec_ctx *)(pbi->v4l2_ctx);
+
+ memset(&hdr, 0, sizeof(hdr));
+ hdr.signal_type = vf->signal_type;
+ hdr.color_parms = pbi->vf_dp;
+ vdec_v4l_set_hdr_infos(ctx, &hdr);
+ }
}
static int vvp9_vf_states(struct vframe_states *states, void *op_arg)
@@ -6695,6 +6827,9 @@ static void vvp9_vf_put(struct vframe_s *vf, void *op_arg)
if (pool->frame_bufs[index].buf.vf_ref > 0)
pool->frame_bufs[index].buf.vf_ref--;
+ if (pbi->is_used_v4l)
+ pool->frame_bufs[index].buf.vframe_bound = true;
+
if (pbi->wait_buf)
WRITE_VREG(HEVC_ASSIST_MBOX0_IRQ_REG,
0x1);
@@ -6864,16 +6999,11 @@ static int prepare_display_buf(struct VP9Decoder_s *pbi,
vf->v4l_mem_handle
= pbi->m_BUF[pic_config->BUF_index].v4l_ref_buf_addr;
if (pbi->mmu_enable) {
- if (vdec_v4l_binding_fd_and_vf(vf->v4l_mem_handle, vf) < 0) {
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "v4l: binding vf fail.\n");
- return -1;
- }
+ vf->mm_box.bmmu_box = pbi->bmmu_box;
+ vf->mm_box.bmmu_idx = HEADER_BUFFER_IDX(pic_config->BUF_index);
+ vf->mm_box.mmu_box = pbi->mmu_box;
+ vf->mm_box.mmu_idx = pic_config->index;
}
- vp9_print(pbi, PRINT_FLAG_V4L_DETAIL,
- "[%d] %s(), v4l mem handle: 0x%lx\n",
- ((struct aml_vcodec_ctx *)(pbi->v4l2_ctx))->id,
- __func__, vf->v4l_mem_handle);
}
#ifdef MULTI_INSTANCE_SUPPORT
@@ -7127,7 +7257,8 @@ static int notify_v4l_eos(struct vdec_s *vdec)
struct VP9Decoder_s *hw = (struct VP9Decoder_s *)vdec->private;
struct aml_vcodec_ctx *ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
struct vframe_s *vf = NULL;
- struct vdec_v4l2_buffer *fb = NULL;
+ int index = INVALID_IDX;
+ ulong expires;
if (hw->is_used_v4l && hw->eos) {
if (kfifo_get(&hw->newframe_q, &vf) == 0 || vf == NULL) {
@@ -7137,15 +7268,21 @@ static int notify_v4l_eos(struct vdec_s *vdec)
return -1;
}
- if (vdec_v4l_get_buffer(hw->v4l2_ctx, &fb)) {
- pr_err("[%d] get fb fail.\n", ctx->id);
+ expires = jiffies + msecs_to_jiffies(2000);
+ while (INVALID_IDX == (index = get_free_fb(hw))) {
+ if (time_after(jiffies, expires))
+ break;
+ }
+
+ if (index == INVALID_IDX) {
+ pr_err("[%d] EOS get free buff fail.\n", ctx->id);
return -1;
}
- vf->type |= VIDTYPE_V4L_EOS;
- vf->timestamp = ULONG_MAX;
- vf->v4l_mem_handle = (unsigned long)fb;
- vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
+ vf->type |= VIDTYPE_V4L_EOS;
+ vf->timestamp = ULONG_MAX;
+ vf->v4l_mem_handle = hw->m_BUF[index].v4l_ref_buf_addr;
+ vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
vf_notify_receiver(vdec->vf_provider_name,
@@ -9648,8 +9785,10 @@ static unsigned long run_ready(struct vdec_s *vdec, unsigned long mask)
if (ctx->param_sets_from_ucode &&
!ctx->v4l_codec_ready &&
- pbi->v4l_params_parsed)
+ pbi->v4l_params_parsed) {
ret = 0; /*the params has parsed.*/
+ } else if (!ctx->v4l_codec_dpb_ready)
+ ret = 0;
}
if (ret)
@@ -9695,6 +9834,7 @@ static void run_front(struct vdec_s *vdec)
vdec_schedule_work(&pbi->work);
return;
}
+
input_empty[pbi->index] = 0;
pbi->dec_result = DEC_RESULT_NONE;
pbi->start_shift_bytes = READ_VREG(HEVC_SHIFT_BYTE_COUNT);
@@ -9965,6 +10105,8 @@ static void init_frame_bufs(struct VP9Decoder_s *pbi)
frame_bufs[i].ref_count = 0;
frame_bufs[i].buf.vf_ref = 0;
frame_bufs[i].buf.decode_idx = 0;
+ frame_bufs[i].buf.cma_alloc_addr = 0;
+ frame_bufs[i].buf.index = i;
}
if (vdec->parallel_dec == 1) {
@@ -10286,6 +10428,16 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->max_pic_h = vp9_buf_height;
vp9_print(pbi, 0, "use buf resolution\n");
}
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_codec_enable",
+ &config_val) == 0)
+ pbi->is_used_v4l = config_val;
+
+ if (get_config_int(pdata->config,
+ "parm_v4l_buffer_margin",
+ &config_val) == 0)
+ pbi->dynamic_buf_num_margin = config_val;
#endif
if (get_config_int(pdata->config, "HDRStaticInfo",
&vf_dp.present_flag) == 0
@@ -10349,18 +10501,6 @@ static int ammvdec_vp9_probe(struct platform_device *pdev)
pbi->vvp9_amstream_dec_info.rate = 30;
}
pbi->low_latency_flag = 1;
- pbi->is_used_v4l = (((unsigned long)
- pbi->vvp9_amstream_dec_info.param & 0x80) >> 7);
- if (pbi->is_used_v4l) {
- pbi->mmu_enable = (((unsigned long)
- pbi->vvp9_amstream_dec_info.param & 0x100) >> 8);
- if (!pbi->mmu_enable)
- pbi->double_write_mode = 0x10;
-
- pbi->mmu_enable = 1;
- pbi->max_pic_w = 4096;
- pbi->max_pic_h = 2304;
- }
vp9_print(pbi, 0,
"no_head %d low_latency %d\n",