示例#1
0
/** @internal @This catches events of the avcdec.
 *
 * @param uprobe pointer to probe
 * @param upipe pointer to pipe throwing the event
 * @param event event thrown
 * @param args optional event-specific parameters
 * @return an error code
 */
static int upipe_glxplayer_catch_avcdec(struct uprobe *uprobe,
                                        struct upipe *upipe,
                                        int event, va_list args)
{
    switch (event) {
        case UPROBE_NEED_OUTPUT: {
            struct upipe_glxplayer *glxplayer =
                container_of(uprobe, struct upipe_glxplayer, uprobe_avcdec_s);
            struct uref *flow_def = va_arg(args, struct uref *);
            struct upipe *deint =
                upipe_void_alloc_output(upipe,
                        glxplayer->upipe_filter_blend_mgr,
                        uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger),
                                         glxplayer->loglevel, "deint"));
            if (unlikely(deint == NULL))
                return UBASE_ERR_ALLOC;

            struct uref *output_flow = uref_dup(flow_def);
            if (unlikely(output_flow == NULL))
                return UBASE_ERR_ALLOC;
            uref_pic_flow_clear_format(output_flow);
            if (unlikely(!ubase_check(uref_pic_flow_set_macropixel(output_flow, 1)) ||
                         !ubase_check(uref_pic_flow_set_planes(output_flow, 0)) ||
                         !ubase_check(uref_pic_flow_add_plane(output_flow, 1, 1, 3,
                                                  "r8g8b8")))) {
                uref_free(output_flow);
                return UBASE_ERR_ALLOC;
            }

            struct upipe *yuvrgb = upipe_flow_alloc_output(deint,
                    glxplayer->upipe_sws_mgr,
                    uprobe_pfx_alloc_va(uprobe_use(glxplayer->uprobe_logger),
                                        glxplayer->loglevel, "rgb"),
                    output_flow);
            assert(yuvrgb != NULL);
            uref_free(output_flow);
            upipe_release(deint);

            glxplayer->upipe_glx_qsink =
                upipe_qsink_alloc(glxplayer->upipe_qsink_mgr,
                    uprobe_pfx_alloc(uprobe_use(glxplayer->uprobe_logger),
                    glxplayer->loglevel, "glx qsink"),
                    glxplayer->upipe_glx_qsrc);
            if (unlikely(glxplayer->upipe_glx_qsink == NULL))
                return UBASE_ERR_ALLOC;
            upipe_set_output(yuvrgb, glxplayer->upipe_glx_qsink);
            upipe_release(yuvrgb);
            return UBASE_ERR_NONE;
        }
        default:
            return uprobe_throw_next(uprobe, upipe, event, args);
    }
}
示例#2
0
/** @internal @This handles data.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure
 * @param upump_p reference to pump that generated the buffer
 * @return false if the input must be blocked
 */
static bool upipe_tblk_handle(struct upipe *upipe, struct uref *uref,
                              struct upump **upump_p)
{
    struct upipe_tblk *upipe_tblk = upipe_tblk_from_upipe(upipe);
    const char *def;
    if (unlikely(ubase_check(uref_flow_get_def(uref, &def)))) {
        if (!ubase_ncmp(def, "pic.")) {
            upipe_tblk->input_alloc = UBUF_ALLOC_PICTURE;
            uref_pic_flow_clear_format(uref);
            uref_flow_set_def(uref, "block.");
        } else if (!ubase_ncmp(def, "sound.")) {
            upipe_tblk->input_alloc = UBUF_ALLOC_SOUND;
            uref_sound_flow_clear_format(uref);
            uref_flow_set_def(uref, "block.");
        } else
            upipe_tblk->input_alloc = UBUF_ALLOC_BLOCK;

        upipe_tblk_store_flow_def(upipe, NULL);
        upipe_tblk_require_ubuf_mgr(upipe, uref);
        return true;
    }

    if (upipe_tblk->flow_def == NULL)
        return false;
    assert(upipe_tblk->ubuf_mgr != NULL);

    switch (upipe_tblk->input_alloc) {
        case UBUF_ALLOC_PICTURE:
            upipe_tblk_handle_pic(upipe, uref, upump_p);
            break;
        case UBUF_ALLOC_SOUND:
            upipe_tblk_handle_sound(upipe, uref, upump_p);
            break;
        default:
            upipe_tblk_output(upipe, uref, upump_p);
            break;
    }
    return true;
}
示例#3
0
/** @internal @This handles data.
 *
 * @param upipe description structure of the pipe
 * @param uref uref structure describing the picture
 * @param upump_p reference to pump that generated the buffer
 * @return true if the packet was handled
 */
static bool upipe_audiobar_handle(struct upipe *upipe, struct uref *uref,
                                  struct upump **upump_p)
{
    struct upipe_audiobar *upipe_audiobar = upipe_audiobar_from_upipe(upipe);
    const char *def;
    if (unlikely(ubase_check(uref_flow_get_def(uref, &def)))) {
        UBASE_FATAL(upipe,
                uref_sound_flow_get_channels(uref, &upipe_audiobar->channels))
        uref_sound_flow_clear_format(uref);
        UBASE_FATAL(upipe,
                uref_attr_import(uref, upipe_audiobar->flow_def_config))
        uref_pic_flow_clear_format(uref);
        UBASE_FATAL(upipe, uref_pic_flow_set_planes(uref, 0))
        UBASE_FATAL(upipe, uref_pic_flow_set_macropixel(uref, 1))
        UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 1, 1, 1, "y8"))
        UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 2, 1, 1, "u8"))
        UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 2, 1, 1, "v8"))
        UBASE_FATAL(upipe, uref_pic_flow_add_plane(uref, 1, 1, 1, "a8"))
        UBASE_FATAL(upipe, uref_pic_set_progressive(uref))

        upipe_audiobar->hsize = upipe_audiobar->vsize =
            upipe_audiobar->sep_width = upipe_audiobar->pad_width = UINT64_MAX;
        upipe_audiobar_require_flow_format(upipe, uref);
        return true;
    }

    if (!upipe_audiobar->ubuf_mgr)
        return false;

    if (unlikely(upipe_audiobar->hsize == UINT64_MAX))
        return false;

    struct ubuf *ubuf = ubuf_pic_alloc(upipe_audiobar->ubuf_mgr,
                                       upipe_audiobar->hsize,
                                       upipe_audiobar->vsize);
    uref_attach_ubuf(uref, ubuf);

    uint8_t *dst[4];
    size_t strides[4];
    uint8_t hsubs[4];
    uint8_t vsubs[4];
    static const char *chroma[4] = { "y8", "u8", "v8", "a8" };
    for (int i = 0; i < 4; i++) {
        if (unlikely(!ubase_check(uref_pic_plane_write(uref, chroma[i],
                            0, 0, -1, -1, &dst[i])) ||
                     !ubase_check(uref_pic_plane_size(uref, chroma[i],
                             &strides[i], &hsubs[i], &vsubs[i], NULL)))) {
             upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
             uref_free(uref);
             return true;
        }
    }

    uint8_t alpha = upipe_audiobar->alpha;
    uint64_t h = upipe_audiobar->vsize;
    const int hred = h - (iec_scale(-8.) * h);
    const int hyellow = h - (iec_scale(-18.) * h);
    uint8_t transparent[4] = { 0x10, 0x80, 0x80, 0 };
    uint8_t black[4] = { 0x10, 0x80, 0x80, alpha };
    uint8_t red[2][4] = { { 76, 85, 0xff, alpha }, { 37, 106, 191, alpha } };
    uint8_t green[2][4] = { { 150, 44, 21, alpha }, { 74, 85, 74, alpha } };
    uint8_t yellow[2][4] = { { 226, 1, 148, alpha }, { 112, 64, 138, alpha } };

    uint64_t pts = 0;
    if (unlikely(!ubase_check(uref_clock_get_pts_prog(uref, &pts)))) {
        upipe_warn(upipe, "unable to read pts");
    }

    for (uint8_t chan = 0; chan < upipe_audiobar->channels; chan++) {
        double amplitude = 0.;
        if (unlikely(!ubase_check(uref_amax_get_amplitude(uref, &amplitude,
                                                          chan))))
            upipe_warn_va(upipe, "unable to get amplitude for channel %"PRIu8", assuming silence", chan);

        double scale = log10(amplitude) * 20;

        // IEC-268-18 return time speed is 20dB per 1.7s (+/- .3)
        if (upipe_audiobar->peak_date[chan])
            upipe_audiobar->peak[chan] -= 20 * (pts - upipe_audiobar->peak_date[chan]) / (1.7 * UCLOCK_FREQ);

        upipe_audiobar->peak_date[chan] = pts;

        if (scale >= upipe_audiobar->peak[chan]) /* higher than lowered peak */
            upipe_audiobar->peak[chan] = scale;
        else /* Current amplitude can not go below the lowered peak value */
            scale = upipe_audiobar->peak[chan];

        scale = iec_scale(scale);

        const int hmax = h - scale * h;
        for (int row = 0; row < h; row++) {
            bool bright = row > hmax;

            const uint8_t *color = row < hred ? red[!bright] :
                                   row < hyellow ? yellow[!bright] :
                                   green[!bright];

            copy_color(dst, strides, hsubs, vsubs, color, row,
                       chan * upipe_audiobar->chan_width,
                       upipe_audiobar->chan_width);
            if (chan && upipe_audiobar->sep_width)
                copy_color(dst, strides, hsubs, vsubs, black, row,
                           chan * upipe_audiobar->chan_width -
                           upipe_audiobar->sep_width / 2,
                           upipe_audiobar->sep_width);

            if (chan == upipe_audiobar->channels - 1 &&
                upipe_audiobar->pad_width)
                copy_color(dst, strides, hsubs, vsubs, transparent, row,
                           (chan + 1) * upipe_audiobar->chan_width,
                           upipe_audiobar->pad_width);
        }
    }

    /* dB marks */
    for (int i = 1; i <= 6; i++) {
        int row = h - (iec_scale(-10 * i) * h);
        copy_color(dst, strides, hsubs, vsubs, black, row, 0,
                   upipe_audiobar->hsize);
    }

    for (int i = 0; i < 4; i++)
        ubuf_pic_plane_unmap(ubuf, chroma[i], 0, 0, -1, -1);
    upipe_audiobar_output(upipe, uref, upump_p);
    return true;
}
示例#4
0
/** avcdec callback */
static int avcdec_catch(struct uprobe *uprobe, struct upipe *upipe,
                        int event, va_list args)
{
    if (event != UPROBE_NEED_OUTPUT)
        return uprobe_throw_next(uprobe, upipe, event, args);

    struct uref *flow_def = va_arg(args, struct uref *);

    uint64_t hsize, vsize, wanted_hsize;
    struct urational sar;
    bool progressive;
    if (unlikely(!ubase_check(uref_pic_flow_get_hsize(flow_def, &hsize)) ||
                 !ubase_check(uref_pic_flow_get_vsize(flow_def, &vsize)) ||
                 !ubase_check(uref_pic_flow_get_sar(flow_def, &sar)))) {
        upipe_err_va(upipe, "incompatible flow def");
        upipe_release(upipe_source);
        return UBASE_ERR_UNHANDLED;
    }
    wanted_hsize = (hsize * sar.num / sar.den / 2) * 2;
    progressive = ubase_check(uref_pic_get_progressive(flow_def));

    struct uref *flow_def2 = uref_dup(flow_def);
    upipe_use(upipe);

    if (!progressive) {
        uref_pic_set_progressive(flow_def2);
        struct upipe *deint = upipe_void_alloc_output(upipe,
                upipe_filter_blend_mgr,
                uprobe_pfx_alloc(uprobe_use(logger),
                                 loglevel, "deint"));
        assert(deint != NULL);
        upipe_release(upipe);
        upipe = deint;
    }

    if (wanted_hsize != hsize) {
        uref_pic_flow_set_hsize(flow_def2, wanted_hsize);
        struct upipe *sws = upipe_flow_alloc_output(upipe, upipe_sws_mgr,
                uprobe_pfx_alloc_va(uprobe_use(logger),
                                    loglevel, "sws"), flow_def2);
        assert(sws != NULL);
        upipe_release(upipe);
        upipe = sws;
    }

    uref_pic_flow_clear_format(flow_def2);
    uref_flow_set_def(flow_def2, "block.mjpeg.pic.");
    struct upipe *jpegenc = upipe_flow_alloc_output(upipe, upipe_avcenc_mgr,
            uprobe_pfx_alloc_va(uprobe_use(logger),
                                loglevel, "jpeg"), flow_def2);
    assert(jpegenc != NULL);
    upipe_release(upipe);
    upipe_set_option(jpegenc, "qmax", "2");
    upipe = jpegenc;

    struct upipe *urefprobe = upipe_void_alloc_output(upipe,
            upipe_probe_uref_mgr,
            uprobe_pfx_alloc_va(uprobe_use(&uprobe_uref),
                                loglevel, "urefprobe"));
    assert(urefprobe != NULL);
    upipe_release(upipe);
    upipe = urefprobe;

    struct upipe *fsink = upipe_void_alloc_output(upipe, upipe_fsink_mgr,
            uprobe_pfx_alloc_va(uprobe_use(logger),
            ((loglevel > UPROBE_LOG_DEBUG) ? UPROBE_LOG_WARNING : loglevel),
            "jpegsink"));
    assert(fsink != NULL);
    upipe_release(upipe);
    upipe_fsink_set_path(fsink, dstpath, UPIPE_FSINK_OVERWRITE);
    upipe = fsink;

    uref_free(flow_def2);
    upipe_release(upipe);
    return UBASE_ERR_NONE;
}
示例#5
0
/** @internal @This sets the input flow def.
 *
 * @param upipe description structure of the pipe
 * @param flow_def the flow format to set
 * @return an error code
 */
