amvdec_ports: optimize some codes of the v4l vcodec.

PD#170885

1. support the h264 decoding with multi-instance.
2. the reference count of clk mux has't clean was fixed.
3. replace capture worker to thread process.
4. optimize the machine status of the vcodec.
5. remover some locks unnecessary to promote efficiency.
6. the picture infos used to vda that was fixed.

Change-Id: I061ebdc088c8c7e14eab73032308715da5f4aafb
Signed-off-by: Nanxin Qin <nanxin.qin@amlogic.com>
This commit is contained in:
Nanxin Qin
2018-07-28 01:04:53 +08:00
committed by Dongjin Kim
parent 8a1571bf31
commit 683ef21d17
16 changed files with 792 additions and 604 deletions

View File

@@ -89,31 +89,17 @@ static struct stream_buf_s bufs[BUF_MAX_NUM] = {
},
};
struct vdec_adapt_config {
struct vdec_s *vdec;
struct stream_port_s port;
struct dec_sysinfo dec_prop;
};
struct vdec_adapt_config g_cfg;
static void set_cfg_info(struct aml_vdec_adapt *vdec)
{
unsigned long sync_mode = (PTS_OUTSIDE | SYNC_OUTSIDE | USE_V4L_PORTS);
g_cfg.port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_ES);
g_cfg.port.flag |= PORT_FLAG_VFORMAT;
g_cfg.dec_prop.format = VFORMAT_H264;
g_cfg.dec_prop.width = 1920;
g_cfg.dec_prop.height = 1080;
g_cfg.dec_prop.rate = 3200;
g_cfg.dec_prop.param = (void *)sync_mode;
}
static void set_system_info(struct vdec_s *vdec)
{
vdec->sys_info = &g_cfg.dec_prop;
vdec->sys_info_store = g_cfg.dec_prop;
vdec->port.type |= (PORT_TYPE_VIDEO | PORT_TYPE_FRAME/* | PORT_TYPE_ES*/);
vdec->port.flag |= PORT_FLAG_VFORMAT;
vdec->dec_prop.format = vdec->format;
vdec->dec_prop.width = 1920;
vdec->dec_prop.height = 1080;
vdec->dec_prop.rate = 3200;
vdec->dec_prop.param = (void *)sync_mode;
}
static void set_vdec_mode(struct vdec_s *vdec)
@@ -127,10 +113,8 @@ static void set_vdec_vfm(struct vdec_s *vdec)
vdec->frame_base_video_path = FRAME_BASE_PATH_V4L_VIDEO;
}
static int enable_hardware(void)
static int enable_hardware(struct stream_port_s *port)
{
struct stream_port_s *port = &g_cfg.port;
if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6)
return -1;
@@ -142,30 +126,22 @@ static int enable_hardware(void)
amports_switch_gate("vdec", 1);
if (has_hevc_vdec()) {
if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC)) {
amports_switch_gate("clk_hevc_mux", 1);
if (port->type & (PORT_TYPE_MPTS | PORT_TYPE_HEVC))
vdec_poweron(VDEC_HEVC);
}
if ((port->type & PORT_TYPE_HEVC) == 0) {
amports_switch_gate("clk_vdec_mux", 1);
if ((port->type & PORT_TYPE_HEVC) == 0)
vdec_poweron(VDEC_1);
}
} else {
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8) {
amports_switch_gate("clk_vdec_mux", 1);
if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M8)
vdec_poweron(VDEC_1);
}
}
}
return 0;
}
static int disable_hardware(void)
static int disable_hardware(struct stream_port_s *port)
{
struct stream_port_s *port = &g_cfg.port;
if (get_cpu_type() < MESON_CPU_MAJOR_ID_M6)
return -1;
@@ -316,9 +292,9 @@ static int audio_component_init(struct stream_port_s *port,
static void video_component_release(struct stream_port_s *port,
struct stream_buf_s *pbuf, int release_num)
{
struct vdec_adapt_config *cfg
= container_of(port, struct vdec_adapt_config, port);
struct vdec_s *vdec = cfg->vdec;
struct aml_vdec_adapt *ada_ctx
= container_of(port, struct aml_vdec_adapt, port);
struct vdec_s *vdec = ada_ctx->vdec;
struct vdec_s *slave = NULL;
bool is_multidec = !vdec_single(vdec);
@@ -355,9 +331,9 @@ static int video_component_init(struct stream_port_s *port,
struct stream_buf_s *pbuf)
{
int ret = -1;
struct vdec_adapt_config *cfg
= container_of(port, struct vdec_adapt_config, port);
struct vdec_s *vdec = cfg->vdec;
struct aml_vdec_adapt *ada_ctx
= container_of(port, struct aml_vdec_adapt, port);
struct vdec_s *vdec = ada_ctx->vdec;
if ((vdec->port_flag & PORT_FLAG_VFORMAT) == 0) {
pr_err("vformat not set\n");
@@ -437,9 +413,9 @@ static int video_component_init(struct stream_port_s *port,
static int vdec_ports_release(struct stream_port_s *port)
{
struct vdec_adapt_config *cfg
= container_of(port, struct vdec_adapt_config, port);
struct vdec_s *vdec = cfg->vdec;
struct aml_vdec_adapt *ada_ctx
= container_of(port, struct aml_vdec_adapt, port);
struct vdec_s *vdec = ada_ctx->vdec;
struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
@@ -492,7 +468,7 @@ static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt)
struct stream_buf_s *pvbuf = &bufs[BUF_TYPE_VIDEO];
struct stream_buf_s *pabuf = &bufs[BUF_TYPE_AUDIO];
//struct stream_buf_s *psbuf = &bufs[BUF_TYPE_SUBTITLE];
struct stream_port_s *port = &g_cfg.port;
struct stream_port_s *port = &vdec_adapt->port;
struct vdec_s *vdec = NULL;
/* create the vdec instance.*/
@@ -503,11 +479,13 @@ static int vdec_ports_init(struct aml_vdec_adapt *vdec_adapt)
/* set v4l2 ctx */
vdec->private = vdec_adapt->ctx;
g_cfg.vdec = vdec;
vdec_adapt->vdec = vdec;
vdec->sys_info = &vdec_adapt->dec_prop;
vdec->sys_info_store = vdec_adapt->dec_prop;
vdec->vf_receiver_name = vdec_adapt->recv_name;
/* set video format and sys info */
vdec_set_format(vdec, g_cfg.dec_prop.format); //set by ioctl ???
set_system_info(vdec);
vdec_set_format(vdec, vdec_adapt->dec_prop.format);
set_vdec_mode(vdec);
set_vdec_vfm(vdec);
@@ -563,7 +541,7 @@ int video_decoder_init(struct aml_vdec_adapt *vdec)
set_cfg_info(vdec);
/* init hw and gate*/
ret = enable_hardware();
ret = enable_hardware(&vdec->port);
if (ret < 0) {
pr_info("enable hw fail.\n");
goto out;
@@ -582,7 +560,7 @@ out:
int video_decoder_release(struct aml_vdec_adapt *vdec)
{
int ret = -1;
struct stream_port_s *port = &g_cfg.port;
struct stream_port_s *port = &vdec->port;
ret = vdec_ports_release(port);
if (ret < 0) {
@@ -591,7 +569,7 @@ int video_decoder_release(struct aml_vdec_adapt *vdec)
}
/* disable gates */
ret = disable_hardware();
ret = disable_hardware(port);
if (ret < 0) {
pr_info("disable hw fail.\n");
goto out;
@@ -600,12 +578,13 @@ out:
return ret;
}
int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count)
int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx,
const char *buf, unsigned int count)
{
int ret = -1;
int try_cnt = 100;
struct stream_port_s *port = &g_cfg.port;
struct vdec_s *vdec = g_cfg.vdec;
struct stream_port_s *port = &ada_ctx->port;
struct vdec_s *vdec = ada_ctx->vdec;
struct stream_buf_s *pbuf = NULL;
if (has_hevc_vdec()) {
@@ -622,9 +601,9 @@ int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count)
do {
if (vdec->port_flag & PORT_FLAG_DRM)
ret = drm_write(file, pbuf, buf, count);
ret = drm_write(ada_ctx->filp, pbuf, buf, count);
else
ret = esparser_write(file, pbuf, buf, count);
ret = esparser_write(ada_ctx->filp, pbuf, buf, count);
} while (ret == -EAGAIN && try_cnt--);
if (slow_input) {
@@ -641,9 +620,9 @@ int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count)
return ret;
}
int is_need_to_buf(void)
int is_need_to_buf(struct aml_vdec_adapt *ada_ctx)
{
struct vdec_s *vdec = g_cfg.vdec;
struct vdec_s *vdec = ada_ctx->vdec;
if (vdec->input.have_frame_num > 8)
return 0;
@@ -651,12 +630,12 @@ int is_need_to_buf(void)
return 1;
}
int vdec_vframe_write(struct file *file, const char *buf,
unsigned int count, unsigned long int timestamp)
int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
const char *buf, unsigned int count, unsigned long int timestamp)
{
int ret = -1;
int try_cnt = 10;
struct vdec_s *vdec = g_cfg.vdec;
struct vdec_s *vdec = ada_ctx->vdec;
/* set timestamp */
vdec_set_timestamp(vdec, timestamp);
@@ -678,33 +657,36 @@ int vdec_vframe_write(struct file *file, const char *buf,
/* dump to file */
dump_write(buf, count);
#endif
aml_v4l2_debug(1, "vdec_vframe_write, vbuf: %p, size: %u, ret: %d, crc: %x\n",
buf, count, ret, crc32(0, buf, count));
aml_v4l2_debug(2, "[%d] write frames, vbuf: %p, size: %u, ret: %d, crc: %x",
ada_ctx->ctx->id, buf, count, ret, crc32(0, buf, count));
return ret;
}
void aml_decoder_flush(void)
void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx)
{
struct vdec_s *vdec = g_cfg.vdec;
struct vdec_s *vdec = ada_ctx->vdec;
if (vdec)
vdec_set_eos(vdec, true);
}
void aml_codec_reset(void)
int aml_codec_reset(struct aml_vdec_adapt *ada_ctx)
{
struct vdec_s *vdec = g_cfg.vdec;
struct vdec_s *vdec = ada_ctx->vdec;
int ret = 0;
if (vdec) {
vdec_set_eos(vdec, false);
vdec_reset(vdec);
ret = vdec_reset(vdec);
}
return ret;
}
bool is_decoder_ready(void)
bool is_input_ready(struct aml_vdec_adapt *ada_ctx)
{
struct vdec_s *vdec = g_cfg.vdec;
struct vdec_s *vdec = ada_ctx->vdec;
int state = VDEC_STATUS_UNINITIALIZED;
if (vdec) {

View File

@@ -2,10 +2,12 @@
#define VDEC_ADAPT_H
#include <linux/amlogic/media/utils/vformat.h>
#include <linux/amlogic/media/utils/amstream.h>
#include "../stream_input/parser/streambuf.h"
#include "aml_vcodec_drv.h"
struct aml_vdec_adapt {
enum vformat_e id;
enum vformat_e format;
void *vsi;
int32_t failure;
uint32_t inst_addr;
@@ -14,27 +16,31 @@ struct aml_vdec_adapt {
struct platform_device *dev;
wait_queue_head_t wq;
struct file *filp;
//ipi_handler_t handler;
struct vdec_s *vdec;
struct stream_port_s port;
struct dec_sysinfo dec_prop;
char *recv_name;
};
int video_decoder_init(struct aml_vdec_adapt *vdec);
int video_decoder_init(struct aml_vdec_adapt *ada_ctx);
int video_decoder_release(struct aml_vdec_adapt *vdec);
int video_decoder_release(struct aml_vdec_adapt *ada_ctx);
int vdec_vbuf_write(struct file *file, const char *buf, unsigned int count);
int vdec_vbuf_write(struct aml_vdec_adapt *ada_ctx,
const char *buf, unsigned int count);
int vdec_vframe_write(struct file *file, const char *buf,
unsigned int count, unsigned long int pts);
int vdec_vframe_write(struct aml_vdec_adapt *ada_ctx,
const char *buf, unsigned int count, unsigned long int timestamp);
int is_need_to_buf(void);
int is_need_to_buf(struct aml_vdec_adapt *ada_ctx);
void aml_decoder_flush(void);
void aml_decoder_flush(struct aml_vdec_adapt *ada_ctx);
void aml_codec_reset(void);
int aml_codec_reset(struct aml_vdec_adapt *ada_ctx);
extern void dump_write(const char __user *buf, size_t count);
bool is_decoder_ready(void);
bool is_input_ready(struct aml_vdec_adapt *ada_ctx);
#endif /* VDEC_ADAPT_H */

File diff suppressed because it is too large Load Diff

View File

@@ -49,8 +49,11 @@ struct aml_video_dec_buf {
struct vdec_fb frame_buffer;
struct codec_mm_s *mem[2];
char mem_onwer[32];
struct list_head node;
bool used;
bool ready_to_display;
bool que_in_m2m;
bool queued_in_vb2;
bool queued_in_v4l2;
bool lastframe;
@@ -77,4 +80,11 @@ 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);
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);
#endif /* _AML_VCODEC_DEC_H_ */

View File

@@ -9,6 +9,7 @@
#include <media/v4l2-event.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-contig.h>
#include <linux/kthread.h>
#include "aml_vcodec_drv.h"
#include "aml_vcodec_dec.h"
@@ -49,24 +50,26 @@ 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;
init_waitqueue_head(&ctx->queue);
mutex_init(&ctx->state_lock);
mutex_init(&ctx->lock);
sema_init(&ctx->sem, 1);
init_waitqueue_head(&ctx->wq);
ctx->type = AML_INST_DECODER;
ret = aml_vcodec_dec_ctrls_setup(ctx);
if (ret) {
aml_v4l2_err("Failed to setup mt vcodec controls\n");
aml_v4l2_err("Failed to setup vcodec controls");
goto err_ctrls_setup;
}
ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev_dec, ctx,
&aml_vcodec_dec_queue_init);
if (IS_ERR((__force void *)ctx->m2m_ctx)) {
ret = PTR_ERR((__force void *)ctx->m2m_ctx);
aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)\n", ret);
aml_v4l2_err("Failed to v4l2_m2m_ctx_init() (%d)", ret);
goto err_m2m_ctx_init;
}
src_vq = v4l2_m2m_get_vq(ctx->m2m_ctx,
@@ -75,6 +78,12 @@ static int fops_vcodec_open(struct file *file)
ctx->empty_flush_buf->lastframe = true;
aml_vcodec_dec_set_default_params(ctx);
ret = aml_thread_start(ctx, try_to_capture, AML_THREAD_CAPTURE, "cap");
if (ret) {
aml_v4l2_err("Failed to creat capture thread.");
goto err_creat_thread;
}
list_add(&ctx->list, &dev->ctx_list);
mutex_unlock(&dev->dev_mutex);
@@ -83,8 +92,8 @@ static int fops_vcodec_open(struct file *file)
return ret;
/* Deinit when failure occurred */
//err_load_fw:
/*v4l2_m2m_ctx_release(ctx->m2m_ctx);*/
err_creat_thread:
v4l2_m2m_ctx_release(ctx->m2m_ctx);
err_m2m_ctx_init:
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
err_ctrls_setup:
@@ -111,13 +120,15 @@ static int fops_vcodec_release(struct file *file)
* Second, the decoder will be flushed and all the buffers will be
* returned in stop_streaming.
*/
v4l2_m2m_ctx_release(ctx->m2m_ctx);
aml_vcodec_dec_release(ctx);
v4l2_m2m_ctx_release(ctx->m2m_ctx);
v4l2_fh_del(&ctx->fh);
v4l2_fh_exit(&ctx->fh);
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
aml_thread_stop(ctx);
list_del_init(&ctx->list);
kfree(ctx->empty_flush_buf);
kfree(ctx);
@@ -156,7 +167,7 @@ static int aml_vcodec_probe(struct platform_device *pdev)
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret) {
aml_v4l2_err("v4l2_device_register err=%d\n", ret);
aml_v4l2_err("v4l2_device_register err=%d", ret);
goto err_res;
}
@@ -164,7 +175,7 @@ static int aml_vcodec_probe(struct platform_device *pdev)
vfd_dec = video_device_alloc();
if (!vfd_dec) {
aml_v4l2_err("Failed to allocate video device\n");
aml_v4l2_err("Failed to allocate video device");
ret = -ENOMEM;
goto err_dec_alloc;
}
@@ -186,7 +197,7 @@ static int aml_vcodec_probe(struct platform_device *pdev)
dev->m2m_dev_dec = v4l2_m2m_init(&aml_vdec_m2m_ops);
if (IS_ERR((__force void *)dev->m2m_dev_dec)) {
aml_v4l2_err("Failed to init mem2mem dec device\n");
aml_v4l2_err("Failed to init mem2mem dec device");
ret = PTR_ERR((__force void *)dev->m2m_dev_dec);
goto err_dec_mem_init;
}
@@ -195,28 +206,17 @@ static int aml_vcodec_probe(struct platform_device *pdev)
alloc_ordered_workqueue(AML_VCODEC_DEC_NAME,
WQ_MEM_RECLAIM | WQ_FREEZABLE);
if (!dev->decode_workqueue) {
aml_v4l2_err("Failed to create decode workqueue\n");
aml_v4l2_err("Failed to create decode workqueue");
ret = -EINVAL;
goto err_event_workq;
}
dev->decode_workqueue_vf =
alloc_ordered_workqueue("aml-vcodec-dec-vf",
WQ_MEM_RECLAIM | WQ_FREEZABLE);
if (!dev->decode_workqueue_vf) {
aml_v4l2_err("Failed to create decode workqueue\n");
ret = -EINVAL;
destroy_workqueue(dev->decode_workqueue);
goto err_event_workq;
}
dev->reset_workqueue =
alloc_ordered_workqueue("aml-vcodec-reset",
WQ_MEM_RECLAIM | WQ_FREEZABLE);
if (!dev->decode_workqueue_vf) {
aml_v4l2_err("Failed to create decode workqueue\n");
if (!dev->reset_workqueue) {
aml_v4l2_err("Failed to create decode workqueue");
ret = -EINVAL;
destroy_workqueue(dev->decode_workqueue_vf);
destroy_workqueue(dev->decode_workqueue);
goto err_event_workq;
}
@@ -235,7 +235,6 @@ static int aml_vcodec_probe(struct platform_device *pdev)
err_dec_reg:
destroy_workqueue(dev->reset_workqueue);
destroy_workqueue(dev->decode_workqueue_vf);
destroy_workqueue(dev->decode_workqueue);
err_event_workq:
v4l2_m2m_release(dev->m2m_dev_dec);
@@ -259,8 +258,8 @@ static int aml_vcodec_dec_remove(struct platform_device *pdev)
{
struct aml_vcodec_dev *dev = platform_get_drvdata(pdev);
flush_workqueue(dev->decode_workqueue_vf);
destroy_workqueue(dev->decode_workqueue_vf);
flush_workqueue(dev->reset_workqueue);
destroy_workqueue(dev->reset_workqueue);
flush_workqueue(dev->decode_workqueue);
destroy_workqueue(dev->decode_workqueue);

View File

@@ -12,7 +12,7 @@
#define AML_VCODEC_DRV_NAME "aml_vcodec_drv"
#define AML_VCODEC_DEC_NAME "aml-vcodec-dec"
#define AML_VCODEC_ENC_NAME "aml-vcodec-enc"
#define AML_PLATFORM_STR "platform:mt8173"
#define AML_PLATFORM_STR "platform:amlogic"
#define AML_VCODEC_MAX_PLANES 3
#define AML_V4L2_BENCHMARK 0
@@ -52,20 +52,25 @@ enum aml_instance_type {
/**
* enum aml_instance_state - The state of an AML Vcodec instance.
* @AML_STATE_FREE - default state when instance is created
* @AML_STATE_INIT - vcodec instance is initialized
* @AML_STATE_HEADER - vdec had sps/pps header parsed or venc
* had sps/pps header encoded
* @AML_STATE_FLUSH - vdec is flushing. Only used by decoder
* @AML_STATE_ABORT - vcodec should be aborted
* @AML_STATE_IDLE - default state when instance is created
* @AML_STATE_INIT - vcodec instance is initialized
* @AML_STATE_PROBE - vdec/venc had sps/pps header parsed/encoded
* @AML_STATE_ACTIVE - vdec is ready for work.
* @AML_STATE_FLUSHING - vdec is flushing. Only used by decoder
* @AML_STATE_FLUSHED - decoder has transacted the last frame.
* @AML_STATE_RESET - decoder has be reset after flush.
* @AML_STATE_ABORT - vcodec should be aborted
*/
enum aml_instance_state {
AML_STATE_FREE = 0,
AML_STATE_INIT = 1,
AML_STATE_HEADER = 2,
AML_STATE_FLUSH = 3,
AML_STATE_ABORT = 4,
AML_STATE_RESET = 5,
AML_STATE_IDLE,
AML_STATE_INIT,
AML_STATE_PROBE,
AML_STATE_READY,
AML_STATE_ACTIVE,
AML_STATE_FLUSHING,
AML_STATE_FLUSHED,
AML_STATE_RESET,
AML_STATE_ABORT,
};
/**
@@ -186,10 +191,10 @@ struct aml_vcodec_pm {
/**
* struct vdec_pic_info - picture size information
* @pic_w: picture width
* @pic_h: picture height
* @buf_w: picture buffer width (64 aligned up from pic_w)
* @buf_h: picture buffer heiht (64 aligned up from pic_h)
* @visible_width: picture width
* @visible_height: picture height
* @coded_width: picture buffer width (64 aligned up from pic_w)
* @coded_height: picture buffer heiht (64 aligned up from pic_h)
* @y_bs_sz: Y bitstream size
* @c_bs_sz: CbCr bitstream size
* @y_len_sz: additional size required to store decompress information for y
@@ -200,16 +205,35 @@ struct aml_vcodec_pm {
* buffer size will be aligned to 176x160.
*/
struct vdec_pic_info {
unsigned int pic_w;
unsigned int pic_h;
unsigned int buf_w;
unsigned int buf_h;
unsigned int visible_width;
unsigned int visible_height;
unsigned int coded_width;
unsigned int coded_height;
unsigned int y_bs_sz;
unsigned int c_bs_sz;
unsigned int y_len_sz;
unsigned int c_len_sz;
};
enum aml_thread_type {
AML_THREAD_OUTPUT,
AML_THREAD_CAPTURE,
};
typedef void (*aml_thread_func)(struct aml_vcodec_ctx *ctx);
struct aml_vdec_thread {
struct list_head node;
spinlock_t lock;
struct semaphore sem;
struct task_struct *task;
enum aml_thread_type type;
void *priv;
int stop;
aml_thread_func func;
};
/**
* struct aml_vcodec_ctx - Context (instance) private data.
*
@@ -256,8 +280,10 @@ struct aml_vcodec_ctx {
struct v4l2_fh fh;
struct v4l2_m2m_ctx *m2m_ctx;
struct aml_vdec_adapt *ada_ctx;
struct aml_q_data q_data[2];
int id;
struct mutex state_lock;
enum aml_instance_state state;
enum aml_encode_param param_change;
struct aml_enc_params enc_params;
@@ -276,7 +302,6 @@ struct aml_vcodec_ctx {
struct v4l2_ctrl_handler ctrl_hdl;
struct work_struct decode_work;
struct work_struct decode_work_vf;
struct work_struct encode_work;
struct work_struct reset_work;
struct vdec_pic_info last_decoded_picinfo;
@@ -289,10 +314,10 @@ struct aml_vcodec_ctx {
int decoded_frame_cnt;
struct mutex lock;
struct semaphore sem;
wait_queue_head_t wq;
bool has_receive_eos;
struct list_head capture_list;
struct list_head vdec_thread_list;
};
/**
@@ -352,7 +377,6 @@ struct aml_vcodec_dev {
unsigned long id_counter;
struct workqueue_struct *decode_workqueue;
struct workqueue_struct *decode_workqueue_vf;
struct workqueue_struct *encode_workqueue;
struct workqueue_struct *reset_workqueue;
int int_cond;

View File

@@ -45,10 +45,10 @@ int aml_vcodec_mem_alloc(struct aml_vcodec_ctx *data,
memset(mem->va, 0, size);
aml_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va);
aml_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id,
aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va);
aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id,
(unsigned long)mem->dma_addr);
aml_v4l2_debug(3, "[%d] size = 0x%lx", ctx->id, size);
aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size);
return 0;
}
@@ -67,10 +67,10 @@ void aml_vcodec_mem_free(struct aml_vcodec_ctx *data,
return;
}
aml_v4l2_debug(3, "[%d] - va = %p", ctx->id, mem->va);
aml_v4l2_debug(3, "[%d] - dma = 0x%lx", ctx->id,
aml_v4l2_debug(4, "[%d] - va = %p", ctx->id, mem->va);
aml_v4l2_debug(4, "[%d] - dma = 0x%lx", ctx->id,
(unsigned long)mem->dma_addr);
aml_v4l2_debug(3, "[%d] size = 0x%lx", ctx->id, size);
aml_v4l2_debug(4, "[%d] size = 0x%lx", ctx->id, size);
dma_free_coherent(dev, size, mem->va, mem->dma_addr);
mem->va = NULL;

View File

@@ -23,11 +23,10 @@ extern bool aml_vcodec_dbg;
#if defined(DEBUG)
#define aml_v4l2_debug(level, fmt, args...) \
do { \
if (aml_v4l2_dbg_level >= level) \
pr_info("[AML_V4L2] level=%d %s(),%d: " fmt "\n",\
level, __func__, __LINE__, ##args); \
#define aml_v4l2_debug(level, fmt, args...) \
do { \
if (aml_v4l2_dbg_level >= level) \
pr_info(fmt "\n", ##args); \
} while (0)
#define aml_v4l2_debug_enter() aml_v4l2_debug(3, "+")
@@ -36,8 +35,8 @@ extern bool aml_vcodec_dbg;
#define aml_vcodec_debug(h, fmt, args...) \
do { \
if (aml_vcodec_dbg) \
pr_info("[AML_VCODEC][%d]: %s() " fmt "\n", \
((struct aml_vcodec_ctx *)h->ctx)->id, \
pr_info("[%d]: %s() " fmt "\n", \
((struct aml_vcodec_ctx *)h->ctx)->id, \
__func__, ##args); \
} while (0)
@@ -56,13 +55,12 @@ extern bool aml_vcodec_dbg;
#endif
#define aml_v4l2_err(fmt, args...) \
pr_err("[AML_V4L2][ERROR] %s:%d: " fmt "\n", __func__, __LINE__, \
##args)
#define aml_v4l2_err(fmt, args...) \
pr_err("[ERR]" fmt "\n", ##args)
#define aml_vcodec_err(h, fmt, args...) \
pr_err("[AML_VCODEC][ERROR][%d]: %s() " fmt "\n", \
((struct aml_vcodec_ctx *)h->ctx)->id, __func__, ##args)
pr_err("[ERR][%d]" fmt "\n", \
((struct aml_vcodec_ctx *)h->ctx)->id, ##args)
void __iomem *aml_vcodec_get_reg_addr(struct aml_vcodec_ctx *data,
unsigned int reg_idx);

View File

@@ -1,6 +1,7 @@
#include "aml_vcodec_vfm.h"
#include "aml_vcodec_vfq.h"
#include "aml_vcodec_util.h"
#include "aml_vcodec_adapt.h"
#include <media/v4l2-mem2mem.h>
#define RECEIVER_NAME "v4l2-video"
@@ -50,16 +51,16 @@ static int vdec_vf_states(struct vframe_states *states, void *op_arg)
return 0;
}
void video_vf_put(struct vdec_fb *fb)
void video_vf_put(char *receiver, struct vdec_fb *fb, int id)
{
struct vframe_provider_s *vfp = vf_get_provider(RECEIVER_NAME);
struct vframe_provider_s *vfp = vf_get_provider(receiver);
struct vframe_s *vf = (struct vframe_s *)fb->vf_handle;
aml_v4l2_debug(4, "%s() [%d], vfp: %p, vf: %p, cnt: %d\n",
__FUNCTION__, __LINE__, vfp, vf, atomic_read(&vf->use_cnt));
aml_v4l2_debug(2, "[%d] TO (%s) vf: %p, idx: %d",
id, vfp->name, vf, vf->index);
if (vfp && vf && atomic_dec_and_test(&vf->use_cnt))
vf_put(vf, RECEIVER_NAME);
vf_put(vf, receiver);
}
static const struct vframe_operations_s vf_provider = {
@@ -76,26 +77,23 @@ static int video_receiver_event_fun(int type, void *data, void *private_data)
struct vframe_states states;
struct vcodec_vfm_s *vfm = (struct vcodec_vfm_s *)private_data;
aml_v4l2_debug(4, "%s() [%d], type: %d, vfm: %p\n",
__FUNCTION__, __LINE__, type, vfm);
//aml_v4l2_debug(4, "[%d] type: %d, vfm: %p", vfm->ctx->id, type, vfm);
switch (type) {
case VFRAME_EVENT_PROVIDER_UNREG: {
if (vf_get_receiver(vfm->prov_name)) {
aml_v4l2_debug(4, "%s() [%d] unreg %s provider.\n",
__FUNCTION__, __LINE__, vfm->prov_name);
aml_v4l2_debug(4, "[%d] unreg %s provider.",
vfm->ctx->id, vfm->prov_name);
vf_unreg_provider(&vfm->vf_prov);
}
vfq_init(&vfm->vf_que, POOL_SIZE + 1, &vfm->pool[0]);
break;
}
case VFRAME_EVENT_PROVIDER_START: {
if (vf_get_receiver(vfm->prov_name)) {
aml_v4l2_debug(4, "%s() [%d] reg %s provider.\n",
__FUNCTION__, __LINE__, vfm->prov_name);
aml_v4l2_debug(4, "[%d] reg %s provider.",
vfm->ctx->id, vfm->prov_name);
vf_provider_init(&vfm->vf_prov, vfm->prov_name,
&vf_provider, vfm);
vf_reg_provider(&vfm->vf_prov);
@@ -126,6 +124,11 @@ static int video_receiver_event_fun(int type, void *data, void *private_data)
if (!vfm->vf)
ret = -1;
if (ret < 0) {
pr_err("[%d] receiver vf err.\n", vfm->ctx->id);
break;
}
vfq_push(&vfm->vf_que, vfm->vf);
/*vf_notify_receiver(vfm->prov_name,
@@ -133,14 +136,15 @@ static int video_receiver_event_fun(int type, void *data, void *private_data)
/* schedule capture work. */
vdec_device_vf_run(vfm->ctx);
aml_v4l2_debug(1, "%s() [%d] VFRAME_EVENT_PROVIDER_VFRAME_READY.\n",
__FUNCTION__, __LINE__);
aml_v4l2_debug(2, "[%d] FROM (%s) vf: %p, idx: %d",
vfm->ctx->id, vf_get_provider(vfm->recv_name)->name,
vfm->vf, vfm->vf->index);
break;
}
default:
aml_v4l2_debug(4, "the vf event is %d .", type);
aml_v4l2_debug(4, "[%d] the vf event is %d", vfm->ctx->id, type);
}
return ret;
@@ -162,8 +166,12 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm)
int vcodec_vfm_init(struct vcodec_vfm_s *vfm)
{
memcpy(vfm->recv_name, RECEIVER_NAME, sizeof(RECEIVER_NAME));
memcpy(vfm->prov_name, PROVIDER_NAME, sizeof(PROVIDER_NAME));
snprintf(vfm->recv_name, VF_NAME_SIZE, "%s-%d",
RECEIVER_NAME, vfm->ctx->id);
snprintf(vfm->prov_name, VF_NAME_SIZE, "%s-%d",
PROVIDER_NAME, vfm->ctx->id);
vfm->ada_ctx->recv_name = vfm->recv_name;
vf_receiver_init(&vfm->vf_recv, vfm->recv_name, &vf_receiver, vfm);
vf_reg_receiver(&vfm->vf_recv);
@@ -174,6 +182,5 @@ int vcodec_vfm_init(struct vcodec_vfm_s *vfm)
void vcodec_vfm_release(struct vcodec_vfm_s *vfm)
{
vf_unreg_receiver(&vfm->vf_recv);
vf_unreg_provider(&vfm->vf_prov);
}

View File

@@ -8,10 +8,11 @@
#include <linux/amlogic/media/vfm/vframe_receiver.h>
#define VF_NAME_SIZE (32)
#define POOL_SIZE (16)
#define POOL_SIZE (64)
struct vcodec_vfm_s {
struct aml_vcodec_ctx *ctx;
struct aml_vdec_adapt *ada_ctx;
struct vfq_s vf_que;
struct vframe_s *vf;
struct vframe_s *pool[POOL_SIZE + 1];
@@ -32,6 +33,6 @@ struct vframe_s *get_video_frame(struct vcodec_vfm_s *vfm);
int get_fb_from_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb **out_fb);
int put_fb_to_queue(struct aml_vcodec_ctx *ctx, struct vdec_fb *in_fb);
void video_vf_put(struct vdec_fb *fb);
void video_vf_put(char *receiver, struct vdec_fb *fb, int id);
#endif /* __AML_VCODEC_VFM_H_ */

View File

@@ -12,6 +12,7 @@
#include "../aml_vcodec_vfm.h"
#include "h264_stream.h"
#include "h264_parse.h"
#include <uapi/linux/swab.h>
/* h264 NALU type */
#define NAL_NON_IDR_SLICE 0x01
@@ -32,6 +33,8 @@
#define H264_MAX_FB_NUM 17
#define HDR_PARSING_BUF_SZ 1024
#define HEADER_BUFFER_SIZE (32 * 1024)
/**
* struct h264_fb - h264 decode frame buffer information
* @vdec_fb_va : virtual address of struct vdec_fb
@@ -104,6 +107,7 @@ struct vdec_h264_dec_info {
*/
struct vdec_h264_vsi {
unsigned char hdr_buf[HDR_PARSING_BUF_SZ];
char *header_buf;
int sps_size;
int pps_size;
int sei_size;
@@ -137,8 +141,6 @@ struct vdec_h264_inst {
struct vcodec_vfm_s vfm;
};
static DEFINE_MUTEX(mutex);
#define DUMP_FILE_NAME "/data/dump/dump.tmp"
static struct file *filp;
static loff_t file_pos;
@@ -177,13 +179,25 @@ void dump_deinit(void)
}
}
void swap_uv(void *uv, int size)
{
int i;
__u16 *p = uv;
size /= 2;
for (i = 0; i < size; i++, p++)
*p = __swab16(*p);
}
static void get_pic_info(struct vdec_h264_inst *inst,
struct vdec_pic_info *pic)
{
*pic = inst->vsi->pic;
aml_vcodec_debug(inst, "pic(%d, %d), buf(%d, %d)",
pic->pic_w, pic->pic_h, pic->buf_w, pic->buf_h);
pic->visible_width, pic->visible_height,
pic->coded_width, pic->coded_height);
aml_vcodec_debug(inst, "Y(%d, %d), C(%d, %d)", pic->y_bs_sz,
pic->y_len_sz, pic->c_bs_sz, pic->c_len_sz);
}
@@ -220,7 +234,7 @@ static int find_start_code(unsigned char *data, unsigned int data_sz)
static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
{
struct vdec_h264_inst *inst = NULL;
int err = -1;
int ret = -1;
inst = kzalloc(sizeof(*inst), GFP_KERNEL);
if (!inst)
@@ -228,56 +242,60 @@ static int vdec_h264_init(struct aml_vcodec_ctx *ctx, unsigned long *h_vdec)
inst->ctx = ctx;
inst->vdec.id = VFORMAT_H264;
inst->vdec.format = VFORMAT_H264;
inst->vdec.dev = ctx->dev->vpu_plat_dev;
inst->vdec.filp = ctx->dev->filp;
inst->vdec.ctx = ctx;
inst->vfm.ctx = ctx;
inst->vfm.ada_ctx = &inst->vdec;
vcodec_vfm_init(&inst->vfm);
//inst->vpu.handler = vpu_dec_ipi_handler;
err = video_decoder_init(&inst->vdec);
if (err) {
aml_vcodec_err(inst, "vdec_h264 init err=%d", err);
//goto error_free_inst;
ret = video_decoder_init(&inst->vdec);
if (ret) {
aml_vcodec_err(inst, "vdec_h264 init err=%d", ret);
goto error_free_inst;
}
//inst->vsi = (struct vdec_h264_vsi *)inst->vpu.vsi;
//probe info from the decoder hw debug_tmp
/* probe info from the stream */
inst->vsi = kzalloc(sizeof(struct vdec_h264_vsi), GFP_KERNEL);
if (!inst->vsi) {
ret = -ENOMEM;
goto error_free_inst;
}
//debug_tmp
inst->vsi->pic.pic_w = 1920;
inst->vsi->pic.pic_h = 1088;
inst->vsi->pic.buf_w = 1920;
inst->vsi->pic.buf_h = 1088;
/* alloc the header buffer to be used cache sps or spp etc.*/
inst->vsi->header_buf = kzalloc(HEADER_BUFFER_SIZE, GFP_KERNEL);
if (!inst->vsi) {
ret = -ENOMEM;
goto error_free_vsi;
}
inst->vsi->pic.visible_width = 1920;
inst->vsi->pic.visible_height = 1080;
inst->vsi->pic.coded_width = 1920;
inst->vsi->pic.coded_height = 1088;
inst->vsi->pic.y_bs_sz = 0;
inst->vsi->pic.y_len_sz = (1920 * 1088);
inst->vsi->pic.c_bs_sz = 0;
inst->vsi->pic.c_len_sz = (1920 * 1088 / 2);
//err = allocate_predication_buf(inst);
//if (err)
//goto error_deinit;
aml_vcodec_debug(inst, "H264 Instance >> %p", inst);
ctx->ada_ctx = &inst->vdec;
*h_vdec = (unsigned long)inst;
dump_init();
return 0;
//error_deinit:
//vpu_dec_deinit(&inst->vpu);
//error_free_inst:
/*kfree(inst->vsi);
error_free_vsi:
kfree(inst->vsi);
error_free_inst:
kfree(inst);
return err;*/
*h_vdec = 0;
return ret;
}
static int refer_buffer_num(int level_idc, int poc_cnt,
@@ -352,11 +370,11 @@ static int refer_buffer_num(int level_idc, int poc_cnt,
return size;
}
static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi)
static void fill_vdec_params(struct vdec_h264_inst *inst, struct h264_SPS_t *sps)
{
struct vdec_pic_info *pic = &vsi->pic;
struct vdec_h264_dec_info *dec = &vsi->dec;
struct v4l2_rect *rect = &vsi->crop;
struct vdec_pic_info *pic = &inst->vsi->pic;
struct vdec_h264_dec_info *dec = &inst->vsi->dec;
struct v4l2_rect *rect = &inst->vsi->crop;
unsigned int mb_w, mb_h, width, height;
unsigned int crop_unit_x = 0, crop_unit_y = 0;
unsigned int poc_cnt = 0;
@@ -388,21 +406,21 @@ static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi)
height -= crop_unit_y * (sps->frame_crop_top_offset +
sps->frame_crop_bottom_offset);
/* fill image size that be used for EGL. */
pic->pic_w = width;
pic->pic_h = height;
/* fill visible area size that be used for EGL. */
pic->visible_width = width;
pic->visible_height = height;
/* calc visible ares. */
rect->left = 0;
rect->top = 0;
rect->width = pic->pic_w;
rect->height = pic->pic_h;
rect->left = 0;
rect->top = 0;
rect->width = pic->visible_width;
rect->height = pic->visible_height;
/* config canvas size that be used for decoder. */
pic->buf_w = ALIGN(mb_w, 4) << 4;
pic->buf_h = ALIGN(mb_h, 4) << 4;
pic->y_len_sz = pic->buf_w * pic->buf_h;
pic->c_len_sz = pic->y_len_sz >> 1;
pic->coded_width = ALIGN(mb_w, 4) << 4;
pic->coded_height = ALIGN(mb_h, 4) << 4;
pic->y_len_sz = pic->coded_width * pic->coded_height;
pic->c_len_sz = pic->y_len_sz >> 1;
/* calc DPB size */
poc_cnt = sps->pic_order_cnt_type;
@@ -411,8 +429,9 @@ static void fill_vdec_params(struct h264_SPS_t *sps, struct vdec_h264_vsi *vsi)
dec->dpb_sz = refer_buffer_num(sps->level_idc, poc_cnt, mb_w, mb_h);
pr_info("the stream infos, width: %d, height: %d, dpb: %d\n",
pic->pic_w, pic->pic_h, dec->dpb_sz);
pr_info("[%d] The stream infos, coded:(%d x %d), visible:(%d x %d), DPB: %d\n",
inst->ctx->id, pic->coded_width, pic->coded_height,
pic->visible_width, pic->visible_height, dec->dpb_sz);
}
static int vdec_h264_probe(unsigned long h_vdec,
@@ -448,7 +467,7 @@ static int vdec_h264_probe(unsigned long h_vdec,
h264_sps_parse(&s, sps);
//h264_sps_info(sps);
fill_vdec_params(sps, inst->vsi);
fill_vdec_params(inst, sps);
kfree(sps);
@@ -459,7 +478,8 @@ static void vdec_h264_deinit(unsigned long h_vdec)
{
struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
mutex_lock(&mutex);
if (!inst)
return;
aml_vcodec_debug_enter(inst);
@@ -469,11 +489,13 @@ static void vdec_h264_deinit(unsigned long h_vdec)
dump_deinit();
kfree(inst->vsi);
kfree(inst);
inst = NULL;
if (inst->vsi && inst->vsi->header_buf)
kfree(inst->vsi->header_buf);
mutex_unlock(&mutex);
if (inst->vsi)
kfree(inst->vsi);
kfree(inst);
}
static int vdec_h264_get_fb(struct vdec_h264_inst *inst, struct vdec_fb **out)
@@ -486,27 +508,27 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out)
struct vframe_s *vf = NULL;
struct vdec_fb *fb = NULL;
aml_vcodec_debug(inst, "%s() [%d], vfm: %p\n",
__FUNCTION__, __LINE__, &inst->vfm);
aml_vcodec_debug(inst, "%s() [%d], vfm: %p",
__func__, __LINE__, &inst->vfm);
vf = peek_video_frame(&inst->vfm);
if (!vf) {
aml_vcodec_debug(inst, "there is no vframe.\n");
aml_vcodec_debug(inst, "there is no vframe.");
*out = NULL;
return;
}
vf = get_video_frame(&inst->vfm);
if (!vf) {
aml_vcodec_debug(inst, "the vframe is avalid.\n");
aml_vcodec_debug(inst, "the vframe is avalid.");
*out = NULL;
return;
}
atomic_set(&vf->use_cnt, 1);
aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx\n",
__FUNCTION__, __LINE__, vf, vf->v4l_mem_handle);
aml_vcodec_debug(inst, "%s() [%d], vf: %p, v4l_mem_handle: %lx, idx: %d\n",
__func__, __LINE__, vf, vf->v4l_mem_handle, vf->index);
fb = (struct vdec_fb *)vf->v4l_mem_handle;
fb->vf_handle = (unsigned long)vf;
@@ -514,14 +536,18 @@ static void vdec_h264_get_vf(struct vdec_h264_inst *inst, struct vdec_fb **out)
*out = fb;
//pr_info("%s, %d\n", __func__, fb->base_y.bytes_used);
//dump_write(fb->base_y.va, fb->base_y.bytes_used);
//dump_write(fb->base_c.va, fb->base_c.bytes_used);
aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu\n",
__FUNCTION__, __LINE__, fb->base_y.va,
/* convert yuv format. */
//swap_uv(fb->base_c.va, fb->base_c.size);
aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %lu",
__func__, __LINE__, fb->base_y.va,
(unsigned int)virt_to_phys(fb->base_y.va), fb->base_y.size);
aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %zu\n",
__FUNCTION__, __LINE__, fb->base_c.va,
aml_vcodec_debug(inst, "%s() [%d], va: %p, phy: %x, size: %lu",
__func__, __LINE__, fb->base_c.va,
(unsigned int)virt_to_phys(fb->base_c.va), fb->base_c.size);
}
@@ -550,47 +576,46 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
nal_start = buf[nal_start_idx];
nal_type = NAL_TYPE(buf[nal_start_idx]);
aml_v4l2_debug(1, "NALU type: %d, size: %u\n", nal_type, buf_sz);
aml_vcodec_debug(inst, "NALU type: %d, size: %u", nal_type, buf_sz);
if (nal_type == NAL_H264_SPS) {
if (buf_sz > HDR_PARSING_BUF_SZ) {
if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) {
err = -EILSEQ;
goto err_free_fb_out;
}
inst->vsi->sps_size = buf_sz;
memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz);
memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz);
inst->vsi->head_offset += inst->vsi->sps_size;
} else if (nal_type == NAL_H264_PPS) {
//buf_sz -= nal_start_idx;
if (buf_sz > HDR_PARSING_BUF_SZ) {
if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) {
err = -EILSEQ;
goto err_free_fb_out;
}
inst->vsi->pps_size = buf_sz;
memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz);
memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz);
inst->vsi->head_offset += inst->vsi->pps_size;
} else if (nal_type == NAL_H264_SEI) {
if (buf_sz > HDR_PARSING_BUF_SZ) {
if (inst->vsi->head_offset + buf_sz > HEADER_BUFFER_SIZE) {
err = -EILSEQ;
goto err_free_fb_out;
}
inst->vsi->sei_size = buf_sz;
memcpy(inst->vsi->hdr_buf + inst->vsi->head_offset, buf, buf_sz);
memcpy(inst->vsi->header_buf + inst->vsi->head_offset, buf, buf_sz);
inst->vsi->head_offset += inst->vsi->sei_size;
} else {
char *write_buf = vmalloc(inst->vsi->head_offset + buf_sz);
memcpy(write_buf, inst->vsi->hdr_buf, inst->vsi->head_offset);
memcpy(write_buf, inst->vsi->header_buf, inst->vsi->head_offset);
memcpy(write_buf + inst->vsi->head_offset, buf, buf_sz);
ret = vdec_vframe_write(vdec->filp, write_buf,
ret = vdec_vframe_write(vdec, write_buf,
inst->vsi->head_offset + buf_sz, timestamp);
aml_vcodec_debug(inst,
"%s() [%d], buf: %p, buf size: %u, write to: %d\n",
__FUNCTION__, __LINE__, write_buf,
inst->vsi->head_offset + buf_sz, ret);
aml_vcodec_debug(inst, "buf: %p, buf size: %u, write to: %d",
write_buf, inst->vsi->head_offset + buf_sz, ret);
memset(inst->vsi->header_buf, 0, HEADER_BUFFER_SIZE);
inst->vsi->head_offset = 0;
inst->vsi->sps_size = 0;
inst->vsi->pps_size = 0;
@@ -626,14 +651,12 @@ static int vdec_h264_decode(unsigned long h_vdec, struct aml_vcodec_mem *bs,
//vpu_dec_end(vpu);
}
aml_vcodec_debug(inst, "\n - NALU[%d] type=%d -\n", inst->num_nalu,
nal_type);
return ret;
err_free_fb_out:
//put_fb_to_free(inst, fb);
aml_vcodec_err(inst, "\n - NALU[%d] err=%d -\n", inst->num_nalu, err);
aml_vcodec_err(inst, "NALU[%d] err=%d", inst->num_nalu, err);
return err;
}
@@ -643,17 +666,13 @@ static int vdec_h264_get_param(unsigned long h_vdec,
int ret = 0;
struct vdec_h264_inst *inst = (struct vdec_h264_inst *)h_vdec;
mutex_lock(&mutex);
if (!inst) {
pr_err("the h264 inst of dec is void.\n");
mutex_unlock(&mutex);
pr_err("the h264 inst of dec is void.");
return -1;
}
switch (type) {
case GET_PARAM_DISP_FRAME_BUFFER:
//vdec_h264_get_fb(inst, &inst->vsi->list_disp, true, out);
vdec_h264_get_vf(inst, out);
break;
@@ -675,11 +694,9 @@ static int vdec_h264_get_param(unsigned long h_vdec,
default:
aml_vcodec_err(inst, "invalid get parameter type=%d", type);
return -EINVAL;
ret = -EINVAL;
}
mutex_unlock(&mutex);
return ret;
}

View File

@@ -74,17 +74,17 @@ int vdec_if_decode(struct aml_vcodec_ctx *ctx, struct aml_vcodec_mem *bs,
if (ctx->drv_handle == 0)
return -EIO;
aml_vdec_lock(ctx);
//aml_vdec_lock(ctx);
aml_vcodec_set_curr_ctx(ctx->dev, ctx);
//aml_vcodec_dec_clock_on(&ctx->dev->pm);//debug_tmp
enable_irq(ctx->dev->dec_irq);
//enable_irq(ctx->dev->dec_irq);
ret = ctx->dec_if->decode(ctx->drv_handle, bs, timestamp, res_chg);
//disable_irq(ctx->dev->dec_irq);
//aml_vcodec_dec_clock_off(&ctx->dev->pm);
aml_vcodec_set_curr_ctx(ctx->dev, NULL);
aml_vdec_unlock(ctx);
//aml_vdec_unlock(ctx);
return ret;
}
@@ -97,9 +97,9 @@ int vdec_if_get_param(struct aml_vcodec_ctx *ctx,
if (ctx->drv_handle == 0)
return -EIO;
aml_vdec_lock(ctx);
//aml_vdec_lock(ctx);
ret = ctx->dec_if->get_param(ctx->drv_handle, type, out);
aml_vdec_unlock(ctx);
//aml_vdec_unlock(ctx);
return ret;
}
@@ -109,11 +109,11 @@ void vdec_if_deinit(struct aml_vcodec_ctx *ctx)
if (ctx->drv_handle == 0)
return;
aml_vdec_lock(ctx);
//aml_vdec_lock(ctx);
//aml_vcodec_dec_clock_on(&ctx->dev->pm);
ctx->dec_if->deinit(ctx->drv_handle);
//aml_vcodec_dec_clock_off(&ctx->dev->pm);
aml_vdec_unlock(ctx);
//aml_vdec_unlock(ctx);
ctx->drv_handle = 0;
}

View File

@@ -13,9 +13,9 @@
* @FB_ST_FREE : frame buffer is not used by decoder any more
*/
enum vdec_fb_status {
FB_ST_NORMAL = 0,
FB_ST_DISPLAY = (1 << 0),
FB_ST_FREE = (1 << 1)
FB_ST_NORMAL,
FB_ST_DISPLAY,
FB_ST_FREE
};
/* For GET_PARAM_DISP_FRAME_BUFFER and GET_PARAM_FREE_FRAME_BUFFER,

View File

@@ -1609,16 +1609,13 @@ static int v4l_get_fb(struct aml_vcodec_ctx *ctx, struct vdec_fb **out)
static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
{
int ret = 0;
struct aml_vcodec_ctx *ctx = NULL;
struct buffer_spec_s *bs = &hw->buffer_spec[idx];
struct canvas_config_s *y_canvas_cfg = NULL;
struct canvas_config_s *c_canvas_cfg = NULL;
struct vdec_fb *fb = NULL;
unsigned int y_addr, c_addr;
int buf_size = (hw->mb_total << 8) + (hw->mb_total << 7);
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s() [%d], buf size: %d\n", __FUNCTION__, __LINE__, buf_size);
if (IS_ERR_OR_NULL(hw->v4l2_ctx)) {
pr_err("the v4l context has err.\n");
return -1;
@@ -1627,26 +1624,31 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
if (bs->cma_alloc_addr)
return 0;
ctx = (struct aml_vcodec_ctx *)(hw->v4l2_ctx);
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"[%d] %s(), buf size: %d\n", ctx->id, __func__,
(hw->mb_total << 8) + (hw->mb_total << 7));
ret = v4l_get_fb(hw->v4l2_ctx, &fb);
if (ret) {
pr_err("get fb fail.\n");
pr_err("[%d] get fb fail.\n", ctx->id);
return ret;
}
bs->cma_alloc_addr = (unsigned long)fb;
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s() [%d], cma alloc addr: 0x%x\n",
__FUNCTION__, __LINE__, bs->cma_alloc_addr);
"[%d] %s(), cma alloc addr: 0x%x\n",
ctx->id, __func__, bs->cma_alloc_addr);
y_addr = virt_to_phys(fb->base_y.va);
c_addr = virt_to_phys(fb->base_c.va);
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s() [%d], y_addr: %x, va: %p\n",
__FUNCTION__, __LINE__, y_addr, fb->base_y.va);
"[%d] %s(), y_addr: %x, va: %p\n",
ctx->id, __func__, y_addr, fb->base_y.va);
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s() [%d], c_addr: %x, va: %p\n",
__FUNCTION__, __LINE__, c_addr, fb->base_c.va);
"[%d] %s(), c_addr: %x, va: %p\n",
ctx->id, __func__, c_addr, fb->base_c.va);
bs->y_addr = y_addr;
bs->u_addr = c_addr;
@@ -1661,7 +1663,7 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
y_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR;
fb->base_y.bytes_used = y_canvas_cfg->width * y_canvas_cfg->height;
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s() [%d], y_w: %d, y_h: %d\n", __FUNCTION__, __LINE__,
"[%d] %s(), y_w: %d, y_h: %d\n", ctx->id, __func__,
y_canvas_cfg->width,y_canvas_cfg->height);
c_canvas_cfg->phy_addr = c_addr;
@@ -1670,11 +1672,11 @@ static int alloc_one_buf_spec_from_queue(struct vdec_h264_hw_s *hw, int idx)
c_canvas_cfg->block_mode = CANVAS_BLKMODE_LINEAR;
fb->base_c.bytes_used = c_canvas_cfg->width * c_canvas_cfg->height;
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s() [%d], c_w: %d, c_h: %d\n", __FUNCTION__, __LINE__,
"[%d] %s(), c_w: %d, c_h: %d\n", ctx->id, __func__,
c_canvas_cfg->width, c_canvas_cfg->height);
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s, alloc buf for bufspec%d\n", __FUNCTION__, idx);
"[%d] %s(), alloc buf for bufspec%d\n", ctx->id, __func__, idx);
return ret;
}
@@ -2140,8 +2142,9 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
vf->v4l_mem_handle
= hw->buffer_spec[buffer_index].cma_alloc_addr;
dpb_print(DECODE_ID(hw), PRINT_FLAG_V4L_DETAIL,
"%s() [%d], v4l mem handle: 0x%x\n",
__FUNCTION__, __LINE__, vf->v4l_mem_handle);
"[%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) {
@@ -2258,6 +2261,7 @@ int prepare_display_buf(struct vdec_s *vdec, struct FrameStore *frame)
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_fb *fb = NULL;
@@ -2270,7 +2274,7 @@ int notify_v4l_eos(struct vdec_s *vdec)
}
if (v4l_get_fb(hw->v4l2_ctx, &fb)) {
pr_err("get fb fail.\n");
pr_err("[%d] get fb fail.\n", ctx->id);
return -1;
}
@@ -2279,9 +2283,10 @@ int notify_v4l_eos(struct vdec_s *vdec)
vf->flag = VFRAME_FLAG_EMPTY_FRAME_V4L;
kfifo_put(&hw->display_q, (const struct vframe_s *)vf);
pr_info("264 EOS notify \n");
vf_notify_receiver(vdec->vf_provider_name,
VFRAME_EVENT_PROVIDER_VFRAME_READY, NULL);
pr_info("[%d] H264 EOS notify.\n", ctx->id);
}
return 0;
@@ -3604,7 +3609,7 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
(unsigned int)((8 << chroma444) - 1));
}
dpb_print(DECODE_ID(hw), 0,
"frame_mbs_only_flag %d, crop_bottom %d, frame_height %d, ",
"frame_mbs_only_flag %d, crop_bottom %d, frame_height %d,\n",
frame_mbs_only_flag, crop_bottom, hw->frame_height);
dpb_print(DECODE_ID(hw), 0,
"mb_height %d,crop_right %d, frame_width %d, mb_width %d\n",
@@ -3755,12 +3760,13 @@ static int vh264_set_params(struct vdec_h264_hw_s *hw,
for (j = 1; j < buf_cnt; j++) {
i = get_buf_spec_by_canvas_pos(hw, j);
if (hw->is_used_v4l &&
alloc_one_buf_spec_from_queue
if (hw->is_used_v4l) {
if (alloc_one_buf_spec_from_queue
(hw, i) < 0) {
if (j++ != buf_cnt)
ret = -1;
break;
if (j++ != buf_cnt)
ret = -1;
break;
}
} else if (alloc_one_buf_spec(hw, i) < 0)
break;
@@ -3974,9 +3980,12 @@ static void vui_config(struct vdec_h264_hw_s *hw)
static void bufmgr_recover(struct vdec_h264_hw_s *hw)
{
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
bufmgr_h264_remove_unused_frame(p_H264_Dpb, 2);
if (error_proc_policy & 0x20)
hw->reset_bufmgr_flag = 1;
if (error_proc_policy & 0x20) {
if (!hw->is_used_v4l)
hw->reset_bufmgr_flag = 1;
}
}
void bufmgr_force_recover(struct h264_dpb_stru *p_H264_Dpb)
@@ -5207,6 +5216,10 @@ static int vh264_hw_ctx_restore(struct vdec_h264_hw_s *hw)
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1<<17);
#endif
/* cbcr_merge_swap_en */
if (hw->is_used_v4l)
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 1 << 16);
SET_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24);
CLEAR_VREG_MASK(MDEC_PIC_DC_CTRL, 0xbf << 24);

