[Pkg-gstreamer-commits] [gstreamer-vaapi] 98/176: vaapiencode: fix negotiation process of output caps.
Vincent Cheng
vcheng at moszumanska.debian.org
Tue Jun 3 08:09:31 UTC 2014
This is an automated email from the git hooks/post-receive script.
vcheng pushed a commit to branch upstream
in repository gstreamer-vaapi.
commit 449ac54348e8816a927b56a285e3b277272226ac
Author: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
Date: Thu Jan 9 18:10:35 2014 +0100
vaapiencode: fix negotiation process of output caps.
The specified caps in gst_video_encoder_set_output_state() function
arguments should not contain any resolution, pixel-aspect-ratio,
framerate, codec-data et al. Those rather should be set through the
returned GstVideoCodecState. This means that output caps creation
could be delayed until before gst_video_encoder_finish_frame() is
called.
This greatly simplifies the GstVideoEncoder::set_format() callback
by the way.
---
gst/vaapi/gstvaapiencode.c | 160 +++++++++++++++++----------------------
gst/vaapi/gstvaapiencode.h | 6 +-
gst/vaapi/gstvaapiencode_h264.c | 50 ++++++++++--
gst/vaapi/gstvaapiencode_h264.h | 2 +
gst/vaapi/gstvaapiencode_mpeg2.c | 19 ++++-
5 files changed, 135 insertions(+), 102 deletions(-)
diff --git a/gst/vaapi/gstvaapiencode.c b/gst/vaapi/gstvaapiencode.c
index f5b0606..fdb18ce 100644
--- a/gst/vaapi/gstvaapiencode.c
+++ b/gst/vaapi/gstvaapiencode.c
@@ -36,7 +36,6 @@
#define GST_VAAPI_ENCODE_FLOW_TIMEOUT GST_FLOW_CUSTOM_SUCCESS
#define GST_VAAPI_ENCODE_FLOW_MEM_ERROR GST_FLOW_CUSTOM_ERROR
#define GST_VAAPI_ENCODE_FLOW_CONVERT_ERROR GST_FLOW_CUSTOM_ERROR_1
-#define GST_VAAPI_ENCODE_FLOW_CODEC_DATA_ERROR GST_FLOW_CUSTOM_ERROR_2
GST_DEBUG_CATEGORY_STATIC (gst_vaapiencode_debug);
#define GST_CAT_DEFAULT gst_vaapiencode_debug
@@ -220,6 +219,40 @@ error_copy_buffer:
}
}
+static gboolean
+ensure_output_state (GstVaapiEncode * encode)
+{
+ GstVideoEncoder *const venc = GST_VIDEO_ENCODER_CAST (encode);
+ GstVaapiEncodeClass *const klass = GST_VAAPIENCODE_GET_CLASS (encode);
+ GstVaapiEncoderStatus status;
+ GstCaps *out_caps;
+
+ if (!encode->input_state_changed)
+ return TRUE;
+
+ out_caps = klass->get_caps (encode);
+ if (!out_caps)
+ return FALSE;
+
+ if (encode->output_state)
+ gst_video_codec_state_unref (encode->output_state);
+ encode->output_state = gst_video_encoder_set_output_state (venc, out_caps,
+ encode->input_state);
+
+ status = gst_vaapi_encoder_get_codec_data (encode->encoder,
+ &encode->output_state->codec_data);
+ if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
+ return FALSE;
+
+#if GST_CHECK_VERSION(1,0,0)
+ if (!gst_video_encoder_negotiate (venc))
+ return FALSE;
+#endif
+
+ encode->input_state_changed = FALSE;
+ return TRUE;
+}
+
static GstFlowReturn
gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout)
{
@@ -244,6 +277,12 @@ gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout)
gst_video_codec_frame_ref (out_frame);
gst_video_codec_frame_set_user_data (out_frame, NULL, NULL);
+ /* Update output state */
+ GST_VIDEO_ENCODER_STREAM_LOCK (encode);
+ if (!ensure_output_state (encode))
+ goto error_output_state;
+ GST_VIDEO_ENCODER_STREAM_UNLOCK (encode);
+
/* Allocate and copy buffer into system memory */
out_buffer = NULL;
ret = klass->alloc_buffer (encode,
@@ -255,35 +294,6 @@ gst_vaapiencode_push_frame (GstVaapiEncode * encode, gint64 timeout)
gst_buffer_replace (&out_frame->output_buffer, out_buffer);
gst_buffer_unref (out_buffer);
- /* Check output caps */
- GST_VIDEO_ENCODER_STREAM_LOCK (encode);
- if (!encode->out_caps_done) {
- GstVideoCodecState *old_state, *new_state;
- GstBuffer *codec_data;
-
- status = gst_vaapi_encoder_get_codec_data (encode->encoder, &codec_data);
- if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
- goto error_codec_data;
-
- if (codec_data) {
- encode->srcpad_caps = gst_caps_make_writable (encode->srcpad_caps);
- gst_caps_set_simple (encode->srcpad_caps,
- "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
- gst_buffer_unref (codec_data);
- old_state =
- gst_video_encoder_get_output_state (GST_VIDEO_ENCODER_CAST (encode));
- new_state =
- gst_video_encoder_set_output_state (GST_VIDEO_ENCODER_CAST (encode),
- gst_caps_ref (encode->srcpad_caps), old_state);
- gst_video_codec_state_unref (old_state);
- gst_video_codec_state_unref (new_state);
- GST_DEBUG ("updated srcpad caps to: %" GST_PTR_FORMAT,
- encode->srcpad_caps);
- }
- encode->out_caps_done = TRUE;
- }
- GST_VIDEO_ENCODER_STREAM_UNLOCK (encode);
-
GST_DEBUG ("output:%" GST_TIME_FORMAT ", size:%zu",
GST_TIME_ARGS (out_frame->pts), gst_buffer_get_size (out_buffer));
@@ -305,12 +315,12 @@ error_allocate_buffer:
gst_video_codec_frame_unref (out_frame);
return ret;
}
-error_codec_data:
+error_output_state:
{
- GST_ERROR ("failed to construct codec-data (status %d)", status);
+ GST_ERROR ("failed to negotiate output state", status);
GST_VIDEO_ENCODER_STREAM_UNLOCK (encode);
gst_video_codec_frame_unref (out_frame);
- return GST_VAAPI_ENCODE_FLOW_CODEC_DATA_ERROR;
+ return GST_FLOW_NOT_NEGOTIATED;
}
}
@@ -374,6 +384,15 @@ gst_vaapiencode_get_caps (GstVideoEncoder * venc, GstCaps * filter)
static gboolean
gst_vaapiencode_destroy (GstVaapiEncode * encode)
{
+ if (encode->input_state) {
+ gst_video_codec_state_unref (encode->input_state);
+ encode->input_state = NULL;
+ }
+
+ if (encode->output_state) {
+ gst_video_codec_state_unref (encode->output_state);
+ encode->output_state = NULL;
+ }
gst_vaapi_encoder_replace (&encode->encoder, NULL);
gst_caps_replace (&encode->sinkpad_caps, NULL);
gst_caps_replace (&encode->srcpad_caps, NULL);
@@ -446,19 +465,12 @@ gst_vaapiencode_update_sink_caps (GstVaapiEncode * encode,
}
static gboolean
-gst_vaapiencode_update_src_caps (GstVaapiEncode * encode,
- GstVideoCodecState * in_state)
+set_codec_state (GstVaapiEncode * encode, GstVideoCodecState * state)
{
- GstVideoCodecState *out_state;
- GstStructure *structure;
- GstCaps *outcaps, *allowed_caps, *template_caps, *intersect;
- GstVaapiEncoderStatus status;
- GstBuffer *codec_data = NULL;
+ GstCaps *out_caps, *allowed_caps, *template_caps, *intersect;
g_return_val_if_fail (encode->encoder, FALSE);
- encode->out_caps_done = FALSE;
-
/* get peer caps for stream-format avc/bytestream, codec_data */
template_caps = gst_pad_get_pad_template_caps (encode->srcpad);
allowed_caps = gst_pad_get_allowed_caps (encode->srcpad);
@@ -467,38 +479,19 @@ gst_vaapiencode_update_src_caps (GstVaapiEncode * encode,
gst_caps_unref (allowed_caps);
/* codec data was not set */
- outcaps = gst_vaapi_encoder_set_format (encode->encoder, in_state, intersect);
+ out_caps = gst_vaapi_encoder_set_format (encode->encoder, state, intersect);
gst_caps_unref (intersect);
- g_return_val_if_fail (outcaps, FALSE);
+ g_return_val_if_fail (out_caps, FALSE);
- if (!gst_caps_is_fixed (outcaps)) {
+ if (!gst_caps_is_fixed (out_caps)) {
GST_ERROR ("encoder output caps was not fixed");
- gst_caps_unref (outcaps);
+ gst_caps_unref (out_caps);
return FALSE;
}
- structure = gst_caps_get_structure (outcaps, 0);
- if (!gst_structure_has_field (structure, "codec_data")) {
- status = gst_vaapi_encoder_get_codec_data (encode->encoder, &codec_data);
- if (status == GST_VAAPI_ENCODER_STATUS_SUCCESS) {
- if (codec_data) {
- outcaps = gst_caps_make_writable (outcaps);
- gst_caps_set_simple (outcaps,
- "codec_data", GST_TYPE_BUFFER, codec_data, NULL);
- gst_buffer_replace (&codec_data, NULL);
- }
- encode->out_caps_done = TRUE;
- }
- } else
- encode->out_caps_done = TRUE;
-
- out_state =
- gst_video_encoder_set_output_state (GST_VIDEO_ENCODER_CAST (encode),
- outcaps, in_state);
- gst_caps_replace (&encode->srcpad_caps, out_state->caps);
- gst_video_codec_state_unref (out_state);
-
- GST_DEBUG ("set srcpad caps to: %" GST_PTR_FORMAT, encode->srcpad_caps);
+ GST_DEBUG ("set srcpad caps to: %" GST_PTR_FORMAT, out_caps);
+ gst_caps_replace (&encode->srcpad_caps, out_caps);
+ gst_caps_unref (out_caps);
return TRUE;
}
@@ -511,39 +504,25 @@ gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state)
if (!ensure_encoder (encode))
return FALSE;
- if (!gst_vaapiencode_update_sink_caps (encode, state))
+ if (!set_codec_state (encode, state))
return FALSE;
- if (!gst_vaapiencode_update_src_caps (encode, state))
+
+ if (!gst_vaapiencode_update_sink_caps (encode, state))
return FALSE;
if (!gst_vaapi_plugin_base_set_caps (GST_VAAPI_PLUGIN_BASE (encode),
- encode->sinkpad_caps, encode->srcpad_caps))
+ state->caps, NULL))
return FALSE;
-#if GST_CHECK_VERSION(1,0,0)
- if (encode->out_caps_done && !gst_video_encoder_negotiate (venc)) {
- GST_ERROR ("failed to negotiate with caps %" GST_PTR_FORMAT,
- encode->srcpad_caps);
- return FALSE;
- }
-#endif
+ if (encode->input_state)
+ gst_video_codec_state_unref (encode->input_state);
+ encode->input_state = gst_video_codec_state_ref (state);
+ encode->input_state_changed = TRUE;
return gst_pad_start_task (encode->srcpad,
(GstTaskFunction) gst_vaapiencode_buffer_loop, encode, NULL);
}
-static gboolean
-gst_vaapiencode_reset (GstVideoEncoder * venc, gboolean hard)
-{
- GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc);
-
- GST_DEBUG ("vaapiencode starting reset");
-
- /* FIXME: compare sink_caps with encoder */
- encode->out_caps_done = FALSE;
- return TRUE;
-}
-
static GstFlowReturn
gst_vaapiencode_handle_frame (GstVideoEncoder * venc,
GstVideoCodecFrame * frame)
@@ -700,7 +679,6 @@ gst_vaapiencode_class_init (GstVaapiEncodeClass * klass)
venc_class->open = GST_DEBUG_FUNCPTR (gst_vaapiencode_open);
venc_class->close = GST_DEBUG_FUNCPTR (gst_vaapiencode_close);
venc_class->set_format = GST_DEBUG_FUNCPTR (gst_vaapiencode_set_format);
- venc_class->reset = GST_DEBUG_FUNCPTR (gst_vaapiencode_reset);
venc_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vaapiencode_handle_frame);
venc_class->finish = GST_DEBUG_FUNCPTR (gst_vaapiencode_finish);
venc_class->getcaps = GST_DEBUG_FUNCPTR (gst_vaapiencode_get_caps);
diff --git a/gst/vaapi/gstvaapiencode.h b/gst/vaapi/gstvaapiencode.h
index 91712af..7ceffa3 100644
--- a/gst/vaapi/gstvaapiencode.h
+++ b/gst/vaapi/gstvaapiencode.h
@@ -59,9 +59,10 @@ struct _GstVaapiEncode
GstPadQueryFunction srcpad_query;
GstVaapiEncoder *encoder;
+ GstVideoCodecState *input_state;
+ gboolean input_state_changed;
+ GstVideoCodecState *output_state;
GPtrArray *prop_values;
-
- guint32 out_caps_done:1;
};
struct _GstVaapiEncodeClass
@@ -75,6 +76,7 @@ struct _GstVaapiEncodeClass
gboolean (*set_property) (GstVaapiEncode * encode,
guint prop_id, const GValue * value);
+ GstCaps * (*get_caps) (GstVaapiEncode * encode);
GstVaapiEncoder * (*alloc_encoder) (GstVaapiEncode * encode,
GstVaapiDisplay * display);
GstFlowReturn (*alloc_buffer) (GstVaapiEncode * encode,
diff --git a/gst/vaapi/gstvaapiencode_h264.c b/gst/vaapi/gstvaapiencode_h264.c
index 0d222b5..f64db7f 100644
--- a/gst/vaapi/gstvaapiencode_h264.c
+++ b/gst/vaapi/gstvaapiencode_h264.c
@@ -34,7 +34,9 @@
GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encode_debug);
#define GST_CAT_DEFAULT gst_vaapi_h264_encode_debug
-#define GST_CAPS_CODEC(CODEC) CODEC "; "
+#define GST_CODEC_CAPS \
+ "video/x-h264, " \
+ "alignment = (string) au"
/* *INDENT-OFF* */
static const char gst_vaapiencode_h264_sink_caps_str[] =
@@ -57,7 +59,7 @@ static const char gst_vaapiencode_h264_sink_caps_str[] =
/* *INDENT-OFF* */
static const char gst_vaapiencode_h264_src_caps_str[] =
- GST_CAPS_CODEC ("video/x-h264");
+ GST_CODEC_CAPS;
/* *INDENT-ON* */
/* *INDENT-OFF* */
@@ -121,6 +123,39 @@ gst_vaapiencode_h264_get_property (GObject * object,
}
}
+static GstCaps *
+gst_vaapiencode_h264_get_caps (GstVaapiEncode * base_encode)
+{
+ GstVaapiEncodeH264 *const encode = GST_VAAPIENCODE_H264_CAST (base_encode);
+ GstCaps *caps, *allowed_caps;
+
+ caps = gst_caps_from_string (GST_CODEC_CAPS);
+
+ /* Check whether "stream-format" is avcC mode */
+ allowed_caps = gst_pad_get_allowed_caps (base_encode->srcpad);
+ if (allowed_caps) {
+ const char *stream_format = NULL;
+ GstStructure *structure;
+ guint i, num_structures;
+
+ num_structures = gst_caps_get_size (allowed_caps);
+ for (i = 0; !stream_format && i < num_structures; i++) {
+ structure = gst_caps_get_structure (allowed_caps, i);
+ if (!gst_structure_has_field_typed (structure, "stream-format",
+ G_TYPE_STRING))
+ continue;
+ stream_format = gst_structure_get_string (structure, "stream-format");
+ }
+ encode->is_avc = stream_format && strcmp (stream_format, "avc") == 0;
+ gst_caps_unref (allowed_caps);
+ }
+ gst_caps_set_simple (caps, "stream-format", G_TYPE_STRING,
+ encode->is_avc ? "avc" : "byte-stream", NULL);
+
+ /* XXX: update profile and level information */
+ return caps;
+}
+
static GstVaapiEncoder *
gst_vaapiencode_h264_alloc_encoder (GstVaapiEncode * base,
GstVaapiDisplay * display)
@@ -221,21 +256,23 @@ error:
}
static GstFlowReturn
-gst_vaapiencode_h264_alloc_buffer (GstVaapiEncode * encode,
+gst_vaapiencode_h264_alloc_buffer (GstVaapiEncode * base_encode,
GstVaapiCodedBuffer * coded_buf, GstBuffer ** out_buffer_ptr)
{
- GstVaapiEncoderH264 *const encoder = (GstVaapiEncoderH264 *) encode->encoder;
+ GstVaapiEncodeH264 *const encode = GST_VAAPIENCODE_H264_CAST (base_encode);
+ GstVaapiEncoderH264 *const encoder = (GstVaapiEncoderH264 *)
+ base_encode->encoder;
GstFlowReturn ret;
g_return_val_if_fail (encoder != NULL, GST_FLOW_ERROR);
ret =
GST_VAAPIENCODE_CLASS (gst_vaapiencode_h264_parent_class)->alloc_buffer
- (encode, coded_buf, out_buffer_ptr);
+ (base_encode, coded_buf, out_buffer_ptr);
if (ret != GST_FLOW_OK)
return ret;
- if (!gst_vaapi_encoder_h264_is_avc (encoder))
+ if (!encode->is_avc)
return GST_FLOW_OK;
/* Convert to avcC format */
@@ -267,6 +304,7 @@ gst_vaapiencode_h264_class_init (GstVaapiEncodeH264Class * klass)
object_class->get_property = gst_vaapiencode_h264_get_property;
encode_class->get_properties = gst_vaapi_encoder_h264_get_default_properties;
+ encode_class->get_caps = gst_vaapiencode_h264_get_caps;
encode_class->alloc_encoder = gst_vaapiencode_h264_alloc_encoder;
encode_class->alloc_buffer = gst_vaapiencode_h264_alloc_buffer;
diff --git a/gst/vaapi/gstvaapiencode_h264.h b/gst/vaapi/gstvaapiencode_h264.h
index bf440bf..d30c065 100644
--- a/gst/vaapi/gstvaapiencode_h264.h
+++ b/gst/vaapi/gstvaapiencode_h264.h
@@ -52,6 +52,8 @@ struct _GstVaapiEncodeH264
{
/*< private >*/
GstVaapiEncode parent_instance;
+
+ guint is_avc:1; /* [FALSE]=byte-stream (default); [TRUE]=avcC */
};
struct _GstVaapiEncodeH264Class
diff --git a/gst/vaapi/gstvaapiencode_mpeg2.c b/gst/vaapi/gstvaapiencode_mpeg2.c
index 7579b2a..b84821c 100644
--- a/gst/vaapi/gstvaapiencode_mpeg2.c
+++ b/gst/vaapi/gstvaapiencode_mpeg2.c
@@ -34,7 +34,9 @@
GST_DEBUG_CATEGORY_STATIC (gst_vaapi_mpeg2_encode_debug);
#define GST_CAT_DEFAULT gst_vaapi_mpeg2_encode_debug
-#define GST_CAPS_CODEC(CODEC) CODEC "; "
+#define GST_CODEC_CAPS \
+ "video/mpeg, mpegversion = (int) 2, " \
+ "systemstream = (boolean) false"
/* *INDENT-OFF* */
static const char gst_vaapiencode_mpeg2_sink_caps_str[] =
@@ -57,8 +59,7 @@ static const char gst_vaapiencode_mpeg2_sink_caps_str[] =
/* *INDENT-OFF* */
static const char gst_vaapiencode_mpeg2_src_caps_str[] =
- GST_CAPS_CODEC ("video/mpeg, mpegversion = (int) 2, "
- "systemstream = (boolean) false");
+ GST_CODEC_CAPS;
/* *INDENT-ON* */
/* *INDENT-OFF* */
@@ -123,6 +124,17 @@ gst_vaapiencode_mpeg2_get_property (GObject * object,
}
}
+static GstCaps *
+gst_vaapiencode_mpeg2_get_caps (GstVaapiEncode * base_encode)
+{
+ GstCaps *caps;
+
+ caps = gst_caps_from_string (GST_CODEC_CAPS);
+
+ /* XXX: update profile and level information */
+ return caps;
+}
+
static GstVaapiEncoder *
gst_vaapiencode_mpeg2_alloc_encoder (GstVaapiEncode * base,
GstVaapiDisplay * display)
@@ -145,6 +157,7 @@ gst_vaapiencode_mpeg2_class_init (GstVaapiEncodeMpeg2Class * klass)
object_class->get_property = gst_vaapiencode_mpeg2_get_property;
encode_class->get_properties = gst_vaapi_encoder_mpeg2_get_default_properties;
+ encode_class->get_caps = gst_vaapiencode_mpeg2_get_caps;
encode_class->alloc_encoder = gst_vaapiencode_mpeg2_alloc_encoder;
gst_element_class_set_static_metadata (element_class,
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gstreamer/gstreamer-vaapi.git
More information about the Pkg-gstreamer-commits
mailing list