static int upipe_vblk_set_flow_def(struct upipe *upipe,
                                   struct uref *flow_def)
{
    struct upipe_vblk *upipe_vblk = upipe_vblk_from_upipe(upipe);

    if (!ubase_check(uref_flow_match_def(flow_def, UREF_VOID_FLOW_DEF)) &&
        !ubase_check(upipe_vblk_check_flow_def(upipe, flow_def)))
        return UBASE_ERR_INVALID;

    struct uref *input_flow_def = uref_dup(flow_def);
    if (unlikely(!input_flow_def)) {
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return UBASE_ERR_ALLOC;
    }
    upipe_vblk_store_flow_def_input(upipe, input_flow_def);

    if (ubase_check(uref_flow_match_def(flow_def, UREF_VOID_FLOW_DEF)))
        return UBASE_ERR_NONE;

    uint64_t hsize = 0, vsize = 0;
    UBASE_RETURN(uref_pic_flow_get_hsize(flow_def, &hsize));
    UBASE_RETURN(uref_pic_flow_get_vsize(flow_def, &vsize));

    struct uref *flow_def_dup = uref_dup(flow_def);
    if (unlikely(!flow_def_dup)) {
        upipe_throw_fatal(upipe, UBASE_ERR_ALLOC);
        return UBASE_ERR_ALLOC;
    }

    struct urational sar;
    uref_pic_flow_clear_format(flow_def_dup);
    uref_pic_flow_copy_format(flow_def_dup, flow_def);
    uref_pic_flow_set_hsize(flow_def_dup, hsize);
    uref_pic_flow_set_vsize(flow_def_dup, vsize);
    if (likely(ubase_check(uref_pic_flow_get_sar(flow_def, &sar)))) {
        uref_pic_flow_set_sar(flow_def_dup, sar);
    } else {
        uref_pic_flow_delete_sar(flow_def_dup);
    }
    bool overscan;
    if (likely(ubase_check(uref_pic_flow_get_overscan(flow_def, &overscan)))) {
        uref_pic_flow_set_overscan(flow_def_dup, overscan);
    } else {
        uref_pic_flow_delete_overscan(flow_def_dup);
    }
    if (likely(ubase_check(uref_pic_get_progressive(flow_def)))) {
        uref_pic_set_progressive(flow_def_dup);
    } else {
        uref_pic_delete_progressive(flow_def_dup);
    }
    upipe_vblk_store_flow_def(upipe, flow_def_dup);

    if (upipe_vblk->ubuf) {
        ubuf_free(upipe_vblk->ubuf);
        upipe_vblk->ubuf = NULL;
    }

    if (upipe_vblk->ubuf_mgr &&
        !ubase_check(ubuf_mgr_check(upipe_vblk->ubuf_mgr, flow_def_dup))) {
        ubuf_mgr_release(upipe_vblk->ubuf_mgr);
        upipe_vblk->ubuf_mgr = NULL;
    }

    return UBASE_ERR_NONE;
}