static GstFlowReturn
gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
                          GstCaps * caps, GstBuffer ** buf)
{
    gint width, height;
    GstStructure *structure = NULL;
    GstSLVideo *slvideo;
    slvideo = GST_SLVIDEO(bsink);

    // caps == requested caps
    // we can ignore these and reverse-negotiate our preferred dimensions with
    // the peer if we like - we need to do this to obey dynamic resize requests
    // flowing in from the app.
    structure = llgst_caps_get_structure (caps, 0);
    if (!llgst_structure_get_int(structure, "width", &width) ||
            !llgst_structure_get_int(structure, "height", &height))
    {
        GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
        return GST_FLOW_NOT_NEGOTIATED;
    }

    GstBuffer *newbuf = llgst_buffer_new();
    bool made_bufferdata_ptr = false;
#define MAXDEPTHHACK 4

    GST_OBJECT_LOCK(slvideo);
    if (slvideo->resize_forced_always) // app is giving us a fixed size to work with
    {
        gint slwantwidth, slwantheight;
        slwantwidth = slvideo->resize_try_width;
        slwantheight = slvideo->resize_try_height;

        if (slwantwidth != width ||
                slwantheight != height)
        {
            // don't like requested caps, we will issue our own suggestion - copy
            // the requested caps but substitute our own width and height and see
            // if our peer is happy with that.

            GstCaps *desired_caps;
            GstStructure *desired_struct;
            desired_caps = llgst_caps_copy (caps);
            desired_struct = llgst_caps_get_structure (desired_caps, 0);

            GValue value = {0};
            g_value_init(&value, G_TYPE_INT);
            g_value_set_int(&value, slwantwidth);
            llgst_structure_set_value (desired_struct, "width", &value);
            g_value_unset(&value);
            g_value_init(&value, G_TYPE_INT);
            g_value_set_int(&value, slwantheight);
            llgst_structure_set_value (desired_struct, "height", &value);

            if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
                                            desired_caps))
            {
                // todo: re-use buffers from a pool?
                // todo: set MALLOCDATA to null, set DATA to point straight to shm?

                // peer likes our cap suggestion
                DEBUGMSG("peer loves us :)");
                GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
                GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
                GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
                llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);

                made_bufferdata_ptr = true;
            } else {
                // peer hates our cap suggestion
                INFOMSG("peer hates us :(");
                llgst_caps_unref(desired_caps);
            }
        }
    }

    GST_OBJECT_UNLOCK(slvideo);

    if (!made_bufferdata_ptr) // need to fallback to malloc at original size
    {
        GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
        GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
        GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
        llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
    }

    *buf = GST_BUFFER_CAST(newbuf);

    return GST_FLOW_OK;
}
Пример #2
0
/* this function handles the link with other elements */
static gboolean
gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
	GstSLVideo *filter;
	GstStructure *structure;
	GstCaps *intersection;
	
	GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
	
	filter = GST_SLVIDEO(bsink);
	
	intersection = llgst_caps_intersect (filter->caps, caps);
	if (llgst_caps_is_empty (intersection))
	{
		// no overlap between our caps and requested caps
		return FALSE;
	}
	llgst_caps_unref(intersection);
	
	int width, height;
	gboolean ret;
	const GValue *fps;
	const GValue *par;
	structure = llgst_caps_get_structure (caps, 0);
	ret = llgst_structure_get_int (structure, "width", &width);
	ret = ret && llgst_structure_get_int (structure, "height", &height);
	fps = llgst_structure_get_value (structure, "framerate");
	ret = ret && (fps != NULL);
	par = llgst_structure_get_value (structure, "pixel-aspect-ratio");
	if (!ret)
		return FALSE;

	filter->width = width;
	filter->height = height;
	filter->fps_n = llgst_value_get_fraction_numerator(fps);
	filter->fps_d = llgst_value_get_fraction_denominator(fps);
	if (par)
	{
		filter->par_n = llgst_value_get_fraction_numerator(par);
		filter->par_d = llgst_value_get_fraction_denominator(par);
	}
	else
	{
		filter->par_n = 1;
		filter->par_d = 1;
	}
	GST_VIDEO_SINK_WIDTH(filter) = width;
	GST_VIDEO_SINK_HEIGHT(filter) = height;
	
	filter->format = SLV_PF_UNKNOWN;
	if (0 == strcmp(llgst_structure_get_name(structure),
			"video/x-raw-rgb"))
	{
		int red_mask;
		int green_mask;
		int blue_mask;
		llgst_structure_get_int(structure, "red_mask", &red_mask);
		llgst_structure_get_int(structure, "green_mask", &green_mask);
		llgst_structure_get_int(structure, "blue_mask", &blue_mask);
		if ((unsigned int)red_mask   == 0xFF000000 &&
		    (unsigned int)green_mask == 0x00FF0000 &&
		    (unsigned int)blue_mask  == 0x0000FF00)
		{
			filter->format = SLV_PF_RGBX;
			//fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n");
		} else if ((unsigned int)red_mask   == 0x0000FF00 &&
			   (unsigned int)green_mask == 0x00FF0000 &&
			   (unsigned int)blue_mask  == 0xFF000000)
		{
			filter->format = SLV_PF_BGRX;
			//fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n");
		}
	}
	
	return TRUE;
}
/* this function handles the link with other elements */
static gboolean
gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
    GstSLVideo *filter;
    GstStructure *structure;

    GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);

    filter = GST_SLVIDEO(bsink);

    int width, height;
    gboolean ret;
    const GValue *fps;
    const GValue *par;
    structure = llgst_caps_get_structure (caps, 0);
    ret = llgst_structure_get_int (structure, "width", &width);
    ret = ret && llgst_structure_get_int (structure, "height", &height);
    fps = llgst_structure_get_value (structure, "framerate");
    ret = ret && (fps != NULL);
    par = llgst_structure_get_value (structure, "pixel-aspect-ratio");
    if (!ret)
        return FALSE;

    INFOMSG("** filter caps set with width=%d, height=%d", width, height);

    GST_OBJECT_LOCK(filter);

    filter->width = width;
    filter->height = height;

    filter->fps_n = llgst_value_get_fraction_numerator(fps);
    filter->fps_d = llgst_value_get_fraction_denominator(fps);
    if (par)
    {
        filter->par_n = llgst_value_get_fraction_numerator(par);
        filter->par_d = llgst_value_get_fraction_denominator(par);
    }
    else
    {
        filter->par_n = 1;
        filter->par_d = 1;
    }
    GST_VIDEO_SINK_WIDTH(filter) = width;
    GST_VIDEO_SINK_HEIGHT(filter) = height;

    // crufty lump - we *always* accept *only* RGBX now.
    /*
    filter->format = SLV_PF_UNKNOWN;
    if (0 == strcmp(llgst_structure_get_name(structure),
    		"video/x-raw-rgb"))
    {
    	int red_mask;
    	int green_mask;
    	int blue_mask;
    	llgst_structure_get_int(structure, "red_mask", &red_mask);
    	llgst_structure_get_int(structure, "green_mask", &green_mask);
    	llgst_structure_get_int(structure, "blue_mask", &blue_mask);
    	if ((unsigned int)red_mask   == 0xFF000000 &&
    	    (unsigned int)green_mask == 0x00FF0000 &&
    	    (unsigned int)blue_mask  == 0x0000FF00)
    	{
    		filter->format = SLV_PF_RGBX;
    		//fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n");
    	} else if ((unsigned int)red_mask   == 0x0000FF00 &&
    		   (unsigned int)green_mask == 0x00FF0000 &&
    		   (unsigned int)blue_mask  == 0xFF000000)
    	{
    		filter->format = SLV_PF_BGRX;
    		//fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n");
    	}
    	}*/

    filter->format = SLV_PF_RGBX;

    GST_OBJECT_UNLOCK(filter);

    return TRUE;
}