Пример #1
0
char * hb_dict_to_encopts( hb_dict_t * dict )
{
    int first_opt = 1;
    char *tmp, *encopts_tmp, *encopts = NULL;
    hb_dict_entry_t * entry = NULL;
    while( ( entry = hb_dict_next( dict, entry ) ) )
    {
        tmp = hb_strdup_printf( "%s%s%s%s",
                                first_opt    ? "" : ":",
                                entry->key,
                                entry->value ? "=" : "",
                                entry->value ? entry->value : "" );
        if( tmp )
        {
            encopts_tmp = hb_strncat_dup( encopts, tmp, strlen( tmp ) );
            if( encopts_tmp )
            {
                if( encopts )
                    free( encopts );
                encopts = encopts_tmp;
            }
            first_opt = 0;
            free( tmp );
        }
    }
    return encopts;
}
Пример #2
0
/***********************************************************************
 * hb_work_encx265_init
 ***********************************************************************
 *
 **********************************************************************/
int encx265Init(hb_work_object_t *w, hb_job_t *job)
{
    hb_work_private_t *pv = calloc(1, sizeof(hb_work_private_t));
    pv->next_chapter_pts  = AV_NOPTS_VALUE;
    pv->delayed_chapters  = hb_list_init();
    pv->job               = job;
    w->private_data       = pv;
    int i, vrate, vrate_base;
    x265_nal *nal;
    uint32_t nnal;

    x265_param *param = pv->param = x265_param_alloc();

    if (x265_param_default_preset(param,
                                  job->encoder_preset, job->encoder_tune) < 0)
    {
        free(pv);
        pv = NULL;
        return 1;
    }

    /* If the PSNR or SSIM tunes are in use, enable the relevant metric */
    param->bEnablePsnr = param->bEnableSsim = 0;
    if (job->encoder_tune != NULL && *job->encoder_tune)
    {
        char *tmp = strdup(job->encoder_tune);
        char *tok = strtok(tmp,   ",./-+");
        do
        {
            if (!strncasecmp(tok, "psnr", 4))
            {
                param->bEnablePsnr = 1;
                break;
            }
            if (!strncasecmp(tok, "ssim", 4))
            {
                param->bEnableSsim = 1;
                break;
            }
        }
        while ((tok = strtok(NULL, ",./-+")) != NULL);
        free(tmp);
    }

    /*
     * Some HandBrake-specific defaults; users can override them
     * using the encoder_options string.
     */
    hb_reduce(&vrate, &vrate_base, job->vrate, job->vrate_base);
    param->fpsNum      = vrate;
    param->fpsDenom    = vrate_base;
    param->keyframeMin = (int)((double)vrate / (double)vrate_base + 0.5);
    param->keyframeMax = param->keyframeMin * 10;

    /* iterate through x265_opts and parse the options */
    hb_dict_entry_t *entry = NULL;
    hb_dict_t *x265_opts = hb_encopts_to_dict(job->encoder_options, job->vcodec);
    while ((entry = hb_dict_next(x265_opts, entry)) != NULL)
    {
        // here's where the strings are passed to libx265 for parsing
        int ret = x265_param_parse(param, entry->key, entry->value);
        // let x265 sanity check the options for us
        switch (ret)
        {
            case X265_PARAM_BAD_NAME:
                hb_log("encx265: unknown option '%s'", entry->key);
                break;
            case X265_PARAM_BAD_VALUE:
                hb_log("encx265: bad argument '%s=%s'", entry->key,
                       entry->value ? entry->value : "(null)");
                break;
            default:
                break;
        }
    }
    hb_dict_free(&x265_opts);

    /*
     * Settings which can't be overriden in the encodeer_options string
     * (muxer-specific settings, resolution, ratecontrol, etc.).
     */
    param->sourceWidth  = job->width;
    param->sourceHeight = job->height;

    if (job->vquality > 0)
    {
        param->rc.rateControlMode = X265_RC_CRF;
        param->rc.rfConstant      = job->vquality;
    }
    else
    {
        param->rc.rateControlMode = X265_RC_ABR;
        param->rc.bitrate         = job->vbitrate;
    }

    /* statsfile (but not 2-pass) */
    memset(pv->csvfn, 0, sizeof(pv->csvfn));
    if (param->logLevel >= X265_LOG_DEBUG)
    {
        if (param->csvfn == NULL)
        {
            hb_get_tempory_filename(job->h, pv->csvfn, "x265.csv");
            param->csvfn = pv->csvfn;
        }
        else
        {
            strncpy(pv->csvfn, param->csvfn, sizeof(pv->csvfn));
        }
    }

    /* Apply profile and level settings last. */
    if (x265_param_apply_profile(param, job->encoder_profile) < 0)
    {
        free(pv);
        pv = NULL;
        return 1;
    }

    /* we should now know whether B-frames are enabled */
    job->areBframes = (param->bframes > 0) + (param->bframes   > 0 &&
                                              param->bBPyramid > 0);

    pv->x265 = x265_encoder_open(param);
    if (pv->x265 == NULL)
    {
        hb_error("encx265: x265_encoder_open failed.");
        free(pv);
        pv = NULL;
        return 1;
    }

    if (x265_encoder_headers(pv->x265, &nal, &nnal) < 0)
    {
        hb_error("encx265: x265_encoder_headers failed.");
        free(pv);
        pv = NULL;
        return 1;
    }

    /*
     * x265's output (headers and bitstream) are in Annex B format.
     *
     * Write the header as is, and let the muxer reformat
     * the extradata and output bitstream properly for us.
     */
    w->config->h265.headers_length = 0;
    for (i = 0; i < nnal; i++)
    {
        if (w->config->h265.headers_length +
            nal[i].sizeBytes > HB_CONFIG_MAX_SIZE)
        {
            hb_error("encx265: bitstream headers too large");
            free(pv);
            pv = NULL;
            return 1;
        }
        memcpy(w->config->h265.headers +
               w->config->h265.headers_length,
               nal[i].payload, nal[i].sizeBytes);
        w->config->h265.headers_length += nal[i].sizeBytes;
    }

    return 0;
}