Files
2026-08-24 10:03:24 +08:00

961 lines
28 KiB
C

/*
* Copyright (c) 2014 Amlogic, Inc. All rights reserved.
*
* This source code is subject to the terms and conditions defined in the
* file 'LICENSE' which is part of this source code package.
*
* Description:
*/
/**
* @file codec_ctrl.c
* @brief Codec control lib functions
*
* @version 1.0.0
* @date 2011-02-24
*/
/* Copyright (C) 2007-2011, Amlogic Inc.
* All right reserved
*
*/
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include "vcodec.h"
#ifdef ANDROID
#include <android/log.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#define LOG_TAG "amcodec"
#define CODEC_PRINT(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#else
#define CODEC_PRINT(f,s...) fprintf(stderr,f,##s)
#endif
#define msleep(n) usleep(n*1000)
// ports
#define CODEC_VIDEO_ES_DEVICE "/dev/amstream_vbuf"
#define CODEC_VIDEO_ES_DEVICE_SCHED "/dev/amstream_vbuf_sched"
#define CODEC_VIDEO_ES_HEVC_DEVICE_SCHED "/dev/amstream_hevc_sched"
#define CODEC_TS_DEVICE "/dev/amstream_mpts"
#define CODEC_PS_DEVICE "/dev/amstream_mpps"
#define CODEC_RM_DEVICE "/dev/amstream_rm"
#define CODEC_VIDEO_HEVC_DEVICE "/dev/amstream_hevc"
#define CODEC_VIDEO_DVAVC_DEVICE "/dev/amstream_dves_avc"
#define CODEC_VIDEO_DVHEVC_DEVICE "/dev/amstream_dves_hevc"
#define CODEC_CNTL_DEVICE "/dev/amvideo"
#define CODEC_VIDEO_FRAME_DEVICE "/dev/amstream_vframe"
#define CODEC_HEVC_FRAME_DEVICE "/dev/amstream_hevc_frame"
/*#define CODEC_VIDEO_DVAV1_DEVICE "/dev/amstream_dves_av1"*/
// ioctl
#define AMSTREAM_IOC_MAGIC 'S'
#define AMSTREAM_IOC_VB_SIZE _IOW((AMSTREAM_IOC_MAGIC), 0x01, int)
#define AMSTREAM_IOC_VFORMAT _IOW((AMSTREAM_IOC_MAGIC), 0x04, int)
#define AMSTREAM_IOC_VID _IOW((AMSTREAM_IOC_MAGIC), 0x06, int)
#define AMSTREAM_IOC_VB_STATUS _IOR((AMSTREAM_IOC_MAGIC), 0x08, int)
#define AMSTREAM_IOC_SYSINFO _IOW((AMSTREAM_IOC_MAGIC), 0x0a, int)
#define AMSTREAM_IOC_PORT_INIT _IO((AMSTREAM_IOC_MAGIC), 0x11)
#define AMSTREAM_IOC_VPAUSE _IOW((AMSTREAM_IOC_MAGIC), 0x17, int)
#define AMSTREAM_IOC_SET_DRMMODE _IOW((AMSTREAM_IOC_MAGIC), 0x91, int)
#define AMSTREAM_IOC_GET_VERSION _IOR((AMSTREAM_IOC_MAGIC), 0xc0, int)
#define AMSTREAM_IOC_GET _IOWR((AMSTREAM_IOC_MAGIC), 0xc1, struct am_ioctl_parm)
#define AMSTREAM_IOC_SET _IOW((AMSTREAM_IOC_MAGIC), 0xc2, struct am_ioctl_parm)
#define AMSTREAM_IOC_GET_EX _IOWR((AMSTREAM_IOC_MAGIC), 0xc3, struct am_ioctl_parm_ex)
#define AMSTREAM_IOC_SET_CRC _IOW((AMSTREAM_IOC_MAGIC), 0xc9, struct usr_crc_info_t)
#define AMSTREAM_IOC_GET_CRC_CMP_RESULT _IOWR((AMSTREAM_IOC_MAGIC), 0xca, int)
// cmds
#define AMSTREAM_SET_VB_SIZE 0x102
#define AMSTREAM_SET_VFORMAT 0x105
#define AMSTREAM_SET_VID 0x107
#define AMSTREAM_PORT_INIT 0x111
#define AMSTREAM_SET_DRMMODE 0x11C
#define AMSTREAM_GET_EX_VB_STATUS 0x900
#define AMSTREAM_GET_EX_VDECSTAT 0x902
struct am_ioctl_parm {
union {
unsigned int data_32;
unsigned long long data_64;
int data_vformat;
char data[8];
};
unsigned int cmd;
char reserved[4];
};
struct am_io_param {
union {
int data;
int id;
};
int len;
union {
char buf[1];
struct buf_status status;
};
};
struct am_ioctl_parm_ex {
union {
struct buf_status status;
struct vdec_status vstatus;
char data[24];
};
unsigned int cmd;
char reserved[4];
};
struct vcodec_amd_table {
unsigned int cmd;
unsigned int parm_cmd;
};
static struct vcodec_amd_table cmd_tables[] = {
/*amstream*/
{ AMSTREAM_IOC_VB_SIZE, AMSTREAM_SET_VB_SIZE },
{ AMSTREAM_IOC_VFORMAT, AMSTREAM_SET_VFORMAT },
{ AMSTREAM_IOC_VID, AMSTREAM_SET_VID },
{ AMSTREAM_IOC_VB_STATUS, AMSTREAM_GET_EX_VB_STATUS },
{ AMSTREAM_IOC_PORT_INIT, AMSTREAM_PORT_INIT },
{ AMSTREAM_IOC_SET_DRMMODE, AMSTREAM_SET_DRMMODE },
{ 0, 0 },
};
static int support_new_cmd = 0;
static void vcodec_h_set_support_new_cmd(int value)
{
support_new_cmd = value;
}
static int vcodec_h_is_support_new_cmd()
{
return support_new_cmd;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_h_open Open codec devices by file name
*
* @param[in] port_addr File name of codec device
* @param[in] flags Open flags
*
* @return The handler of codec device
*/
/* --------------------------------------------------------------------------*/
static int vcodec_h_open(const char *port_addr, int flags)
{
int r;
int retry_open_times = 0;
retry_open:
r = open(port_addr, flags);
if (r < 0 /*&& r == EBUSY */) {
//--------------------------------
retry_open_times++;
if (retry_open_times == 1) {
CODEC_PRINT("Init [%s] failed,ret = %d error=%d retry_open!\n", port_addr, r, errno);
}
msleep(10);
if (retry_open_times < 1000) {
goto retry_open;
}
CODEC_PRINT("retry_open [%s] failed,ret = %d error=%d used_times=%d*10(ms)\n", port_addr, r, errno, retry_open_times);
//--------------------------------
//CODEC_PRINT("Init [%s] failed,ret = %d error=%d\n", port_addr, r, errno);
return r;
}
if (retry_open_times > 0) {
CODEC_PRINT("retry_open [%s] success,ret = %d error=%d used_times=%d*10(ms)\n", port_addr, r, errno, retry_open_times);
}
return (int)r;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_h_close Close codec devices
*
* @param[in] h Handler of codec device
*
* @return 0 for success
*/
/* --------------------------------------------------------------------------*/
static int vcodec_h_close(int h)
{
int r;
if (h >= 0) {
r = close(h);
if (r < 0) {
CODEC_PRINT("close failed,handle=%d,ret=%d errno=%d\n", h, r, errno);
}
}
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_h_control IOCTL commands for codec devices
*
* @param[in] h Codec device handler
* @param[in] cmd IOCTL commands
* @param[in] parameter IOCTL commands parameter
*
* @return 0 for success, non-0 for fail
*/
/* --------------------------------------------------------------------------*/
static int vcodec_h_control(int h, int cmd, unsigned long parameter)
{
int r;
if (h < 0) {
return -1;
}
r = ioctl(h, cmd, parameter);
if (r < 0) {
CODEC_PRINT("send control failed,handle=%d,cmd=%x,parameter=%lx, t=%x errno=%d\n", h, cmd, parameter, r, errno);
return r;
}
return 0;
}
static int vcodec_h_ioctl_set(int h, int subcmd, unsigned long parameter)
{
int r;
int cmd_new = AMSTREAM_IOC_SET;
unsigned long parm_new;
switch (subcmd) {
case AMSTREAM_SET_VB_SIZE:
case AMSTREAM_SET_VID:
case AMSTREAM_SET_DRMMODE: {
struct am_ioctl_parm parm;
memset(&parm, 0, sizeof(parm));
parm.cmd = subcmd;
parm.data_32 = parameter;
parm_new = (unsigned long)&parm;
r = ioctl(h, cmd_new, parm_new);
}
break;
case AMSTREAM_SET_VFORMAT: {
struct am_ioctl_parm parm;
memset(&parm, 0, sizeof(parm));
parm.cmd = subcmd;
parm.data_vformat = parameter;
parm_new = (unsigned long)&parm;
r = ioctl(h, cmd_new, parm_new);
}
break;
case AMSTREAM_PORT_INIT: {
struct am_ioctl_parm parm;
memset(&parm, 0, sizeof(parm));
parm.cmd = subcmd;
parm_new = (unsigned long)&parm;
r = ioctl(h, cmd_new, parm_new);
}
break;
default: {
struct am_ioctl_parm parm;
memset(&parm, 0, sizeof(parm));
parm.cmd = subcmd;
parm.data_32 = parameter;
parm_new = (unsigned long)&parm;
r = ioctl(h, cmd_new, parm_new);
}
break;
}
if (r < 0) {
CODEC_PRINT("vcodec_h_ioctl_set failed,handle=%d,cmd=%x,parameter=%lx, t=%x errno=%d\n", h, subcmd, parameter, r, errno);
return r;
}
return 0;
}
static int vcodec_h_ioctl_get(int h, int subcmd, unsigned long parameter)
{
int r;
struct am_ioctl_parm parm;
unsigned long parm_new;
memset(&parm, 0, sizeof(parm));
parm.cmd = subcmd;
parm.data_32 = *(unsigned int *)parameter;
parm_new = (unsigned long)&parm;
r = ioctl(h, AMSTREAM_IOC_GET, parm_new);
if (r < 0) {
CODEC_PRINT("vcodec_h_ioctl_get failed,handle=%d,subcmd=%x,parameter=%lx, t=%x errno=%d\n", h, subcmd, parameter, r, errno);
return r;
}
if (parameter != 0) {
*(unsigned int *)parameter = parm.data_32;
}
return 0;
}
static int get_old_cmd(unsigned int cmd)
{
struct vcodec_amd_table *p;
for (p = cmd_tables; p->cmd; p++) {
if (p->parm_cmd == cmd) {
return p->cmd;
}
}
return -1;
}
static int vcodec_h_ioctl_get_ex(int h, int subcmd, unsigned long parameter)
{
int r;
int cmd_new = AMSTREAM_IOC_GET_EX;
unsigned long parm_new;
switch (subcmd) {
case AMSTREAM_GET_EX_VB_STATUS: {
struct am_ioctl_parm_ex parm;
memset(&parm, 0, sizeof(parm));
parm.cmd = subcmd;
parm_new = (unsigned long)&parm;
r = ioctl(h, cmd_new, parm_new);
if (r >= 0 && parameter != 0) {
memcpy((void *)parameter, &parm.status, sizeof(struct buf_status));
}
}
break;
case AMSTREAM_GET_EX_VDECSTAT: {
struct am_ioctl_parm_ex parm;
memset(&parm, 0, sizeof(parm));
parm.cmd = subcmd;
parm_new = (unsigned long)&parm;
r = ioctl(h, cmd_new, parm_new);
if (r >= 0 && parameter != 0) {
memcpy((void *)parameter, &parm.vstatus, sizeof(struct vdec_status));
}
}
break;
default:
r = -1;
break;
}
if (r < 0) {
CODEC_PRINT("vcodec_h_ioctl_get_ex failed,handle=%d,subcmd=%x,parameter=%lx, t=%x errno=%d\n", h, subcmd, parameter, r, errno);
return r;
}
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_h_control IOCTL commands for codec devices
*
* @param[in] h Codec device handler
* @param[in] cmd IOCTL commands
* @param[in] parameter IOCTL commands parameter
*
* @return 0 for success, non-0 for fail
*/
/* --------------------------------------------------------------------------*/
static int vcodec_h_ioctl(int h, unsigned int cmd, unsigned int subcmd, unsigned long parameter)
{
int r;
if (h < 0) {
return -1;
}
if (!vcodec_h_is_support_new_cmd()) {
int old_cmd = get_old_cmd(subcmd);
if (old_cmd == -1) {
return -1;
}
return vcodec_h_control(h, old_cmd, parameter);
}
switch (cmd) {
case AMSTREAM_IOC_SET:
r = vcodec_h_ioctl_set(h, subcmd, parameter);
break;
case AMSTREAM_IOC_GET:
r = vcodec_h_ioctl_get(h, subcmd, parameter);
break;
case AMSTREAM_IOC_GET_EX:
r = vcodec_h_ioctl_get_ex(h, subcmd, parameter);
break;
default:
r = ioctl(h, cmd, parameter);
break;
}
if (r < 0) {
CODEC_PRINT("vcodec_h_ioctl failed,handle=%d,cmd=%x,subcmd=%x, parameter=%lx, t=%x errno=%d\n", h, cmd, subcmd, parameter, r, errno);
return r;
}
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_h_read Read data from codec devices
*
* @param[in] handle Codec device handler
* @param[out] buffer Buffer for the data read from codec device
* @param[in] size Size of the data to be read
*
* @return read length or fail if < 0
*/
/* --------------------------------------------------------------------------*/
static int vcodec_h_read(int handle, void *buffer, int size)
{
int r;
r = read(handle, buffer, size);
if (r < 0) {
CODEC_PRINT("read failed,handle=%d,ret=%d errno=%d\n", handle, r, errno);
}
return r;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_h_write Write data to codec devices
*
* @param[in] handle Codec device handler
* @param[out] buffer Buffer for the data to be written to codec device
* @param[in] size Size of the data to be written
*
* @return write length or fail if < 0
*/
/* --------------------------------------------------------------------------*/
static int vcodec_h_write(int handle, void *buffer, int size)
{
int r;
r = write(handle, buffer, size);
if (r < 0 && errno != EAGAIN) {
CODEC_PRINT("write failed,handle=%d,ret=%d errno=%d\n", handle, r, errno);
}
return r;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_change_buf_size Change buffer size of codec device
*
* @param[in] pcodec Pointer of codec parameter structure
*
* @return Success of fail error type
*/
/* --------------------------------------------------------------------------*/
static int vcodec_change_buf_size(vcodec_para_t *pcodec)
{
int r;
if (pcodec->vbuf_size > 0) {
r = vcodec_h_ioctl(pcodec->handle, AMSTREAM_IOC_SET, AMSTREAM_SET_VB_SIZE, pcodec->vbuf_size);
if (r < 0) {
return r;
}
}
return CODEC_ERROR_NONE;
}
/* --------------------------------------------------------------------------*/
/**
* @brief set_video_format Set video format to codec device
*
* @param[in] pcodec Pointer of codec parameter structure
*
* @return 0 for success, or error type
*/
/* --------------------------------------------------------------------------*/
static int set_video_format(vcodec_para_t *pcodec)
{
int format = pcodec->video_type;
int r;
if (format < 0 || format > VFORMAT_MAX) {
return -CODEC_ERROR_VIDEO_TYPE_UNKNOWN;
}
r = vcodec_h_ioctl(pcodec->handle, AMSTREAM_IOC_SET, AMSTREAM_SET_VFORMAT, format);
if (pcodec->video_pid >= 0) {
r = vcodec_h_ioctl(pcodec->handle, AMSTREAM_IOC_SET, AMSTREAM_SET_VID, pcodec->video_pid);
if (r < 0) {
return r;
}
}
if (r < 0) {
return r;
}
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief set_video_vcodec_info Set video information(width, height...) to codec device
*
* @param[in] pcodec Pointer of codec parameter structure
*
* @return 0 for success, or error type
*/
/* --------------------------------------------------------------------------*/
static int set_video_codec_info(vcodec_para_t *pcodec)
{
dec_sysinfo_t am_sysinfo = pcodec->am_sysinfo;
int r;
r = vcodec_h_control(pcodec->handle, AMSTREAM_IOC_SYSINFO, (unsigned long)&am_sysinfo);
if (r < 0) {
return r;
}
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_check_new_cmd Check new cmd for ioctl
*
*/
/* --------------------------------------------------------------------------*/
static inline void vcodec_check_new_cmd(int handle)
{
if (!vcodec_h_is_support_new_cmd()) {
int r;
int version = 0;
r = vcodec_h_control(handle, AMSTREAM_IOC_GET_VERSION, (unsigned long)&version);
if ((r == 0) && (version >= 0x20000)) {
CODEC_PRINT("vcodec_init amstream version : %d.%d\n", (version & 0xffff0000) >> 16, version & 0xffff);
vcodec_h_set_support_new_cmd(1);
} else {
CODEC_PRINT("vcodec_init amstream use old cmd\n");
vcodec_h_set_support_new_cmd(0);
}
}
}
static int vcodec_set_drmmode(vcodec_para_t *pcodec, unsigned int setval)
{
return vcodec_h_ioctl(pcodec->handle, AMSTREAM_IOC_SET, AMSTREAM_SET_DRMMODE, setval);
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_get_vbuf_state Get the state of video buffer by codec device
*
* @param[in] p Pointer of codec parameter structure
* @param[out] buf Pointer of buffer status structure to get video buffer state
*
* @return Success or fail type
*/
/* --------------------------------------------------------------------------*/
int vcodec_get_vbuf_state(vcodec_para_t *p, struct buf_status *buf)
{
int r;
if (vcodec_h_is_support_new_cmd()) {
struct buf_status status;
r = vcodec_h_ioctl(p->handle, AMSTREAM_IOC_GET_EX, AMSTREAM_GET_EX_VB_STATUS, (unsigned long)&status);
memcpy(buf, &status, sizeof(*buf));
} else {
struct am_io_param am_io;
r = vcodec_h_control(p->handle, AMSTREAM_IOC_VB_STATUS, (unsigned long)&am_io);
memcpy(buf, &am_io.status, sizeof(*buf));
}
return r;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_video_es_init Initialize the codec device for es video
*
* @param[in] pcodec Pointer of codec parameter structure
* sched Chose single mode device or stream mode device
*
* @return Success or fail error type
*/
/* --------------------------------------------------------------------------*/
static inline int vcodec_video_es_init(vcodec_para_t *pcodec, int sched)
{
int handle;
int r;
int codec_r;
int flags = O_WRONLY;
char *amstream_dev = CODEC_VIDEO_ES_DEVICE;
if (!pcodec->has_video) {
return CODEC_ERROR_NONE;
}
flags |= pcodec->noblock ? O_NONBLOCK : 0;
if (pcodec->video_type == VFORMAT_AV1) {
if (sched == FRAME_MODE)
amstream_dev = CODEC_HEVC_FRAME_DEVICE; //av1 hevc frame mode
else
amstream_dev = CODEC_VIDEO_HEVC_DEVICE;
} else if (pcodec->video_type == VFORMAT_HEVC ||
pcodec->video_type == VFORMAT_VP9 ||
pcodec->video_type == VFORMAT_AVS2 ||
pcodec->video_type == VFORMAT_AVS3 ||
pcodec->video_type == VFORMAT_H266) {
if (sched != SINGLE_MODE)
amstream_dev = CODEC_VIDEO_ES_HEVC_DEVICE_SCHED;
else
amstream_dev = CODEC_VIDEO_HEVC_DEVICE;
if ((pcodec->amld_enable) && (pcodec->video_type == VFORMAT_HEVC))
amstream_dev = CODEC_VIDEO_DVHEVC_DEVICE;
} else {
if ((pcodec->video_type == VFORMAT_H264) ||
(pcodec->video_type == VFORMAT_MPEG12) ||
(pcodec->video_type == VFORMAT_MPEG4) ||
(pcodec->video_type == VFORMAT_MJPEG)) {
if (sched != SINGLE_MODE)
amstream_dev = CODEC_VIDEO_ES_DEVICE_SCHED;
else
amstream_dev = CODEC_VIDEO_ES_DEVICE;
} else
amstream_dev = CODEC_VIDEO_ES_DEVICE;
if (pcodec->video_type == VFORMAT_H264 && pcodec->amld_enable)
amstream_dev = CODEC_VIDEO_DVAVC_DEVICE;
}
printf("vcodec open device %s \n", amstream_dev);
handle = vcodec_h_open(amstream_dev, flags);
if (handle < 0) {
return CODEC_OPEN_HANDLE_FAILED;
}
pcodec->handle = handle;
vcodec_check_new_cmd(handle);
r = set_video_format(pcodec);
if (r < 0) {
vcodec_h_close(handle);
codec_r = r;
CODEC_PRINT("%d,%s,%d\n", errno, __FUNCTION__, __LINE__);
return codec_r;
}
r = set_video_codec_info(pcodec);
if (r < 0) {
vcodec_h_close(handle);
codec_r = r;
CODEC_PRINT("%d,%s,%d\n", errno, __FUNCTION__, __LINE__);
return codec_r;
}
r = vcodec_set_drmmode(pcodec, pcodec->drmmode);
if (r < 0) {
vcodec_h_close(handle);
codec_r = r;
CODEC_PRINT("%d,%s,%d\n", errno, __FUNCTION__, __LINE__);
return codec_r;
}
return CODEC_ERROR_NONE;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_init Initialize the codec device based on stream type
*
* @param[in] pcodec Pointer of codec parameter structure
*
* @return Success or fail error type
*/
/* --------------------------------------------------------------------------*/
int vcodec_init(vcodec_para_t *pcodec)
{
int ret;
pcodec->handle = -1;
pcodec->cntl_handle = -1;
switch (pcodec->stream_type) {
case STREAM_TYPE_ES_VIDEO:
ret = vcodec_video_es_init(pcodec, pcodec->mode);
break;
case STREAM_TYPE_UNKNOWN:
default:
return -CODEC_ERROR_STREAM_TYPE_UNKNOWN;
}
if (ret != 0) {
return ret;
}
ret = vcodec_init_cntl(pcodec);
if (ret != CODEC_ERROR_NONE) {
return ret;
}
ret = vcodec_change_buf_size(pcodec);
if (ret != 0) {
return -CODEC_ERROR_SET_BUFSIZE_FAILED;
}
ret = vcodec_h_ioctl(pcodec->handle, AMSTREAM_IOC_SET, AMSTREAM_PORT_INIT, 0);
if (ret != 0) {
return -CODEC_ERROR_INIT_FAILED;
}
return ret;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_write Write data to codec device
*
* @param[in] pcodec Pointer of codec parameter structure
* @param[in] buffer Buffer for data to be written
* @param[in] len Length of the data to be written
*
* @return Length of the written data, or fail if < 0
*/
/* --------------------------------------------------------------------------*/
int vcodec_write(vcodec_para_t *pcodec, void *buffer, int len)
{
return vcodec_h_write(pcodec->handle, buffer, len);
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_read Read data from codec device
*
* @param[in] pcodec Pointer of codec parameter structure
* @param[out] buffer Buffer for data read from codec device
* @param[in] len Length of the data to be read
*
* @return Length of the read data, or fail if < 0
*/
/* --------------------------------------------------------------------------*/
int vcodec_read(vcodec_para_t *pcodec, void *buffer, int len)
{
return vcodec_h_read(pcodec->handle, buffer, len);
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_close Close codec device
*
* @param[in] pcodec Pointer of codec parameter structure
*
* @return 0 for success, or fail type if < 0
*/
/* --------------------------------------------------------------------------*/
int vcodec_close(vcodec_para_t *pcodec)
{
int res = 0;
res |= vcodec_close_cntl(pcodec);
res |= vcodec_h_close(pcodec->handle);
return res;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_pause Pause all playing(A/V) by codec device
*
* @param[in] p Pointer of codec parameter structure
*
* @return Success or fail error type
*/
/* --------------------------------------------------------------------------*/
int vcodec_pause(vcodec_para_t *p)
{
int ret = CODEC_ERROR_NONE;
if (p) {
if (p->has_video) {
ret = vcodec_h_control(p->cntl_handle, AMSTREAM_IOC_VPAUSE, 1);
}
} else {
ret = CODEC_ERROR_PARAMETER;
}
return ret;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_resume Resume playing(A/V) by codec device
*
* @param[in] p Pointer of codec parameter structure
*
* @return Success or fail error type
*/
/* --------------------------------------------------------------------------*/
int vcodec_resume(vcodec_para_t *p)
{
int ret = CODEC_ERROR_NONE;
if (p) {
if (p->has_video) {
ret = vcodec_h_control(p->cntl_handle, AMSTREAM_IOC_VPAUSE, 0);
}
} else {
ret = CODEC_ERROR_PARAMETER;
}
return ret;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_reset Reset codec device
*
* @param[in] p Pointer of codec parameter structure
*
* @return Success or fail error type
*/
/* --------------------------------------------------------------------------*/
int vcodec_reset(vcodec_para_t *p)
{
int ret;
ret = vcodec_close(p);
if (ret != 0) {
return ret;
}
ret = vcodec_init(p);
CODEC_PRINT("[%s:%d]ret=%x\n", __FUNCTION__, __LINE__, ret);
return ret;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_init_cntl Initialize the video control device
*
* @param[in] pcodec Pointer of codec parameter structure
*
* @return Success or fail error type
*/
/* --------------------------------------------------------------------------*/
int vcodec_init_cntl(vcodec_para_t *pcodec)
{
int cntl;
cntl = vcodec_h_open(CODEC_CNTL_DEVICE, O_RDWR);
if (cntl < 0) {
CODEC_PRINT("get %s failed\n", CODEC_CNTL_DEVICE);
return cntl;
}
pcodec->cntl_handle = cntl;
return CODEC_ERROR_NONE;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_close_cntl Close video control device
*
* @param[in] pcodec Pointer of codec parameter structure
*
* @return Success or fail error type
*/
/* --------------------------------------------------------------------------*/
int vcodec_close_cntl(vcodec_para_t *pcodec)
{
int res = CODEC_ERROR_NONE;
if (pcodec) {
if (pcodec->cntl_handle) {
res = vcodec_h_close(pcodec->cntl_handle);
}
}
return res;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_set_frame_cmp_crc write every frame crc for compare;
*
* @param[in] pcodec Pointer of codec parameter structure, crc poll pointer and size
*
* @return Success or fail error
*/
/* --------------------------------------------------------------------------*/
int vcodec_set_frame_cmp_crc(vcodec_para_t *vcodec, const int *crc, int size, int id)
{
int ret = -1;
struct usr_crc_info_t crc_info;
int i;
if (vcodec == NULL)
return -1;
for (i = 0; i < size; i++) {
crc_info.id = id; /* only for one instance */
crc_info.pic_num = i;
crc_info.y_crc = crc[i * 2];
crc_info.uv_crc = crc[i * 2 + 1];
ret = vcodec_h_control(vcodec->handle,
AMSTREAM_IOC_SET_CRC, (unsigned long)&crc_info);
if (ret < 0) {
printf("set frame compare crc32 value failed, i = %d\n", i);
return -1;
}
}
return 0;
}
/* --------------------------------------------------------------------------*/
/**
* @brief vcodec_get_crc_check_result get all crc cmp result
*
* @param[in] pcodec Pointer of codec parameter structure, Vdec ID
*
* @return Success or fail error type, cmp result.
*/
/* --------------------------------------------------------------------------*/
int vcodec_get_crc_check_result(vcodec_para_t *vcodec, int vdec_id)
{
int ret, result = 0x00ff;
if (vcodec == NULL)
return -1;
result &= vdec_id; /*set the vdec id */
ret = vcodec_h_control(vcodec->handle,
AMSTREAM_IOC_GET_CRC_CMP_RESULT, (unsigned long)&result);
//printf("get result ret = %d, result = %d\n", ret, result);
if (ret < 0)
return ret;
return result;
}
/* --------------------------------------------------------------------------*/
/**
* @brief is_dec_cmp_ongoing require decoding and compare crc num;
*
* @param[in] pcodec Pointer of codec parameter structure, Vdec ID.
*
* @return Fail error type, or rest compare frame num;
*/
/* --------------------------------------------------------------------------*/
int is_crc_cmp_ongoing(vcodec_para_t *vcodec, int vdec_id)
{
int ret = 0;
int rest_num = 0xff00;
if (vcodec == NULL)
return -1;
rest_num |= vdec_id;
ret = vcodec_h_control(vcodec->handle,
AMSTREAM_IOC_GET_CRC_CMP_RESULT, (unsigned long)&rest_num);
if (ret < 0)
return ret;
return rest_num;
}