vaapidecode: plug a memory leak.
[platform/upstream/gstreamer-vaapi.git] / gst / vaapi / gstvaapidecode.c
index b3519a9..da422e2 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2010-2011 Splitted-Desktop Systems
  *    Author: Gwenole Beauchesne <gwenole.beauchesne@splitted-desktop.com>
- *  Copyright (C) 2011-2013 Intel Corporation
+ *  Copyright (C) 2011-2014 Intel Corporation
  *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
  *
  *  This library is free software; you can redistribute it and/or
 #include <gst/vaapi/gstvaapidecoder_mpeg2.h>
 #include <gst/vaapi/gstvaapidecoder_mpeg4.h>
 #include <gst/vaapi/gstvaapidecoder_vc1.h>
+#include <gst/vaapi/gstvaapidecoder_vp8.h>
 
 #define GST_PLUGIN_NAME "vaapidecode"
 #define GST_PLUGIN_DESC "A VA-API based video decoder"
 
+#define GST_VAAPI_DECODE_FLOW_PARSE_DATA        GST_FLOW_CUSTOM_SUCCESS_2
+
 GST_DEBUG_CATEGORY_STATIC(gst_debug_vaapidecode);
 #define GST_CAT_DEFAULT gst_debug_vaapidecode
 
@@ -67,6 +70,7 @@ static const char gst_vaapidecode_sink_caps_str[] =
     GST_CAPS_CODEC("video/x-h263")
     GST_CAPS_CODEC("video/x-h264")
     GST_CAPS_CODEC("video/x-wmv")
+    GST_CAPS_CODEC("video/x-vp8")
     GST_CAPS_CODEC("image/jpeg")
     ;
 
@@ -110,10 +114,12 @@ 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);
 
     g_assert(decode->decoder == decoder);
 
     gst_vaapidecode_update_src_caps(decode, codec_state);
+    gst_video_decoder_negotiate(vdec);
 }
 
 static inline gboolean
@@ -130,6 +136,14 @@ gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
     GstVideoDecoder * const vdec = GST_VIDEO_DECODER(decode);
     GstVideoCodecState *state;
     GstVideoInfo *vi, vis;
+#if GST_CHECK_VERSION(1,1,0)
+    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));
+#endif
 
     state = gst_video_decoder_set_output_state(vdec,
         GST_VIDEO_INFO_FORMAT(&ref_state->info),
@@ -149,15 +163,32 @@ gst_vaapidecode_update_src_caps(GstVaapiDecode *decode,
 
 #if GST_CHECK_VERSION(1,1,0)
     vis = *vi;
-    if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
-        /* XXX: this is a workaround until auto-plugging is fixed when
-           format=ENCODED + memory:VASurface caps feature are provided.
-           Meanwhile, providing a random format here works but this is
-           a terribly wrong thing per se. */
-        gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_NV12,
+    switch (feature) {
+    case GST_VAAPI_CAPS_FEATURE_GL_TEXTURE_UPLOAD_META:
+        gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_RGBA,
             GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
+        features = gst_caps_features_new(
+            GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL);
+        break;
+    default:
+        if (GST_VIDEO_INFO_FORMAT(vi) == GST_VIDEO_FORMAT_ENCODED) {
+            /* XXX: this is a workaround until auto-plugging is fixed when
+            format=ENCODED + memory:VASurface caps feature are provided.
+            Meanwhile, providing a random format here works but this is
+            a terribly wrong thing per se. */
+            gst_video_info_set_format(&vis, GST_VIDEO_FORMAT_NV12,
+                GST_VIDEO_INFO_WIDTH(vi), GST_VIDEO_INFO_HEIGHT(vi));
+#if GST_CHECK_VERSION(1,3,0)
+            if (feature == GST_VAAPI_CAPS_FEATURE_VAAPI_SURFACE)
+                features = gst_caps_features_new(
+                    GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE, NULL);
+#endif
+        }
+        break;
     }
     state->caps = gst_video_info_to_caps(&vis);
+    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 */
@@ -461,12 +492,38 @@ gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
     GstVideoInfo vi;
     guint size, min, max;
     gboolean need_pool, update_pool;
+    gboolean has_video_meta = FALSE;
+    GstVideoCodecState *state;
+#if GST_CHECK_VERSION(1,1,0) && USE_GLX
+    GstCapsFeatures *features, *features2;
+#endif
 
     gst_query_parse_allocation(query, &caps, &need_pool);
 
     if (!caps)
         goto error_no_caps;
 
+    state = gst_video_decoder_get_output_state(vdec);
+
+    decode->has_texture_upload_meta = FALSE;
+    has_video_meta = gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
+#if GST_CHECK_VERSION(1,1,0) && USE_GLX
+    if (has_video_meta)
+        decode->has_texture_upload_meta = gst_query_find_allocation_meta(query,
+            GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
+
+    features = gst_caps_get_features(state->caps, 0);
+    features2 = gst_caps_features_new(GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, NULL);
+
+    /* Update src caps if feature is not handled downstream */
+    if (!decode->has_texture_upload_meta &&
+        gst_caps_features_is_equal(features, features2))
+        gst_vaapidecode_update_src_caps (decode, state);
+    gst_caps_features_free(features2);
+#endif
+
+    gst_video_codec_state_unref(state);
+
     gst_video_info_init(&vi);
     gst_video_info_from_caps(&vi, caps);
     if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED)
@@ -491,6 +548,8 @@ gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
             GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META)) {
         GST_INFO("no pool or doesn't support GstVaapiVideoMeta, "
             "making new pool");
+        if (pool)
+            gst_object_unref(pool);
         pool = gst_vaapi_video_buffer_pool_new(
             GST_VAAPI_PLUGIN_BASE_DISPLAY(decode));
         if (!pool)
@@ -503,14 +562,11 @@ gst_vaapidecode_decide_allocation(GstVideoDecoder *vdec, GstQuery *query)
         gst_buffer_pool_set_config(pool, config);
     }
 
