x264.c
来自「这个库实现了录象功能」· C语言 代码 · 共 933 行 · 第 1/2 页
C
933 行
static struct { int x264_level; lqt_log_level_t lqt_level; }log_levels[] = { { X264_LOG_ERROR, LQT_LOG_ERROR }, { X264_LOG_WARNING, LQT_LOG_WARNING }, { X264_LOG_INFO, LQT_LOG_INFO }, { X264_LOG_DEBUG, LQT_LOG_DEBUG }, { X264_LOG_NONE, LQT_LOG_WARNING } };static voidx264_do_log( void * priv, int i_level, const char *psz, va_list argp) { int i; lqt_log_level_t lqt_level; quicktime_t * file; char * msg_string; #ifndef HAVE_VASPRINTF int len;#endif file = (quicktime_t *)priv; for(i = 0; i < sizeof(log_levels) / sizeof(log_levels[0]); i++) { if(log_levels[i].x264_level == i_level) { lqt_level = log_levels[i].lqt_level; break; } } if(i >= sizeof(log_levels) / sizeof(log_levels[0])) { lqt_log(file, LQT_LOG_WARNING, LOG_DOMAIN, "Invalid log level from x264"); return; }#ifndef HAVE_VASPRINTF len = vsnprintf((char*)0, 0, psz, argp); msg_string = malloc(len+1); vsnprintf(msg_string, len+1, psz, argp);#else vasprintf(&msg_string, psz, argp);#endif i = strlen(msg_string); if(msg_string[i-1] == '\n') msg_string[i-1] = '\0'; lqt_logs(file, lqt_level, LOG_DOMAIN, msg_string); free(msg_string); }static void set_fiel(quicktime_t * file, int track) { quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_stsd_table_t *stsd; stsd = vtrack->track->mdia.minf.stbl.stsd.table; if(stsd->has_fiel) return; switch(vtrack->interlace_mode) { case LQT_INTERLACE_NONE: lqt_set_fiel(file, track, 1, 0); break; case LQT_INTERLACE_TOP_FIRST: lqt_set_fiel(file, track, 2, 9); break; case LQT_INTERLACE_BOTTOM_FIRST: lqt_set_fiel(file, track, 2, 14); break; } }static int encode(quicktime_t *file, unsigned char **row_pointers, int track) { x264_picture_t pic_in; int result = 0, pixel_width, pixel_height; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_trak_t *trak = vtrack->track; quicktime_x264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int height = trak->tkhd.track_height; int width = trak->tkhd.track_width; uint8_t * avcc; int avcc_size; if(!row_pointers) { vtrack->stream_cmodel = BC_YUV420P; return 0; } /* Initialize */ if(!codec->initialized) { codec->work_buffer_size = width * height * 3; codec->work_buffer = malloc(codec->work_buffer_size); /* Any smaller value here? */ /* We want a global header */ codec->params.b_repeat_headers = 0; /* Don't output psnr statistics */ codec->params.analyse.b_psnr = 0; /* Set format */ codec->params.i_width = width; codec->params.i_height = height; lqt_get_pixel_aspect(file, track, &pixel_width, &pixel_height); codec->params.vui.i_sar_width = pixel_width; codec->params.vui.i_sar_height = pixel_height; codec->params.i_fps_num = lqt_video_time_scale(file, track); codec->params.i_fps_den = lqt_frame_duration(file, track, NULL); // Set up logging codec->params.pf_log = x264_do_log; codec->params.p_log_private = file; #if X264_BUILD >= 51 if(lqt_get_interlace_mode(file, track) != LQT_INTERLACE_NONE) { lqt_log(file, LQT_LOG_INFO, LOG_DOMAIN, "Choosing interlaced encoding"); codec->params.b_interlaced = 1; set_fiel(file, track); }#endif /* Set multipass control */ if(codec->total_passes) { /* Force ABR */ codec->params.rc.i_rc_method = X264_RC_ABR;#if X264_BUILD < 54 codec->params.rc.i_rf_constant = 0;#else codec->params.rc.f_rf_constant = 0.;#endif if(codec->pass == 1) { /* Strings will be made private by x264 */ codec->params.rc.psz_stat_out = codec->stats_filename; codec->params.rc.b_stat_write = 1; } else if(codec->pass == codec->total_passes) { /* Strings will be made private by x264 */ codec->params.rc.psz_stat_in = codec->stats_filename; codec->params.rc.b_stat_read = 1; } }#ifdef DUMP_CONFIG dump_params(&codec->params);#endif /* Open encoder */ codec->enc = x264_encoder_open(&codec->params); if(!codec->enc) { lqt_log(file, LQT_LOG_ERROR, LOG_DOMAIN, "x264_encoder_open failed"); return result; } if(codec->params.i_bframe) vtrack->has_b_frames = 1; /* Encode global header */ avcc = create_avcc_atom(codec, &avcc_size); quicktime_user_atoms_add_atom(&(trak->mdia.minf.stbl.stsd.table[0].user_atoms), "avcC", avcc, avcc_size); file->moov.iods.videoProfileId = 0x15; codec->initialized = 1; } /* Encode picture */ memset(&pic_in, 0, sizeof(pic_in)); pic_in.img.i_csp = X264_CSP_I420; pic_in.img.i_plane = 3; pic_in.img.plane[0] = row_pointers[0]; pic_in.img.plane[1] = row_pointers[1]; pic_in.img.plane[2] = row_pointers[2]; pic_in.img.i_stride[0] = vtrack->stream_row_span; pic_in.img.i_stride[1] = vtrack->stream_row_span_uv; pic_in.img.i_stride[2] = vtrack->stream_row_span_uv; pic_in.i_pts = vtrack->timestamp; pic_in.i_type = X264_TYPE_AUTO; flush_frame(file, track, &pic_in); return result; }static int flush(quicktime_t *file, int track) { quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_x264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; /* Do nothing if we didn't encode anything yet */ if(!codec->initialized) return 0; return flush_frame(file, track, (x264_picture_t*)0); } #define INTPARAM(name, var) \ if(!strcasecmp(key, name)) \ { \ var = *((int*)value); \ found = 1; \ }#define FLOATPARAM(name, var) \ if(!strcasecmp(key, name)) \ { \ var = *((float*)value); \ found = 1; \ }#define ENUMPARAM(name, var, arr) \ if(!strcasecmp(key, name)) \ { \ for(i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) \ { \ if(!strcasecmp((char*)value, arr[i].s)) \ { \ var = arr[i].i; \ break; \ } \ } \ found = 1; \ }typedef struct { char * s; int i; } enum_t; enum_t me_methods[] = { { "Diamond search", X264_ME_DIA }, { "Hexagonal search", X264_ME_HEX }, { "Uneven Multi-Hexagon", X264_ME_UMH }, { "Exhaustive search", X264_ME_ESA } };enum_t trellis[] = { { "Disabled", 0 }, { "Enabled (final)", 1 }, { "Enabled (always)", 2 } };enum_t direct_modes[] = { { "None", X264_DIRECT_PRED_NONE }, { "Spatial", X264_DIRECT_PRED_SPATIAL }, { "Temporal", X264_DIRECT_PRED_TEMPORAL }, { "Auto", X264_DIRECT_PRED_AUTO } };enum_t rc_methods[] = { { "Constant quality", X264_RC_CQP }, { "Average bitrate", X264_RC_ABR }, { "CRF based VBR", X264_RC_CRF } };#if X264_BUILD >= 63enum_t bframe_adaptives[] = { { "None", X264_B_ADAPT_NONE }, { "Fast", X264_B_ADAPT_FAST }, { "Trellis", X264_B_ADAPT_TRELLIS } };#endifstatic int set_parameter(quicktime_t *file, int track, const char *key, const void *value) { int found = 0, i; quicktime_x264_codec_t *codec = ((quicktime_codec_t*)file->vtracks[track].codec)->priv; INTPARAM("x264_i_keyint_max", codec->params.i_keyint_max); INTPARAM("x264_i_keyint_min", codec->params.i_keyint_min); INTPARAM("x264_i_scenecut_threshold", codec->params.i_scenecut_threshold); INTPARAM("x264_i_bframe", codec->params.i_bframe);#if X264_BUILD < 63 INTPARAM("x264_b_bframe_adaptive", codec->params.b_bframe_adaptive);#else ENUMPARAM("x264_i_bframe_adaptive", codec->params.i_bframe_adaptive, bframe_adaptives);#endif INTPARAM("x264_i_bframe_bias", codec->params.i_bframe_bias); INTPARAM("x264_b_bframe_pyramid", codec->params.b_bframe_pyramid); ENUMPARAM("x264_i_rc_method", codec->params.rc.i_rc_method, rc_methods); INTPARAM("x264_i_bitrate", codec->params.rc.i_bitrate); INTPARAM("x264_i_qp_constant", codec->params.rc.i_qp_constant);#if X264_BUILD < 54 INTPARAM("x264_i_rf_constant", codec->params.rc.i_rf_constant);#else FLOATPARAM("x264_f_rf_constant", codec->params.rc.f_rf_constant);#endif INTPARAM("x264_i_qp_min", codec->params.rc.i_qp_min); INTPARAM("x264_i_qp_max", codec->params.rc.i_qp_max); INTPARAM("x264_i_qp_step", codec->params.rc.i_qp_step); FLOATPARAM("x264_f_rate_tolerance", codec->params.rc.f_rate_tolerance); INTPARAM("x264_i_vbv_max_bitrate", codec->params.rc.i_vbv_max_bitrate); INTPARAM("x264_i_vbv_buffer_size", codec->params.rc.i_vbv_buffer_size); FLOATPARAM("x264_f_vbv_buffer_init", codec->params.rc.f_vbv_buffer_init); FLOATPARAM("x264_f_ip_factor", codec->params.rc.f_ip_factor); FLOATPARAM("x264_f_pb_factor", codec->params.rc.f_pb_factor); INTPARAM("x264_analyse_8x8_transform", codec->params.analyse.b_transform_8x8); if(!strcasecmp(key, "x264_analyse_psub16x16")) { if(*(int*)(value)) { codec->params.analyse.inter |= X264_ANALYSE_PSUB16x16; } else { codec->params.analyse.inter &= ~X264_ANALYSE_PSUB16x16; } found = 1; } if(!strcasecmp(key, "x264_analyse_bsub16x16")) { if(*(int*)(value)) { codec->params.analyse.inter |= X264_ANALYSE_BSUB16x16; } else { codec->params.analyse.inter &= ~X264_ANALYSE_BSUB16x16; } found = 1; } if(!strcasecmp(key, "x264_analyse_psub8x8")) { if(*(int*)(value)) { codec->params.analyse.inter |= X264_ANALYSE_PSUB8x8; } else { codec->params.analyse.inter &= ~X264_ANALYSE_PSUB8x8; } found = 1; } if(!strcasecmp(key, "x264_analyse_i8x8")) { if(*(int*)(value)) { codec->params.analyse.intra |= X264_ANALYSE_I8x8; codec->params.analyse.inter |= X264_ANALYSE_I8x8; } else { codec->params.analyse.intra &= ~X264_ANALYSE_I8x8; codec->params.analyse.inter &= ~X264_ANALYSE_I8x8; } found = 1; } if(!strcasecmp(key, "x264_analyse_i4x4")) { if(*(int*)(value)) { codec->params.analyse.intra |= X264_ANALYSE_I4x4; codec->params.analyse.inter |= X264_ANALYSE_I4x4; } else { codec->params.analyse.intra &= ~X264_ANALYSE_I4x4; codec->params.analyse.inter &= ~X264_ANALYSE_I4x4; } found = 1; } ENUMPARAM("x264_i_me_method", codec->params.analyse.i_me_method, me_methods); INTPARAM("x264_i_subpel_refine", codec->params.analyse.i_subpel_refine);#if X264_BUILD < 65 INTPARAM("x264_b_bframe_rdo", codec->params.analyse.b_bframe_rdo);#endif INTPARAM("x264_i_me_range", codec->params.analyse.i_me_range); INTPARAM("x264_i_frame_reference", codec->params.i_frame_reference); INTPARAM("x264_b_chroma_me", codec->params.analyse.b_chroma_me); INTPARAM("x264_b_mixed_references", codec->params.analyse.b_mixed_references);#if X264_BUILD < 65 INTPARAM("x264_b_bidir_me", codec->params.analyse.b_bidir_me);#endif INTPARAM("x264_b_weighted_bipred", codec->params.analyse.b_weighted_bipred); ENUMPARAM("x264_i_direct_mv_pred", codec->params.analyse.i_direct_mv_pred, direct_modes); INTPARAM("x264_b_deblocking_filter", codec->params.b_deblocking_filter); INTPARAM("x264_i_deblocking_filter_alphac0", codec->params.i_deblocking_filter_alphac0); INTPARAM("x264_i_deblocking_filter_beta", codec->params.i_deblocking_filter_beta); INTPARAM("x264_b_cabac", codec->params.b_cabac); ENUMPARAM("x264_i_trellis", codec->params.analyse.i_trellis, trellis); INTPARAM("x264_i_noise_reduction", codec->params.analyse.i_noise_reduction); if(!found) lqt_log(file, LQT_LOG_WARNING, LOG_DOMAIN, "Unrecognized parameter %s", key); return 0; }void quicktime_init_codec_x264(quicktime_video_map_t *vtrack) { quicktime_x264_codec_t *codec; /* Init public items */ ((quicktime_codec_t*)vtrack->codec)->priv = calloc(1, sizeof(quicktime_x264_codec_t)); ((quicktime_codec_t*)vtrack->codec)->delete_vcodec = delete_codec; ((quicktime_codec_t*)vtrack->codec)->encode_video = encode; ((quicktime_codec_t*)vtrack->codec)->set_pass = set_pass_x264; ((quicktime_codec_t*)vtrack->codec)->flush = flush; ((quicktime_codec_t*)vtrack->codec)->decode_video = 0; ((quicktime_codec_t*)vtrack->codec)->set_parameter = set_parameter; ((quicktime_codec_t*)vtrack->codec)->decode_audio = 0; ((quicktime_codec_t*)vtrack->codec)->encode_audio = 0; /* Init private items */ codec = ((quicktime_codec_t*)vtrack->codec)->priv; x264_param_default(&(codec->params)); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?