mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-10 12:57:06 +09:00
media_module: vdec [1/1]
PD#OTT-1699 Problem: not support multi-vdec user data read Solution: Add getting available user data vdec interface Verify: Verified U212 Change-Id: I10d22cd545bcc1421dd291866c9f039e38f61e44 Signed-off-by: Rong Zhang <rong.zhang@amlogic.com>
This commit is contained in:
@@ -55,6 +55,8 @@
|
||||
#include "../utils/firmware.h"
|
||||
#include <linux/amlogic/tee.h>
|
||||
#include "../../../common/chips/decoder_cpu_ver_info.h"
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
|
||||
#define DRIVER_NAME "amvdec_h264"
|
||||
#define MODULE_NAME "amvdec_h264"
|
||||
@@ -248,6 +250,7 @@ static unsigned int canvas_mode;
|
||||
/* 0~128*/
|
||||
static u32 bad_block_scale;
|
||||
#endif
|
||||
static u32 enable_userdata_debug;
|
||||
|
||||
static unsigned int enable_switch_fense = 1;
|
||||
#define EN_SWITCH_FENCE() (enable_switch_fense && !is_4k)
|
||||
@@ -339,6 +342,8 @@ static struct ge2d_context_s *ge2d_videoh264_context;
|
||||
|
||||
static struct vdec_info *gvs;
|
||||
|
||||
static struct vdec_s *vdec_h264;
|
||||
|
||||
static int ge2d_videoh264task_init(void)
|
||||
{
|
||||
if (ge2d_videoh264_context == NULL)
|
||||
@@ -577,7 +582,10 @@ static tvin_trans_fmt_t convert_3d_format(u32 type)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG_CC_USER_DATA
|
||||
|
||||
#define DUMP_CC_AS_ASCII
|
||||
|
||||
#ifdef DUMP_CC_AS_ASCII
|
||||
static int vbi_to_ascii(int c)
|
||||
{
|
||||
if (c < 0)
|
||||
@@ -591,7 +599,7 @@ static int vbi_to_ascii(int c)
|
||||
return c;
|
||||
}
|
||||
|
||||
static void dump_cc_ascii(const uint8_t *buf, int poc)
|
||||
static void dump_cc_ascii(const uint8_t *buf, unsigned int vpts, int poc)
|
||||
{
|
||||
int cc_flag;
|
||||
int cc_count;
|
||||
@@ -628,72 +636,56 @@ static void dump_cc_ascii(const uint8_t *buf, int poc)
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (index) {
|
||||
case 8:
|
||||
pr_info("push poc:%d : %c %c %c %c %c %c %c %c\n",
|
||||
poc,
|
||||
szAscii[0], szAscii[1], szAscii[2], szAscii[3],
|
||||
szAscii[4], szAscii[5], szAscii[6], szAscii[7]);
|
||||
break;
|
||||
case 7:
|
||||
pr_info("push poc:%d : %c %c %c %c %c %c %c\n",
|
||||
poc,
|
||||
szAscii[0], szAscii[1], szAscii[2], szAscii[3],
|
||||
szAscii[4], szAscii[5], szAscii[6]);
|
||||
break;
|
||||
case 6:
|
||||
pr_info("push poc:%d : %c %c %c %c %c %c\n", poc,
|
||||
szAscii[0], szAscii[1], szAscii[2], szAscii[3],
|
||||
szAscii[4], szAscii[5]);
|
||||
break;
|
||||
case 5:
|
||||
pr_info("push poc:%d : %c %c %c %c %c\n", poc,
|
||||
szAscii[0], szAscii[1], szAscii[2], szAscii[3],
|
||||
szAscii[4]);
|
||||
break;
|
||||
case 4:
|
||||
pr_info("push poc:%d : %c %c %c %c\n", poc,
|
||||
szAscii[0], szAscii[1], szAscii[2], szAscii[3]);
|
||||
break;
|
||||
case 3:
|
||||
pr_info("push poc:%d : %c %c %c\n", poc,
|
||||
szAscii[0], szAscii[1], szAscii[2]);
|
||||
break;
|
||||
case 2:
|
||||
pr_info("push poc:%d : %c %c\n", poc,
|
||||
szAscii[0], szAscii[1]);
|
||||
break;
|
||||
case 1:
|
||||
pr_info("push poc:%d : %c\n", poc, szAscii[0]);
|
||||
break;
|
||||
default:
|
||||
pr_info("push poc:%d and no CC data: index = %d\n",
|
||||
poc, index);
|
||||
break;
|
||||
|
||||
if (index > 0 && index <= 8) {
|
||||
char pr_buf[128];
|
||||
int len;
|
||||
|
||||
sprintf(pr_buf, "push vpts:0x%x, poc:%d :", vpts, poc);
|
||||
len = strlen(pr_buf);
|
||||
for (i=0;i<index;i++)
|
||||
sprintf(pr_buf + len + i*2, "%c ", szAscii[i]);
|
||||
pr_info("%s\n", pr_buf);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
#define DUMP_USER_DATA_HEX
|
||||
*/
|
||||
|
||||
#ifdef DUMP_USER_DATA_HEX
|
||||
static void print_data(unsigned char *pdata, int len)
|
||||
{
|
||||
int nLeft;
|
||||
char buf[128];
|
||||
|
||||
nLeft = len;
|
||||
while (nLeft >= 16) {
|
||||
int i;
|
||||
|
||||
for (i=0;i<16;i++)
|
||||
sprintf(buf+i*3, "%02x ", pdata[i]);
|
||||
|
||||
pr_info("%s\n", buf);
|
||||
nLeft -= 16;
|
||||
pdata += 16;
|
||||
}
|
||||
|
||||
while (nLeft >= 8) {
|
||||
pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
pdata[0], pdata[1], pdata[2], pdata[3],
|
||||
pdata[4], pdata[5], pdata[6], pdata[7]);
|
||||
int i;
|
||||
for (i=0;i<nLeft;i++)
|
||||
sprintf(buf+i*3, "%02x ", pdata[i]);
|
||||
|
||||
pr_info("%s\n", buf);
|
||||
nLeft -= 8;
|
||||
pdata += 8;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static void aml_swap_data(uint8_t *user_data, int ud_size)
|
||||
{
|
||||
int swap_blocks, i, j, k, m;
|
||||
@@ -712,8 +704,10 @@ static void aml_swap_data(uint8_t *user_data, int ud_size)
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_data(unsigned int user_data_wp,
|
||||
|
||||
static void udr_dump_data(unsigned int user_data_wp,
|
||||
unsigned int user_data_length,
|
||||
unsigned int pts,
|
||||
int poc)
|
||||
{
|
||||
unsigned char *pdata;
|
||||
@@ -759,42 +753,628 @@ static void dump_data(unsigned int user_data_wp,
|
||||
}
|
||||
|
||||
aml_swap_data(szBuf, user_data_len);
|
||||
|
||||
#ifdef DUMP_USER_DATA_HEX
|
||||
print_data(szBuf, user_data_len);
|
||||
#endif
|
||||
dump_cc_ascii(szBuf+7, poc);
|
||||
|
||||
#ifdef DUMP_CC_AS_ASCII
|
||||
dump_cc_ascii(szBuf+7, pts, poc);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
struct vh264_userdata_recored_t {
|
||||
struct userdata_meta_info_t meta_info;
|
||||
u32 rec_start;
|
||||
u32 rec_len;
|
||||
};
|
||||
|
||||
#define USERDATA_FIFO_NUM 256
|
||||
|
||||
struct vh264_userdata_info_t {
|
||||
struct vh264_userdata_recored_t records[USERDATA_FIFO_NUM];
|
||||
u8 *data_buf;
|
||||
u8 *data_buf_end;
|
||||
u32 buf_len;
|
||||
u32 read_index;
|
||||
u32 write_index;
|
||||
u32 last_wp;
|
||||
};
|
||||
|
||||
static struct vh264_userdata_info_t *p_userdata_mgr;
|
||||
|
||||
static DEFINE_MUTEX(userdata_mutex);
|
||||
|
||||
|
||||
void vh264_crate_userdata_manager(u8 *userdata_buf, int buf_len)
|
||||
{
|
||||
p_userdata_mgr = (struct vh264_userdata_info_t *)
|
||||
vmalloc(sizeof(struct vh264_userdata_info_t));
|
||||
if (p_userdata_mgr) {
|
||||
memset(p_userdata_mgr, 0,
|
||||
sizeof(struct vh264_userdata_info_t));
|
||||
p_userdata_mgr->data_buf = userdata_buf;
|
||||
p_userdata_mgr->buf_len = buf_len;
|
||||
p_userdata_mgr->data_buf_end = userdata_buf + buf_len;
|
||||
}
|
||||
}
|
||||
|
||||
void vh264_destroy_userdata_manager(void)
|
||||
{
|
||||
if (p_userdata_mgr) {
|
||||
vfree(p_userdata_mgr);
|
||||
p_userdata_mgr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#define DUMP_USER_DATA
|
||||
*/
|
||||
#ifdef DUMP_USER_DATA
|
||||
|
||||
#define MAX_USER_DATA_SIZE 3145728
|
||||
static void *user_data_buf;
|
||||
static unsigned char *pbuf_start;
|
||||
static int total_len;
|
||||
static int bskip;
|
||||
static int n_userdata_id;
|
||||
|
||||
|
||||
static void print_mem_data(unsigned char *pdata,
|
||||
int len,
|
||||
unsigned int flag,
|
||||
unsigned int duration,
|
||||
unsigned int vpts,
|
||||
unsigned int vpts_valid,
|
||||
int rec_id)
|
||||
{
|
||||
int nLeft;
|
||||
|
||||
nLeft = len;
|
||||
#if 0
|
||||
pr_info("%d len = %d, flag = %d, duration = %d, vpts = 0x%x, vpts_valid = %d\n",
|
||||
rec_id, len, flag,
|
||||
duration, vpts, vpts_valid);
|
||||
#endif
|
||||
pr_info("%d len = %d, flag = %d, vpts = 0x%x\n",
|
||||
rec_id, len, flag, vpts);
|
||||
|
||||
|
||||
while (nLeft >= 16) {
|
||||
pr_info("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
pdata[0], pdata[1], pdata[2], pdata[3],
|
||||
pdata[4], pdata[5], pdata[6], pdata[7],
|
||||
pdata[8], pdata[9], pdata[10], pdata[11],
|
||||
pdata[12], pdata[13], pdata[14], pdata[15]);
|
||||
nLeft -= 16;
|
||||
pdata += 16;
|
||||
}
|
||||
|
||||
|
||||
while (nLeft > 0) {
|
||||
pr_info("%02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
pdata[0], pdata[1], pdata[2], pdata[3],
|
||||
pdata[4], pdata[5], pdata[6], pdata[7]);
|
||||
nLeft -= 8;
|
||||
pdata += 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void dump_data(u8 *pdata,
|
||||
unsigned int user_data_length,
|
||||
unsigned int flag,
|
||||
unsigned int duration,
|
||||
unsigned int vpts,
|
||||
unsigned int vpts_valid,
|
||||
int rec_id)
|
||||
{
|
||||
unsigned char szBuf[256];
|
||||
|
||||
|
||||
memset(szBuf, 0, 256);
|
||||
memcpy(szBuf, pdata, user_data_length);
|
||||
/*
|
||||
aml_swap_data(szBuf, user_data_length);
|
||||
*/
|
||||
|
||||
print_mem_data(szBuf, user_data_length,
|
||||
flag, duration, vpts,
|
||||
vpts_valid, rec_id);
|
||||
|
||||
#ifdef DEBUG_CC_DUMP_ASCII
|
||||
dump_cc_ascii(szBuf+7);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void push_to_buf(u8 *pdata, int len, struct userdata_meta_info_t *pmeta)
|
||||
{
|
||||
u32 *pLen;
|
||||
int info_cnt;
|
||||
u8 *pbuf_end;
|
||||
|
||||
if (!user_data_buf)
|
||||
return;
|
||||
|
||||
if (bskip) {
|
||||
pr_info("over size, skip\n");
|
||||
return;
|
||||
}
|
||||
info_cnt = 0;
|
||||
pLen = (u32 *)pbuf_start;
|
||||
|
||||
*pLen = len;
|
||||
pbuf_start += sizeof(u32);
|
||||
info_cnt++;
|
||||
pLen++;
|
||||
|
||||
*pLen = pmeta->duration;
|
||||
pbuf_start += sizeof(u32);
|
||||
info_cnt++;
|
||||
pLen++;
|
||||
|
||||
*pLen = pmeta->flags;
|
||||
pbuf_start += sizeof(u32);
|
||||
info_cnt++;
|
||||
pLen++;
|
||||
|
||||
*pLen = pmeta->vpts;
|
||||
pbuf_start += sizeof(u32);
|
||||
info_cnt++;
|
||||
pLen++;
|
||||
|
||||
*pLen = pmeta->vpts_valid;
|
||||
pbuf_start += sizeof(u32);
|
||||
info_cnt++;
|
||||
pLen++;
|
||||
|
||||
|
||||
*pLen = n_userdata_id;
|
||||
pbuf_start += sizeof(u32);
|
||||
info_cnt++;
|
||||
pLen++;
|
||||
|
||||
|
||||
|
||||
pbuf_end = (u8 *)sei_data_buffer + USER_DATA_SIZE;
|
||||
if (pdata + len > pbuf_end) {
|
||||
int first_section_len;
|
||||
|
||||
first_section_len = pbuf_end - pdata;
|
||||
memcpy(pbuf_start, pdata, first_section_len);
|
||||
pdata = (u8 *)sei_data_buffer;
|
||||
pbuf_start += first_section_len;
|
||||
memcpy(pbuf_start, pdata, len - first_section_len);
|
||||
pbuf_start += len - first_section_len;
|
||||
} else {
|
||||
memcpy(pbuf_start, pdata, len);
|
||||
pbuf_start += len;
|
||||
}
|
||||
|
||||
total_len += len + info_cnt * sizeof(u32);
|
||||
if (total_len >= MAX_USER_DATA_SIZE-4096)
|
||||
bskip = 1;
|
||||
}
|
||||
|
||||
|
||||
static void dump_userdata_info(
|
||||
void *puser_data,
|
||||
int len,
|
||||
struct userdata_meta_info_t *pmeta)
|
||||
{
|
||||
u8 *pstart;
|
||||
|
||||
pstart = (u8 *)puser_data;
|
||||
|
||||
|
||||
push_to_buf(pstart, len, pmeta);
|
||||
}
|
||||
|
||||
static void show_user_data_buf(void)
|
||||
{
|
||||
u8 *pbuf;
|
||||
int len;
|
||||
unsigned int flag;
|
||||
unsigned int duration;
|
||||
unsigned int vpts;
|
||||
unsigned int vpts_valid;
|
||||
int rec_id;
|
||||
|
||||
pr_info("show user data buf\n");
|
||||
pbuf = user_data_buf;
|
||||
|
||||
while (pbuf < pbuf_start) {
|
||||
u32 *pLen;
|
||||
|
||||
pLen = (u32 *)pbuf;
|
||||
|
||||
len = *pLen;
|
||||
pLen++;
|
||||
pbuf += sizeof(u32);
|
||||
|
||||
duration = *pLen;
|
||||
pLen++;
|
||||
pbuf += sizeof(u32);
|
||||
|
||||
flag = *pLen;
|
||||
pLen++;
|
||||
pbuf += sizeof(u32);
|
||||
|
||||
vpts = *pLen;
|
||||
pLen++;
|
||||
pbuf += sizeof(u32);
|
||||
|
||||
vpts_valid = *pLen;
|
||||
pLen++;
|
||||
pbuf += sizeof(u32);
|
||||
|
||||
rec_id = *pLen;
|
||||
pLen++;
|
||||
pbuf += sizeof(u32);
|
||||
|
||||
dump_data(pbuf, len, flag, duration, vpts, vpts_valid, rec_id);
|
||||
pbuf += len;
|
||||
msleep(30);
|
||||
}
|
||||
}
|
||||
|
||||
static int vh264_init_userdata_dump(void)
|
||||
{
|
||||
user_data_buf = kmalloc(MAX_USER_DATA_SIZE, GFP_KERNEL);
|
||||
if (user_data_buf)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vh264_dump_userdata(void)
|
||||
{
|
||||
if (user_data_buf) {
|
||||
show_user_data_buf();
|
||||
kfree(user_data_buf);
|
||||
user_data_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void vh264_reset_user_data_buf(void)
|
||||
{
|
||||
total_len = 0;
|
||||
pbuf_start = user_data_buf;
|
||||
bskip = 0;
|
||||
n_userdata_id = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vh264_add_userdata(struct userdata_meta_info_t meta_info, int wp)
|
||||
{
|
||||
struct vh264_userdata_recored_t *p_userdata_rec;
|
||||
int data_length;
|
||||
|
||||
mutex_lock(&userdata_mutex);
|
||||
|
||||
if (p_userdata_mgr) {
|
||||
if (wp > p_userdata_mgr->last_wp)
|
||||
data_length = wp - p_userdata_mgr->last_wp;
|
||||
else
|
||||
data_length = wp + p_userdata_mgr->buf_len -
|
||||
p_userdata_mgr->last_wp;
|
||||
|
||||
if (data_length & 0x7)
|
||||
data_length = (((data_length + 8) >> 3) << 3);
|
||||
#if 0
|
||||
pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n",
|
||||
p_userdata_mgr->read_index,
|
||||
p_userdata_mgr->write_index,
|
||||
data_length,
|
||||
p_userdata_mgr->last_wp,
|
||||
wp,
|
||||
n_userdata_id);
|
||||
#endif
|
||||
p_userdata_rec = p_userdata_mgr->records +
|
||||
p_userdata_mgr->write_index;
|
||||
p_userdata_rec->meta_info = meta_info;
|
||||
p_userdata_rec->rec_start = p_userdata_mgr->last_wp;
|
||||
p_userdata_rec->rec_len = data_length;
|
||||
p_userdata_mgr->last_wp = wp;
|
||||
|
||||
#ifdef DUMP_USER_DATA
|
||||
dump_userdata_info(p_userdata_mgr->data_buf +
|
||||
p_userdata_rec->rec_start,
|
||||
data_length,
|
||||
&meta_info);
|
||||
n_userdata_id++;
|
||||
#endif
|
||||
|
||||
p_userdata_mgr->write_index++;
|
||||
if (p_userdata_mgr->write_index >= USERDATA_FIFO_NUM)
|
||||
p_userdata_mgr->write_index = 0;
|
||||
}
|
||||
mutex_unlock(&userdata_mutex);
|
||||
|
||||
vdec_wakeup_userdata_poll(vdec_h264);
|
||||
}
|
||||
|
||||
static int vh264_user_data_read(struct vdec_s *vdec,
|
||||
struct userdata_param_t *puserdata_para)
|
||||
{
|
||||
int rec_ri, rec_wi;
|
||||
int rec_len;
|
||||
u8 *rec_data_start;
|
||||
u8 *pdest_buf;
|
||||
struct vh264_userdata_recored_t *p_userdata_rec;
|
||||
u32 data_size;
|
||||
u32 res;
|
||||
int copy_ok = 1;
|
||||
|
||||
|
||||
pdest_buf = puserdata_para->pbuf_addr;
|
||||
|
||||
|
||||
mutex_lock(&userdata_mutex);
|
||||
|
||||
if (!p_userdata_mgr) {
|
||||
mutex_unlock(&userdata_mutex);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
pr_info("ri = %d, wi = %d\n",
|
||||
p_userdata_mgr->read_index,
|
||||
p_userdata_mgr->write_index);
|
||||
*/
|
||||
rec_ri = p_userdata_mgr->read_index;
|
||||
rec_wi = p_userdata_mgr->write_index;
|
||||
|
||||
if (rec_ri == rec_wi) {
|
||||
mutex_unlock(&userdata_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p_userdata_rec = p_userdata_mgr->records + rec_ri;
|
||||
|
||||
rec_len = p_userdata_rec->rec_len;
|
||||
rec_data_start = p_userdata_rec->rec_start + p_userdata_mgr->data_buf;
|
||||
/*
|
||||
pr_info("rec_len:%d, rec_start:%d, buf_len:%d\n",
|
||||
p_userdata_rec->rec_len,
|
||||
p_userdata_rec->rec_start,
|
||||
puserdata_para->buf_len);
|
||||
*/
|
||||
if (rec_len <= puserdata_para->buf_len) {
|
||||
/* dvb user data buffer is enought to copy the whole recored. */
|
||||
data_size = rec_len;
|
||||
if (rec_data_start + data_size
|
||||
> p_userdata_mgr->data_buf_end) {
|
||||
int first_section_len;
|
||||
|
||||
first_section_len = p_userdata_mgr->buf_len -
|
||||
p_userdata_rec->rec_start;
|
||||
res = (u32)copy_to_user((void *)pdest_buf,
|
||||
(void *)rec_data_start,
|
||||
first_section_len);
|
||||
if (res) {
|
||||
pr_info("p1 read not end res=%d, request=%d\n",
|
||||
res, first_section_len);
|
||||
copy_ok = 0;
|
||||
|
||||
p_userdata_rec->rec_len -=
|
||||
first_section_len - res;
|
||||
p_userdata_rec->rec_start +=
|
||||
first_section_len - res;
|
||||
puserdata_para->data_size =
|
||||
first_section_len - res;
|
||||
} else {
|
||||
res = (u32)copy_to_user(
|
||||
(void *)(pdest_buf+first_section_len),
|
||||
(void *)p_userdata_mgr->data_buf,
|
||||
data_size - first_section_len);
|
||||
if (res) {
|
||||
pr_info("p2 read not end res=%d, request=%d\n",
|
||||
res, data_size);
|
||||
copy_ok = 0;
|
||||
}
|
||||
p_userdata_rec->rec_len -=
|
||||
data_size - res;
|
||||
p_userdata_rec->rec_start =
|
||||
data_size - first_section_len - res;
|
||||
puserdata_para->data_size =
|
||||
data_size - res;
|
||||
}
|
||||
} else {
|
||||
res = (u32)copy_to_user((void *)pdest_buf,
|
||||
(void *)rec_data_start,
|
||||
data_size);
|
||||
if (res) {
|
||||
pr_info("p3 read not end res=%d, request=%d\n",
|
||||
res, data_size);
|
||||
copy_ok = 0;
|
||||
}
|
||||
p_userdata_rec->rec_len -= data_size - res;
|
||||
p_userdata_rec->rec_start += data_size - res;
|
||||
puserdata_para->data_size = data_size - res;
|
||||
}
|
||||
|
||||
if (copy_ok) {
|
||||
p_userdata_mgr->read_index++;
|
||||
if (p_userdata_mgr->read_index >= USERDATA_FIFO_NUM)
|
||||
p_userdata_mgr->read_index = 0;
|
||||
}
|
||||
} else {
|
||||
/* dvb user data buffer is not enought
|
||||
to copy the whole recored. */
|
||||
data_size = puserdata_para->buf_len;
|
||||
if (rec_data_start + data_size
|
||||
> p_userdata_mgr->data_buf_end) {
|
||||
int first_section_len;
|
||||
|
||||
first_section_len = p_userdata_mgr->buf_len
|
||||
- p_userdata_rec->rec_start;
|
||||
res = (u32)copy_to_user((void *)pdest_buf,
|
||||
(void *)rec_data_start,
|
||||
first_section_len);
|
||||
if (res) {
|
||||
pr_info("p4 read not end res=%d, request=%d\n",
|
||||
res, first_section_len);
|
||||
copy_ok = 0;
|
||||
p_userdata_rec->rec_len -=
|
||||
first_section_len - res;
|
||||
p_userdata_rec->rec_start +=
|
||||
first_section_len - res;
|
||||
puserdata_para->data_size =
|
||||
first_section_len - res;
|
||||
} else {
|
||||
/* first secton copy is ok*/
|
||||
res = (u32)copy_to_user(
|
||||
(void *)(pdest_buf+first_section_len),
|
||||
(void *)p_userdata_mgr->data_buf,
|
||||
data_size - first_section_len);
|
||||
if (res) {
|
||||
pr_info("p5 read not end res=%d, request=%d\n",
|
||||
res,
|
||||
data_size - first_section_len);
|
||||
copy_ok = 0;
|
||||
}
|
||||
|
||||
p_userdata_rec->rec_len -= data_size - res;
|
||||
p_userdata_rec->rec_start =
|
||||
data_size - first_section_len - res;
|
||||
puserdata_para->data_size = data_size - res;
|
||||
}
|
||||
} else {
|
||||
res = (u32)copy_to_user((void *)pdest_buf,
|
||||
(void *)rec_data_start,
|
||||
data_size);
|
||||
if (res) {
|
||||
pr_info("p6 read not end res=%d, request=%d\n",
|
||||
res, data_size);
|
||||
copy_ok = 0;
|
||||
}
|
||||
|
||||
p_userdata_rec->rec_len -= data_size - res;
|
||||
p_userdata_rec->rec_start += data_size - res;
|
||||
puserdata_para->data_size = data_size - res;
|
||||
}
|
||||
|
||||
if (copy_ok) {
|
||||
p_userdata_mgr->read_index++;
|
||||
if (p_userdata_mgr->read_index
|
||||
>= USERDATA_FIFO_NUM)
|
||||
p_userdata_mgr->read_index = 0;
|
||||
}
|
||||
|
||||
}
|
||||
puserdata_para->meta_info = p_userdata_rec->meta_info;
|
||||
|
||||
if (p_userdata_mgr->read_index <= p_userdata_mgr->write_index)
|
||||
puserdata_para->meta_info.records_in_que =
|
||||
p_userdata_mgr->write_index -
|
||||
p_userdata_mgr->read_index;
|
||||
else
|
||||
puserdata_para->meta_info.records_in_que =
|
||||
p_userdata_mgr->write_index +
|
||||
USERDATA_FIFO_NUM -
|
||||
p_userdata_mgr->read_index;
|
||||
|
||||
puserdata_para->version = (0<<24|0<<16|0<<8|1);
|
||||
|
||||
mutex_unlock(&userdata_mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void vh264_wakeup_userdata_poll(struct vdec_s *vdec)
|
||||
{
|
||||
amstream_wakeup_userdata_poll(vdec);
|
||||
}
|
||||
|
||||
static void vh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
|
||||
{
|
||||
mutex_lock(&userdata_mutex);
|
||||
|
||||
if (p_userdata_mgr) {
|
||||
pr_info("h264_reset_userdata_fifo: bInit: %d, ri: %d, wi: %d\n",
|
||||
bInit, p_userdata_mgr->read_index,
|
||||
p_userdata_mgr->write_index);
|
||||
p_userdata_mgr->read_index = 0;
|
||||
p_userdata_mgr->write_index = 0;
|
||||
|
||||
if (bInit)
|
||||
p_userdata_mgr->last_wp = 0;
|
||||
}
|
||||
|
||||
mutex_unlock(&userdata_mutex);
|
||||
}
|
||||
|
||||
|
||||
static void userdata_push_do_work(struct work_struct *work)
|
||||
{
|
||||
unsigned int sei_itu35_flags;
|
||||
unsigned int sei_itu35_wp;
|
||||
unsigned int sei_itu35_data_length;
|
||||
struct userdata_poc_info_t user_data_poc;
|
||||
|
||||
memset(&user_data_poc, 0x0, sizeof(struct userdata_poc_info_t));
|
||||
struct userdata_meta_info_t meta_info;
|
||||
u32 offset, pts;
|
||||
u64 pts_us64 = 0;
|
||||
u32 slice_type;
|
||||
u32 reg;
|
||||
u32 poc_number;
|
||||
u32 picture_struct;
|
||||
|
||||
memset(&meta_info, 0, sizeof(meta_info));
|
||||
|
||||
meta_info.duration = frame_dur;
|
||||
|
||||
reg = READ_VREG(AV_SCRATCH_M);
|
||||
poc_number = reg & 0x7FFFFFF;
|
||||
if ((poc_number >> 16) == 0x7FF)
|
||||
poc_number = (reg & 0x7FFFFFF) - 0x8000000;
|
||||
|
||||
slice_type = (reg >> 29) & 0x7;
|
||||
switch (slice_type) {
|
||||
case SLICE_TYPE_I:
|
||||
meta_info.flags |= 1<<7;
|
||||
break;
|
||||
case SLICE_TYPE_P:
|
||||
meta_info.flags |= 3<<7;
|
||||
break;
|
||||
case SLICE_TYPE_B:
|
||||
meta_info.flags |= 2<<7;
|
||||
break;
|
||||
}
|
||||
meta_info.poc_number = poc_number;
|
||||
picture_struct = (reg >> 27) & 0x3;
|
||||
|
||||
meta_info.flags |= (VFORMAT_H264 << 3) | (picture_struct << 12);
|
||||
|
||||
|
||||
offset = READ_VREG(AV_SCRATCH_L);
|
||||
|
||||
if (pts_pickout_offset_us64
|
||||
(PTS_TYPE_VIDEO, offset, &pts, 0, &pts_us64) != 0) {
|
||||
pr_info("pts pick outfailed, offset:0x%x\n", offset);
|
||||
pts = -1;
|
||||
meta_info.vpts_valid = 0;
|
||||
} else
|
||||
meta_info.vpts_valid = 1;
|
||||
meta_info.vpts = pts;
|
||||
/*
|
||||
pr_info("offset:0x%x, vpts:0x%x, slice:%d, poc:%d\n",
|
||||
offset, pts, slice_type,
|
||||
poc_number);
|
||||
*/
|
||||
sei_itu35_flags = READ_VREG(AV_SCRATCH_J);
|
||||
sei_itu35_wp = (sei_itu35_flags >> 16) & 0xffff;
|
||||
sei_itu35_data_length = sei_itu35_flags & 0x7fff;
|
||||
|
||||
#if 0
|
||||
pr_info("pocinfo 0x%x, top poc %d, wp 0x%x, length %d\n",
|
||||
READ_VREG(AV_SCRATCH_L),
|
||||
READ_VREG(AV_SCRATCH_M),
|
||||
sei_itu35_wp, sei_itu35_data_length);
|
||||
#endif
|
||||
user_data_poc.poc_info = READ_VREG(AV_SCRATCH_L);
|
||||
user_data_poc.poc_number = READ_VREG(AV_SCRATCH_M);
|
||||
#ifdef DEBUG_CC_USER_DATA
|
||||
dump_data(sei_itu35_wp, sei_itu35_data_length,
|
||||
user_data_poc.poc_number);
|
||||
#endif
|
||||
if (enable_userdata_debug)
|
||||
udr_dump_data(sei_itu35_wp,
|
||||
sei_itu35_data_length,
|
||||
pts, poc_number);
|
||||
|
||||
|
||||
vh264_add_userdata(meta_info, sei_itu35_wp);
|
||||
|
||||
WRITE_VREG(AV_SCRATCH_J, 0);
|
||||
wakeup_userdata_poll(user_data_poc, sei_itu35_wp,
|
||||
(unsigned long)sei_data_buffer,
|
||||
USER_DATA_SIZE, sei_itu35_data_length);
|
||||
}
|
||||
|
||||
|
||||
@@ -2533,7 +3113,7 @@ static int vh264_local_init(void)
|
||||
pts_discontinue = false;
|
||||
no_idr_error_count = 0;
|
||||
|
||||
reset_userdata_fifo(1);
|
||||
vh264_reset_userdata_fifo(vdec_h264, 1);
|
||||
|
||||
if (enable_switch_fense) {
|
||||
for (i = 0; i < ARRAY_SIZE(fense_buffer_spec); i++) {
|
||||
@@ -3080,6 +3660,11 @@ static int amvdec_h264_probe(struct platform_device *pdev)
|
||||
pdata->dec_status = vh264_dec_status;
|
||||
pdata->set_trickmode = vh264_set_trickmode;
|
||||
pdata->set_isreset = vh264_set_isreset;
|
||||
|
||||
pdata->user_data_read = vh264_user_data_read;
|
||||
pdata->reset_userdata_fifo = vh264_reset_userdata_fifo;
|
||||
pdata->wakeup_userdata_poll = vh264_wakeup_userdata_poll;
|
||||
|
||||
is_reset = 0;
|
||||
clk_adj_frame_count = 0;
|
||||
if (vh264_init() < 0) {
|
||||
@@ -3090,6 +3675,14 @@ static int amvdec_h264_probe(struct platform_device *pdev)
|
||||
mutex_unlock(&vh264_mutex);
|
||||
return -ENODEV;
|
||||
}
|
||||
vdec_h264 = pdata;
|
||||
vh264_crate_userdata_manager(sei_data_buffer, USER_DATA_SIZE);
|
||||
vh264_reset_userdata_fifo(vdec_h264, 1);
|
||||
|
||||
#ifdef DUMP_USER_DATA
|
||||
vh264_init_userdata_dump();
|
||||
vh264_reset_user_data_buf();
|
||||
#endif
|
||||
|
||||
INIT_WORK(&error_wd_work, error_do_work);
|
||||
INIT_WORK(&stream_switching_work, stream_switching_do);
|
||||
@@ -3118,6 +3711,11 @@ static int amvdec_h264_remove(struct platform_device *pdev)
|
||||
mutex_lock(&vh264_mutex);
|
||||
vh264_stop(MODE_FULL);
|
||||
vdec_source_changed(VFORMAT_H264, 0, 0, 0);
|
||||
|
||||
#ifdef DUMP_USER_DATA
|
||||
vh264_dump_userdata();
|
||||
#endif
|
||||
vh264_destroy_userdata_manager();
|
||||
atomic_set(&vh264_active, 0);
|
||||
#ifdef DEBUG_PTS
|
||||
pr_info
|
||||
@@ -3249,6 +3847,11 @@ MODULE_PARM_DESC(bad_block_scale,
|
||||
"\n print bad_block_scale\n");
|
||||
#endif
|
||||
|
||||
module_param(enable_userdata_debug, uint, 0664);
|
||||
MODULE_PARM_DESC(enable_userdata_debug,
|
||||
"\n enable_userdata_debug\n");
|
||||
|
||||
|
||||
module_init(amvdec_h264_driver_init_module);
|
||||
module_exit(amvdec_h264_driver_remove_module);
|
||||
|
||||
|
||||
@@ -479,10 +479,9 @@ static int vh264_vf_states(struct vframe_states *states, void *);
|
||||
static int vh264_event_cb(int type, void *data, void *private_data);
|
||||
static void vh264_work(struct work_struct *work);
|
||||
static void vh264_notify_work(struct work_struct *work);
|
||||
static void user_data_push_work(struct work_struct *work);
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
static void user_data_ready_notify_work(struct work_struct *work);
|
||||
static void vmh264_wakeup_userdata_poll(void);
|
||||
static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec);
|
||||
#endif
|
||||
|
||||
static const char vh264_dec_id[] = "vh264-dev";
|
||||
@@ -617,8 +616,6 @@ struct vdec_h264_hw_s {
|
||||
/* recycle buffer for user data storing all itu35 records */
|
||||
void *sei_user_data_buffer;
|
||||
u32 sei_user_data_wp;
|
||||
int sei_poc;
|
||||
struct work_struct user_data_work;
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
struct work_struct user_data_ready_work;
|
||||
#endif
|
||||
@@ -816,9 +813,7 @@ struct vdec_h264_hw_s {
|
||||
/*user data*/
|
||||
struct mutex userdata_mutex;
|
||||
struct mh264_userdata_info_t userdata_info;
|
||||
struct list_head frame_uds; /*user data records list waiting for vpts*/
|
||||
struct list_head free_uds_wait_nodes; /*free user data records list*/
|
||||
struct mh264_ud_record_wait_node_t free_nodes[MAX_FREE_USERDATA_NODES];
|
||||
struct mh264_userdata_record_t ud_record;
|
||||
int wait_for_udr_send;
|
||||
#endif
|
||||
u32 no_mem_count;
|
||||
@@ -4778,11 +4773,6 @@ static irqreturn_t vh264_isr_thread_fn(struct vdec_s *vdec, int irq)
|
||||
|
||||
if (p_H264_Dpb->mVideo.dec_picture) {
|
||||
int cfg_ret = 0;
|
||||
if (hw->sei_itu_data_len) {
|
||||
hw->sei_poc =
|
||||
p_H264_Dpb->mVideo.dec_picture->poc;
|
||||
schedule_work(&hw->user_data_work);
|
||||
}
|
||||
if (slice_header_process_status == 1) {
|
||||
if ((p_H264_Dpb->mSPS.profile_idc == BASELINE) ||
|
||||
(((unsigned long)(hw->vh264_amstream_dec_info
|
||||
@@ -5216,20 +5206,23 @@ send_again:
|
||||
}
|
||||
|
||||
if (READ_VREG(AV_SCRATCH_G) == 1) {
|
||||
hw->sei_itu_data_len =
|
||||
int aux_data_len;
|
||||
aux_data_len =
|
||||
(READ_VREG(H264_AUX_DATA_SIZE) >> 16) << 4;
|
||||
if (hw->sei_itu_data_len > SEI_ITU_DATA_SIZE * 2) {
|
||||
if (aux_data_len > SEI_ITU_DATA_SIZE * 2) {
|
||||
dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
|
||||
"itu data size more than 4K: %d, discarded it\n",
|
||||
hw->sei_itu_data_len);
|
||||
hw->sei_itu_data_len = 0;
|
||||
aux_data_len);
|
||||
aux_data_len = 0;
|
||||
}
|
||||
|
||||
if (hw->sei_itu_data_len != 0) {
|
||||
if (aux_data_len != 0) {
|
||||
u8 *trans_data_buf;
|
||||
u8 *sei_data_buf;
|
||||
u32 temp;
|
||||
u32 *pswap_data;
|
||||
int new_size;
|
||||
int bContinue;
|
||||
|
||||
dma_sync_single_for_cpu(
|
||||
amports_get_dma_device(),
|
||||
@@ -5241,16 +5234,29 @@ send_again:
|
||||
#endif
|
||||
|
||||
trans_data_buf = (u8 *)hw->aux_addr;
|
||||
sei_data_buf = (u8 *)hw->sei_itu_data_buf;
|
||||
for (i = 0; i < hw->sei_itu_data_len/2; i++)
|
||||
sei_data_buf[i] = trans_data_buf[i*2];
|
||||
hw->sei_itu_data_len = hw->sei_itu_data_len / 2;
|
||||
new_size = hw->sei_itu_data_len + aux_data_len / 2;
|
||||
|
||||
pswap_data = (u32 *)hw->sei_itu_data_buf;
|
||||
for (i = 0; i < hw->sei_itu_data_len/4; i = i+2) {
|
||||
temp = pswap_data[i];
|
||||
pswap_data[i] = pswap_data[i+1];
|
||||
pswap_data[i+1] = temp;
|
||||
bContinue = 1;
|
||||
if (new_size > SEI_ITU_DATA_SIZE) {
|
||||
dpb_print(DECODE_ID(hw), PRINT_FLAG_ERROR,
|
||||
"itu data size over (0x%x, 0x%x), discarded it\n",
|
||||
hw->sei_itu_data_len,
|
||||
new_size);
|
||||
bContinue = 0;
|
||||
}
|
||||
|
||||
if (bContinue) {
|
||||
sei_data_buf = (u8 *)hw->sei_itu_data_buf + hw->sei_itu_data_len;
|
||||
for (i = 0; i < aux_data_len/2; i++)
|
||||
sei_data_buf[i] = trans_data_buf[i*2];
|
||||
hw->sei_itu_data_len += aux_data_len / 2;
|
||||
|
||||
pswap_data = (u32 *)sei_data_buf;
|
||||
for (i = 0; i < aux_data_len/8; i = i+2) {
|
||||
temp = pswap_data[i];
|
||||
pswap_data[i] = pswap_data[i+1];
|
||||
pswap_data[i+1] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
WRITE_VREG(AV_SCRATCH_G, 0);
|
||||
@@ -5943,7 +5949,6 @@ static s32 vh264_init(struct vdec_h264_hw_s *hw)
|
||||
vh264_local_init(hw);
|
||||
INIT_WORK(&hw->work, vh264_work);
|
||||
INIT_WORK(&hw->notify_work, vh264_notify_work);
|
||||
INIT_WORK(&hw->user_data_work, user_data_push_work);
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
INIT_WORK(&hw->user_data_ready_work, user_data_ready_notify_work);
|
||||
#endif
|
||||
@@ -6126,7 +6131,6 @@ static int vh264_stop(struct vdec_h264_hw_s *hw)
|
||||
#endif
|
||||
cancel_work_sync(&hw->work);
|
||||
cancel_work_sync(&hw->notify_work);
|
||||
cancel_work_sync(&hw->user_data_work);
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
cancel_work_sync(&hw->user_data_ready_work);
|
||||
#endif
|
||||
@@ -6210,15 +6214,9 @@ static void vh264_notify_work(struct work_struct *work)
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
static void vmh264_reset_udr_mgr(struct vdec_h264_hw_s *hw)
|
||||
{
|
||||
int i;
|
||||
hw->wait_for_udr_send = 0;
|
||||
|
||||
INIT_LIST_HEAD(&hw->free_uds_wait_nodes);
|
||||
INIT_LIST_HEAD(&hw->frame_uds);
|
||||
|
||||
for (i = 0; i < MAX_FREE_USERDATA_NODES; i++)
|
||||
list_add_tail(&hw->free_nodes[i].list,
|
||||
&hw->free_uds_wait_nodes);
|
||||
hw->sei_itu_data_len = 0;
|
||||
memset(&hw->ud_record, 0, sizeof(hw->ud_record));
|
||||
}
|
||||
|
||||
static void vmh264_crate_userdata_manager(
|
||||
@@ -6522,70 +6520,74 @@ static void vmh264_reset_user_data_buf(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vmh264_input_udc_waitqueue(struct vdec_h264_hw_s *hw,
|
||||
struct userdata_meta_info_t meta_info,
|
||||
int wp)
|
||||
{
|
||||
struct mh264_ud_record_wait_node_t *node;
|
||||
struct mh264_userdata_record_t *p_userdata_rec;
|
||||
int data_length;
|
||||
|
||||
node = list_entry(
|
||||
hw->free_uds_wait_nodes.next,
|
||||
struct mh264_ud_record_wait_node_t,
|
||||
list);
|
||||
|
||||
if (node) {
|
||||
if (wp > hw->userdata_info.last_wp)
|
||||
data_length = wp - hw->userdata_info.last_wp;
|
||||
else
|
||||
data_length = wp + hw->userdata_info.buf_len
|
||||
- hw->userdata_info.last_wp;
|
||||
|
||||
if (data_length & 0x7)
|
||||
data_length = (((data_length + 8) >> 3) << 3);
|
||||
#if 0
|
||||
pr_info("wakeup_push: ri:%d, wi:%d, data_len:%d, last_wp:%d, wp:%d, id = %d\n",
|
||||
lg_p_mpeg12_userdata_info->read_index,
|
||||
lg_p_mpeg12_userdata_info->write_index,
|
||||
data_length,
|
||||
lg_p_mpeg12_userdata_info->last_wp,
|
||||
wp,
|
||||
n_userdata_id);
|
||||
#endif
|
||||
p_userdata_rec = &node->ud_record;
|
||||
p_userdata_rec->meta_info = meta_info;
|
||||
p_userdata_rec->rec_start = hw->userdata_info.last_wp;
|
||||
p_userdata_rec->rec_len = data_length;
|
||||
#if 0
|
||||
dump_userdata_record(hw, p_userdata_rec);
|
||||
#endif
|
||||
list_move(&node->list, &hw->frame_uds);
|
||||
}
|
||||
hw->userdata_info.last_wp = wp;
|
||||
}
|
||||
|
||||
static void vmh264_udc_fill_vpts(struct vdec_h264_hw_s *hw,
|
||||
int frame_type,
|
||||
u32 vpts,
|
||||
u32 vpts_valid)
|
||||
{
|
||||
struct mh264_ud_record_wait_node_t *node;
|
||||
struct mh264_ud_record_wait_node_t *tmp;
|
||||
struct mh264_userdata_record_t *pud_record;
|
||||
struct h264_dpb_stru *p_H264_Dpb = &hw->dpb;
|
||||
|
||||
if (!list_empty(&hw->frame_uds)) {
|
||||
list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) {
|
||||
pud_record = &node->ud_record;
|
||||
pud_record->meta_info.vpts = vpts;
|
||||
pud_record->meta_info.vpts_valid = vpts_valid;
|
||||
pud_record->meta_info.poc_number =
|
||||
p_H264_Dpb->mVideo.dec_picture->poc;
|
||||
}
|
||||
hw->wait_for_udr_send = 1;
|
||||
schedule_work(&hw->user_data_ready_work);
|
||||
unsigned char *pdata;
|
||||
u8 *pmax_sei_data_buffer;
|
||||
u8 *sei_data_buf;
|
||||
int i;
|
||||
int wp;
|
||||
int data_length;
|
||||
struct mh264_userdata_record_t *p_userdata_rec;
|
||||
|
||||
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
struct userdata_meta_info_t meta_info;
|
||||
memset(&meta_info, 0, sizeof(meta_info));
|
||||
#endif
|
||||
|
||||
if (hw->sei_itu_data_len <= 0)
|
||||
return;
|
||||
|
||||
pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp;
|
||||
pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE;
|
||||
sei_data_buf = (u8 *)hw->sei_itu_data_buf;
|
||||
for (i = 0; i < hw->sei_itu_data_len; i++) {
|
||||
*pdata++ = sei_data_buf[i];
|
||||
if (pdata >= pmax_sei_data_buffer)
|
||||
pdata = (u8 *)hw->sei_user_data_buffer;
|
||||
}
|
||||
|
||||
hw->sei_user_data_wp = (hw->sei_user_data_wp
|
||||
+ hw->sei_itu_data_len) % USER_DATA_SIZE;
|
||||
hw->sei_itu_data_len = 0;
|
||||
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
meta_info.duration = hw->frame_dur;
|
||||
meta_info.flags |= (VFORMAT_H264 << 3);
|
||||
|
||||
meta_info.vpts = vpts;
|
||||
meta_info.vpts_valid = vpts_valid;
|
||||
meta_info.poc_number =
|
||||
p_H264_Dpb->mVideo.dec_picture->poc;
|
||||
|
||||
|
||||
wp = hw->sei_user_data_wp;
|
||||
|
||||
if (hw->sei_user_data_wp > hw->userdata_info.last_wp)
|
||||
data_length = wp - hw->userdata_info.last_wp;
|
||||
else
|
||||
data_length = wp + hw->userdata_info.buf_len
|
||||
- hw->userdata_info.last_wp;
|
||||
|
||||
if (data_length & 0x7)
|
||||
data_length = (((data_length + 8) >> 3) << 3);
|
||||
|
||||
p_userdata_rec = &hw->ud_record;
|
||||
p_userdata_rec->meta_info = meta_info;
|
||||
p_userdata_rec->rec_start = hw->userdata_info.last_wp;
|
||||
p_userdata_rec->rec_len = data_length;
|
||||
hw->userdata_info.last_wp = wp;
|
||||
|
||||
hw->wait_for_udr_send = 1;
|
||||
schedule_work(&hw->user_data_ready_work);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -6594,26 +6596,21 @@ static void user_data_ready_notify_work(struct work_struct *work)
|
||||
struct vdec_h264_hw_s *hw = container_of(work,
|
||||
struct vdec_h264_hw_s, user_data_ready_work);
|
||||
|
||||
struct mh264_ud_record_wait_node_t *node;
|
||||
struct mh264_ud_record_wait_node_t *tmp;
|
||||
|
||||
list_for_each_entry_safe(node, tmp, &hw->frame_uds, list) {
|
||||
mutex_lock(&hw->userdata_mutex);
|
||||
mutex_lock(&hw->userdata_mutex);
|
||||
|
||||
hw->userdata_info.records[hw->userdata_info.write_index]
|
||||
= node->ud_record;
|
||||
hw->userdata_info.write_index++;
|
||||
if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM)
|
||||
hw->userdata_info.write_index = 0;
|
||||
hw->userdata_info.records[hw->userdata_info.write_index]
|
||||
= hw->ud_record;
|
||||
hw->userdata_info.write_index++;
|
||||
if (hw->userdata_info.write_index >= USERDATA_FIFO_NUM)
|
||||
hw->userdata_info.write_index = 0;
|
||||
|
||||
mutex_unlock(&hw->userdata_mutex);
|
||||
mutex_unlock(&hw->userdata_mutex);
|
||||
|
||||
list_move(&node->list, &hw->free_uds_wait_nodes);
|
||||
#ifdef DUMP_USERDATA_RECORD
|
||||
dump_userdata_record(hw, &node->ud_record);
|
||||
dump_userdata_record(hw, &hw->ud_record);
|
||||
#endif
|
||||
vdec_wakeup_userdata_poll(hw_to_vdec(hw));
|
||||
}
|
||||
vdec_wakeup_userdata_poll(hw_to_vdec(hw));
|
||||
|
||||
hw->wait_for_udr_send = 0;
|
||||
if (!hw->frmbase_cont_flag) {
|
||||
@@ -6636,13 +6633,12 @@ static int vmh264_user_data_read(struct vdec_s *vdec,
|
||||
struct mh264_userdata_record_t *p_userdata_rec;
|
||||
u32 data_size;
|
||||
u32 res;
|
||||
unsigned long addr;
|
||||
int copy_ok = 1;
|
||||
|
||||
hw = (struct vdec_h264_hw_s *)vdec->private;
|
||||
|
||||
addr = puserdata_para->pbuf_addr;
|
||||
pdest_buf = (void *)addr;
|
||||
pdest_buf = puserdata_para->pbuf_addr;
|
||||
|
||||
mutex_lock(&hw->userdata_mutex);
|
||||
|
||||
/*
|
||||
@@ -6833,56 +6829,13 @@ static void vmh264_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
|
||||
}
|
||||
}
|
||||
|
||||
static void vmh264_wakeup_userdata_poll(void)
|
||||
static void vmh264_wakeup_userdata_poll(struct vdec_s *vdec)
|
||||
{
|
||||
amstream_wakeup_userdata_poll();
|
||||
amstream_wakeup_userdata_poll(vdec);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void user_data_push_work(struct work_struct *work)
|
||||
{
|
||||
struct vdec_h264_hw_s *hw = container_of(work,
|
||||
struct vdec_h264_hw_s, user_data_work);
|
||||
|
||||
struct userdata_poc_info_t user_data_poc;
|
||||
unsigned char *pdata;
|
||||
u8 *pmax_sei_data_buffer;
|
||||
u8 *sei_data_buf;
|
||||
int i;
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
struct userdata_meta_info_t meta_info;
|
||||
memset(&meta_info, 0, sizeof(meta_info));
|
||||
#endif
|
||||
|
||||
pdata = (u8 *)hw->sei_user_data_buffer + hw->sei_user_data_wp;
|
||||
pmax_sei_data_buffer = (u8 *)hw->sei_user_data_buffer + USER_DATA_SIZE;
|
||||
sei_data_buf = (u8 *)hw->sei_itu_data_buf;
|
||||
for (i = 0; i < hw->sei_itu_data_len; i++) {
|
||||
*pdata++ = sei_data_buf[i];
|
||||
if (pdata >= pmax_sei_data_buffer)
|
||||
pdata = (u8 *)hw->sei_user_data_buffer;
|
||||
}
|
||||
|
||||
hw->sei_user_data_wp = (hw->sei_user_data_wp
|
||||
+ hw->sei_itu_data_len) % USER_DATA_SIZE;
|
||||
user_data_poc.poc_number = hw->sei_poc;
|
||||
|
||||
hw->sei_itu_data_len = 0;
|
||||
|
||||
#ifdef MH264_USERDATA_ENABLE
|
||||
meta_info.duration = hw->frame_dur;
|
||||
meta_info.flags |= (VFORMAT_H264 << 3);
|
||||
|
||||
|
||||
vmh264_input_udc_waitqueue(hw, meta_info, hw->sei_user_data_wp);
|
||||
|
||||
#endif
|
||||
/*
|
||||
pr_info("sei_itu35_wp = %d, poc = %d\n",
|
||||
hw->sei_user_data_wp, hw->sei_poc);
|
||||
*/
|
||||
}
|
||||
|
||||
static void vh264_work(struct work_struct *work)
|
||||
{
|
||||
@@ -7496,7 +7449,6 @@ static void reset(struct vdec_s *vdec)
|
||||
|
||||
cancel_work_sync(&hw->work);
|
||||
cancel_work_sync(&hw->notify_work);
|
||||
cancel_work_sync(&hw->user_data_work);
|
||||
if (hw->stat & STAT_VDEC_RUN) {
|
||||
amhevc_stop();
|
||||
hw->stat &= ~STAT_VDEC_RUN;
|
||||
|
||||
@@ -1263,7 +1263,7 @@ static void vmpeg12_ppmgr_reset(void)
|
||||
#endif
|
||||
|
||||
static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit);
|
||||
static void vmpeg12_wakeup_userdata_poll(void);
|
||||
static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec);
|
||||
|
||||
static void reset_do_work(struct work_struct *work)
|
||||
{
|
||||
@@ -1487,15 +1487,12 @@ static int vmpeg12_user_data_read(struct vdec_s *vdec,
|
||||
u8 *rec_data_start;
|
||||
u8 *pdest_buf;
|
||||
struct mpeg12_userdata_recored_t *p_userdata_rec;
|
||||
unsigned long addr;
|
||||
|
||||
|
||||
u32 data_size;
|
||||
u32 res;
|
||||
int copy_ok = 1;
|
||||
|
||||
addr = puserdata_para->pbuf_addr;
|
||||
pdest_buf = (void *)addr;
|
||||
pdest_buf = puserdata_para->pbuf_addr;
|
||||
|
||||
mutex_lock(&userdata_mutex);
|
||||
|
||||
if (!p_userdata_mgr) {
|
||||
@@ -1683,9 +1680,9 @@ static void vmpeg12_reset_userdata_fifo(struct vdec_s *vdec, int bInit)
|
||||
mutex_unlock(&userdata_mutex);
|
||||
}
|
||||
|
||||
static void vmpeg12_wakeup_userdata_poll(void)
|
||||
static void vmpeg12_wakeup_userdata_poll(struct vdec_s *vdec)
|
||||
{
|
||||
amstream_wakeup_userdata_poll();
|
||||
amstream_wakeup_userdata_poll(vdec);
|
||||
}
|
||||
|
||||
static int vmpeg12_vdec_info_init(void)
|
||||
|
||||
@@ -3738,6 +3738,31 @@ struct vdec_s *vdec_get_default_vdec_for_userdata(void)
|
||||
}
|
||||
EXPORT_SYMBOL(vdec_get_default_vdec_for_userdata);
|
||||
|
||||
struct vdec_s *vdec_get_vdec_by_id(int vdec_id)
|
||||
{
|
||||
struct vdec_s *vdec;
|
||||
struct vdec_s *ret_vdec;
|
||||
struct vdec_core_s *core = vdec_core;
|
||||
unsigned long flags;
|
||||
|
||||
flags = vdec_core_lock(vdec_core);
|
||||
|
||||
ret_vdec = NULL;
|
||||
if (!list_empty(&core->connected_vdec_list)) {
|
||||
list_for_each_entry(vdec, &core->connected_vdec_list, list) {
|
||||
if (vdec->id == vdec_id) {
|
||||
ret_vdec = vdec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vdec_core_unlock(vdec_core, flags);
|
||||
|
||||
return ret_vdec;
|
||||
}
|
||||
EXPORT_SYMBOL(vdec_get_vdec_by_id);
|
||||
|
||||
int vdec_read_user_data(struct vdec_s *vdec,
|
||||
struct userdata_param_t *p_userdata_param)
|
||||
{
|
||||
@@ -3756,9 +3781,9 @@ EXPORT_SYMBOL(vdec_read_user_data);
|
||||
|
||||
int vdec_wakeup_userdata_poll(struct vdec_s *vdec)
|
||||
{
|
||||
if (vdec && vdec == vdec_get_default_vdec_for_userdata()) {
|
||||
if (vdec) {
|
||||
if (vdec->wakeup_userdata_poll)
|
||||
vdec->wakeup_userdata_poll();
|
||||
vdec->wakeup_userdata_poll(vdec);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -243,7 +243,7 @@ struct vdec_s {
|
||||
int (*user_data_read)(struct vdec_s *vdec,
|
||||
struct userdata_param_t *puserdata_para);
|
||||
void (*reset_userdata_fifo)(struct vdec_s *vdec, int bInit);
|
||||
void (*wakeup_userdata_poll)(void);
|
||||
void (*wakeup_userdata_poll)(struct vdec_s *vdec);
|
||||
/* private */
|
||||
void *private; /* decoder per instance specific data */
|
||||
#ifdef VDEC_DEBUG_SUPPORT
|
||||
@@ -427,6 +427,8 @@ int vdec_wakeup_userdata_poll(struct vdec_s *vdec);
|
||||
|
||||
void vdec_reset_userdata_fifo(struct vdec_s *vdec, int bInit);
|
||||
|
||||
struct vdec_s *vdec_get_vdec_by_id(int vdec_id);
|
||||
|
||||
#ifdef VDEC_DEBUG_SUPPORT
|
||||
extern void vdec_set_step_mode(void);
|
||||
#endif
|
||||
|
||||
@@ -45,7 +45,7 @@ int amstream_request_firmware_from_sys(const char *file_name,
|
||||
void set_vsync_pts_inc_mode(int inc);
|
||||
|
||||
void set_real_audio_info(void *arg);
|
||||
void amstream_wakeup_userdata_poll(void);
|
||||
void amstream_wakeup_userdata_poll(struct vdec_s *vdec);
|
||||
#define dbg() pr_info("on %s,line %d\n", __func__, __LINE__);
|
||||
|
||||
struct device *amports_get_dma_device(void);
|
||||
|
||||
@@ -323,6 +323,8 @@ static wait_queue_head_t amstream_userdata_wait;
|
||||
static struct userdata_poc_info_t userdata_poc_info[USERDATA_FIFO_NUM];
|
||||
static int userdata_poc_ri, userdata_poc_wi;
|
||||
static int last_read_wi;
|
||||
static u32 ud_ready_vdec_flag;
|
||||
|
||||
|
||||
|
||||
static DEFINE_MUTEX(userdata_mutex);
|
||||
@@ -1411,9 +1413,25 @@ int wakeup_userdata_poll(struct userdata_poc_info_t poc,
|
||||
return userdata_buf->buf_rp;
|
||||
}
|
||||
EXPORT_SYMBOL(wakeup_userdata_poll);
|
||||
void amstream_wakeup_userdata_poll(void)
|
||||
|
||||
|
||||
void amstream_wakeup_userdata_poll(struct vdec_s *vdec)
|
||||
{
|
||||
int vdec_id;
|
||||
|
||||
vdec_id = vdec->id;
|
||||
if (vdec_id > 31) {
|
||||
pr_info("Error, not support so many instances(%d) user data push\n",
|
||||
vdec_id);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&userdata_mutex);
|
||||
ud_ready_vdec_flag |= (1<<vdec_id);
|
||||
|
||||
atomic_set(&userdata_ready, 1);
|
||||
mutex_unlock(&userdata_mutex);
|
||||
|
||||
wake_up_interruptible(&amstream_userdata_wait);
|
||||
}
|
||||
EXPORT_SYMBOL(amstream_wakeup_userdata_poll);
|
||||
@@ -3001,6 +3019,7 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
|
||||
if (this->type & PORT_TYPE_USERDATA) {
|
||||
struct userdata_param_t param;
|
||||
struct userdata_param_t *p_userdata_param;
|
||||
struct vdec_s *vdec;
|
||||
|
||||
p_userdata_param = ¶m;
|
||||
|
||||
@@ -3011,23 +3030,56 @@ static long amstream_do_ioctl_old(struct port_priv_s *priv,
|
||||
break;
|
||||
}
|
||||
|
||||
if (vdec_read_user_data(NULL,
|
||||
p_userdata_param) == 0) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
vdec = vdec_get_vdec_by_id(p_userdata_param->instance_id);
|
||||
if (vdec) {
|
||||
if (vdec_read_user_data(vdec,
|
||||
p_userdata_param) == 0) {
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (copy_to_user((void *)arg,
|
||||
p_userdata_param,
|
||||
sizeof(struct userdata_param_t)))
|
||||
r = -EFAULT;
|
||||
if (copy_to_user((void *)arg,
|
||||
p_userdata_param,
|
||||
sizeof(struct userdata_param_t)))
|
||||
r = -EFAULT;
|
||||
} else
|
||||
r = -EINVAL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case AMSTREAM_IOC_UD_AVAILABLE_VDEC:
|
||||
{
|
||||
unsigned int ready_vdec;
|
||||
|
||||
mutex_lock(&userdata_mutex);
|
||||
ready_vdec = ud_ready_vdec_flag;
|
||||
ud_ready_vdec_flag = 0;
|
||||
mutex_unlock(&userdata_mutex);
|
||||
|
||||
put_user(ready_vdec, (uint32_t __user *)arg);
|
||||
}
|
||||
break;
|
||||
|
||||
case AMSTREAM_IOC_GET_VDEC_ID:
|
||||
if (this->type & PORT_TYPE_VIDEO && priv->vdec) {
|
||||
put_user(priv->vdec->id, (int32_t __user *)arg);
|
||||
} else
|
||||
r = -EINVAL;
|
||||
break;
|
||||
|
||||
|
||||
case AMSTREAM_IOC_UD_FLUSH_USERDATA:
|
||||
if (this->type & PORT_TYPE_USERDATA) {
|
||||
vdec_reset_userdata_fifo(NULL, 0);
|
||||
pr_info("reset_userdata_fifo\n");
|
||||
struct vdec_s *vdec;
|
||||
int vdec_id;
|
||||
|
||||
get_user(vdec_id, (int __user *)arg);
|
||||
vdec = vdec_get_vdec_by_id(vdec_id);
|
||||
if (vdec) {
|
||||
vdec_reset_userdata_fifo(vdec, 0);
|
||||
pr_info("reset_userdata_fifo for vdec: %d\n", vdec_id);
|
||||
}
|
||||
} else
|
||||
r = -EINVAL;
|
||||
break;
|
||||
@@ -3343,6 +3395,60 @@ static long amstream_set_sysinfo(struct port_priv_s *priv,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct userdata_param32_t {
|
||||
uint32_t version;
|
||||
uint32_t instance_id; /*input, 0~9*/
|
||||
uint32_t buf_len; /*input*/
|
||||
uint32_t data_size; /*output*/
|
||||
compat_uptr_t pbuf_addr; /*input*/
|
||||
struct userdata_meta_info_t meta_info; /*output*/
|
||||
};
|
||||
|
||||
|
||||
static long amstream_ioc_get_userdata(struct port_priv_s *priv,
|
||||
struct userdata_param32_t __user *arg)
|
||||
{
|
||||
struct userdata_param_t __user *data;
|
||||
struct userdata_param32_t __user *data32 = arg;
|
||||
int ret;
|
||||
struct userdata_param32_t param;
|
||||
|
||||
|
||||
if (copy_from_user(¶m,
|
||||
(void __user *)arg,
|
||||
sizeof(struct userdata_param32_t)))
|
||||
return -EFAULT;
|
||||
|
||||
data = compat_alloc_user_space(sizeof(*data));
|
||||
if (!access_ok(VERIFY_WRITE, data, sizeof(*data)))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_in_user(data, data32, 4 * sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_in_user(&data->meta_info, &data32->meta_info,
|
||||
sizeof(data->meta_info)))
|
||||
return -EFAULT;
|
||||
|
||||
if (put_user(compat_ptr(param.pbuf_addr), &data->pbuf_addr))
|
||||
return -EFAULT;
|
||||
|
||||
ret = amstream_do_ioctl(priv, AMSTREAM_IOC_UD_BUF_READ,
|
||||
(unsigned long)data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (copy_in_user(&data32->version, &data->version, 4 * sizeof(u32)) ||
|
||||
copy_in_user(&data32->meta_info, &data->meta_info,
|
||||
sizeof(data32->meta_info)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static long amstream_compat_ioctl(struct file *file,
|
||||
unsigned int cmd, ulong arg)
|
||||
{
|
||||
@@ -3361,6 +3467,8 @@ static long amstream_compat_ioctl(struct file *file,
|
||||
return amstream_ioc_setget_ptr(priv, cmd, compat_ptr(arg));
|
||||
case AMSTREAM_IOC_SYSINFO:
|
||||
return amstream_set_sysinfo(priv, compat_ptr(arg));
|
||||
case AMSTREAM_IOC_UD_BUF_READ:
|
||||
return amstream_ioc_get_userdata(priv, compat_ptr(arg));
|
||||
default:
|
||||
return amstream_do_ioctl(priv, cmd, (ulong)compat_ptr(arg));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user