-    decode->has_texture_upload_meta = FALSE;
-    if (gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL)) {
+    if (has_video_meta) {
         config = gst_buffer_pool_get_config(pool);
         gst_buffer_pool_config_add_option(config,
             GST_BUFFER_POOL_OPTION_VIDEO_META);
 #if GST_CHECK_VERSION(1,1,0) && USE_GLX
-        decode->has_texture_upload_meta = gst_query_find_allocation_meta(query,
-            GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
         if (decode->has_texture_upload_meta)
             gst_buffer_pool_config_add_option(config,
                 GST_BUFFER_POOL_OPTION_VIDEO_GL_TEXTURE_UPLOAD_META);
@@ -581,6 +637,11 @@ gst_vaapidecode_create(GstVaapiDecode *decode, GstCaps *caps)
         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;
+#endif
     default:
         decode->decoder = NULL;
         break;
@@ -717,6 +778,8 @@ gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state)
         return FALSE;
     if (!gst_vaapidecode_update_src_caps(decode, state))
         return FALSE;
+    if (!gst_video_decoder_negotiate(vdec))
+        return FALSE;
     if (!gst_vaapi_plugin_base_set_caps(plugin, decode->sinkpad_caps,
             decode->srcpad_caps))
         return FALSE;
@@ -726,7 +789,7 @@ gst_vaapidecode_set_format(GstVideoDecoder *vdec, GstVideoCodecState *state)
 }
 
 static GstFlowReturn
-gst_vaapidecode_parse(GstVideoDecoder *vdec,
+gst_vaapidecode_parse_frame(GstVideoDecoder *vdec,
     GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
 {
     GstVaapiDecode * const decode = GST_VAAPIDECODE(vdec);
@@ -749,7 +812,7 @@ gst_vaapidecode_parse(GstVideoDecoder *vdec,
             decode->current_frame_size = 0;
         }
         else
-            ret = GST_FLOW_OK;
+            ret = GST_VAAPI_DECODE_FLOW_PARSE_DATA;
         break;
     case GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA:
         ret = GST_VIDEO_DECODER_FLOW_NEED_DATA;
@@ -770,6 +833,18 @@ gst_vaapidecode_parse(GstVideoDecoder *vdec,
     return ret;
 }
 
+static GstFlowReturn
+gst_vaapidecode_parse(GstVideoDecoder *vdec,
+    GstVideoCodecFrame *frame, GstAdapter *adapter, gboolean at_eos)
+{
+    GstFlowReturn ret;
+
+    do {
+        ret = gst_vaapidecode_parse_frame(vdec, frame, adapter, at_eos);
+    } while (ret == GST_VAAPI_DECODE_FLOW_PARSE_DATA);
+    return ret;
+}
+
 static GstStateChangeReturn
 gst_vaapidecode_change_state (GstElement * element, GstStateChange transition)
 {