View File

@@ -1581,7 +1581,8 @@ s32 vdec_init(struct vdec_s *vdec, int is_4k)
"vdec-map-%d", vdec->id);
} else if (p->frame_base_video_path == FRAME_BASE_PATH_V4L_VIDEO) {
snprintf(vdec->vfm_map_chain, VDEC_MAP_NAME_SIZE,
"%s %s", vdec->vf_provider_name, "v4l2-video");
"%s %s", vdec->vf_provider_name,
vdec->vf_receiver_name);
snprintf(vdec->vfm_map_id, VDEC_MAP_NAME_SIZE,
"vdec-map-%d", vdec->id);
}
@@ -2442,6 +2443,7 @@ void vdec_poweron(enum vdec_type_e core)
* m8baby and m8m2 can dynamic adjust vdec clock,
* power on with default clock level
*/
amports_switch_gate("clk_vdec_mux", 1);
vdec_clock_hi_enable();
/* power up vdec memories */
WRITE_VREG(DOS_MEM_PD_VDEC, 0);
@@ -2519,6 +2521,9 @@ void vdec_poweron(enum vdec_type_e core)
WRITE_VREG(DOS_SW_RESET3, 0xffffffff);
WRITE_VREG(DOS_SW_RESET3, 0);
/* enable hevc clock */
amports_switch_gate("clk_hevc_mux", 1);
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
amports_switch_gate("clk_hevcb_mux", 1);
hevc_clock_hi_enable();
hevc_back_clock_hi_enable();
/* power up hevc memories */

