Esempio n. 1
0
struct mp_image *convert_image(struct mp_image *image, int destfmt,
                               struct mp_log *log)
{
    int d_w, d_h;
    mp_image_params_get_dsize(&image->params, &d_w, &d_h);
    bool is_anamorphic = image->w != d_w || image->h != d_h;

    // Caveat: no colorspace/levels conversion done if pixel formats equal
    //         it's unclear what colorspace/levels the target wants
    if (image->imgfmt == destfmt && !is_anamorphic)
        return mp_image_new_ref(image);

    struct mp_image *dst = mp_image_alloc(destfmt, d_w, d_h);
    if (!dst) {
        mp_err(log, "Out of memory.\n");
        return NULL;
    }
    mp_image_copy_attributes(dst, image);

    if (mp_image_swscale(dst, image, mp_sws_hq_flags) < 0) {
        mp_err(log, "Error when converting image.\n");
        talloc_free(dst);
        return NULL;
    }

    return dst;
}
Esempio n. 2
0
void mp_get_src_dst_rects(struct mp_log *log, struct mp_vo_opts *opts,
                          int vo_caps, struct mp_image_params *video,
                          int window_w, int window_h, double monitor_par,
                          struct mp_rect *out_src,
                          struct mp_rect *out_dst,
                          struct mp_osd_res *out_osd)
{
    int src_w = video->w;
    int src_h = video->h;
    int src_dw, src_dh;
    mp_image_params_get_dsize(video, &src_dw, &src_dh);
    if (video->rotate % 180 == 90 && (vo_caps & VO_CAP_ROTATE90)) {
        MPSWAP(int, src_w, src_h);
        MPSWAP(int, src_dw, src_dh);
    }
    window_w = MPMAX(1, window_w);
    window_h = MPMAX(1, window_h);
    struct mp_rect dst = {0, 0, window_w, window_h};
    struct mp_rect src = {0, 0, src_w,    src_h};
    struct mp_osd_res osd = {
        .w = window_w,
        .h = window_h,
        .display_par = monitor_par,
    };
    if (opts->keepaspect) {
        int scaled_width, scaled_height;
        aspect_calc_panscan(log, opts, src_w, src_h, src_dw, src_dh,
                            window_w, window_h, monitor_par,
                            &scaled_width, &scaled_height);
        src_dst_split_scaling(src_w, window_w, scaled_width, opts->unscaled,
                              opts->zoom, opts->align_x, opts->pan_x,
                              &src.x0, &src.x1, &dst.x0, &dst.x1,
                              &osd.ml, &osd.mr);
        src_dst_split_scaling(src_h, window_h, scaled_height, opts->unscaled,
                              opts->zoom, opts->align_y, opts->pan_y,
                              &src.y0, &src.y1, &dst.y0, &dst.y1,
                              &osd.mt, &osd.mb);
    }

    *out_src = src;
    *out_dst = dst;
    *out_osd = osd;

    int sw = src.x1 - src.x0, sh = src.y1 - src.y0;
    int dw = dst.x1 - dst.x0, dh = dst.y1 - dst.y0;

    mp_verbose(log, "Window size: %dx%d\n",
               window_w, window_h);
    mp_verbose(log, "Video source: %dx%d (%d:%d)\n",
               video->w, video->h, video->p_w, video->p_h);
    mp_verbose(log, "Video display: (%d, %d) %dx%d -> (%d, %d) %dx%d\n",
               src.x0, src.y0, sw, sh, dst.x0, dst.y0, dw, dh);
    mp_verbose(log, "Video scale: %f/%f\n",
               (double)dw / sw, (double)dh / sh);
    mp_verbose(log, "OSD borders: l=%d t=%d r=%d b=%d\n",
               osd.ml, osd.mt, osd.mr, osd.mb);
    mp_verbose(log, "Video borders: l=%d t=%d r=%d b=%d\n",
               dst.x0, dst.y0, window_w - dst.x1, window_h - dst.y1);
}
Esempio n. 3
0
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
                    struct mp_image_params *out)
{
    struct vf_priv_s *p = vf->priv;

    *out = *in;

    if (p->outfmt)
        out->imgfmt = p->outfmt;
    if (p->colormatrix)
        out->colorspace = p->colormatrix;
    if (p->colorlevels)
        out->colorlevels = p->colorlevels;
    if (p->primaries)
        out->primaries = p->primaries;
    if (p->gamma)
        out->gamma = p->gamma;
    if (p->chroma_location)
        out->chroma_location = p->chroma_location;
    if (p->stereo_in)
        out->stereo_in = p->stereo_in;
    if (p->stereo_out)
        out->stereo_out = p->stereo_out;
    if (p->rotate >= 0)
        out->rotate = p->rotate;

    AVRational dsize;
    mp_image_params_get_dsize(out, &dsize.num, &dsize.den);
    if (p->dw > 0)
        dsize.num = p->dw;
    if (p->dh > 0)
        dsize.den = p->dh;
    if (p->dar > 0)
        dsize = av_d2q(p->dar, INT_MAX);
    mp_image_params_set_dsize(out, dsize.num, dsize.den);

    // Make sure the user-overrides are consistent (no RGB csp for YUV, etc.).
    mp_image_params_guess_csp(out);

    return 0;
}
Esempio n. 4
0
static int reinit_vs(struct vf_instance *vf)
{
    struct vf_priv_s *p = vf->priv;
    VSMap *vars = NULL, *in = NULL, *out = NULL;
    int res = -1;

    destroy_vs(vf);

    MP_DBG(vf, "initializing...\n");
    p->initializing = true;

    if (p->drv->load_core(vf) < 0 || !p->vsapi || !p->vscore) {
        MP_FATAL(vf, "Could not get vapoursynth API handle.\n");
        goto error;
    }

    in = p->vsapi->createMap();
    out = p->vsapi->createMap();
    vars = p->vsapi->createMap();
    if (!in || !out || !vars)
        goto error;

    p->vsapi->createFilter(in, out, "Input", infiltInit, infiltGetFrame,
                           infiltFree, fmSerial, 0, vf, p->vscore);
    int vserr;
    p->in_node = p->vsapi->propGetNode(out, "clip", 0, &vserr);
    if (!p->in_node) {
        MP_FATAL(vf, "Could not get our own input node.\n");
        goto error;
    }

    if (p->vsapi->propSetNode(vars, "video_in", p->in_node, 0))
        goto error;

    int d_w, d_h;
    mp_image_params_get_dsize(&p->fmt_in, &d_w, &d_h);

    p->vsapi->propSetInt(vars, "video_in_dw", d_w, 0);
    p->vsapi->propSetInt(vars, "video_in_dh", d_h, 0);
    p->vsapi->propSetFloat(vars, "container_fps", vf->chain->container_fps, 0);
    p->vsapi->propSetFloat(vars, "display_fps", vf->chain->display_fps, 0);

    if (p->drv->load(vf, vars) < 0)
        goto error;
    if (!p->out_node) {
        MP_FATAL(vf, "Could not get script output node.\n");
        goto error;
    }

    const VSVideoInfo *vi = p->vsapi->getVideoInfo(p->out_node);
    if (!isConstantFormat(vi)) {
        MP_FATAL(vf, "Video format is required to be constant.\n");
        goto error;
    }

    pthread_mutex_lock(&p->lock);
    p->initializing = false;
    pthread_mutex_unlock(&p->lock);
    MP_DBG(vf, "initialized.\n");
    res = 0;
error:
    if (p->vsapi) {
        p->vsapi->freeMap(in);
        p->vsapi->freeMap(out);
        p->vsapi->freeMap(vars);
    }
    if (res < 0)
        destroy_vs(vf);
    return res;
}
Esempio n. 5
0
struct mp_image *convert_image(struct mp_image *image, int destfmt,
                               struct mp_log *log)
{
    int d_w, d_h;
    mp_image_params_get_dsize(&image->params, &d_w, &d_h);

    struct mp_image_params p = {
        .imgfmt = destfmt,
        .w = d_w,
        .h = d_h,
        .p_w = 1,
        .p_h = 1,
    };
    mp_image_params_guess_csp(&p);

    // If RGB, just assume everything is correct.
    if (p.color.space != MP_CSP_RGB) {
        // Currently, assume what FFmpeg's jpg encoder needs.
        // Of course this works only for non-HDR (no HDR support in libswscale).
        p.color.levels = MP_CSP_LEVELS_PC;
        p.color.space = MP_CSP_BT_601;
        p.chroma_location = MP_CHROMA_CENTER;
        mp_image_params_guess_csp(&p);
    }

    if (mp_image_params_equal(&p, &image->params))
        return mp_image_new_ref(image);

    struct mp_image *dst = mp_image_alloc(p.imgfmt, p.w, p.h);
    if (!dst) {
        mp_err(log, "Out of memory.\n");
        return NULL;
    }
    mp_image_copy_attributes(dst, image);

    dst->params = p;

    if (mp_image_swscale(dst, image, mp_sws_hq_flags) < 0) {
        mp_err(log, "Error when converting image.\n");
        talloc_free(dst);
        return NULL;
    }

    return dst;
}

bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
                const char *filename, struct mp_log *log)
{
    struct image_writer_opts defs = image_writer_opts_defaults;
    if (!opts)
        opts = &defs;

    struct image_writer_ctx ctx = { log, opts, image->fmt };
    bool (*write)(struct image_writer_ctx *, mp_image_t *, FILE *) = write_lavc;
    int destfmt = 0;

#if HAVE_JPEG
    if (opts->format == AV_CODEC_ID_MJPEG) {
        write = write_jpeg;
        destfmt = IMGFMT_RGB24;
    }
#endif

    if (!destfmt)
        destfmt = get_target_format(&ctx);

    struct mp_image *dst = convert_image(image, destfmt, log);
    if (!dst)
        return false;

    FILE *fp = fopen(filename, "wb");
    bool success = false;
    if (fp == NULL) {
        mp_err(log, "Error opening '%s' for writing!\n", filename);
    } else {
        success = write(&ctx, dst, fp);
        success = !fclose(fp) && success;
        if (!success)
            mp_err(log, "Error writing file '%s'!\n", filename);
    }

    talloc_free(dst);
    return success;
}

void dump_png(struct mp_image *image, const char *filename, struct mp_log *log)
{
    struct image_writer_opts opts = image_writer_opts_defaults;
    opts.format = AV_CODEC_ID_PNG;
    write_image(image, &opts, filename, log);
}