2 #include "gstvaapibaseencoder.h"
10 #include "va/va_x11.h"
12 #include "gst/gstclock.h"
13 #include "gst/gstvalue.h"
15 #include "gst/vaapi/gstvaapiobject.h"
16 #include "gst/vaapi/gstvaapiobject_priv.h"
17 #include "gst/vaapi/gstvaapicontext.h"
18 #include "gst/vaapi/gstvaapisurface.h"
19 #include "gst/vaapi/gstvaapisurfacepool.h"
20 #include "gst/vaapi/gstvaapivideobuffer.h"
21 #include "gst/vaapi/gstvaapidisplay_priv.h"
22 #include "gst/vaapi/gstvaapidebug.h"
26 #include "gst/vaapi/gstvaapivideobuffer_glx.h"
27 #define gst_vaapi_video_buffer_new_from_pool(pool) \
28 gst_vaapi_video_buffer_glx_new_from_pool(pool)
32 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_base_encoder_debug);
33 #define GST_CAT_DEFAULT gst_vaapi_base_encoder_debug
35 #define VA_INVALID_PROFILE 0xffffffff
36 #define DEFAULT_VA_CODEDBUF_NUM 4
38 #define GST_TYPE_ENCODER_SHARED_BUFFER (gst_base_encode_buffer_get_type())
40 static GstMiniObjectClass *gst_encoder_share_buffer_parent_class = NULL;
42 typedef struct _GstEncoderShareBuffer GstEncoderShareBuffer;
43 struct _GstEncoderShareBuffer {
46 GstVaapiBaseEncoder *encoder;
50 struct _GstVaapiBaseEncoderPrivate {
51 guint32 format; /*NV12, I420,*/
53 /*total encoded frames*/
55 gboolean frame_notify_flag;
57 VABufferID *coded_bufs;
58 guint32 coded_buf_num;
59 GMutex *code_buffer_lock;
60 GCond *code_buffer_cond;
61 GQueue *available_code_buffers;
63 GstVaapiSurfacePool *surfaces_pool;
68 G_DEFINE_TYPE(GstVaapiBaseEncoder, gst_vaapi_base_encoder, GST_TYPE_VAAPI_ENCODER);
70 static EncoderStatus gst_vaapi_base_encoder_initialize_default(
71 GstVaapiEncoder* encoder, GstVaapiDisplay *display);
72 static EncoderStatus gst_vaapi_base_encoder_uninitialize_default(
73 GstVaapiEncoder* encoder, GstVaapiDisplay *display);
74 static EncoderStatus gst_vaapi_base_encoder_open_default(GstVaapiEncoder* encoder,
75 GstVaapiDisplay *display, void* private_data,
76 GstVaapiContext **context);
77 static EncoderStatus gst_vaapi_base_encoder_close_default(GstVaapiEncoder* encoder,
78 GstVaapiDisplay *display, GstVaapiContext *context);
79 static EncoderStatus gst_vaapi_base_encoder_encode_default(GstVaapiEncoder* encoder,
80 GstVaapiDisplay *display, GstVaapiContext *context,
81 GstBuffer *raw_pic, GList **coded_pics);
82 static EncoderStatus gst_vaapi_base_encoder_flush_default(GstVaapiEncoder* encoder,
83 GstVaapiDisplay *display,
84 GstVaapiContext *context,
86 static GstBuffer *gst_vaapi_base_encoder_copy_buffer_default(GstVaapiBaseEncoder *encoder,
87 guint8 *frame, guint32 frame_size, VABufferID *coded_buf);
90 static gboolean base_encoder_alloc_coded_buffers(GstVaapiBaseEncoder *base_encoder,
91 GstVaapiDisplay *display, GstVaapiContext *context);
92 static EncoderStatus base_encoder_release_coded_buffers(GstVaapiBaseEncoder *base_encoder,
93 GstVaapiDisplay *display, GstVaapiContext *context);
94 static EncoderStatus base_put_raw_buffer_to_surface(GstVaapiBaseEncoder *base_encoder,
95 GstVaapiDisplay *display, GstBuffer *raw_pic, GstVaapiSurface *surface);
97 static EncoderStatus base_query_encoding_status(GstVaapiBaseEncoder *base_encoder,
98 GstVaapiDisplay *display, GstVaapiSurface *buffer_surface,
99 gboolean is_key, GstVaapiVideoBuffer *surface_buffer,
100 VABufferID *coded_buf, GList **coded_pics);
102 static VABufferID *pop_available_coded_buffer(GstVaapiBaseEncoderPrivate *base_prv);
103 static gboolean push_available_coded_buffer(
104 GstVaapiBaseEncoderPrivate *base_prv, VABufferID *buf);
107 gst_vaapi_base_encoder_finalize(GObject *object)
109 /*free private buffers*/
110 GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
111 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(object);
113 if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
114 gst_vaapi_encoder_uninitialize(encoder);
117 g_mutex_free(base_prv->code_buffer_lock);
118 g_cond_free(base_prv->code_buffer_cond);
119 if (base_prv->available_code_buffers) {
120 g_queue_free(base_prv->available_code_buffers);
121 base_prv->available_code_buffers = NULL;
124 G_OBJECT_CLASS(gst_vaapi_base_encoder_parent_class)->finalize(object);
129 gst_vaapi_base_encoder_class_init(GstVaapiBaseEncoderClass *klass)
131 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
132 GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
133 g_type_class_add_private(klass, sizeof(GstVaapiBaseEncoderPrivate));
135 GST_DEBUG_CATEGORY_INIT (gst_vaapi_base_encoder_debug, "gst_vaapi_base_encoder", 0,
136 "gst_vaapi_base_encoder element");
138 object_class->finalize = gst_vaapi_base_encoder_finalize;
140 encoder_class->initialize = gst_vaapi_base_encoder_initialize_default;
141 encoder_class->uninitialize = gst_vaapi_base_encoder_uninitialize_default;
142 encoder_class->open = gst_vaapi_base_encoder_open_default;
143 encoder_class->close = gst_vaapi_base_encoder_close_default;
144 encoder_class->encode = gst_vaapi_base_encoder_encode_default;
145 encoder_class->flush = gst_vaapi_base_encoder_flush_default;
146 encoder_class->get_codec_data = NULL;
148 /* user defined functions*/
149 klass->validate_attributes = NULL;
150 klass->pre_alloc_resource = NULL;
151 klass->release_resource = NULL;
152 klass->prepare_next_input_buffer = NULL;
153 klass->render_frame = NULL;
154 klass->notify_frame = NULL;
155 klass->copy_coded_frame = NULL;
156 klass->encode_frame_failed = NULL;
159 object_class->set_property = gst_vaapi_base_encoder_set_property;
160 object_class->get_property = gst_vaapi_base_encoder_get_property;
165 gst_encoder_share_buffer_finalize (GstEncoderShareBuffer *base_buffer)
167 GstVaapiBaseEncoder *encoder = NULL;
168 VABufferID* coded_id = NULL;
169 GstVaapiDisplay *display = NULL;
170 GstVaapiBaseEncoderPrivate *encoder_prv = NULL;
172 gboolean is_locked = FALSE;
174 encoder = base_buffer->encoder;
175 coded_id = base_buffer->coded_id;
176 display = ENCODER_DISPLAY(encoder);
177 encoder_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
179 ENCODER_ASSERT(display);
180 VADisplay va_dpy = gst_vaapi_display_get_display(display);
182 ENCODER_ASSERT(encoder_prv);
183 ENCODER_ASSERT(coded_id && VA_INVALID_ID!= *coded_id);
185 /*if (--(*base_buffer->ref_coded_id) == 0) */
187 /*g_free(base_buffer->ref_coded_id);*/
188 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
189 vaUnmapBuffer(va_dpy, *coded_id);
190 ENCODER_RELEASE_DISPLAY_LOCK(display);
191 push_available_coded_buffer(encoder_prv, coded_id);
194 if (GST_MINI_OBJECT_CLASS(gst_encoder_share_buffer_parent_class)->finalize) {
195 GST_MINI_OBJECT_CLASS(gst_encoder_share_buffer_parent_class)->finalize(GST_MINI_OBJECT(base_buffer));
200 gst_encode_share_buffer_class_init (gpointer g_class, gpointer class_data)
202 GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS(g_class);
204 gst_encoder_share_buffer_parent_class = g_type_class_peek_parent(g_class);
205 ENCODER_ASSERT(gst_encoder_share_buffer_parent_class);
207 mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
208 gst_encoder_share_buffer_finalize;
213 gst_base_encode_buffer_get_type (void)
215 static GType s_base_encode_buffer_type = 0;
216 if (G_UNLIKELY (s_base_encode_buffer_type == 0)) {
217 static const GTypeInfo s_base_encode_buffer_info = {
218 sizeof(GstBufferClass),
221 gst_encode_share_buffer_class_init,
224 sizeof(GstEncoderShareBuffer),
229 s_base_encode_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
230 "GstEncoderShareBuffer", &s_base_encode_buffer_info, 0);
232 return s_base_encode_buffer_type;
235 static GstEncoderShareBuffer *
236 gst_base_encode_share_buffer_new(GstVaapiBaseEncoder *encoder, VABufferID *coded_id)
238 GstEncoderShareBuffer *buf = (GstEncoderShareBuffer*)gst_mini_object_new(GST_TYPE_ENCODER_SHARED_BUFFER);
239 buf->coded_id = coded_id;
240 buf->encoder = encoder;
246 gst_vaapi_base_encoder_init(GstVaapiBaseEncoder *encoder)
248 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
249 ENCODER_ASSERT(base_prv);
251 /* init private values*/
252 base_prv->format = 0;
253 base_prv->profile= VA_INVALID_PROFILE;
254 base_prv->frame_count = 0;
255 base_prv->frame_notify_flag = FALSE;
257 base_prv->coded_bufs = NULL;
258 base_prv->coded_buf_num = DEFAULT_VA_CODEDBUF_NUM;
259 base_prv->code_buffer_lock = g_mutex_new();
260 base_prv->code_buffer_cond = g_cond_new();
261 base_prv->available_code_buffers = g_queue_new();
263 base_prv->surfaces_pool = NULL;
264 base_prv->need_flush = FALSE;
268 gst_vaapi_base_encoder_set_frame_notify(GstVaapiBaseEncoder *encoder, gboolean flag)
270 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
271 base_prv->frame_notify_flag = flag;
275 gst_vaapi_base_encoder_set_va_profile(GstVaapiBaseEncoder *encoder, guint profile)
277 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
278 base_prv->profile = profile;
283 gst_vaapi_base_encoder_set_input_format(GstVaapiBaseEncoder* encoder, guint32 format)
285 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
286 base_prv->format = format;
290 gst_vaapi_base_encoder_initialize_default(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
292 return ENCODER_NO_ERROR;
296 gst_vaapi_base_encoder_uninitialize_default(GstVaapiEncoder* encoder, GstVaapiDisplay *display)
298 return ENCODER_NO_ERROR;
303 default_validate_encoder_parameters(GstVaapiBaseEncoder *encoder)
305 if (!ENCODER_WIDTH(encoder) || !ENCODER_HEIGHT(encoder) || !ENCODER_FPS(encoder)) {
312 gst_vaapi_base_encoder_open_default(GstVaapiEncoder* encoder, GstVaapiDisplay *display, void* private_data, GstVaapiContext **context)
314 GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
315 GstVaapiBaseEncoderClass *base_class = GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
316 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
318 GstVaapiSurfacePool *surfaces_pool = private_data;
319 GstVaapiContext *out_context = NULL;
321 EncoderStatus ret = ENCODER_NO_ERROR;
322 gboolean check_attri_ret = TRUE;
323 /*check and set default values*/
324 if (base_class->validate_attributes) {
325 check_attri_ret = base_class->validate_attributes(base_encoder);
327 check_attri_ret = default_validate_encoder_parameters(base_encoder);
329 ENCODER_CHECK_STATUS(check_attri_ret, ENCODER_PARAMETER_ERR, "vaapi encoder paramerter error.");
330 ENCODER_CHECK_STATUS(VA_INVALID_PROFILE != base_prv->profile, ENCODER_PROFILE_ERR, "vaapi encoder profile not set.");
332 ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
335 out_context = g_object_new(
336 GST_VAAPI_TYPE_CONTEXT,
338 "id", GST_VAAPI_ID(VA_INVALID_ID),
339 "entrypoint", gst_vaapi_entrypoint(VAEntrypointEncSlice),
340 "width", ENCODER_WIDTH(encoder),
341 "height", ENCODER_HEIGHT(encoder),
345 gst_vaapi_context_set_surface_pool(out_context, surfaces_pool);
347 g_object_set(out_context, "profile", gst_vaapi_profile(base_prv->profile), NULL);
350 VAAPI_UNUSED_ARG(surfaces_pool);
351 out_context = gst_vaapi_context_new(display,
352 gst_vaapi_profile(base_prv->profile),
353 gst_vaapi_entrypoint(VAEntrypointEncSlice),
354 ENCODER_WIDTH(encoder),
355 ENCODER_HEIGHT(encoder));
357 ENCODER_CHECK_STATUS(out_context, ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.");
358 ENCODER_CHECK_STATUS(VA_INVALID_ID != GST_VAAPI_OBJECT_ID(out_context), ENCODER_CONTEXT_ERR, "gst_vaapi_context_new failed.");
360 if (base_class->pre_alloc_resource) {
361 ENCODER_CHECK_STATUS(base_class->pre_alloc_resource(base_encoder, display, out_context),
362 ENCODER_MEM_ERR, "encoder <pre_alloc_resource> failed.");
364 ENCODER_CHECK_STATUS(
365 base_encoder_alloc_coded_buffers(base_encoder, display, out_context),
367 "encoder <base_encoder_alloc_coded_buffers> failed."
369 *context = out_context;
371 base_prv->surfaces_pool = gst_vaapi_context_get_surface_pool(out_context);
372 ENCODER_ASSERT(base_prv->surfaces_pool);
373 return ENCODER_NO_ERROR;
377 if (ENCODER_NO_ERROR != ret) {
378 gst_vaapi_base_encoder_close_default(encoder, display, out_context);
380 g_object_unref(out_context);
387 gst_vaapi_base_encoder_close_default(GstVaapiEncoder* encoder, GstVaapiDisplay *display, GstVaapiContext *context)
389 GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
390 GstVaapiBaseEncoderClass *base_class = GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
391 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
392 EncoderStatus ret = ENCODER_NO_ERROR;
394 /* release buffers first */
395 base_prv->need_flush = FALSE;
397 if (base_class->release_resource) {
398 base_class->release_resource(base_encoder, display, context);
400 base_encoder_release_coded_buffers(base_encoder, display, context);
401 base_prv->frame_count = 0;
403 if (base_prv->surfaces_pool) {
404 g_object_unref(base_prv->surfaces_pool);
405 base_prv->surfaces_pool = NULL;
412 base_encoder_alloc_coded_buffers(GstVaapiBaseEncoder *base_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
414 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(base_encoder);
416 ENCODER_ASSERT(display && context);
417 VADisplay va_dpy = gst_vaapi_display_get_display(display);
418 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
419 VAStatus va_status = VA_STATUS_SUCCESS;
420 gboolean is_locked = FALSE;
423 guint32 buffer_size = (ENCODER_WIDTH(base_encoder) * ENCODER_HEIGHT(base_encoder) * 400) / (16*16);
425 ENCODER_ASSERT(base_prv->available_code_buffers);
426 ENCODER_ASSERT(!base_prv->coded_bufs);
428 base_prv->coded_bufs = (VABufferID*)g_malloc0(base_prv->coded_buf_num * sizeof(base_prv->coded_bufs[0]));
430 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
431 for (i = 0; i < base_prv->coded_buf_num; i++) {
432 va_status = vaCreateBuffer(va_dpy, context_id,VAEncCodedBufferType,
433 buffer_size, 1, NULL, &base_prv->coded_bufs[i]);
434 if (VA_STATUS_SUCCESS != va_status)
437 ENCODER_RELEASE_DISPLAY_LOCK(display);
438 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, FALSE, "create coded buffer failed.");
440 /* init queue available_code_buffers */
441 g_mutex_lock(base_prv->code_buffer_lock);
442 for (i = 0; i < base_prv->coded_buf_num; i++) {
443 g_queue_push_head(base_prv->available_code_buffers, &base_prv->coded_bufs[i]);
445 g_cond_signal(base_prv->code_buffer_cond);
446 g_mutex_unlock(base_prv->code_buffer_lock);
454 base_encoder_release_coded_buffers(GstVaapiBaseEncoder *base_encoder, GstVaapiDisplay *display, GstVaapiContext *context)
456 VAStatus va_status = VA_STATUS_SUCCESS;
457 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(base_encoder);
458 guint32 available_buf_count = base_prv->coded_buf_num;
460 gboolean is_locked = FALSE;
462 ENCODER_ASSERT(display);
463 ENCODER_ASSERT(context);
464 VAAPI_UNUSED_ARG(va_status);
465 VADisplay va_dpy = gst_vaapi_display_get_display(display);
467 /* wait clear all available coded buffers*/
468 g_mutex_lock(base_prv->code_buffer_lock);
469 while (available_buf_count) {
470 if (g_queue_is_empty(base_prv->available_code_buffers)) {
471 g_cond_wait(base_prv->code_buffer_cond, base_prv->code_buffer_lock);
473 g_queue_pop_head(base_prv->available_code_buffers);
474 available_buf_count--;
477 g_mutex_unlock(base_prv->code_buffer_lock);
479 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
480 for (i = 0; i < base_prv->coded_buf_num; i++) {
481 va_status = vaDestroyBuffer(va_dpy, base_prv->coded_bufs[i]);
483 ENCODER_RELEASE_DISPLAY_LOCK(display);
485 return ENCODER_NO_ERROR;
489 gst_vaapi_base_encoder_encode_default(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
490 GstVaapiContext *context, GstBuffer *raw_pic, GList **coded_pics)
492 GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
493 GstVaapiBaseEncoderClass *base_class = GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
494 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(base_encoder);
496 EncoderStatus ret = ENCODER_NO_ERROR;
497 gboolean is_key = FALSE;
498 VABufferID* coded_buf = NULL;
499 VAStatus va_status = VA_STATUS_SUCCESS;
500 VASurfaceID buffer_surface_id = VA_INVALID_SURFACE;
501 GstVaapiSurface *buffer_surface = NULL;
503 gboolean is_locked = FALSE;
505 ENCODER_ASSERT(display && context);
506 VADisplay va_dpy = gst_vaapi_display_get_display(display);
507 VAContextID context_id = GST_VAAPI_OBJECT_ID(context);
508 GstVaapiSurface *new_surface = NULL;
511 GstVaapiVideoBuffer *video_buffer = NULL;
513 ENCODER_CHECK_STATUS(raw_pic || base_class->prepare_next_input_buffer,
514 ENCODER_DATA_ERR, "Need a picture to encode");
516 /* load picture to surface */
517 if (GST_VAAPI_IS_VIDEO_BUFFER(raw_pic)) {
518 video_buffer = GST_VAAPI_VIDEO_BUFFER(raw_pic);
519 gst_buffer_ref(GST_BUFFER_CAST(video_buffer));
521 ENCODER_CHECK_STATUS(base_prv->surfaces_pool, ENCODER_SURFACE_ERR, "surface pool could not be found in context");
522 video_buffer = (GstVaapiVideoBuffer*)gst_vaapi_video_buffer_new_from_pool((GstVaapiVideoPool*)base_prv->surfaces_pool);
523 new_surface = gst_vaapi_video_buffer_get_surface(video_buffer); //gst_vaapi_context_get_surface(context);
524 ENCODER_CHECK_STATUS(new_surface, ENCODER_SURFACE_ERR, "base_pop_free_surface failed.");
526 /* put picture to new surface */
527 va_status = base_put_raw_buffer_to_surface(base_encoder, display, raw_pic, new_surface);
528 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "va put buffer to surface failed.");
530 GST_BUFFER_TIMESTAMP(video_buffer) = GST_BUFFER_TIMESTAMP(raw_pic);
531 GST_BUFFER_DURATION(video_buffer) = GST_BUFFER_DURATION(raw_pic);
534 base_prv->need_flush = TRUE;
538 if (base_class->prepare_next_input_buffer) {
539 GstVaapiVideoBuffer* tmp_buf = NULL;
540 ret = base_class->prepare_next_input_buffer(base_encoder, video_buffer, base_prv->need_flush, &tmp_buf);
541 base_prv->need_flush = FALSE;
543 gst_buffer_unref(GST_BUFFER_CAST(video_buffer));
546 if (ret != ENCODER_NO_ERROR || !tmp_buf)
548 video_buffer = tmp_buf;
551 buffer_surface = gst_vaapi_video_buffer_get_surface(video_buffer);
552 buffer_surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
553 ENCODER_CHECK_STATUS(buffer_surface_id != VA_INVALID_SURFACE, ENCODER_SURFACE_ERR, "surface id == VA_INVALID_SURFACE.");
556 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
557 va_status = vaBeginPicture(va_dpy, context_id, buffer_surface_id);
558 //ENCODER_RELEASE_DISPLAY_LOCK(display);
560 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaBeginPicture error.");
562 /*get valid coded buffer*/
563 coded_buf = pop_available_coded_buffer(base_prv);
564 ENCODER_CHECK_STATUS(coded_buf, ENCODER_ENC_RES_ERR, "dequeue_available_coded_buffer error.");
567 ret = base_class->render_frame(base_encoder, display, context,
568 buffer_surface, base_prv->frame_count,
569 *coded_buf, &is_key);
570 /* prepare failed, push back */
571 if (ENCODER_NO_ERROR != ret) {
572 push_available_coded_buffer(base_prv, coded_buf);
574 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret, ENCODER_PICTURE_ERR, "base_prepare_encoding failed.");
577 //ENCODER_ACQUIRE_DISPLAY_LOCK(display);
578 va_status = vaEndPicture(va_dpy, context_id);
579 ENCODER_RELEASE_DISPLAY_LOCK(display);
580 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status, ENCODER_PICTURE_ERR, "vaEndPicture error.");
582 /*query surface result*/
583 ret = base_query_encoding_status(base_encoder, display, buffer_surface,
584 is_key, video_buffer, coded_buf, coded_pics);
585 if (ENCODER_NO_ERROR != ret) {
589 base_prv->frame_count++;
591 if (base_class->prepare_next_input_buffer) {
593 gst_buffer_unref(GST_BUFFER_CAST(video_buffer));
596 buffer_surface = NULL;
601 ENCODER_RELEASE_DISPLAY_LOCK(display);
602 if (ret > ENCODER_NO_ERROR) {
603 ret = ENCODER_NO_ERROR;
605 if (ret < 0 && base_class->encode_frame_failed) {
606 base_class->encode_frame_failed(base_encoder, video_buffer);
609 gst_buffer_unref(GST_BUFFER_CAST(video_buffer));
616 pop_available_coded_buffer(GstVaapiBaseEncoderPrivate *base_prv)
618 VABufferID *coded_buf = NULL;
621 g_mutex_lock(base_prv->code_buffer_lock);
623 ENCODER_CHECK_STATUS(base_prv->available_code_buffers, FALSE, "coded buffer not found");
624 while (g_queue_is_empty(base_prv->available_code_buffers)) {
625 g_cond_wait(base_prv->code_buffer_cond, base_prv->code_buffer_lock);
627 coded_buf = (VABufferID*)g_queue_pop_head (base_prv->available_code_buffers);
630 g_mutex_unlock(base_prv->code_buffer_lock);
631 VAAPI_UNUSED_ARG(ret);
636 push_available_coded_buffer(GstVaapiBaseEncoderPrivate *base_prv, VABufferID *buf)
638 g_mutex_lock(base_prv->code_buffer_lock);
639 g_queue_push_head(base_prv->available_code_buffers, buf);
640 g_cond_signal(base_prv->code_buffer_cond);
641 g_mutex_unlock(base_prv->code_buffer_lock);
646 base_put_raw_buffer_to_surface(GstVaapiBaseEncoder *base_encoder,
647 GstVaapiDisplay *display,
649 GstVaapiSurface *surface)
651 EncoderStatus ret = ENCODER_NO_ERROR;
652 GstVaapiImage *image;
653 GstVaapiImageFormat image_format;
654 guint8 *y_src = NULL, *u_src = NULL, *v_src = NULL;
655 guint8 *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
656 int y_size = 0, u_size = 0;
657 int row = 0, col = 0;
658 guint32 plane_count = 0;
659 guint32 image_width = 0, image_height = 0;
660 guint32 pitchy = 0, pitchu = 0, pitchv = 0;
661 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(base_encoder);
663 ENCODER_ASSERT(display);
664 VAAPI_UNUSED_ARG(pitchv);
665 VAAPI_UNUSED_ARG(v_dst);
667 image = gst_vaapi_surface_derive_image(surface);
668 gst_vaapi_image_map(image);
670 image_format = gst_vaapi_image_get_format(image);
671 image_width = gst_vaapi_image_get_width(image);
672 image_height = gst_vaapi_image_get_height(image);
674 /* copy buffer to surface */
675 ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
677 y_size = ENCODER_WIDTH(base_encoder) * ENCODER_HEIGHT(base_encoder);
678 u_size = ((ENCODER_WIDTH(base_encoder)+1) >> 1) * ((ENCODER_HEIGHT(base_encoder)+1) >> 1);
680 y_src = GST_BUFFER_DATA(raw_pic);
681 u_src = y_src + y_size;
682 v_src = u_src + u_size;
684 plane_count = gst_vaapi_image_get_plane_count(image);
685 y_dst = gst_vaapi_image_get_plane(image, 0);
686 u_dst = gst_vaapi_image_get_plane(image, 1);
687 pitchy = gst_vaapi_image_get_pitch(image, 0);
688 pitchu = gst_vaapi_image_get_pitch(image, 1);
690 if (plane_count > 2) {
691 v_dst = gst_vaapi_image_get_plane(image, 2);
692 pitchv = gst_vaapi_image_get_pitch(image, 2);
695 /* copy from avcenc.c*/
697 for (row = 0; row < image_height; row++) {
698 memcpy(y_dst, y_src, image_width);
700 y_src += ENCODER_WIDTH(base_encoder);
703 if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
704 if (GST_VAAPI_IMAGE_I420 == base_prv->format) {
705 for (row = 0; row < image_height / 2; row++) {
706 for (col = 0; col < image_width / 2; col++) {
707 u_dst[col * 2] = u_src[col];
708 u_dst[col * 2 + 1] = v_src[col];
712 u_src += (ENCODER_WIDTH(base_encoder)>>1);
713 v_src += (ENCODER_WIDTH(base_encoder)>>1);
715 } else if (GST_VAAPI_IMAGE_NV12 == base_prv->format){
716 for (row = 0; row < image_height / 2; row++) {
717 memcpy(u_dst, u_src, image_width);
718 u_src += ENCODER_WIDTH(base_encoder);
725 /* FIXME: fix this later */
730 g_object_unref(image);
736 base_query_encoding_status(GstVaapiBaseEncoder *base_encoder,
737 GstVaapiDisplay *display,
738 GstVaapiSurface *buffer_surface,
740 GstVaapiVideoBuffer *surface_buffer,
741 VABufferID *coded_buf,
744 EncoderStatus ret = ENCODER_NO_ERROR;
745 VAStatus va_status = VA_STATUS_SUCCESS;
746 VASurfaceStatus surface_status = 0;
747 VACodedBufferSegment *buf_list = NULL;
748 GstBuffer* ret_buffer = NULL;
749 gboolean has_coded_data = FALSE;
750 gboolean is_locked = FALSE;
751 GstVaapiBaseEncoderClass *base_class = GST_VAAPI_BASE_ENCODER_GET_CLASS(base_encoder);
752 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(base_encoder);
754 ENCODER_ASSERT(display);
755 VASurfaceID surface_id = (VASurfaceID)GST_VAAPI_OBJECT_ID(buffer_surface);
756 VADisplay va_dpy = gst_vaapi_display_get_display(display);
758 ENCODER_ASSERT(coded_pics);
759 VAAPI_UNUSED_ARG(has_coded_data);
762 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
764 va_status = vaSyncSurface(va_dpy, surface_id);
765 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaSyncSurface failed.");
767 va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status);
768 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaQuerySurfaceStatus failed.");
769 if (VASurfaceSkipped&surface_status) {
770 ENCODER_LOG_ERROR("frame skipped, dts:%" GST_TIME_FORMAT, GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(surface_buffer)));
773 va_status = vaMapBuffer(va_dpy, *coded_buf, (void **)(&buf_list));
774 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS ==va_status, ENCODER_QUERY_STATUS_ERR, "vaMapBuffer failed.");
777 ENCODER_RELEASE_DISPLAY_LOCK(display);
779 while (buf_list != NULL) {
780 if (base_prv->frame_notify_flag && base_class->notify_frame) {
781 base_class->notify_frame(base_encoder, buf_list->buf, buf_list->size);
784 if (base_class->copy_coded_frame) {
785 ret_buffer = base_class->copy_coded_frame(
786 base_encoder, buf_list->buf,
787 buf_list->size, coded_buf);
789 ret_buffer = gst_vaapi_base_encoder_copy_buffer_default(
790 base_encoder, buf_list->buf,
791 buf_list->size, coded_buf);
793 GST_BUFFER_TIMESTAMP(ret_buffer) = GST_BUFFER_TIMESTAMP(surface_buffer);
794 GST_BUFFER_DURATION(ret_buffer) = GST_BUFFER_DURATION(surface_buffer);
796 GST_BUFFER_FLAG_SET(ret_buffer, GST_BUFFER_FLAG_DELTA_UNIT);
798 GST_BUFFER_OFFSET_END(ret_buffer) = GST_BUFFER_OFFSET_END(surface_buffer);
799 *coded_pics = g_list_append(*coded_pics, ret_buffer);
800 buf_list = (VACodedBufferSegment*)buf_list->next;
801 ENCODER_ASSERT(NULL == buf_list);
802 has_coded_data = TRUE;
803 FPS_CALCULATION(vaapiencode);
809 { // if non-related, push back to available_code_buffers
810 ENCODER_ACQUIRE_DISPLAY_LOCK(display);
811 vaUnmapBuffer(va_dpy, *coded_buf);
812 ENCODER_RELEASE_DISPLAY_LOCK(display);
813 push_available_coded_buffer(base_prv, coded_buf);
816 return ENCODER_NO_ERROR;
820 ENCODER_RELEASE_DISPLAY_LOCK(display);
825 gst_vaapi_base_encoder_copy_buffer_default(GstVaapiBaseEncoder *encoder,
828 VABufferID *coded_buf)
830 GstBuffer *ret_buffer = NULL;
832 ret_buffer = gst_base_encode_share_buffer_new(encoder, coded_buf);
833 ENCODER_ASSERT(ret_buffer);
834 GST_BUFFER_MALLOCDATA(ret_buffer) = NULL;
835 GST_BUFFER_DATA(ret_buffer) = frame;
836 GST_BUFFER_SIZE(ret_buffer) = frame_size;
838 ret_buffer = gst_buffer_new_and_alloc(frame_size);
839 memcpy(GST_BUFFER_DATA(ret_buffer),frame, frame_size);
845 gst_vaapi_base_encoder_flush_default(GstVaapiEncoder* encoder, GstVaapiDisplay *display,
846 GstVaapiContext *context, GList **coded_pics)
848 GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
849 EncoderStatus ret = ENCODER_NO_ERROR;
850 GstVaapiBaseEncoderPrivate *base_prv = GST_VAAPI_BASE_ENCODER_GET_PRIVATE(base_encoder);
852 base_prv->frame_count = 0;
853 base_prv->need_flush = TRUE;
854 /*do we need destroy base_prv->seq_parameter? */