add Intel Copyright
[profile/ivi/gstreamer-vaapi.git] / gst / vaapiencode / gstvaapih264encoder.c
index 4d7a039..71b3e63 100644 (file)
@@ -1,3 +1,23 @@
+/*
+ *  gstvaapih264encoder.c -  H.264 encoder
+ *
+ *  Copyright (C) 2011 Intel Corporation
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1
+ *  of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free
+ *  Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ *  Boston, MA 02110-1301 USA
+ */
 
 #include "gstvaapih264encoder.h"
 
@@ -63,12 +83,6 @@ typedef enum {
   SLICE_TYPE_I  = 2
 } H264_SLICE_TYPE;
 
-struct _GstH264EncodeBuffer {
-  GstBuffer           buffer;
-  VABufferID         *coded_id;
-  GstH264EncoderPrivate *encoder;
-};
-
 struct _GstH264EncoderPrivate {
   GstH264Encoder   *public;
   guint32           format;   /*NV12, I420,*/
@@ -212,115 +226,6 @@ gst_h264_encoder_class_init(GstH264EncoderClass *klass)
   */
 }
 
-
-static void
-gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data)
-{
-  GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
-
-  h264_encode_buffer_parent_class = g_type_class_peek_parent(g_class);
-  ENCODER_ASSERT(h264_encode_buffer_parent_class);
-
-  mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
-      gst_h264_encode_buffer_finalize;
-}
-
-
-static GType
-gst_h264_encode_buffer_get_type (void)
-{
-  static GType s_h264_encode_buffer_type = 0;
-  if (G_UNLIKELY (s_h264_encode_buffer_type == 0)) {
-    static const GTypeInfo s_h264_encode_buffer_info = {
-      sizeof(GstBufferClass),
-      NULL,
-      NULL,
-      gst_h264_encode_buffer_class_init,
-      NULL,
-      NULL,
-      sizeof(GstH264EncodeBuffer),
-      0,
-      NULL,
-      NULL
-    };
-    s_h264_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
-        "GstH264EncodeBuffer", &s_h264_encode_buffer_info, 0);
-  }
-  return s_h264_encode_buffer_type;
-}
-
-static void
-gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer)
-{
-  GstH264EncoderPrivate *h264_prv = NULL;
-  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);
-  VADisplay va_dpy = gst_vaapi_display_get_display(display);
-
-  ENCODER_ASSERT(h264_prv);
-  ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
-
-  /*if (--(*h264_buffer->ref_coded_id) == 0) */
-  {
-    /*g_free(h264_buffer->ref_coded_id);*/
-    ENCODER_ACQUIRE_DISPLAY_LOCK(display);
-    vaUnmapBuffer(va_dpy, *coded_id);
-    ENCODER_RELEASE_DISPLAY_LOCK(display);
-    push_available_coded_buffer(h264_prv, coded_id);
-  }
-
-  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));
-  }
-}
-
-static GstH264EncodeBuffer *
-gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
-                           VABufferID *coded_id)
-{
-  GstH264EncodeBuffer *buf = (GstH264EncodeBuffer*)gst_mini_object_new(GST_TYPE_H264_ENCODE_BUFFER);
-  buf->coded_id = coded_id;
-  buf->encoder = h264_prv;
-  return buf;
-}
-
-
-static GstVaapiSurface *
-h264_get_video_surface(GstH264EncoderPrivate *h264_prv, GstVaapiVideoBuffer *video_buffer)
-{
-  //ref_surface
-  GstVaapiSurface *ret = gst_vaapi_video_buffer_get_surface(video_buffer);
-
-  ENCODER_CHECK_STATUS(ret, NULL, "video buffer doesn't have a surface");
-#if 0
-  g_queue_push_tail(h264_prv->video_buffer_caches,video_buffer);
-  gst_buffer_ref(GST_BUFFER(video_buffer));
-#endif
-  return ret;
-
-  end:
-  return NULL;
-}
-
-static void
-h264_release_video_surface(GstH264EncoderPrivate *h264_prv, VASurfaceID surface)
-{
-#if 0
-  ENCODER_ASSERT(h264_prv->video_buffer_caches);
-  g_queue_find_custom(h264_prv->video_buffer_caches,xx, compare_func);
-  for (h264_prv->video_buffer_caches) {
-  }
-#endif
-}
-
 static VAProfile
 h264_get_va_profile(guint32 profile)
 {
@@ -679,9 +584,7 @@ gst_h264_encoder_prepare_next_buffer(GstVaapiBaseEncoder* encoder,
   GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
   GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
   GstVaapiVideoBuffer  *return_buf = NULL;
-  GstVaapiVideoBuffer  *tmp_next_buf = NULL;
-  guint64 pts = 0;
-  guint32 cts = 0;
+  //guint64 pts = 0;
 
   if (NULL == display_buf && g_queue_is_empty(h264_prv->queued_buffers)) {
     ret = ENCODER_BUFFER_EMPTY;
@@ -736,6 +639,7 @@ gst_h264_encoder_prepare_next_buffer(GstVaapiBaseEncoder* encoder,
 end:
   *out_buf = return_buf;
   /* calculate cts/pts/dts */
+#if 0
   if (return_buf) {
     pts = GST_BUFFER_TIMESTAMP(return_buf);
     tmp_next_buf = (GstVaapiVideoBuffer*)g_queue_peek_head(h264_prv->queued_buffers);
@@ -744,13 +648,17 @@ end:
     } else if (SLICE_TYPE_B == h264_prv->cur_slice_type) {
       GST_BUFFER_TIMESTAMP(return_buf) = h264_prv->last_decode_time;
     }
-    cts = (pts + h264_prv->default_cts_offset - GST_BUFFER_TIMESTAMP(return_buf));
-    ENCODER_ASSERT(cts < 0x80000000);
-    if (cts > 0x80000000) {
-      cts = 0;
+
+    pts += h264_prv->default_cts_offset;
+    if ((gint64)(pts - GST_BUFFER_TIMESTAMP(return_buf)) < 0) {
+      pts = GST_BUFFER_TIMESTAMP(return_buf);
     }
-    GST_BUFFER_OFFSET_END(return_buf) = cts;
+
+    GST_BUFFER_OFFSET_END(return_buf) = pts;
+    GST_BUFFER_TIMESTAMP(return_buf) = pts;
   }
+#endif
+
   return ret;
 }
 
@@ -798,19 +706,23 @@ gst_h264_encoder_rendering(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *displa
     va_status = vaCreateBuffer(va_dpy, context_id,
                                VAEncSequenceParameterBufferType,
                                sizeof(seq_h264), 1, &seq_h264, &h264_prv->seq_parameter);
-    ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_ENC_RES_ERR, "alloc seq-buffer failed.\n");
+    ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                         ENCODER_ENC_RES_ERR, "alloc seq-buffer failed.");
     va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->seq_parameter, 1);
-    ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaRenderPicture seq-parameters failed.\n");
+    ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
+                         ENCODER_PICTURE_ERR, "vaRenderPicture seq-parameters failed.");
   }
 
   /* set pic_parameters*/
   if (!h264_prv->ref_surface1) {
     h264_prv->ref_surface1 = gst_vaapi_context_get_surface(context);
-    ENCODER_CHECK_STATUS(h264_prv->ref_surface1, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
+    ENCODER_CHECK_STATUS(h264_prv->ref_surface1, ENCODER_SURFACE_ERR,
+                         "reference surface, h264_pop_free_surface failed.");
   }
   if (!h264_prv->recon_surface) {
     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");
+    ENCODER_CHECK_STATUS(h264_prv->recon_surface, ENCODER_SURFACE_ERR,
+                         "reconstructed surface, h264_pop_free_surface failed.");
   }
 
   pic_h264.reference_picture = GST_VAAPI_OBJECT_ID(h264_prv->ref_surface1);
@@ -827,10 +739,12 @@ gst_h264_encoder_rendering(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *displa
   va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
                                sizeof(pic_h264), 1, &pic_h264, &h264_prv->pic_parameter);
 
-  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "creating pic-param buffer failed.\n");
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       ENCODER_PICTURE_ERR, "creating pic-param buffer failed.");
 
   va_status = vaRenderPicture(va_dpy, context_id, &h264_prv->pic_parameter, 1);
-  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_PICTURE_ERR, "rendering pic-param buffer failed.\n");
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       ENCODER_PICTURE_ERR, "rendering pic-param buffer failed.");
 
   /* set slice parameters, support multiple slices */
   int i = 0;
@@ -864,10 +778,12 @@ gst_h264_encoder_rendering(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *displa
                              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");
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       ENCODER_PICTURE_ERR, "creating slice-parameters buffer failed.");
 
   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");
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       ENCODER_PICTURE_ERR, "rendering slice-parameters buffer failed.");
 
   /*after finished, set ref_surface1_index, recon_surface_index */
   GstVaapiSurface *swap = h264_prv->ref_surface1;
@@ -924,7 +840,7 @@ h264_recreate_seq_param(GstH264Encoder *h264_encoder,
   else if (h264_encoder->init_qp == -2)
       seq_h264.rate_control_method = BR_VBR;
   else {
-      assert(h264_encoder->init_qp >= 0 && h264_encoder->init_qp <= 51);
+      ENCODER_ASSERT(h264_encoder->init_qp >= 0 && h264_encoder->init_qp <= 51);
       seq_h264.rate_control_method = BR_CQP;
   }
 
@@ -961,7 +877,7 @@ h264_recreate_seq_param(GstH264Encoder *h264_encoder,
                              sizeof(seq_h264), 1,
                              &seq_h264, &h264_prv->seq_parameter);
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
-                     FALSE, "alloc seq-buffer failed.\n");
+                     FALSE, "alloc seq-buffer failed.");
 
   /*pack sps header buffer/data */
   if (NULL == h264_prv->sps_data) {
@@ -1048,6 +964,14 @@ h264_recreate_pic_param(GstH264Encoder *h264_encoder,
   pic_h264.pic_fields.bits.transform_8x8_mode_flag = 1;
   pic_h264.pic_fields.bits.deblocking_filter_control_present_flag = 1;
 
+  char *frame_type = "I";
+  if (h264_prv->cur_slice_type == SLICE_TYPE_P)
+    frame_type = "P";
+  if (h264_prv->cur_slice_type == SLICE_TYPE_B)
+    frame_type = "B";
+  ENCODER_LOG_INFO("type:%s, frame_num:%d, display_num:%d",
+         frame_type, pic_h264.frame_num, pic_h264.CurrPic.TopFieldOrderCnt);
+
   if (VA_INVALID_ID != h264_prv->pic_parameter) { /* share the same pic_parameter*/
     vaDestroyBuffer(va_dpy, h264_prv->pic_parameter);
     h264_prv->pic_parameter = VA_INVALID_ID;
@@ -1055,7 +979,8 @@ h264_recreate_pic_param(GstH264Encoder *h264_encoder,
   va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType,
                                sizeof(pic_h264), 1, &pic_h264, &h264_prv->pic_parameter);
 
-  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, FALSE, "creating pic-param buffer failed.\n");
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       FALSE, "creating pic-param buffer failed.");
 
   //if (NULL == h264_prv->pps_data) {
   if (VA_INVALID_ID == h264_prv->packed_pps_data_buf) {
@@ -1166,7 +1091,8 @@ h264_recreate_slice_param(GstH264Encoder *h264_encoder,
                              h264_encoder->slice_num,
                              h264_prv->slice_param_buffers,
                              &h264_prv->slice_parameter);
-  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, FALSE, "creating slice-parameters buffer failed.\n");
+  ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status,
+                       FALSE, "creating slice-parameters buffer failed.");
 
 end:
   return ret;
