mutter/cogl-gst/cogl-gst-video-sink.h
Robert Bragg 849f691969 cogl-gst: add cogl_gst_video_sink_get_natural_size() api
This adds api for querying a "natural" width and height for a video
which has the correct aspect ratio for displaying on square, 1:1 pixels.

The natural size is the minimum size where downscaling is not required.

Reviewed-by: Neil Roberts <neil@linux.intel.com>
2014-03-20 17:34:04 +00:00

528 lines
18 KiB
C

/*
* Cogl
*
* A Low Level GPU Graphics and Utilities API
*
* Copyright (C) 2007, 2008 OpenedHand
* Copyright (C) 2009, 2010, 2013 Intel Corporation
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#ifndef __COGL_GST_VIDEO_SINK_H__
#define __COGL_GST_VIDEO_SINK_H__
#include <glib-object.h>
#include <gst/base/gstbasesink.h>
/* We just need the public Cogl api for cogl-gst but we first need to
* undef COGL_COMPILATION to avoid getting an error that normally
* checks cogl.h isn't used internally. */
#ifdef COGL_COMPILATION
#undef COGL_COMPILATION
#endif
#include <cogl/cogl.h>
#include <cogl/cogl.h>
/**
* SECTION:cogl-gst-video-sink
* @short_description: A video sink for integrating a GStreamer
* pipeline with a Cogl pipeline.
*
* #CoglGstVideoSink is a subclass of #GstBaseSink which can be used to
* create a #CoglPipeline for rendering the frames of the video.
*
* To create a basic video player, an application can create a
* #GstPipeline as normal using gst_pipeline_new() and set the
* sink on it to one created with cogl_gst_video_sink_new(). The
* application can then listen for the #CoglGstVideoSink::new-frame
* signal which will be emitted whenever there are new textures ready
* for rendering. For simple rendering, the application can just call
* cogl_gst_video_sink_get_pipeline() in the signal handler and use
* the returned pipeline to paint the new frame.
*
* An application is also free to do more advanced rendering by
* customizing the pipeline. In that case it should listen for the
* #CoglGstVideoSink::pipeline-ready signal which will be emitted as
* soon as the sink has determined enough information about the video
* to know how it should be rendered. In the handler for this signal,
* the application can either make modifications to a copy of the
* pipeline returned by cogl_gst_video_sink_get_pipeline() or it can
* create its own pipeline from scratch and ask the sink to configure
* it with cogl_gst_video_sink_setup_pipeline(). If a custom pipeline
* is created using one of these methods then the application should
* call cogl_gst_video_sink_attach_frame() on the pipeline before
* rendering in order to update the textures on the pipeline's layers.
*
* If the %COGL_FEATURE_ID_GLSL feature is available then the pipeline
* used by the sink will have a shader snippet with a function in it
* called cogl_gst_sample_video0 which takes a single vec2 argument.
* This can be used by custom snippets set the by the application to
* sample from the video. The vec2 argument represents the normalised
* coordinates within the video. The function returns a vec4
* containing a pre-multiplied RGBA color of the pixel within the
* video.
*
* Since: 1.16
*/
G_BEGIN_DECLS
#define COGL_GST_TYPE_VIDEO_SINK cogl_gst_video_sink_get_type()
#define COGL_GST_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
COGL_GST_TYPE_VIDEO_SINK, CoglGstVideoSink))
#define COGL_GST_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
COGL_GST_TYPE_VIDEO_SINK, CoglGstVideoSinkClass))
#define COGL_GST_IS_VIDEO_SINK(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
COGL_GST_TYPE_VIDEO_SINK))
#define COGL_GST_IS_VIDEO_SINK_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
COGL_GST_TYPE_VIDEO_SINK))
#define COGL_GST_VIDEO_SINK_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
COGL_GST_TYPE_VIDEO_SINK, CoglGstVideoSinkClass))
typedef struct _CoglGstVideoSink CoglGstVideoSink;
typedef struct _CoglGstVideoSinkClass CoglGstVideoSinkClass;
typedef struct _CoglGstVideoSinkPrivate CoglGstVideoSinkPrivate;
/**
* CoglGstVideoSink:
*
* The #CoglGstVideoSink structure contains only private data and
* should be accessed using the provided API.
*
* Since: 1.16
*/
struct _CoglGstVideoSink
{
/*< private >*/
GstBaseSink parent;
CoglGstVideoSinkPrivate *priv;
};
/**
* CoglGstVideoSinkClass:
* @new_frame: handler for the #CoglGstVideoSink::new-frame signal
* @pipeline_ready: handler for the #CoglGstVideoSink::pipeline-ready signal
*
* Since: 1.16
*/
/**
* CoglGstVideoSink::new-frame:
* @sink: the #CoglGstVideoSink
*
* The sink will emit this signal whenever there are new textures
* available for a new frame of the video. After this signal is
* emitted, an application can call cogl_gst_video_sink_get_pipeline()
* to get a pipeline suitable for rendering the frame. If the
* application is using a custom pipeline it can alternatively call
* cogl_gst_video_sink_attach_frame() to attach the textures.
*
* Since: 1.16
*/
/**
* CoglGstVideoSink::pipeline-ready:
* @sink: the #CoglGstVideoSink
*
* The sink will emit this signal as soon as it has gathered enough
* information from the video to configure a pipeline. If the
* application wants to do some customized rendering, it can setup its
* pipeline after this signal is emitted. The application's pipeline
* will typically either be a copy of the one returned by
* cogl_gst_video_sink_get_pipeline() or it can be a completely custom
* pipeline which is setup using cogl_gst_video_sink_setup_pipeline().
*
* Note that it is an error to call either of those functions before
* this signal is emitted. The #CoglGstVideoSink::new-frame signal
* will only be emitted after the pipeline is ready so the application
* could also create its pipeline in the handler for that.
*
* Since: 1.16
*/
struct _CoglGstVideoSinkClass
{
/*< private >*/
GstBaseSinkClass parent_class;
/*< public >*/
void (* new_frame) (CoglGstVideoSink *sink);
void (* pipeline_ready) (CoglGstVideoSink *sink);
/*< private >*/
void *_padding_dummy[8];
};
GType
cogl_gst_video_sink_get_type (void) G_GNUC_CONST;
/**
* cogl_gst_video_sink_new:
* @ctx: The #CoglContext
*
* Creates a new #CoglGstVideoSink which will create resources for use
* with the given context.
*
* Return value: (transfer full): a new #CoglGstVideoSink
* Since: 1.16
*/
CoglGstVideoSink *
cogl_gst_video_sink_new (CoglContext *ctx);
/**
* cogl_gst_video_sink_is_ready:
* @sink: The #CoglGstVideoSink
*
* Returns whether the pipeline is ready and so
* cogl_gst_video_sink_get_pipeline() and
* cogl_gst_video_sink_setup_pipeline() can be called without causing error.
*
* Note: Normally an application will wait until the
* #CoglGstVideoSink::pipeline-ready signal is emitted instead of
* polling the ready status with this api, but sometimes when a sink
* is passed between components that didn't have an opportunity to
* connect a signal handler this can be useful.
*
* Return value: %TRUE if the sink is ready, else %FALSE
* Since: 1.16
*/
CoglBool
cogl_gst_video_sink_is_ready (CoglGstVideoSink *sink);
/**
* cogl_gst_video_sink_get_pipeline:
* @vt: The #CoglGstVideoSink
*
* Returns a pipeline suitable for rendering the current frame of the
* given video sink. The pipeline will already have the textures for
* the frame attached. For simple rendering, an application will
* typically call this function immediately before it paints the
* video. It can then just paint a rectangle using the returned
* pipeline.
*
* An application is free to make a copy of this
* pipeline and modify it for custom rendering.
*
* Note: it is considered an error to call this function before the
* #CoglGstVideoSink::pipeline-ready signal is emitted.
*
* Return value: (transfer none): the pipeline for rendering the
* current frame
* Since: 1.16
*/
CoglPipeline *
cogl_gst_video_sink_get_pipeline (CoglGstVideoSink *vt);
/**
* cogl_gst_video_sink_set_context:
* @vt: The #CoglGstVideoSink
* @ctx: The #CoglContext for the sink to use
*
* Sets the #CoglContext that the video sink should use for creating
* any resources. This function would normally only be used if the
* sink was constructed via gst_element_factory_make() instead of
* cogl_gst_video_sink_new().
*
* Since: 1.16
*/
void
cogl_gst_video_sink_set_context (CoglGstVideoSink *vt,
CoglContext *ctx);
/**
* cogl_gst_video_sink_get_free_layer:
* @sink: The #CoglGstVideoSink
*
* This can be used when doing specialised rendering of the video by
* customizing the pipeline. #CoglGstVideoSink may use up to three
* private layers on the pipeline in order to attach the textures of
* the video frame. This function will return the index of the next
* available unused layer after the sink's internal layers. This can
* be used by the application to add additional layers, for example to
* blend in another color in the fragment processing.
*
* Return value: the index of the next available layer after the
* sink's internal layers.
* Since: 1.16
*/
int
cogl_gst_video_sink_get_free_layer (CoglGstVideoSink *sink);
/**
* cogl_gst_video_sink_attach_frame:
* @sink: The #CoglGstVideoSink
* @pln: A #CoglPipeline
*
* Updates the given pipeline with the textures for the current frame.
* This can be used if the application wants to customize the
* rendering using its own pipeline. Typically this would be called in
* response to the #CoglGstVideoSink::new-frame signal which is
* emitted whenever the new textures are available. The application
* would then make a copy of its template pipeline and call this to
* set the textures.
*
* Since: 1.16
*/
void
cogl_gst_video_sink_attach_frame (CoglGstVideoSink *sink,
CoglPipeline *pln);
/**
* cogl_gst_video_sink_set_first_layer:
* @sink: The #CoglGstVideoSink
* @first_layer: The new first layer
*
* Sets the index of the first layer that the sink will use for its
* rendering. This is useful if the application wants to have custom
* layers that appear before the layers added by the sink. In that
* case by default the sink's layers will be modulated with the result
* of the application's layers that come before @first_layer.
*
* Note that if this function is called then the name of the function
* to call in the shader snippets to sample the video will also
* change. For example, if @first_layer is three then the function
* will be cogl_gst_sample_video3.
*
* Since: 1.16
*/
void
cogl_gst_video_sink_set_first_layer (CoglGstVideoSink *sink,
int first_layer);
/**
* cogl_gst_video_sink_set_default_sample:
* @sink: The #CoglGstVideoSink
* @default_sample: Whether to add the default sampling
*
* By default the pipeline generated by
* cogl_gst_video_sink_setup_pipeline() and
* cogl_gst_video_sink_get_pipeline() will have a layer with a shader
* snippet that automatically samples the video. If the application
* wants to sample the video in a completely custom way using its own
* shader snippet it can set @default_sample to %FALSE to avoid this
* default snippet being added. In that case the application's snippet
* can call cogl_gst_sample_video0 to sample the texture itself.
*
* Since: 1.16
*/
void
cogl_gst_video_sink_set_default_sample (CoglGstVideoSink *sink,
CoglBool default_sample);
/**
* cogl_gst_video_sink_setup_pipeline:
* @sink: The #CoglGstVideoSink
* @pipeline: A #CoglPipeline
*
* Configures the given pipeline so that will be able to render the
* video for the @sink. This should only be used if the application
* wants to perform some custom rendering using its own pipeline.
* Typically an application will call this in response to the
* #CoglGstVideoSink::pipeline-ready signal.
*
* Note: it is considered an error to call this function before the
* #CoglGstVideoSink::pipeline-ready signal is emitted.
*
* Since: 1.16
*/
void
cogl_gst_video_sink_setup_pipeline (CoglGstVideoSink *sink,
CoglPipeline *pipeline);
/**
* cogl_gst_video_sink_get_aspect:
* @sink: A #CoglGstVideoSink
*
* Returns a width-for-height aspect ratio that lets you calculate a
* suitable width for displaying your video based on a given height by
* multiplying your chosen height by the returned aspect ratio.
*
* This aspect ratio is calculated based on the underlying size of the
* video buffers and the current pixel-aspect-ratio.
*
* Return value: a width-for-height aspect ratio
*
* Since: 1.16
* Stability: unstable
*/
float
cogl_gst_video_sink_get_aspect (CoglGstVideoSink *sink);
/**
* cogl_gst_video_sink_get_width_for_height:
* @sink: A #CoglGstVideoSink
* @height: A specific output @height
*
* Calculates a suitable output width for a specific output @height
* that will maintain the video's aspect ratio.
*
* Return value: An output width for the given output @height.
*
* Since: 1.16
* Stability: unstable
*/
float
cogl_gst_video_sink_get_width_for_height (CoglGstVideoSink *sink,
float height);
/**
* cogl_gst_video_sink_get_height_for_width:
* @sink: A #CoglGstVideoSink
* @width: A specific output @width
*
* Calculates a suitable output height for a specific output @width
* that will maintain the video's aspect ratio.
*
* Return value: An output height for the given output @width.
*
* Since: 1.16
* Stability: unstable
*/
float
cogl_gst_video_sink_get_height_for_width (CoglGstVideoSink *sink,
float width);
/**
* cogl_gst_video_sink_get_natural_size:
* @sink: A #CoglGstVideoSink
* @width: (out): return location for the video's natural width
* @height: (out): return location for the video's natural height
*
* Considering the real resolution of the video as well as the aspect
* ratio of pixel data that may need to be stretched when being displayed;
* this function calculates what the natural size of the underlying
* video source is.
*
* The natural size has the correct aspect ratio for displaying the
* video and is the minimum size where downscaling is not required.
*
* <note>This natural size is calculated assuming that the video will
* be displayed on square pixels.</note>
*
* Since: 1.18
* Stability: unstable
*/
void
cogl_gst_video_sink_get_natural_size (CoglGstVideoSink *sink,
float *width,
float *height);
/**
* cogl_gst_video_sink_get_natural_width:
* @sink: A #CoglGstVideoSink
*
* Considering the real resolution of the video as well as the aspect
* ratio of pixel data that may need to be stretched when being displayed;
* this function calculates what the natural size of the underlying
* video source is, and returns its width.
*
* The natural size has the correct aspect ratio for displaying the
* video and is the minimum size where downscaling is not required.
*
* <note>This natural size is calculated assuming that the video will
* be displayed on square pixels.</note>
*
* Return value: The video's natural width
*
* Since: 1.18
* Stability: unstable
*/
float
cogl_gst_video_sink_get_natural_width (CoglGstVideoSink *sink);
/**
* cogl_gst_video_sink_get_natural_height:
* @sink: A #CoglGstVideoSink
*
* Considering the real resolution of the video as well as the aspect
* ratio of pixel data that may need to be stretched when being displayed;
* this function calculates what the natural size of the underlying
* video source is, and returns its height.
*
* The natural size has the correct aspect ratio for displaying the
* video and is the minimum size where downscaling is not required.
*
* <note>This natural size is calculated assuming that the video will
* be displayed on square pixels.</note>
*
* Return value: The video's natural height
*
* Since: 1.18
* Stability: unstable
*/
float
cogl_gst_video_sink_get_natural_height (CoglGstVideoSink *sink);
/**
* CoglGstRectangle:
* @x: The X coordinate of the top left of the rectangle
* @y: The Y coordinate of the top left of the rectangle
* @width: The width of the rectangle
* @height: The height of the rectangle
*
* Describes a rectangle that can be used for video output.
*/
typedef struct _CoglGstRectangle
{
float x;
float y;
float width;
float height;
} CoglGstRectangle;
/**
* cogl_gst_video_sink_fit_size:
* @sink: A #CoglGstVideoSink
* @available: (in): The space available for video output
* @output: (inout): The return location for the calculated output position
*
* Calculates a suitable @output rectangle that can fit inside the
* @available space while maintaining the aspect ratio of the current
* video.
*
* Applications would typically use this api for "letterboxing" by
* using this api to position a video inside a fixed screen space and
* filling the remaining space with black borders.
*
* Since: 1.16
* Stability: unstable
*/
void
cogl_gst_video_sink_fit_size (CoglGstVideoSink *sink,
const CoglGstRectangle *available,
CoglGstRectangle *output);
G_END_DECLS
#endif