summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2022-08-31 16:13:37 +0200
committerMauro Carvalho Chehab <mchehab@kernel.org>2022-09-24 09:19:42 +0200
commitae219872834a32da88408a92a4b4745c11f5a7ce (patch)
tree6b466579815aebc5e6018975724c46c9980ac88b /include
parentmedia: drivers: use video_device_pipeline_alloc_start() (diff)
downloadlinux-ae219872834a32da88408a92a4b4745c11f5a7ce.tar.xz
linux-ae219872834a32da88408a92a4b4745c11f5a7ce.zip
media: mc: entity: Rewrite media_pipeline_start()
[Note: the code is mostly from Laurent but the patch description is from Tomi] The media_pipeline_start() and media_pipeline_stop() functions use the media graph walk API to traverse the graph and validate the pipeline. The graph walk traverses the media graph following links between the entities. Also, while the pipeline can't change between the start and stop calls, the graph is walked again from scratch at stop time, or any time a driver needs to inspect the pipeline. With the upcoming multiplexed streams support we will need a bit more intelligent pipeline construction, as e.g. two independent streams may be passing through a single entity via separate pads in which case those pads should not be part of the same pipeline. This patch essentially rewrites the media_pipeline_start/stop so that a pipeline is defined as a set of pads instead of entities and the media graph traversal considers the pad interdependencies when choosing which links to follow. Currently all the entity's pads are considered as interdependent. This means that the behavior with all the current drivers stays the same, but in the future we can define a more fine-grained pipeline construction. Additionally the media pipeline's pads are cached at media_pipeline_start() time, and re-used at media_pipeline_stop() which avoid the need to re-walk the whole graph as the previous implementation did. Also, caching pads in the pipeline can serve in the future as the foundation to provide a better API than the media graph walk to drivers to iterate over pads and entities in the pipeline. Note that the old media_pipeline_start/stop used the media graph walk API. The new version does not use the media graph walk API, but instead a new implementation. There are two reasons for not changing the graph walk: it proved to be rather difficult to change the graph walk to have the features implemented in this patch, and second, this keeps the backward compatibility of the graph walk as there are users of the graph walk API The long term plan is that all the existing code would be converted to use the new cached pipeline, thus allowing us to remove the graph walk. Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/media/media-entity.h71
1 files changed, 65 insertions, 6 deletions
diff --git a/include/media/media-entity.h b/include/media/media-entity.h
index a77933afaa48..00990b20b3d5 100644
--- a/include/media/media-entity.h
+++ b/include/media/media-entity.h
@@ -101,13 +101,33 @@ struct media_graph {
* struct media_pipeline - Media pipeline related information
*
* @allocated: Media pipeline allocated and freed by the framework
+ * @mdev: The media device the pipeline is part of
+ * @pads: List of media_pipeline_pad
* @start_count: Media pipeline start - stop count
- * @graph: Media graph walk during pipeline start / stop
*/
struct media_pipeline {
bool allocated;
+ struct media_device *mdev;
+ struct list_head pads;
int start_count;
- struct media_graph graph;
+};
+
+/**
+ * struct media_pipeline_pad - A pad part of a media pipeline
+ *
+ * @list: Entry in the media_pad pads list
+ * @pipe: The media_pipeline that the pad is part of
+ * @pad: The media pad
+ *
+ * This structure associate a pad with a media pipeline. Instances of
+ * media_pipeline_pad are created by media_pipeline_start() when it builds the
+ * pipeline, and stored in the &media_pad.pads list. media_pipeline_stop()
+ * removes the entries from the list and deletes them.
+ */
+struct media_pipeline_pad {
+ struct list_head list;
+ struct media_pipeline *pipe;
+ struct media_pad *pad;
};
/**
@@ -189,6 +209,8 @@ enum media_pad_signal_type {
* @flags: Pad flags, as defined in
* :ref:`include/uapi/linux/media.h <media_header>`
* (seek for ``MEDIA_PAD_FL_*``)
+ * @pipe: Pipeline this pad belongs to. Use media_entity_pipeline() to
+ * access this field.
*/
struct media_pad {
struct media_gobj graph_obj; /* must be first field in struct */
@@ -196,6 +218,12 @@ struct media_pad {
u16 index;
enum media_pad_signal_type sig_type;
unsigned long flags;
+
+ /*
+ * The fields below are private, and should only be accessed via
+ * appropriate functions.
+ */
+ struct media_pipeline *pipe;
};
/**
@@ -272,7 +300,6 @@ enum media_entity_type {
* @links: List of data links.
* @ops: Entity operations.
* @use_count: Use count for the entity.
- * @pipe: Pipeline this entity belongs to.
* @info: Union with devnode information. Kept just for backward
* compatibility.
* @info.dev: Contains device major and minor info.
@@ -308,8 +335,6 @@ struct media_entity {
int use_count;
- struct media_pipeline *pipe;
-
union {
struct {
u32 major;
@@ -939,6 +964,18 @@ media_entity_remote_source_pad_unique(const struct media_entity *entity)
}
/**
+ * media_pad_is_streaming - Test if a pad is part of a streaming pipeline
+ * @pad: The pad
+ *
+ * Return: True if the pad is part of a pipeline started with the
+ * media_pipeline_start() function, false otherwise.
+ */
+static inline bool media_pad_is_streaming(const struct media_pad *pad)
+{
+ return pad->pipe;
+}
+
+/**
* media_entity_is_streaming - Test if an entity is part of a streaming pipeline
* @entity: The entity
*
@@ -947,13 +984,22 @@ media_entity_remote_source_pad_unique(const struct media_entity *entity)
*/
static inline bool media_entity_is_streaming(const struct media_entity *entity)
{
- return entity->pipe;
+ struct media_pad *pad;
+
+ media_entity_for_each_pad(entity, pad) {
+ if (media_pad_is_streaming(pad))
+ return true;
+ }
+
+ return false;
}
/**
* media_entity_pipeline - Get the media pipeline an entity is part of
* @entity: The entity
*
+ * DEPRECATED: use media_pad_pipeline() instead.
+ *
* This function returns the media pipeline that an entity has been associated
* with when constructing the pipeline with media_pipeline_start(). The pointer
* remains valid until media_pipeline_stop() is called.
@@ -969,6 +1015,19 @@ static inline bool media_entity_is_streaming(const struct media_entity *entity)
struct media_pipeline *media_entity_pipeline(struct media_entity *entity);
/**
+ * media_pad_pipeline - Get the media pipeline a pad is part of
+ * @pad: The pad
+ *
+ * This function returns the media pipeline that a pad has been associated
+ * with when constructing the pipeline with media_pipeline_start(). The pointer
+ * remains valid until media_pipeline_stop() is called.
+ *
+ * Return: The media_pipeline the pad is part of, or NULL if the pad is
+ * not part of any pipeline.
+ */
+struct media_pipeline *media_pad_pipeline(struct media_pad *pad);
+
+/**
* media_entity_get_fwnode_pad - Get pad number from fwnode
*
* @entity: The entity