예제 #1
0
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 ;
}
예제 #2
0
파일: dirac.c 프로젝트: CSRedRat/vlc
/*****************************************************************************
 * 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;
}