mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-14 13:21:28 +00:00
vaapidecode: move to GstVideoDecoder base class.
Make vaapidecode derive from the standard GstVideoDecoder base element class. This simplifies the code to the strict minimum for the decoder element and makes it easier to port to GStreamer 1.x API. Signed-off-by: Sreerenj Balachandran <sreerenj.balachandran@intel.com> Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
This commit is contained in:
parent
ddc74f8a20
commit
9127f17d81
2 changed files with 160 additions and 233 deletions
|
@ -98,7 +98,7 @@ gst_video_context_interface_init(GstVideoContextInterface *iface);
|
||||||
G_DEFINE_TYPE_WITH_CODE(
|
G_DEFINE_TYPE_WITH_CODE(
|
||||||
GstVaapiDecode,
|
GstVaapiDecode,
|
||||||
gst_vaapidecode,
|
gst_vaapidecode,
|
||||||
GST_TYPE_ELEMENT,
|
GST_TYPE_VIDEO_DECODER,
|
||||||
G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
|
G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
|
||||||
gst_vaapidecode_implements_iface_init);
|
gst_vaapidecode_implements_iface_init);
|
||||||
G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
|
G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
|
||||||
|
@ -131,43 +131,46 @@ gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps)
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps)
|
gst_vaapidecode_update_src_caps(GstVaapiDecode *decode, GstCaps *caps)
|
||||||
{
|
{
|
||||||
GstCaps *other_caps;
|
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
||||||
GstStructure *structure;
|
GstVideoCodecState *state, *ref_state;
|
||||||
const GValue *v_width, *v_height, *v_framerate, *v_par, *v_interlaced;
|
GstVideoInfo info;
|
||||||
gboolean success;
|
|
||||||
|
|
||||||
if (!decode->srcpad_caps) {
|
if (!gst_video_info_from_caps(&info, caps))
|
||||||
decode->srcpad_caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
|
return FALSE;
|
||||||
if (!decode->srcpad_caps)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
structure = gst_caps_get_structure(caps, 0);
|
ref_state = g_slice_new0(GstVideoCodecState);
|
||||||
v_width = gst_structure_get_value(structure, "width");
|
ref_state->ref_count = 1;
|
||||||
v_height = gst_structure_get_value(structure, "height");
|
ref_state->info = info;
|
||||||
v_framerate = gst_structure_get_value(structure, "framerate");
|
|
||||||
v_par = gst_structure_get_value(structure, "pixel-aspect-ratio");
|
|
||||||
v_interlaced = gst_structure_get_value(structure, "interlaced");
|
|
||||||
|
|
||||||
structure = gst_caps_get_structure(decode->srcpad_caps, 0);
|
state = gst_video_decoder_set_output_state(vdec,
|
||||||
if (v_width && v_height) {
|
GST_VIDEO_INFO_FORMAT(&info), info.width, info.height, ref_state);
|
||||||
gst_structure_set_value(structure, "width", v_width);
|
gst_video_codec_state_unref(ref_state);
|
||||||
gst_structure_set_value(structure, "height", v_height);
|
if (!state)
|
||||||
}
|
return FALSE;
|
||||||
if (v_framerate)
|
|
||||||
gst_structure_set_value(structure, "framerate", v_framerate);
|
|
||||||
if (v_par)
|
|
||||||
gst_structure_set_value(structure, "pixel-aspect-ratio", v_par);
|
|
||||||
if (v_interlaced)
|
|
||||||
gst_structure_set_value(structure, "interlaced", v_interlaced);
|
|
||||||
|
|
||||||
gst_structure_set(structure, "type", G_TYPE_STRING, "vaapi", NULL);
|
gst_video_codec_state_unref(state);
|
||||||
gst_structure_set(structure, "opengl", G_TYPE_BOOLEAN, USE_GLX, NULL);
|
|
||||||
|
|
||||||
other_caps = gst_caps_copy(decode->srcpad_caps);
|
/* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not
|
||||||
success = gst_pad_set_caps(decode->srcpad, other_caps);
|
reconstruct suitable caps for "encoded" video formats */
|
||||||
gst_caps_unref(other_caps);
|
state->caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME);
|
||||||
return success;
|
if (!state->caps)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
gst_caps_set_simple(state->caps,
|
||||||
|
"type", G_TYPE_STRING, "vaapi",
|
||||||
|
"opengl", G_TYPE_BOOLEAN, USE_GLX,
|
||||||
|
"width", G_TYPE_INT, info.width,
|
||||||
|
"height", G_TYPE_INT, info.height,
|
||||||
|
"framerate", GST_TYPE_FRACTION, info.fps_n, info.fps_d,
|
||||||
|
"pixel-aspect-ratio", GST_TYPE_FRACTION, info.par_n, info.par_d,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
if (GST_VIDEO_INFO_IS_INTERLACED(&info))
|
||||||
|
gst_caps_set_simple(state->caps, "interlaced", G_TYPE_BOOLEAN,
|
||||||
|
TRUE, NULL);
|
||||||
|
|
||||||
|
gst_caps_replace(&decode->srcpad_caps, state->caps);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -179,13 +182,13 @@ gst_vaapidecode_release(GstVaapiDecode *decode)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_vaapidecode_step(GstVaapiDecode *decode)
|
gst_vaapidecode_handle_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame)
|
||||||
{
|
{
|
||||||
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
||||||
GstVaapiSurfaceProxy *proxy;
|
GstVaapiSurfaceProxy *proxy;
|
||||||
GstVaapiDecoderStatus status;
|
GstVaapiDecoderStatus status;
|
||||||
GstBuffer *buffer;
|
GstVideoCodecFrame *out_frame;
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstClockTime timestamp;
|
|
||||||
gint64 end_time;
|
gint64 end_time;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -195,56 +198,51 @@ gst_vaapidecode_step(GstVaapiDecode *decode)
|
||||||
end_time += GST_TIME_AS_USECONDS(decode->last_buffer_time);
|
end_time += GST_TIME_AS_USECONDS(decode->last_buffer_time);
|
||||||
end_time += G_TIME_SPAN_SECOND;
|
end_time += G_TIME_SPAN_SECOND;
|
||||||
|
|
||||||
proxy = gst_vaapi_decoder_get_surface(decode->decoder, &status);
|
status = gst_vaapi_decoder_decode(decode->decoder, frame, &proxy);
|
||||||
if (!proxy) {
|
if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
|
||||||
if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) {
|
gboolean was_signalled;
|
||||||
gboolean was_signalled;
|
g_mutex_lock(&decode->decoder_mutex);
|
||||||
g_mutex_lock(&decode->decoder_mutex);
|
was_signalled = g_cond_wait_until(
|
||||||
was_signalled = g_cond_wait_until(
|
&decode->decoder_ready,
|
||||||
&decode->decoder_ready,
|
&decode->decoder_mutex,
|
||||||
&decode->decoder_mutex,
|
end_time
|
||||||
end_time
|
);
|
||||||
);
|
g_mutex_unlock(&decode->decoder_mutex);
|
||||||
g_mutex_unlock(&decode->decoder_mutex);
|
if (was_signalled)
|
||||||
if (was_signalled)
|
continue;
|
||||||
continue;
|
goto error_decode_timeout;
|
||||||
goto error_decode_timeout;
|
|
||||||
}
|
|
||||||
if (status != GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA)
|
|
||||||
goto error_decode;
|
|
||||||
/* More data is needed */
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
|
||||||
|
goto error_decode;
|
||||||
|
|
||||||
|
/* Current frame was decoded but no surface was output */
|
||||||
|
if (!proxy)
|
||||||
|
break;
|
||||||
|
|
||||||
|
out_frame = gst_vaapi_surface_proxy_get_user_data(proxy);
|
||||||
|
|
||||||
gst_vaapi_surface_proxy_set_user_data(proxy,
|
gst_vaapi_surface_proxy_set_user_data(proxy,
|
||||||
decode, (GDestroyNotify)gst_vaapidecode_release);
|
decode, (GDestroyNotify)gst_vaapidecode_release);
|
||||||
|
|
||||||
buffer = gst_vaapi_video_buffer_new(decode->display);
|
out_frame->output_buffer = gst_vaapi_video_buffer_new(decode->display);
|
||||||
if (!buffer)
|
if (!out_frame->output_buffer)
|
||||||
goto error_create_buffer;
|
goto error_create_buffer;
|
||||||
|
|
||||||
timestamp = GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
|
out_frame->pts = GST_VAAPI_SURFACE_PROXY_TIMESTAMP(proxy);
|
||||||
if (!decode->render_time_base)
|
out_frame->duration = GST_VAAPI_SURFACE_PROXY_DURATION(proxy);
|
||||||
decode->render_time_base = g_get_monotonic_time();
|
|
||||||
decode->last_buffer_time = timestamp;
|
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP(buffer) = timestamp;
|
|
||||||
GST_BUFFER_DURATION(buffer) = GST_VAAPI_SURFACE_PROXY_DURATION(proxy);
|
|
||||||
gst_buffer_set_caps(buffer, GST_PAD_CAPS(decode->srcpad));
|
|
||||||
|
|
||||||
if (GST_VAAPI_SURFACE_PROXY_TFF(proxy))
|
if (GST_VAAPI_SURFACE_PROXY_TFF(proxy))
|
||||||
GST_BUFFER_FLAG_SET(buffer, GST_VIDEO_BUFFER_TFF);
|
GST_VIDEO_CODEC_FRAME_FLAG_SET(out_frame,
|
||||||
|
GST_VIDEO_CODEC_FRAME_FLAG_TFF);
|
||||||
|
|
||||||
gst_vaapi_video_buffer_set_surface_proxy(
|
gst_vaapi_video_buffer_set_surface_proxy(
|
||||||
GST_VAAPI_VIDEO_BUFFER(buffer),
|
GST_VAAPI_VIDEO_BUFFER(out_frame->output_buffer), proxy);
|
||||||
proxy
|
gst_vaapi_surface_proxy_unref(proxy);
|
||||||
);
|
|
||||||
|
|
||||||
ret = gst_pad_push(decode->srcpad, buffer);
|
ret = gst_video_decoder_finish_frame(vdec, out_frame);
|
||||||
if (ret != GST_FLOW_OK)
|
if (ret != GST_FLOW_OK)
|
||||||
goto error_commit_buffer;
|
goto error_commit_buffer;
|
||||||
|
break;
|
||||||
gst_vaapi_surface_proxy_unref(proxy);
|
|
||||||
}
|
}
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
|
||||||
|
@ -268,6 +266,7 @@ error_decode:
|
||||||
ret = GST_FLOW_UNEXPECTED;
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
gst_video_decoder_drop_frame(vdec, frame);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
error_create_buffer:
|
error_create_buffer:
|
||||||
|
@ -278,13 +277,13 @@ error_create_buffer:
|
||||||
GST_DEBUG("video sink failed to create video buffer for proxy'ed "
|
GST_DEBUG("video sink failed to create video buffer for proxy'ed "
|
||||||
"surface %" GST_VAAPI_ID_FORMAT,
|
"surface %" GST_VAAPI_ID_FORMAT,
|
||||||
GST_VAAPI_ID_ARGS(surface_id));
|
GST_VAAPI_ID_ARGS(surface_id));
|
||||||
gst_vaapi_surface_proxy_unref(proxy);
|
gst_video_decoder_drop_frame(vdec, out_frame);
|
||||||
return GST_FLOW_UNEXPECTED;
|
return GST_FLOW_UNEXPECTED;
|
||||||
}
|
}
|
||||||
error_commit_buffer:
|
error_commit_buffer:
|
||||||
{
|
{
|
||||||
GST_DEBUG("video sink rejected the video buffer (error %d)", ret);
|
GST_DEBUG("video sink rejected the video buffer (error %d)", ret);
|
||||||
gst_vaapi_surface_proxy_unref(proxy);
|
gst_video_decoder_drop_frame(vdec, out_frame);
|
||||||
return GST_FLOW_UNEXPECTED;
|
return GST_FLOW_UNEXPECTED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,7 +352,6 @@ static void
|
||||||
gst_vaapidecode_destroy(GstVaapiDecode *decode)
|
gst_vaapidecode_destroy(GstVaapiDecode *decode)
|
||||||
{
|
{
|
||||||
if (decode->decoder) {
|
if (decode->decoder) {
|
||||||
(void)gst_vaapi_decoder_put_buffer(decode->decoder, NULL);
|
|
||||||
g_object_unref(decode->decoder);
|
g_object_unref(decode->decoder);
|
||||||
decode->decoder = NULL;
|
decode->decoder = NULL;
|
||||||
}
|
}
|
||||||
|
@ -384,18 +382,6 @@ gst_vaapidecode_reset(GstVaapiDecode *decode, GstCaps *caps)
|
||||||
return gst_vaapidecode_create(decode, caps);
|
return gst_vaapidecode_create(decode, caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_vaapidecode_flush(GstVaapiDecode *decode)
|
|
||||||
{
|
|
||||||
g_return_val_if_fail(decode->decoder, FALSE);
|
|
||||||
|
|
||||||
if (!gst_vaapi_decoder_put_buffer(decode->decoder, NULL))
|
|
||||||
return FALSE;
|
|
||||||
if (gst_vaapidecode_step(decode) != GST_FLOW_OK)
|
|
||||||
return FALSE;
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* GstImplementsInterface interface */
|
/* GstImplementsInterface interface */
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -453,53 +439,84 @@ gst_vaapidecode_finalize(GObject *object)
|
||||||
decode->allowed_caps = NULL;
|
decode->allowed_caps = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decode->delayed_new_seg) {
|
|
||||||
gst_event_unref(decode->delayed_new_seg);
|
|
||||||
decode->delayed_new_seg = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_cond_clear(&decode->decoder_ready);
|
g_cond_clear(&decode->decoder_ready);
|
||||||
g_mutex_clear(&decode->decoder_mutex);
|
g_mutex_clear(&decode->decoder_mutex);
|
||||||
|
|
||||||
G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
|
G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static gboolean
|
||||||
gst_vaapidecode_change_state(GstElement *element, GstStateChange transition)
|
gst_vaapidecode_open(GstVideoDecoder *vdec)
|
||||||
{
|
{
|
||||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(element);
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
||||||
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
|
||||||
|
|
||||||
switch (transition) {
|
decode->is_ready = TRUE;
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
return TRUE;
|
||||||
decode->is_ready = TRUE;
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vaapidecode_close(GstVideoDecoder *vdec)
|
||||||
|
{
|
||||||
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
||||||
|
|
||||||
|
gst_vaapidecode_destroy(decode);
|
||||||
|
g_clear_object(&decode->display);
|
||||||
|
decode->is_ready = FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state)
|
||||||
|
{
|
||||||
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
||||||
|
GstCaps * const caps = state->caps;
|
||||||
|
|
||||||
|
if (!gst_vaapidecode_update_sink_caps(decode, caps))
|
||||||
|
return FALSE;
|
||||||
|
if (!gst_vaapidecode_update_src_caps(decode, caps))
|
||||||
|
return FALSE;
|
||||||
|
if (!gst_vaapidecode_reset(decode, decode->sinkpad_caps))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstFlowReturn
|
||||||
|
gst_vaapidecode_parse(GstVideoDecoder *vdec,
|
||||||
|
GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
|
||||||
|
{
|
||||||
|
GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
|
||||||
|
GstVaapiDecoderStatus status;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
guint got_unit_size;
|
||||||
|
gboolean got_frame;
|
||||||
|
|
||||||
|
status = gst_vaapi_decoder_parse(decode->decoder, frame,
|
||||||
|
adapter, at_eos, &got_unit_size, &got_frame);
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case GST_VAAPI_DECODER_STATUS_SUCCESS:
|
||||||
|
if (got_unit_size > 0)
|
||||||
|
gst_video_decoder_add_to_frame(vdec, got_unit_size);
|
||||||
|
if (got_frame)
|
||||||
|
ret = gst_video_decoder_have_frame(vdec);
|
||||||
|
else
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
|
||||||
|
ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CODEC:
|
||||||
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_PROFILE:
|
||||||
|
case GST_VAAPI_DECODER_STATUS_ERROR_UNSUPPORTED_CHROMA_FORMAT:
|
||||||
|
GST_WARNING("parse error %d", status);
|
||||||
|
ret = GST_FLOW_NOT_SUPPORTED;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
GST_ERROR("parse error %d", status);
|
||||||
|
ret = GST_FLOW_UNEXPECTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
ret = GST_ELEMENT_CLASS(gst_vaapidecode_parent_class)->change_state(element, transition);
|
|
||||||
if (ret != GST_STATE_CHANGE_SUCCESS)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
switch (transition) {
|
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
|
||||||
break;
|
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
|
||||||
gst_vaapidecode_destroy(decode);
|
|
||||||
g_clear_object(&decode->display);
|
|
||||||
decode->is_ready = FALSE;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return GST_STATE_CHANGE_SUCCESS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -507,14 +524,19 @@ gst_vaapidecode_class_init(GstVaapiDecodeClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
|
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
|
||||||
GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
|
GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
|
||||||
|
GstVideoDecoderClass * const vdec_class = GST_VIDEO_DECODER_CLASS(klass);
|
||||||
GstPadTemplate *pad_template;
|
GstPadTemplate *pad_template;
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
|
GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode,
|
||||||
GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
|
GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
|
||||||
|
|
||||||
object_class->finalize = gst_vaapidecode_finalize;
|
object_class->finalize = gst_vaapidecode_finalize;
|
||||||
|
|
||||||
element_class->change_state = gst_vaapidecode_change_state;
|
vdec_class->open = GST_DEBUG_FUNCPTR(gst_vaapidecode_open);
|
||||||
|
vdec_class->close = GST_DEBUG_FUNCPTR(gst_vaapidecode_close);
|
||||||
|
vdec_class->set_format = GST_DEBUG_FUNCPTR(gst_vaapidecode_set_format);
|
||||||
|
vdec_class->parse = GST_DEBUG_FUNCPTR(gst_vaapidecode_parse);
|
||||||
|
vdec_class->handle_frame = GST_DEBUG_FUNCPTR(gst_vaapidecode_handle_frame);
|
||||||
|
|
||||||
gst_element_class_set_details_simple(
|
gst_element_class_set_details_simple(
|
||||||
element_class,
|
element_class,
|
||||||
|
@ -610,90 +632,6 @@ gst_vaapidecode_get_caps(GstPad *pad)
|
||||||
return gst_caps_ref(decode->allowed_caps);
|
return gst_caps_ref(decode->allowed_caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_vaapidecode_set_caps(GstPad *pad, GstCaps *caps)
|
|
||||||
{
|
|
||||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
|
|
||||||
|
|
||||||
g_return_val_if_fail(pad == decode->sinkpad, FALSE);
|
|
||||||
|
|
||||||
if (!gst_vaapidecode_update_sink_caps(decode, caps))
|
|
||||||
return FALSE;
|
|
||||||
if (!gst_vaapidecode_update_src_caps(decode, caps))
|
|
||||||
return FALSE;
|
|
||||||
if (!gst_vaapidecode_reset(decode, decode->sinkpad_caps))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* Propagate NEWSEGMENT event downstream, now that pads are linked */
|
|
||||||
if (decode->delayed_new_seg) {
|
|
||||||
if (gst_pad_push_event(decode->srcpad, decode->delayed_new_seg))
|
|
||||||
gst_event_unref(decode->delayed_new_seg);
|
|
||||||
decode->delayed_new_seg = NULL;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_vaapidecode_chain(GstPad *pad, GstBuffer *buf)
|
|
||||||
{
|
|
||||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
|
|
||||||
|
|
||||||
if (!gst_vaapi_decoder_put_buffer(decode->decoder, buf))
|
|
||||||
goto error_push_buffer;
|
|
||||||
|
|
||||||
gst_buffer_unref(buf);
|
|
||||||
return gst_vaapidecode_step(decode);
|
|
||||||
|
|
||||||
/* ERRORS */
|
|
||||||
error_push_buffer:
|
|
||||||
{
|
|
||||||
GST_DEBUG("failed to push input buffer to decoder");
|
|
||||||
gst_buffer_unref(buf);
|
|
||||||
return GST_FLOW_UNEXPECTED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_vaapidecode_sink_event(GstPad *pad, GstEvent *event)
|
|
||||||
{
|
|
||||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
|
|
||||||
|
|
||||||
GST_DEBUG("handle sink event '%s'", GST_EVENT_TYPE_NAME(event));
|
|
||||||
|
|
||||||
/* Propagate event downstream */
|
|
||||||
switch (GST_EVENT_TYPE(event)) {
|
|
||||||
case GST_EVENT_NEWSEGMENT:
|
|
||||||
if (decode->delayed_new_seg) {
|
|
||||||
gst_event_unref(decode->delayed_new_seg);
|
|
||||||
decode->delayed_new_seg = NULL;
|
|
||||||
}
|
|
||||||
if (!GST_PAD_PEER(decode->srcpad)) {
|
|
||||||
decode->delayed_new_seg = gst_event_ref(event);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GST_EVENT_EOS:
|
|
||||||
if (!gst_vaapidecode_flush(decode)) {
|
|
||||||
GST_WARNING("failed to flush buffers");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return gst_pad_push_event(decode->srcpad, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_vaapidecode_src_event(GstPad *pad, GstEvent *event)
|
|
||||||
{
|
|
||||||
GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad));
|
|
||||||
|
|
||||||
GST_DEBUG("handle src event '%s'", GST_EVENT_TYPE_NAME(event));
|
|
||||||
|
|
||||||
/* Propagate event upstream */
|
|
||||||
return gst_pad_push_event(decode->sinkpad, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vaapidecode_query (GstPad *pad, GstQuery *query) {
|
gst_vaapidecode_query (GstPad *pad, GstQuery *query) {
|
||||||
GstVaapiDecode *decode = GST_VAAPIDECODE (gst_pad_get_parent_element (pad));
|
GstVaapiDecode *decode = GST_VAAPIDECODE (gst_pad_get_parent_element (pad));
|
||||||
|
@ -703,8 +641,10 @@ gst_vaapidecode_query (GstPad *pad, GstQuery *query) {
|
||||||
|
|
||||||
if (gst_vaapi_reply_to_query (query, decode->display))
|
if (gst_vaapi_reply_to_query (query, decode->display))
|
||||||
res = TRUE;
|
res = TRUE;
|
||||||
|
else if (GST_PAD_IS_SINK(pad))
|
||||||
|
res = decode->sinkpad_query(decode->sinkpad, query);
|
||||||
else
|
else
|
||||||
res = gst_pad_query_default (pad, query);
|
res = decode->srcpad_query(decode->srcpad, query);
|
||||||
|
|
||||||
g_object_unref (decode);
|
g_object_unref (decode);
|
||||||
return res;
|
return res;
|
||||||
|
@ -713,14 +653,12 @@ gst_vaapidecode_query (GstPad *pad, GstQuery *query) {
|
||||||
static void
|
static void
|
||||||
gst_vaapidecode_init(GstVaapiDecode *decode)
|
gst_vaapidecode_init(GstVaapiDecode *decode)
|
||||||
{
|
{
|
||||||
GstVaapiDecodeClass *klass = GST_VAAPIDECODE_GET_CLASS(decode);
|
GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
|
||||||
GstElementClass * const element_class = GST_ELEMENT_CLASS(klass);
|
|
||||||
|
|
||||||
decode->display = NULL;
|
decode->display = NULL;
|
||||||
decode->decoder = NULL;
|
decode->decoder = NULL;
|
||||||
decode->decoder_caps = NULL;
|
decode->decoder_caps = NULL;
|
||||||
decode->allowed_caps = NULL;
|
decode->allowed_caps = NULL;
|
||||||
decode->delayed_new_seg = NULL;
|
|
||||||
decode->render_time_base = 0;
|
decode->render_time_base = 0;
|
||||||
decode->last_buffer_time = 0;
|
decode->last_buffer_time = 0;
|
||||||
decode->is_ready = FALSE;
|
decode->is_ready = FALSE;
|
||||||
|
@ -728,29 +666,16 @@ gst_vaapidecode_init(GstVaapiDecode *decode)
|
||||||
g_mutex_init(&decode->decoder_mutex);
|
g_mutex_init(&decode->decoder_mutex);
|
||||||
g_cond_init(&decode->decoder_ready);
|
g_cond_init(&decode->decoder_ready);
|
||||||
|
|
||||||
/* Pad through which data comes in to the element */
|
gst_video_decoder_set_packetized(vdec, FALSE);
|
||||||
decode->sinkpad = gst_pad_new_from_template(
|
|
||||||
gst_element_class_get_pad_template(element_class, "sink"),
|
|
||||||
"sink"
|
|
||||||
);
|
|
||||||
decode->sinkpad_caps = NULL;
|
|
||||||
|
|
||||||
gst_pad_set_getcaps_function(decode->sinkpad, gst_vaapidecode_get_caps);
|
/* Pad through which data comes in to the element */
|
||||||
gst_pad_set_setcaps_function(decode->sinkpad, gst_vaapidecode_set_caps);
|
decode->sinkpad = GST_VIDEO_DECODER_SINK_PAD(vdec);
|
||||||
gst_pad_set_chain_function(decode->sinkpad, gst_vaapidecode_chain);
|
decode->sinkpad_query = GST_PAD_QUERYFUNC(decode->sinkpad);
|
||||||
gst_pad_set_event_function(decode->sinkpad, gst_vaapidecode_sink_event);
|
|
||||||
gst_pad_set_query_function(decode->sinkpad, gst_vaapidecode_query);
|
gst_pad_set_query_function(decode->sinkpad, gst_vaapidecode_query);
|
||||||
gst_element_add_pad(GST_ELEMENT(decode), decode->sinkpad);
|
gst_pad_set_getcaps_function(decode->sinkpad, gst_vaapidecode_get_caps);
|
||||||
|
|
||||||
/* Pad through which data goes out of the element */
|
/* Pad through which data goes out of the element */
|
||||||
decode->srcpad = gst_pad_new_from_template(
|
decode->srcpad = GST_VIDEO_DECODER_SRC_PAD(vdec);
|
||||||
gst_element_class_get_pad_template(element_class, "src"),
|
decode->srcpad_query = GST_PAD_QUERYFUNC(decode->srcpad);
|
||||||
"src"
|
|
||||||
);
|
|
||||||
decode->srcpad_caps = NULL;
|
|
||||||
|
|
||||||
gst_pad_use_fixed_caps(decode->srcpad);
|
|
||||||
gst_pad_set_event_function(decode->srcpad, gst_vaapidecode_src_event);
|
|
||||||
gst_pad_set_query_function(decode->srcpad, gst_vaapidecode_query);
|
gst_pad_set_query_function(decode->srcpad, gst_vaapidecode_query);
|
||||||
gst_element_add_pad(GST_ELEMENT(decode), decode->srcpad);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <gst/gst.h>
|
#include <gst/gst.h>
|
||||||
#include <gst/gsttask.h>
|
#include <gst/gsttask.h>
|
||||||
|
#include <gst/video/gstvideodecoder.h>
|
||||||
#include <gst/vaapi/gstvaapidisplay.h>
|
#include <gst/vaapi/gstvaapidisplay.h>
|
||||||
#include <gst/vaapi/gstvaapidecoder.h>
|
#include <gst/vaapi/gstvaapidecoder.h>
|
||||||
|
|
||||||
|
@ -59,19 +60,20 @@ typedef struct _GstVaapiDecodeClass GstVaapiDecodeClass;
|
||||||
|
|
||||||
struct _GstVaapiDecode {
|
struct _GstVaapiDecode {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
GstElement parent_instance;
|
GstVideoDecoder parent_instance;
|
||||||
|
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
GstCaps *sinkpad_caps;
|
GstCaps *sinkpad_caps;
|
||||||
|
GstPadQueryFunction sinkpad_query;
|
||||||
GstPad *srcpad;
|
GstPad *srcpad;
|
||||||
GstCaps *srcpad_caps;
|
GstCaps *srcpad_caps;
|
||||||
|
GstPadQueryFunction srcpad_query;
|
||||||
GstVaapiDisplay *display;
|
GstVaapiDisplay *display;
|
||||||
GstVaapiDecoder *decoder;
|
GstVaapiDecoder *decoder;
|
||||||
GMutex decoder_mutex;
|
GMutex decoder_mutex;
|
||||||
GCond decoder_ready;
|
GCond decoder_ready;
|
||||||
GstCaps *decoder_caps;
|
GstCaps *decoder_caps;
|
||||||
GstCaps *allowed_caps;
|
GstCaps *allowed_caps;
|
||||||
GstEvent *delayed_new_seg;
|
|
||||||
gint64 render_time_base;
|
gint64 render_time_base;
|
||||||
GstClockTime last_buffer_time;
|
GstClockTime last_buffer_time;
|
||||||
unsigned int is_ready : 1;
|
unsigned int is_ready : 1;
|
||||||
|
@ -79,7 +81,7 @@ struct _GstVaapiDecode {
|
||||||
|
|
||||||
struct _GstVaapiDecodeClass {
|
struct _GstVaapiDecodeClass {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
GstElementClass parent_class;
|
GstVideoDecoderClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType
|
GType
|
||||||
|
|
Loading…
Reference in a new issue