Files
BPI-CM9-Linux/aml-comp/vendor/amlogic/ccdatabase/server/dataserver_reader_userdata.c
T

240 lines
6.8 KiB
C
Raw Normal View History

2026-08-13 11:28:40 +08:00
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <errno.h>
#include "dataserver_reader_inner.h"
#ifdef LOG_LOGCAT
#define LOG_TAG "ccdataserver"
#include <log/log.h>
#define ds_inf(_fmt_,...) ALOGI("%s:%d "_fmt_, __func__, __LINE__, ##__VA_ARGS__)
#define ds_err(_fmt_,...) ALOGE("%s:%d "_fmt_, __func__, __LINE__, ##__VA_ARGS__)
#else
#define ds_inf(_fmt_,...) printf("I %s:%d "_fmt_"\n", __func__, __LINE__, ##__VA_ARGS__)
#define ds_err(_fmt_,...) printf("E %s:%d "_fmt_"\n", __func__, __LINE__, ##__VA_ARGS__)
#endif
struct userdata_meta_info_t {
uint32_t poc_number;
/************ flags bit definition ***********
bit 0: //used for mpeg2
1, group start
0, not group start
bit 1-2: //used for mpeg2
0, extension_and_user_data( 0 )
1, extension_and_user_data( 1 )
2, extension_and_user_data( 2 )
bit 3-6: //video format
0, VFORMAT_MPEG12
1, VFORMAT_MPEG4
2, VFORMAT_H264
3, VFORMAT_MJPEG
4, VFORMAT_REAL
5, VFORMAT_JPEG
6, VFORMAT_VC1
7, VFORMAT_AVS
8, VFORMAT_SW
9, VFORMAT_H264MVC
10, VFORMAT_H264_4K2K
11, VFORMAT_HEVC
12, VFORMAT_H264_ENC
13, VFORMAT_JPEG_ENC
14, VFORMAT_VP9
bit 7-9: //frame type
0, Unknown Frame Type
1, I Frame
2, B Frame
3, P Frame
4, D_Type_MPEG2
bit 10: //top_field_first_flag valid
0: top_field_first_flag is not valid
1: top_field_first_flag is valid
bit 11: //top_field_first bit val
bit 12-13: //picture_struct, used for H264
0: Invalid
1: TOP_FIELD_PICTURE
2: BOT_FIELD_PICTURE
3: FRAME_PICTURE
**********************************************/
uint32_t flags;
uint32_t vpts; /*video frame pts*/
/******************************************
0: pts is invalid, please use duration to calculate
1: pts is valid
******************************************/
uint32_t vpts_valid;
/*duration for frame*/
uint32_t duration;
/* how many records left in queue waiting to be read*/
uint32_t records_in_que;
unsigned long long priv_data;
uint64_t vpts_64; /*valid only if version == 2*/
uint32_t padding_data[2];
};
struct userdata_param_t {
uint32_t version;
uint32_t instance_id; /*input, 0~9*/
uint32_t buf_len; /*input*/
uint32_t data_size; /*output*/
void* pbuf_addr; /*input*/
struct userdata_meta_info_t meta_info; /*output*/
};
#define AMSTREAM_IOC_MAGIC 'S'
#define AMSTREAM_IOC_UD_FLUSH_USERDATA _IOR(AMSTREAM_IOC_MAGIC, 0x56, int)
#define AMSTREAM_IOC_UD_BUF_READ _IOR(AMSTREAM_IOC_MAGIC, 0x57, int)
#define AMSTREAM_IOC_UD_AVAILABLE_VDEC _IOR(AMSTREAM_IOC_MAGIC, 0x5c, unsigned int)
#define USERDATA_POLL_TIMEOUT 100
static void *ds_userdata_read_task(void *args)
{
reader_inst_t *inst = (reader_inst_t *)args;
ds_inf("userdata read task started");
uint8_t buf[5 * 1024 + 4];
int flush = 1;
while (inst->running) {
struct pollfd pfd[2];
int ret;
pfd[0].fd = inst->fd;
pfd[1].fd = inst->evtfd;
pfd[0].events = pfd[1].events = POLLIN | POLLERR;
ret = poll(pfd, 2, USERDATA_POLL_TIMEOUT);
if (!inst->running || ret <= 0 || !(pfd[0].events & POLLIN))
continue;
int vdec_ids = 0;
ret = ioctl(inst->fd, AMSTREAM_IOC_UD_AVAILABLE_VDEC, &vdec_ids);
if (ret == -1) {
ds_err("ioctl AVAILABLE_VDECS fail, err(%d/%s)", errno, strerror(errno));
}
int vdec_id = vdec_ids;
/*drop the data not current vid*/
if (vdec_id != inst->priv)
continue;
if (flush) {
ret = ioctl(inst->fd, AMSTREAM_IOC_UD_FLUSH_USERDATA, &vdec_id);
if (ret == -1) {
ds_inf("ioctl FLUSH_USERDATA %d, err(%d/%s)", vdec_id, errno, strerror(errno));
}
flush = 0;
}
struct userdata_param_t user_para_info;
do {
memset(&user_para_info, 0, sizeof(struct userdata_param_t));
user_para_info.pbuf_addr = (void*)(size_t)buf;
user_para_info.buf_len = sizeof(buf);
user_para_info.instance_id = vdec_id;
ret = ioctl(inst->fd, AMSTREAM_IOC_UD_BUF_READ, &user_para_info);
if (ret == -1) {
ds_err("ioctl READ fail, err(%d/%s)", errno, strerror(errno));
continue;
}
if (user_para_info.data_size <= 0)
continue;
#define MAX_CC_DATA_LEN (1024*5 + 4)
if (user_para_info.data_size > MAX_CC_DATA_LEN)
user_para_info.data_size = MAX_CC_DATA_LEN;
/*callback the data*/
{
ds_data_callback_t *cb;
pthread_mutex_lock(&inst->callback_list_lock);
/*move the waiting callbacks to main list*/
if (!list_empty(&inst->callback_wait_list)) {
struct list_head *pos, *tmp;
list_for_each_safe(pos, tmp, &inst->callback_wait_list) {
list_del(pos);
list_add_tail(pos, &inst->callback_list);
}
}
list_for_each_entry(cb, &inst->callback_list, head) {
cb->fn.data_cb((uint8_t *)&user_para_info, sizeof(user_para_info), cb->priv);
cb->fn.data_cb(buf, user_para_info.data_size, cb->priv);
cb->fn.ready_cb(1/*blk mode*/, sizeof(user_para_info) + user_para_info.data_size, cb->priv);
ds_inf("userdata: %zd+%d", sizeof(user_para_info), user_para_info.data_size);
}
pthread_mutex_unlock(&inst->callback_list_lock);
}
} while (user_para_info.meta_info.records_in_que > 1);
}
ds_inf("userdata read task exit");
return 0;
}
static int ds_userdata_set(reader_inst_t *inst, const char *settings)
{
(void)inst;
int ret = 0;
char *set = "src_para_userdata_vid";
int len = strlen(set);
if (!settings)
return ret;
if (strncmp(settings, set, len) == 0) {
int vid = 1;
if (sscanf(settings, "%*s %d", &vid) == 1) {
ds_inf("userdata vid set:%d", vid);
inst->priv = vid;
} else {
ds_err("userdata vid set fail");
ret = -1;
}
}
return ret;
}
static ds_reader_t userdata_reader = {
.task = ds_userdata_read_task,
.set = ds_userdata_set,
};
static ds_reader_t* ds_userdata_reader_check(const char *devname)
{
if (strcmp(devname, "/dev/amstream_userdata") == 0)
return &userdata_reader;
return NULL;
}
REG_DS_READER(ds_userdata_reader_check);