static void gst_slvideo_finalize (GObject * object) { GstSLVideo *slvideo; slvideo = GST_SLVIDEO (object); if (slvideo->caps) { llgst_caps_unref(slvideo->caps); } G_OBJECT_CLASS(parent_class)->finalize (object); }
/* 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; }
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; }