support h263 encoder(vah263encode) in mrst "gst-launch videotestsrc num-buffers=100...
authorWind Yuan <feng.yuan@intel.com>
Thu, 13 Oct 2011 07:17:54 +0000 (15:17 +0800)
committerZhong Cong <congx.zhong@intel.com>
Tue, 5 Feb 2013 07:37:11 +0000 (15:37 +0800)
gst/vaapiencode/gstvaapiencode.h
gst/vaapiencode/h264encoder.c
gst/vaapiencode/h264encoder.h

index d87e734..d123b91 100644 (file)
 
 G_BEGIN_DECLS
 
+/* Default templates */
+#define GST_CAPS_CODEC(CODEC)          \
+    CODEC ", "                         \
+    "width  = (int) [ 1, MAX ], "      \
+    "height = (int) [ 1, MAX ]; "
+
+
 #define GST_TYPE_VAAPI_ENCODE             (gst_vaapi_encode_get_type())
 #define GST_IS_VAAPI_ENCODE(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VAAPI_ENCODE))
 #define GST_IS_VAAPI_ENCODE_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VAAPI_ENCODE))
index 21bb7f1..4da33f9 100644 (file)
@@ -51,12 +51,12 @@ struct _GstH264EncodeBuffer {
 
 struct _GstH264EncoderPrivate {
   GstH264Encoder   *public;
-  uint32_t          format;   /*NV12, I420,*/
+  guint32           format;   /*NV12, I420,*/
   gboolean          es_flag;  /*elementary flag*/
 
   /* private data*/
   //GstVaapiDisplay  *vaapi_display;
-  GstVaapiContext  *vaapi_context;
+  //GstVaapiContext  *vaapi_context;
   GQueue           *video_buffer_caches; /*not used for baseline*/
 
   GstVaapiSurface  *ref_surface;  /* reference buffer*/
@@ -68,15 +68,15 @@ struct _GstH264EncoderPrivate {
   VABufferID        pic_parameter;
   VABufferID        slice_parameter;
   VAEncSliceParameterBuffer *slice_param_buffers;
-  uint32_t          default_slice_height;
-  uint32_t          slice_mod_mb_num;
+  guint32           default_slice_height;
+  guint32           slice_mod_mb_num;
 
   VABufferID       *coded_bufs;
-  uint32_t          coded_buf_num;
-  uint32_t          cur_coded_index;
+  guint32           coded_buf_num;
+  guint32           cur_coded_index;
 
   /*total encoded frames*/
-  uint32_t          frame_count;
+  guint32           frame_count;
 
   GstBuffer        *sps_data;
   GstBuffer        *pps_data;
@@ -97,51 +97,59 @@ G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_ENCODER);
 #define BIT_STREAM_BIT_SIZE(stream)  ((stream)->bit_size)
 
 struct _H264Bitstream {
-  uint8_t  *buffer;
-  uint32_t  bit_size;
-  uint32_t  max_bit_capability;
+  guint8   *buffer;
+  guint32   bit_size;
+  guint32   max_bit_capability;
 };
 
 typedef struct _H264Bitstream H264Bitstream;
 
-static const uint8_t h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
+static const guint8 h264_bit_mask[9] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
 
 static GstBufferClass *h264_encode_buffer_parent_class = NULL;
 
 
-static EncoderStatus gst_h264_encoder_initialize(GstVaapiEncoder* encoder);
-static EncoderStatus gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder);
-static EncoderStatus gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data);
-static EncoderStatus gst_h264_encoder_close(GstVaapiEncoder* encoder);
-static EncoderStatus gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics);
-static EncoderStatus gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics);
-
-static gboolean   gst_h264_validate_parameters(GstH264Encoder *encoder);
-static void     gst_h264_encoder_finalize(GObject *object);
-static void     gst_h264_encoder_init_public_values(GstH264Encoder* encoder);
-
-static VAProfile  h264_get_va_profile(uint32_t profile);
-static EncoderStatus h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv);
-static EncoderStatus h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv);
-static EncoderStatus h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
-                                             GstBuffer *raw_pic,
-                                             GstVaapiSurface *surface);
-
-static EncoderStatus h264_prepare_encoding(GstH264EncoderPrivate *h264_prv,
-                                             GstBuffer *raw_pic, gboolean is_key,
-                                             VABufferID coded_buf);
-static EncoderStatus h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
-                                         VASurfaceID surface_id,
-                                         gboolean is_key,
-                                         GstClockTime timestamp,
-                                         GstClockTime duration,
-                                         VABufferID *coded_buf,
-                                         GList **coded_pics);
+static EncoderStatus gst_h264_encoder_initialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display);
+static EncoderStatus gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display);
+static EncoderStatus gst_h264_encoder_open(GstVaapiEncoder* encoder, GstVaapiDisplay *display, void* private_data, GstVaapiContext **context);
+static EncoderStatus gst_h264_encoder_close(GstVaapiEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context);
+static EncoderStatus gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
+                                                 GstVaapiContext *context, GstBuffer *raw_pic, GList **coded_pics);
+static EncoderStatus gst_h264_encoder_flush(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
+                                                 GstVaapiContext *context, GList **coded_pics);
+/*other functions*/
+static EncoderStatus gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
+static EncoderStatus gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
+
+static gboolean      gst_h264_validate_parameters(GstH264Encoder *encoder);
+static void          gst_h264_encoder_finalize(GObject *object);
+static void          gst_h264_encoder_init_public_values(GstH264Encoder* encoder);
+
+static VAProfile     h264_get_va_profile(guint32 profile);
+static EncoderStatus h264_encoder_alloc_buffers(GstH264Encoder *h264_encoder,
+                                                GstVaapiDisplay *display, GstVaapiContext *context);
+static EncoderStatus h264_encoder_release_buffers(GstH264Encoder *h264_encoder,
+                                                GstVaapiDisplay *display, GstVaapiContext *context);
+static EncoderStatus h264_put_raw_buffer_to_surface(GstH264Encoder *h264_encoder,
+                                                  GstVaapiDisplay *display,
+                                                  GstBuffer *raw_pic,
+                                                  GstVaapiSurface *surface);
+
+static EncoderStatus h264_prepare_encoding(GstH264Encoder *h264_encoder, GstVaapiDisplay *display,
+                                             GstVaapiContext *context, gboolean is_key, VABufferID coded_buf);
+static EncoderStatus h264_query_encoding_status(GstH264Encoder *h264_encoder,
+                                             GstVaapiDisplay *display,
+                                             GstVaapiSurface *buffer_surface,
+                                             gboolean is_key,
+                                             GstClockTime timestamp,
+                                             GstClockTime duration,
+                                             VABufferID *coded_buf,
+                                             GList **coded_pics);
 static EncoderStatus
-h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size);
+h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const guint8 *buf, guint32 size);
 static GstBuffer *h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
-                                                   uint8_t *frame,
-                                                   uint32_t frame_size,
+                                                   guint8 *frame,
+                                                   guint32 frame_size,
                                                    VABufferID *coded_buf);
 
 
@@ -153,26 +161,30 @@ static GstH264EncodeBuffer *gst_h264_encode_buffer_new(GstH264EncoderPrivate *h2
                                                        VABufferID *coded_id);
 
 /* h264 bitstream functions */
-static void     h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability);
-static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size);
-static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value);
-static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value);
-static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value);
+static void     h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability);
+static gboolean h264_bitstream_write_uint(H264Bitstream *bitstream, guint32 value, guint32 bit_size);
+static gboolean h264_bitstream_align(H264Bitstream *bitstream, guint32 value);
+static gboolean h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value);
+static gboolean h264_bitstream_write_se(H264Bitstream *bitstream, guint32 value);
 static gboolean h264_bitstream_write_trailing_bits(H264Bitstream *bitstream);
 
-static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size);
+static gboolean h264_bitstream_write_byte_array(H264Bitstream *bitstream, const guint8 *buf, guint32 byte_size);
 static void     h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag);
-static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size);
+static gboolean h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size);
 static gboolean h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
 static gboolean h264_bitstream_write_pps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv);
-static const uint8_t *h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size);
-static gboolean h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
-                                uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc);
-
-/*other functions*/
-static EncoderStatus gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
-static EncoderStatus gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder* encoder, GstBuffer **buffer);
-
+static const guint8 *h264_next_nal(const guint8 *buffer, guint32 len, guint32 *nal_size);
+static gboolean h264_read_sps_attributes(const guint8 *sps_data, guint32 sps_size,
+                                guint32 *profile_idc, guint32 *profile_comp, guint32 *level_idc);
+
+/* available_coded_buffer actions */
+static VABufferID *pop_available_coded_buffer(GstH264EncoderPrivate *h264_prv);
+static gboolean push_available_coded_buffer(GstH264EncoderPrivate *h264_prv, VABufferID *buf);
+static gboolean alloc_all_available_coded_buffers(GstH264EncoderPrivate *h264_prv,
+                                          GstVaapiDisplay *display, GstVaapiContext *context,
+                                          guint32 buffer_size, gboolean need_display_lock);
+static void wait_and_clear_available_coded_buffers(GstH264EncoderPrivate *h264_prv,
+                                          GstVaapiDisplay *display, gboolean need_display_lock);
 
 static void
 gst_h264_encoder_class_init(GstH264EncoderClass *klass)
@@ -189,6 +201,9 @@ gst_h264_encoder_class_init(GstH264EncoderClass *klass)
   encoder_class->close = gst_h264_encoder_close;
   encoder_class->encode = gst_h264_encoder_encode;
   encoder_class->flush = gst_h264_encoder_flush;
+  encoder_class->get_codec_data = gst_h264_encoder_get_avcC_codec_data;
+  /* encoder_class->get_codec_data = gst_h264_encoder_get_nal_codec_data; */
+
   /*
   object_class->set_property = gst_h264_encoder_set_property;
   object_class->get_property = gst_h264_encoder_get_property;
@@ -239,29 +254,27 @@ gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
   VABufferID* coded_id = NULL;
   GstVaapiDisplay *display = NULL;
 
+  gboolean is_locked = FALSE;
+
   h264_prv = h264_buffer->encoder;
   coded_id = h264_buffer->coded_id;
   display = ENCODER_DISPLAY(h264_prv->public);
 
   ENCODER_ASSERT(display);
-  ENCODER_ASSERT(h264_prv->vaapi_context);
   VADisplay va_dpy = gst_vaapi_display_get_display(display);
 
   ENCODER_ASSERT(h264_prv);
   ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
-  ENCODER_ASSERT(h264_prv->available_code_buffers);
 
-  g_mutex_lock(h264_prv->code_buffer_lock);
   /*if (--(*h264_buffer->ref_coded_id) == 0) */
   {
     /*g_free(h264_buffer->ref_coded_id);*/
+    ENCODER_ACQUIRE_DISPLAY_LOCK(display);
     vaUnmapBuffer(va_dpy, *coded_id);
-    g_queue_push_head(h264_prv->available_code_buffers, coded_id);
-    g_cond_signal(h264_prv->code_buffer_cond);
+    ENCODER_RELEASE_DISPLAY_LOCK(display);
+    push_available_coded_buffer(h264_prv, coded_id);
   }
 
-  g_mutex_unlock(h264_prv->code_buffer_lock);
-
   if (GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize) {
     GST_MINI_OBJECT_CLASS(h264_encode_buffer_parent_class)->finalize(GST_MINI_OBJECT(h264_buffer));
   }
@@ -306,29 +319,8 @@ h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
 #endif
 }
 
-static GstVaapiSurface *
-h264_pop_free_surface(GstH264EncoderPrivate *h264_prv)
-{
-  ENCODER_ASSERT(h264_prv && h264_prv->vaapi_context);
-
-  /*may need lock*/
-  GstVaapiSurface *surface = gst_vaapi_context_get_surface(h264_prv->vaapi_context);
-  return surface;
-}
-
-static void
-h264_push_free_surface(GstH264EncoderPrivate *h264_prv, GstVaapiSurface *surface)
-{
-  ENCODER_ASSERT(surface);
-  if (!surface) {
-    return;
-  }
-  gst_vaapi_context_put_surface(h264_prv->vaapi_context, surface);
-}
-
-
 static VAProfile
-h264_get_va_profile(uint32_t profile)
+h264_get_va_profile(guint32 profile)
 {
   switch (profile) {
     case H264_PROFILE_BASELINE:
@@ -369,7 +361,6 @@ gst_h264_encoder_init(GstH264Encoder *encoder)
   h264_prv->es_flag = TRUE;
 
   //h264_prv->vaapi_display = NULL;
-  h264_prv->vaapi_context= NULL;
   h264_prv->ref_surface = NULL;
   h264_prv->recon_surface = NULL;
   h264_prv->video_buffer_caches = g_queue_new();
@@ -394,17 +385,19 @@ gst_h264_encoder_init(GstH264Encoder *encoder)
   h264_prv->code_buffer_cond = g_cond_new();
   h264_prv->available_code_buffers = g_queue_new();
 
-  encoder_prv->get_codec_data = gst_h264_encoder_get_avcC_codec_data;
-  /* encoder_prv->get_codec_data = gst_h264_encoder_get_nal_codec_data; */
-
 }
 
 static void
 gst_h264_encoder_finalize(GObject *object)
 {
   /*free private buffers*/
+  GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
   GstH264EncoderPrivate *h264_prv = ENCPRV(object);
 
+  if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
+    gst_vaapi_encoder_uninitialize(encoder);
+  }
+
   g_mutex_free(h264_prv->code_buffer_lock);
   g_cond_free(h264_prv->code_buffer_cond);
   if (h264_prv->available_code_buffers) {
@@ -412,27 +405,6 @@ gst_h264_encoder_finalize(GObject *object)
     h264_prv->available_code_buffers = NULL;
   }
 
-  if (h264_prv->ref_surface) {
-    if (h264_prv->vaapi_context) {
-      h264_push_free_surface(h264_prv, h264_prv->ref_surface);
-    } else {
-      g_object_unref(h264_prv->ref_surface);
-    }
-    h264_prv->ref_surface = NULL;
-  }
-  if (h264_prv->recon_surface) {
-    if (h264_prv->vaapi_context) {
-      h264_push_free_surface(h264_prv, h264_prv->recon_surface);
-    } else {
-      g_object_unref(h264_prv->recon_surface);
-    }
-    h264_prv->recon_surface = NULL;
-  }
-  if (h264_prv->vaapi_context) {
-    g_object_unref(h264_prv->vaapi_context);
-    h264_prv->vaapi_context= NULL;
-  }
-
   if (h264_prv->video_buffer_caches) {
     g_queue_free(h264_prv->video_buffer_caches);
     h264_prv->video_buffer_caches = NULL;
@@ -468,7 +440,7 @@ gst_h264_encoder_init_public_values(GstH264Encoder* encoder)
 }
 
 void
-gst_h264_encoder_set_input_format(GstH264Encoder* encoder, uint32_t format)
+gst_h264_encoder_set_input_format(GstH264Encoder* encoder, guint32 format)
 {
   GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
   h264_prv->format = format;
@@ -482,13 +454,13 @@ gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
 }
 
 EncoderStatus
-gst_h264_encoder_initialize(GstVaapiEncoder* encoder)
+gst_h264_encoder_initialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
 {
   return ENCODER_NO_ERROR;
 }
 
 EncoderStatus
-gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder)
+gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
 {
   return ENCODER_NO_ERROR;
 
@@ -553,18 +525,15 @@ gst_h264_validate_parameters(GstH264Encoder *encoder)
 }
 
 EncoderStatus
-gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data)
+gst_h264_encoder_open(GstVaapiEncoder* encoder, GstVaapiDisplay *display, void* private_data, GstVaapiContext **context)
 {
   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
   GstVaapiSurfacePool *surfaces_pool = private_data;
-  GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+  GstVaapiContext *out_context = NULL;
+  VAProfile va_profile = -1;
 
   EncoderStatus ret = ENCODER_NO_ERROR;
-  VAProfile va_profile = -1;
-  VAEntrypoint entrypoints[5];
-  int num_entrypoints,slice_entrypoint;
-  VAConfigAttrib attrib[5];
   VAStatus va_status = VA_STATUS_SUCCESS;
 
   /*check and set default values*/
@@ -572,11 +541,10 @@ gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data)
 
   va_profile = h264_get_va_profile(h264_encoder->profile);
   ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
-  ENCODER_ASSERT(!h264_prv->vaapi_context);
   ENCODER_CHECK_STATUS(-1 != va_profile, ENCODER_PROFILE_ERR, "profile(%d) is NOT supported.\n", h264_encoder->profile);
 
 #ifdef _MRST_
-  h264_prv->vaapi_context = g_object_new(
+  out_context = g_object_new(
         GST_VAAPI_TYPE_CONTEXT,
         "display",      display,
         "id",           GST_VAAPI_ID(VA_INVALID_ID),
@@ -586,47 +554,52 @@ gst_h264_encoder_open(GstVaapiEncoder* encoder, void* private_data)
         NULL
     );
   if (surfaces_pool) {
-    gst_vaapi_context_set_surface_pool(h264_prv->vaapi_context, surfaces_pool);
+    gst_vaapi_context_set_surface_pool(out_context, surfaces_pool);
   }
-  g_object_set(h264_prv->vaapi_context, "profile",  gst_vaapi_profile(va_profile), NULL);
+  g_object_set(out_context, "profile",  gst_vaapi_profile(va_profile), NULL);
 
 #else
   VAAPI_UNUSED_ARG(surfaces_pool);
-  h264_prv->vaapi_context = gst_vaapi_context_new(display,
+  out_context = gst_vaapi_context_new(display,
                         gst_vaapi_profile(va_profile),
                         gst_vaapi_entrypoint(VAEntrypointEncSlice),
                         ENCODER_WIDTH(encoder),
                         ENCODER_HEIGHT(encoder));
 #endif
-  ENCODER_CHECK_STATUS(h264_prv->vaapi_context, ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
-  ret = h264_encoder_alloc_buffers(h264_prv);
+  ENCODER_CHECK_STATUS(out_context, ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.\n");
+  ret = h264_encoder_alloc_buffers(h264_encoder, display, out_context);
   if (ENCODER_NO_ERROR != ret) {
     goto end;
   }
-
+  *context = out_context;
   return ENCODER_NO_ERROR;
 
-  end:
+end:
   // clear resources
-  gst_h264_encoder_close(encoder);
+  if (ENCODER_NO_ERROR != ret) {
+    gst_h264_encoder_close(encoder, display, out_context);
+    if (out_context) {
+      g_object_unref(out_context);
+    }
+  }
   return ret;
 
 }
 
 EncoderStatus
-gst_h264_encoder_close(GstVaapiEncoder* encoder)
+gst_h264_encoder_close(GstVaapiEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context)
 {
   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
   EncoderStatus ret = ENCODER_NO_ERROR;
   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
 
   /* release buffers first */
-  h264_encoder_release_buffers(h264_prv);
+  h264_encoder_release_buffers(h264_encoder, display, context);
 
   /*remove ref_surface*/
   if (h264_prv->ref_surface) {
-    if (h264_prv->vaapi_context) {
-      h264_push_free_surface(h264_prv, h264_prv->ref_surface);
+    if (context) {
+      gst_vaapi_context_put_surface(context, h264_prv->ref_surface);
     } else {
       g_object_unref(h264_prv->ref_surface);
     }
@@ -635,20 +608,14 @@ gst_h264_encoder_close(GstVaapiEncoder* encoder)
 
   /*remove recon_surface*/
   if (h264_prv->recon_surface) {
-    if (h264_prv->vaapi_context) {
-      h264_push_free_surface(h264_prv, h264_prv->recon_surface);
+    if (context) {
+      gst_vaapi_context_put_surface(context, h264_prv->recon_surface);
     } else {
       g_object_unref(h264_prv->recon_surface);
     }
     h264_prv->recon_surface = NULL;
   }
 
-  /*remove vaapi_context*/
-  if (h264_prv->vaapi_context) {
-    g_object_unref(h264_prv->vaapi_context);
-    h264_prv->vaapi_context = NULL;
-  }
-
   h264_prv->frame_count = 0;
 
   if (h264_prv->sps_data) {
@@ -663,98 +630,50 @@ gst_h264_encoder_close(GstVaapiEncoder* encoder)
 }
 
 static EncoderStatus
-h264_encoder_alloc_buffers(GstH264EncoderPrivate *h264_prv)
+h264_encoder_alloc_buffers(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
 {
   EncoderStatus ret = ENCODER_NO_ERROR;
   VAStatus va_status = VA_STATUS_SUCCESS;
-  GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
-  uint32_t i;
+  GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+  guint32 i;
 
-  ENCODER_ASSERT(display);
-  ENCODER_ASSERT(h264_prv->vaapi_context);
+  ENCODER_ASSERT(display && context);
   VADisplay va_dpy = gst_vaapi_display_get_display(display);
-  VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
+  VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
   gboolean is_locked = FALSE;
 
-  GST_VAAPI_DISPLAY_LOCK(display);
-  is_locked = TRUE;
-
-  /* create coded buffers */
-  h264_prv->coded_bufs = (VABufferID*)g_malloc0(h264_prv->coded_buf_num * sizeof(h264_prv->coded_bufs[0]));
-  { // check width, height  ????
-      uint32_t codedbuf_size = (ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public) * 400) / (16*16);
-      for (i = 0; i < h264_prv->coded_buf_num; i++) {
-        va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
-                                   codedbuf_size, 1, NULL, &h264_prv->coded_bufs[i]);
-
-        ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc coded buffer failed.\n");
-      }
-  }
-
-  /* unlock here */
-  GST_VAAPI_DISPLAY_UNLOCK(display);
-  is_locked = FALSE;
-
-  ENCODER_ASSERT(h264_prv->available_code_buffers);
+  guint32 codedbuf_size = (ENCODER_WIDTH(h264_encoder) * ENCODER_HEIGHT(h264_encoder) * 400) / (16*16);
+  ENCODER_CHECK_STATUS(alloc_all_available_coded_buffers(h264_prv, display, context, codedbuf_size, TRUE),
+                       ENCODER_ENC_RES_ERR,
+                       "alloc_all_available_coded_buffers failed.\n");
 
   /* create slice_param_buffers */
-  h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_prv->public->slice_num,
+  h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_encoder->slice_num,
                                                      sizeof(h264_prv->slice_param_buffers[0]));
-
-  /* init queue available_code_buffers */
-  g_mutex_lock(h264_prv->code_buffer_lock);
-  for (i = 0; i < h264_prv->coded_buf_num; i++) {
-    g_queue_push_tail (h264_prv->available_code_buffers, &h264_prv->coded_bufs[i]);
-  }
-  g_cond_signal(h264_prv->code_buffer_cond);
-  g_mutex_unlock(h264_prv->code_buffer_lock);
-
-  return ENCODER_NO_ERROR;
-
-  end:
-  if (is_locked) {
-    GST_VAAPI_DISPLAY_UNLOCK(display);
-    is_locked = FALSE;
-  }
+end:
   return ret;
-
 }
 
 static EncoderStatus
-h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv)
+h264_encoder_release_buffers(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
 {
   VAStatus va_status = VA_STATUS_SUCCESS;
-  uint32_t available_buf_count = h264_prv->coded_buf_num;
-  GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
-  uint32_t i;
+  GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+  guint32 available_buf_count = h264_prv->coded_buf_num;
+  guint32 i;
+
+  gboolean is_locked = FALSE;
 
   ENCODER_ASSERT(display);
-  ENCODER_ASSERT(h264_prv->vaapi_context);
+  ENCODER_ASSERT(context);
   VADisplay va_dpy = gst_vaapi_display_get_display(display);
 
-  /* wait for all coded buffer freed*/
-  g_mutex_lock(h264_prv->code_buffer_lock);
-  while (available_buf_count) {
-    if (g_queue_is_empty(h264_prv->available_code_buffers)) {
-      g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
-    } else {
-      g_queue_pop_head(h264_prv->available_code_buffers);
-      available_buf_count--;
-    }
-  }
-  g_mutex_unlock(h264_prv->code_buffer_lock);
+  /* wait clear all coded buffer freed*/
+  wait_and_clear_available_coded_buffers(h264_prv, display, TRUE);
 
-  GST_VAAPI_DISPLAY_LOCK(display);
-  for (i = 0; i < h264_prv->coded_buf_num; i++) {
-    va_status = vaDestroyBuffer(va_dpy, h264_prv->coded_bufs[i]);
-  }
+  ENCODER_ACQUIRE_DISPLAY_LOCK(display);
   va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
-  GST_VAAPI_DISPLAY_UNLOCK(display);
-
-  if (h264_prv->coded_bufs) {
-    g_free(h264_prv->coded_bufs);
-    h264_prv->coded_bufs = NULL;
-  }
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
 
   if (h264_prv->slice_param_buffers) {
     g_free(h264_prv->slice_param_buffers);
@@ -765,11 +684,11 @@ h264_encoder_release_buffers(GstH264EncoderPrivate *h264_prv)
 }
 
 EncoderStatus
-gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **coded_pics)
+gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
+                        GstVaapiContext *context, GstBuffer *raw_pic, GList **coded_pics)
 {
   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
-  GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
 
   EncoderStatus ret = ENCODER_NO_ERROR;
   gboolean is_key = FALSE;
@@ -778,30 +697,31 @@ gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **co
   VASurfaceID  buffer_surface_id = VA_INVALID_SURFACE;
   GstVaapiSurface *buffer_surface = NULL;
 
-  ENCODER_ASSERT(display);
-  ENCODER_ASSERT(h264_prv->vaapi_context);
+  gboolean is_locked = FALSE;
+
+  ENCODER_ASSERT(display && context);
   VADisplay va_dpy = gst_vaapi_display_get_display(display);
-  VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
+  VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
   GstVaapiSurface *new_surface = NULL;
 
   if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
     buffer_surface = h264_get_video_surface(h264_prv, GST_VAAPI_VIDEO_BUFFER(raw_pic));
   } else {
-    new_surface = h264_pop_free_surface(h264_prv);
+    new_surface = gst_vaapi_context_get_surface(context);
     buffer_surface = new_surface;
     ENCODER_CHECK_STATUS(buffer_surface, ENCODER_SURFACE_ERR, "h264_pop_free_surface failed.\n");
 
     /*input picture to h264_prv->cur_surface_index*/
-    va_status = h264_put_raw_buffer_to_surface(h264_prv, raw_pic, buffer_surface);
+    va_status = h264_put_raw_buffer_to_surface(h264_encoder, display, raw_pic, buffer_surface);
     ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "va put buffer to surface failed.\n");
   }
   buffer_surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
   ENCODER_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, ENCODER_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.\n");
 
   /* begin picture, using default sid 0*/
-  GST_VAAPI_DISPLAY_LOCK(display);
+  ENCODER_ACQUIRE_DISPLAY_LOCK(display);
   va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
-  GST_VAAPI_DISPLAY_UNLOCK(display);
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
 
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaBeginPicture error.\n");
 
@@ -809,29 +729,23 @@ gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **co
   is_key = ((h264_prv->frame_count % h264_encoder->intra_period) == 0);
 
   /*get valid coded buffer*/
-  g_mutex_lock(h264_prv->code_buffer_lock);
-  ENCODER_ASSERT(h264_prv->available_code_buffers);
-  while (g_queue_is_empty(h264_prv->available_code_buffers)) {
-    g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
-  }
+  coded_buf = pop_available_coded_buffer(h264_prv);
+  ENCODER_CHECK_STATUS(coded_buf, ENCODER_ENC_RES_ERR, "dequeue_available_coded_buffer error.\n");
 
-  coded_buf = (VABufferID*)g_queue_pop_head (h264_prv->available_code_buffers);
-  ret = h264_prepare_encoding(h264_prv, raw_pic, is_key, *coded_buf);
+  ret = h264_prepare_encoding(h264_encoder, display, context, is_key, *coded_buf);
   if (ENCODER_NO_ERROR != ret) {
-    g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
+    push_available_coded_buffer(h264_prv, coded_buf);
   }
-  g_mutex_unlock(h264_prv->code_buffer_lock);
-
   ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ENCODER_PICTURE_ERR, "h264_prepare_encoding failed.\n");
 
   /* end picture */
-  GST_VAAPI_DISPLAY_LOCK(display);
+  ENCODER_ACQUIRE_DISPLAY_LOCK(display);
   va_status = vaEndPicture(va_dpy, context_id);
-  GST_VAAPI_DISPLAY_UNLOCK(display);
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaEndPicture error.\n");
 
   /*query surface result*/
-  ret = h264_query_encoding_status(h264_prv, buffer_surface_id,
+  ret = h264_query_encoding_status(h264_encoder, display, buffer_surface,
                                    is_key, GST_BUFFER_TIMESTAMP(raw_pic), GST_BUFFER_DURATION(raw_pic), coded_buf, coded_pics);
   if (ENCODER_NO_ERROR != ret) {
     goto end;
@@ -839,16 +753,123 @@ gst_h264_encoder_encode(GstVaapiEncoder* encoder, GstBuffer *raw_pic, GList **co
 
   h264_prv->frame_count++;
 
-
-  end:
+end:
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
   if (new_surface) {
-    h264_push_free_surface(h264_prv, new_surface);
+    gst_vaapi_context_put_surface(context, new_surface);
+  }
+  return ret;
+}
+
+static VABufferID *
+pop_available_coded_buffer(GstH264EncoderPrivate *h264_prv)
+{
+  VABufferID *coded_buf = NULL;
+  gboolean ret = TRUE;
+
+  g_mutex_lock(h264_prv->code_buffer_lock);
+
+  ENCODER_CHECK_STATUS(h264_prv->available_code_buffers, FALSE, "coded buffer not found");
+  while (g_queue_is_empty(h264_prv->available_code_buffers)) {
+    g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
+  }
+  coded_buf = (VABufferID*)g_queue_pop_head (h264_prv->available_code_buffers);
+
+end:
+  g_mutex_unlock(h264_prv->code_buffer_lock);
+  return coded_buf;
+}
+
+static gboolean
+push_available_coded_buffer(GstH264EncoderPrivate *h264_prv, VABufferID *buf)
+{
+  g_mutex_lock(h264_prv->code_buffer_lock);
+  g_queue_push_head(h264_prv->available_code_buffers, buf);
+  g_cond_signal(h264_prv->code_buffer_cond);
+  g_mutex_unlock(h264_prv->code_buffer_lock);
+  return TRUE;
+}
+
+static gboolean
+alloc_all_available_coded_buffers(GstH264EncoderPrivate *h264_prv, GstVaapiDisplay *display,
+                                     GstVaapiContext *context, guint32 buffer_size, gboolean need_display_lock)
+{
+  guint32 i = 0;
+  gboolean ret = TRUE;
+  VADisplay va_dpy = gst_vaapi_display_get_display(display);
+  VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
+  VAStatus va_status = VA_STATUS_SUCCESS;
+
+  ENCODER_ASSERT(h264_prv->available_code_buffers);
+  ENCODER_ASSERT(!h264_prv->coded_bufs);
+
+  h264_prv->coded_bufs = (VABufferID*)g_malloc0(h264_prv->coded_buf_num * sizeof(h264_prv->coded_bufs[0]));
+
+  if (need_display_lock) { /* lock */
+    GST_VAAPI_DISPLAY_LOCK(display);
+  }
+  for (i = 0; i < h264_prv->coded_buf_num; i++) {
+    va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
+                               buffer_size, 1, NULL, &h264_prv->coded_bufs[i]);
+    if (VA_STATUS_SUCCESS != va_status)
+      break;
+  }
+  if (need_display_lock) {  /* unlock */
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+  }
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, FALSE, "alloc coded buffer failed.\n");
+
+  /* init queue available_code_buffers */
+  g_mutex_lock(h264_prv->code_buffer_lock);
+  for (i = 0; i < h264_prv->coded_buf_num; i++) {
+    g_queue_push_head(h264_prv->available_code_buffers, &h264_prv->coded_bufs[i]);
   }
+  g_cond_signal(h264_prv->code_buffer_cond);
+  g_mutex_unlock(h264_prv->code_buffer_lock);
+
+end:
   return ret;
 }
 
+static void
+wait_and_clear_available_coded_buffers(GstH264EncoderPrivate *h264_prv,
+                                    GstVaapiDisplay *display, gboolean need_display_lock)
+{
+  guint32 available_buf_count = h264_prv->coded_buf_num;
+  VADisplay va_dpy = gst_vaapi_display_get_display(display);
+  VAStatus va_status = VA_STATUS_SUCCESS;
+  guint32 i = 0;
+
+  g_mutex_lock(h264_prv->code_buffer_lock);
+  while (available_buf_count) {
+    if (g_queue_is_empty(h264_prv->available_code_buffers)) {
+      g_cond_wait(h264_prv->code_buffer_cond, h264_prv->code_buffer_lock);
+    } else {
+      g_queue_pop_head(h264_prv->available_code_buffers);
+      available_buf_count--;
+    }
+  }
+  g_mutex_unlock(h264_prv->code_buffer_lock);
+
+  if (need_display_lock) {
+    GST_VAAPI_DISPLAY_LOCK(display);
+  }
+  for (i = 0; i < h264_prv->coded_buf_num; i++) {
+    va_status = vaDestroyBuffer(va_dpy, h264_prv->coded_bufs[i]);
+  }
+  if (need_display_lock) {
+    GST_VAAPI_DISPLAY_UNLOCK(display);
+  }
+
+  if (h264_prv->coded_bufs) {
+    g_free(h264_prv->coded_bufs);
+    h264_prv->coded_bufs = NULL;
+  }
+}
+
 static EncoderStatus
-h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
+h264_put_raw_buffer_to_surface(GstH264Encoder *h264_encoder,
+                               GstVaapiDisplay *display,
                                GstBuffer *raw_pic,
                                GstVaapiSurface *surface)
 {
@@ -858,14 +879,14 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
   VADisplay va_dpy;
   GstVaapiImage *image;
   GstVaapiImageFormat image_format;
-  uint8_t *y_src = NULL, *u_src = NULL, *v_src = NULL;
-  uint8_t *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
+  guint8 *y_src = NULL, *u_src = NULL, *v_src = NULL;
+  guint8 *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
   int y_size = 0, u_size = 0;
   int row = 0, col = 0;
-  uint32_t plane_count = 0;
-  uint32_t image_width = 0, image_height = 0;
-  uint32_t pitchy = 0, pitchu = 0, pitchv = 0;
-  GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
+  guint32 plane_count = 0;
+  guint32 image_width = 0, image_height = 0;
+  guint32 pitchy = 0, pitchu = 0, pitchv = 0;
+  GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
 
   ENCODER_ASSERT(display);
   va_dpy = gst_vaapi_display_get_display(display);
@@ -880,8 +901,8 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
   /* copy buffer to surface */
   ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
 
-  y_size = ENCODER_WIDTH(h264_prv->public) * ENCODER_HEIGHT(h264_prv->public);
-  u_size = ((ENCODER_WIDTH(h264_prv->public)+1) >> 1) * ((ENCODER_HEIGHT(h264_prv->public)+1) >> 1);
+  y_size = ENCODER_WIDTH(h264_encoder) * ENCODER_HEIGHT(h264_encoder);
+  u_size = ((ENCODER_WIDTH(h264_encoder)+1) >> 1) * ((ENCODER_HEIGHT(h264_encoder)+1) >> 1);
 
   y_src = GST_BUFFER_DATA(raw_pic);
   u_src = y_src + y_size;
@@ -903,7 +924,7 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
   for (row = 0; row < image_height; row++) {
       memcpy(y_dst, y_src, image_width);
       y_dst += pitchy;
-      y_src += ENCODER_WIDTH(h264_prv->public);
+      y_src += ENCODER_WIDTH(h264_encoder);
   }
 
   if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
@@ -915,13 +936,13 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
           }
 
           u_dst += pitchu;
-          u_src += (ENCODER_WIDTH(h264_prv->public)>>1);
-          v_src += (ENCODER_WIDTH(h264_prv->public)>>1);
+          u_src += (ENCODER_WIDTH(h264_encoder)>>1);
+          v_src += (ENCODER_WIDTH(h264_encoder)>>1);
       }
     } else if (GST_VAAPI_IMAGE_NV12 == h264_prv->format){
       for (row = 0; row < image_height / 2; row++) {
         memcpy(u_dst, u_src, image_width);
-        u_src += ENCODER_WIDTH(h264_prv->public);
+        u_src += ENCODER_WIDTH(h264_encoder);
         u_dst += pitchu;
       }
     } else {
@@ -940,39 +961,41 @@ h264_put_raw_buffer_to_surface(GstH264EncoderPrivate *h264_prv,
 
 
 static EncoderStatus
-h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gboolean is_key, VABufferID coded_buf)
+h264_prepare_encoding(GstH264Encoder *h264_encoder, GstVaapiDisplay *display,
+                        GstVaapiContext *context, gboolean is_key, VABufferID coded_buf)
 {
   EncoderStatus ret = ENCODER_NO_ERROR;
   VAStatus va_status = VA_STATUS_SUCCESS;
-  GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
+  GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
 
   VAEncPictureParameterBufferH264 pic_h264;
   VAEncSliceParameterBuffer *slice_h264 = NULL;
 
-  ENCODER_ASSERT(display);
-  ENCODER_ASSERT(h264_prv->vaapi_context);
+  gboolean is_locked = FALSE;
+
+  ENCODER_ASSERT(display && context);
   VADisplay va_dpy = gst_vaapi_display_get_display(display);
-  VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
+  VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
 
   /* lock display */
-  GST_VAAPI_DISPLAY_LOCK(display);
+  ENCODER_ACQUIRE_DISPLAY_LOCK(display);
   /*handle first surface_index*/
   /*only need first frame*/
   if (VA_INVALID_ID == h264_prv->seq_parameter) { /*first time*/
     VAEncSequenceParameterBufferH264 seq_h264 = {0};
 
-    seq_h264.level_idc = h264_prv->public->level; /* 3.0 */
+    seq_h264.level_idc = h264_encoder->level; /* 3.0 */
     seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
-    seq_h264.picture_width_in_mbs = (ENCODER_WIDTH(h264_prv->public)+15)/16;
-    seq_h264.picture_height_in_mbs = (ENCODER_HEIGHT(h264_prv->public)+15)/16;
+    seq_h264.picture_width_in_mbs = (ENCODER_WIDTH(h264_encoder)+15)/16;
+    seq_h264.picture_height_in_mbs = (ENCODER_HEIGHT(h264_encoder)+15)/16;
 
-    seq_h264.bits_per_second = h264_prv->public->bitrate;
-    seq_h264.frame_rate = ENCODER_FPS(h264_prv->public);
-    seq_h264.initial_qp = h264_prv->public->init_qp; /*qp_value; 15, 24, 26?*/
-    seq_h264.min_qp = h264_prv->public->min_qp;     /*1, 6, 10*/
+    seq_h264.bits_per_second = h264_encoder->bitrate;
+    seq_h264.frame_rate = ENCODER_FPS(h264_encoder);
+    seq_h264.initial_qp = h264_encoder->init_qp; /*qp_value; 15, 24, 26?*/
+    seq_h264.min_qp = h264_encoder->min_qp;     /*1, 6, 10*/
     seq_h264.basic_unit_size = 0;
-    seq_h264.intra_period = h264_prv->public->intra_period;
-    seq_h264.intra_idr_period = h264_prv->public->intra_period;
+    seq_h264.intra_period = h264_encoder->intra_period;
+    seq_h264.intra_idr_period = h264_encoder->intra_period;
 
     va_status = vaCreateBuffer(va_dpy, context_id,
                                VAEncSequenceParameterBufferType,
@@ -984,19 +1007,19 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool
 
   /* set pic_parameters*/
   if (!h264_prv->ref_surface) {
-    h264_prv->ref_surface = h264_pop_free_surface(h264_prv);
+    h264_prv->ref_surface = gst_vaapi_context_get_surface(context);
     ENCODER_CHECK_STATUS(h264_prv->ref_surface, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
   }
   if (!h264_prv->recon_surface) {
-    h264_prv->recon_surface = h264_pop_free_surface(h264_prv);
+    h264_prv->recon_surface = gst_vaapi_context_get_surface(context);
     ENCODER_CHECK_STATUS(h264_prv->recon_surface, ENCODER_SURFACE_ERR, "reconstructed surface, h264_pop_free_surface failed.\n");
   }
 
   pic_h264.reference_picture = GST_VAAPI_OBJECT_ID(h264_prv->ref_surface);
   pic_h264.reconstructed_picture = GST_VAAPI_OBJECT_ID(h264_prv->recon_surface);
   pic_h264.coded_buf = coded_buf;
-  pic_h264.picture_width = ENCODER_WIDTH(h264_prv->public);
-  pic_h264.picture_height = ENCODER_HEIGHT(h264_prv->public);
+  pic_h264.picture_width = ENCODER_WIDTH(h264_encoder);
+  pic_h264.picture_height = ENCODER_HEIGHT(h264_encoder);
   pic_h264.last_picture = 0; // last pic or not
 
   if (VA_INVALID_ID != h264_prv->pic_parameter) { /* share the same pic_parameter*/
@@ -1013,11 +1036,11 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool
 
   /* set slice parameters, support multiple slices */
   int i = 0;
-  uint32_t last_row_num = 0;
-  uint32_t slice_mod_num = h264_prv->slice_mod_mb_num;
+  guint32 last_row_num = 0;
+  guint32 slice_mod_num = h264_prv->slice_mod_mb_num;
 
-  memset(h264_prv->slice_param_buffers, 0, h264_prv->public->slice_num*sizeof(h264_prv->slice_param_buffers[0]));
-  for (i = 0; i < h264_prv->public->slice_num; ++i) {
+  memset(h264_prv->slice_param_buffers, 0, h264_encoder->slice_num*sizeof(h264_prv->slice_param_buffers[0]));
+  for (i = 0; i < h264_encoder->slice_num; ++i) {
     slice_h264 = &h264_prv->slice_param_buffers[i];
     slice_h264->start_row_number = last_row_num;               /* unit MB*/
     slice_h264->slice_height = h264_prv->default_slice_height; /* unit MB */
@@ -1030,7 +1053,7 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool
     slice_h264->slice_flags.bits.disable_deblocking_filter_idc = 0;
 
   }
-  ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(h264_prv->public)+15)/16);
+  ENCODER_ASSERT(last_row_num == (ENCODER_HEIGHT(h264_encoder)+15)/16);
 
   if (VA_INVALID_ID != h264_prv->slice_parameter) {
     vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
@@ -1040,7 +1063,7 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool
                              context_id,
                              VAEncSliceParameterBufferType,
                              sizeof(h264_prv->slice_param_buffers[0]),
-                             h264_prv->public->slice_num,
+                             h264_encoder->slice_num,
                              h264_prv->slice_param_buffers,
                              &h264_prv->slice_parameter);
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating slice-parameters buffer failed.\n");
@@ -1048,20 +1071,20 @@ h264_prepare_encoding(GstH264EncoderPrivate *h264_prv, GstBuffer *raw_pic, gbool
   va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->slice_parameter, 1);
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering slice-parameters buffer failed.\n");
 
-
   /*after finished, set ref_surface_index, recon_surface_index */
   GstVaapiSurface *swap = h264_prv->ref_surface;
   h264_prv->ref_surface = h264_prv->recon_surface;
   h264_prv->recon_surface = swap;
 
   end:
-  GST_VAAPI_DISPLAY_UNLOCK(display);
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
   return ret;
 }
 
 static EncoderStatus
-h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
-                           VASurfaceID surface_id,
+h264_query_encoding_status(GstH264Encoder *h264_encoder,
+                           GstVaapiDisplay *display,
+                           GstVaapiSurface *buffer_surface,
                            gboolean is_key,
                            GstClockTime timestamp,
                            GstClockTime duration,
@@ -1075,19 +1098,16 @@ h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
   GstBuffer* ret_buffer = NULL;
   gboolean has_coded_data = FALSE;
   gboolean is_locked = FALSE;
+  GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
 
-  GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
-
-  ENCODER_ASSERT(display);
-  ENCODER_ASSERT(h264_prv->vaapi_context);
+  ENCODER_ASSERT(display && context);
+  VASurfaceID surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
   VADisplay va_dpy = gst_vaapi_display_get_display(display);
-  //VAContextID context_id = GST_VAAPI_OBJECT_ID(h264_prv->vaapi_context);
 
   ENCODER_ASSERT(coded_pics && *coded_pics == NULL);
 
   /* lock display */
-  GST_VAAPI_DISPLAY_LOCK(display);
-  is_locked = TRUE;
+  ENCODER_ACQUIRE_DISPLAY_LOCK(display);
 
   va_status = vaSyncSurface(va_dpy, surface_id);
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaSyncSurface failed.\n");
@@ -1102,10 +1122,7 @@ h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
 
   /*unlock display*/
-  if (is_locked) {
-    GST_VAAPI_DISPLAY_UNLOCK(display);
-    is_locked = FALSE;
-  }
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
 
   while (buf_list != NULL) {
       if (!h264_prv->sps_data || !h264_prv->pps_data) {
@@ -1127,36 +1144,30 @@ h264_query_encoding_status(GstH264EncoderPrivate *h264_prv,
   if (!has_coded_data)
 #endif
   { // if non-related, push back to available_code_buffers
-    g_mutex_lock(h264_prv->code_buffer_lock);
-    GST_VAAPI_DISPLAY_LOCK(display);
+    ENCODER_ACQUIRE_DISPLAY_LOCK(display);
     vaUnmapBuffer(va_dpy, *coded_buf);
-    GST_VAAPI_DISPLAY_UNLOCK(display);
-    g_queue_push_head(h264_prv->available_code_buffers, coded_buf);
-    g_cond_signal(h264_prv->code_buffer_cond);
-    g_mutex_unlock(h264_prv->code_buffer_lock);
+    ENCODER_RELEASE_DISPLAY_LOCK(display);
+    push_available_coded_buffer(h264_prv, coded_buf);
   }
 
   return ENCODER_NO_ERROR;
 
-  end:
+end:
   /*unlock display*/
-  if (is_locked) {
-    GST_VAAPI_DISPLAY_UNLOCK(display);
-    is_locked = FALSE;
-  }
+  ENCODER_RELEASE_DISPLAY_LOCK(display);
   return ret;
 }
 
 static GstBuffer *
 h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
-                                        uint8_t *frame,
-                                        uint32_t frame_size,
+                                        guint8 *frame,
+                                        guint32 frame_size,
                                         VABufferID *coded_buf)
 {
   GstBuffer *ret_buffer;
-  uint32_t   nal_size;
-  const uint8_t   *nal_start;
-  uint8_t  *frame_end;
+  guint32   nal_size;
+  const guint8   *nal_start;
+  guint8  *frame_end;
 
 #if SHARE_CODED_BUF
   ret_buffer = gst_h264_encode_buffer_new(h264_prv, coded_buf);
@@ -1203,12 +1214,12 @@ h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
 }
 
 static EncoderStatus
-h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, uint32_t size)
+h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const guint8 *buf, guint32 size)
 {
-  const uint8_t *end = buf + size;
-  const uint8_t *nal_start = buf;
-  uint32_t nal_size = 0;
-  uint8_t nal_type;
+  const guint8 *end = buf + size;
+  const guint8 *nal_start = buf;
+  guint32 nal_size = 0;
+  guint8 nal_type;
   GstBuffer *sps = NULL, *pps = NULL;
 
   while((!sps || !pps) && (nal_start = h264_next_nal(nal_start, end-nal_start, &nal_size)) != NULL) {
@@ -1248,8 +1259,8 @@ h264_encoder_read_sps_pps(GstH264EncoderPrivate *h264_prv, const uint8_t *buf, u
 }
 
 static gboolean
-h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
-                                uint32_t *profile_idc, uint32_t *profile_comp, uint32_t *level_idc)
+h264_read_sps_attributes(const guint8 *sps_data, guint32 sps_size,
+                                guint32 *profile_idc, guint32 *profile_comp, guint32 *level_idc)
 {
   ENCODER_ASSERT(profile_idc && profile_comp && level_idc);
   ENCODER_ASSERT(sps_size >= 4);
@@ -1265,12 +1276,12 @@ h264_read_sps_attributes(const uint8_t *sps_data, uint32_t sps_size,
 
 
 EncoderStatus
-gst_h264_encoder_flush(GstVaapiEncoder* encoder, GList **coded_pics)
+gst_h264_encoder_flush(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
+                       GstVaapiContext *context, GList **coded_pics)
 {
   GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
   EncoderStatus ret = ENCODER_NO_ERROR;
   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
-  GstVaapiDisplay *display = ENCODER_DISPLAY(h264_prv->public);
 
   h264_prv->frame_count = 0;
   /*do we need destroy h264_prv->seq_parameter? */
@@ -1293,11 +1304,11 @@ int main_test(int argc, char* argv[])
 
   GList *coded_pics = NULL;
   GstBuffer **raw_buffer = NULL;
-  const uint32_t raw_buffer_num = 20;
+  const guint32 raw_buffer_num = 20;
 
   GstBuffer *tmp_buffer;
 
-  uint32_t i = 0, k = 0;
+  guint32 i = 0, k = 0;
 
   gst_init (&argc, &argv);
 
@@ -1321,11 +1332,11 @@ int main_test(int argc, char* argv[])
   ret = gst_vaapi_encoder_open(encoder, NULL);
   ENCODER_ASSERT(ret == ENCODER_NO_ERROR);
 
-  uint32_t buffer_size = encoder->width * encoder->width *3 /2;
-  uint32_t y_width = encoder->width, y_size = encoder->width * encoder->height;
-  uint32_t u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
-  uint32_t v_width = encoder->width/2;
-  uint8_t *y_src, *u_src, *v_src;
+  guint32 buffer_size = encoder->width * encoder->width *3 /2;
+  guint32 y_width = encoder->width, y_size = encoder->width * encoder->height;
+  guint32 u_width = encoder->width/2, u_size = (encoder->width/2) * (encoder->height/2);
+  guint32 v_width = encoder->width/2;
+  guint8 *y_src, *u_src, *v_src;
 
   /*set buffers*/
   int box_width=8;
@@ -1382,9 +1393,9 @@ gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffe
   GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
   GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
   GstBuffer *avc_codec;
-  const uint32_t configuration_version = 0x01;
-  const uint32_t length_size_minus_one = 0x03;
-  uint32_t profile, profile_comp, level_idc;
+  const guint32 configuration_version = 0x01;
+  const guint32 length_size_minus_one = 0x03;
+  guint32 profile, profile_comp, level_idc;
 
   ENCODER_ASSERT(buffer);
   if (!h264_prv->sps_data || !h264_prv->pps_data) {
@@ -1471,7 +1482,7 @@ gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer
 }
 
 static void
-h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability)
+h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability)
 {
   bitstream->bit_size = 0;
   bitstream->buffer = NULL;
@@ -1482,12 +1493,12 @@ h264_bitstream_init(H264Bitstream *bitstream, uint32_t bit_capability)
 }
 
 static gboolean
-h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit_size)
+h264_bitstream_write_uint(H264Bitstream *bitstream, guint32 value, guint32 bit_size)
 {
   gboolean ret = TRUE;
-  uint32_t byte_pos, bit_offset;
-  uint8_t  *cur_byte;
-  uint32_t fill_bits;
+  guint32 byte_pos, bit_offset;
+  guint8  *cur_byte;
+  guint32 fill_bits;
 
   if(!bit_size) {
     return TRUE;
@@ -1515,9 +1526,9 @@ h264_bitstream_write_uint(H264Bitstream *bitstream, uint32_t value, uint32_t bit
   return FALSE;
 }
 
-static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value)
+static gboolean h264_bitstream_align(H264Bitstream *bitstream, guint32 value)
 {
-  uint32_t bit_offset, bit_left;
+  guint32 bit_offset, bit_left;
 
   bit_offset = (bitstream->bit_size&0x07);
   if (!bit_offset) {
@@ -1530,7 +1541,7 @@ static gboolean h264_bitstream_align(H264Bitstream *bitstream, uint32_t value)
 
 
 static gboolean
-h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, uint32_t byte_size)
+h264_bitstream_write_byte_array(H264Bitstream *bitstream, const guint8 *buf, guint32 byte_size)
 {
   gboolean ret = TRUE;
   if (!byte_size) {
@@ -1550,16 +1561,16 @@ h264_bitstream_write_byte_array(H264Bitstream *bitstream, const uint8_t *buf, ui
   }
   return TRUE;
 
-  end:
+end:
   return FALSE;
 }
 
 static gboolean
-h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value)
+h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value)
 {
   gboolean ret = TRUE;
-  uint32_t size_in_bits = 0;
-  uint32_t tmp_value = ++value;
+  guint32  size_in_bits = 0;
+  guint32  tmp_value = ++value;
   while (tmp_value) {
     ++size_in_bits;
     tmp_value >>= 1;
@@ -1568,15 +1579,15 @@ h264_bitstream_write_ue(H264Bitstream *bitstream, uint32_t value)
   ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
   return TRUE;
 
-  end:
+end:
   return FALSE;
 }
 
 static gboolean
-h264_bitstream_write_se(H264Bitstream *bitstream, int32_t value)
+h264_bitstream_write_se(H264Bitstream *bitstream, guint32 value)
 {
   gboolean ret = TRUE;
-  uint32_t new_val;
+  guint32 new_val;
 
   if (value <= 0) {
     new_val = -(value<<1);
@@ -1611,10 +1622,10 @@ h264_bitstream_destroy(H264Bitstream *bitstream, gboolean free_flag)
 }
 
 static gboolean
-h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size)
+h264_bitstream_auto_grow(H264Bitstream *bitstream, guint32 extra_bit_size)
 {
-  uint32_t new_bit_size = extra_bit_size + bitstream->bit_size;
-  uint32_t clear_pos;
+  guint32 new_bit_size = extra_bit_size + bitstream->bit_size;
+  guint32 clear_pos;
 
   ENCODER_ASSERT(bitstream->bit_size <= bitstream->max_bit_capability);
   if (new_bit_size <= bitstream->max_bit_capability) {
@@ -1634,21 +1645,21 @@ h264_bitstream_auto_grow(H264Bitstream *bitstream, uint32_t extra_bit_size)
 static gboolean
 h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_prv)
 {
-  uint32_t constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
-  uint32_t seq_parameter_set_id = 0;
+  guint32 constraint_set0_flag, constraint_set1_flag, constraint_set2_flag, constraint_set3_flag;
+  guint32 seq_parameter_set_id = 0;
 
   /*need to set the values*/
-  uint32_t log2_max_frame_num_minus4 = 0;  // 1? 3?
-  uint32_t pic_order_cnt_type = 0; // Must be 0
-  uint32_t log2_max_pic_order_cnt_lsb_minus4 = 0;  // 2 ? 4?
-  uint32_t num_ref_frames = 1;  // only P frames
-  uint32_t gaps_in_frame_num_value_allowed_flag = 0; // ??
-  uint32_t mb_width = (ENCODER_WIDTH(h264_prv->public)+15)/16; // mb_width
-  uint32_t mb_height = (ENCODER_HEIGHT(h264_prv->public)+15)/16; // mb_height
-  int32_t frame_mbs_only_flag = 1; // only mbs
-  uint32_t frame_cropping_flag = 0;
-  uint32_t frame_crop_bottom_offset = 0;
-  uint32_t vui_present_flag = 0; // no vui flags
+  guint32 log2_max_frame_num_minus4 = 0;  // 1? 3?
+  guint32 pic_order_cnt_type = 0; // Must be 0
+  guint32 log2_max_pic_order_cnt_lsb_minus4 = 0;  // 2 ? 4?
+  guint32 num_ref_frames = 1;  // only P frames
+  guint32 gaps_in_frame_num_value_allowed_flag = 0; // ??
+  guint32 mb_width = (ENCODER_WIDTH(h264_prv->public)+15)/16; // mb_width
+  guint32 mb_height = (ENCODER_HEIGHT(h264_prv->public)+15)/16; // mb_height
+  guint32 frame_mbs_only_flag = 1; // only mbs
+  guint32 frame_cropping_flag = 0;
+  guint32 frame_crop_bottom_offset = 0;
+  guint32 vui_present_flag = 0; // no vui flags
 
 
   constraint_set0_flag = h264_prv->public->profile == H264_PROFILE_BASELINE;
@@ -1715,14 +1726,14 @@ h264_bitstream_write_sps(H264Bitstream *bitstream, GstH264EncoderPrivate *h264_p
 
 }
 
-static const uint8_t *
-h264_next_nal(const uint8_t *buffer, uint32_t len, uint32_t *nal_size)
+static const guint8 *
+h264_next_nal(const guint8 *buffer, guint32 len, guint32 *nal_size)
 {
-    const uint8_t *cur = buffer;
-    const uint8_t *end = buffer + len;
-    const uint8_t *nal_start = NULL;
-    uint32_t flag = 0xFFFFFFFF;
-    uint32_t nal_start_len = 0;
+    const guint8 *cur = buffer;
+    const guint8 *end = buffer + len;
+    const guint8 *nal_start = NULL;
+    guint32 flag = 0xFFFFFFFF;
+    guint32 nal_start_len = 0;
 
     ENCODER_ASSERT(len >= 0 && buffer && nal_size);
     if (len < 3) {
index 785a3db..7c8b809 100644 (file)
@@ -62,17 +62,13 @@ typedef enum {
 struct _GstH264Encoder {
   GstVaapiEncoder parent;   /*based on gobject*/
 
-  uint32_t profile;
-  uint32_t level;
-  //uint32_t width;
-  //uint32_t height;
-  //uint32_t frame_rate;
-  uint32_t bitrate;
-  uint32_t intra_period;
-  int32_t  init_qp;  /*default 24*/
-  int32_t  min_qp;   /*default 1*/
-  uint32_t slice_num;
-  /* private data; */
+  guint32         profile;
+  guint32         level;
+  guint32         bitrate;
+  guint32         intra_period;
+  guint32         init_qp;  /*default 24*/
+  guint32         min_qp;   /*default 1*/
+  guint32         slice_num;
 };
 
 struct _GstH264EncoderClass {
@@ -88,7 +84,7 @@ static inline void gst_h264_encoder_unref (GstH264Encoder * encoder)
   g_object_unref (encoder);
 }
 
-void     gst_h264_encoder_set_input_format(GstH264Encoder* encoder, uint32_t format);
+void     gst_h264_encoder_set_input_format(GstH264Encoder* encoder, guint32 format);
 void     gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es);