Update source to Armbian-dev-202610.A311Y3

This commit is contained in:
2026-11-11 08:50:43 +08:00
parent 3428a94f6b
commit f459ef6a9e
12514 changed files with 2264376 additions and 468481 deletions
@@ -17,6 +17,7 @@
#define AMVENC_265_DEVICE "/dev/HevcEnc"
#define AMVENC_VERS_DEVICE "/dev/vc8000"
#define AMVENC_TAHOE_DEVICE "/dev/tahoe"
#define AMVENC_TAHOE_V4L_DEVICE "/dev/video90"
typedef enum amvenc_hw_e {
AMVENC_UNKNOWN,
@@ -133,7 +134,7 @@ int selectHW(amvenc_codec_id_t codec_id, int *hw_type)
VLOG(DEBUG, "amvenc_vers present");
ret = 0;
}
else if (access(AMVENC_TAHOE_DEVICE, F_OK ) != -1) {
else if ((access(AMVENC_TAHOE_DEVICE, F_OK ) != -1) || (access(AMVENC_TAHOE_V4L_DEVICE, F_OK )!= -1)) {
*hw_type = AMVENC_TAHOE;
VLOG(DEBUG, "amvenc_tahoe present");
ret = 0;
@@ -158,7 +159,7 @@ int selectHW(amvenc_codec_id_t codec_id, int *hw_type)
VLOG(DEBUG, "amvenc_vers present");
ret = 0;
}
else if (access(AMVENC_TAHOE_DEVICE, F_OK ) != -1) {
else if ((access(AMVENC_TAHOE_DEVICE, F_OK ) != -1) || (access(AMVENC_TAHOE_V4L_DEVICE, F_OK )!= -1)) {
*hw_type = AMVENC_TAHOE;
VLOG(DEBUG, "amvenc_tahoe present");
ret = 0;
@@ -41,10 +41,371 @@
#include "tahoe_register.h"
#include <string.h>
#include <sys/poll.h>
#include <linux/videodev2.h>
#include <linux/v4l2-controls.h>
#include <errno.h>
#define MAX_FRAME_WINDOW (120)
venc_info_t s_venc_info;
#include <fcntl.h> // open(), O_RDWR, O_RDONLY...
#include <unistd.h> // close(), read(), write()
#include <stdlib.h>
struct v4l2_buffer *src_buf_info = NULL;
struct v4l2_buffer *dst_buf_info = NULL;
unsigned char **src_buffers = NULL;
unsigned char **dst_buffers = NULL;
int *src_buf_lengths = NULL;
int *dst_buf_lengths = NULL;
int src_buf_count = 0, dst_buf_count = 0;
//int frame_count = 0;
//struct v4l2_buffer src_buf, dst_buf;
struct timespec ts_start, ts_end;
#define CLEAR(x) memset(&(x), 0, sizeof(x))
void query_and_set_control(int fd, unsigned int id, int value) {
struct v4l2_queryctrl query;
struct v4l2_control ctrl;
CLEAR(query);
query.id = id;
if (ioctl(fd, VIDIOC_QUERYCTRL, &query) == 0) {
printf("[%s] range: %d - %d, default: %d, step: %d\n",
query.name, query.minimum, query.maximum, query.default_value, query.step);
if (value >= query.minimum && value <= query.maximum) {
CLEAR(ctrl);
ctrl.id = id;
ctrl.value = value;
if (ioctl(fd, VIDIOC_S_CTRL, &ctrl) == 0) {
printf("[%s] set to %d successfully\n", query.name, value);
} else {
perror("VIDIOC_S_CTRL failed");
}
} else {
printf("[%s] value %d out of range [%d, %d], skipping\n",
query.name, value, query.minimum, query.maximum);
}
} else {
printf("Control 0x%08x not supported\n", id);
}
}
void setup_encoder_params(int fd, handle_t *encode_info) {
printf("\n=== Setting up encoder parameters ===\n");
// GOP
query_and_set_control(fd, V4L2_CID_MPEG_VIDEO_GOP_SIZE, encode_info->enc_gop);
// Bitrate
query_and_set_control(fd, V4L2_CID_MPEG_VIDEO_BITRATE, encode_info->enc_bitrate);
// H.264 Profile
if (encode_info->profile == 3 && encode_info->enc_fmt == CODEC_ID_H264)
query_and_set_control(fd, V4L2_CID_MPEG_VIDEO_H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_HIGH);
//
// // H.264 Level
if (encode_info->enc_fmt == CODEC_ID_H264)
query_and_set_control(fd, V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
//
if (encode_info->profile == 3 && encode_info->enc_fmt == CODEC_ID_H265)
query_and_set_control(fd, V4L2_CID_MPEG_VIDEO_HEVC_PROFILE, V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN);
if (encode_info->enc_fmt == CODEC_ID_H265)
query_and_set_control(fd, V4L2_CID_MPEG_VIDEO_HEVC_LEVEL, V4L2_MPEG_VIDEO_HEVC_LEVEL_4);
// query_and_set_control(fd, V4L2_CID_MPEG_VIDEO_HEVC_TIER_FLAG,
// V4L2_MPEG_VIDEO_HEVC_TIER_MAIN);
}
int setup_src_format_mplane(int fd, handle_t *encode_info,int plane_num) {
struct v4l2_format fmt;
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
fmt.fmt.pix_mp.width = encode_info->enc_width;
fmt.fmt.pix_mp.height = encode_info->enc_height;
if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV12)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12;
else if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV21)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV21;
else if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_YUV420_PLANAR)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420;
else if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_RGB888)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGB24;
#if 0
else if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_RGBA8888)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_RGBA32;
#endif
fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
printf("setup_src_format_mplane fmt input:%d\n",encode_info->mfdin_input_fmt);
if (encode_info->current_mode == DMA_TYPE) { //dmabuf
if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV12)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;
else if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV21)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV21M;
else if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_YUV420_PLANAR)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUV420M;
fmt.fmt.pix_mp.num_planes = plane_num;
if (1 == fmt.fmt.pix_mp.num_planes) { //rgb rgba?
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = encode_info->enc_width;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = encode_info->enc_width * encode_info->enc_height * 3 / 2;
}
else if (2 == fmt.fmt.pix_mp.num_planes) {
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = encode_info->enc_width;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = encode_info->enc_width * encode_info->enc_height;
fmt.fmt.pix_mp.plane_fmt[1].bytesperline = encode_info->enc_width;
fmt.fmt.pix_mp.plane_fmt[1].sizeimage = encode_info->enc_width * encode_info->enc_height / 2;
}
else if (3 == fmt.fmt.pix_mp.num_planes){
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = encode_info->enc_width;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = encode_info->enc_width * encode_info->enc_height;
fmt.fmt.pix_mp.plane_fmt[1].bytesperline = encode_info->enc_width;
fmt.fmt.pix_mp.plane_fmt[1].sizeimage = encode_info->enc_width * encode_info->enc_height / 4;
fmt.fmt.pix_mp.plane_fmt[2].bytesperline = encode_info->enc_width;
fmt.fmt.pix_mp.plane_fmt[2].sizeimage = encode_info->enc_width * encode_info->enc_height / 4;
}
}
else { //mmap
fmt.fmt.pix_mp.num_planes = 1;
if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_RGB888) {
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = encode_info->enc_width * 3;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = encode_info->enc_width * encode_info->enc_height * 3;
}
else if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_RGBA8888) {
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = encode_info->enc_width * 4;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = encode_info->enc_width * encode_info->enc_height * 4;
}
else {
fmt.fmt.pix_mp.plane_fmt[0].bytesperline = encode_info->enc_width;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = encode_info->enc_width * encode_info->enc_height * 3 / 2;
}
}
printf("sizeimage:%d %d\n",fmt.fmt.pix_mp.plane_fmt[0].sizeimage,fmt.fmt.pix_mp.plane_fmt[1].sizeimage);
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
perror("VIDIOC_S_FMT (src) failed");
return -1;
}
printf("Source format (MPLANE): %dx%d, pixelformat: %c%c%c%c, planes: %d\n",
fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
fmt.fmt.pix_mp.pixelformat & 0xFF,
(fmt.fmt.pix_mp.pixelformat >> 8) & 0xFF,
(fmt.fmt.pix_mp.pixelformat >> 16) & 0xFF,
(fmt.fmt.pix_mp.pixelformat >> 24) & 0xFF,
fmt.fmt.pix_mp.num_planes);
return 0;
}
int setup_dst_format_mplane(int fd, handle_t *encode_info) {
struct v4l2_format fmt;
CLEAR(fmt);
fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
fmt.fmt.pix_mp.width = encode_info->enc_width;
fmt.fmt.pix_mp.height = encode_info->enc_height;
if (encode_info->enc_fmt == CODEC_ID_H264)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;
else if (encode_info->enc_fmt == CODEC_ID_H265)
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_HEVC;
fmt.fmt.pix_mp.field = V4L2_FIELD_NONE;
fmt.fmt.pix_mp.num_planes = 1;
fmt.fmt.pix_mp.plane_fmt[0].sizeimage = 5*1024*1024;
if (ioctl(fd, VIDIOC_S_FMT, &fmt) < 0) {
perror("VIDIOC_S_FMT (dst) failed");
return -1;
}
printf("Destination format (MPLANE): %dx%d, pixelformat: %c%c%c%c, planes: %d\n",
fmt.fmt.pix_mp.width, fmt.fmt.pix_mp.height,
fmt.fmt.pix_mp.pixelformat & 0xFF,
(fmt.fmt.pix_mp.pixelformat >> 8) & 0xFF,
(fmt.fmt.pix_mp.pixelformat >> 16) & 0xFF,
(fmt.fmt.pix_mp.pixelformat >> 24) & 0xFF,
fmt.fmt.pix_mp.num_planes);
return 0;
}
int setup_buffers_mplane(int fd, int type, int count,
struct v4l2_buffer **buf_info,
unsigned char ***buffers,
int **buf_lengths,
int *num_buffers,enum v4l2_memory memory_type) {
struct v4l2_requestbuffers req;
CLEAR(req);
req.count = count;
req.type = type;
//req.memory = V4L2_MEMORY_MMAP;
if (0 != memory_type) {
req.memory = memory_type;
}
else { //by default
req.memory = V4L2_MEMORY_MMAP;
}
if (ioctl(fd, VIDIOC_REQBUFS, &req) < 0) {
perror("VIDIOC_REQBUFS failed");
return -1;
}
*num_buffers = req.count;
printf("Allocated %d buffers for type %d\n", req.count, type);
if (req.count == 0) {
printf("No buffers allocated\n");
return -1;
}
*buf_info = calloc(req.count, sizeof(struct v4l2_buffer));
*buffers = calloc(req.count, sizeof(unsigned char *));
*buf_lengths = calloc(req.count, sizeof(int));
if (!*buf_info || !*buffers || !*buf_lengths) {
perror("calloc failed");
return -1;
}
for (int i = 0; i < req.count; i++) {
struct v4l2_buffer buf;
struct v4l2_plane planes[VIDEO_MAX_PLANES];
CLEAR(buf);
buf.type = type;
//buf.memory = V4L2_MEMORY_MMAP;
buf.index = i;
buf.length = VIDEO_MAX_PLANES;
// buf.m.planes = planes;
buf.m.planes = calloc(VIDEO_MAX_PLANES,
sizeof(struct v4l2_plane));
if (0 != memory_type) {
buf.memory = memory_type;
}
else { //by default
buf.memory = V4L2_MEMORY_MMAP;
}
if (ioctl(fd, VIDIOC_QUERYBUF, &buf) < 0) {
perror("VIDIOC_QUERYBUF failed");
return -1;
}
memcpy(&((*buf_info)[i]), &buf, sizeof(struct v4l2_buffer));
(*buf_lengths)[i] = 0;
for (int p = 0; p < buf.length; p++) {
int plane_size = buf.m.planes[p].length;
(*buf_lengths)[i] += plane_size;
printf("Buffer %d, plane %d: offset=0x%08x, length=%d\n",
i, p, buf.m.planes[p].m.mem_offset, plane_size);
if ((p == 0) && (buf.memory == V4L2_MEMORY_MMAP)) {
(*buffers)[i] = mmap(NULL, plane_size,
PROT_READ | PROT_WRITE,
MAP_SHARED, fd,
buf.m.planes[p].m.mem_offset);
if ((*buffers)[i] == MAP_FAILED) {
perror("mmap failed");
return -1;
}
printf("Buffer %d mapped at %p, size %d\n",
i, (*buffers)[i], plane_size);
}
}
}
return 0;
}
void detectV4l2Support(handle_t *encode_info) {
if ((access("/dev/video90", F_OK ) != -1)) {
encode_info->v4l2_enable = true;
VLOG(ERR, "v4l2 component present");
return;
}
return;
}
int queue_buffer_mplane(int fd, struct v4l2_buffer *buf) {
if (ioctl(fd, VIDIOC_QBUF, buf) < 0) {
perror("VIDIOC_QBUF failed");
return -1;
}
return 0;
}
int dequeue_buffer_mplane(int fd, int type, struct v4l2_buffer *buf, struct v4l2_plane *planes,enum v4l2_memory memory_type) {
// struct v4l2_plane planes[VIDEO_MAX_PLANES];
CLEAR(*buf);
memset(planes, 0, sizeof(struct v4l2_plane) * VIDEO_MAX_PLANES);
buf->type = type;
if (0 != memory_type) {
buf->memory = memory_type;
}
else {
buf->memory = V4L2_MEMORY_MMAP;
}
buf->length = VIDEO_MAX_PLANES;
buf->m.planes = planes;
if (ioctl(fd, VIDIOC_DQBUF, buf) < 0) {
if (errno == EAGAIN) {
return -EAGAIN;
}
perror("VIDIOC_DQBUF failed");
return -1;
}
return 0;
}
int stream_on(int fd, int type) {
enum v4l2_buf_type buf_type = type;
if (ioctl(fd, VIDIOC_STREAMON, &buf_type) < 0) {
perror("VIDIOC_STREAMON failed");
return -1;
}
return 0;
}
int stream_off(int fd, int type) {
enum v4l2_buf_type buf_type = type;
if (ioctl(fd, VIDIOC_STREAMOFF, &buf_type) < 0) {
perror("VIDIOC_STREAMOFF failed");
return -1;
}
return 0;
}
void print_frame_info(struct v4l2_buffer *buf, const char *tag) {
printf("[%s] Buffer %d, type=%d, bytesused=", tag, buf->index, buf->type);
if (buf->length > 0 && buf->m.planes) {
int total = 0;
for (int p = 0; p < buf->length; p++) {
total += buf->m.planes[p].bytesused;
}
printf("%d", total);
} else {
printf("%d", buf->bytesused);
}
printf(", flags=0x%x\n", buf->flags);
}
int get_header(handle_t *handle, unsigned char *pHeader, unsigned int *pLength)
{
venc_info_t *venc = &s_venc_info;
@@ -116,32 +477,77 @@ int get_header(handle_t *handle, unsigned char *pHeader, unsigned int *pLength)
return 0;
}
int get_bsbframe(handle_t *handle, unsigned char *buffer, unsigned int *buf_nal_size, signed char *frame_type)
{
venc_info_t *venc = &s_venc_info;
unsigned int esaddr_offset = 0;
unsigned long esPhyAddr;
int eslength;
unsigned long espVirAddr = 0;
unsigned long slice_header_length = 0;
int length_cp = 0;
if (handle->v4l2_enable) {
venc_info_t *venc = &s_venc_info;
struct v4l2_buffer dst_buf;
struct v4l2_plane planes[VIDEO_MAX_PLANES];
int ret = -1;
slice_header_length = handle->enc_es.slice_header_length;
esPhyAddr = handle->enc_es.esPhyAddr;
eslength = handle->enc_es.eslength;
esaddr_offset = esPhyAddr - venc->common_buffer[handle->chn_id].phys_addr;
espVirAddr = venc->common_buffer[handle->chn_id].virt_addr + esaddr_offset;
VLOG(INFO,"[%s][%d]offset:0x%x\n", __func__, __LINE__, slice_header_length);
VLOG(INFO,"[%s][%d]esPhyAddr:0x%lx\n", __func__, __LINE__, esPhyAddr);
VLOG(INFO,"[%s][%d]esaddr_offset:0x%lx\n", __func__, __LINE__, esaddr_offset);
VLOG(INFO,"[%s][%d]espVirAddr:0x%lx\n", __func__, __LINE__, espVirAddr);
VLOG(INFO,"[%s][%d]eslength:%d\n", __func__, __LINE__, eslength);
ret = dequeue_buffer_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &dst_buf, planes, 0);
while (ret != 0) {
usleep(1000);
ret = dequeue_buffer_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, &dst_buf, planes, 0);
}
length_cp = ((eslength + 15) >> 4) << 4;
memcpy(buffer, (const void *)((ulong)espVirAddr), length_cp);
*buf_nal_size = eslength;
(*frame_type) = handle->enc_es.frame_type;
VLOG(INFO,"[%s][%d]buf_nal_size:%d,frame_type:%d\n", __func__, __LINE__,*buf_nal_size,(*frame_type));
if (ret == 0) {
handle->data_len = 0;
if (dst_buf.length > 0 && dst_buf.m.planes) {
for (int p = 0; p < dst_buf.length; p++) {
handle->data_len += dst_buf.m.planes[p].bytesused;
}
}
safe_memcpy(buffer, dst_buffers[dst_buf.index], handle->data_len);
if (dst_buf.flags & V4L2_BUF_FLAG_LAST) {
printf("End of stream reached\n");
}
if (dst_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
(*frame_type) = 0;
}
else {
(*frame_type) = 1;
}
if (queue_buffer_mplane(venc->venc_fd, &dst_buf) < 0) {
printf("queue_buffer_mplane err\n");
}
(*buf_nal_size) = handle->data_len;
} else if (ret != -EAGAIN) {
perror("dequeue dst failed");
}
}
else {
venc_info_t *venc = &s_venc_info;
unsigned int esaddr_offset = 0;
unsigned long esPhyAddr;
int eslength;
unsigned long espVirAddr = 0;
unsigned long slice_header_length = 0;
int length_cp = 0;
slice_header_length = handle->enc_es.slice_header_length;
esPhyAddr = handle->enc_es.esPhyAddr;
eslength = handle->enc_es.eslength;
esaddr_offset = esPhyAddr - venc->common_buffer[handle->chn_id].phys_addr;
espVirAddr = venc->common_buffer[handle->chn_id].virt_addr + esaddr_offset;
VLOG(INFO,"[%s][%d]offset:0x%x\n", __func__, __LINE__, slice_header_length);
VLOG(INFO,"[%s][%d]esPhyAddr:0x%lx\n", __func__, __LINE__, esPhyAddr);
VLOG(INFO,"[%s][%d]esaddr_offset:0x%lx\n", __func__, __LINE__, esaddr_offset);
VLOG(INFO,"[%s][%d]espVirAddr:0x%lx\n", __func__, __LINE__, espVirAddr);
VLOG(INFO,"[%s][%d]eslength:%d\n", __func__, __LINE__, eslength);
length_cp = ((eslength + 15) >> 4) << 4;
memcpy(buffer, (const void *)((ulong)espVirAddr), length_cp);
*buf_nal_size = eslength;
(*frame_type) = handle->enc_es.frame_type;
VLOG(INFO,"[%s][%d]buf_nal_size:%d,frame_type:%d\n", __func__, __LINE__,*buf_nal_size,(*frame_type));
}
return 0;
}
@@ -191,10 +597,43 @@ int check_initparam(handle_t handle)
void encoder_open(char *fwfile) {
venc_init();
vrisc_reset();
firmware_load(fwfile);
firmware_boot();
// venc_init();
// vrisc_reset();
// firmware_load(fwfile);
// firmware_boot();
venc_info_t *venc = &s_venc_info;
struct v4l2_capability cap;
memset(&s_venc_info, 0x00, sizeof(s_venc_info));
s_venc_info.venc_fd = -1;
venc->venc_fd = open("/dev/video90", O_RDWR);
if (venc->venc_fd < 0) {
VLOG(INFO,"[VENC] Can't open venc driver. [error=%s]. \n", strerror(errno));
// return -1;
}
VLOG(INFO,"open venc fd:%d,&venc:%lx!",venc->venc_fd,(unsigned long)venc);
if (ioctl(venc->venc_fd, VIDIOC_QUERYCAP, &cap) < 0) {
perror("VIDIOC_QUERYCAP failed");
close(venc->venc_fd);
// return -1;
}
printf("Driver: %s\n", cap.driver);
printf("Card: %s\n", cap.card);
printf("Bus: %s\n", cap.bus_info);
printf("Capabilities: 0x%08x\n", cap.capabilities);
if (!(cap.capabilities & V4L2_CAP_VIDEO_M2M_MPLANE)) {
printf("Device does not support V4L2_CAP_VIDEO_M2M_MPLANE\n");
printf("Try using non-mplane version\n");
close(venc->venc_fd);
// return -1;
}
printf("Device supports M2M MPLANE\n");
}
void encoder_unmap(int inst_id) {
@@ -213,41 +652,58 @@ void encoder_close() {
int vl_tahoe_encoder_init(int codec_id, handle_t encode_info) {
// int ret;
// VPMultiEncHandle* mHandle = (VPMultiEncHandle *) malloc(sizeof(VPMultiEncHandle));
//
// if (mHandle == NULL)
// goto exit;
// memset(mHandle, 0, sizeof(VPMultiEncHandle));
// if (!check_qp_tbl(qp_tbl)) {
// goto exit;
// }
//
// vp5_set_log_level(ERR);
//
// ret = initEncParams(mHandle, codec_id, encode_info, qp_tbl);
// if (ret < 0)
// goto exit;
//
// mHandle->am_enc_handle = AML_MultiEncInitialize(&(mHandle->mEncParams));
// if (mHandle->am_enc_handle == 0)
// goto exit;
// mHandle->mPrependSPSPPSToIDRFrames =
// encode_info.prepend_spspps_to_idr_frames;
// mHandle->mSpsPpsHeaderReceived = false;
// mHandle->mNumInputFrames = -1; // 1st two buffers contain SPS and PPS
// if (encode_info.strict_rc_window > MAX_FRAME_WINDOW)
// encode_info.strict_rc_window = MAX_FRAME_WINDOW;
// mHandle->hist_win_len = encode_info.strict_rc_window;
// mHandle->hist_skip_thresh = encode_info.strict_rc_skip_thresh;
venc_info_t *venc = &s_venc_info;
if (check_initparam(encode_info)) {
printf("check_initparam failed\n");
return -1;
}
vdi_alloc_common_buffer(encode_info.chn_id);
venc_lock();
create_channel(encode_info);
venc_unlock();
// vdi_alloc_common_buffer(encode_info.chn_id);
// venc_lock();
// create_channel(encode_info);
// venc_unlock();
setup_encoder_params(venc->venc_fd, &encode_info);
if (setup_src_format_mplane(venc->venc_fd, &encode_info, 1) < 0) {
close(venc->venc_fd);
return -1;
}
if (setup_dst_format_mplane(venc->venc_fd, &encode_info) < 0) {
close(venc->venc_fd);
return -1;
}
if (setup_buffers_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 2,
&src_buf_info, &src_buffers, &src_buf_lengths, &src_buf_count, 0) < 0) {
close(venc->venc_fd);
return -1;
}
if (setup_buffers_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 2,
&dst_buf_info, &dst_buffers, &dst_buf_lengths, &dst_buf_count, 0) < 0) {
close(venc->venc_fd);
return -1;
}
for (int i = 0; i < dst_buf_count; i++) {
if (queue_buffer_mplane(venc->venc_fd, &dst_buf_info[i]) < 0) {
close(venc->venc_fd);
return -1;
}
}
if (stream_on(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
close(venc->venc_fd);
return -1;
}
if (stream_on(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) < 0) {
close(venc->venc_fd);
return -1;
}
printf("Stream started\n");
return 0;
// return (vl_codec_handle_t)mHandle;
@@ -258,6 +714,75 @@ int vl_tahoe_encoder_init(int codec_id, handle_t encode_info) {
// return (vl_codec_handle_t)NULL;
}
int vl_v4l2_switch_to_dmamode( handle_t encode_info,int plane_num) {
venc_info_t *venc = &s_venc_info;
VLOG(ERR,"switch to dmamode!\n");
stream_off(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
stream_off(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
for (int i = 0; i < src_buf_count; i++) {
munmap(src_buffers[i], src_buf_lengths[i]);
}
for (int i = 0; i < dst_buf_count; i++) {
munmap(dst_buffers[i], dst_buf_lengths[i]);
}
free(src_buffers);
free(dst_buffers);
for (int i = 0; i < src_buf_count; i++) {
free(src_buf_info[i].m.planes);
}
free(src_buf_info);
free(dst_buf_info);
free(src_buf_lengths);
free(dst_buf_lengths);
setup_encoder_params(venc->venc_fd, &encode_info);
if (setup_src_format_mplane(venc->venc_fd, &encode_info, plane_num) < 0) {
close(venc->venc_fd);
return -1;
}
if (setup_dst_format_mplane(venc->venc_fd, &encode_info) < 0) {
close(venc->venc_fd);
return -1;
}
if (setup_buffers_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, 2,
&src_buf_info, &src_buffers, &src_buf_lengths, &src_buf_count, V4L2_MEMORY_DMABUF) < 0) {
close(venc->venc_fd);
return -1;
}
if (setup_buffers_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, 2,
&dst_buf_info, &dst_buffers, &dst_buf_lengths, &dst_buf_count, 0) < 0) {
close(venc->venc_fd);
return -1;
}
for (int i = 0; i < dst_buf_count; i++) {
if (queue_buffer_mplane(venc->venc_fd, &dst_buf_info[i]) < 0) {
close(venc->venc_fd);
return -1;
}
}
if (stream_on(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) < 0) {
close(venc->venc_fd);
return -1;
}
if (stream_on(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) < 0) {
close(venc->venc_fd);
return -1;
}
printf("Stream started\n");
}
int vl_video_encoder_change_bitrate(handle_t *encode_info,
int bitRate)
{
@@ -387,33 +912,85 @@ static int encode_poll(int fd, int timeout) {
return poll(poll_fd, 1, timeout);
}
int vl_tahoe_encoder_encode(handle_t *encode_info)
int num = 0;
bool get_input_buf_forv4l(ulong *pInput,struct v4l2_buffer *src_buf,handle_t *encode_info) {
venc_info_t *venc = &s_venc_info;
struct v4l2_plane planes[VIDEO_MAX_PLANES];
int ret = -1;
enum v4l2_memory type;
if (encode_info->current_mode == 3) {
type = V4L2_MEMORY_DMABUF;
}
else {
type = V4L2_MEMORY_MMAP;
}
if (num < 2) {
memcpy(src_buf,&src_buf_info[num],sizeof(struct v4l2_buffer));
//src_buf = &src_buf_info[num];
ret = 0;
num++;
} else {
ret = dequeue_buffer_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, src_buf, planes, type);
while (ret != 0) {
usleep(1000);
ret = dequeue_buffer_mplane(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, src_buf, planes, type);
}
}
if (ret == 0) {
(*pInput) = src_buffers[src_buf->index];
return true;
}
return false;
}
int vl_tahoe_encoder_encode(handle_t *encode_info,struct v4l2_buffer *src_buf)
{
int ret = 0;
// int ret = 0;
//vdi_debug(encode_info->chn_id);
venc_lock();
roi_config(encode_info);
osd_config(encode_info);
if (encode_info->cfg_update == 1) {
dynamic_parameter_set(encode_info);
encode_info->cfg_update = 0;
}
encode_one_frame(encode_info);
if (encode_poll(s_venc_info.venc_fd, -1) <= 0) {
VLOG(ERR,"[%s][%d]poll fail\n", __func__, __LINE__);
return -1;
}
encode_info->enc_es.slice_header_length = venc_read_register(TAHOE_EC_DMA0) & 0x3F;
encode_info->enc_es.esPhyAddr = venc_read_register(TAHOE_EC_DMA0) - encode_info->enc_es.slice_header_length;
encode_info->enc_es.esPhyAddr |= (((ulong)(venc_read_register(TAHOE_EC_DMA6) & 0x03)) << 32);
encode_info->enc_es.eslength = venc_read_register(TAHOE_EC_LENGTH);
encode_info->enc_es.frame_type = venc_read_register(OUTPUT_FRAME_TYPE);
// venc_lock();
// roi_config(encode_info);
// osd_config(encode_info);
// if (encode_info->cfg_update == 1) {
// dynamic_parameter_set(encode_info);
// encode_info->cfg_update = 0;
// }
// encode_one_frame(encode_info);
// if (encode_poll(s_venc_info.venc_fd, -1) <= 0) {
// VLOG(ERR,"[%s][%d]poll fail\n", __func__, __LINE__);
// return -1;
// }
// encode_info->enc_es.slice_header_length = venc_read_register(TAHOE_EC_DMA0) & 0x3F;
// encode_info->enc_es.esPhyAddr = venc_read_register(TAHOE_EC_DMA0) - encode_info->enc_es.slice_header_length;
// encode_info->enc_es.esPhyAddr |= (((ulong)(venc_read_register(TAHOE_EC_DMA6) & 0x03)) << 32);
// encode_info->enc_es.eslength = venc_read_register(TAHOE_EC_LENGTH);
// encode_info->enc_es.frame_type = venc_read_register(OUTPUT_FRAME_TYPE);
//
// VLOG(INFO,"es buffer phyaddr:%lx,lsb:%x",encode_info->enc_es.esPhyAddr,(venc_read_register(TAHOE_EC_DMA0) - encode_info->enc_es.slice_header_length));
//
// venc_unlock();
venc_info_t *venc = &s_venc_info;
struct v4l2_buffer dst_buf;
struct v4l2_plane planes[VIDEO_MAX_PLANES];
int ret = 0;//-1;
VLOG(INFO,"es buffer phyaddr:%lx,lsb:%x",encode_info->enc_es.esPhyAddr,(venc_read_register(TAHOE_EC_DMA0) - encode_info->enc_es.slice_header_length));
if (encode_info->current_mode == VMALLOC_TYPE) {
if (src_buf && (src_buf->length > 0) && src_buf->m.planes) {
int y_size = encode_info->enc_width * encode_info->enc_height;
int uv_size = (encode_info->enc_width / 2) * (encode_info->enc_height / 2) * 2;
src_buf->m.planes[0].bytesused = y_size + uv_size;//一个planes的情况
}
}
if (queue_buffer_mplane(venc->venc_fd, src_buf) < 0) {
printf("queue_buffer_mplane err\n");
}
venc_unlock();
return ret;
}
@@ -428,9 +1005,31 @@ int vl_tahoe_encoder_destroy(handle_t encode_info) {
// free(handle->mSPSPPSData);
// if (handle)
// free(handle);
venc_lock();
destroy_channel(encode_info);
venc_unlock();
// venc_lock();
// destroy_channel(encode_info);
// venc_unlock();
venc_info_t *venc = &s_venc_info;
stream_off(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
stream_off(venc->venc_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
for (int i = 0; i < src_buf_count; i++) {
munmap(src_buffers[i], src_buf_lengths[i]);
}
for (int i = 0; i < dst_buf_count; i++) {
munmap(dst_buffers[i], dst_buf_lengths[i]);
}
free(src_buffers);
free(dst_buffers);
for (int i = 0; i < src_buf_count; i++) {
free(src_buf_info[i].m.planes);
}
free(src_buf_info);
free(dst_buf_info);
free(src_buf_lengths);
free(dst_buf_lengths);
close(venc->venc_fd);
return 1;
}
@@ -34,6 +34,7 @@
#define _VP_CODEC_TAHOE_H_
#include "vp_codec_tahoe.h"
#include <linux/videodev2.h>
void encoder_open(char *fwfile);
void encoder_close();
@@ -47,11 +48,14 @@ int vl_video_encoder_change_qp(handle_t *encode_info,
int minQpI, int maxQpI, int maxDeltaQp,
int minQpP, int maxQpP,
int minQpB, int maxQpB);
int vl_tahoe_encoder_encode(handle_t *encode_info);
int vl_tahoe_encoder_encode(handle_t *encode_info,struct v4l2_buffer *src_buf);
int get_dsframe(handle_t *handle, unsigned char *buffer, unsigned int *buf_nal_size);
int get_bsbframe(handle_t *handle, unsigned char *buffer, unsigned int *buf_nal_size, signed char *frame_type);
int get_header(handle_t *handle, unsigned char *pHeader, unsigned int *pLength);
int check_initparam(handle_t handle);
int vl_tahoe_encoder_generate_header(handle_t *encode_info);
bool get_input_buf_forv4l(ulong *pInput,struct v4l2_buffer *src_buf, handle_t *encode_info);
void detectV4l2Support(handle_t *encode_info);
int vl_v4l2_switch_to_dmamode( handle_t encode_info,int plane_num) ;
#endif
@@ -45,6 +45,8 @@
#include <string.h>
#include <sys/poll.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <linux/v4l2-controls.h>
#define FW_STRING_LEN_MAX 256
#define HE_BUF_SIZE 0x100000
@@ -62,7 +64,6 @@ int output_fd_dump = -1;
#endif
vl_codec_tahoe_handle_t vt_tahoe_encoder_init(int codec_id, vt_encode_info_t encode_param) {
venc_buffer_t hdBuffer[3] = {0};
char fwfile[FW_STRING_LEN_MAX] = {0};
@@ -130,6 +131,8 @@ vl_codec_tahoe_handle_t vt_tahoe_encoder_init(int codec_id, vt_encode_info_t enc
}*/
snprintf(fwfile, FW_STRING_LEN_MAX, "%s", FW_PATH);
detectV4l2Support(encode_info);
if (0 == get_cur_instance()) {
VLOG(INFO,"loading fw:%s\n",fwfile);
encoder_open(fwfile);
@@ -158,22 +161,25 @@ vl_codec_tahoe_handle_t vt_tahoe_encoder_init(int codec_id, vt_encode_info_t enc
encode_info->input_buf[0].size = encode_info->enc_width * encode_info->enc_height * 4;//fix me!!!
}
if (vdi_allocate_dma_memory(&encode_info->input_buf[0]) < 0) {
VLOG(ERR,"Can not allocat input Buffer in vmalloc mode!\n");
return -1;
}
for (i = 0; i < 3; i++) {
memset(&hdBuffer[i], 0, sizeof(hdBuffer[i]));
hdBuffer[i].size = HE_BUF_SIZE;
if (vdi_allocate_dma_memory(&hdBuffer[i]) < 0) {
printf("Can not allocat hd Buffer chnid %d\n", encode_info->chn_id);
if (!encode_info->v4l2_enable) {
if (vdi_allocate_dma_memory(&encode_info->input_buf[0]) < 0) {
VLOG(ERR,"Can not allocat input Buffer in vmalloc mode!\n");
return -1;
}
VLOG(INFO,"[%s][%d]hdBuffer[%d].phys_addr:0x%x\n", \
__func__,__LINE__, i, hdBuffer[i].phys_addr);
encode_info->header_buf_addr[i] = hdBuffer[i].phys_addr;
for (i = 0; i < 3; i++) {
memset(&hdBuffer[i], 0, sizeof(hdBuffer[i]));
hdBuffer[i].size = HE_BUF_SIZE;
if (vdi_allocate_dma_memory(&hdBuffer[i]) < 0) {
printf("Can not allocat hd Buffer chnid %d\n", encode_info->chn_id);
return -1;
}
VLOG(INFO,"[%s][%d]hdBuffer[%d].phys_addr:0x%x\n", \
__func__,__LINE__, i, hdBuffer[i].phys_addr);
encode_info->header_buf_addr[i] = hdBuffer[i].phys_addr;
}
}
#if DUMP_FILE_ENABLE
input_fd_dump = open("/data/tahoe_dump_input.yuv", O_CREAT | O_RDWR | O_TRUNC, 0644);
if (input_fd_dump < 0)
@@ -288,6 +294,7 @@ vt_encoding_metadata_t vt_tahoe_encoder_encode(vl_codec_tahoe_handle_t codec_han
//venc_buffer_t input_buf = {0};
int header_length = 0;
int i = 0;
struct v4l2_buffer src_buf;
tahoe_dma_buf_info_t dma_info_map;
memset(&result,0,sizeof(result));
@@ -300,6 +307,12 @@ vt_encoding_metadata_t vt_tahoe_encoder_encode(vl_codec_tahoe_handle_t codec_han
}
if (VMALLOC_TYPE == in_buffer_info->buf_type) {
encode_info->current_mode = VMALLOC_TYPE;
if (encode_info->v4l2_enable) {
if (!get_input_buf_forv4l(&encode_info->input_buf[0].virt_addr,&src_buf,encode_info)) {
VLOG(ERR,"get_input_buf_forv4l failed\n");
}
}
if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV12 || encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV21 ||
encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_YUV420_PLANAR) {
//need fix
@@ -323,11 +336,21 @@ vt_encoding_metadata_t vt_tahoe_encoder_encode(vl_codec_tahoe_handle_t codec_han
encode_info->buf_stride = encode_info->enc_width; //fix me!!!
VLOG(INFO,"vmalloc mode,input data addr:%x %x %x\n",encode_info->tahoe_enc_pic.inpt_buf_addr[0],encode_info->tahoe_enc_pic.inpt_buf_addr[1],encode_info->tahoe_enc_pic.inpt_buf_addr[2]);
}
#if 1
else if (DMA_TYPE == in_buffer_info->buf_type) {
vt_dma_info_t *dma_info;
dma_info = &(in_buffer_info->buf_info.dma_info);
vt_dma_info_t *dma_info;
dma_info = &(in_buffer_info->buf_info.dma_info);
if (encode_info->v4l2_enable && (DMA_TYPE != encode_info->current_mode)) {
encode_info->current_mode = DMA_TYPE;
vl_v4l2_switch_to_dmamode(*encode_info,dma_info->num_planes);
}
if (encode_info->v4l2_enable) {
if (!get_input_buf_forv4l(&encode_info->input_buf[0].virt_addr,&src_buf,encode_info)) {
VLOG(ERR,"get_input_buf_forv4l failed\n");
}
}
if (encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV12 || encode_info->mfdin_input_fmt == MFDI_INPUT_FMT_NV21) {
if (dma_info->num_planes != 1 && dma_info->num_planes != 2) {
VLOG(ERR,"invalid num_planes %d\n", dma_info->num_planes);
@@ -371,7 +394,10 @@ vt_encoding_metadata_t vt_tahoe_encoder_encode(vl_codec_tahoe_handle_t codec_han
dma_info_map.fd[i] = dma_info->shared_fd[i];
VLOG(INFO,"instance %d:**shared_fd %d\n", encode_info->chn_id,dma_info->shared_fd[i]);
}
vdi_config_dma(&dma_info_map);
if (!encode_info->v4l2_enable) {
vdi_config_dma(&dma_info_map);
}
VLOG(INFO,"instance %d:dma map num_planes:%d\n",encode_info->chn_id,dma_info_map.num_planes);
encode_info->buf_stride = ((encode_info->enc_width + 15) >> 4) << 4;
@@ -385,15 +411,51 @@ vt_encoding_metadata_t vt_tahoe_encoder_encode(vl_codec_tahoe_handle_t codec_han
encode_info->tahoe_enc_pic.inpt_buf_addr[2] = encode_info->tahoe_enc_pic.inpt_buf_addr[1] +
encode_info->buf_stride * encode_info->enc_height / 4;
}
if (encode_info->v4l2_enable) {
src_buf.m.planes[0].bytesused = encode_info->buf_stride * encode_info->enc_height * 3 / 2;
src_buf.m.planes[0].length = encode_info->buf_stride * encode_info->enc_height * 3 / 2;
src_buf.m.planes[0].m.fd = dma_info->shared_fd[0];
}
}
}
if (dma_info_map.num_planes > 1 )
if (dma_info_map.num_planes > 1 )
encode_info->tahoe_enc_pic.inpt_buf_addr[1]= dma_info_map.phys_addr[1];
if (dma_info_map.num_planes > 2)
encode_info->tahoe_enc_pic.inpt_buf_addr[2]= dma_info_map.phys_addr[2];
if (encode_info->v4l2_enable && (dma_info_map.num_planes == 2)) {
src_buf.m.planes[0].bytesused = encode_info->buf_stride * encode_info->enc_height;
src_buf.m.planes[0].length = encode_info->buf_stride * encode_info->enc_height;
src_buf.m.planes[0].m.fd = dma_info->shared_fd[0];
src_buf.m.planes[1].bytesused = encode_info->buf_stride * encode_info->enc_height / 2;
src_buf.m.planes[1].m.fd = dma_info->shared_fd[1];
src_buf.m.planes[1].length = encode_info->buf_stride * encode_info->enc_height / 2;
}
if (encode_info->v4l2_enable && (dma_info_map.num_planes == 3)) {
src_buf.m.planes[0].bytesused = encode_info->buf_stride * encode_info->enc_height;
src_buf.m.planes[0].length = encode_info->buf_stride * encode_info->enc_height;
src_buf.m.planes[0].m.fd = dma_info->shared_fd[0];
src_buf.m.planes[1].bytesused = encode_info->buf_stride * encode_info->enc_height / 4;
src_buf.m.planes[1].length = encode_info->buf_stride * encode_info->enc_height / 4;
src_buf.m.planes[1].m.fd = dma_info->shared_fd[1];
src_buf.m.planes[2].bytesused = encode_info->buf_stride * encode_info->enc_height / 4;
src_buf.m.planes[2].length = encode_info->buf_stride * encode_info->enc_height / 4;
src_buf.m.planes[2].m.fd = dma_info->shared_fd[2];
}
}
#endif
ret = vl_tahoe_encoder_encode(encode_info);
if (encode_info->v4l2_enable) {
ret = vl_tahoe_encoder_encode(encode_info,&src_buf);
}
else {
ret = vl_tahoe_encoder_encode(encode_info, 0);
}
if (ret < 0) {
VLOG(ERR,"send encode cmd to encoder failed!ret:%d \n",ret);
result.is_valid = 0;
@@ -403,7 +465,9 @@ vt_encoding_metadata_t vt_tahoe_encoder_encode(vl_codec_tahoe_handle_t codec_han
if (0 == encode_info->enc_es.frame_type || 1 == encode_info->enc_es.frame_type) {
VLOG(INFO,"IDR or I frame!!\n");
vt_tahoe_encoder_generate_header(codec_handle, out, &header_length);
if (!encode_info->v4l2_enable) {
vt_tahoe_encoder_generate_header(codec_handle, out, &header_length);
}
result.is_key_frame = 1;
}
@@ -426,7 +490,7 @@ vt_encoding_metadata_t vt_tahoe_encoder_encode(vl_codec_tahoe_handle_t codec_han
VLOG(INFO,"dump tahoe output file,%d",result.encoded_data_length_in_bytes);
}
#endif
if (DMA_TYPE == in_buffer_info->buf_type) {
if ((DMA_TYPE == in_buffer_info->buf_type) && (!encode_info->v4l2_enable)) {
ret = vdi_unmap_dma(&dma_info_map);
if (ret != 0) {
VLOG(ERR,"vdi_unmap_dma src buffer failed!!\n");
@@ -270,6 +270,11 @@ typedef struct {
u8 golden_match_flag;
venc_buffer_t input_buf[3];
u8 svc_enable;
unsigned char *out;
unsigned char *input_yuvbuf;
int data_len;
unsigned char v4l2_enable;
unsigned char current_mode;
} handle_t;
#define TAHOE_REG_BASE_ADDR 0xFE370000
@@ -504,6 +504,7 @@ static void *encode_thread(void *param)
int frame_num;
int End_status = 0;
int pw = 0;
struct v4l2_buffer src_buf;
if (NULL != param)
cfg_encode = (encodecCfgParam *)param;
@@ -634,6 +635,7 @@ static void *encode_thread(void *param)
End_status = -1;
goto exit;
}
printf("open success,fd:%d\n",fp);
if (cfg_encode->cfg_upd_enabled) {
fp_cfg = fopen((const char*)cfg_encode->cfg_file, "r");
@@ -709,6 +711,9 @@ static void *encode_thread(void *param)
}
memset(&encode_info, 0, sizeof(handle_t));
detectV4l2Support(&encode_info);
encode_info.init_qp = 30;
encode_info.enc_rc_mode = 2;
encode_info.chn_id = cfg_encode->chnid;
@@ -965,29 +970,31 @@ static void *encode_thread(void *param)
}
}
} else {
memset(&pFbSrcMem, 0, sizeof(pFbSrcMem));
pFbSrcMem.size = framesize;
pFbSrcMem.cached = 1;
if (!encode_info.v4l2_enable) {
memset(&pFbSrcMem, 0, sizeof(pFbSrcMem));
pFbSrcMem.size = framesize;
pFbSrcMem.cached = 1;
if (vdi_allocate_dma_memory(&pFbSrcMem) < 0) {
printf("Can not allocat dma Buffer chnid %d\n", encode_info.chn_id);
End_status = -1;
goto end;
if (vdi_allocate_dma_memory(&pFbSrcMem) < 0) {
printf("Can not allocat dma Buffer chnid %d\n", encode_info.chn_id);
End_status = -1;
goto end;
}
}
}
//for vps/sps/pps
for (i = 0; i < 3; i++) {
memset(&bsBuffer[i], 0, sizeof(bsBuffer[i]));
bsBuffer[i].size = ENC_STREAM_BUF_SIZE;
if (vdi_allocate_dma_memory(&bsBuffer[i]) < 0) {
printf("Can not allocat dma Buffer chnid %d\n", encode_info.chn_id);
End_status = -1;
goto end;
}
printf("[%s][%d]bsBuffer[%d].phys_addr:0x%x\n", \
__func__,__LINE__, i, bsBuffer[i].phys_addr);
}
// for (i = 0; i < 3; i++) {
// memset(&bsBuffer[i], 0, sizeof(bsBuffer[i]));
// bsBuffer[i].size = ENC_STREAM_BUF_SIZE;
// if (vdi_allocate_dma_memory(&bsBuffer[i]) < 0) {
// printf("Can not allocat dma Buffer chnid %d\n", encode_info.chn_id);
// End_status = -1;
// goto end;
// }
// printf("[%s][%d]bsBuffer[%d].phys_addr:0x%x\n", \
// __func__,__LINE__, i, bsBuffer[i].phys_addr);
// }
if (!encode_info.buf_stride)
{
@@ -1013,28 +1020,42 @@ static void *encode_thread(void *param)
printf("header buf addr:%lx %lx %lx\n",encode_info.header_buf_addr[0],encode_info.header_buf_addr[1],encode_info.header_buf_addr[2]);
printf("New allocate frame address y:0x%x cb:0x%x cr:0x%x\n",
encode_info.tahoe_enc_pic.inpt_buf_addr[0], encode_info.tahoe_enc_pic.inpt_buf_addr[1], encode_info.tahoe_enc_pic.inpt_buf_addr[2]);
#if 0
encode_info.out = (unsigned char *) malloc(outbuffer_len);
if (encode_info.out == NULL) {
printf("Can not malloc outbuffer\n");
End_status = -1;
goto end;
}
encode_info.input_yuvbuf = (unsigned char *) malloc(framesize);
if (encode_info.input_yuvbuf == NULL) {
printf("Can not allocat inputBuffer\n");
End_status = -1;
goto exit;
}
#endif
if (vl_tahoe_encoder_init(encode_info.enc_fmt, encode_info) < 0) {
printf("vl_tahoe_encoder_init failed chnid %d\n", encode_info.chn_id);
End_status = -1;
goto exit;
}
if (cfg_encode->power_test_enabled) {
for (pw = 0; pw < POWER_TEST_NUM_MAX; pw++) {
if (fread(inputBuffer, 1, framesize, fp) != framesize)
{
rewind(fp);
clearerr(fp);
if (fread(inputBuffer, 1, framesize, fp) != framesize) {
printf("read input file error!\n");
End_status = -1;
goto exit;
}
}
memcpy((void *)((unsigned long)pFbPwSrcMem[pw].virt_addr), inputBuffer, framesize);
}
}
// if (cfg_encode->power_test_enabled) {
// for (pw = 0; pw < POWER_TEST_NUM_MAX; pw++) {
// if (fread(inputBuffer, 1, framesize, fp) != framesize)
// {
// rewind(fp);
// clearerr(fp);
// if (fread(inputBuffer, 1, framesize, fp) != framesize) {
// printf("read input file error!\n");
// End_status = -1;
// goto exit;
// }
// }
// memcpy((void *)((unsigned long)pFbPwSrcMem[pw].virt_addr), inputBuffer, framesize);
// }
// }
gettimeofday(&timeStart, NULL);
for (i = 0; i < cfg_encode->num; i++) {
@@ -1051,10 +1072,15 @@ static void *encode_thread(void *param)
encode_info.tahoe_enc_pic.inpt_buf_addr[2] = pFbPwSrcMem[pw].phys_addr + (encode_info.buf_stride * encode_info.enc_height * 5 / 4);
}
} else {
if (encode_info.v4l2_enable) {
if (!get_input_buf_forv4l(&pFbSrcMem.virt_addr,&src_buf,&encode_info)) {
VLOG(ERR,"get_input_buf_forv4l failed\n");
}
}
if (fread(inputBuffer, 1, framesize, fp) != framesize)
{
rewind(fp);
clearerr(fp);
fseek(fp, 0, SEEK_SET);
if (fread(inputBuffer, 1, framesize, fp) != framesize) {
printf("read input file error!\n");
End_status = -1;
@@ -1062,6 +1088,7 @@ static void *encode_thread(void *param)
}
}
memcpy((void *)((unsigned long)pFbSrcMem.virt_addr), inputBuffer, framesize);
}
if (cfg_encode->osd_enabled) {
@@ -1090,27 +1117,34 @@ static void *encode_thread(void *param)
encode_info.poc = 0;
if (encode_info.enc_frame_type == FRAME_TYPE_IDR || encode_info.enc_frame_type == FRAME_TYPE_I)
{
vl_tahoe_encoder_generate_header(&encode_info);
ret = get_header(&encode_info, outbuffer, (unsigned int *)&dataLength);
if (ret == 0) {
write(outfd, (unsigned char *) outbuffer, dataLength);
if (!encode_info.v4l2_enable) {
vl_tahoe_encoder_generate_header(&encode_info);
ret = get_header(&encode_info, outbuffer, (unsigned int *)&dataLength);
if (ret == 0) {
write(outfd, (unsigned char *) outbuffer, dataLength);
}
}
}
vl_tahoe_encoder_encode(&encode_info);
if (encode_info.v4l2_enable) {
vl_tahoe_encoder_encode(&encode_info,&src_buf);
}
else {
vl_tahoe_encoder_encode(&encode_info,0);
}
ret = get_bsbframe(&encode_info, outbuffer, (unsigned int *)&dataLength, &frame_type);
gettimeofday(&writeStart, NULL);
if (ret == 0) {
write(outfd, (unsigned char *) outbuffer,
dataLength);
}
if (cfg_encode->ds_enabled) {
ret = get_dsframe(&encode_info, outbuffer, (unsigned int *)&dataLength);
if (ret == 0) {
write(dsfd, (unsigned char *) outbuffer,
dataLength);
}
write(outfd, outbuffer, dataLength);
}
// if (cfg_encode->ds_enabled) {
// ret = get_dsframe(&encode_info, outbuffer, (unsigned int *)&dataLength);
// if (ret == 0) {
// write(dsfd, (unsigned char *) outbuffer,
// dataLength);
// }
// }
gettimeofday(&writeEnd, NULL);
frameWriteTime = uTimeDiff(writeEnd, writeStart);
ioTime += frameWriteTime;
@@ -0,0 +1,42 @@
CC=aarch64-linux-gnu-gcc
CFLAG=
SRCFILE=a9_encoder_test.c
TARGET=a9_encoder_test
OBJ=a9_encoder_test.o
RAWDATAYUV=../yuv/nv21_480p.yuv
AMLAPP=./bin/tahoe_test
TARGET_DIR=$(LIBPLAYER_TARGET_DIR)/usr
LDFLAGS += -lm -lrt
INSTALL_FLAGS= -m 755
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) $(OBJ) -static -o $(TARGET)
$(OBJ): $(SRCFILE)
$(CC) -c $(CFLAGS) $< -o $@
install:$(TARGET)
install $(INSTALL_FLAGS) $(TARGET) $(TARGET_DIR)/bin
install $(INSTALL_FLAGS) $(RAWDATAYUV) $(TARGET_DIR)/bin
install $(INSTALL_FLAGS) $(AMLAPP) $(TARGET_DIR)/bin
.PHONY:clean
clean:
-rm -f *.o
-rm -f $(TARGET)
@@ -0,0 +1,165 @@
/***********************************************************************************************************************************
* Copyright(C) 2026,Amlogic All Rights Reserved
*
* @file : a9_encoder_test.c
*
* @brief : a9 encoder slt test
***********************************************************************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define RET_LEN 1024
int my_system(const char *cmd, char *result, int len)
{
assert(cmd != NULL && result != NULL
&& len >= RET_LEN);
FILE * fp = NULL;
int i = 0;
if ((fp = popen(cmd, "r")) == NULL ) {
printf("popen error!\n");
return -1;
}
if (fgets(result, len, fp) != NULL) {
printf("result: %s\n", result);
} else {
printf("fgets failed\n");
return -1;
}
while (result[i] != ' ')
i++;
result[i] = '\0';
pclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("Usage: [a9_encoder_test] [codec_id]\n");
printf(" codec_id: 1: h.264, 2 : h.265, 3 : h.264 + h.265\n");
return -1;
}
int ret = -1;
char* result_avc_2 = NULL;
char* result_avc_1 = NULL;
char* result_hevc_1 = NULL;
char* result_hevc_2 = NULL;
//h.264 test
if ((atoi(argv[1]) & 1) == 1) {
result_avc_1 = (char *) calloc(RET_LEN, sizeof(char));
result_avc_2 = (char *) calloc(RET_LEN, sizeof(char));
if (result_avc_1 == NULL || result_avc_2 == NULL) {
printf("avc calloc failed\n");
exit(1);
}
//h.264 test 1
system("tahoe_test /vendor/bin/nv21_480p.yuv /data/a9_es.h264.1 640 480 30 30 1000000 5 2 0 1 4");
sleep(1);
//h.264 test 2
system("tahoe_test /vendor/bin/nv21_480p.yuv /data/a9_es.h264.2 640 480 30 30 1000000 5 2 0 1 4");
if (my_system("md5sum /data/a9_es.h264.1", result_avc_1, RET_LEN) != 0) {
printf("md5sum /data/a9_es.h264.1 failed\n");
goto EXIT;
}
if (my_system("md5sum /data/a9_es.h264.2", result_avc_2, RET_LEN) != 0) {
printf("md5sum /data/a9_es.h264.2 failed\n");
goto EXIT;
}
if (strlen(result_avc_1) != 0 && strlen(result_avc_2) != 0) {
ret = strcmp(result_avc_1, result_avc_2);
}
printf("\n\n{\"result\": %s, \"item\": a9_h264_encoder}\n\n\n", \
(ret == 0) ? "true" : "false");
}
//h.265 test
ret = -1;
if ((atoi(argv[1]) & 2) == 2) {
result_hevc_1 = (char *) calloc(RET_LEN, sizeof(char));
result_hevc_2 = (char *) calloc(RET_LEN, sizeof(char));
if (result_hevc_1 == NULL || result_hevc_2 == NULL) {
printf("hevc calloc failed\n");
exit(1);
}
//h.265 test 1
system("tahoe_test /vendor/bin/nv21_480p.yuv /data/a9_es.h265.1 640 480 30 30 1000000 5 2 0 1 5");
sleep(1);
//h.265 test 2
system("tahoe_test /vendor/bin/nv21_480p.yuv /data/a9_es.h265.2 640 480 30 30 1000000 5 2 0 1 5");
if (my_system("md5sum /data/a9_es.h265.1", result_hevc_1, RET_LEN) != 0) {
printf("md5sum /data/a9_es.h265.1 failed\n");
goto EXIT;
}
if (my_system("md5sum /data/a9_es.h265.2", result_hevc_2, RET_LEN) != 0) {
printf("md5sum /data/a9_es.h265.2 failed\n");
goto EXIT;
}
if (strlen(result_hevc_1) != 0 && strlen(result_hevc_2) != 0) {
ret = strcmp(result_hevc_1, result_hevc_2);
}
printf("\n\n{\"result\": %s, \"item\": a9_h265_encoder}\n\n\n", \
(ret == 0) ? "true" : "false");
}
EXIT:
if (result_hevc_1 != NULL) {
free(result_hevc_1);
result_hevc_1 = NULL;
}
if (result_hevc_2 != NULL) {
free(result_hevc_2);
result_hevc_2 = NULL;
}
if (result_avc_1 != NULL) {
free(result_avc_1);
result_avc_1 = NULL;
}
if (result_avc_2 != NULL) {
free(result_avc_2);
result_avc_2 = NULL;
}
system("rm -f /data/a9_es*");
return 0;
}
@@ -0,0 +1,30 @@
# Copyright 2013 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := tahoe_test
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/bin
LOCAL_SRC_FILES_arm := tahoe_test
$(warning LOCAL_SRC_FILES_arm=$(LOCAL_SRC_FILES_arm))
LOCAL_CHECK_ELF_FILES := false
LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 legacy_proprietary
LOCAL_LICENSE_CONDITIONS := notice proprietary by_exception_only
include $(BUILD_PREBUILT)
@@ -0,0 +1,6 @@
1. make
2. push file to board:
yuv file: ../yuv/nv21_480p.yuv
app file: bin/tahoe_test
slt test file: a9_encoder_test
3. run test