@@ -1195,15 +1121,21 @@ gst_h264_encoder_rendering(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *displa
 
   if (!h264_prv->ref_surface1) {
     h264_prv->ref_surface1 = gst_vaapi_context_get_surface(context);
-    ENCODER_CHECK_STATUS(h264_prv->ref_surface1, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
+    ENCODER_CHECK_STATUS(h264_prv->ref_surface1,
+                         ENCODER_SURFACE_ERR,
+                         "reference surface, h264_pop_free_surface failed.");
   }
   if (!h264_prv->ref_surface2) {
     h264_prv->ref_surface2 = gst_vaapi_context_get_surface(context);
-    ENCODER_CHECK_STATUS(h264_prv->ref_surface2, ENCODER_SURFACE_ERR, "reference surface, h264_pop_free_surface failed.\n");
+    ENCODER_CHECK_STATUS(h264_prv->ref_surface2,
+                         ENCODER_SURFACE_ERR,
+                         "reference surface, h264_pop_free_surface failed.");
   }
   if (!h264_prv->recon_surface) {
     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");
+    ENCODER_CHECK_STATUS(h264_prv->recon_surface,
+                         ENCODER_SURFACE_ERR,
+                         "reconstructed surface, h264_pop_free_surface failed.");
   }
 
   if (SLICE_TYPE_P == h264_prv->cur_slice_type) {
@@ -1253,7 +1185,7 @@ gst_h264_encoder_rendering(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *displa
 
   va_status = vaRenderPicture(va_dpy, context_id, va_buffers, va_buffers_count);
   ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR,
-                       "vaRenderH264Picture failed.\n");
+                       "vaRenderH264Picture failed.");
 
   /*after finished,  swap  recon and surface2*/
   if (SLICE_TYPE_P == h264_prv->cur_slice_type ||
@@ -1628,7 +1560,9 @@ h264_bitstream_write_uint(H264Bitstream *bitstream, guint32 value, guint32 bit_s
   }
 
   VAAPI_UNUSED_ARG(ret);
-  ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size), FALSE, "h264_bitstream_auto_grow failed.\n");
+  ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, bit_size),
+                       FALSE,
+                       "h264_bitstream_auto_grow failed.");
   byte_pos = (bitstream->bit_size>>3);
   bit_offset = (bitstream->bit_size&0x07);
   cur_byte = bitstream->buffer + byte_pos;
