一 都说android集成了libhevc用来做h265软解码,因为性能比较好。我自己在x86上测试了一下,估计是libhevc 实现的x86 SIMD不太好,速度只有ffmpeg里面openhec的20%左右。

二 先在ffmpeg里面实现wrapper给android端同学用用。

三 libhevc全都是操作结构体的方式调用的,其实用起来不是很方便。尤其是出错了,也不知道啥原因,需要一步步debug。 libhevc自己的demo,是结合了display的,不能作为参考,因为集成到ffmpeg里面也不需要display。

四 libhevc解码步骤

4.1 创建对象

4.2 设置解码核个数

 4.3 设置CPU类型

这里,因为我要用在手机上,所以默认设置的ARM_NEON

4.4 解码器设置为解码参数头模式

 4.5 解码参数头,vps,sps,pps

4.6 把解码器设置为解码帧模式

4.7 解码视频帧

总结:大概就是分上面7个步骤,值得注意的时候,有时候输入的视频帧是hvcc格式的,有时候是annexb格式的。但是libhevc只能解码annexb格式的,所以需要转换下。另外解码出来的视频帧是yuv420sp_uv格式的,我们常用的是yuv420p格式的,这个我们需要转换下。

上代码:

#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>#include "libavutil/avassert.h"
#include "libavutil/cpu.h"
#include "libavutil/film_grain_params.h"
#include "libavutil/mastering_display_metadata.h"
#include "libavutil/imgutils.h"
#include "libavutil/opt.h"#include "hevc_parse.h"
#include "avcodec.h"
#include "bytestream.h"
#include "codec_internal.h"
#include "decode.h"
#include "internal.h"
#include "ihevc_typedefs.h"
#include "iv.h"
#include "ivd.h"
#include "ihevcd_cxa.h"
#include "ithread.h"
#include "ihevcd_error.h"
#include "bsf.h"#define ALIGN8(x) ((((x) + 7) >> 3) << 3)
#define NUM_DISPLAY_BUFFERS 4
#define DEFAULT_FPS         30#define ENABLE_DEGRADE 0
#define MAX_DISP_BUFFERS    64
#define EXTRA_DISP_BUFFERS  0
#define STRLENGTH 1000#define ADAPTIVE_TEST
#define ADAPTIVE_MAX_WD 8192
#define ADAPTIVE_MAX_HT 4096
//#define TEST_FLUSH
#define FLUSH_FRM_CNT 100#define PEAK_WINDOW_SIZE            8
#define DEFAULT_SHARE_DISPLAY_BUF   0
#define STRIDE                      0
#define DEFAULT_NUM_CORES           2#define DUMP_SINGLE_BUF 0
#define IV_ISFATALERROR(x)         (((x) >> IVD_FATALERROR) & 0x1)#define ivd_cxa_api_function        ihevcd_cxa_api_function
#define INIT_INVALID_PTS  (-500000)
typedef struct
{UWORD32 u4_piclen_flag;UWORD32 u4_file_save_flag;UWORD32 u4_chksum_save_flag;IV_COLOR_FORMAT_T e_output_chroma_format;IVD_ARCH_T e_arch;IVD_SOC_T e_soc;UWORD32 dump_q_rd_idx;UWORD32 dump_q_wr_idx;WORD32  disp_q_wr_idx;WORD32  disp_q_rd_idx;void *cocodec_obj;UWORD32 share_disp_buf;UWORD32 num_disp_buf;UWORD32 b_pic_present;WORD32 i4_degrade_type;WORD32 i4_degrade_pics;UWORD32 u4_num_cores;UWORD32 disp_delay;WORD32 trace_enable;CHAR ac_trace_fname[STRLENGTH];CHAR ac_piclen_fname[STRLENGTH];CHAR ac_ip_fname[STRLENGTH];CHAR ac_op_fname[STRLENGTH];CHAR ac_op_chksum_fname[STRLENGTH];ivd_out_bufdesc_t s_disp_buffers[MAX_DISP_BUFFERS];iv_yuv_buf_t s_disp_frm_queue[MAX_DISP_BUFFERS];UWORD32 s_disp_frm_id_queue[MAX_DISP_BUFFERS];UWORD32 loopback;UWORD32 display;UWORD32 full_screen;UWORD32 fps;UWORD32 max_wd;UWORD32 max_ht;UWORD32 max_level;UWORD32 u4_strd;/* For signalling to display thread */UWORD32 u4_pic_wd;UWORD32 u4_pic_ht;/* For IOS diplay */WORD32 i4_screen_wd;WORD32 i4_screen_ht;//UWORD32 u4_output_present;WORD32  quit;WORD32  paused;WORD32  last_gebuf_index;    void *pv_disp_ctx;void *display_thread_handle;WORD32 display_thread_created;volatile WORD32 display_init_done;volatile WORD32 display_deinit_flag;IV_COLOR_FORMAT_T (*get_color_fmt)(void);UWORD32 (*get_stride)(void);
} vid_dec_ctx_t;typedef struct LibhevcdecContext {AVClass *class;/* This packet coincides with AVCodecInternal.in_pkt* and if not owned by us. */AVBufferPool *pool;int pool_size;int tile_threads;int num_cores;int apply_grain;char *cpu_simd;int operating_point;int all_layers;vid_dec_ctx_t s_app_ctx;int inited;ivd_out_bufdesc_t *ps_out_buf;const AVBitStreamFilter *hevcbsfc;AVBSFContext *bsf_context;int last_max_timestamp;int last_duration;
} LibhevcdecContext;#define HEVCDEC_PIXEL_LAYOUT_I400 0
#define HEVCDEC_PIXEL_LAYOUT_I420 1
#define HEVCDEC_PIXEL_LAYOUT_I422 2
#define HEVCDEC_PIXEL_LAYOUT_I444 3
static const uint8_t libhevc_startcode[4] = {0x00, 0x00, 0x00, 0x01};
static const enum AVPixelFormat pix_fmt[][3] = {[HEVCDEC_PIXEL_LAYOUT_I400] = { AV_PIX_FMT_GRAY8,   AV_PIX_FMT_GRAY10,    AV_PIX_FMT_GRAY12 },[HEVCDEC_PIXEL_LAYOUT_I420] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12 },[HEVCDEC_PIXEL_LAYOUT_I422] = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12 },[HEVCDEC_PIXEL_LAYOUT_I444] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12 },
};static const enum AVPixelFormat pix_fmt_rgb[3] = {AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
};static UWORD32 default_get_stride(void)
{return 0;
}static IV_COLOR_FORMAT_T default_get_color_fmt(void)
{return IV_YUV_420P;
}static void * _aligned_malloc(int32_t size, int32_t alignment)
{int32_t alignsize = (size + alignment - 1)/alignment * alignment;return malloc(alignsize);
}static void _aligned_free(void *pv_buf)
{if (pv_buf) {free(pv_buf);}
}static void *ihevca_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size)
{(void)pv_ctxt;return (void *)_aligned_malloc(i4_size, alignment);
}static void ihevca_aligned_free(void *pv_ctxt, void *pv_buf)
{(void)pv_ctxt;_aligned_free(pv_buf);return;
}static int libhevcdec_init_bsf(AVCodecContext *c)
{LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data; /**init hevc bitstream filter* */libhevc->hevcbsfc = av_bsf_get_by_name("hevc_mp4toannexb");if (libhevc->hevcbsfc == NULL) {av_log(c, AV_LOG_ERROR, "libhevc av_bitstream_filter_init  failed.");return -4;}if (av_bsf_alloc(libhevc->hevcbsfc, &libhevc->bsf_context) != 0) {av_log(c, AV_LOG_ERROR, "libhevc av_bsf_alloc  failed.");return -5;}if (avcodec_parameters_from_context(libhevc->bsf_context->par_in, c) != 0) {av_log(c, AV_LOG_ERROR, "libhevc avcodec_parameters_from_context  failed.");return -6;}libhevc->bsf_context->time_base_in = c->time_base;av_bsf_init(libhevc->bsf_context);return 0;
}static av_cold int libhevcdec_init(AVCodecContext *c)
{LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data;
/**    int pool_size;int tile_threads;int num_cores;int apply_grain;int operating_point;int all_layers;* */int ret;strcpy(libhevc->s_app_ctx.ac_ip_fname, "\0");libhevc->s_app_ctx.dump_q_wr_idx = 0;libhevc->s_app_ctx.dump_q_rd_idx = 0;libhevc->s_app_ctx.display_thread_created = 0;libhevc->s_app_ctx.disp_q_wr_idx = 0;libhevc->s_app_ctx.disp_q_rd_idx = 0;libhevc->s_app_ctx.disp_delay = 0;libhevc->s_app_ctx.loopback = 0;libhevc->s_app_ctx.display = 0;libhevc->s_app_ctx.full_screen = 0;libhevc->s_app_ctx.u4_piclen_flag = 0;libhevc->s_app_ctx.fps = DEFAULT_FPS;libhevc->s_app_ctx.share_disp_buf = 0;//DEFAULT_SHARE_DISPLAY_BUF;libhevc->s_app_ctx.u4_num_cores = DEFAULT_NUM_CORES;libhevc->s_app_ctx.i4_degrade_type = 0;libhevc->s_app_ctx.i4_degrade_pics = 0;libhevc->s_app_ctx.e_arch = ARCH_ARM_A9Q;libhevc->s_app_ctx.e_soc = SOC_GENERIC;libhevc->s_app_ctx.u4_strd = STRIDE;libhevc->s_app_ctx.display_thread_handle           = malloc(ithread_get_handle_size());libhevc->s_app_ctx.quit          = 0;libhevc->s_app_ctx.paused        = 0;libhevc->s_app_ctx.get_stride = &default_get_stride;libhevc->s_app_ctx.get_color_fmt = &default_get_color_fmt;libhevc->s_app_ctx.display_deinit_flag = 0;libhevc->s_app_ctx.e_output_chroma_format = IV_YUV_420SP_UV;libhevc->inited = 0;libhevc->bsf_context = NULL;libhevc->last_max_timestamp = INIT_INVALID_PTS;libhevc->last_duration = 40;//default 25fpslibhevc->ps_out_buf = (ivd_out_bufdesc_t *)malloc(sizeof(ivd_out_bufdesc_t));memset(libhevc->ps_out_buf, 0x0, sizeof(ivd_out_bufdesc_t));libhevc->ps_out_buf->u4_num_bufs = 3;/**create decode instance * */ihevcd_cxa_create_ip_t s_create_ip;ihevcd_cxa_create_op_t s_create_op;void *fxns = &ivd_cxa_api_function;s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = libhevc->s_app_ctx.share_disp_buf;s_create_ip.s_ivd_create_ip_t.e_output_format = (IV_COLOR_FORMAT_T)libhevc->s_app_ctx.e_output_chroma_format;s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ihevca_aligned_malloc;s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ihevca_aligned_free;s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ihevcd_cxa_create_ip_t);s_create_op.s_ivd_create_op_t.u4_size = sizeof(ihevcd_cxa_create_op_t);ret = ivd_cxa_api_function(NULL, (void *)&s_create_ip,(void *)&s_create_op);if (ret != IV_SUCCESS) {av_log(c, AV_LOG_ERROR, "libhevc decoder open created failed.");        return -1;}iv_obj_t *codec_obj = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;codec_obj->pv_fxns = fxns;codec_obj->u4_size = sizeof(iv_obj_t);libhevc->s_app_ctx.cocodec_obj = codec_obj; //set code object here ############################/** set num of cores*/ihevcd_cxa_ctl_set_num_cores_ip_t s_ctl_set_cores_ip;ihevcd_cxa_ctl_set_num_cores_op_t s_ctl_set_cores_op;s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;s_ctl_set_cores_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES;s_ctl_set_cores_ip.u4_num_cores = libhevc->s_app_ctx.u4_num_cores;s_ctl_set_cores_ip.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_ip_t);s_ctl_set_cores_op.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_op_t);ret = ivd_cxa_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_cores_ip,(void *)&s_ctl_set_cores_op);if (ret != IV_SUCCESS) {av_log(c, AV_LOG_ERROR, "libhevc decoder set cores failed.");     return -2; }/**set processor type* */ihevcd_cxa_ctl_set_processor_ip_t s_ctl_set_num_processor_ip;ihevcd_cxa_ctl_set_processor_op_t s_ctl_set_num_processor_op;s_ctl_set_num_processor_ip.e_cmd = IVD_CMD_VIDEO_CTL;s_ctl_set_num_processor_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_PROCESSOR;s_ctl_set_num_processor_ip.u4_arch = libhevc->s_app_ctx.e_arch;s_ctl_set_num_processor_ip.u4_soc = libhevc->s_app_ctx.e_soc;s_ctl_set_num_processor_ip.u4_size = sizeof(ihevcd_cxa_ctl_set_processor_ip_t);s_ctl_set_num_processor_op.u4_size = sizeof(ihevcd_cxa_ctl_set_processor_op_t);ret = ivd_cxa_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_num_processor_ip,(void *)&s_ctl_set_num_processor_op);if (ret != IV_SUCCESS) {av_log(c, AV_LOG_ERROR, "libhevc decoder set processor type failed.");return -3; }return 0;
}static void libhevcdec_flush(AVCodecContext *c)
{
#if 0Libdav1dContext *dav1d = c->priv_data;dav1d_data_unref(&dav1d->data);dav1d_flush(dav1d->c);
#endif
}static int libhevcdec_fill_frame_withbuf(AVCodecContext *c, AVFrame *frame, ivd_video_decode_op_t *s_video_decode_frame_op, ivd_video_decode_ip_t *s_video_decode_frame_ip)
{LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data; frame->width = c->width;frame->height = c->height;frame->format = AV_PIX_FMT_YUV420P;if (libhevc->last_max_timestamp == INIT_INVALID_PTS) {libhevc->last_max_timestamp = s_video_decode_frame_op->u4_ts;} else {if (libhevc->last_max_timestamp >= s_video_decode_frame_op->u4_ts|| (s_video_decode_frame_op->u4_ts - libhevc->last_max_timestamp < libhevc->last_duration)) {libhevc->last_max_timestamp += libhevc->last_duration;} else {libhevc->last_max_timestamp = s_video_decode_frame_op->u4_ts;} }frame->pts = libhevc->last_max_timestamp;   frame->pkt_dts = libhevc->last_max_timestamp;if (av_frame_get_buffer(frame, 16) != 0) {av_log(c, AV_LOG_ERROR, "decode get AVFrame buffer failed.");    return -14;}if (s_video_decode_frame_op->e_pic_type == IV_I_FRAME || s_video_decode_frame_op->e_pic_type == IV_IDR_FRAME) {frame->pict_type = AV_PICTURE_TYPE_I;frame->key_frame = 1;} else if (s_video_decode_frame_op->e_pic_type == IV_P_FRAME ||s_video_decode_frame_op->e_pic_type == IV_IP_FRAME ||s_video_decode_frame_op->e_pic_type == IV_PP_FRAME) {frame->pict_type = AV_PICTURE_TYPE_P;} else {frame->pict_type = AV_PICTURE_TYPE_B;}if (s_video_decode_frame_op->e_output_format == IV_YUV_420P) {/**copy y* */for (int i = 0; i < c->height; i++) {UWORD8 *ybuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_y_buf;memcpy(frame->data[0] + i * frame->linesize[0], ybuf + i * s_video_decode_frame_op->s_disp_frm_buf.u4_y_strd, c->width);}/**copy u* */for (int i = 0; i < c->height/2; i++) {UWORD8 *ubuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_u_buf;      UWORD8 *vbuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_v_buf;memcpy(frame->data[1] + i * frame->linesize[1], ubuf + i * s_video_decode_frame_op->s_disp_frm_buf.u4_u_strd, c->width/2);memcpy(frame->data[2] + i * frame->linesize[2], vbuf + i * s_video_decode_frame_op->s_disp_frm_buf.u4_v_strd, c->width/2);}} else if (s_video_decode_frame_op->e_output_format == IV_YUV_420SP_UV) {/**copy y* */for (int i = 0; i < c->height; i++) {UWORD8 *ybuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_y_buf;        memcpy(frame->data[0] + i * frame->linesize[0], (uint8_t*)ybuf + i * s_video_decode_frame_op->s_disp_frm_buf.u4_y_strd, c->width);}/**copy u v* */for (int i = 0; i < c->height/2; i++) {for (int j = 0; j < c->width/2; j++) {UWORD8 *ubuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_u_buf;    int index = i * s_video_decode_frame_op->s_disp_frm_buf.u4_u_strd + j * 2;frame->data[1][i * frame->linesize[1] + j] = ubuf[index];frame->data[2][i * frame->linesize[2] + j] = ubuf[index + 1];}}} else if (s_video_decode_frame_op->e_output_format == IV_YUV_420SP_VU) {/**copy y* */for (int i = 0; i < c->height; i++) {UWORD8 *ybuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_y_buf;  memcpy(frame->data[0] + i * frame->linesize[0], ybuf + i * s_video_decode_frame_op->s_disp_frm_buf.u4_y_strd, c->width);}/**copy u v* */for (int i = 0; i < c->height/2; i++) {for (int j = 0; j < c->width/2; j++) {UWORD8 *ubuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_u_buf;int index = i * s_video_decode_frame_op->s_disp_frm_buf.u4_u_strd + j * 2;frame->data[2][i * frame->linesize[2] + j] = ubuf[index];frame->data[1][i * frame->linesize[1] + j] = ubuf[index + 1];}}}return 0;
}static uint8_t *writebytes(uint8_t *dst, const uint8_t *src, int len)
{memcpy(dst, src, len);return dst + len;
}static int libhevcdec_hvcc2annexb(AVCodecContext *c, AVPacket *pkt)
{LibhevcdecContext *hevcdec = (LibhevcdecContext *)c->priv_data;    if (av_bsf_send_packet(hevcdec->bsf_context, pkt) < 0){av_log(c, AV_LOG_ERROR, "av_bsf_send_packet faile \n");return -1;}if (av_bsf_receive_packet(hevcdec->bsf_context, pkt) < 0) {av_log(c, AV_LOG_ERROR, "av_bsf_receive_packet faile \n");return -2;}return 0;
}static int libhevcdec_make_codechead(AVCodecContext *c, uint8_t **buf)
{
#define MAX_PADDING (256)int outlen = c->extradata_size + MAX_PADDING;uint8_t *outbuf = (uint8_t*)malloc(outlen);uint8_t *tmp = outbuf;if (outbuf == NULL) {av_log(c, AV_LOG_ERROR, "alloc codec head mem failed..");return -1;}    HEVCParamSets ps;HEVCSEI sei;memset(&ps, 0x0, sizeof(HEVCParamSets));memset(&sei, 0x0, sizeof(HEVCSEI));int is_nalff = 0;int nal_length_size = 0;int res = ff_hevc_decode_extradata(c->extradata, c->extradata_size, &ps, &sei, &is_nalff, &nal_length_size, 0, 0, c);if (res != 0) {av_log(c, AV_LOG_ERROR, "parse extra data failed.");ff_hevc_ps_uninit(&ps);return -3;}for (int i = 0; i < HEVC_MAX_VPS_COUNT; i++) {if (ps.vps_list[i]) {HEVCVPS *vps = (HEVCVPS *)ps.vps_list[i]->data;tmp = writebytes(tmp, libhevc_startcode, 4);tmp = writebytes(tmp, vps->data, vps->data_size);         }}for (int i = 0; i < HEVC_MAX_SPS_COUNT; i++) {if (ps.sps_list[i]) {HEVCSPS *sps = (HEVCSPS *)ps.sps_list[i]->data;tmp = writebytes(tmp, libhevc_startcode, 4);tmp = writebytes(tmp, sps->data, sps->data_size);}}for (int i = 0; i < HEVC_MAX_PPS_COUNT; i++) {if (ps.pps_list[i]) {HEVCPPS *pps = (HEVCPPS *)ps.pps_list[i]->data;tmp = writebytes(tmp, libhevc_startcode, 4);tmp = writebytes(tmp, pps->data, pps->data_size);}}ff_hevc_ps_uninit(&ps);*buf = outbuf;return tmp - outbuf;
}static int libhevcdec_receive_frame(AVCodecContext *c, AVFrame *frame)
{LibhevcdecContext *hevcdec = (LibhevcdecContext *)c->priv_data;uint8_t *disp_outbuf = NULL;int outlen = 0;int cur_dts = 0;AVPacket pkt = { 0 };int res = ff_decode_get_packet(c, &pkt);if (res < 0 && res != AVERROR_EOF)return res;
#define FAIL(value) \{\pkt.buf = NULL; \av_packet_unref(&pkt); \return value; \}\
(void)0
#define SUCCESS() FAIL(0)if (pkt.size) {    cur_dts = pkt.pts;if (pkt.duration > 0) {hevcdec->last_duration = pkt.duration;}if (!hevcdec->inited) {/**set into decoder header mode* */ivd_ctl_set_config_ip_t s_ctl_ip;ivd_ctl_set_config_op_t s_ctl_op;s_ctl_ip.u4_disp_wd = 0;s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;s_ctl_ip.e_vid_dec_mode = IVD_DECODE_HEADER;s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);res = ivd_cxa_api_function((iv_obj_t*)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_ctl_ip,(void *)&s_ctl_op);if (res != IV_SUCCESS) {av_log(c, AV_LOG_ERROR, "set decode header mode failed.");FAIL(-2);}      /** try deocde header* */
#if 1uint8_t *headbuf = pkt.data;uint8_t headlen = pkt.size;uint8_t *codechead = NULL;if (c->extradata && c->extradata_size > 0) {res = libhevcdec_make_codechead(c, &codechead);if (res < 0) {av_log(c, AV_LOG_ERROR, "parse codec head failed.");if (codechead) av_free(codechead);FAIL(-10);}headbuf = codechead;headlen = res;}
#endifivd_video_decode_ip_t s_video_decode_ip;ivd_video_decode_op_t s_video_decode_op;s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE;s_video_decode_ip.u4_ts = pkt.pts;s_video_decode_ip.pv_stream_buffer = headbuf;s_video_decode_ip.u4_num_Bytes = headlen;s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t);s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t);/*****************************************************************************//*   API Call: Header Decode                                                  *//*****************************************************************************/res = ihevcd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_video_decode_ip,(void *)&s_video_decode_op);if (codechead) av_free(codechead);if (res != IV_SUCCESS) {av_log(c, AV_LOG_ERROR, "decode header failed.");FAIL(-3);}c->width = s_video_decode_op.u4_pic_wd;c->height = s_video_decode_op.u4_pic_ht;c->codec_type = AVMEDIA_TYPE_VIDEO;if (libhevcdec_init_bsf(c) != 0) {av_log(c, AV_LOG_ERROR, "libhevcdec_init_bsf failed.");FAIL(-13);}if (libhevcdec_hvcc2annexb(c, &pkt) != 0) {av_log(c, AV_LOG_ERROR, "set decode header mode failed.");FAIL(-1);}cur_dts = pkt.dts;#define AlignTo(value, align) \((value + align - 1)/align * align)outlen = AlignTo(c->width, 64) * AlignTo(c->height, 64) * 3;hevcdec->ps_out_buf->u4_min_out_buf_size[0] = hevcdec->ps_out_buf->u4_min_out_buf_size[1] = hevcdec->ps_out_buf->u4_min_out_buf_size[2] = AlignTo(c->width, 64) * AlignTo(c->height, 64);#if 1/**set frame out mode* */ivd_ctl_set_config_ip_t s_ctl_decode_ip;ivd_ctl_set_config_op_t s_ctl_decode_op;s_ctl_decode_ip.u4_disp_wd = 0;s_ctl_decode_ip.e_frm_skip_mode = IVD_SKIP_NONE;s_ctl_decode_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;s_ctl_decode_ip.e_vid_dec_mode = IVD_DECODE_FRAME;s_ctl_decode_ip.e_cmd = IVD_CMD_VIDEO_CTL;s_ctl_decode_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;s_ctl_decode_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);s_ctl_decode_op.u4_size = sizeof(ivd_ctl_set_config_op_t);res = ivd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_ctl_decode_ip, (void *)&s_ctl_decode_op);if (IV_SUCCESS != res) {av_log(c, AV_LOG_ERROR, "decode set decode mode failed.");FAIL(-5);}
#endifhevcdec->inited = 1;if (hevcdec->ps_out_buf->pu1_bufs[0] == NULL) {disp_outbuf = (uint8_t*)malloc(outlen);hevcdec->ps_out_buf->pu1_bufs[0] = disp_outbuf;hevcdec->ps_out_buf->u4_min_out_buf_size[0] = hevcdec->ps_out_buf->u4_min_out_buf_size[1] = hevcdec->ps_out_buf->u4_min_out_buf_size[2] = AlignTo(c->width, 64) * AlignTo(c->height, 64);hevcdec->ps_out_buf->pu1_bufs[1] = hevcdec->ps_out_buf->pu1_bufs[0] + AlignTo(c->width, 64) * AlignTo(c->height, 64);hevcdec->ps_out_buf->pu1_bufs[2] = hevcdec->ps_out_buf->pu1_bufs[1] + AlignTo(c->width, 64) * AlignTo(c->height, 64);hevcdec->ps_out_buf->u4_num_bufs = 3;}ivd_video_decode_ip_t s_video_decode_frame_ip;ivd_video_decode_op_t s_video_decode_frame_op;s_video_decode_frame_ip.e_cmd = IVD_CMD_VIDEO_DECODE;s_video_decode_frame_ip.u4_ts = cur_dts;s_video_decode_frame_ip.pv_stream_buffer = pkt.data;s_video_decode_frame_ip.u4_num_Bytes = pkt.size;s_video_decode_frame_ip.u4_size = sizeof(ivd_video_decode_ip_t);s_video_decode_frame_ip.s_out_buffer.u4_min_out_buf_size[0] =hevcdec->ps_out_buf->u4_min_out_buf_size[0];s_video_decode_frame_ip.s_out_buffer.u4_min_out_buf_size[1] =hevcdec->ps_out_buf->u4_min_out_buf_size[1];s_video_decode_frame_ip.s_out_buffer.u4_min_out_buf_size[2] =hevcdec->ps_out_buf->u4_min_out_buf_size[2];s_video_decode_frame_ip.s_out_buffer.pu1_bufs[0] =hevcdec->ps_out_buf->pu1_bufs[0];s_video_decode_frame_ip.s_out_buffer.pu1_bufs[1] =hevcdec->ps_out_buf->pu1_bufs[1];s_video_decode_frame_ip.s_out_buffer.pu1_bufs[2] =hevcdec->ps_out_buf->pu1_bufs[2];s_video_decode_frame_ip.s_out_buffer.u4_num_bufs =hevcdec->ps_out_buf->u4_num_bufs;s_video_decode_frame_op.s_disp_frm_buf.pv_y_buf = hevcdec->ps_out_buf->pu1_bufs[0];s_video_decode_frame_op.s_disp_frm_buf.pv_u_buf = hevcdec->ps_out_buf->pu1_bufs[1];s_video_decode_frame_op.s_disp_frm_buf.pv_v_buf = hevcdec->ps_out_buf->pu1_bufs[2];s_video_decode_frame_op.u4_size = sizeof(ivd_video_decode_op_t);res = ivd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_video_decode_frame_ip,(void *)&s_video_decode_frame_op);if (res != IV_SUCCESS) {av_log(c, AV_LOG_ERROR, "decode key frame failed. error %d.", s_video_decode_op.u4_error_code);FAIL(-4);}if (s_video_decode_frame_op.e_output_format != IV_YUV_420P && s_video_decode_frame_op.e_output_format != IV_YUV_420SP_UV&& s_video_decode_frame_op.e_output_format != IV_YUV_420SP_VU) {av_log(c, AV_LOG_ERROR, "decode format not support. format %d.", s_video_decode_frame_op.e_output_format);FAIL(-5);}if (frame && s_video_decode_op.u4_frame_decoded_flag) {if (libhevcdec_fill_frame_withbuf(c, frame, &s_video_decode_frame_op, &s_video_decode_frame_ip) != 0) {av_log(c, AV_LOG_ERROR, "fill frame failed.");FAIL(-6);}}c->pix_fmt = AV_PIX_FMT_YUV420P;SUCCESS();}if (libhevcdec_hvcc2annexb(c, &pkt) != 0) {av_log(c, AV_LOG_ERROR, "libhevcdec_hvcc2annexb failed.");FAIL(-15);}ivd_video_decode_ip_t s_video_decode_ip;ivd_video_decode_op_t s_video_decode_op; s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE;s_video_decode_ip.u4_ts = cur_dts;s_video_decode_ip.pv_stream_buffer = pkt.data;s_video_decode_ip.u4_num_Bytes = pkt.size;s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t);s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] =hevcdec->ps_out_buf->u4_min_out_buf_size[0];s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] =hevcdec->ps_out_buf->u4_min_out_buf_size[1];s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] =hevcdec->ps_out_buf->u4_min_out_buf_size[2];s_video_decode_ip.s_out_buffer.pu1_bufs[0] =hevcdec->ps_out_buf->pu1_bufs[0];s_video_decode_ip.s_out_buffer.pu1_bufs[1] =hevcdec->ps_out_buf->pu1_bufs[1];s_video_decode_ip.s_out_buffer.pu1_bufs[2] =hevcdec->ps_out_buf->pu1_bufs[2];s_video_decode_ip.s_out_buffer.u4_num_bufs =hevcdec->ps_out_buf->u4_num_bufs;s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t);res = ivd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_video_decode_ip,(void *)&s_video_decode_op);if (res != IV_SUCCESS) {av_log(c, AV_LOG_ERROR, "Error in video Frame decode : res %x Error %x\n", res,s_video_decode_op.u4_error_code);FAIL(-8);}if (frame && s_video_decode_op.u4_frame_decoded_flag && s_video_decode_op.u4_output_present) {if (libhevcdec_fill_frame_withbuf(c, frame, &s_video_decode_op, &s_video_decode_ip) != 0) {av_log(c, AV_LOG_ERROR, "fill frame failed.");FAIL(-9);}}if (s_video_decode_op.u4_output_present) {//        fprintf(stderr, "linesize[%d %d %d] resolution[%dx%d]type[%d]\n", frame->linesize[0], frame->linesize[1], frame->linesize[2], frame->width, frame->height, frame->pict_type);}}SUCCESS();
}static av_cold int libhevcdec_close(AVCodecContext *c)
{LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data;if (libhevc->ps_out_buf->pu1_bufs[0]) {free(libhevc->ps_out_buf->pu1_bufs[0]);libhevc->ps_out_buf->pu1_bufs[0] = libhevc->ps_out_buf->pu1_bufs[1] = libhevc->ps_out_buf->pu1_bufs[2] = NULL;}if (libhevc->ps_out_buf) {free(libhevc->ps_out_buf);libhevc->ps_out_buf = NULL;}if (libhevc->bsf_context) {av_bsf_free(&libhevc->bsf_context);libhevc->bsf_context = NULL;}return 0;
}
#define OFFSET(x) offsetof(LibhevcdecContext, x)
#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
static const AVOption hevcdec_options[] = {{ "numcores", "decode cores", OFFSET(num_cores), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 16, VD},{ "cpusimd",        "Set the cpu simd",   OFFSET(cpu_simd),        AV_OPT_TYPE_STRING, { .str = "ARM_NEONINTR" }, 0, 0, VD},{ NULL }
};static const AVClass libhevcdec_class = {.class_name = "libhevcdec",.item_name  = av_default_item_name,.option     = hevcdec_options,.version    = LIBAVUTIL_VERSION_INT,
};const FFCodec ff_libhevcdec_decoder = {.p.name         = "libhevcdec",.p.long_name    = NULL_IF_CONFIG_SMALL("libhevcdec hevc  decoder by VideoLAN"),.p.type         = AVMEDIA_TYPE_VIDEO,.p.id           = AV_CODEC_ID_HEVC,.priv_data_size = sizeof(LibhevcdecContext),.init           = libhevcdec_init,.close          = libhevcdec_close,.flush          = libhevcdec_flush,FF_CODEC_RECEIVE_FRAME_CB(libhevcdec_receive_frame),.p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,.caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS |FF_CODEC_CAP_AUTO_THREADS,.p.priv_class   = &libhevcdec_class,.p.wrapper_name = "libhevcdec",
};

参考别的库引入,在configure脚本里面加上配置项,然后configure一下,就能编译了。

--enable-libhevcdec --enable-libx264 --enable-gpl --extra-cflags='-I/data/decoder/libhevc/decoder -I/data/decoder/libhevc/common' --extra-ldflags='-L /data/decoder/libhevc/build/' --extra-libs='-lhevcdec -ldl -lm' --disable-ffplay

解码命令示例:

./ffmpeg_g -vcodec libhevcdec -vsync 0 -i chiji.mp4 -y 123.yuv

配置不会可以发邮件,1045056991@qq.com

在ffmpeg上实现libhevc wrapper相关推荐

  1. rk3399 rkmpp 在ffmpeg上实现硬编解码

    一.编译指令: --enable-cross-compile --cross-prefix=/home/cks/fireFlyLinuxSdk/firefly/linux_sdk/buildroot/ ...

  2. FFmpeg 硬件加速方案概览 (上)

    被称为"多媒体技术领域的瑞士军刀",FFmpeg拥有广泛的应用基础.不过,当(实时)处理海量视频时,需要借助各种方法提升效率.比如,短视频平台Revvel将视频转码服务迁移到AWS ...

  3. 在AWS Lambda上部署EC2编译的FFmpeg工具——自定义层的方案

    大纲 1 确定Lambda运行时环境 1.1 Lambda系统.镜像.内核版本 1.2 运行时 1.2.1 Python 1.2.2 Java 2 环境准备 2.1 创建EC2实例 3 编译FFmpe ...

  4. ffmpeg api的应用——提取视频图片

    这些年来,"短视频"吸引了无数网民的注意.相对于丰富有趣的内容,我们码农可能更关心其底层技术实现.本系列文章将结合ffmpeg,讲解几则视频处理案例.(转载请指明出于breakso ...

  5. 英特尔QSV技术在FFmpeg中的实现与使用

    本文来自英特尔资深软件工程师张华在LiveVideoStackCon 2018讲师热身分享,并由LiveVideoStack整理而成.在分享中张华介绍了英特尔GPU硬件架构,并详细解析了英特尔QSV技 ...

  6. FFmpeg Maintainer赵军:FFmpeg关键组件与硬件加速

    本文来自FFmpeg Maintainer赵军在LiveVideoStackCon 2018热身分享,并由LiveVideoStack整理而成.在分享中,赵军介绍了FFmpeg的历史.关键组件,并介绍 ...

  7. linux下成功安装ffmpeg( 亲测有效 )

    linux下成功安装ffmpeg( 亲测有效 ) 一.下载 二.安装步骤 1.安装yasm 2.安装ffmpeg 总结 一.下载 ffmpeg 官网下载: http://ffmpeg.org/down ...

  8. vue使用better-scroll实现下拉刷新、上拉加载

    本文目的是为了实现列表的下拉刷新.上拉加载,所以选择了better-scroll这个库. 用好这个库,需要理解下面说明 必须包含两个大的div,外层和内层div 外层div设置可视的大小(宽或者高)- ...

  9. vue better-scroll 使用 下拉刷新、上拉加载

    我的目的是为了实现列表的下拉刷新.上拉加载,所以选择了better-scroll这个库. 用好这个库,需要理解下面说明 必须包含两个大的div,外层和内层div 外层div设置可视的大小(宽或者高)- ...

最新文章

  1. pyqt setStyleSheet用法
  2. java rest post list,Java RestTemplate.postForLocation方法代码示例
  3. LSMW批处理使用方法(02)_步骤1
  4. pytorch基础知识整理(一)自动求导机制
  5. config done shell_shell do...done $config
  6. cmd命令重定向到剪切板
  7. oracle查询最高一条记录,oracle 查询已有记录,上一条记录,下一条记录
  8. 【推荐】.NET批量上传控件——HtmlInputFiles
  9. ajax代码原理,关于Ajax的原理以及代码封装详解
  10. testlink php nginx,linux环境部署testlink步骤说明
  11. 标准正态分布的积分怎么求?
  12. [Flink]Flink实时框架介绍
  13. HTML5微数据学习笔记
  14. 【转-整理】Struts2中package,action,result,method配置详解
  15. 节俭,是一种了不起的能力
  16. 杰控连接mysql_杰控FameView组态软件在数据库连接和查询方面的应用
  17. 计算机的五个发展阶段详细介绍,计算机的发展阶段可以分为那五个阶段吗?
  18. 原生android ui设计,在拟物和扁平之间寻找平衡:原生安卓UI设计进化史
  19. LR.JAVA报表设计器,快速点亮报表设计技能
  20. iOS开发-Tom猫

热门文章

  1. Vue项目搭建时npm install出现npm ERR code 1报错
  2. vue路由跳转回退后页面不刷新处理
  3. 讨论网络计算机英语作文,计算机的英语作文赏析
  4. java中去除全角和半角空格
  5. ArcGIS基础实验操作100例--实验77按要素分区统计路网
  6. C#毕业设计——基于C#+asp.net+sqlserver的选课系统设计与实现(毕业论文+程序源码)——选课系统
  7. 大数据分析证书有用吗?
  8. 重磅升级!《人工智能:现代方法(第4版)》(赠书)
  9. kali foremost 分离文件_提取伴奏还在用Au?来用人工智能免费快速分离音乐吧!...
  10. Windows Server 2003 共享文件夹权限设置