static int libdirac_encode_init(AVCodecContext *avccontext) { FfmpegDiracEncoderParams* p_dirac_params = avccontext->priv_data; int no_local = 1; int verbose = avccontext->debug; VideoFormat preset; /* get Dirac preset */ preset = GetDiracVideoFormatPreset(avccontext); /* initialize the encoder context */ dirac_encoder_context_init (&(p_dirac_params->enc_ctx), preset); p_dirac_params->enc_ctx.src_params.chroma = GetDiracChromaFormat(avccontext->pix_fmt); if (p_dirac_params->enc_ctx.src_params.chroma == formatNK) { av_log (avccontext, AV_LOG_ERROR, "Unsupported pixel format %d. This codec supports only " "Planar YUV formats (yuv420p, yuv422p, yuv444p\n", avccontext->pix_fmt); return -1; } p_dirac_params->enc_ctx.src_params.frame_rate.numerator = avccontext->time_base.den; p_dirac_params->enc_ctx.src_params.frame_rate.denominator = avccontext->time_base.num; p_dirac_params->enc_ctx.src_params.width = avccontext->width; p_dirac_params->enc_ctx.src_params.height = avccontext->height; p_dirac_params->frame_size = avpicture_get_size(avccontext->pix_fmt, avccontext->width, avccontext->height); avccontext->coded_frame = &p_dirac_params->picture; if (no_local) { p_dirac_params->enc_ctx.decode_flag = 0; p_dirac_params->enc_ctx.instr_flag = 0; } else { p_dirac_params->enc_ctx.decode_flag = 1; p_dirac_params->enc_ctx.instr_flag = 1; } /* Intra-only sequence */ if (avccontext->gop_size == 0 ) p_dirac_params->enc_ctx.enc_params.num_L1 = 0; else avccontext->has_b_frames = 1; if (avccontext->flags & CODEC_FLAG_QSCALE) { if (avccontext->global_quality != 0) { p_dirac_params->enc_ctx.enc_params.qf = avccontext->global_quality / (FF_QP2LAMBDA*10.0); /* if it is not default bitrate then send target rate. */ if (avccontext->bit_rate >= 1000 && avccontext->bit_rate != 200000) { p_dirac_params->enc_ctx.enc_params.trate = avccontext->bit_rate / 1000; } } else p_dirac_params->enc_ctx.enc_params.lossless = 1; } else if (avccontext->bit_rate >= 1000) p_dirac_params->enc_ctx.enc_params.trate = avccontext->bit_rate / 1000; if ((preset > VIDEO_FORMAT_QCIF || preset < VIDEO_FORMAT_QSIF525) && avccontext->bit_rate == 200000) { p_dirac_params->enc_ctx.enc_params.trate = 0; } if (avccontext->flags & CODEC_FLAG_INTERLACED_ME) { /* all material can be coded as interlaced or progressive * irrespective of the type of source material */ p_dirac_params->enc_ctx.enc_params.picture_coding_mode = 1; } p_dirac_params->p_encoder = dirac_encoder_init (&(p_dirac_params->enc_ctx), verbose ); if (!p_dirac_params->p_encoder) { av_log(avccontext, AV_LOG_ERROR, "Unrecoverable Error: dirac_encoder_init failed. "); return EXIT_FAILURE; } /* allocate enough memory for the incoming data */ p_dirac_params->p_in_frame_buf = av_malloc(p_dirac_params->frame_size); /* initialize the encoded frame queue */ ff_dirac_schro_queue_init(&p_dirac_params->enc_frame_queue); return 0 ; }
/***************************************************************************** * OpenEncoder: probe the encoder and return score *****************************************************************************/ static int OpenEncoder( vlc_object_t *p_this ) { encoder_t *p_enc = (encoder_t *)p_this; encoder_sys_t *p_sys = p_enc->p_sys; int i_tmp; float f_tmp; char *psz_tmp; if( p_enc->fmt_out.i_codec != VLC_CODEC_DIRAC && !p_enc->b_force ) { return VLC_EGENERIC; } if( !p_enc->fmt_in.video.i_frame_rate || !p_enc->fmt_in.video.i_frame_rate_base || !p_enc->fmt_in.video.i_height || !p_enc->fmt_in.video.i_width ) { msg_Err( p_enc, "Framerate and picture dimensions must be non-zero" ); return VLC_EGENERIC; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_sys = calloc( 1, sizeof(*p_sys) ) ) == NULL ) return VLC_ENOMEM; p_enc->p_sys = p_sys; p_enc->pf_encode_video = Encode; p_enc->fmt_out.i_codec = VLC_CODEC_DIRAC; p_enc->fmt_out.i_cat = VIDEO_ES; if( ( p_sys->p_dts_fifo = block_FifoNew() ) == NULL ) { CloseEncoder( p_this ); return VLC_ENOMEM; } ResetPTStlb( p_enc ); /* guess the video format based upon number of lines and picture height */ int i = 0; VideoFormat guessed_video_fmt = VIDEO_FORMAT_CUSTOM; /* Pick the dirac_video_format in this order of preference: * 1. an exact match in frame height and an approximate fps match * 2. the previous preset with a smaller number of lines. */ do { if( dirac_format_guess[i].i_height > p_enc->fmt_in.video.i_height ) { guessed_video_fmt = dirac_format_guess[i-1].i_vf; break; } if( dirac_format_guess[i].i_height != p_enc->fmt_in.video.i_height ) continue; int src_fps = p_enc->fmt_in.video.i_frame_rate / p_enc->fmt_in.video.i_frame_rate_base; int delta_fps = abs( dirac_format_guess[i].i_approx_fps - src_fps ); if( delta_fps > 2 ) continue; guessed_video_fmt = dirac_format_guess[i].i_vf; break; } while( dirac_format_guess[++i].i_height ); dirac_encoder_context_init( &p_sys->ctx, guessed_video_fmt ); /* constants set from the input video format */ p_sys->ctx.src_params.width = p_enc->fmt_in.video.i_width; p_sys->ctx.src_params.height = p_enc->fmt_in.video.i_height; p_sys->ctx.src_params.frame_rate.numerator = p_enc->fmt_in.video.i_frame_rate; p_sys->ctx.src_params.frame_rate.denominator = p_enc->fmt_in.video.i_frame_rate_base; unsigned u_asr_num, u_asr_den; vlc_ureduce( &u_asr_num, &u_asr_den, p_enc->fmt_in.video.i_sar_num, p_enc->fmt_in.video.i_sar_den, 0 ); p_sys->ctx.src_params.pix_asr.numerator = u_asr_num; p_sys->ctx.src_params.pix_asr.denominator = u_asr_den; config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg ); psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CHROMAFMT ); if( !psz_tmp ) goto error; else if( !strcmp( psz_tmp, "420" ) ) { p_enc->fmt_in.i_codec = VLC_CODEC_I420; p_enc->fmt_in.video.i_bits_per_pixel = 12; p_sys->ctx.src_params.chroma = format420; p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 3 / 2; } else if( !strcmp( psz_tmp, "422" ) ) { p_enc->fmt_in.i_codec = VLC_CODEC_I422; p_enc->fmt_in.video.i_bits_per_pixel = 16; p_sys->ctx.src_params.chroma = format422; p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 2; } else if( !strcmp( psz_tmp, "444" ) ) { p_enc->fmt_in.i_codec = VLC_CODEC_I444; p_enc->fmt_in.video.i_bits_per_pixel = 24; p_sys->ctx.src_params.chroma = format444; p_sys->i_buffer_in = p_enc->fmt_in.video.i_width * p_enc->fmt_in.video.i_height * 3; } else { msg_Err( p_enc, "Invalid chroma format: %s", psz_tmp ); free( psz_tmp ); goto error; } free( psz_tmp ); p_sys->ctx.enc_params.qf = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_QUALITY_FACTOR ); /* use bitrate from sout-transcode-vb in kbps */ p_sys->ctx.enc_params.trate = p_enc->fmt_out.i_bitrate / 1000; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_TARGETRATE ); if( i_tmp > -1 ) p_sys->ctx.enc_params.trate = i_tmp; p_enc->fmt_out.i_bitrate = p_sys->ctx.enc_params.trate * 1000; p_sys->ctx.enc_params.lossless = var_GetBool( p_enc, ENC_CFG_PREFIX ENC_LOSSLESS ); psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_PREFILTER ); if( !psz_tmp ) goto error; else if( !strcmp( psz_tmp, "none" ) ) { p_sys->ctx.enc_params.prefilter = NO_PF; } else if( !strcmp( psz_tmp, "cwm" ) ) { p_sys->ctx.enc_params.prefilter = CWM; } else if( !strcmp( psz_tmp, "rectlp" ) ) { p_sys->ctx.enc_params.prefilter = RECTLP; } else if( !strcmp( psz_tmp, "diaglp" ) ) { p_sys->ctx.enc_params.prefilter = DIAGLP; } else { msg_Err( p_enc, "Invalid prefilter: %s", psz_tmp ); free( psz_tmp ); goto error; } free( psz_tmp ); p_sys->ctx.enc_params.prefilter_strength = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_PREFILTER_STRENGTH ); i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_L1SEP ); if( i_tmp > -1 ) p_sys->ctx.enc_params.L1_sep = i_tmp; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_L1NUM ); if( i_tmp > -1 ) p_sys->ctx.enc_params.num_L1 = i_tmp; psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_CODINGMODE ); if( !psz_tmp ) goto error; else if( !strcmp( psz_tmp, "auto" ) ) { p_sys->b_auto_field_coding = true; } else if( !strcmp( psz_tmp, "progressive" ) ) { p_sys->b_auto_field_coding = false; p_sys->ctx.enc_params.picture_coding_mode = 0; } else if( !strcmp( psz_tmp, "field" ) ) { p_sys->b_auto_field_coding = false; p_sys->ctx.enc_params.picture_coding_mode = 1; } else { msg_Err( p_enc, "Invalid codingmode: %s", psz_tmp ); free( psz_tmp ); goto error; } free( psz_tmp ); psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_MVPREC ); if( !psz_tmp ) goto error; else if( !strcmp( psz_tmp, "1" ) ) { p_sys->ctx.enc_params.mv_precision = MV_PRECISION_PIXEL; } else if( !strcmp( psz_tmp, "1/2" ) ) { p_sys->ctx.enc_params.mv_precision = MV_PRECISION_HALF_PIXEL; } else if( !strcmp( psz_tmp, "1/4" ) ) { p_sys->ctx.enc_params.mv_precision = MV_PRECISION_QUARTER_PIXEL; } else if( !strcmp( psz_tmp, "1/8" ) ) { p_sys->ctx.enc_params.mv_precision = MV_PRECISION_EIGHTH_PIXEL; } else { msg_Err( p_enc, "Invalid mv-prec: %s", psz_tmp ); free( psz_tmp ); goto error; } free( psz_tmp ); /* * {x,y}b{len,sep} must be multiples of 4 */ i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_WIDTH ); if( i_tmp > -1 ) p_sys->ctx.enc_params.xbsep = i_tmp / 4 * 4; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_HEIGHT ); if( i_tmp > -1 ) p_sys->ctx.enc_params.ybsep = i_tmp / 4 * 4; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_OVERLAP ); if( i_tmp > -1 ) { p_sys->ctx.enc_params.xblen = p_sys->ctx.enc_params.xbsep * (100 + i_tmp) / 400 * 4; p_sys->ctx.enc_params.yblen = p_sys->ctx.enc_params.ybsep * (100 + i_tmp) / 400 * 4; } /* * {x,y}blen >= {x,y}bsep * {x,y}blen <= 2* {x,y}bsep */ i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_XBLEN ); if( i_tmp > -1 ) { int xblen = __MAX( i_tmp, p_sys->ctx.enc_params.xbsep ); xblen = __MIN( xblen, 2 * p_sys->ctx.enc_params.xbsep ); p_sys->ctx.enc_params.xblen = xblen; } i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MCBLK_YBLEN ); if( i_tmp > -1 ) { int yblen = __MAX( i_tmp, p_sys->ctx.enc_params.ybsep ); yblen = __MIN( yblen, 2 * p_sys->ctx.enc_params.ybsep ); p_sys->ctx.enc_params.yblen = yblen; } psz_tmp = var_GetString( p_enc, ENC_CFG_PREFIX ENC_ME_SIMPLESEARCH ); if( !psz_tmp ) goto error; if( *psz_tmp != '\0' ) { /* of the form [0-9]+:[0-9]+ */ char *psz_start = psz_tmp; char *psz_end = psz_tmp; p_sys->ctx.enc_params.x_range_me = strtol(psz_start, &psz_end, 10); if( *psz_end != ':' || psz_end == psz_start ) { msg_Err( p_enc, "Invalid simple search range: %s", psz_tmp ); free( psz_tmp ); goto error; } psz_start = ++psz_end; p_sys->ctx.enc_params.y_range_me = strtol(psz_start, &psz_end, 10); if( *psz_end != '\0' || psz_end == psz_start ) { msg_Err( p_enc, "Invalid simple search range: %s", psz_tmp ); free( psz_tmp ); goto error; } if( p_sys->ctx.enc_params.x_range_me < 0 || p_sys->ctx.enc_params.y_range_me < 0 ) { msg_Err( p_enc, "Invalid negative simple search range: %s", psz_tmp ); free( psz_tmp ); goto error; } p_sys->ctx.enc_params.full_search = 1; } free( psz_tmp ); #if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,1) p_sys->ctx.enc_params.combined_me = var_GetBool( p_enc, ENC_CFG_PREFIX ENC_ME_COMBINED ); #endif i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTRA ); if( i_tmp > -1 ) p_sys->ctx.enc_params.intra_wlt_filter = i_tmp; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTINTER ); if( i_tmp > -1 ) p_sys->ctx.enc_params.inter_wlt_filter = i_tmp; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_DWTDEPTH ); if( i_tmp > -1 ) p_sys->ctx.enc_params.wlt_depth = i_tmp; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_MULTIQUANT ); if( i_tmp > -1 ) p_sys->ctx.enc_params.multi_quants = i_tmp; i_tmp = var_GetInteger( p_enc, ENC_CFG_PREFIX ENC_SPARTITION ); if( i_tmp > -1 ) p_sys->ctx.enc_params.spatial_partition = i_tmp; p_sys->ctx.enc_params.using_ac = !var_GetBool( p_enc, ENC_CFG_PREFIX ENC_NOAC ); f_tmp = var_GetFloat( p_enc, ENC_CFG_PREFIX ENC_CPD ); if( f_tmp > -1 ) p_sys->ctx.enc_params.cpd = f_tmp; /* Allocate the buffer for inputing frames into the encoder */ if( ( p_sys->p_buffer_in = malloc( p_sys->i_buffer_in ) ) == NULL ) { CloseEncoder( p_this ); return VLC_ENOMEM; } /* Set up output buffer */ /* Unfortunately it isn't possible to determine if the buffer * is too small (and then reallocate it) */ p_sys->i_buffer_out = 4096 + p_sys->i_buffer_in; if( ( p_sys->p_buffer_out = malloc( p_sys->i_buffer_out ) ) == NULL ) { CloseEncoder( p_this ); return VLC_ENOMEM; } return VLC_SUCCESS; error: CloseEncoder( p_this ); return VLC_EGENERIC; }