Files
BPI-CM9-Linux/aml-comp/hardware/amlogic/libencoder/amvenc/amvenc_lib/amvenc.c
T
2026-08-24 10:03:24 +08:00

285 lines
8.8 KiB
C

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "amvenc_common.h"
#include "amvenc.h"
#include "amvenc_multi.h"
#include "amvenc_264.h"
#include "amvenc_265.h"
#include "amvenc_vers.h"
#include "amvenc_tahoe.h"
#define AMVENC_MULTI_DEVICE "/dev/amvenc_multi"
#define AMVENC_264_DEVICE "/dev/amvenc_avc"
#define AMVENC_265_DEVICE "/dev/HevcEnc"
#define AMVENC_VERS_DEVICE "/dev/vc8000"
#define AMVENC_TAHOE_DEVICE "/dev/tahoe"
typedef enum amvenc_hw_e {
AMVENC_UNKNOWN,
AMVENC_MULTI,
AMVENC_264,
AMVENC_265,
AMVENC_VERS,
AMVENC_TAHOE,
AMVENC_MAX,
} amvenc_hw_t;
struct amvenc_manager_s {
int (*loadModule) (void);
amvenc_handle_t (*init) (amvenc_codec_id_t codec_id,
amvenc_info_t encode_info,
amvenc_qp_param_t* qp_tbl);
amvenc_metadata_t (*generate_header) (amvenc_handle_t handle,
unsigned char *pHeader,
unsigned int *pLength);
amvenc_metadata_t (*encode) (amvenc_handle_t handle,
amvenc_frame_info_t frame_info,
amvenc_frame_type_t type,
unsigned char* out,
amvenc_buffer_info_t *in_buffer_info,
amvenc_buffer_info_t *ret_buffer_info);
int (*change_bitrate) (amvenc_handle_t handle, int bitRate);
int (*destroy) (amvenc_handle_t handle);
int (*unloadModule) (void);
};
static const struct amvenc_manager_s amvenc_multi_data = {
.loadModule = amvenc_multi_load_Module,
.init = amvenc_multi_init,
.generate_header = amvenc_multi_generate_header,
.encode = amvenc_multi_encode,
.change_bitrate = amvenc_multi_change_bitrate,
.destroy = amvenc_multi_destroy,
.unloadModule = amvenc_multi_unload_Module,
};
static const struct amvenc_manager_s amvenc_264_data = {
.loadModule = amvenc_264_load_Module,
.init = amvenc_264_init,
.generate_header = amvenc_264_generate_header,
.encode = amvenc_264_encode,
.change_bitrate = amvenc_264_change_bitrate,
.destroy = amvenc_264_destroy,
.unloadModule = amvenc_264_unload_Module,
};
static const struct amvenc_manager_s amvenc_265_data = {
.loadModule = amvenc_265_load_Module,
.init = amvenc_265_init,
.generate_header = amvenc_265_generate_header,
.encode = amvenc_265_encode,
.change_bitrate = amvenc_265_change_bitrate,
.destroy = amvenc_265_destroy,
.unloadModule = amvenc_265_unload_Module,
};
static const struct amvenc_manager_s amvenc_vers_data = {
.loadModule = amvenc_vers_load_Module,
.init = amvenc_vers_init,
.generate_header = amvenc_vers_generate_header,
.encode = amvenc_vers_encode,
.change_bitrate = amvenc_vers_change_bitrate,
.destroy = amvenc_vers_destroy,
.unloadModule = amvenc_vers_unload_Module,
};
static const struct amvenc_manager_s amvenc_tahoe_data = {
.loadModule = amvenc_tahoe_load_Module,
.init = amvenc_tahoe_init,
.generate_header = amvenc_tahoe_generate_header,
.encode = amvenc_tahoe_encode,
.change_bitrate = amvenc_tahoe_change_bitrate,
.destroy = amvenc_tahoe_destroy,
.unloadModule = amvenc_tahoe_unload_Module,
};
const static struct amvenc_manager_s *amvenc_manager[] = {
NULL,
&amvenc_multi_data,
&amvenc_264_data,
&amvenc_265_data,
&amvenc_vers_data,
&amvenc_tahoe_data,
NULL,
};
typedef struct amvencHandle_s {
amvenc_hw_t hw_type;
amvenc_handle_t codec_handle;
} amvencHandle;
int selectHW(amvenc_codec_id_t codec_id, int *hw_type)
{
int ret = -1;
VLOG(DEBUG, "selectEncoder");
if (AML_CODEC_ID_H264 == codec_id) {
if (access(AMVENC_MULTI_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_MULTI;
VLOG(DEBUG, "amvenc_multi 264 present");
ret = 0;
}
else if (access(AMVENC_264_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_264;
VLOG(DEBUG, "amvenc_264 present");
ret = 0;
}
else if (access(AMVENC_VERS_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_VERS;
VLOG(DEBUG, "amvenc_vers present");
ret = 0;
}
else if (access(AMVENC_TAHOE_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_TAHOE;
VLOG(DEBUG, "amvenc_tahoe present");
ret = 0;
}
else {
VLOG(ERR, "can not find available h.264 driver!!!,please check!");
}
}
if (AML_CODEC_ID_H265 == codec_id) {
if (access(AMVENC_MULTI_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_MULTI;
VLOG(DEBUG, "amvenc_multi 265 present");
ret = 0;
}
else if (access(AMVENC_265_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_265;
VLOG(DEBUG, "amvenc_265 present");
ret = 0;
}
else if (access(AMVENC_VERS_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_VERS;
VLOG(DEBUG, "amvenc_vers present");
ret = 0;
}
else if (access(AMVENC_TAHOE_DEVICE, F_OK ) != -1) {
*hw_type = AMVENC_TAHOE;
VLOG(DEBUG, "amvenc_tahoe present");
ret = 0;
}
else {
VLOG(ERR, "can not find available h.265 driver!!!,please check!");
}
}
return ret;
}
amvenc_handle_t amvenc_init(amvenc_codec_id_t codec_id,
amvenc_info_t encode_info,
amvenc_qp_param_t* qp_tbl)
{
int ret = -1;
int hw_type = 0;
amvencHandle* mHandle = (amvencHandle *) malloc(sizeof(amvencHandle));
if (mHandle == NULL)
goto exit;
amvenc_set_log_level(INFO);
ret = selectHW(codec_id, &hw_type);
if (ret != 0)
goto exit;
mHandle->hw_type = hw_type;
if (NULL == amvenc_manager[mHandle->hw_type])
goto exit;
if (NULL == amvenc_manager[mHandle->hw_type]->loadModule)
goto exit;
ret = amvenc_manager[mHandle->hw_type]->loadModule();
if (ret != 0)
goto exit;
if (NULL == amvenc_manager[mHandle->hw_type]->init)
goto exit;
mHandle->codec_handle = amvenc_manager[mHandle->hw_type]->init(codec_id, encode_info, qp_tbl);
if (mHandle->codec_handle == 0)
goto exit;
return (amvenc_handle_t)mHandle;
exit:
if (mHandle != NULL)
free(mHandle);
return (amvenc_handle_t)NULL;
}
amvenc_metadata_t amvenc_generate_header(amvenc_handle_t handle,
unsigned char *pHeader,
unsigned int *pLength)
{
amvencHandle* mHandle = (amvencHandle *)handle;
amvenc_metadata_t result;
if (mHandle == NULL)
goto exit;
memset(&result, 0, sizeof(result));
if (amvenc_manager[mHandle->hw_type]) {
if (amvenc_manager[mHandle->hw_type]->generate_header)
return amvenc_manager[mHandle->hw_type]->generate_header(mHandle->codec_handle, pHeader, pLength);
}
exit:
result.is_valid = false;
return result;
}
amvenc_metadata_t amvenc_encode(amvenc_handle_t handle,
amvenc_frame_info_t frame_info,
amvenc_frame_type_t type,
unsigned char* out,
amvenc_buffer_info_t *in_buffer_info,
amvenc_buffer_info_t *ret_buffer_info)
{
amvencHandle* mHandle = (amvencHandle *)handle;
amvenc_metadata_t result;
if (mHandle == NULL)
goto exit;
memset(&result, 0, sizeof(result));
if (amvenc_manager[mHandle->hw_type]) {
if (amvenc_manager[mHandle->hw_type]->encode)
return amvenc_manager[mHandle->hw_type]->encode(mHandle->codec_handle, frame_info, type, out, in_buffer_info, ret_buffer_info);
}
exit:
result.is_valid = false;
return result;
}
int amvenc_change_bitrate(amvenc_handle_t handle,
int bitRate)
{
amvencHandle* mHandle = (amvencHandle *)handle;
if (mHandle == NULL)
return -1;
if (amvenc_manager[mHandle->hw_type]) {
if (amvenc_manager[mHandle->hw_type]->change_bitrate)
return amvenc_manager[mHandle->hw_type]->change_bitrate(mHandle->codec_handle, bitRate);
}
return -1;
}
int amvenc_destroy(amvenc_handle_t handle)
{
amvencHandle* mHandle = (amvencHandle *)handle;
if (mHandle == NULL)
return -1;
if (amvenc_manager[mHandle->hw_type]) {
if (amvenc_manager[mHandle->hw_type]->destroy)
amvenc_manager[mHandle->hw_type]->destroy(mHandle->codec_handle);
if (amvenc_manager[mHandle->hw_type]->unloadModule)
amvenc_manager[mHandle->hw_type]->unloadModule();
}
if (mHandle)
free(mHandle);
return 0;
}