#include "gst/vaapi/gstvaapivideobuffer.h"
#include "gst/vaapi/gstvaapidisplay_priv.h"
-#define ENCPRV(encoder) GST_H264_ENCODER_GET_PRIVATE(encoder)
+GST_DEBUG_CATEGORY_STATIC (gst_vaapi_h264_encoder_debug);
+#define GST_CAT_DEFAULT gst_vaapi_h264_encoder_debug
#define SHARE_CODED_BUF 0
#define REF_RECON_SURFACE_NUM 2
-typedef struct _GstH264EncodeBuffer GstH264EncodeBuffer;
-
-#define GST_TYPE_H264_ENCODE_BUFFER (gst_h264_encode_buffer_get_type())
-
typedef enum {
NAL_UNKNOWN = 0,
NAL_NON_IDR = 1,
gboolean es_flag; /*elementary flag*/
/* private data*/
- //GstVaapiDisplay *vaapi_display;
- //GstVaapiContext *vaapi_context;
GQueue *video_buffer_caches; /*not used for baseline*/
GstVaapiSurface *ref_surface; /* reference buffer*/
GstVaapiSurface *recon_surface; /* reconstruct buffer*/
- //VAAPI_Encode_State encode_state;
-
VABufferID seq_parameter;
VABufferID pic_parameter;
VABufferID slice_parameter;
guint32 default_slice_height;
guint32 slice_mod_mb_num;
- VABufferID *coded_bufs;
- guint32 coded_buf_num;
- guint32 cur_coded_index;
-
- /*total encoded frames*/
- guint32 frame_count;
-
GstBuffer *sps_data;
GstBuffer *pps_data;
- GMutex *code_buffer_lock;
- GCond *code_buffer_cond;
- GQueue *available_code_buffers;
-
};
-G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_ENCODER);
+G_DEFINE_TYPE(GstH264Encoder, gst_h264_encoder, GST_TYPE_VAAPI_BASE_ENCODER);
// 4096-1
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, 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);
+ 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_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 gboolean gst_h264_validate_parameters(GstVaapiBaseEncoder *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 guint8 *buf, guint32 size);
-static GstBuffer *h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
- guint8 *frame,
- guint32 frame_size,
- VABufferID *coded_buf);
-
+static gboolean gst_h264_encoder_alloc_slices(GstVaapiBaseEncoder *encoder,
+ GstVaapiDisplay *display, GstVaapiContext *context);
+static gboolean gst_h264_encoder_release_resource(GstVaapiBaseEncoder* encoder,
+ GstVaapiDisplay *display, GstVaapiContext *context);
-/*encoded buffer, for SHARE_CODED_BUF */
-static void gst_h264_encode_buffer_class_init (gpointer g_class, gpointer class_data);
-static GType gst_h264_encode_buffer_get_type (void);
-static void gst_h264_encode_buffer_finalize (GstH264EncodeBuffer *h264_buffer);
-static GstH264EncodeBuffer *gst_h264_encode_buffer_new(GstH264EncoderPrivate *h264_prv,
- VABufferID *coded_id);
+static EncoderStatus gst_h264_prepare_encoding(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display,
+ GstVaapiContext *context, GstVaapiSurface *surface,
+ guint frame_index, VABufferID coded_buf, gboolean *is_key);
+static void gst_h264_notify_frame(GstVaapiBaseEncoder *encoder, guint8 *buf, guint32 size);
+//static EncoderStatus h264_encoder_read_sps_pps(
+// GstH264EncoderPrivate *h264_prv, const guint8 *buf, guint32 size);
+static GstBuffer *gst_h264_encoder_copy_coded_buffer(GstVaapiBaseEncoder *encoder,
+ guint8 *frame, guint32 frame_size, VABufferID *coded_buf);
/* h264 bitstream functions */
static void h264_bitstream_init(H264Bitstream *bitstream, guint32 bit_capability);
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)
{
GObjectClass * const object_class = G_OBJECT_CLASS(klass);
GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
+ GstVaapiBaseEncoderClass * const base_class = GST_VAAPI_BASE_ENCODER_CLASS(klass);
+
g_type_class_add_private(klass, sizeof(GstH264EncoderPrivate));
+ GST_DEBUG_CATEGORY_INIT (gst_vaapi_h264_encoder_debug, "gst_va_h264_encoder", 0,
+ "gst_va_h264_encoder element");
+
object_class->finalize = gst_h264_encoder_finalize;
- encoder_class->initialize = gst_h264_encoder_initialize;
- encoder_class->uninitialize = gst_h264_encoder_uninitialize;
- encoder_class->open = gst_h264_encoder_open;
- encoder_class->close = gst_h264_encoder_close;
- encoder_class->encode = gst_h264_encoder_encode;
+ base_class->validate_attributes = gst_h264_validate_parameters;
+ base_class->pre_alloc_resource = gst_h264_encoder_alloc_slices;
+ base_class->release_resource = gst_h264_encoder_release_resource;
+ base_class->prepare_frame = gst_h264_prepare_encoding;
+ base_class->notify_frame = gst_h264_notify_frame;
+ base_class->copy_coded_frame = gst_h264_encoder_copy_coded_buffer;
+
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; */
static void
gst_h264_encoder_init(GstH264Encoder *encoder)
{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
GstVaapiEncoderPrivate *encoder_prv = GST_VAAPI_ENCODER_GET_PRIVATE(encoder);
ENCODER_ASSERT(h264_prv);
h264_prv->public = encoder;
/* init public attributes */
gst_h264_encoder_init_public_values(encoder);
+ gst_vaapi_base_encoder_set_frame_notify(GST_VAAPI_BASE_ENCODER(encoder), TRUE);
/* init private values*/
h264_prv->format = GST_MAKE_FOURCC('N','V','1','2');
h264_prv->es_flag = TRUE;
- //h264_prv->vaapi_display = NULL;
h264_prv->ref_surface = NULL;
h264_prv->recon_surface = NULL;
- h264_prv->video_buffer_caches = g_queue_new();
- //h264_prv->encode_state = H264_ENC_NULL;
h264_prv->seq_parameter = VA_INVALID_ID;
h264_prv->pic_parameter = VA_INVALID_ID;
h264_prv->slice_parameter = VA_INVALID_ID;
h264_prv->default_slice_height = 0;
h264_prv->slice_mod_mb_num = 0;
- h264_prv->coded_bufs = NULL;
- h264_prv->coded_buf_num = DEFAULT_CODEDBUF_NUM;
- h264_prv->frame_count = 0;
h264_prv->sps_data = NULL;
h264_prv->pps_data = NULL;
- /*index init*/
- h264_prv->cur_coded_index = 0;
- /*init others*/
- h264_prv->code_buffer_lock = g_mutex_new();
- h264_prv->code_buffer_cond = g_cond_new();
- h264_prv->available_code_buffers = g_queue_new();
-
}
static void
{
/*free private buffers*/
GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
- GstH264EncoderPrivate *h264_prv = ENCPRV(object);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(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) {
- g_queue_free(h264_prv->available_code_buffers);
- h264_prv->available_code_buffers = NULL;
- }
-
- if (h264_prv->video_buffer_caches) {
- g_queue_free(h264_prv->video_buffer_caches);
- h264_prv->video_buffer_caches = NULL;
- };
if (h264_prv->sps_data) {
gst_buffer_unref(h264_prv->sps_data);
h264_prv->sps_data = NULL;
g_free(h264_prv->slice_param_buffers);
h264_prv->slice_param_buffers = NULL;
}
+
+ G_OBJECT_CLASS(gst_h264_encoder_parent_class)->finalize(object);
}
{
encoder->profile = 0;
encoder->level = 0;
- //encoder->width = 0;
- //encoder->height = 0;
- //encoder->frame_rate = 0;
encoder->bitrate = 0;
encoder->intra_period = 0;
encoder->init_qp = -1;
}
void
-gst_h264_encoder_set_input_format(GstH264Encoder* encoder, guint32 format)
-{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
- h264_prv->format = format;
-}
-
-void
gst_h264_encoder_set_es_flag(GstH264Encoder* encoder, gboolean es)
{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
h264_prv->es_flag = es;
}
-EncoderStatus
-gst_h264_encoder_initialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
-{
- return ENCODER_NO_ERROR;
-}
-
-EncoderStatus
-gst_h264_encoder_uninitialize(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
-{
- return ENCODER_NO_ERROR;
-
-}
gboolean
-gst_h264_validate_parameters(GstH264Encoder *encoder)
+gst_h264_validate_parameters(GstVaapiBaseEncoder *base_encoder)
{
- GstH264EncoderPrivate *h264_prv = ENCPRV(encoder);
+ GstH264Encoder *encoder = GST_H264_ENCODER(base_encoder);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
if (!ENCODER_WIDTH(encoder) || !ENCODER_HEIGHT(encoder) || !ENCODER_FPS(encoder)) {
return FALSE;
}
if (!encoder->profile) {
encoder->profile = H264_DEFAULT_PROFILE;
}
+ gst_vaapi_base_encoder_set_va_profile(base_encoder, h264_get_va_profile(encoder->profile));
if (!encoder->level) {
encoder->level = H264_DEFAULT_LEVEL;
}
return TRUE;
}
-EncoderStatus
-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;
- GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
- GstVaapiContext *out_context = NULL;
- VAProfile va_profile = -1;
- EncoderStatus ret = ENCODER_NO_ERROR;
+static gboolean
+h264_encoder_release_parameters(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
+{
VAStatus va_status = VA_STATUS_SUCCESS;
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
+ guint32 i;
- /*check and set default values*/
- ENCODER_CHECK_STATUS(gst_h264_validate_parameters(h264_encoder), ENCODER_PARAMETER_ERR, "h264encoder paramerter error.\n");
+ gboolean is_locked = FALSE;
- va_profile = h264_get_va_profile(h264_encoder->profile);
- ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
- ENCODER_CHECK_STATUS(-1 != va_profile, ENCODER_PROFILE_ERR, "profile(%d) is NOT supported.\n", h264_encoder->profile);
+ ENCODER_ASSERT(display);
+ ENCODER_ASSERT(context);
+ VADisplay va_dpy = gst_vaapi_display_get_display(display);
-#ifdef _MRST_
- out_context = g_object_new(
- GST_VAAPI_TYPE_CONTEXT,
- "display", display,
- "id", GST_VAAPI_ID(VA_INVALID_ID),
- "entrypoint", gst_vaapi_entrypoint(VAEntrypointEncSlice),
- "width", ENCODER_WIDTH(encoder),
- "height", ENCODER_HEIGHT(encoder),
- NULL
- );
- if (surfaces_pool) {
- gst_vaapi_context_set_surface_pool(out_context, surfaces_pool);
+ ENCODER_ACQUIRE_DISPLAY_LOCK(display);
+ if (VA_INVALID_ID != h264_prv->seq_parameter) {
+ va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
+ h264_prv->seq_parameter = VA_INVALID_ID;
}
- g_object_set(out_context, "profile", gst_vaapi_profile(va_profile), NULL);
-
-#else
- VAAPI_UNUSED_ARG(surfaces_pool);
- 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(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;
+ if (VA_INVALID_ID != h264_prv->pic_parameter) {
+ va_status = vaDestroyBuffer(va_dpy, h264_prv->pic_parameter);
+ h264_prv->pic_parameter = VA_INVALID_ID;
+ }
+ if (VA_INVALID_ID != h264_prv->slice_parameter) {
+ va_status = vaDestroyBuffer(va_dpy, h264_prv->slice_parameter);
+ h264_prv->slice_parameter = VA_INVALID_ID;
}
- *context = out_context;
- return ENCODER_NO_ERROR;
-end:
- // clear resources
- if (ENCODER_NO_ERROR != ret) {
- gst_h264_encoder_close(encoder, display, out_context);
- if (out_context) {
- g_object_unref(out_context);
- }
+ ENCODER_RELEASE_DISPLAY_LOCK(display);
+
+ if (h264_prv->slice_param_buffers) {
+ g_free(h264_prv->slice_param_buffers);
+ h264_prv->slice_param_buffers = NULL;
}
- return ret;
+ return TRUE;
}
-EncoderStatus
-gst_h264_encoder_close(GstVaapiEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context)
+
+static gboolean
+gst_h264_encoder_release_resource(GstVaapiBaseEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context)
{
GstH264Encoder* h264_encoder = GST_H264_ENCODER(encoder);
- EncoderStatus ret = ENCODER_NO_ERROR;
- GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+ gboolean ret = TRUE;
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
/* release buffers first */
- h264_encoder_release_buffers(h264_encoder, display, context);
+ h264_encoder_release_parameters(h264_encoder, display, context);
/*remove ref_surface*/
if (h264_prv->ref_surface) {
h264_prv->recon_surface = NULL;
}
- h264_prv->frame_count = 0;
-
if (h264_prv->sps_data) {
gst_buffer_unref(h264_prv->sps_data);
h264_prv->sps_data = NULL;
return ret;
}
-static EncoderStatus
-h264_encoder_alloc_buffers(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
-{
- EncoderStatus ret = ENCODER_NO_ERROR;
- VAStatus va_status = VA_STATUS_SUCCESS;
- GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
- guint32 i;
-
- ENCODER_ASSERT(display && context);
- VADisplay va_dpy = gst_vaapi_display_get_display(display);
- VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
- gboolean is_locked = FALSE;
-
- 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_encoder->slice_num,
- sizeof(h264_prv->slice_param_buffers[0]));
-end:
- return ret;
-}
-
-static EncoderStatus
-h264_encoder_release_buffers(GstH264Encoder *h264_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
-{
- VAStatus va_status = VA_STATUS_SUCCESS;
- 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(context);
- VADisplay va_dpy = gst_vaapi_display_get_display(display);
-
- /* wait clear all coded buffer freed*/
- wait_and_clear_available_coded_buffers(h264_prv, display, TRUE);
-
- ENCODER_ACQUIRE_DISPLAY_LOCK(display);
- va_status = vaDestroyBuffer(va_dpy, h264_prv->seq_parameter);
- ENCODER_RELEASE_DISPLAY_LOCK(display);
-
- if (h264_prv->slice_param_buffers) {
- g_free(h264_prv->slice_param_buffers);
- h264_prv->slice_param_buffers = NULL;
- }
-
- return ENCODER_NO_ERROR;
-}
-
-EncoderStatus
-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);
-
- EncoderStatus ret = ENCODER_NO_ERROR;
- gboolean is_key = FALSE;
- VABufferID* coded_buf = NULL;
- VAStatus va_status = VA_STATUS_SUCCESS;
- VASurfaceID buffer_surface_id = VA_INVALID_SURFACE;
- GstVaapiSurface *buffer_surface = NULL;
-
- gboolean is_locked = FALSE;
-
- ENCODER_ASSERT(display && context);
- VADisplay va_dpy = gst_vaapi_display_get_display(display);
- 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 = 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_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*/
- ENCODER_ACQUIRE_DISPLAY_LOCK(display);
- va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
- ENCODER_RELEASE_DISPLAY_LOCK(display);
-
- ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaBeginPicture error.\n");
-
- /* set input buffers*/
- is_key = ((h264_prv->frame_count % h264_encoder->intra_period) == 0);
-
- /*get valid coded buffer*/
- coded_buf = pop_available_coded_buffer(h264_prv);
- ENCODER_CHECK_STATUS(coded_buf, ENCODER_ENC_RES_ERR, "dequeue_available_coded_buffer error.\n");
-
- ret = h264_prepare_encoding(h264_encoder, display, context, is_key, *coded_buf);
- if (ENCODER_NO_ERROR != ret) {
- push_available_coded_buffer(h264_prv, coded_buf);
- }
- ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ENCODER_PICTURE_ERR, "h264_prepare_encoding failed.\n");
-
- /* end picture */
- ENCODER_ACQUIRE_DISPLAY_LOCK(display);
- va_status = vaEndPicture(va_dpy, context_id);
- 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_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;
- }
-
- h264_prv->frame_count++;
-
-end:
- ENCODER_RELEASE_DISPLAY_LOCK(display);
- if (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)
+gst_h264_encoder_alloc_slices(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display, GstVaapiContext *context)
{
- 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;
+ GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
- 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:
+ h264_prv->slice_param_buffers = (VAEncSliceParameterBuffer*)g_malloc0_n(h264_encoder->slice_num,
+ sizeof(h264_prv->slice_param_buffers[0]));
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(GstH264Encoder *h264_encoder,
- GstVaapiDisplay *display,
- GstBuffer *raw_pic,
- GstVaapiSurface *surface)
-{
- EncoderStatus ret = ENCODER_NO_ERROR;
- VAStatus va_status = VA_STATUS_SUCCESS;
- VAImage surface_image;
- VADisplay va_dpy;
- GstVaapiImage *image;
- GstVaapiImageFormat image_format;
- 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;
- 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);
- /*map image*/
- image = gst_vaapi_surface_derive_image(surface);
- gst_vaapi_image_map(image);
-
- image_format = gst_vaapi_image_get_format(image);
- image_width = gst_vaapi_image_get_width(image);
- image_height = gst_vaapi_image_get_height(image);
-
- /* copy buffer to surface */
- ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>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;
- v_src = u_src + u_size;
-
- plane_count = gst_vaapi_image_get_plane_count(image);
- y_dst = gst_vaapi_image_get_plane(image, 0);
- u_dst = gst_vaapi_image_get_plane(image, 1);
- pitchy = gst_vaapi_image_get_pitch(image, 0);
- pitchu = gst_vaapi_image_get_pitch(image, 1);
-
- if (plane_count > 2) {
- v_dst = gst_vaapi_image_get_plane(image, 2);
- pitchv = gst_vaapi_image_get_pitch(image, 2);
- }
-
- /* copy from avcenc.c*/
- /* Y plane */
- for (row = 0; row < image_height; row++) {
- memcpy(y_dst, y_src, image_width);
- y_dst += pitchy;
- y_src += ENCODER_WIDTH(h264_encoder);
- }
-
- if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
- if (GST_VAAPI_IMAGE_I420 == h264_prv->format) {
- for (row = 0; row < image_height / 2; row++) {
- for (col = 0; col < image_width / 2; col++) {
- u_dst[col * 2] = u_src[col];
- u_dst[col * 2 + 1] = v_src[col];
- }
-
- u_dst += pitchu;
- 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_encoder);
- u_dst += pitchu;
- }
- } else {
- ENCODER_ASSERT(0);
- }
- } else {
- /* FIXME: fix this later */
- ENCODER_ASSERT(0);
- }
-
- /*unmap image*/
- g_object_unref(image);
- end:
- return ret;
-}
static EncoderStatus
-h264_prepare_encoding(GstH264Encoder *h264_encoder, GstVaapiDisplay *display,
- GstVaapiContext *context, gboolean is_key, VABufferID coded_buf)
+gst_h264_prepare_encoding(GstVaapiBaseEncoder *encoder, GstVaapiDisplay *display,
+ GstVaapiContext *context, GstVaapiSurface *surface,
+ guint frame_index, VABufferID coded_buf, gboolean *is_key)
{
EncoderStatus ret = ENCODER_NO_ERROR;
VAStatus va_status = VA_STATUS_SUCCESS;
- GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
-
+ GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
+#ifdef _MRST_
VAEncPictureParameterBufferH264 pic_h264;
+#else
+ VAEncPictureParameterBufferH264Baseline pic_h264;
+#endif
VAEncSliceParameterBuffer *slice_h264 = NULL;
gboolean is_locked = FALSE;
VADisplay va_dpy = gst_vaapi_display_get_display(display);
VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
+ *is_key = ((frame_index % h264_encoder->intra_period) == 0);
+
/* 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*/
+ #ifdef _MRST_
VAEncSequenceParameterBufferH264 seq_h264 = {0};
+ #else
+ VAEncSequenceParameterBufferH264Baseline seq_h264 = {0};
+ #endif
seq_h264.level_idc = h264_encoder->level; /* 3.0 */
seq_h264.max_num_ref_frames = 1; /*Only I, P frames*/
--slice_mod_num;
}
last_row_num += slice_h264->slice_height;
- slice_h264->slice_flags.bits.is_intra = is_key;
+ slice_h264->slice_flags.bits.is_intra = *is_key;
slice_h264->slice_flags.bits.disable_deblocking_filter_idc = 0;
}
return ret;
}
-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)
-{
- EncoderStatus ret = ENCODER_NO_ERROR;
- VAStatus va_status = VA_STATUS_SUCCESS;
- VASurfaceStatus surface_status = 0;
- VACodedBufferSegment *buf_list = NULL;
- GstBuffer* ret_buffer = NULL;
- gboolean has_coded_data = FALSE;
- gboolean is_locked = FALSE;
- GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
-
- ENCODER_ASSERT(display && context);
- VASurfaceID surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
- VADisplay va_dpy = gst_vaapi_display_get_display(display);
-
- ENCODER_ASSERT(coded_pics && *coded_pics == NULL);
-
- /* lock display */
- 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");
-
- va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status);
- ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.\n");
- if (VASurfaceSkipped&surface_status) {
- ENCODER_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT ".\n", GST_TIME_ARGS(timestamp));
- }
-
- va_status = vaMapBuffer(va_dpy, *coded_buf, (void **)(&buf_list));
- ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaMapBuffer failed.\n");
-
- /*unlock display*/
- ENCODER_RELEASE_DISPLAY_LOCK(display);
-
- while (buf_list != NULL) {
- if (!h264_prv->sps_data || !h264_prv->pps_data) {
- h264_encoder_read_sps_pps(h264_prv, buf_list->buf, buf_list->size);
- }
- ret_buffer = h264_encoder_create_coded_buffer(h264_prv, buf_list->buf, buf_list->size, coded_buf);
- GST_BUFFER_TIMESTAMP(ret_buffer) = timestamp;
- GST_BUFFER_DURATION(ret_buffer) = duration;
- if (!is_key) {
- GST_BUFFER_FLAG_SET(ret_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
- }
- *coded_pics = g_list_append(*coded_pics, ret_buffer);
- buf_list = (VACodedBufferSegment*)buf_list->next;
- ENCODER_ASSERT(NULL == buf_list);
- has_coded_data = TRUE;
- }
-
-#if SHARE_CODED_BUF
- if (!has_coded_data)
-#endif
- { // if non-related, push back to available_code_buffers
- ENCODER_ACQUIRE_DISPLAY_LOCK(display);
- vaUnmapBuffer(va_dpy, *coded_buf);
- ENCODER_RELEASE_DISPLAY_LOCK(display);
- push_available_coded_buffer(h264_prv, coded_buf);
- }
-
- return ENCODER_NO_ERROR;
-
-end:
- /*unlock display*/
- ENCODER_RELEASE_DISPLAY_LOCK(display);
- return ret;
-}
static GstBuffer *
-h264_encoder_create_coded_buffer(GstH264EncoderPrivate *h264_prv,
+gst_h264_encoder_copy_coded_buffer(GstVaapiBaseEncoder *encoder,
guint8 *frame,
guint32 frame_size,
VABufferID *coded_buf)
{
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
GstBuffer *ret_buffer;
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);
- ENCODER_ASSERT(ret_buffer);
- GST_BUFFER_MALLOCDATA(ret_buffer) = NULL;
- GST_BUFFER_DATA(ret_buffer) = buf_list->buf;
- GST_BUFFER_SIZE(ret_buffer) = buf_list->size;
-#else
ret_buffer = gst_buffer_new();
ENCODER_ASSERT(ret_buffer);
H264Bitstream bitstream;
GST_BUFFER_DATA(ret_buffer) = BIT_STREAM_BUFFER(&bitstream);
GST_BUFFER_SIZE(ret_buffer) = BIT_STREAM_BIT_SIZE(&bitstream)/8;
h264_bitstream_destroy(&bitstream, FALSE);
-#endif
return ret_buffer;
-
}
static EncoderStatus
return ENCODER_NO_ERROR;
}
+static void
+gst_h264_notify_frame(GstVaapiBaseEncoder *encoder, guint8 *buf, guint32 size)
+{
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(encoder);
+ if (!h264_prv->sps_data || !h264_prv->pps_data) {
+ h264_encoder_read_sps_pps(h264_prv, buf, size);
+ }
+ if (h264_prv->sps_data && h264_prv->pps_data) {
+ gst_vaapi_base_encoder_set_frame_notify(GST_VAAPI_BASE_ENCODER(encoder), FALSE);
+ }
+}
+
+
static gboolean
h264_read_sps_attributes(const guint8 *sps_data, guint32 sps_size,
guint32 *profile_idc, guint32 *profile_comp, guint32 *level_idc)
}
-EncoderStatus
+static EncoderStatus
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);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
- h264_prv->frame_count = 0;
- /*do we need destroy h264_prv->seq_parameter? */
+ //h264_prv->frame_count = 0;
+ //gst_vaapi_base_encoder_set_frame_notify((GST_VAAPI_BASE_ENCODER)encoder, TRUE);
//end:
return ret;
h264_encoder->profile = 64;
h264_encoder->level = 30;
- h264_encoder->parent.width = 1280;
- h264_encoder->parent.height = 720;
- h264_encoder->parent.frame_rate = 10;
+ encoder->width = 1280;
+ encoder->height = 720;
+ encoder->frame_rate = 10;
h264_encoder->bitrate = 512*1000;
h264_encoder->intra_period = 30;
ret = gst_vaapi_encoder_initialize(encoder);
gst_h264_encoder_get_avcC_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
{
GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
- GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
GstBuffer *avc_codec;
const guint32 configuration_version = 0x01;
const guint32 length_size_minus_one = 0x03;
gst_h264_encoder_get_nal_codec_data(GstVaapiEncoder *encoder, GstBuffer **buffer)
{
GstH264Encoder *h264_encoder = GST_H264_ENCODER(encoder);
- GstH264EncoderPrivate *h264_prv = ENCPRV(h264_encoder);
+ GstH264EncoderPrivate *h264_prv = GST_H264_ENCODER_GET_PRIVATE(h264_encoder);
GstBuffer *nal_sps_pps;
ENCODER_ASSERT(buffer);