mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 08:41:07 +00:00
videoencoder: Add decide_allocation vfunc and functions to allocate buffers with the information from the allocation query
This commit is contained in:
parent
83c7eace98
commit
cce1078fe9
2 changed files with 172 additions and 0 deletions
|
@ -161,6 +161,9 @@ struct _GstVideoEncoderPrivate
|
||||||
|
|
||||||
gint64 bytes;
|
gint64 bytes;
|
||||||
gint64 time;
|
gint64 time;
|
||||||
|
|
||||||
|
GstAllocator *allocator;
|
||||||
|
GstAllocationParams params;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _ForcedKeyUnitEvent ForcedKeyUnitEvent;
|
typedef struct _ForcedKeyUnitEvent ForcedKeyUnitEvent;
|
||||||
|
@ -222,6 +225,8 @@ static gboolean gst_video_encoder_sink_event_default (GstVideoEncoder * encoder,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
static gboolean gst_video_encoder_src_event_default (GstVideoEncoder * encoder,
|
static gboolean gst_video_encoder_src_event_default (GstVideoEncoder * encoder,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
|
static gboolean gst_video_encoder_decide_allocation_default (GstVideoEncoder *
|
||||||
|
encoder, GstQuery * query);
|
||||||
static gboolean gst_video_encoder_propose_allocation_default (GstVideoEncoder *
|
static gboolean gst_video_encoder_propose_allocation_default (GstVideoEncoder *
|
||||||
encoder, GstQuery * query);
|
encoder, GstQuery * query);
|
||||||
|
|
||||||
|
@ -284,6 +289,7 @@ gst_video_encoder_class_init (GstVideoEncoderClass * klass)
|
||||||
klass->sink_event = gst_video_encoder_sink_event_default;
|
klass->sink_event = gst_video_encoder_sink_event_default;
|
||||||
klass->src_event = gst_video_encoder_src_event_default;
|
klass->src_event = gst_video_encoder_src_event_default;
|
||||||
klass->propose_allocation = gst_video_encoder_propose_allocation_default;
|
klass->propose_allocation = gst_video_encoder_propose_allocation_default;
|
||||||
|
klass->decide_allocation = gst_video_encoder_decide_allocation_default;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -704,6 +710,36 @@ gst_video_encoder_sink_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
|
||||||
return caps;
|
return caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_video_encoder_decide_allocation_default (GstVideoEncoder * encoder,
|
||||||
|
GstQuery * query)
|
||||||
|
{
|
||||||
|
GstAllocator *allocator = NULL;
|
||||||
|
GstAllocationParams params;
|
||||||
|
gboolean update_allocator;
|
||||||
|
|
||||||
|
/* we got configuration from our peer or the decide_allocation method,
|
||||||
|
* parse them */
|
||||||
|
if (gst_query_get_n_allocation_params (query) > 0) {
|
||||||
|
/* try the allocator */
|
||||||
|
gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
|
||||||
|
update_allocator = TRUE;
|
||||||
|
} else {
|
||||||
|
allocator = NULL;
|
||||||
|
gst_allocation_params_init (¶ms);
|
||||||
|
update_allocator = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_allocator)
|
||||||
|
gst_query_set_nth_allocation_param (query, 0, allocator, ¶ms);
|
||||||
|
else
|
||||||
|
gst_query_add_allocation_param (query, allocator, ¶ms);
|
||||||
|
if (allocator)
|
||||||
|
gst_object_unref (allocator);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_video_encoder_propose_allocation_default (GstVideoEncoder * encoder,
|
gst_video_encoder_propose_allocation_default (GstVideoEncoder * encoder,
|
||||||
GstQuery * query)
|
GstQuery * query)
|
||||||
|
@ -761,6 +797,11 @@ gst_video_encoder_finalize (GObject * object)
|
||||||
}
|
}
|
||||||
g_rec_mutex_clear (&encoder->stream_lock);
|
g_rec_mutex_clear (&encoder->stream_lock);
|
||||||
|
|
||||||
|
if (encoder->priv->allocator) {
|
||||||
|
gst_object_unref (encoder->priv->allocator);
|
||||||
|
encoder->priv->allocator = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1279,9 +1320,13 @@ close_failed:
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_video_encoder_set_src_caps (GstVideoEncoder * encoder)
|
gst_video_encoder_set_src_caps (GstVideoEncoder * encoder)
|
||||||
{
|
{
|
||||||
|
GstVideoEncoderClass *klass = GST_VIDEO_ENCODER_GET_CLASS (encoder);
|
||||||
|
GstAllocator *allocator;
|
||||||
|
GstAllocationParams params;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
GstVideoCodecState *state = encoder->priv->output_state;
|
GstVideoCodecState *state = encoder->priv->output_state;
|
||||||
GstVideoInfo *info = &state->info;
|
GstVideoInfo *info = &state->info;
|
||||||
|
GstQuery *query;
|
||||||
|
|
||||||
g_return_val_if_fail (state->caps != NULL, FALSE);
|
g_return_val_if_fail (state->caps != NULL, FALSE);
|
||||||
|
|
||||||
|
@ -1309,8 +1354,122 @@ gst_video_encoder_set_src_caps (GstVideoEncoder * encoder)
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gst_pad_set_caps (encoder->srcpad, state->caps);
|
ret = gst_pad_set_caps (encoder->srcpad, state->caps);
|
||||||
|
if (!ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
query = gst_query_new_allocation (state->caps, TRUE);
|
||||||
|
if (!gst_pad_peer_query (encoder->srcpad, query)) {
|
||||||
|
GST_DEBUG_OBJECT (encoder, "didn't get downstream ALLOCATION hints");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (klass->decide_allocation != NULL);
|
||||||
|
ret = klass->decide_allocation (encoder, query);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (encoder, "ALLOCATION (%d) params: %" GST_PTR_FORMAT, ret,
|
||||||
|
query);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
goto no_decide_allocation;
|
||||||
|
|
||||||
|
/* we got configuration from our peer or the decide_allocation method,
|
||||||
|
* parse them */
|
||||||
|
if (gst_query_get_n_allocation_params (query) > 0) {
|
||||||
|
gst_query_parse_nth_allocation_param (query, 0, &allocator, ¶ms);
|
||||||
|
} else {
|
||||||
|
allocator = NULL;
|
||||||
|
gst_allocation_params_init (¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder->priv->allocator)
|
||||||
|
gst_object_unref (encoder->priv->allocator);
|
||||||
|
encoder->priv->allocator = allocator;
|
||||||
|
encoder->priv->params = params;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (query)
|
||||||
|
gst_query_unref (query);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* Errors */
|
||||||
|
no_decide_allocation:
|
||||||
|
{
|
||||||
|
GST_WARNING_OBJECT (encoder, "Subclass failed to decide allocation");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_video_encoder_alloc_output_buffer:
|
||||||
|
* @encoder: a #GstVideoEncoder
|
||||||
|
* @size: size of the buffer
|
||||||
|
*
|
||||||
|
* Helper function that allocates a buffer to hold an encoded video frame
|
||||||
|
* for @encoder's current #GstVideoCodecState.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): allocated buffer
|
||||||
|
*/
|
||||||
|
GstBuffer *
|
||||||
|
gst_video_encoder_alloc_output_buffer (GstVideoEncoder * encoder, gsize size)
|
||||||
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
|
|
||||||
|
g_return_val_if_fail (size > 0, NULL);
|
||||||
|
|
||||||
|
GST_DEBUG ("alloc src buffer");
|
||||||
|
|
||||||
|
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
|
||||||
|
if (G_UNLIKELY (encoder->priv->output_state_changed
|
||||||
|
|| (encoder->priv->output_state
|
||||||
|
&& gst_pad_check_reconfigure (encoder->srcpad))))
|
||||||
|
gst_video_encoder_set_src_caps (encoder);
|
||||||
|
|
||||||
|
buffer =
|
||||||
|
gst_buffer_new_allocate (encoder->priv->allocator, size,
|
||||||
|
&encoder->priv->params);
|
||||||
|
|
||||||
|
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_video_encoder_alloc_output_frame:
|
||||||
|
* @encoder: a #GstVideoEncoder
|
||||||
|
* @frame: a #GstVideoCodecFrame
|
||||||
|
* @size: size of the buffer
|
||||||
|
*
|
||||||
|
* Helper function that allocates a buffer to hold an encoded video frame for @encoder's
|
||||||
|
* current #GstVideoCodecState. Subclass should already have configured video
|
||||||
|
* state and set src pad caps.
|
||||||
|
*
|
||||||
|
* The buffer allocated here is owned by the frame and you should only
|
||||||
|
* keep references to the frame, not the buffer.
|
||||||
|
*
|
||||||
|
* Returns: %GST_FLOW_OK if an output buffer could be allocated
|
||||||
|
*/
|
||||||
|
GstFlowReturn
|
||||||
|
gst_video_encoder_alloc_output_frame (GstVideoEncoder *
|
||||||
|
encoder, GstVideoCodecFrame * frame, gsize size)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (frame->output_buffer == NULL, GST_FLOW_ERROR);
|
||||||
|
g_return_val_if_fail (size > 0, GST_FLOW_ERROR);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (encoder->priv->output_state_changed
|
||||||
|
|| (encoder->priv->output_state
|
||||||
|
&& gst_pad_check_reconfigure (encoder->srcpad))))
|
||||||
|
gst_video_encoder_set_src_caps (encoder);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (encoder, "alloc buffer size %d", size);
|
||||||
|
GST_VIDEO_ENCODER_STREAM_LOCK (encoder);
|
||||||
|
|
||||||
|
frame->output_buffer =
|
||||||
|
gst_buffer_new_allocate (encoder->priv->allocator, size,
|
||||||
|
&encoder->priv->params);
|
||||||
|
|
||||||
|
GST_VIDEO_ENCODER_STREAM_UNLOCK (encoder);
|
||||||
|
|
||||||
|
return frame->output_buffer ? GST_FLOW_OK : GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -191,6 +191,10 @@ struct _GstVideoEncoder
|
||||||
* Event handler on the source pad. This function should return
|
* Event handler on the source pad. This function should return
|
||||||
* TRUE if the event was handled and should be discarded
|
* TRUE if the event was handled and should be discarded
|
||||||
* (i.e. not unref'ed).
|
* (i.e. not unref'ed).
|
||||||
|
* @decide_allocation: Optional.
|
||||||
|
* Setup the allocation parameters for allocating output
|
||||||
|
* buffers. The passed in query contains the result of the
|
||||||
|
* downstream allocation query.
|
||||||
* @propose_allocation: Optional.
|
* @propose_allocation: Optional.
|
||||||
* Propose buffer allocation parameters for upstream elements.
|
* Propose buffer allocation parameters for upstream elements.
|
||||||
*
|
*
|
||||||
|
@ -236,6 +240,8 @@ struct _GstVideoEncoderClass
|
||||||
gboolean (*src_event) (GstVideoEncoder *encoder,
|
gboolean (*src_event) (GstVideoEncoder *encoder,
|
||||||
GstEvent *event);
|
GstEvent *event);
|
||||||
|
|
||||||
|
gboolean (*decide_allocation) (GstVideoEncoder *encoder, GstQuery *query);
|
||||||
|
|
||||||
gboolean (*propose_allocation) (GstVideoEncoder * encoder,
|
gboolean (*propose_allocation) (GstVideoEncoder * encoder,
|
||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
|
|
||||||
|
@ -256,6 +262,13 @@ GstVideoCodecFrame* gst_video_encoder_get_frame (GstVideoEncoder *encode
|
||||||
int frame_number);
|
int frame_number);
|
||||||
GstVideoCodecFrame* gst_video_encoder_get_oldest_frame (GstVideoEncoder *encoder);
|
GstVideoCodecFrame* gst_video_encoder_get_oldest_frame (GstVideoEncoder *encoder);
|
||||||
|
|
||||||
|
GstBuffer * gst_video_encoder_alloc_output_buffer (GstVideoEncoder * decoder,
|
||||||
|
gsize size);
|
||||||
|
|
||||||
|
GstFlowReturn gst_video_encoder_alloc_output_frame (GstVideoEncoder *decoder,
|
||||||
|
GstVideoCodecFrame *frame,
|
||||||
|
gsize size);
|
||||||
|
|
||||||
GstFlowReturn gst_video_encoder_finish_frame (GstVideoEncoder *encoder,
|
GstFlowReturn gst_video_encoder_finish_frame (GstVideoEncoder *encoder,
|
||||||
GstVideoCodecFrame *frame);
|
GstVideoCodecFrame *frame);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue