+/*
+ * 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"
SLICE_TYPE_I = 2
} H264_SLICE_TYPE;
-struct _GstH264EncodeBuffer {
- GstBuffer buffer;
- VABufferID *coded_id;
- GstH264EncoderPrivate *encoder;
-};
-
struct _GstH264EncoderPrivate {
GstH264Encoder *public;
guint32 format; /*NV12, I420,*/
*/
}
-
-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)
{
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;
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);
} 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;
}
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);
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;
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;
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;
}
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) {
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;
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) {
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;
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) {
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 ||
}
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;
}
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);
++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;
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;