mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-06 10:42:22 +00:00
video: Refactor convert_frame a bit and fix some minor memory leaks in error cases
This commit is contained in:
parent
168aceb3da
commit
b54c4b486a
1 changed files with 108 additions and 70 deletions
|
@ -108,40 +108,14 @@ fail:
|
||||||
return encoder;
|
return encoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static GstElement *
|
||||||
* gst_video_convert_frame:
|
build_convert_frame_pipeline (GstElement ** src_element,
|
||||||
* @buf: a #GstBuffer
|
GstElement ** sink_element, const GstCaps * from_caps,
|
||||||
* @to_caps: the #GstCaps to convert to
|
const GstCaps * to_caps, GError ** err)
|
||||||
* @timeout: the maximum amount of time allowed for the processing.
|
|
||||||
* @err: pointer to a #GError. Can be %NULL.
|
|
||||||
*
|
|
||||||
* Converts a raw video buffer into the specified output caps.
|
|
||||||
*
|
|
||||||
* The output caps can be any raw video formats or any image formats (jpeg, png, ...).
|
|
||||||
*
|
|
||||||
* The width, height and pixel-aspect-ratio can also be specified in the output caps.
|
|
||||||
*
|
|
||||||
* Returns: The converted #GstBuffer, or %NULL if an error happened (in which case @err
|
|
||||||
* will point to the #GError).
|
|
||||||
*/
|
|
||||||
GstBuffer *
|
|
||||||
gst_video_convert_frame (GstBuffer * buf, const GstCaps * to_caps,
|
|
||||||
GstClockTime timeout, GError ** err)
|
|
||||||
{
|
{
|
||||||
GstElement *src = NULL, *csp = NULL, *vscale = NULL, *sink = NULL, *encoder =
|
GstElement *src = NULL, *csp = NULL, *vscale = NULL;
|
||||||
NULL, *pipeline;
|
GstElement *sink = NULL, *encoder = NULL, *pipeline;
|
||||||
GstMessage *msg;
|
|
||||||
GstBuffer *result = NULL;
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GstBus *bus;
|
|
||||||
GstCaps *from_caps;
|
|
||||||
GstFlowReturn ret;
|
|
||||||
|
|
||||||
g_return_val_if_fail (buf != NULL, NULL);
|
|
||||||
g_return_val_if_fail (to_caps != NULL, NULL);
|
|
||||||
g_return_val_if_fail (GST_BUFFER_CAPS (buf) != NULL, NULL);
|
|
||||||
|
|
||||||
from_caps = GST_BUFFER_CAPS (buf);
|
|
||||||
|
|
||||||
/* videoscale is here to correct for the pixel-aspect-ratio for us */
|
/* videoscale is here to correct for the pixel-aspect-ratio for us */
|
||||||
GST_DEBUG ("creating elements");
|
GST_DEBUG ("creating elements");
|
||||||
|
@ -194,6 +168,104 @@ gst_video_convert_frame (GstBuffer * buf, const GstCaps * to_caps,
|
||||||
goto link_failed;
|
goto link_failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*src_element = src;
|
||||||
|
*sink_element = sink;
|
||||||
|
|
||||||
|
return pipeline;
|
||||||
|
/* ERRORS */
|
||||||
|
no_encoder:
|
||||||
|
{
|
||||||
|
gst_object_unref (pipeline);
|
||||||
|
|
||||||
|
GST_ERROR ("could not find an encoder for provided caps");
|
||||||
|
if (err)
|
||||||
|
*err = error;
|
||||||
|
else
|
||||||
|
g_error_free (error);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
no_elements:
|
||||||
|
{
|
||||||
|
if (src)
|
||||||
|
gst_object_unref (src);
|
||||||
|
if (csp)
|
||||||
|
gst_object_unref (csp);
|
||||||
|
if (vscale)
|
||||||
|
gst_object_unref (vscale);
|
||||||
|
if (sink)
|
||||||
|
gst_object_unref (sink);
|
||||||
|
GST_ERROR ("Could not convert video frame: %s", error->message);
|
||||||
|
if (err)
|
||||||
|
*err = error;
|
||||||
|
else
|
||||||
|
g_error_free (error);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
no_pipeline:
|
||||||
|
{
|
||||||
|
gst_object_unref (src);
|
||||||
|
gst_object_unref (csp);
|
||||||
|
gst_object_unref (vscale);
|
||||||
|
gst_object_unref (sink);
|
||||||
|
|
||||||
|
GST_ERROR ("Could not convert video frame: no pipeline (unknown error)");
|
||||||
|
if (err)
|
||||||
|
*err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
|
||||||
|
"Could not convert video frame: no pipeline (unknown error)");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
link_failed:
|
||||||
|
{
|
||||||
|
gst_object_unref (pipeline);
|
||||||
|
|
||||||
|
GST_ERROR ("Could not convert video frame: failed to link elements");
|
||||||
|
if (err)
|
||||||
|
*err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION,
|
||||||
|
"Could not convert video frame: failed to link elements");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_video_convert_frame:
|
||||||
|
* @buf: a #GstBuffer
|
||||||
|
* @to_caps: the #GstCaps to convert to
|
||||||
|
* @timeout: the maximum amount of time allowed for the processing.
|
||||||
|
* @err: pointer to a #GError. Can be %NULL.
|
||||||
|
*
|
||||||
|
* Converts a raw video buffer into the specified output caps.
|
||||||
|
*
|
||||||
|
* The output caps can be any raw video formats or any image formats (jpeg, png, ...).
|
||||||
|
*
|
||||||
|
* The width, height and pixel-aspect-ratio can also be specified in the output caps.
|
||||||
|
*
|
||||||
|
* Returns: The converted #GstBuffer, or %NULL if an error happened (in which case @err
|
||||||
|
* will point to the #GError).
|
||||||
|
*/
|
||||||
|
GstBuffer *
|
||||||
|
gst_video_convert_frame (GstBuffer * buf, const GstCaps * to_caps,
|
||||||
|
GstClockTime timeout, GError ** err)
|
||||||
|
{
|
||||||
|
GstMessage *msg;
|
||||||
|
GstBuffer *result = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
GstBus *bus;
|
||||||
|
GstCaps *from_caps;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
GstElement *pipeline, *src, *sink;
|
||||||
|
|
||||||
|
g_return_val_if_fail (buf != NULL, NULL);
|
||||||
|
g_return_val_if_fail (to_caps != NULL, NULL);
|
||||||
|
g_return_val_if_fail (GST_BUFFER_CAPS (buf) != NULL, NULL);
|
||||||
|
|
||||||
|
from_caps = GST_BUFFER_CAPS (buf);
|
||||||
|
|
||||||
|
pipeline =
|
||||||
|
build_convert_frame_pipeline (&src, &sink, from_caps, to_caps, &error);
|
||||||
|
if (!pipeline)
|
||||||
|
goto no_pipeline;
|
||||||
|
|
||||||
/* now set the pipeline to the paused state, after we push the buffer into
|
/* now set the pipeline to the paused state, after we push the buffer into
|
||||||
* appsrc, this should preroll the converted buffer in appsink */
|
* appsrc, this should preroll the converted buffer in appsink */
|
||||||
GST_DEBUG ("running conversion pipeline to caps %" GST_PTR_FORMAT, to_caps);
|
GST_DEBUG ("running conversion pipeline to caps %" GST_PTR_FORMAT, to_caps);
|
||||||
|
@ -258,47 +330,13 @@ gst_video_convert_frame (GstBuffer * buf, const GstCaps * to_caps,
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
no_encoder:
|
|
||||||
{
|
|
||||||
GST_ERROR ("could not find an encoder for provided caps");
|
|
||||||
if (err)
|
|
||||||
*err = error;
|
|
||||||
else
|
|
||||||
g_error_free (error);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
no_elements:
|
|
||||||
{
|
|
||||||
if (src)
|
|
||||||
gst_object_unref (src);
|
|
||||||
if (csp)
|
|
||||||
gst_object_unref (csp);
|
|
||||||
if (vscale)
|
|
||||||
gst_object_unref (vscale);
|
|
||||||
if (sink)
|
|
||||||
gst_object_unref (sink);
|
|
||||||
GST_ERROR ("Could not convert video frame: %s", error->message);
|
|
||||||
if (err)
|
|
||||||
*err = error;
|
|
||||||
else
|
|
||||||
g_error_free (error);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
no_pipeline:
|
no_pipeline:
|
||||||
{
|
{
|
||||||
GST_ERROR ("Could not convert video frame: no pipeline (unknown error)");
|
|
||||||
if (err)
|
if (err)
|
||||||
*err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED,
|
*err = error;
|
||||||
"Could not convert video frame: no pipeline (unknown error)");
|
else
|
||||||
return NULL;
|
g_error_free (error);
|
||||||
}
|
|
||||||
link_failed:
|
|
||||||
{
|
|
||||||
GST_ERROR ("Could not convert video frame: failed to link elements");
|
|
||||||
if (err)
|
|
||||||
*err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION,
|
|
||||||
"Could not convert video frame: failed to link elements");
|
|
||||||
gst_object_unref (pipeline);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue