diff --git a/gst/vaapi/gstvaapidecode.c b/gst/vaapi/gstvaapidecode.c index 0ba5ee7fcf..9ae72a7c83 100644 --- a/gst/vaapi/gstvaapidecode.c +++ b/gst/vaapi/gstvaapidecode.c @@ -56,12 +56,13 @@ #define GST_VAAPI_DECODE_FLOW_PARSE_DATA GST_FLOW_CUSTOM_SUCCESS_2 -GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode); +GST_DEBUG_CATEGORY_STATIC (gst_debug_vaapidecode); #define GST_CAT_DEFAULT gst_debug_vaapidecode /* Default templates */ #define GST_CAPS_CODEC(CODEC) CODEC "; " +/* *INDENT-OFF* */ static const char gst_vaapidecode_sink_caps_str[] = GST_CAPS_CODEC("video/mpeg, mpegversion=2, systemstream=(boolean)false") GST_CAPS_CODEC("video/mpeg, mpegversion=4") @@ -104,947 +105,943 @@ G_DEFINE_TYPE_WITH_CODE( gst_vaapidecode, GST_TYPE_VIDEO_DECODER, GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES) +/* *INDENT-ON* */ + +static gboolean gst_vaapidecode_update_src_caps (GstVaapiDecode * decode); static gboolean -gst_vaapidecode_update_src_caps(GstVaapiDecode *decode); - -static gboolean -gst_vaapi_decode_input_state_replace(GstVaapiDecode *decode, - const GstVideoCodecState *new_state); +gst_vaapi_decode_input_state_replace (GstVaapiDecode * decode, + const GstVideoCodecState * new_state); static void -gst_vaapi_decoder_state_changed(GstVaapiDecoder *decoder, - const GstVideoCodecState *codec_state, gpointer user_data) +gst_vaapi_decoder_state_changed (GstVaapiDecoder * decoder, + const GstVideoCodecState * codec_state, gpointer user_data) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(user_data); - GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode); - GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(vdec); + GstVaapiDecode *const decode = GST_VAAPIDECODE (user_data); + GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode); + GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (vdec); - g_assert(decode->decoder == decoder); + g_assert (decode->decoder == decoder); - if (!gst_vaapi_decode_input_state_replace(decode, codec_state)) - return; - if (!gst_vaapidecode_update_src_caps(decode)) - return; - if (!gst_video_decoder_negotiate(vdec)) - return; - if (!gst_vaapi_plugin_base_set_caps(plugin, NULL, decode->srcpad_caps)) - return; + if (!gst_vaapi_decode_input_state_replace (decode, codec_state)) + return; + if (!gst_vaapidecode_update_src_caps (decode)) + return; + if (!gst_video_decoder_negotiate (vdec)) + return; + if (!gst_vaapi_plugin_base_set_caps (plugin, NULL, decode->srcpad_caps)) + return; } static gboolean -gst_vaapi_decode_input_state_replace(GstVaapiDecode *decode, - const GstVideoCodecState *new_state) +gst_vaapi_decode_input_state_replace (GstVaapiDecode * decode, + const GstVideoCodecState * new_state) { - if (decode->input_state) { - if (new_state) { - const GstCaps *curcaps = decode->input_state->caps; - if (gst_caps_is_always_compatible(curcaps, new_state->caps)) - return FALSE; - } - gst_video_codec_state_unref(decode->input_state); + if (decode->input_state) { + if (new_state) { + const GstCaps *curcaps = decode->input_state->caps; + if (gst_caps_is_always_compatible (curcaps, new_state->caps)) + return FALSE; } + gst_video_codec_state_unref (decode->input_state); + } - if (new_state) - decode->input_state = gst_video_codec_state_ref - ((GstVideoCodecState*) new_state); - else - decode->input_state = NULL; + if (new_state) + decode->input_state = gst_video_codec_state_ref + ((GstVideoCodecState *) new_state); + else + decode->input_state = NULL; - return TRUE; + return TRUE; } static inline gboolean -gst_vaapidecode_update_sink_caps(GstVaapiDecode *decode, GstCaps *caps) +gst_vaapidecode_update_sink_caps (GstVaapiDecode * decode, GstCaps * caps) { - gst_caps_replace(&decode->sinkpad_caps, caps); - return TRUE; + gst_caps_replace (&decode->sinkpad_caps, caps); + return TRUE; } static gboolean -gst_vaapidecode_update_src_caps(GstVaapiDecode *decode) +gst_vaapidecode_update_src_caps (GstVaapiDecode * decode) { - GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode); - GstVideoCodecState *state, *ref_state; - GstVideoInfo *vi; - GstVideoFormat format = GST_VIDEO_FORMAT_I420; + GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode); + GstVideoCodecState *state, *ref_state; + GstVideoInfo *vi; + GstVideoFormat format = GST_VIDEO_FORMAT_I420; - if (!decode->input_state) - return FALSE; + if (!decode->input_state) + return FALSE; - ref_state = decode->input_state; + ref_state = decode->input_state; #if GST_CHECK_VERSION(1,1,0) - GstCapsFeatures *features = NULL; - GstVaapiCapsFeature feature; + GstCapsFeatures *features = NULL; + GstVaapiCapsFeature feature; - feature = gst_vaapi_find_preferred_caps_feature( - GST_VIDEO_DECODER_SRC_PAD(vdec), - GST_VIDEO_INFO_FORMAT(&ref_state->info), &format); + feature = + gst_vaapi_find_preferred_caps_feature (GST_VIDEO_DECODER_SRC_PAD (vdec), + GST_VIDEO_INFO_FORMAT (&ref_state->info), &format); - if (feature == GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED) - return FALSE; + if (feature == GST_VAAPI_CAPS_FEATURE_NOT_NEGOTIATED) + return FALSE; - switch (feature) { + switch (feature) { #if (USE_GLX || USE_EGL) case GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META: - if (decode->has_texture_upload_meta) - features = gst_caps_features_new( - GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL); - else - format = GST_VIDEO_FORMAT_I420; - break; + if (decode->has_texture_upload_meta) + features = + gst_caps_features_new + (GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL); + else + format = GST_VIDEO_FORMAT_I420; + break; #endif #if GST_CHECK_VERSION(1,5,0) case GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE: - features = gst_caps_features_new( - GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, NULL); - break; + features = + gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, NULL); + break; #endif default: - break; - } + break; + } #endif - state = gst_video_decoder_set_output_state(vdec, format, - ref_state->info.width, ref_state->info.height, - (GstVideoCodecState *)ref_state); - if (!state || state->info.width == 0 || state->info.height == 0) - return FALSE; + state = gst_video_decoder_set_output_state (vdec, format, + ref_state->info.width, ref_state->info.height, + (GstVideoCodecState *) ref_state); + if (!state || state->info.width == 0 || state->info.height == 0) + return FALSE; - vi = &state->info; + vi = &state->info; #if GST_CHECK_VERSION(1,1,0) - state->caps = gst_video_info_to_caps(vi); - if (features) - gst_caps_set_features(state->caps, 0, features); + state->caps = gst_video_info_to_caps (vi); + if (features) + gst_caps_set_features (state->caps, 0, features); #else - /* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not - reconstruct suitable caps for "encoded" video formats */ - state->caps = gst_caps_from_string(GST_VAAPI_SURFACE_CAPS_NAME); - if (!state->caps) - return FALSE; + /* XXX: gst_video_info_to_caps() from GStreamer 0.10 does not + reconstruct suitable caps for "encoded" video formats */ + state->caps = gst_caps_from_string (GST_VAAPI_SURFACE_CAPS_NAME); + 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, vi->width, - "height", G_TYPE_INT, vi->height, - "framerate", GST_TYPE_FRACTION, vi->fps_n, vi->fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, vi->par_n, vi->par_d, - NULL); + gst_caps_set_simple (state->caps, + "type", G_TYPE_STRING, "vaapi", + "opengl", G_TYPE_BOOLEAN, USE_GLX, + "width", G_TYPE_INT, vi->width, + "height", G_TYPE_INT, vi->height, + "framerate", GST_TYPE_FRACTION, vi->fps_n, vi->fps_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, vi->par_n, vi->par_d, NULL); - gst_caps_set_interlaced(state->caps, vi); + gst_caps_set_interlaced (state->caps, vi); #endif - gst_caps_replace(&decode->srcpad_caps, state->caps); - gst_video_codec_state_unref(state); - return TRUE; + gst_caps_replace (&decode->srcpad_caps, state->caps); + gst_video_codec_state_unref (state); + return TRUE; } static void -gst_vaapidecode_release(GstVaapiDecode *decode) +gst_vaapidecode_release (GstVaapiDecode * decode) { - g_mutex_lock(&decode->surface_ready_mutex); - g_cond_signal(&decode->surface_ready); - g_mutex_unlock(&decode->surface_ready_mutex); + g_mutex_lock (&decode->surface_ready_mutex); + g_cond_signal (&decode->surface_ready); + g_mutex_unlock (&decode->surface_ready_mutex); } static GstFlowReturn -gst_vaapidecode_push_decoded_frame(GstVideoDecoder *vdec, - GstVideoCodecFrame *out_frame) +gst_vaapidecode_push_decoded_frame (GstVideoDecoder * vdec, + GstVideoCodecFrame * out_frame) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - GstVaapiSurfaceProxy *proxy; - GstFlowReturn ret; + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + GstVaapiSurfaceProxy *proxy; + GstFlowReturn ret; #if GST_CHECK_VERSION(1,0,0) - const GstVaapiRectangle *crop_rect; - GstVaapiVideoMeta *meta; - guint flags; + const GstVaapiRectangle *crop_rect; + GstVaapiVideoMeta *meta; + guint flags; #endif - if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY(out_frame)) { - proxy = gst_video_codec_frame_get_user_data(out_frame); + if (!GST_VIDEO_CODEC_FRAME_IS_DECODE_ONLY (out_frame)) { + proxy = gst_video_codec_frame_get_user_data (out_frame); - gst_vaapi_surface_proxy_set_destroy_notify(proxy, - (GDestroyNotify)gst_vaapidecode_release, decode); + gst_vaapi_surface_proxy_set_destroy_notify (proxy, + (GDestroyNotify) gst_vaapidecode_release, decode); #if GST_CHECK_VERSION(1,0,0) - ret = gst_video_decoder_allocate_output_frame(vdec, out_frame); - if (ret != GST_FLOW_OK) - goto error_create_buffer; + ret = gst_video_decoder_allocate_output_frame (vdec, out_frame); + if (ret != GST_FLOW_OK) + goto error_create_buffer; - meta = gst_buffer_get_vaapi_video_meta(out_frame->output_buffer); - if (!meta) - goto error_get_meta; - gst_vaapi_video_meta_set_surface_proxy(meta, proxy); + meta = gst_buffer_get_vaapi_video_meta (out_frame->output_buffer); + if (!meta) + goto error_get_meta; + gst_vaapi_video_meta_set_surface_proxy (meta, proxy); - flags = gst_vaapi_surface_proxy_get_flags(proxy); - if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) { - guint out_flags = GST_VIDEO_BUFFER_FLAG_INTERLACED; - if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_TFF) - out_flags |= GST_VIDEO_BUFFER_FLAG_TFF; - if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_RFF) - out_flags |= GST_VIDEO_BUFFER_FLAG_RFF; - if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD) - out_flags |= GST_VIDEO_BUFFER_FLAG_ONEFIELD; - GST_BUFFER_FLAG_SET(out_frame->output_buffer, out_flags); - } - - crop_rect = gst_vaapi_surface_proxy_get_crop_rect(proxy); - if (crop_rect) { - GstVideoCropMeta * const crop_meta = - gst_buffer_add_video_crop_meta(out_frame->output_buffer); - if (crop_meta) { - crop_meta->x = crop_rect->x; - crop_meta->y = crop_rect->y; - crop_meta->width = crop_rect->width; - crop_meta->height = crop_rect->height; - } - } + flags = gst_vaapi_surface_proxy_get_flags (proxy); + if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_INTERLACED) { + guint out_flags = GST_VIDEO_BUFFER_FLAG_INTERLACED; + if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_TFF) + out_flags |= GST_VIDEO_BUFFER_FLAG_TFF; + if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_RFF) + out_flags |= GST_VIDEO_BUFFER_FLAG_RFF; + if (flags & GST_VAAPI_SURFACE_PROXY_FLAG_ONEFIELD) + out_flags |= GST_VIDEO_BUFFER_FLAG_ONEFIELD; + GST_BUFFER_FLAG_SET (out_frame->output_buffer, out_flags); + } + crop_rect = gst_vaapi_surface_proxy_get_crop_rect (proxy); + if (crop_rect) { + GstVideoCropMeta *const crop_meta = + gst_buffer_add_video_crop_meta (out_frame->output_buffer); + if (crop_meta) { + crop_meta->x = crop_rect->x; + crop_meta->y = crop_rect->y; + crop_meta->width = crop_rect->width; + crop_meta->height = crop_rect->height; + } + } #if GST_CHECK_VERSION(1,1,0) && (USE_GLX || USE_EGL) - if (decode->has_texture_upload_meta) - gst_buffer_ensure_texture_upload_meta(out_frame->output_buffer); + if (decode->has_texture_upload_meta) + gst_buffer_ensure_texture_upload_meta (out_frame->output_buffer); #endif #else - out_frame->output_buffer = - gst_vaapi_video_buffer_new_with_surface_proxy(proxy); - if (!out_frame->output_buffer) - goto error_create_buffer; + out_frame->output_buffer = + gst_vaapi_video_buffer_new_with_surface_proxy (proxy); + if (!out_frame->output_buffer) + goto error_create_buffer; #endif - } + } - ret = gst_video_decoder_finish_frame(vdec, out_frame); - if (ret != GST_FLOW_OK) - goto error_commit_buffer; + ret = gst_video_decoder_finish_frame (vdec, out_frame); + if (ret != GST_FLOW_OK) + goto error_commit_buffer; - gst_video_codec_frame_unref(out_frame); - return GST_FLOW_OK; + gst_video_codec_frame_unref (out_frame); + return GST_FLOW_OK; - /* ERRORS */ + /* ERRORS */ error_create_buffer: - { - const GstVaapiID surface_id = - gst_vaapi_surface_get_id(GST_VAAPI_SURFACE_PROXY_SURFACE(proxy)); + { + const GstVaapiID surface_id = + gst_vaapi_surface_get_id (GST_VAAPI_SURFACE_PROXY_SURFACE (proxy)); - GST_ELEMENT_ERROR(vdec, STREAM, FAILED, - ("Failed to create sink buffer"), - ("video sink failed to create video buffer for proxy'ed " - "surface %" GST_VAAPI_ID_FORMAT, - GST_VAAPI_ID_ARGS(surface_id))); - gst_video_decoder_drop_frame(vdec, out_frame); - gst_video_codec_frame_unref(out_frame); - return GST_FLOW_ERROR; - } + GST_ELEMENT_ERROR (vdec, STREAM, FAILED, + ("Failed to create sink buffer"), + ("video sink failed to create video buffer for proxy'ed " + "surface %" GST_VAAPI_ID_FORMAT, GST_VAAPI_ID_ARGS (surface_id))); + gst_video_decoder_drop_frame (vdec, out_frame); + gst_video_codec_frame_unref (out_frame); + return GST_FLOW_ERROR; + } #if GST_CHECK_VERSION(1,0,0) error_get_meta: - { - GST_ELEMENT_ERROR(vdec, STREAM, FAILED, - ("Failed to get vaapi video meta attached to video buffer"), - ("Failed to get vaapi video meta attached to video buffer")); - gst_video_decoder_drop_frame(vdec, out_frame); - gst_video_codec_frame_unref(out_frame); - return GST_FLOW_ERROR; - } + { + GST_ELEMENT_ERROR (vdec, STREAM, FAILED, + ("Failed to get vaapi video meta attached to video buffer"), + ("Failed to get vaapi video meta attached to video buffer")); + gst_video_decoder_drop_frame (vdec, out_frame); + gst_video_codec_frame_unref (out_frame); + return GST_FLOW_ERROR; + } #endif error_commit_buffer: - { - if (ret != GST_FLOW_FLUSHING) - GST_ERROR("video sink rejected the video buffer (error: %s [%d])", - gst_flow_get_name (ret), ret); - gst_video_codec_frame_unref(out_frame); - return ret; - } + { + if (ret != GST_FLOW_FLUSHING) + GST_ERROR ("video sink rejected the video buffer (error: %s [%d])", + gst_flow_get_name (ret), ret); + gst_video_codec_frame_unref (out_frame); + return ret; + } } static GstFlowReturn -gst_vaapidecode_push_all_decoded_frames(GstVaapiDecode *decode) +gst_vaapidecode_push_all_decoded_frames (GstVaapiDecode * decode) { - GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode); - GstVaapiDecoderStatus status; - GstVideoCodecFrame *out_frame; - GstFlowReturn ret; + GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode); + GstVaapiDecoderStatus status; + GstVideoCodecFrame *out_frame; + GstFlowReturn ret; - for (;;) { - status = gst_vaapi_decoder_get_frame(decode->decoder, &out_frame); + for (;;) { + status = gst_vaapi_decoder_get_frame (decode->decoder, &out_frame); - switch (status) { - case GST_VAAPI_DECODER_STATUS_SUCCESS: - ret = gst_vaapidecode_push_decoded_frame(vdec, out_frame); - if (ret != GST_FLOW_OK) - return ret; - break; - case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA: - return GST_FLOW_OK; - default: - GST_ELEMENT_ERROR (vdec, STREAM, DECODE, ("Decoding failed"), - ("Unknown decoding error")); - return GST_FLOW_ERROR; - } + switch (status) { + case GST_VAAPI_DECODER_STATUS_SUCCESS: + ret = gst_vaapidecode_push_decoded_frame (vdec, out_frame); + if (ret != GST_FLOW_OK) + return ret; + break; + case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA: + return GST_FLOW_OK; + default: + GST_ELEMENT_ERROR (vdec, STREAM, DECODE, ("Decoding failed"), + ("Unknown decoding error")); + return GST_FLOW_ERROR; } - g_assert_not_reached(); + } + g_assert_not_reached (); } static GstFlowReturn -gst_vaapidecode_handle_frame(GstVideoDecoder *vdec, GstVideoCodecFrame *frame) +gst_vaapidecode_handle_frame (GstVideoDecoder * vdec, + GstVideoCodecFrame * frame) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - GstVaapiDecoderStatus status; - GstFlowReturn ret; + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + GstVaapiDecoderStatus status; + GstFlowReturn ret; - if (!decode->input_state) - goto not_negotiated; + if (!decode->input_state) + goto not_negotiated; - if (G_UNLIKELY(!decode->active) || - gst_pad_needs_reconfigure(GST_VIDEO_DECODER_SRC_PAD(vdec))) { - GST_DEBUG_OBJECT(decode, "activating the decoder"); - if (!gst_vaapidecode_update_src_caps(decode)) - goto not_negotiated; + if (G_UNLIKELY (!decode->active) || + gst_pad_needs_reconfigure (GST_VIDEO_DECODER_SRC_PAD (vdec))) { + GST_DEBUG_OBJECT (decode, "activating the decoder"); + if (!gst_vaapidecode_update_src_caps (decode)) + goto not_negotiated; - if (!gst_video_decoder_negotiate(vdec)) - goto not_negotiated; + if (!gst_video_decoder_negotiate (vdec)) + goto not_negotiated; - GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(vdec); - if (!gst_vaapi_plugin_base_set_caps(plugin, NULL, decode->srcpad_caps)) - goto not_negotiated; + GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (vdec); + if (!gst_vaapi_plugin_base_set_caps (plugin, NULL, decode->srcpad_caps)) + goto not_negotiated; - decode->active = TRUE; + decode->active = TRUE; + } + + /* Decode current frame */ + for (;;) { + status = gst_vaapi_decoder_decode (decode->decoder, frame); + if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) { + /* Make sure that there are no decoded frames waiting in the + output queue. */ + ret = gst_vaapidecode_push_all_decoded_frames (decode); + if (ret != GST_FLOW_OK) + goto error_push_all_decoded_frames; + + g_mutex_lock (&decode->surface_ready_mutex); + if (gst_vaapi_decoder_check_status (decode->decoder) == + GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) + g_cond_wait (&decode->surface_ready, &decode->surface_ready_mutex); + g_mutex_unlock (&decode->surface_ready_mutex); + continue; } + if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) + goto error_decode; + break; + } - /* Decode current frame */ - for (;;) { - status = gst_vaapi_decoder_decode(decode->decoder, frame); - if (status == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) { - /* Make sure that there are no decoded frames waiting in the - output queue. */ - ret = gst_vaapidecode_push_all_decoded_frames(decode); - if (ret != GST_FLOW_OK) - goto error_push_all_decoded_frames; + /* Note that gst_vaapi_decoder_decode cannot return success without + completing the decode and pushing all decoded frames into the output + queue */ + ret = gst_vaapidecode_push_all_decoded_frames (decode); + if (ret != GST_FLOW_OK && ret != GST_FLOW_FLUSHING) + GST_ERROR ("push loop error after decoding %d", ret); + return ret; - g_mutex_lock(&decode->surface_ready_mutex); - if (gst_vaapi_decoder_check_status (decode->decoder) == GST_VAAPI_DECODER_STATUS_ERROR_NO_SURFACE) - g_cond_wait(&decode->surface_ready, &decode->surface_ready_mutex); - g_mutex_unlock(&decode->surface_ready_mutex); - continue; - } - if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) - goto error_decode; + /* ERRORS */ +error_push_all_decoded_frames: + { + GST_ERROR ("push loop error while decoding %d", ret); + gst_video_decoder_drop_frame (vdec, frame); + return ret; + } +error_decode: + { + GST_ERROR ("decode error %d", status); + switch (status) { + 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: + ret = GST_FLOW_NOT_SUPPORTED; + break; + default: + GST_ELEMENT_ERROR (vdec, STREAM, DECODE, ("Decoding error"), + ("Decode error %d", status)); + ret = GST_FLOW_ERROR; break; } - - /* Note that gst_vaapi_decoder_decode cannot return success without - completing the decode and pushing all decoded frames into the output - queue */ - ret = gst_vaapidecode_push_all_decoded_frames(decode); - if (ret != GST_FLOW_OK && ret != GST_FLOW_FLUSHING) - GST_ERROR("push loop error after decoding %d", ret); + gst_video_decoder_drop_frame (vdec, frame); return ret; - - /* ERRORS */ -error_push_all_decoded_frames: - { - GST_ERROR("push loop error while decoding %d", ret); - gst_video_decoder_drop_frame(vdec, frame); - return ret; - } -error_decode: - { - GST_ERROR("decode error %d", status); - switch (status) { - 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: - ret = GST_FLOW_NOT_SUPPORTED; - break; - default: - GST_ELEMENT_ERROR (vdec, STREAM, DECODE, ("Decoding error"), - ("Decode error %d", status)); - ret = GST_FLOW_ERROR; - break; - } - gst_video_decoder_drop_frame(vdec, frame); - return ret; - } + } not_negotiated: - { - GST_ERROR_OBJECT (decode, "not negotiated"); - ret = GST_FLOW_NOT_NEGOTIATED; - gst_video_decoder_drop_frame (vdec, frame); - return ret; - } + { + GST_ERROR_OBJECT (decode, "not negotiated"); + ret = GST_FLOW_NOT_NEGOTIATED; + gst_video_decoder_drop_frame (vdec, frame); + return ret; + } } static gboolean -gst_vaapidecode_flush(GstVideoDecoder *vdec) +gst_vaapidecode_flush (GstVideoDecoder * vdec) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - GstVaapiDecoderStatus status; + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + GstVaapiDecoderStatus status; - if (!decode->decoder) - return TRUE; - - /* If there is something in GstVideoDecoder's output adapter, then - submit the frame for decoding */ - if (decode->current_frame_size) { - gst_video_decoder_have_frame(vdec); - decode->current_frame_size = 0; - } - - status = gst_vaapi_decoder_flush(decode->decoder); - if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) - goto error_flush; + if (!decode->decoder) return TRUE; - /* ERRORS */ + /* If there is something in GstVideoDecoder's output adapter, then + submit the frame for decoding */ + if (decode->current_frame_size) { + gst_video_decoder_have_frame (vdec); + decode->current_frame_size = 0; + } + + status = gst_vaapi_decoder_flush (decode->decoder); + if (status != GST_VAAPI_DECODER_STATUS_SUCCESS) + goto error_flush; + return TRUE; + + /* ERRORS */ error_flush: - { - GST_ERROR("failed to flush decoder (status %d)", status); - return FALSE; - } + { + GST_ERROR ("failed to flush decoder (status %d)", status); + return FALSE; + } } static GstFlowReturn -gst_vaapidecode_finish(GstVideoDecoder *vdec) +gst_vaapidecode_finish (GstVideoDecoder * vdec) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - GstFlowReturn ret = GST_FLOW_OK; + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + GstFlowReturn ret = GST_FLOW_OK; - if (!decode->decoder) - return GST_FLOW_OK; + if (!decode->decoder) + return GST_FLOW_OK; - if (!gst_vaapidecode_flush(vdec)) { - gst_vaapidecode_push_all_decoded_frames(decode); - return GST_FLOW_ERROR; - } + if (!gst_vaapidecode_flush (vdec)) { + gst_vaapidecode_push_all_decoded_frames (decode); + return GST_FLOW_ERROR; + } - return gst_vaapidecode_push_all_decoded_frames(decode); + return gst_vaapidecode_push_all_decoded_frames (decode); } #if GST_CHECK_VERSION(1,0,0) static gboolean -gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query) +gst_vaapidecode_decide_allocation (GstVideoDecoder * vdec, GstQuery * query) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - GstCaps *caps = NULL; - GstVideoCodecState *state; - GstVaapiCapsFeature feature; - GstVideoFormat out_format; + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + GstCaps *caps = NULL; + GstVideoCodecState *state; + GstVaapiCapsFeature feature; + GstVideoFormat out_format; - gst_query_parse_allocation(query, &caps, NULL); + gst_query_parse_allocation (query, &caps, NULL); - feature = - gst_vaapi_find_preferred_caps_feature(GST_VIDEO_DECODER_SRC_PAD(vdec), - GST_VIDEO_FORMAT_ENCODED, &out_format); - decode->has_texture_upload_meta = FALSE; + feature = + gst_vaapi_find_preferred_caps_feature (GST_VIDEO_DECODER_SRC_PAD (vdec), + GST_VIDEO_FORMAT_ENCODED, &out_format); + decode->has_texture_upload_meta = FALSE; #if GST_CHECK_VERSION(1,1,0) && (USE_GLX || USE_EGL) - decode->has_texture_upload_meta = - (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META) && - gst_query_find_allocation_meta (query, - GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL); + decode->has_texture_upload_meta = + (feature == GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META) && + gst_query_find_allocation_meta (query, + GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL); #endif - /* Update src caps if feature is not handled downstream */ - state = gst_video_decoder_get_output_state(vdec); - if (!gst_caps_is_always_compatible(caps, state->caps)) - gst_vaapidecode_update_src_caps(decode); - gst_video_codec_state_unref(state); + /* Update src caps if feature is not handled downstream */ + state = gst_video_decoder_get_output_state (vdec); + if (!gst_caps_is_always_compatible (caps, state->caps)) + gst_vaapidecode_update_src_caps (decode); + gst_video_codec_state_unref (state); - return gst_vaapi_plugin_base_decide_allocation(GST_VAAPI_PLUGIN_BASE(vdec), - query, feature); + return gst_vaapi_plugin_base_decide_allocation (GST_VAAPI_PLUGIN_BASE (vdec), + query, feature); } #endif static inline gboolean -gst_vaapidecode_ensure_display(GstVaapiDecode *decode) +gst_vaapidecode_ensure_display (GstVaapiDecode * decode) { - return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(decode)); + return gst_vaapi_plugin_base_ensure_display (GST_VAAPI_PLUGIN_BASE (decode)); } static inline guint -gst_vaapi_codec_from_caps(GstCaps *caps) +gst_vaapi_codec_from_caps (GstCaps * caps) { - return gst_vaapi_profile_get_codec(gst_vaapi_profile_from_caps(caps)); + return gst_vaapi_profile_get_codec (gst_vaapi_profile_from_caps (caps)); } static gboolean -gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps) +gst_vaapidecode_create (GstVaapiDecode * decode, GstCaps * caps) { - GstVaapiDisplay *dpy; + GstVaapiDisplay *dpy; - if (!gst_vaapidecode_ensure_display(decode)) - return FALSE; - dpy = GST_VAAPI_PLUGIN_BASE_DISPLAY(decode); + if (!gst_vaapidecode_ensure_display (decode)) + return FALSE; + dpy = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode); - switch (gst_vaapi_codec_from_caps(caps)) { + switch (gst_vaapi_codec_from_caps (caps)) { case GST_VAAPI_CODEC_MPEG2: - decode->decoder = gst_vaapi_decoder_mpeg2_new(dpy, caps); - break; + decode->decoder = gst_vaapi_decoder_mpeg2_new (dpy, caps); + break; case GST_VAAPI_CODEC_MPEG4: case GST_VAAPI_CODEC_H263: - decode->decoder = gst_vaapi_decoder_mpeg4_new(dpy, caps); - break; + decode->decoder = gst_vaapi_decoder_mpeg4_new (dpy, caps); + break; case GST_VAAPI_CODEC_H264: - decode->decoder = gst_vaapi_decoder_h264_new(dpy, caps); + decode->decoder = gst_vaapi_decoder_h264_new (dpy, caps); - /* Set the stream buffer alignment for better optimizations */ - if (decode->decoder && caps) { - GstStructure * const structure = gst_caps_get_structure(caps, 0); - const gchar *str = NULL; + /* Set the stream buffer alignment for better optimizations */ + if (decode->decoder && caps) { + GstStructure *const structure = gst_caps_get_structure (caps, 0); + const gchar *str = NULL; - if ((str = gst_structure_get_string(structure, "alignment"))) { - GstVaapiStreamAlignH264 alignment; - if (g_strcmp0(str, "au") == 0) - alignment = GST_VAAPI_STREAM_ALIGN_H264_AU; - else if (g_strcmp0(str, "nal") == 0) - alignment = GST_VAAPI_STREAM_ALIGN_H264_NALU; - else - alignment = GST_VAAPI_STREAM_ALIGN_H264_NONE; - gst_vaapi_decoder_h264_set_alignment( - GST_VAAPI_DECODER_H264(decode->decoder), alignment); - } + if ((str = gst_structure_get_string (structure, "alignment"))) { + GstVaapiStreamAlignH264 alignment; + if (g_strcmp0 (str, "au") == 0) + alignment = GST_VAAPI_STREAM_ALIGN_H264_AU; + else if (g_strcmp0 (str, "nal") == 0) + alignment = GST_VAAPI_STREAM_ALIGN_H264_NALU; + else + alignment = GST_VAAPI_STREAM_ALIGN_H264_NONE; + gst_vaapi_decoder_h264_set_alignment (GST_VAAPI_DECODER_H264 (decode-> + decoder), alignment); } - break; + } + break; case GST_VAAPI_CODEC_WMV3: case GST_VAAPI_CODEC_VC1: - decode->decoder = gst_vaapi_decoder_vc1_new(dpy, caps); - break; + decode->decoder = gst_vaapi_decoder_vc1_new (dpy, caps); + break; #if USE_JPEG_DECODER case GST_VAAPI_CODEC_JPEG: - decode->decoder = gst_vaapi_decoder_jpeg_new(dpy, caps); - break; + decode->decoder = gst_vaapi_decoder_jpeg_new (dpy, caps); + break; #endif #if USE_VP8_DECODER case GST_VAAPI_CODEC_VP8: - decode->decoder = gst_vaapi_decoder_vp8_new(dpy, caps); - break; + decode->decoder = gst_vaapi_decoder_vp8_new (dpy, caps); + break; #endif default: - decode->decoder = NULL; - break; - } - if (!decode->decoder) - return FALSE; + decode->decoder = NULL; + break; + } + if (!decode->decoder) + return FALSE; - gst_vaapi_decoder_set_codec_state_changed_func(decode->decoder, - gst_vaapi_decoder_state_changed, decode); + gst_vaapi_decoder_set_codec_state_changed_func (decode->decoder, + gst_vaapi_decoder_state_changed, decode); - decode->decoder_caps = gst_caps_ref(caps); - return TRUE; + decode->decoder_caps = gst_caps_ref (caps); + return TRUE; } static void -gst_vaapidecode_destroy(GstVaapiDecode *decode) +gst_vaapidecode_destroy (GstVaapiDecode * decode) { - gst_vaapi_decoder_replace(&decode->decoder, NULL); - gst_caps_replace(&decode->decoder_caps, NULL); + gst_vaapi_decoder_replace (&decode->decoder, NULL); + gst_caps_replace (&decode->decoder_caps, NULL); - decode->active = FALSE; + decode->active = FALSE; - gst_vaapidecode_release(decode); + gst_vaapidecode_release (decode); } static gboolean -gst_vaapidecode_reset_full(GstVaapiDecode *decode, GstCaps *caps, gboolean hard) +gst_vaapidecode_reset_full (GstVaapiDecode * decode, GstCaps * caps, + gboolean hard) { - GstVaapiCodec codec; + GstVaapiCodec codec; - decode->has_texture_upload_meta = FALSE; + decode->has_texture_upload_meta = FALSE; - /* Reset tracked frame size */ - decode->current_frame_size = 0; + /* Reset tracked frame size */ + decode->current_frame_size = 0; - /* Reset timers if hard reset was requested (e.g. seek) */ - if (hard) { - GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode); - GstVideoCodecFrame *out_frame = NULL; + /* Reset timers if hard reset was requested (e.g. seek) */ + if (hard) { + GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode); + GstVideoCodecFrame *out_frame = NULL; - gst_vaapi_decoder_flush(decode->decoder); + gst_vaapi_decoder_flush (decode->decoder); - /* Purge all decoded frames as we don't need them (e.g. seek) */ - while (gst_vaapi_decoder_get_frame_with_timeout(decode->decoder, - &out_frame, 0) == GST_VAAPI_DECODER_STATUS_SUCCESS) { - gst_video_codec_frame_unref(out_frame); - out_frame = NULL; - } + /* Purge all decoded frames as we don't need them (e.g. seek) */ + while (gst_vaapi_decoder_get_frame_with_timeout (decode->decoder, + &out_frame, 0) == GST_VAAPI_DECODER_STATUS_SUCCESS) { + gst_video_codec_frame_unref (out_frame); + out_frame = NULL; } + } - /* Only reset decoder if codec type changed */ - else if (decode->decoder && decode->decoder_caps) { - if (gst_caps_is_always_compatible(caps, decode->decoder_caps)) - return TRUE; - codec = gst_vaapi_codec_from_caps(caps); - if (codec == gst_vaapi_decoder_get_codec(decode->decoder)) - return TRUE; - } + /* Only reset decoder if codec type changed */ + else if (decode->decoder && decode->decoder_caps) { + if (gst_caps_is_always_compatible (caps, decode->decoder_caps)) + return TRUE; + codec = gst_vaapi_codec_from_caps (caps); + if (codec == gst_vaapi_decoder_get_codec (decode->decoder)) + return TRUE; + } - gst_vaapidecode_destroy(decode); - return gst_vaapidecode_create(decode, caps); + gst_vaapidecode_destroy (decode); + return gst_vaapidecode_create (decode, caps); } static void -gst_vaapidecode_finalize(GObject *object) +gst_vaapidecode_finalize (GObject * object) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(object); + GstVaapiDecode *const decode = GST_VAAPIDECODE (object); - gst_caps_replace(&decode->sinkpad_caps, NULL); - gst_caps_replace(&decode->srcpad_caps, NULL); - gst_caps_replace(&decode->allowed_caps, NULL); + gst_caps_replace (&decode->sinkpad_caps, NULL); + gst_caps_replace (&decode->srcpad_caps, NULL); + gst_caps_replace (&decode->allowed_caps, NULL); - g_cond_clear(&decode->surface_ready); - g_mutex_clear(&decode->surface_ready_mutex); + g_cond_clear (&decode->surface_ready); + g_mutex_clear (&decode->surface_ready_mutex); - gst_vaapi_plugin_base_finalize(GST_VAAPI_PLUGIN_BASE(object)); - G_OBJECT_CLASS(gst_vaapidecode_parent_class)->finalize(object); + gst_vaapi_plugin_base_finalize (GST_VAAPI_PLUGIN_BASE (object)); + G_OBJECT_CLASS (gst_vaapidecode_parent_class)->finalize (object); } static gboolean -gst_vaapidecode_open(GstVideoDecoder *vdec) +gst_vaapidecode_open (GstVideoDecoder * vdec) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - GstVaapiDisplay * const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY(decode); - gboolean success; + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + GstVaapiDisplay *const old_display = GST_VAAPI_PLUGIN_BASE_DISPLAY (decode); + gboolean success; - if (!gst_vaapi_plugin_base_open(GST_VAAPI_PLUGIN_BASE(decode))) - return FALSE; + if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (decode))) + return FALSE; - /* Let GstVideoContext ask for a proper display to its neighbours */ - /* Note: steal old display that may be allocated from get_caps() - so that to retain a reference to it, thus avoiding extra - initialization steps if we turn out to simply re-use the - existing (cached) VA display */ - GST_VAAPI_PLUGIN_BASE_DISPLAY(decode) = NULL; - success = gst_vaapidecode_ensure_display(decode); - if (old_display) - gst_vaapi_display_unref(old_display); - return success; + /* Let GstVideoContext ask for a proper display to its neighbours */ + /* Note: steal old display that may be allocated from get_caps() + so that to retain a reference to it, thus avoiding extra + initialization steps if we turn out to simply re-use the + existing (cached) VA display */ + GST_VAAPI_PLUGIN_BASE_DISPLAY (decode) = NULL; + success = gst_vaapidecode_ensure_display (decode); + if (old_display) + gst_vaapi_display_unref (old_display); + return success; } static gboolean -gst_vaapidecode_close(GstVideoDecoder *vdec) +gst_vaapidecode_close (GstVideoDecoder * vdec) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); - gst_vaapi_decode_input_state_replace(decode, NULL); - gst_vaapidecode_destroy(decode); - gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(decode)); + gst_vaapi_decode_input_state_replace (decode, NULL); + gst_vaapidecode_destroy (decode); + gst_vaapi_plugin_base_close (GST_VAAPI_PLUGIN_BASE (decode)); + return TRUE; +} + +static gboolean +gst_vaapidecode_reset (GstVideoDecoder * vdec, gboolean hard) +{ + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + + /* In GStreamer 1.0 context, this means a flush */ + if (decode->decoder && !hard && !gst_vaapidecode_flush (vdec)) + return FALSE; + return gst_vaapidecode_reset_full (decode, decode->sinkpad_caps, hard); +} + +static gboolean +gst_vaapidecode_set_format (GstVideoDecoder * vdec, GstVideoCodecState * state) +{ + GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (vdec); + GstVaapiDecode *const decode = GST_VAAPIDECODE (vdec); + + if (!gst_vaapi_decode_input_state_replace (decode, state)) return TRUE; -} + if (!gst_vaapidecode_update_sink_caps (decode, state->caps)) + return FALSE; + if (!gst_vaapi_plugin_base_set_caps (plugin, decode->sinkpad_caps, NULL)) + return FALSE; + if (!gst_vaapidecode_reset_full (decode, decode->sinkpad_caps, FALSE)) + return FALSE; -static gboolean -gst_vaapidecode_reset(GstVideoDecoder *vdec, gboolean hard) -{ - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - - /* In GStreamer 1.0 context, this means a flush */ - if (decode->decoder && !hard && !gst_vaapidecode_flush(vdec)) - return FALSE; - return gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, hard); -} - -static gboolean -gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state) -{ - GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(vdec); - GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec); - - if (!gst_vaapi_decode_input_state_replace(decode, state)) - return TRUE; - if (!gst_vaapidecode_update_sink_caps(decode, state->caps)) - return FALSE; - if (!gst_vaapi_plugin_base_set_caps(plugin, decode->sinkpad_caps, NULL)) - return FALSE; - if (!gst_vaapidecode_reset_full(decode, decode->sinkpad_caps, FALSE)) - return FALSE; - - return TRUE; + return TRUE; } static GstFlowReturn -gst_vaapidecode_parse_frame(GstVideoDecoder *vdec, - GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos) +gst_vaapidecode_parse_frame (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; + 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); + status = gst_vaapi_decoder_parse (decode->decoder, frame, + adapter, at_eos, &got_unit_size, &got_frame); - switch (status) { + switch (status) { case GST_VAAPI_DECODER_STATUS_SUCCESS: - if (got_unit_size > 0) { - gst_video_decoder_add_to_frame(vdec, got_unit_size); - decode->current_frame_size += got_unit_size; - } - if (got_frame) { - ret = gst_video_decoder_have_frame(vdec); - decode->current_frame_size = 0; - } - else - ret = GST_VAAPI_DECODE_FLOW_PARSE_DATA; - break; + if (got_unit_size > 0) { + gst_video_decoder_add_to_frame (vdec, got_unit_size); + decode->current_frame_size += got_unit_size; + } + if (got_frame) { + ret = gst_video_decoder_have_frame (vdec); + decode->current_frame_size = 0; + } else + ret = GST_VAAPI_DECODE_FLOW_PARSE_DATA; + break; case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA: - ret = GST_VIDEO_DECODER_FLOW_NEED_DATA; - break; + ret = GST_VIDEO_DECODER_FLOW_NEED_DATA; + break; 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; - decode->current_frame_size = 0; - break; + GST_WARNING ("parse error %d", status); + ret = GST_FLOW_NOT_SUPPORTED; + decode->current_frame_size = 0; + break; default: - GST_ERROR("parse error %d", status); - ret = GST_FLOW_EOS; - decode->current_frame_size = 0; - break; - } - return ret; + GST_ERROR ("parse error %d", status); + ret = GST_FLOW_EOS; + decode->current_frame_size = 0; + break; + } + return ret; } static GstFlowReturn -gst_vaapidecode_parse(GstVideoDecoder *vdec, - GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos) +gst_vaapidecode_parse (GstVideoDecoder * vdec, + GstVideoCodecFrame * frame, GstAdapter * adapter, gboolean at_eos) { - GstFlowReturn ret; + GstFlowReturn ret; - do { - ret = gst_vaapidecode_parse_frame(vdec, frame, adapter, at_eos); - } while (ret == GST_VAAPI_DECODE_FLOW_PARSE_DATA); - return ret; + do { + ret = gst_vaapidecode_parse_frame (vdec, frame, adapter, at_eos); + } while (ret == GST_VAAPI_DECODE_FLOW_PARSE_DATA); + return ret; } static void -gst_vaapidecode_class_init(GstVaapiDecodeClass *klass) +gst_vaapidecode_class_init (GstVaapiDecodeClass * klass) { - GObjectClass * const object_class = G_OBJECT_CLASS(klass); - GstElementClass * const element_class = GST_ELEMENT_CLASS(klass); - GstVideoDecoderClass * const vdec_class = GST_VIDEO_DECODER_CLASS(klass); - GstPadTemplate *pad_template; + GObjectClass *const object_class = G_OBJECT_CLASS (klass); + GstElementClass *const element_class = GST_ELEMENT_CLASS (klass); + GstVideoDecoderClass *const vdec_class = GST_VIDEO_DECODER_CLASS (klass); + GstPadTemplate *pad_template; - GST_DEBUG_CATEGORY_INIT(gst_debug_vaapidecode, - GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC); + GST_DEBUG_CATEGORY_INIT (gst_debug_vaapidecode, + GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC); - gst_vaapi_plugin_base_class_init(GST_VAAPI_PLUGIN_BASE_CLASS(klass)); + gst_vaapi_plugin_base_class_init (GST_VAAPI_PLUGIN_BASE_CLASS (klass)); - object_class->finalize = gst_vaapidecode_finalize; + object_class->finalize = gst_vaapidecode_finalize; - 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->reset = GST_DEBUG_FUNCPTR(gst_vaapidecode_reset); - vdec_class->parse = GST_DEBUG_FUNCPTR(gst_vaapidecode_parse); - vdec_class->handle_frame = GST_DEBUG_FUNCPTR(gst_vaapidecode_handle_frame); - vdec_class->finish = GST_DEBUG_FUNCPTR(gst_vaapidecode_finish); + 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->reset = GST_DEBUG_FUNCPTR (gst_vaapidecode_reset); + vdec_class->parse = GST_DEBUG_FUNCPTR (gst_vaapidecode_parse); + vdec_class->handle_frame = GST_DEBUG_FUNCPTR (gst_vaapidecode_handle_frame); + vdec_class->finish = GST_DEBUG_FUNCPTR (gst_vaapidecode_finish); #if GST_CHECK_VERSION(1,0,0) - vdec_class->decide_allocation = - GST_DEBUG_FUNCPTR(gst_vaapidecode_decide_allocation); + vdec_class->decide_allocation = + GST_DEBUG_FUNCPTR (gst_vaapidecode_decide_allocation); #endif - gst_element_class_set_static_metadata(element_class, - "VA-API decoder", - "Codec/Decoder/Video", - GST_PLUGIN_DESC, - "Gwenole Beauchesne "); + gst_element_class_set_static_metadata (element_class, + "VA-API decoder", + "Codec/Decoder/Video", + GST_PLUGIN_DESC, "Gwenole Beauchesne "); - /* sink pad */ - pad_template = gst_static_pad_template_get(&gst_vaapidecode_sink_factory); - gst_element_class_add_pad_template(element_class, pad_template); + /* sink pad */ + pad_template = gst_static_pad_template_get (&gst_vaapidecode_sink_factory); + gst_element_class_add_pad_template (element_class, pad_template); - /* src pad */ - pad_template = gst_static_pad_template_get(&gst_vaapidecode_src_factory); - gst_element_class_add_pad_template(element_class, pad_template); + /* src pad */ + pad_template = gst_static_pad_template_get (&gst_vaapidecode_src_factory); + gst_element_class_add_pad_template (element_class, pad_template); } static gboolean -gst_vaapidecode_ensure_allowed_caps(GstVaapiDecode *decode) +gst_vaapidecode_ensure_allowed_caps (GstVaapiDecode * decode) { - GstCaps *caps, *allowed_caps; - GArray *profiles; - guint i; + GstCaps *caps, *allowed_caps; + GArray *profiles; + guint i; - if (decode->allowed_caps) - return TRUE; - - if (!gst_vaapidecode_ensure_display(decode)) - goto error_no_display; - - profiles = gst_vaapi_display_get_decode_profiles( - GST_VAAPI_PLUGIN_BASE_DISPLAY(decode)); - if (!profiles) - goto error_no_profiles; - - allowed_caps = gst_caps_new_empty(); - if (!allowed_caps) - goto error_no_memory; - - for (i = 0; i < profiles->len; i++) { - const GstVaapiProfile profile = - g_array_index(profiles, GstVaapiProfile, i); - const gchar *media_type_name; - const gchar *profile_name; - GstStructure *structure; - - media_type_name = gst_vaapi_profile_get_media_type_name(profile); - if (!media_type_name) - continue; - - caps = gst_caps_from_string(media_type_name); - if (!caps) - continue; - structure = gst_caps_get_structure (caps, 0); - - profile_name = gst_vaapi_profile_get_name(profile); - if (profile_name) - gst_structure_set(structure, "profile", G_TYPE_STRING, - profile_name, NULL); - - allowed_caps = gst_caps_merge(allowed_caps, caps); - } - decode->allowed_caps = gst_caps_simplify (allowed_caps); - - g_array_unref(profiles); + if (decode->allowed_caps) return TRUE; - /* ERRORS */ + if (!gst_vaapidecode_ensure_display (decode)) + goto error_no_display; + + profiles = + gst_vaapi_display_get_decode_profiles (GST_VAAPI_PLUGIN_BASE_DISPLAY + (decode)); + if (!profiles) + goto error_no_profiles; + + allowed_caps = gst_caps_new_empty (); + if (!allowed_caps) + goto error_no_memory; + + for (i = 0; i < profiles->len; i++) { + const GstVaapiProfile profile = + g_array_index (profiles, GstVaapiProfile, i); + const gchar *media_type_name; + const gchar *profile_name; + GstStructure *structure; + + media_type_name = gst_vaapi_profile_get_media_type_name (profile); + if (!media_type_name) + continue; + + caps = gst_caps_from_string (media_type_name); + if (!caps) + continue; + structure = gst_caps_get_structure (caps, 0); + + profile_name = gst_vaapi_profile_get_name (profile); + if (profile_name) + gst_structure_set (structure, "profile", G_TYPE_STRING, + profile_name, NULL); + + allowed_caps = gst_caps_merge (allowed_caps, caps); + } + decode->allowed_caps = gst_caps_simplify (allowed_caps); + + g_array_unref (profiles); + return TRUE; + + /* ERRORS */ error_no_display: - { - GST_ERROR("failed to retrieve VA display"); - return FALSE; - } + { + GST_ERROR ("failed to retrieve VA display"); + return FALSE; + } error_no_profiles: - { - GST_ERROR("failed to retrieve VA decode profiles"); - return FALSE; - } + { + GST_ERROR ("failed to retrieve VA decode profiles"); + return FALSE; + } error_no_memory: - { - GST_ERROR("failed to allocate allowed-caps set"); - g_array_unref(profiles); - return FALSE; - } + { + GST_ERROR ("failed to allocate allowed-caps set"); + g_array_unref (profiles); + return FALSE; + } } static GstCaps * -gst_vaapidecode_get_caps(GstPad *pad) +gst_vaapidecode_get_caps (GstPad * pad) { - GstVaapiDecode * const decode = GST_VAAPIDECODE(GST_OBJECT_PARENT(pad)); + GstVaapiDecode *const decode = GST_VAAPIDECODE (GST_OBJECT_PARENT (pad)); - if (!gst_vaapidecode_ensure_allowed_caps(decode)) - return gst_caps_new_empty(); + if (!gst_vaapidecode_ensure_allowed_caps (decode)) + return gst_caps_new_empty (); - return gst_caps_ref(decode->allowed_caps); + return gst_caps_ref (decode->allowed_caps); } static gboolean -gst_vaapidecode_query(GST_PAD_QUERY_FUNCTION_ARGS) +gst_vaapidecode_query (GST_PAD_QUERY_FUNCTION_ARGS) { - GstVaapiDecode * const decode = - GST_VAAPIDECODE(gst_pad_get_parent_element(pad)); - GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(decode); - gboolean res; + GstVaapiDecode *const decode = + GST_VAAPIDECODE (gst_pad_get_parent_element (pad)); + GstVaapiPluginBase *const plugin = GST_VAAPI_PLUGIN_BASE (decode); + gboolean res; - GST_INFO_OBJECT(decode, "query type %s", GST_QUERY_TYPE_NAME(query)); + GST_INFO_OBJECT (decode, "query type %s", GST_QUERY_TYPE_NAME (query)); - if (gst_vaapi_reply_to_query(query, plugin->display)) { - GST_DEBUG("sharing display %p", plugin->display); + if (gst_vaapi_reply_to_query (query, plugin->display)) { + GST_DEBUG ("sharing display %p", plugin->display); + res = TRUE; + } else if (GST_PAD_IS_SINK (pad)) { + switch (GST_QUERY_TYPE (query)) { +#if GST_CHECK_VERSION(1,0,0) + case GST_QUERY_CAPS:{ + GstCaps *filter, *caps = NULL; + + gst_query_parse_caps (query, &filter); + caps = gst_vaapidecode_get_caps (pad); + + if (filter) { + GstCaps *tmp = caps; + caps = gst_caps_intersect_full (filter, tmp, + GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (tmp); + } + + GST_DEBUG_OBJECT (decode, "Returning sink caps %" GST_PTR_FORMAT, caps); + + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); res = TRUE; - } - else if (GST_PAD_IS_SINK(pad)) { - switch (GST_QUERY_TYPE(query)) { -#if GST_CHECK_VERSION(1,0,0) - case GST_QUERY_CAPS: { - GstCaps *filter, *caps = NULL; - - gst_query_parse_caps(query, &filter); - caps = gst_vaapidecode_get_caps(pad); - - if (filter) { - GstCaps *tmp = caps; - caps = gst_caps_intersect_full(filter, tmp, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref(tmp); - } - - GST_DEBUG_OBJECT(decode, "Returning sink caps %" GST_PTR_FORMAT, - caps); - - gst_query_set_caps_result(query, caps); - gst_caps_unref(caps); - res = TRUE; - break; - } + break; + } #endif - default: - res = GST_PAD_QUERY_FUNCTION_CALL(plugin->sinkpad_query, pad, - parent, query); - break; - } + default: + res = GST_PAD_QUERY_FUNCTION_CALL (plugin->sinkpad_query, pad, + parent, query); + break; } - else { - switch (GST_QUERY_TYPE(query)) { + } else { + switch (GST_QUERY_TYPE (query)) { #if GST_CHECK_VERSION(1,0,0) - case GST_QUERY_CAPS: { - GstCaps *filter, *caps = NULL; + case GST_QUERY_CAPS:{ + GstCaps *filter, *caps = NULL; - gst_query_parse_caps(query, &filter); - caps = gst_pad_get_pad_template_caps(pad); + gst_query_parse_caps (query, &filter); + caps = gst_pad_get_pad_template_caps (pad); - if (filter) { - GstCaps *tmp = caps; - caps = gst_caps_intersect_full(filter, tmp, - GST_CAPS_INTERSECT_FIRST); - gst_caps_unref(tmp); - } - - GST_DEBUG_OBJECT(decode, "Returning src caps %" GST_PTR_FORMAT, - caps); - - gst_query_set_caps_result(query, caps); - gst_caps_unref(caps); - res = TRUE; - break; + if (filter) { + GstCaps *tmp = caps; + caps = gst_caps_intersect_full (filter, tmp, + GST_CAPS_INTERSECT_FIRST); + gst_caps_unref (tmp); } + + GST_DEBUG_OBJECT (decode, "Returning src caps %" GST_PTR_FORMAT, caps); + + gst_query_set_caps_result (query, caps); + gst_caps_unref (caps); + res = TRUE; + break; + } #endif - default: - res = GST_PAD_QUERY_FUNCTION_CALL(plugin->srcpad_query, pad, - parent, query); - break; - } + default: + res = GST_PAD_QUERY_FUNCTION_CALL (plugin->srcpad_query, pad, + parent, query); + break; } + } - gst_object_unref(decode); - return res; + gst_object_unref (decode); + return res; } static void -gst_vaapidecode_init(GstVaapiDecode *decode) +gst_vaapidecode_init (GstVaapiDecode * decode) { - GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode); - GstPad *pad; + GstVideoDecoder *const vdec = GST_VIDEO_DECODER (decode); + GstPad *pad; - gst_vaapi_plugin_base_init(GST_VAAPI_PLUGIN_BASE(decode), GST_CAT_DEFAULT); + gst_vaapi_plugin_base_init (GST_VAAPI_PLUGIN_BASE (decode), GST_CAT_DEFAULT); - decode->decoder = NULL; - decode->decoder_caps = NULL; - decode->allowed_caps = NULL; + decode->decoder = NULL; + decode->decoder_caps = NULL; + decode->allowed_caps = NULL; - g_mutex_init(&decode->surface_ready_mutex); - g_cond_init(&decode->surface_ready); + g_mutex_init (&decode->surface_ready_mutex); + g_cond_init (&decode->surface_ready); - gst_video_decoder_set_packetized(vdec, FALSE); + gst_video_decoder_set_packetized (vdec, FALSE); - /* Pad through which data comes in to the element */ - pad = GST_VAAPI_PLUGIN_BASE_SINK_PAD(decode); - gst_pad_set_query_function(pad, GST_DEBUG_FUNCPTR(gst_vaapidecode_query)); + /* Pad through which data comes in to the element */ + pad = GST_VAAPI_PLUGIN_BASE_SINK_PAD (decode); + gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_vaapidecode_query)); #if !GST_CHECK_VERSION(1,0,0) - gst_pad_set_getcaps_function(pad, gst_vaapidecode_get_caps); + gst_pad_set_getcaps_function (pad, gst_vaapidecode_get_caps); #endif - /* Pad through which data goes out of the element */ - pad = GST_VAAPI_PLUGIN_BASE_SRC_PAD(decode); - gst_pad_set_query_function(pad, GST_DEBUG_FUNCPTR(gst_vaapidecode_query)); + /* Pad through which data goes out of the element */ + pad = GST_VAAPI_PLUGIN_BASE_SRC_PAD (decode); + gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_vaapidecode_query)); }