• 在ffmpeg上实现libhevc wrapper


    一 都说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格式的,这个我们需要转换下。

    上代码:

    1. #include <unistd.h>
    2. #include <fcntl.h>
    3. #include <sys/types.h>
    4. #include "libavutil/avassert.h"
    5. #include "libavutil/cpu.h"
    6. #include "libavutil/film_grain_params.h"
    7. #include "libavutil/mastering_display_metadata.h"
    8. #include "libavutil/imgutils.h"
    9. #include "libavutil/opt.h"
    10. #include "hevc_parse.h"
    11. #include "avcodec.h"
    12. #include "bytestream.h"
    13. #include "codec_internal.h"
    14. #include "decode.h"
    15. #include "internal.h"
    16. #include "ihevc_typedefs.h"
    17. #include "iv.h"
    18. #include "ivd.h"
    19. #include "ihevcd_cxa.h"
    20. #include "ithread.h"
    21. #include "ihevcd_error.h"
    22. #include "bsf.h"
    23. #define ALIGN8(x) ((((x) + 7) >> 3) << 3)
    24. #define NUM_DISPLAY_BUFFERS 4
    25. #define DEFAULT_FPS 30
    26. #define ENABLE_DEGRADE 0
    27. #define MAX_DISP_BUFFERS 64
    28. #define EXTRA_DISP_BUFFERS 0
    29. #define STRLENGTH 1000
    30. #define ADAPTIVE_TEST
    31. #define ADAPTIVE_MAX_WD 8192
    32. #define ADAPTIVE_MAX_HT 4096
    33. //#define TEST_FLUSH
    34. #define FLUSH_FRM_CNT 100
    35. #define PEAK_WINDOW_SIZE 8
    36. #define DEFAULT_SHARE_DISPLAY_BUF 0
    37. #define STRIDE 0
    38. #define DEFAULT_NUM_CORES 2
    39. #define DUMP_SINGLE_BUF 0
    40. #define IV_ISFATALERROR(x) (((x) >> IVD_FATALERROR) & 0x1)
    41. #define ivd_cxa_api_function ihevcd_cxa_api_function
    42. #define INIT_INVALID_PTS (-500000)
    43. typedef struct
    44. {
    45. UWORD32 u4_piclen_flag;
    46. UWORD32 u4_file_save_flag;
    47. UWORD32 u4_chksum_save_flag;
    48. IV_COLOR_FORMAT_T e_output_chroma_format;
    49. IVD_ARCH_T e_arch;
    50. IVD_SOC_T e_soc;
    51. UWORD32 dump_q_rd_idx;
    52. UWORD32 dump_q_wr_idx;
    53. WORD32 disp_q_wr_idx;
    54. WORD32 disp_q_rd_idx;
    55. void *cocodec_obj;
    56. UWORD32 share_disp_buf;
    57. UWORD32 num_disp_buf;
    58. UWORD32 b_pic_present;
    59. WORD32 i4_degrade_type;
    60. WORD32 i4_degrade_pics;
    61. UWORD32 u4_num_cores;
    62. UWORD32 disp_delay;
    63. WORD32 trace_enable;
    64. CHAR ac_trace_fname[STRLENGTH];
    65. CHAR ac_piclen_fname[STRLENGTH];
    66. CHAR ac_ip_fname[STRLENGTH];
    67. CHAR ac_op_fname[STRLENGTH];
    68. CHAR ac_op_chksum_fname[STRLENGTH];
    69. ivd_out_bufdesc_t s_disp_buffers[MAX_DISP_BUFFERS];
    70. iv_yuv_buf_t s_disp_frm_queue[MAX_DISP_BUFFERS];
    71. UWORD32 s_disp_frm_id_queue[MAX_DISP_BUFFERS];
    72. UWORD32 loopback;
    73. UWORD32 display;
    74. UWORD32 full_screen;
    75. UWORD32 fps;
    76. UWORD32 max_wd;
    77. UWORD32 max_ht;
    78. UWORD32 max_level;
    79. UWORD32 u4_strd;
    80. /* For signalling to display thread */
    81. UWORD32 u4_pic_wd;
    82. UWORD32 u4_pic_ht;
    83. /* For IOS diplay */
    84. WORD32 i4_screen_wd;
    85. WORD32 i4_screen_ht;
    86. //UWORD32 u4_output_present;
    87. WORD32 quit;
    88. WORD32 paused;
    89. WORD32 last_gebuf_index;
    90. void *pv_disp_ctx;
    91. void *display_thread_handle;
    92. WORD32 display_thread_created;
    93. volatile WORD32 display_init_done;
    94. volatile WORD32 display_deinit_flag;
    95. IV_COLOR_FORMAT_T (*get_color_fmt)(void);
    96. UWORD32 (*get_stride)(void);
    97. } vid_dec_ctx_t;
    98. typedef struct LibhevcdecContext {
    99. AVClass *class;
    100. /* This packet coincides with AVCodecInternal.in_pkt
    101. * and if not owned by us. */
    102. AVBufferPool *pool;
    103. int pool_size;
    104. int tile_threads;
    105. int num_cores;
    106. int apply_grain;
    107. char *cpu_simd;
    108. int operating_point;
    109. int all_layers;
    110. vid_dec_ctx_t s_app_ctx;
    111. int inited;
    112. ivd_out_bufdesc_t *ps_out_buf;
    113. const AVBitStreamFilter *hevcbsfc;
    114. AVBSFContext *bsf_context;
    115. int last_max_timestamp;
    116. int last_duration;
    117. } LibhevcdecContext;
    118. #define HEVCDEC_PIXEL_LAYOUT_I400 0
    119. #define HEVCDEC_PIXEL_LAYOUT_I420 1
    120. #define HEVCDEC_PIXEL_LAYOUT_I422 2
    121. #define HEVCDEC_PIXEL_LAYOUT_I444 3
    122. static const uint8_t libhevc_startcode[4] = {0x00, 0x00, 0x00, 0x01};
    123. static const enum AVPixelFormat pix_fmt[][3] = {
    124. [HEVCDEC_PIXEL_LAYOUT_I400] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY10, AV_PIX_FMT_GRAY12 },
    125. [HEVCDEC_PIXEL_LAYOUT_I420] = { AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P10, AV_PIX_FMT_YUV420P12 },
    126. [HEVCDEC_PIXEL_LAYOUT_I422] = { AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV422P12 },
    127. [HEVCDEC_PIXEL_LAYOUT_I444] = { AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12 },
    128. };
    129. static const enum AVPixelFormat pix_fmt_rgb[3] = {
    130. AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRP12,
    131. };
    132. static UWORD32 default_get_stride(void)
    133. {
    134. return 0;
    135. }
    136. static IV_COLOR_FORMAT_T default_get_color_fmt(void)
    137. {
    138. return IV_YUV_420P;
    139. }
    140. static void * _aligned_malloc(int32_t size, int32_t alignment)
    141. {
    142. int32_t alignsize = (size + alignment - 1)/alignment * alignment;
    143. return malloc(alignsize);
    144. }
    145. static void _aligned_free(void *pv_buf)
    146. {
    147. if (pv_buf) {
    148. free(pv_buf);
    149. }
    150. }
    151. static void *ihevca_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size)
    152. {
    153. (void)pv_ctxt;
    154. return (void *)_aligned_malloc(i4_size, alignment);
    155. }
    156. static void ihevca_aligned_free(void *pv_ctxt, void *pv_buf)
    157. {
    158. (void)pv_ctxt;
    159. _aligned_free(pv_buf);
    160. return;
    161. }
    162. static int libhevcdec_init_bsf(AVCodecContext *c)
    163. {
    164. LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data;
    165. /*
    166. *init hevc bitstream filter
    167. * */
    168. libhevc->hevcbsfc = av_bsf_get_by_name("hevc_mp4toannexb");
    169. if (libhevc->hevcbsfc == NULL) {
    170. av_log(c, AV_LOG_ERROR, "libhevc av_bitstream_filter_init failed.");
    171. return -4;
    172. }
    173. if (av_bsf_alloc(libhevc->hevcbsfc, &libhevc->bsf_context) != 0) {
    174. av_log(c, AV_LOG_ERROR, "libhevc av_bsf_alloc failed.");
    175. return -5;
    176. }
    177. if (avcodec_parameters_from_context(libhevc->bsf_context->par_in, c) != 0) {
    178. av_log(c, AV_LOG_ERROR, "libhevc avcodec_parameters_from_context failed.");
    179. return -6;
    180. }
    181. libhevc->bsf_context->time_base_in = c->time_base;
    182. av_bsf_init(libhevc->bsf_context);
    183. return 0;
    184. }
    185. static av_cold int libhevcdec_init(AVCodecContext *c)
    186. {
    187. LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data;
    188. /*
    189. * int pool_size;
    190. int tile_threads;
    191. int num_cores;
    192. int apply_grain;
    193. int operating_point;
    194. int all_layers;
    195. * */
    196. int ret;
    197. strcpy(libhevc->s_app_ctx.ac_ip_fname, "\0");
    198. libhevc->s_app_ctx.dump_q_wr_idx = 0;
    199. libhevc->s_app_ctx.dump_q_rd_idx = 0;
    200. libhevc->s_app_ctx.display_thread_created = 0;
    201. libhevc->s_app_ctx.disp_q_wr_idx = 0;
    202. libhevc->s_app_ctx.disp_q_rd_idx = 0;
    203. libhevc->s_app_ctx.disp_delay = 0;
    204. libhevc->s_app_ctx.loopback = 0;
    205. libhevc->s_app_ctx.display = 0;
    206. libhevc->s_app_ctx.full_screen = 0;
    207. libhevc->s_app_ctx.u4_piclen_flag = 0;
    208. libhevc->s_app_ctx.fps = DEFAULT_FPS;
    209. libhevc->s_app_ctx.share_disp_buf = 0;//DEFAULT_SHARE_DISPLAY_BUF;
    210. libhevc->s_app_ctx.u4_num_cores = DEFAULT_NUM_CORES;
    211. libhevc->s_app_ctx.i4_degrade_type = 0;
    212. libhevc->s_app_ctx.i4_degrade_pics = 0;
    213. libhevc->s_app_ctx.e_arch = ARCH_ARM_A9Q;
    214. libhevc->s_app_ctx.e_soc = SOC_GENERIC;
    215. libhevc->s_app_ctx.u4_strd = STRIDE;
    216. libhevc->s_app_ctx.display_thread_handle = malloc(ithread_get_handle_size());
    217. libhevc->s_app_ctx.quit = 0;
    218. libhevc->s_app_ctx.paused = 0;
    219. libhevc->s_app_ctx.get_stride = &default_get_stride;
    220. libhevc->s_app_ctx.get_color_fmt = &default_get_color_fmt;
    221. libhevc->s_app_ctx.display_deinit_flag = 0;
    222. libhevc->s_app_ctx.e_output_chroma_format = IV_YUV_420SP_UV;
    223. libhevc->inited = 0;
    224. libhevc->bsf_context = NULL;
    225. libhevc->last_max_timestamp = INIT_INVALID_PTS;
    226. libhevc->last_duration = 40;//default 25fps
    227. libhevc->ps_out_buf = (ivd_out_bufdesc_t *)malloc(sizeof(ivd_out_bufdesc_t));
    228. memset(libhevc->ps_out_buf, 0x0, sizeof(ivd_out_bufdesc_t));
    229. libhevc->ps_out_buf->u4_num_bufs = 3;
    230. /*
    231. *create decode instance
    232. * */
    233. ihevcd_cxa_create_ip_t s_create_ip;
    234. ihevcd_cxa_create_op_t s_create_op;
    235. void *fxns = &ivd_cxa_api_function;
    236. s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
    237. s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = libhevc->s_app_ctx.share_disp_buf;
    238. s_create_ip.s_ivd_create_ip_t.e_output_format = (IV_COLOR_FORMAT_T)libhevc->s_app_ctx.e_output_chroma_format;
    239. s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ihevca_aligned_malloc;
    240. s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ihevca_aligned_free;
    241. s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = NULL;
    242. s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ihevcd_cxa_create_ip_t);
    243. s_create_op.s_ivd_create_op_t.u4_size = sizeof(ihevcd_cxa_create_op_t);
    244. ret = ivd_cxa_api_function(NULL, (void *)&s_create_ip,
    245. (void *)&s_create_op);
    246. if (ret != IV_SUCCESS) {
    247. av_log(c, AV_LOG_ERROR, "libhevc decoder open created failed.");
    248. return -1;
    249. }
    250. iv_obj_t *codec_obj = (iv_obj_t*)s_create_op.s_ivd_create_op_t.pv_handle;
    251. codec_obj->pv_fxns = fxns;
    252. codec_obj->u4_size = sizeof(iv_obj_t);
    253. libhevc->s_app_ctx.cocodec_obj = codec_obj; //set code object here ############################
    254. /*
    255. * set num of cores
    256. */
    257. ihevcd_cxa_ctl_set_num_cores_ip_t s_ctl_set_cores_ip;
    258. ihevcd_cxa_ctl_set_num_cores_op_t s_ctl_set_cores_op;
    259. s_ctl_set_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    260. s_ctl_set_cores_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_NUM_CORES;
    261. s_ctl_set_cores_ip.u4_num_cores = libhevc->s_app_ctx.u4_num_cores;
    262. s_ctl_set_cores_ip.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_ip_t);
    263. s_ctl_set_cores_op.u4_size = sizeof(ihevcd_cxa_ctl_set_num_cores_op_t);
    264. ret = ivd_cxa_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_cores_ip,
    265. (void *)&s_ctl_set_cores_op);
    266. if (ret != IV_SUCCESS) {
    267. av_log(c, AV_LOG_ERROR, "libhevc decoder set cores failed.");
    268. return -2;
    269. }
    270. /*
    271. *set processor type
    272. * */
    273. ihevcd_cxa_ctl_set_processor_ip_t s_ctl_set_num_processor_ip;
    274. ihevcd_cxa_ctl_set_processor_op_t s_ctl_set_num_processor_op;
    275. s_ctl_set_num_processor_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    276. s_ctl_set_num_processor_ip.e_sub_cmd = (IVD_CONTROL_API_COMMAND_TYPE_T)IHEVCD_CXA_CMD_CTL_SET_PROCESSOR;
    277. s_ctl_set_num_processor_ip.u4_arch = libhevc->s_app_ctx.e_arch;
    278. s_ctl_set_num_processor_ip.u4_soc = libhevc->s_app_ctx.e_soc;
    279. s_ctl_set_num_processor_ip.u4_size = sizeof(ihevcd_cxa_ctl_set_processor_ip_t);
    280. s_ctl_set_num_processor_op.u4_size = sizeof(ihevcd_cxa_ctl_set_processor_op_t);
    281. ret = ivd_cxa_api_function((iv_obj_t *)codec_obj, (void *)&s_ctl_set_num_processor_ip,
    282. (void *)&s_ctl_set_num_processor_op);
    283. if (ret != IV_SUCCESS) {
    284. av_log(c, AV_LOG_ERROR, "libhevc decoder set processor type failed.");
    285. return -3;
    286. }
    287. return 0;
    288. }
    289. static void libhevcdec_flush(AVCodecContext *c)
    290. {
    291. #if 0
    292. Libdav1dContext *dav1d = c->priv_data;
    293. dav1d_data_unref(&dav1d->data);
    294. dav1d_flush(dav1d->c);
    295. #endif
    296. }
    297. static int libhevcdec_fill_frame_withbuf(AVCodecContext *c, AVFrame *frame, ivd_video_decode_op_t *s_video_decode_frame_op,
    298. ivd_video_decode_ip_t *s_video_decode_frame_ip)
    299. {
    300. LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data;
    301. frame->width = c->width;
    302. frame->height = c->height;
    303. frame->format = AV_PIX_FMT_YUV420P;
    304. if (libhevc->last_max_timestamp == INIT_INVALID_PTS) {
    305. libhevc->last_max_timestamp = s_video_decode_frame_op->u4_ts;
    306. } else {
    307. if (libhevc->last_max_timestamp >= s_video_decode_frame_op->u4_ts
    308. || (s_video_decode_frame_op->u4_ts - libhevc->last_max_timestamp < libhevc->last_duration)) {
    309. libhevc->last_max_timestamp += libhevc->last_duration;
    310. } else {
    311. libhevc->last_max_timestamp = s_video_decode_frame_op->u4_ts;
    312. }
    313. }
    314. frame->pts = libhevc->last_max_timestamp;
    315. frame->pkt_dts = libhevc->last_max_timestamp;
    316. if (av_frame_get_buffer(frame, 16) != 0) {
    317. av_log(c, AV_LOG_ERROR, "decode get AVFrame buffer failed.");
    318. return -14;
    319. }
    320. if (s_video_decode_frame_op->e_pic_type == IV_I_FRAME
    321. || s_video_decode_frame_op->e_pic_type == IV_IDR_FRAME) {
    322. frame->pict_type = AV_PICTURE_TYPE_I;
    323. frame->key_frame = 1;
    324. } else if (s_video_decode_frame_op->e_pic_type == IV_P_FRAME ||
    325. s_video_decode_frame_op->e_pic_type == IV_IP_FRAME ||
    326. s_video_decode_frame_op->e_pic_type == IV_PP_FRAME) {
    327. frame->pict_type = AV_PICTURE_TYPE_P;
    328. } else {
    329. frame->pict_type = AV_PICTURE_TYPE_B;
    330. }
    331. if (s_video_decode_frame_op->e_output_format == IV_YUV_420P) {
    332. /*
    333. *copy y
    334. * */
    335. for (int i = 0; i < c->height; i++) {
    336. UWORD8 *ybuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_y_buf;
    337. memcpy(frame->data[0] + i * frame->linesize[0], ybuf + i * s_video_decode_frame_op->s_disp_frm_buf.u4_y_strd, c->width);
    338. }
    339. /*
    340. *copy u
    341. * */
    342. for (int i = 0; i < c->height/2; i++) {
    343. UWORD8 *ubuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_u_buf;
    344. UWORD8 *vbuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_v_buf;
    345. 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);
    346. 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);
    347. }
    348. } else if (s_video_decode_frame_op->e_output_format == IV_YUV_420SP_UV) {
    349. /*
    350. *copy y
    351. * */
    352. for (int i = 0; i < c->height; i++) {
    353. UWORD8 *ybuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_y_buf;
    354. 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);
    355. }
    356. /*
    357. *copy u v
    358. * */
    359. for (int i = 0; i < c->height/2; i++) {
    360. for (int j = 0; j < c->width/2; j++) {
    361. UWORD8 *ubuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_u_buf;
    362. int index = i * s_video_decode_frame_op->s_disp_frm_buf.u4_u_strd + j * 2;
    363. frame->data[1][i * frame->linesize[1] + j] = ubuf[index];
    364. frame->data[2][i * frame->linesize[2] + j] = ubuf[index + 1];
    365. }
    366. }
    367. } else if (s_video_decode_frame_op->e_output_format == IV_YUV_420SP_VU) {
    368. /*
    369. *copy y
    370. * */
    371. for (int i = 0; i < c->height; i++) {
    372. UWORD8 *ybuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_y_buf;
    373. memcpy(frame->data[0] + i * frame->linesize[0], ybuf + i * s_video_decode_frame_op->s_disp_frm_buf.u4_y_strd, c->width);
    374. }
    375. /*
    376. *copy u v
    377. * */
    378. for (int i = 0; i < c->height/2; i++) {
    379. for (int j = 0; j < c->width/2; j++) {
    380. UWORD8 *ubuf = (UWORD8*)s_video_decode_frame_op->s_disp_frm_buf.pv_u_buf;
    381. int index = i * s_video_decode_frame_op->s_disp_frm_buf.u4_u_strd + j * 2;
    382. frame->data[2][i * frame->linesize[2] + j] = ubuf[index];
    383. frame->data[1][i * frame->linesize[1] + j] = ubuf[index + 1];
    384. }
    385. }
    386. }
    387. return 0;
    388. }
    389. static uint8_t *writebytes(uint8_t *dst, const uint8_t *src, int len)
    390. {
    391. memcpy(dst, src, len);
    392. return dst + len;
    393. }
    394. static int libhevcdec_hvcc2annexb(AVCodecContext *c, AVPacket *pkt)
    395. {
    396. LibhevcdecContext *hevcdec = (LibhevcdecContext *)c->priv_data;
    397. if (av_bsf_send_packet(hevcdec->bsf_context, pkt) < 0){
    398. av_log(c, AV_LOG_ERROR, "av_bsf_send_packet faile \n");
    399. return -1;
    400. }
    401. if (av_bsf_receive_packet(hevcdec->bsf_context, pkt) < 0) {
    402. av_log(c, AV_LOG_ERROR, "av_bsf_receive_packet faile \n");
    403. return -2;
    404. }
    405. return 0;
    406. }
    407. static int libhevcdec_make_codechead(AVCodecContext *c, uint8_t **buf)
    408. {
    409. #define MAX_PADDING (256)
    410. int outlen = c->extradata_size + MAX_PADDING;
    411. uint8_t *outbuf = (uint8_t*)malloc(outlen);
    412. uint8_t *tmp = outbuf;
    413. if (outbuf == NULL) {
    414. av_log(c, AV_LOG_ERROR, "alloc codec head mem failed..");
    415. return -1;
    416. }
    417. HEVCParamSets ps;
    418. HEVCSEI sei;
    419. memset(&ps, 0x0, sizeof(HEVCParamSets));
    420. memset(&sei, 0x0, sizeof(HEVCSEI));
    421. int is_nalff = 0;
    422. int nal_length_size = 0;
    423. int res = ff_hevc_decode_extradata(c->extradata, c->extradata_size, &ps, &sei, &is_nalff, &nal_length_size, 0, 0, c);
    424. if (res != 0) {
    425. av_log(c, AV_LOG_ERROR, "parse extra data failed.");
    426. ff_hevc_ps_uninit(&ps);
    427. return -3;
    428. }
    429. for (int i = 0; i < HEVC_MAX_VPS_COUNT; i++) {
    430. if (ps.vps_list[i]) {
    431. HEVCVPS *vps = (HEVCVPS *)ps.vps_list[i]->data;
    432. tmp = writebytes(tmp, libhevc_startcode, 4);
    433. tmp = writebytes(tmp, vps->data, vps->data_size);
    434. }
    435. }
    436. for (int i = 0; i < HEVC_MAX_SPS_COUNT; i++) {
    437. if (ps.sps_list[i]) {
    438. HEVCSPS *sps = (HEVCSPS *)ps.sps_list[i]->data;
    439. tmp = writebytes(tmp, libhevc_startcode, 4);
    440. tmp = writebytes(tmp, sps->data, sps->data_size);
    441. }
    442. }
    443. for (int i = 0; i < HEVC_MAX_PPS_COUNT; i++) {
    444. if (ps.pps_list[i]) {
    445. HEVCPPS *pps = (HEVCPPS *)ps.pps_list[i]->data;
    446. tmp = writebytes(tmp, libhevc_startcode, 4);
    447. tmp = writebytes(tmp, pps->data, pps->data_size);
    448. }
    449. }
    450. ff_hevc_ps_uninit(&ps);
    451. *buf = outbuf;
    452. return tmp - outbuf;
    453. }
    454. static int libhevcdec_receive_frame(AVCodecContext *c, AVFrame *frame)
    455. {
    456. LibhevcdecContext *hevcdec = (LibhevcdecContext *)c->priv_data;
    457. uint8_t *disp_outbuf = NULL;
    458. int outlen = 0;
    459. int cur_dts = 0;
    460. AVPacket pkt = { 0 };
    461. int res = ff_decode_get_packet(c, &pkt);
    462. if (res < 0 && res != AVERROR_EOF)
    463. return res;
    464. #define FAIL(value) \
    465. {\
    466. pkt.buf = NULL; \
    467. av_packet_unref(&pkt); \
    468. return value; \
    469. }\
    470. (void)0
    471. #define SUCCESS() FAIL(0)
    472. if (pkt.size) {
    473. cur_dts = pkt.pts;
    474. if (pkt.duration > 0) {
    475. hevcdec->last_duration = pkt.duration;
    476. }
    477. if (!hevcdec->inited) {
    478. /*
    479. *set into decoder header mode
    480. * */
    481. ivd_ctl_set_config_ip_t s_ctl_ip;
    482. ivd_ctl_set_config_op_t s_ctl_op;
    483. s_ctl_ip.u4_disp_wd = 0;
    484. s_ctl_ip.e_frm_skip_mode = IVD_SKIP_NONE;
    485. s_ctl_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
    486. s_ctl_ip.e_vid_dec_mode = IVD_DECODE_HEADER;
    487. s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    488. s_ctl_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
    489. s_ctl_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
    490. s_ctl_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
    491. res = ivd_cxa_api_function((iv_obj_t*)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_ctl_ip,
    492. (void *)&s_ctl_op);
    493. if (res != IV_SUCCESS) {
    494. av_log(c, AV_LOG_ERROR, "set decode header mode failed.");
    495. FAIL(-2);
    496. }
    497. /*
    498. * try deocde header
    499. * */
    500. #if 1
    501. uint8_t *headbuf = pkt.data;
    502. uint8_t headlen = pkt.size;
    503. uint8_t *codechead = NULL;
    504. if (c->extradata && c->extradata_size > 0) {
    505. res = libhevcdec_make_codechead(c, &codechead);
    506. if (res < 0) {
    507. av_log(c, AV_LOG_ERROR, "parse codec head failed.");
    508. if (codechead) av_free(codechead);
    509. FAIL(-10);
    510. }
    511. headbuf = codechead;
    512. headlen = res;
    513. }
    514. #endif
    515. ivd_video_decode_ip_t s_video_decode_ip;
    516. ivd_video_decode_op_t s_video_decode_op;
    517. s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
    518. s_video_decode_ip.u4_ts = pkt.pts;
    519. s_video_decode_ip.pv_stream_buffer = headbuf;
    520. s_video_decode_ip.u4_num_Bytes = headlen;
    521. s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t);
    522. s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t);
    523. /*****************************************************************************/
    524. /* API Call: Header Decode */
    525. /*****************************************************************************/
    526. res = ihevcd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_video_decode_ip,
    527. (void *)&s_video_decode_op);
    528. if (codechead) av_free(codechead);
    529. if (res != IV_SUCCESS) {
    530. av_log(c, AV_LOG_ERROR, "decode header failed.");
    531. FAIL(-3);
    532. }
    533. c->width = s_video_decode_op.u4_pic_wd;
    534. c->height = s_video_decode_op.u4_pic_ht;
    535. c->codec_type = AVMEDIA_TYPE_VIDEO;
    536. if (libhevcdec_init_bsf(c) != 0) {
    537. av_log(c, AV_LOG_ERROR, "libhevcdec_init_bsf failed.");
    538. FAIL(-13);
    539. }
    540. if (libhevcdec_hvcc2annexb(c, &pkt) != 0) {
    541. av_log(c, AV_LOG_ERROR, "set decode header mode failed.");
    542. FAIL(-1);
    543. }
    544. cur_dts = pkt.dts;
    545. #define AlignTo(value, align) \
    546. ((value + align - 1)/align * align)
    547. outlen = AlignTo(c->width, 64) * AlignTo(c->height, 64) * 3;
    548. hevcdec->ps_out_buf->u4_min_out_buf_size[0] = hevcdec->ps_out_buf->u4_min_out_buf_size[1] =
    549. hevcdec->ps_out_buf->u4_min_out_buf_size[2] = AlignTo(c->width, 64) * AlignTo(c->height, 64);
    550. #if 1
    551. /*
    552. *set frame out mode
    553. * */
    554. ivd_ctl_set_config_ip_t s_ctl_decode_ip;
    555. ivd_ctl_set_config_op_t s_ctl_decode_op;
    556. s_ctl_decode_ip.u4_disp_wd = 0;
    557. s_ctl_decode_ip.e_frm_skip_mode = IVD_SKIP_NONE;
    558. s_ctl_decode_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
    559. s_ctl_decode_ip.e_vid_dec_mode = IVD_DECODE_FRAME;
    560. s_ctl_decode_ip.e_cmd = IVD_CMD_VIDEO_CTL;
    561. s_ctl_decode_ip.e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
    562. s_ctl_decode_ip.u4_size = sizeof(ivd_ctl_set_config_ip_t);
    563. s_ctl_decode_op.u4_size = sizeof(ivd_ctl_set_config_op_t);
    564. res = ivd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_ctl_decode_ip, (void *)&s_ctl_decode_op);
    565. if (IV_SUCCESS != res) {
    566. av_log(c, AV_LOG_ERROR, "decode set decode mode failed.");
    567. FAIL(-5);
    568. }
    569. #endif
    570. hevcdec->inited = 1;
    571. if (hevcdec->ps_out_buf->pu1_bufs[0] == NULL) {
    572. disp_outbuf = (uint8_t*)malloc(outlen);
    573. hevcdec->ps_out_buf->pu1_bufs[0] = disp_outbuf;
    574. hevcdec->ps_out_buf->u4_min_out_buf_size[0] = hevcdec->ps_out_buf->u4_min_out_buf_size[1] =
    575. hevcdec->ps_out_buf->u4_min_out_buf_size[2] = AlignTo(c->width, 64) * AlignTo(c->height, 64);
    576. hevcdec->ps_out_buf->pu1_bufs[1] = hevcdec->ps_out_buf->pu1_bufs[0] + AlignTo(c->width, 64) * AlignTo(c->height, 64);
    577. hevcdec->ps_out_buf->pu1_bufs[2] = hevcdec->ps_out_buf->pu1_bufs[1] + AlignTo(c->width, 64) * AlignTo(c->height, 64);
    578. hevcdec->ps_out_buf->u4_num_bufs = 3;
    579. }
    580. ivd_video_decode_ip_t s_video_decode_frame_ip;
    581. ivd_video_decode_op_t s_video_decode_frame_op;
    582. s_video_decode_frame_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
    583. s_video_decode_frame_ip.u4_ts = cur_dts;
    584. s_video_decode_frame_ip.pv_stream_buffer = pkt.data;
    585. s_video_decode_frame_ip.u4_num_Bytes = pkt.size;
    586. s_video_decode_frame_ip.u4_size = sizeof(ivd_video_decode_ip_t);
    587. s_video_decode_frame_ip.s_out_buffer.u4_min_out_buf_size[0] =
    588. hevcdec->ps_out_buf->u4_min_out_buf_size[0];
    589. s_video_decode_frame_ip.s_out_buffer.u4_min_out_buf_size[1] =
    590. hevcdec->ps_out_buf->u4_min_out_buf_size[1];
    591. s_video_decode_frame_ip.s_out_buffer.u4_min_out_buf_size[2] =
    592. hevcdec->ps_out_buf->u4_min_out_buf_size[2];
    593. s_video_decode_frame_ip.s_out_buffer.pu1_bufs[0] =
    594. hevcdec->ps_out_buf->pu1_bufs[0];
    595. s_video_decode_frame_ip.s_out_buffer.pu1_bufs[1] =
    596. hevcdec->ps_out_buf->pu1_bufs[1];
    597. s_video_decode_frame_ip.s_out_buffer.pu1_bufs[2] =
    598. hevcdec->ps_out_buf->pu1_bufs[2];
    599. s_video_decode_frame_ip.s_out_buffer.u4_num_bufs =
    600. hevcdec->ps_out_buf->u4_num_bufs;
    601. s_video_decode_frame_op.s_disp_frm_buf.pv_y_buf = hevcdec->ps_out_buf->pu1_bufs[0];
    602. s_video_decode_frame_op.s_disp_frm_buf.pv_u_buf = hevcdec->ps_out_buf->pu1_bufs[1];
    603. s_video_decode_frame_op.s_disp_frm_buf.pv_v_buf = hevcdec->ps_out_buf->pu1_bufs[2];
    604. s_video_decode_frame_op.u4_size = sizeof(ivd_video_decode_op_t);
    605. res = ivd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_video_decode_frame_ip,
    606. (void *)&s_video_decode_frame_op);
    607. if (res != IV_SUCCESS) {
    608. av_log(c, AV_LOG_ERROR, "decode key frame failed. error %d.", s_video_decode_op.u4_error_code);
    609. FAIL(-4);
    610. }
    611. if (s_video_decode_frame_op.e_output_format != IV_YUV_420P
    612. && s_video_decode_frame_op.e_output_format != IV_YUV_420SP_UV
    613. && s_video_decode_frame_op.e_output_format != IV_YUV_420SP_VU) {
    614. av_log(c, AV_LOG_ERROR, "decode format not support. format %d.", s_video_decode_frame_op.e_output_format);
    615. FAIL(-5);
    616. }
    617. if (frame && s_video_decode_op.u4_frame_decoded_flag) {
    618. if (libhevcdec_fill_frame_withbuf(c, frame, &s_video_decode_frame_op, &s_video_decode_frame_ip) != 0) {
    619. av_log(c, AV_LOG_ERROR, "fill frame failed.");
    620. FAIL(-6);
    621. }
    622. }
    623. c->pix_fmt = AV_PIX_FMT_YUV420P;
    624. SUCCESS();
    625. }
    626. if (libhevcdec_hvcc2annexb(c, &pkt) != 0) {
    627. av_log(c, AV_LOG_ERROR, "libhevcdec_hvcc2annexb failed.");
    628. FAIL(-15);
    629. }
    630. ivd_video_decode_ip_t s_video_decode_ip;
    631. ivd_video_decode_op_t s_video_decode_op;
    632. s_video_decode_ip.e_cmd = IVD_CMD_VIDEO_DECODE;
    633. s_video_decode_ip.u4_ts = cur_dts;
    634. s_video_decode_ip.pv_stream_buffer = pkt.data;
    635. s_video_decode_ip.u4_num_Bytes = pkt.size;
    636. s_video_decode_ip.u4_size = sizeof(ivd_video_decode_ip_t);
    637. s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[0] =
    638. hevcdec->ps_out_buf->u4_min_out_buf_size[0];
    639. s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[1] =
    640. hevcdec->ps_out_buf->u4_min_out_buf_size[1];
    641. s_video_decode_ip.s_out_buffer.u4_min_out_buf_size[2] =
    642. hevcdec->ps_out_buf->u4_min_out_buf_size[2];
    643. s_video_decode_ip.s_out_buffer.pu1_bufs[0] =
    644. hevcdec->ps_out_buf->pu1_bufs[0];
    645. s_video_decode_ip.s_out_buffer.pu1_bufs[1] =
    646. hevcdec->ps_out_buf->pu1_bufs[1];
    647. s_video_decode_ip.s_out_buffer.pu1_bufs[2] =
    648. hevcdec->ps_out_buf->pu1_bufs[2];
    649. s_video_decode_ip.s_out_buffer.u4_num_bufs =
    650. hevcdec->ps_out_buf->u4_num_bufs;
    651. s_video_decode_op.u4_size = sizeof(ivd_video_decode_op_t);
    652. res = ivd_cxa_api_function((iv_obj_t *)hevcdec->s_app_ctx.cocodec_obj, (void *)&s_video_decode_ip,
    653. (void *)&s_video_decode_op);
    654. if (res != IV_SUCCESS) {
    655. av_log(c, AV_LOG_ERROR, "Error in video Frame decode : res %x Error %x\n", res,
    656. s_video_decode_op.u4_error_code);
    657. FAIL(-8);
    658. }
    659. if (frame && s_video_decode_op.u4_frame_decoded_flag && s_video_decode_op.u4_output_present) {
    660. if (libhevcdec_fill_frame_withbuf(c, frame, &s_video_decode_op, &s_video_decode_ip) != 0) {
    661. av_log(c, AV_LOG_ERROR, "fill frame failed.");
    662. FAIL(-9);
    663. }
    664. }
    665. if (s_video_decode_op.u4_output_present) {
    666. // 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);
    667. }
    668. }
    669. SUCCESS();
    670. }
    671. static av_cold int libhevcdec_close(AVCodecContext *c)
    672. {
    673. LibhevcdecContext *libhevc = (LibhevcdecContext*)c->priv_data;
    674. if (libhevc->ps_out_buf->pu1_bufs[0]) {
    675. free(libhevc->ps_out_buf->pu1_bufs[0]);
    676. libhevc->ps_out_buf->pu1_bufs[0] = libhevc->ps_out_buf->pu1_bufs[1] = libhevc->ps_out_buf->pu1_bufs[2] = NULL;
    677. }
    678. if (libhevc->ps_out_buf) {
    679. free(libhevc->ps_out_buf);
    680. libhevc->ps_out_buf = NULL;
    681. }
    682. if (libhevc->bsf_context) {
    683. av_bsf_free(&libhevc->bsf_context);
    684. libhevc->bsf_context = NULL;
    685. }
    686. return 0;
    687. }
    688. #define OFFSET(x) offsetof(LibhevcdecContext, x)
    689. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
    690. static const AVOption hevcdec_options[] = {
    691. { "numcores", "decode cores", OFFSET(num_cores), AV_OPT_TYPE_INT, { .i64 = 2 }, 0, 16, VD},
    692. { "cpusimd", "Set the cpu simd", OFFSET(cpu_simd), AV_OPT_TYPE_STRING, { .str = "ARM_NEONINTR" }, 0, 0, VD},
    693. { NULL }
    694. };
    695. static const AVClass libhevcdec_class = {
    696. .class_name = "libhevcdec",
    697. .item_name = av_default_item_name,
    698. .option = hevcdec_options,
    699. .version = LIBAVUTIL_VERSION_INT,
    700. };
    701. const FFCodec ff_libhevcdec_decoder = {
    702. .p.name = "libhevcdec",
    703. .p.long_name = NULL_IF_CONFIG_SMALL("libhevcdec hevc decoder by VideoLAN"),
    704. .p.type = AVMEDIA_TYPE_VIDEO,
    705. .p.id = AV_CODEC_ID_HEVC,
    706. .priv_data_size = sizeof(LibhevcdecContext),
    707. .init = libhevcdec_init,
    708. .close = libhevcdec_close,
    709. .flush = libhevcdec_flush,
    710. FF_CODEC_RECEIVE_FRAME_CB(libhevcdec_receive_frame),
    711. .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS,
    712. .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_SETS_PKT_DTS |
    713. FF_CODEC_CAP_AUTO_THREADS,
    714. .p.priv_class = &libhevcdec_class,
    715. .p.wrapper_name = "libhevcdec",
    716. };

    参考别的库引入,在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

  • 相关阅读:
    混凝土搅拌站预拌厂数字孪生可视化管理系统,三维可视化数据监控平台
    汇凯金业:黄金5g工艺是什么意思
    Python自学笔记9:实操案例六(千年虫,购物流程)
    NLP模型(二)——GloVe介绍
    网页JS自动化脚本(十)新旧字符串关键词检测
    【数据分类】基于麻雀搜索算法优化支持向量机的数据分类方法 SSA-SVM分类算法【Matlab代码#61】
    创建型-单例模式-实现和优缺点
    1488. 避免洪水泛滥
    【智能优化算法-飞蛾扑火优化算法】基于水循环混合飞蛾扑火优化算法求解约束的工程优化问题附matlab代码WCMFO
    【免费模板】2023数学建模国赛word+latex模板免费分享
  • 原文地址:https://blog.csdn.net/fantasy_ARM9/article/details/125434561