View File

@@ -612,10 +612,6 @@ static int video_port_init(struct port_priv_s *priv,
pbuf->for_4k = 1;
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_TXLX
&& port->vformat == VFORMAT_H264) {
amports_switch_gate("clk_hevc_mux", 1);
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
amports_switch_gate("clk_hevcb_mux", 1);
vdec_poweron(VDEC_HEVC);
}
} else {
@@ -1620,22 +1616,14 @@ static int amstream_open(struct inode *inode, struct file *file)
if (has_hevc_vdec()) {
if (port->type &
(PORT_TYPE_MPTS | PORT_TYPE_HEVC)) {
amports_switch_gate("clk_hevc_mux", 1);
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_G12A)
amports_switch_gate("clk_hevcb_mux", 1);
(PORT_TYPE_MPTS | PORT_TYPE_HEVC))
vdec_poweron(VDEC_HEVC);
}
if ((port->type & PORT_TYPE_HEVC) == 0) {
amports_switch_gate("clk_vdec_mux", 1);
if ((port->type & PORT_TYPE_HEVC) == 0)
vdec_poweron(VDEC_1);
}
} else {
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8) {
amports_switch_gate("clk_vdec_mux", 1);
if (get_cpu_major_id() >= AM_MESON_CPU_MAJOR_ID_M8)
vdec_poweron(VDEC_1);
}
}
}