00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "avcodec.h"
00021 #include <x264.h>
00022 #include <math.h>
00023
00024 typedef struct X264Context {
00025 x264_param_t params;
00026 x264_t *enc;
00027 x264_picture_t pic;
00028 AVFrame out_pic;
00029 } X264Context;
00030
00031 static void
00032 X264_log(void *p, int level, const char *fmt, va_list args)
00033 {
00034 static const int level_map[] = {
00035 [X264_LOG_ERROR] = AV_LOG_ERROR,
00036 [X264_LOG_WARNING] = AV_LOG_ERROR,
00037 [X264_LOG_INFO] = AV_LOG_INFO,
00038 [X264_LOG_DEBUG] = AV_LOG_DEBUG
00039 };
00040
00041 if(level < 0 || level > X264_LOG_DEBUG)
00042 return;
00043
00044 av_vlog(p, level_map[level], fmt, args);
00045 }
00046
00047
00048 static int
00049 encode_nals(uint8_t *buf, int size, x264_nal_t *nals, int nnal)
00050 {
00051 uint8_t *p = buf;
00052 int i;
00053
00054 for(i = 0; i < nnal; i++){
00055 int s = x264_nal_encode(p, &size, 1, nals + i);
00056 if(s < 0)
00057 return -1;
00058 p += s;
00059 }
00060
00061 return p - buf;
00062 }
00063
00064 extern int
00065 X264_frame(AVCodecContext *ctx, uint8_t *buf, int bufsize, void *data)
00066 {
00067 X264Context *x4 = ctx->priv_data;
00068 AVFrame *frame = data;
00069 x264_nal_t *nal;
00070 int nnal, i;
00071 x264_picture_t pic_out;
00072
00073 x4->pic.img.i_csp = X264_CSP_I420;
00074 x4->pic.img.i_plane = 3;
00075
00076 for(i = 0; i < 3; i++){
00077 x4->pic.img.plane[i] = frame->data[i];
00078 x4->pic.img.i_stride[i] = frame->linesize[i];
00079 }
00080
00081 x4->pic.i_pts = frame->pts;
00082 x4->pic.i_type = X264_TYPE_AUTO;
00083
00084 if(x264_encoder_encode(x4->enc, &nal, &nnal, &x4->pic, &pic_out))
00085 return -1;
00086
00087 bufsize = encode_nals(buf, bufsize, nal, nnal);
00088 if(bufsize < 0)
00089 return -1;
00090
00091
00092 x4->out_pic.pts = pic_out.i_pts;
00093
00094 switch(pic_out.i_type){
00095 case X264_TYPE_IDR:
00096 case X264_TYPE_I:
00097 x4->out_pic.pict_type = FF_I_TYPE;
00098 break;
00099 case X264_TYPE_P:
00100 x4->out_pic.pict_type = FF_P_TYPE;
00101 break;
00102 case X264_TYPE_B:
00103 case X264_TYPE_BREF:
00104 x4->out_pic.pict_type = FF_B_TYPE;
00105 break;
00106 }
00107
00108 x4->out_pic.key_frame = pic_out.i_type == X264_TYPE_IDR;
00109 x4->out_pic.quality = (pic_out.i_qpplus1 - 1) * FF_QP2LAMBDA;
00110
00111 return bufsize;
00112 }
00113
00114 static int
00115 X264_close(AVCodecContext *avctx)
00116 {
00117 X264Context *x4 = avctx->priv_data;
00118
00119 if(x4->enc)
00120 x264_encoder_close(x4->enc);
00121
00122 return 0;
00123 }
00124
00125 extern int
00126 X264_init(AVCodecContext *avctx)
00127 {
00128 X264Context *x4 = avctx->priv_data;
00129
00130 x264_param_default(&x4->params);
00131
00132 x4->params.pf_log = X264_log;
00133 x4->params.p_log_private = avctx;
00134
00135 x4->params.i_keyint_max = avctx->gop_size;
00136 x4->params.rc.i_bitrate = avctx->bit_rate / 1000;
00137 x4->params.rc.i_vbv_buffer_size = avctx->rc_buffer_size / 1000;
00138 if(avctx->rc_buffer_size) {
00139 #if X264_BUILD < 48
00140 x4->params.rc.b_cbr = 1;
00141 #else
00142 x4->params.rc.i_rc_method = X264_RC_ABR;
00143 #endif
00144 }
00145 x4->params.i_bframe = avctx->max_b_frames;
00146 x4->params.b_cabac = avctx->coder_type == FF_CODER_TYPE_AC;
00147
00148 x4->params.rc.i_qp_min = avctx->qmin;
00149 x4->params.rc.i_qp_max = avctx->qmax;
00150 x4->params.rc.i_qp_step = avctx->max_qdiff;
00151
00152 if(avctx->flags & CODEC_FLAG_QSCALE && avctx->global_quality > 0)
00153 x4->params.rc.i_qp_constant =
00154 12 + 6 * log2((double) avctx->global_quality / FF_QP2LAMBDA);
00155
00156 x4->params.i_width = avctx->width;
00157 x4->params.i_height = avctx->height;
00158 x4->params.vui.i_sar_width = avctx->sample_aspect_ratio.num;
00159 x4->params.vui.i_sar_height = avctx->sample_aspect_ratio.den;
00160 x4->params.i_fps_num = avctx->time_base.den;
00161 x4->params.i_fps_den = avctx->time_base.num;
00162
00163 x4->params.i_threads = avctx->thread_count;
00164
00165 x4->enc = x264_encoder_open(&x4->params);
00166 if(!x4->enc)
00167 return -1;
00168
00169 avctx->coded_frame = &x4->out_pic;
00170
00171 return 0;
00172 }
00173
00174 AVCodec x264_encoder = {
00175 .name = "h264",
00176 .type = CODEC_TYPE_VIDEO,
00177 .id = CODEC_ID_H264,
00178 .priv_data_size = sizeof(X264Context),
00179 .init = X264_init,
00180 .encode = X264_frame,
00181 .close = X264_close,
00182 .pix_fmts = (enum PixelFormat[]) { PIX_FMT_YUV420P, -1 }
00183 };