@@ -1672,7 +1606,9 @@ h264_bitstream_write_byte_array(H264Bitstream *bitstream, const guint8 *buf, gui
   }
 
   VAAPI_UNUSED_ARG(ret);
-  ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3), FALSE, "h264_bitstream_auto_grow failed.\n");
+  ENCODER_CHECK_STATUS(TRUE == h264_bitstream_auto_grow(bitstream, byte_size<<3),
+                       FALSE,
+                       "h264_bitstream_auto_grow failed.");
   if (0 == (bitstream->bit_size&0x07)) {
     memcpy(&bitstream->buffer[bitstream->bit_size>>3], buf, byte_size);
     bitstream->bit_size += (byte_size<<3);
@@ -1699,8 +1635,12 @@ h264_bitstream_write_ue(H264Bitstream *bitstream, guint32 value)
     ++size_in_bits;
     tmp_value >>= 1;
   }
-  ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1), FALSE, "h264_bitstream_write_ue failed.\n");
-  ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits), FALSE, "h264_bitstream_write_ue failed.\n");
+  ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, 0, size_in_bits-1),
+                       FALSE,
+                       "h264_bitstream_write_ue failed.");
+  ENCODER_CHECK_STATUS(h264_bitstream_write_uint(bitstream, value, size_in_bits),
+                       FALSE,
+                       "h264_bitstream_write_ue failed.");
 
 end:
   return ret;
@@ -1718,7 +1658,9 @@ h264_bitstream_write_se(H264Bitstream *bitstream, gint32 value)
     new_val = (value<<1) - 1;
   }
 
-  ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val), FALSE, "h264_bitstream_write_se failed.\n");
+  ENCODER_CHECK_STATUS(h264_bitstream_write_ue(bitstream, new_val),
+                       FALSE,
+                       "h264_bitstream_write_se failed.");
 
 end:
   return ret;