680 lines
20 KiB
C
680 lines
20 KiB
C
/*
|
|
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
|
|
*
|
|
* This source code is subject to the terms and conditions defined in below
|
|
* which is part of this source code package.
|
|
*
|
|
* Description:
|
|
*/
|
|
|
|
// Copyright (C) 2019 Amlogic, Inc. All rights reserved.
|
|
//
|
|
// All information contained herein is Amlogic confidential.
|
|
//
|
|
// This software is provided to you pursuant to Software License
|
|
// Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be
|
|
// used only in accordance with the terms of this agreement.
|
|
//
|
|
// Redistribution and use in source and binary forms, with or without
|
|
// modification is strictly prohibited without prior written permission
|
|
// from Amlogic.
|
|
//
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
#define LOG_TAG "jenc_test"
|
|
#define LOG_LINE() printf("[%s:%d]\n", __FUNCTION__, __LINE__)
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/time.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/poll.h>
|
|
#include <stdint.h>
|
|
|
|
#include "jpegenc_api.h"
|
|
#include "jpegenc.h"
|
|
static int64_t total_enc_time=0;
|
|
static int total_enc_frame=0;
|
|
struct jpegenc_request_s {
|
|
u32 src;
|
|
u32 encoder_width;
|
|
u32 encoder_height;
|
|
u32 framesize;
|
|
u32 jpeg_quality;
|
|
u32 QuantTable_id;
|
|
u32 flush_flag;
|
|
u32 block_mode;
|
|
jpegenc_mem_type_e type;
|
|
jpegenc_frame_fmt_e input_fmt;
|
|
jpegenc_frame_fmt_e output_fmt;
|
|
|
|
u32 y_off;
|
|
u32 u_off;
|
|
u32 v_off;
|
|
|
|
u32 y_stride;
|
|
u32 u_stride;
|
|
u32 v_stride;
|
|
|
|
u32 h_stride;
|
|
};
|
|
|
|
//#include <media/stagefright/foundation/ALooper.h>
|
|
//using namespace android;
|
|
#define ENCODER_PATH "/dev/jpegenc"
|
|
|
|
#define JPEGENC_IOC_MAGIC 'J'
|
|
|
|
#define JPEGENC_IOC_GET_DEVINFO _IOW(JPEGENC_IOC_MAGIC, 0xf0, uint32_t)
|
|
#define JPEGENC_IOC_GET_BUFFINFO _IOW(JPEGENC_IOC_MAGIC, 0x00, uint32_t)
|
|
#define JPEGENC_IOC_CONFIG_INIT _IOW(JPEGENC_IOC_MAGIC, 0x01, uint32_t)
|
|
#define JPEGENC_IOC_NEW_CMD _IOW(JPEGENC_IOC_MAGIC, 0x02, uint32_t)
|
|
#define JPEGENC_IOC_GET_STAGE _IOW(JPEGENC_IOC_MAGIC, 0x03, uint32_t)
|
|
#define JPEGENC_IOC_GET_OUTPUT_SIZE _IOW(JPEGENC_IOC_MAGIC, 0x04, uint32_t)
|
|
#define JPEGENC_IOC_SET_EXT_QUANT_TABLE _IOW(JPEGENC_IOC_MAGIC, 0x05, uint32_t)
|
|
#define JPEGENC_IOC_QUERY_DMA_SUPPORT _IOW(JPEGENC_IOC_MAGIC, 0x06, uint32_t)
|
|
#define JPEGENC_IOC_CONFIG_DMA_INPUT _IOW(JPEGENC_IOC_MAGIC, 0x07, int32_t)
|
|
#define JPEGENC_IOC_RELEASE_DMA_INPUT _IOW(JPEGENC_IOC_MAGIC, 0x08, uint32_t)
|
|
#define JPEGENC_IOC_NEW_CMD2 _IOW(JPEGENC_IOC_MAGIC, 0x09, struct jpegenc_request_s)
|
|
|
|
#define JPEGENC_ENCODER_IDLE 0
|
|
#define JPEGENC_ENCODER_START 1
|
|
/* #define JPEGENC_ENCODER_SOS_HEADER 2 */
|
|
#define JPEGENC_ENCODER_MCU 3
|
|
#define JPEGENC_ENCODER_DONE 4
|
|
|
|
//#define simulation
|
|
#define ALIGNE_64(a) (((a + 63) >> 6) << 6)
|
|
static int64_t file_read_time_total = 0;
|
|
typedef unsigned char uint8_t;
|
|
typedef unsigned int uint32_t;
|
|
|
|
#define ENCODE_DONE_TIMEOUT 5000
|
|
|
|
//#define DEBUG_TIME
|
|
#ifdef DEBUG_TIME
|
|
static struct timeval start_test, end_test;
|
|
static unsigned long long g_total_time;
|
|
#define PER_FRAME 100
|
|
static unsigned int g_frame_cnt, g_avg_time;
|
|
#endif
|
|
|
|
#define JPEGENC_FLUSH_FLAG_INPUT 0x1
|
|
#define JPEGENC_FLUSH_FLAG_OUTPUT 0x2
|
|
|
|
void RGB_to_YUV(int w, int h, unsigned char* yuv, unsigned char* rgb) {
|
|
unsigned char val_r = rgb[0], val_g = rgb[1], val_b = rgb[2];
|
|
int y, u = 0, v = 0;
|
|
y = 0.30078 * val_r + 0.5859 * val_g + 0.11328 * val_b;
|
|
if (y > 255) {
|
|
y = 255;
|
|
} else if (y < 0) {
|
|
y = 0;
|
|
}
|
|
yuv[0] = y;
|
|
if (0 == h % 2 && 0 == w % 2) {
|
|
u = -0.11328 * val_r - 0.33984 * val_g + 0.51179 * val_b + 128;
|
|
if (u > 255) {
|
|
u = 255;
|
|
} else if (u < 0) {
|
|
u = 0;
|
|
}
|
|
yuv[1] = u;
|
|
v = 0.51179 * val_r - 0.429688 * val_g - 0.08203 * val_b + 128;
|
|
if (v > 255) {
|
|
v = 255;
|
|
} else if (v < 0) {
|
|
v = 0;
|
|
}
|
|
yuv[2] = v;
|
|
}
|
|
}
|
|
|
|
long hw_encode_init(int timeout) {
|
|
int ret = -1;
|
|
uint32_t buff_info[7];
|
|
|
|
hw_jpegenc_t* hw_info = (hw_jpegenc_t*) malloc(sizeof(hw_jpegenc_t));
|
|
if (!hw_info)
|
|
return (long)NULL;
|
|
|
|
memset(hw_info,0,sizeof(hw_jpegenc_t));
|
|
hw_info->jpeg_size = 0;
|
|
|
|
hw_info->dev_fd = open(ENCODER_PATH, O_RDWR);
|
|
|
|
if (hw_info->dev_fd < 0) {
|
|
printf("hw_encode open device fail, %d:%s\n", errno, strerror(errno));
|
|
goto EXIT_INIT;
|
|
}
|
|
|
|
memset(buff_info, 0, sizeof(buff_info));
|
|
|
|
ret = ioctl(hw_info->dev_fd, JPEGENC_IOC_GET_BUFFINFO, &buff_info[0]);
|
|
|
|
if ((ret) || (buff_info[0] == 0)) {
|
|
printf("hw_encode -- no buffer information\n");
|
|
goto EXIT_INIT;
|
|
}
|
|
|
|
hw_info->mmap_buff.addr = (unsigned char*) mmap(0, buff_info[0], PROT_READ | PROT_WRITE, MAP_SHARED, hw_info->dev_fd, 0);
|
|
|
|
if (hw_info->mmap_buff.addr == MAP_FAILED) {
|
|
printf("hw_encode Error: failed to map framebuffer device to memory.\n");
|
|
goto EXIT_INIT;
|
|
} /*else
|
|
printf("mapped address is %p\n", hw_info->mmap_buff.addr);*/
|
|
|
|
ret = ioctl(hw_info->dev_fd, JPEGENC_IOC_CONFIG_INIT, NULL);
|
|
|
|
hw_info->mmap_buff.size = buff_info[0];
|
|
hw_info->input_buf.addr = hw_info->mmap_buff.addr + buff_info[1];
|
|
hw_info->input_buf.size = buff_info[2];
|
|
hw_info->assit_buf.addr = hw_info->mmap_buff.addr + buff_info[3];
|
|
hw_info->assit_buf.size = buff_info[4];
|
|
hw_info->output_buf.addr = hw_info->mmap_buff.addr + buff_info[5];
|
|
hw_info->output_buf.size = buff_info[6];
|
|
hw_info->timeout = timeout;
|
|
|
|
if (hw_info->timeout == 0)
|
|
hw_info->timeout = -1;
|
|
|
|
//printf("hw_info->mmap_buff.size, 0x%x, hw_info->input_buf.addr:0x%p\n", hw_info->mmap_buff.size, hw_info->input_buf.addr);
|
|
//printf("hw_info->assit_buf.addr, 0x%p, hw_info->output_buf.addr:0x%p\n", hw_info->assit_buf.addr, hw_info->output_buf.addr);
|
|
|
|
return (long)hw_info;
|
|
|
|
EXIT_INIT:
|
|
if (hw_info->mmap_buff.addr) {
|
|
munmap(hw_info->mmap_buff.addr, hw_info->mmap_buff.size);
|
|
hw_info->mmap_buff.addr = NULL;
|
|
}
|
|
|
|
if (hw_info->dev_fd >= 0) {
|
|
close(hw_info->dev_fd);
|
|
hw_info->dev_fd = -1;
|
|
}
|
|
if (hw_info != NULL)
|
|
free(hw_info);
|
|
|
|
return (long)NULL;
|
|
}
|
|
|
|
int hw_encode_uninit(jpegenc_handle_t handle) {
|
|
int ret = 0;
|
|
uint32_t buff_info[5];
|
|
|
|
hw_jpegenc_t* hw_info = (hw_jpegenc_t*) handle;
|
|
|
|
if (!hw_info)
|
|
return -1;
|
|
|
|
if (hw_info->mmap_buff.addr) {
|
|
munmap(hw_info->mmap_buff.addr, hw_info->mmap_buff.size);
|
|
hw_info->mmap_buff.addr = NULL;
|
|
}
|
|
|
|
if (ioctl(hw_info->dev_fd, JPEGENC_IOC_RELEASE_DMA_INPUT, NULL) < 0)
|
|
printf("JPEGENC_IOC_RELEASE_DMA_INPUT fail %d %s\n", errno, strerror(errno));
|
|
|
|
if (hw_info->dev_fd >= 0)
|
|
close(hw_info->dev_fd);
|
|
|
|
hw_info->dev_fd = -1;
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void rgb32to24(const uint8_t *src, uint8_t *dst, int src_size) {
|
|
int i;
|
|
int num_pixels = src_size >> 2;
|
|
for (i = 0; i < num_pixels; i++) {
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
*dst++ = *src++;
|
|
src++;
|
|
}
|
|
}
|
|
|
|
static int RGBA32_To_RGB24Canvas(hw_jpegenc_t* hw_info) {
|
|
unsigned char* src = NULL;
|
|
unsigned char* dst = NULL;
|
|
int bytes_per_line = hw_info->width * 4;
|
|
unsigned int canvas_w = (((hw_info->width * 3) + 31) >> 5) << 5;
|
|
int mb_h = hw_info->height;
|
|
int i;
|
|
|
|
src = (unsigned char*) hw_info->src;
|
|
dst = hw_info->input_buf.addr;
|
|
if (canvas_w != (hw_info->width * 3)) {
|
|
for (i = 0; i < mb_h; i++) {
|
|
rgb32to24(src, dst, bytes_per_line);
|
|
dst += canvas_w;
|
|
src += bytes_per_line;
|
|
}
|
|
} else {
|
|
rgb32to24(src, dst, bytes_per_line * mb_h);
|
|
}
|
|
return canvas_w * mb_h;
|
|
}
|
|
|
|
static int RGB24_To_RGB24Canvas(hw_jpegenc_t* hw_info) {
|
|
unsigned char* src = NULL;
|
|
unsigned char* dst = NULL;
|
|
int bytes_per_line = hw_info->width * 3;
|
|
int canvas_w = (((hw_info->width * 3) + 31) >> 5) << 5;
|
|
int mb_h = hw_info->height;
|
|
unsigned int i;
|
|
|
|
src = (unsigned char*) hw_info->src;
|
|
dst = hw_info->input_buf.addr;
|
|
if (bytes_per_line != canvas_w) {
|
|
for (i = 0; i < hw_info->height; i++) {
|
|
memcpy(dst, src, bytes_per_line);
|
|
dst += canvas_w;
|
|
src += bytes_per_line;
|
|
}
|
|
} else {
|
|
memcpy(dst, src, bytes_per_line * mb_h);
|
|
}
|
|
return canvas_w * mb_h;
|
|
}
|
|
|
|
static int YUV422_To_Canvas(hw_jpegenc_t* hw_info) {
|
|
unsigned char* src = NULL;
|
|
unsigned char* dst = NULL;
|
|
int bytes_per_line = hw_info->width * 2;
|
|
int canvas_w = (((hw_info->width * 2) + 31) >> 5) << 5;
|
|
int mb_h = hw_info->height;
|
|
unsigned int i;
|
|
|
|
src = (unsigned char*) hw_info->src;
|
|
dst = hw_info->input_buf.addr;
|
|
if (bytes_per_line != canvas_w) {
|
|
for (i = 0; i < hw_info->height; i++) {
|
|
memcpy(dst, src, bytes_per_line);
|
|
dst += canvas_w;
|
|
src += bytes_per_line;
|
|
}
|
|
} else {
|
|
memcpy(dst, src, bytes_per_line * mb_h);
|
|
}
|
|
return canvas_w * mb_h;
|
|
}
|
|
|
|
static int encode_poll(int fd, int timeout) {
|
|
struct pollfd poll_fd[1];
|
|
poll_fd[0].fd = fd;
|
|
poll_fd[0].events = POLLIN | POLLERR;
|
|
return poll(poll_fd, 1, timeout);
|
|
}
|
|
|
|
#ifdef simulation
|
|
static unsigned copy_to_local(hw_jpegenc_t* hw_info)
|
|
{
|
|
int size = 0;
|
|
unsigned char* src = NULL;
|
|
unsigned char* dst = NULL;
|
|
|
|
size = hw_info->input_size;
|
|
src = (unsigned char*)hw_info->src;
|
|
dst = hw_info->input_buf.addr;
|
|
|
|
memcpy(dst, src, size);
|
|
|
|
return size;
|
|
}
|
|
#else
|
|
static unsigned copy_to_local(hw_jpegenc_t* hw_info) {
|
|
unsigned offset = 0;
|
|
int luma_stride = 0, chroma_stride = 0;
|
|
unsigned i = 0;
|
|
unsigned total_size = 0;
|
|
unsigned char* src = NULL;
|
|
unsigned char* dst = NULL;
|
|
int plane_num = 2;
|
|
|
|
//unsigned int aligned_height = ((hw_info->height + 15) >> 4) << 4;
|
|
|
|
if ((hw_info->in_format == FMT_YUV420) || (hw_info->in_format == FMT_YUV444_PLANE) || (hw_info->in_format == FMT_RGB888_PLANE))
|
|
plane_num = 3;
|
|
else
|
|
plane_num = 2;
|
|
|
|
luma_stride = hw_info->y_stride;
|
|
|
|
// if (hw_info->in_format == FMT_YUV420) {
|
|
// luma_stride = ((hw_info->width + 63) >> 6) << 6;
|
|
// chroma_stride = luma_stride / 2; //TODO
|
|
// } else {
|
|
// luma_stride = ((hw_info->width + 31) >> 5) << 5;
|
|
// chroma_stride = luma_stride;
|
|
// }
|
|
|
|
src = (unsigned char*) hw_info->src;
|
|
dst = hw_info->input_buf.addr;
|
|
|
|
if (luma_stride != hw_info->width) {
|
|
printf("copy y line by line\n");
|
|
|
|
for (i = 0; i < hw_info->height; i++) {
|
|
memcpy(dst, src, hw_info->width);
|
|
dst += luma_stride;
|
|
src += hw_info->width;
|
|
}
|
|
} else {
|
|
memcpy(dst, src, hw_info->height * hw_info->width);
|
|
}
|
|
|
|
if (plane_num == 2) {
|
|
offset = hw_info->h_stride * luma_stride;
|
|
|
|
chroma_stride = luma_stride;
|
|
printf("offset=%d\n", offset);
|
|
|
|
src = (unsigned char*) (hw_info->src + hw_info->width * hw_info->height);
|
|
dst = (unsigned char*) (hw_info->input_buf.addr + offset);
|
|
|
|
if (chroma_stride != hw_info->width) {
|
|
for (i = 0; i < hw_info->height / 2; i++) {
|
|
memcpy(dst, src, hw_info->width);
|
|
dst += chroma_stride;
|
|
src += hw_info->width;
|
|
}
|
|
} else {
|
|
memcpy(dst, src, hw_info->width * hw_info->height / 2);
|
|
}
|
|
} else if (plane_num == 3) {
|
|
if (hw_info->in_format == FMT_YUV420) {
|
|
chroma_stride = luma_stride / 2;
|
|
offset = hw_info->h_stride * luma_stride;
|
|
|
|
hw_info->u_stride = hw_info->y_stride / 2;
|
|
hw_info->v_stride = hw_info->y_stride / 2;
|
|
|
|
printf("uoff=%d\n", offset);
|
|
int i=0;
|
|
src = (unsigned char*) (hw_info->src + hw_info->width * hw_info->height);
|
|
dst = (unsigned char*) (hw_info->input_buf.addr + offset);
|
|
|
|
for (i = 0; i < hw_info->height / 2; i++) {
|
|
memcpy( dst, src, hw_info->width / 2);
|
|
src += hw_info->width / 2;
|
|
dst += chroma_stride;
|
|
}
|
|
|
|
offset = hw_info->h_stride * luma_stride + (chroma_stride * hw_info->h_stride / 2);
|
|
printf("voff=%d\n", offset);
|
|
|
|
src = (unsigned char*) (hw_info->src + hw_info->width * hw_info->height * 5 / 4);
|
|
dst = (unsigned char*) (hw_info->input_buf.addr + offset);
|
|
|
|
for (i = 0; i < hw_info->height / 2; i++) {
|
|
memcpy( dst, src, hw_info->width / 2);
|
|
src += hw_info->width / 2;
|
|
dst += chroma_stride;
|
|
}
|
|
} else if (hw_info->in_format == FMT_YUV444_PLANE) {
|
|
chroma_stride = luma_stride;
|
|
offset = hw_info->h_stride * luma_stride;
|
|
|
|
hw_info->u_stride = hw_info->y_stride;
|
|
hw_info->v_stride = hw_info->y_stride;
|
|
|
|
printf("uoff=%d\n", offset);
|
|
int i=0;
|
|
src = (unsigned char*) (hw_info->src + hw_info->width * hw_info->height);
|
|
dst = (unsigned char*) (hw_info->input_buf.addr + offset);
|
|
|
|
for (i = 0; i < hw_info->height; i++) {
|
|
memcpy( dst, src, hw_info->width);
|
|
src += hw_info->width;
|
|
dst += chroma_stride;
|
|
}
|
|
|
|
offset = hw_info->h_stride * luma_stride * 2;
|
|
printf("voff=%d\n", offset);
|
|
|
|
src = (unsigned char*) (hw_info->src + hw_info->width * hw_info->height * 2);
|
|
dst = (unsigned char*) (hw_info->input_buf.addr + offset);
|
|
|
|
for (i = 0; i < hw_info->height; i++) {
|
|
memcpy( dst, src, hw_info->width);
|
|
src += hw_info->width;
|
|
dst += chroma_stride;
|
|
}
|
|
}
|
|
}
|
|
printf("luma_stride=%d, h_stride=%d, hw_info->bpp=%d\n",
|
|
luma_stride, hw_info->h_stride, hw_info->bpp);
|
|
total_size = luma_stride * hw_info->h_stride * hw_info->bpp / 8;
|
|
return total_size;
|
|
}
|
|
#endif
|
|
static int64_t GetNowUs() {
|
|
struct timeval tv;
|
|
gettimeofday(&tv, NULL);
|
|
|
|
return (int64_t)(tv.tv_sec) * 1000000 + (int64_t)(tv.tv_usec);
|
|
}
|
|
static size_t start_encoder(hw_jpegenc_t* hw_info) {
|
|
int i;
|
|
int bpp;
|
|
uint32_t size = 0;
|
|
uint32_t cmd[34], status;
|
|
uint32_t in_format = hw_info->in_format;
|
|
uint32_t info_off;
|
|
|
|
#ifdef simulation
|
|
hw_info->src_size = copy_to_local(hw_info);
|
|
cmd[5] = hw_info->src_size;
|
|
#else
|
|
//printf("hw_info->type=%d\n", hw_info->type);
|
|
if (hw_info->type == JPEGENC_LOCAL_BUFF) {
|
|
if ((hw_info->in_format == FMT_RGB888) || (hw_info->in_format == FMT_YUV444_SINGLE)) {
|
|
hw_info->src_size = RGB24_To_RGB24Canvas(hw_info);
|
|
} else if (hw_info->in_format == FMT_RGBA8888) {
|
|
hw_info->src_size = RGBA32_To_RGB24Canvas(hw_info);
|
|
hw_info->in_format = FMT_RGB888;
|
|
} else if (hw_info->in_format == FMT_YUV422_SINGLE) {
|
|
//printf("[%s:%d]\n", __FUNCTION__, __LINE__);
|
|
hw_info->src_size = YUV422_To_Canvas(hw_info);
|
|
} else {
|
|
//printf("[%s:%d]\n", __FUNCTION__, __LINE__);
|
|
hw_info->src_size = copy_to_local(hw_info);
|
|
}
|
|
cmd[5] = hw_info->src_size;
|
|
//printf("cmd[5]=%d\n", cmd[5]);
|
|
|
|
} else if (hw_info->type == JPEGENC_DMA_BUFF) {
|
|
cmd[5] = hw_info->width * hw_info->height * hw_info->bpp / 8;
|
|
}
|
|
#endif
|
|
//printf("[%s:%d]\n", __FUNCTION__, __LINE__);
|
|
cmd[0] = hw_info->type; //input buffer type
|
|
cmd[1] = hw_info->in_format;
|
|
cmd[2] = hw_info->out_format;
|
|
cmd[3] = hw_info->width;
|
|
cmd[4] = hw_info->height;
|
|
cmd[6] = (hw_info->type == JPEGENC_LOCAL_BUFF) ? 0 : hw_info->canvas;
|
|
cmd[7] = hw_info->quality;
|
|
cmd[8] = hw_info->qtbl_id;
|
|
cmd[9] = (hw_info->type == JPEGENC_LOCAL_BUFF) ? (JPEGENC_FLUSH_FLAG_INPUT | JPEGENC_FLUSH_FLAG_OUTPUT) : JPEGENC_FLUSH_FLAG_OUTPUT;
|
|
cmd[10] = hw_info->block_mode;
|
|
|
|
cmd[11] = hw_info->y_stride;
|
|
cmd[12] = hw_info->y_stride;
|
|
cmd[13] = hw_info->y_stride;
|
|
cmd[14] = hw_info->h_stride;
|
|
|
|
if (hw_info->type == JPEGENC_DMA_BUFF) {
|
|
info_off = 14;
|
|
cmd[info_off++] = hw_info->dma_buf_planes;
|
|
cmd[info_off++] = hw_info->dma_fd[0];
|
|
cmd[info_off++] = hw_info->dma_fd[1];
|
|
cmd[info_off++] = hw_info->dma_fd[2];
|
|
}
|
|
|
|
struct jpegenc_request_s request;
|
|
request.type = hw_info->type;
|
|
request.input_fmt = hw_info->in_format;
|
|
request.output_fmt = hw_info->out_format;
|
|
request.encoder_width = hw_info->width;
|
|
request.encoder_height = hw_info->height;
|
|
request.src = (hw_info->type == JPEGENC_LOCAL_BUFF) ? 0 : hw_info->canvas;
|
|
|
|
request.jpeg_quality = hw_info->quality;
|
|
request.QuantTable_id = hw_info->qtbl_id;
|
|
request.flush_flag = (hw_info->type == JPEGENC_LOCAL_BUFF) ? (JPEGENC_FLUSH_FLAG_INPUT | JPEGENC_FLUSH_FLAG_OUTPUT) : JPEGENC_FLUSH_FLAG_OUTPUT;
|
|
request.block_mode = hw_info->block_mode;
|
|
|
|
request.y_off = hw_info->y_off;
|
|
request.u_off = hw_info->u_off;
|
|
request.v_off = hw_info->v_off;
|
|
request.y_stride = hw_info->y_stride;
|
|
request.u_stride = hw_info->u_stride;
|
|
request.v_stride = hw_info->v_stride;
|
|
request.h_stride = hw_info->h_stride;
|
|
request.framesize = cmd[5];
|
|
|
|
ioctl(hw_info->dev_fd, JPEGENC_IOC_NEW_CMD, cmd);
|
|
//ioctl(hw_info->dev_fd, JPEGENC_IOC_NEW_CMD2, (unsigned long)(&request));
|
|
|
|
if (encode_poll(hw_info->dev_fd, hw_info->timeout) <= 0) {
|
|
printf("hw_encode: poll fail\n");
|
|
return 0;
|
|
}
|
|
|
|
ioctl(hw_info->dev_fd, JPEGENC_IOC_GET_STAGE, &status);
|
|
|
|
if (status == JPEGENC_ENCODER_DONE) {
|
|
cmd[0] = 0;
|
|
cmd[1] = 0;
|
|
|
|
ioctl(hw_info->dev_fd, JPEGENC_IOC_GET_OUTPUT_SIZE, &cmd);
|
|
|
|
if ((cmd[0] > 0) && (cmd[1] > 0)) {
|
|
//printf("hw_encode: done head size:%d, size: %d\n", cmd[0], cmd[1]);
|
|
memcpy(hw_info->dst, hw_info->assit_buf.addr, cmd[0]);
|
|
memcpy(hw_info->dst + cmd[0], hw_info->output_buf.addr, cmd[1]);
|
|
|
|
size = cmd[0] + cmd[1];
|
|
} else {
|
|
printf("hw_encode: output buffer size error: bitstream buffer size: %d, jpeg size: %d, output buffer size: %d\n",
|
|
hw_info->output_buf.size, cmd[1], hw_info->dst_size);
|
|
size = 0;
|
|
}
|
|
}
|
|
//printf("[%s:%d]\n", __FUNCTION__, __LINE__);
|
|
return size;
|
|
}
|
|
|
|
int hw_encode(jpegenc_handle_t handle, jpegenc_frame_info_t frame_info, uint8_t *dst, uint32_t* datalen) {
|
|
int ret;
|
|
|
|
#ifdef DEBUG_TIME
|
|
uint32_t total_time = 0;
|
|
gettimeofday(&start_test, NULL);
|
|
#endif
|
|
|
|
if (handle == (long)NULL) {
|
|
printf("[%s:%d] handle is NULL!\n", __FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
if ((frame_info.mem_type == JPEGENC_LOCAL_BUFF) && (frame_info.YCbCr[0] == 0)) {
|
|
printf("[%s:%d]param err!, src is NULL!\n", __FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
if ((frame_info.mem_type == JPEGENC_DMA_BUFF) && ((int)frame_info.YCbCr[0] < 0)) {
|
|
printf("[%s:%d]param err!, dma_fd < 0\n", __FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
if (dst == NULL) {
|
|
printf("[%s:%d]param err!, dst is NULL!\n", __FUNCTION__, __LINE__);
|
|
return -1;
|
|
}
|
|
|
|
hw_jpegenc_t* hw_info = (hw_jpegenc_t*)handle;
|
|
|
|
hw_info->qtbl_id = 0;
|
|
hw_info->quality = frame_info.quality;
|
|
hw_info->in_format = (jpegenc_frame_fmt_e) frame_info.iformat;
|
|
hw_info->width = frame_info.width;
|
|
hw_info->height = frame_info.height;
|
|
hw_info->y_stride = frame_info.w_stride;
|
|
hw_info->u_stride = frame_info.w_stride;
|
|
hw_info->v_stride = frame_info.w_stride;
|
|
hw_info->h_stride = frame_info.h_stride;
|
|
hw_info->canvas = 0;
|
|
hw_info->dst = dst;
|
|
//printf("hw_info->dst=%p\n", dst);
|
|
hw_info->dst_size = *datalen;
|
|
|
|
switch (hw_info->in_format) {
|
|
case FMT_NV21:
|
|
hw_info->bpp = 12;
|
|
break;
|
|
case FMT_RGB888:
|
|
hw_info->bpp = 24;
|
|
break;
|
|
case FMT_YUV422_SINGLE:
|
|
hw_info->bpp = 16;
|
|
break;
|
|
case FMT_YUV444_PLANE:
|
|
case FMT_RGB888_PLANE:
|
|
case FMT_YUV444_SINGLE:
|
|
hw_info->bpp = 24;
|
|
break;
|
|
default:
|
|
hw_info->bpp = 12;
|
|
}
|
|
|
|
hw_info->type = frame_info.mem_type;
|
|
if (hw_info->type == JPEGENC_LOCAL_BUFF) {
|
|
hw_info->src = (uint8_t *)frame_info.YCbCr[0];
|
|
} else if (hw_info->type == JPEGENC_DMA_BUFF) {
|
|
hw_info->dma_buf_planes = frame_info.plane_num;
|
|
hw_info->dma_fd[0] = frame_info.YCbCr[0];
|
|
hw_info->dma_fd[1] = frame_info.YCbCr[1];
|
|
hw_info->dma_fd[2] = frame_info.YCbCr[2];
|
|
}
|
|
hw_info->out_format = (jpegenc_frame_fmt_e) frame_info.oformat;
|
|
|
|
hw_info->jpeg_size = start_encoder(hw_info);
|
|
|
|
*datalen = hw_info->jpeg_size;
|
|
|
|
#ifdef DEBUG_TIME
|
|
gettimeofday(&end_test, NULL);
|
|
total_time = (end_test.tv_sec - start_test.tv_sec) * 1000000 + end_test.tv_usec - start_test.tv_usec;
|
|
g_total_time += total_time;
|
|
g_frame_cnt++;
|
|
if (g_frame_cnt >= PER_FRAME)
|
|
{
|
|
g_avg_time = g_total_time / PER_FRAME;
|
|
g_frame_cnt = 0;
|
|
g_total_time = 0;
|
|
printf("jpeg hw_encode: average per frame need %d us\n", g_avg_time);
|
|
}
|
|
//printf("hw_encode: need time: %d us, jpeg size:%zu\n", total_time, hw_info->jpeg_size);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|