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 + -
显示快捷键?