2 * gstvaapibaseencoder.c - VA-API base encoder
4 * Copyright (C) 2011 Intel Corporation
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public License
8 * as published by the Free Software Foundation; either version 2.1
9 * of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301 USA
22 #include "gstvaapibaseencoder.h"
27 #include <glib-object.h>
32 #include "va/va_x11.h"
34 #include "gst/gstclock.h"
35 #include "gst/gstvalue.h"
37 #include "gstvaapiobject.h"
38 #include "gstvaapiobject_priv.h"
39 #include "gstvaapicontext.h"
40 #include "gstvaapisurface.h"
41 #include "gstvaapisurfacepool.h"
42 #include "gstvaapivideobuffer.h"
43 #include "gstvaapidisplay_priv.h"
44 #include "gstvaapidebug.h"
46 GST_DEBUG_CATEGORY_STATIC (gst_vaapi_base_encoder_debug);
47 #define GST_CAT_DEFAULT gst_vaapi_base_encoder_debug
49 #define VA_INVALID_PROFILE 0xffffffff
50 #define DEFAULT_VA_CODEDBUF_NUM 4
51 #define GST_VAAPI_ENCODER_SURFACE_COUNT 3
53 #define GST_VAAPI_BASE_ENCODER_LOCK(encoder) \
55 g_static_rec_mutex_lock( \
56 &((GstVaapiBaseEncoder*)(encoder))->priv->mutex); \
59 #define GST_VAAPI_BASE_ENCODER_UNLOCK(encoder) \
61 g_static_rec_mutex_unlock( \
62 &((GstVaapiBaseEncoder*)(encoder))->priv->mutex); \
65 struct _GstVaapiBaseEncoderPrivate {
66 guint32 format; /*NV12, I420,*/
68 /*total encoded frames*/
70 VABufferID *coded_bufs;
71 guint32 coded_buf_num;
72 GStaticRecMutex mutex;
73 GQueue *idle_buf_queue;
74 GQueue *busy_buf_queue;
76 GstVaapiSurfacePool *surfaces_pool;
77 GstVaapiBaseEncoderNotifyStatus notify_status;
80 guint buffer_sharing_flag : 1;
81 guint buffer_notify_flag : 1;
85 G_DEFINE_TYPE(GstVaapiBaseEncoder, gst_vaapi_base_encoder, GST_TYPE_VAAPI_ENCODER)
87 typedef struct _GstVaapiEncoderBufferInfo GstVaapiEncoderBufferInfo;
88 typedef struct _GstVaapiEncoderBufferInfoClass GstVaapiEncoderBufferInfoClass;
90 #define GST_TYPE_VAAPI_ENCODER_BUFFER_INFO \
91 (gst_vaapi_encoder_buffer_info_get_type())
93 #define GST_VAAPI_ENCODER_BUFFER_INFO(obj) \
94 (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
95 GST_TYPE_VAAPI_ENCODER_BUFFER_INFO,\
96 GstVaapiEncoderBufferInfo))
98 struct _GstVaapiEncoderBufferInfo {
100 GstVaapiBaseEncoder *encoder;
102 GstClockTime timestamp;
103 GstClockTime duration;
108 guint32 is_mapped : 1;
111 struct _GstVaapiEncoderBufferInfoClass {
112 GObjectClass base_class;
116 GstVaapiEncoderBufferInfo,
117 gst_vaapi_encoder_buffer_info,
121 gst_vaapi_encoder_buffer_info_map(
122 GstVaapiEncoderBufferInfo *info,
126 g_return_val_if_fail(info, FALSE);
127 g_return_val_if_fail(info->encoder && info->id && buf, FALSE);
129 GstVaapiDisplay *display = ENCODER_DISPLAY(info->encoder);
130 VADisplay va_dpy = ENCODER_VA_DISPLAY(info->encoder);
131 VAStatus va_status = VA_STATUS_SUCCESS;
136 GST_VAAPI_DISPLAY_LOCK(display);
137 va_status = vaMapBuffer(va_dpy, *info->id, &info->data);
138 GST_VAAPI_DISPLAY_UNLOCK(display);
140 g_return_val_if_fail(va_status == VA_STATUS_SUCCESS, FALSE);
141 info->is_mapped = TRUE;
147 gst_vaapi_encoder_buffer_info_unmap(
148 GstVaapiEncoderBufferInfo *info
151 g_return_val_if_fail(info, FALSE);
152 g_return_val_if_fail(info->encoder && info->id, FALSE);
154 GstVaapiDisplay *display = ENCODER_DISPLAY(info->encoder);
155 VADisplay va_dpy = ENCODER_VA_DISPLAY(info->encoder);
156 VAStatus va_status = VA_STATUS_SUCCESS;
158 if (!info->is_mapped)
161 GST_VAAPI_DISPLAY_LOCK(display);
162 va_status = vaUnmapBuffer(va_dpy, *info->id);
163 GST_VAAPI_DISPLAY_UNLOCK(display);
165 info->is_mapped = FALSE;
167 g_return_val_if_fail(va_status == VA_STATUS_SUCCESS, FALSE);
171 static GstVaapiEncoderBufferInfo*
172 pop_busy_buffer_info(GstVaapiBaseEncoder *encoder)
174 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
175 GstVaapiEncoderBufferInfo *info = NULL;
177 g_return_val_if_fail(priv->busy_buf_queue, NULL);
179 GST_VAAPI_BASE_ENCODER_LOCK(encoder);
181 if (g_queue_is_empty(priv->busy_buf_queue))
184 info = (GstVaapiEncoderBufferInfo*)g_queue_pop_head(priv->busy_buf_queue);
187 GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
192 push_busy_buffer_info(
193 GstVaapiBaseEncoder *encoder,
194 GstVaapiEncoderBufferInfo *info)
196 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
198 GST_VAAPI_BASE_ENCODER_LOCK(encoder);
199 g_queue_push_tail(priv->busy_buf_queue, info);
200 GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
204 pop_idle_buffer_id(GstVaapiBaseEncoder *encoder)
206 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
207 VABufferID *coded_buf = NULL;
209 g_return_val_if_fail(priv->idle_buf_queue, NULL);
211 GST_VAAPI_BASE_ENCODER_LOCK(encoder);
213 if (g_queue_is_empty(priv->idle_buf_queue))
216 coded_buf = (VABufferID*)g_queue_pop_head(priv->idle_buf_queue);
219 GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
225 GstVaapiBaseEncoder *encoder,
229 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
231 GST_VAAPI_BASE_ENCODER_LOCK(encoder);
232 g_queue_push_tail(priv->idle_buf_queue, buf);
233 GST_VAAPI_BASE_ENCODER_UNLOCK(encoder);
237 gst_vaapi_encoder_buffer_info_init(
238 GstVaapiEncoderBufferInfo *info
241 info->encoder = NULL;
246 info->is_key = FALSE;
247 info->is_mapped = FALSE;
251 gst_vaapi_encoder_buffer_info_finalize(GObject *object)
253 GstVaapiEncoderBufferInfo *info = GST_VAAPI_ENCODER_BUFFER_INFO(object);
255 if (info->id && *info->id != VA_INVALID_ID && info->encoder) {
257 gst_vaapi_encoder_buffer_info_unmap(info);
258 push_idle_buffer_id(info->encoder, info->id);
262 g_object_unref(info->encoder);
263 info->encoder = NULL;
268 static GstVaapiEncoderBufferInfo*
269 gst_vaapi_encoder_buffer_info_new(
270 GstVaapiBaseEncoder *encoder
273 GstVaapiEncoderBufferInfo *ret;
275 g_return_val_if_fail(encoder, NULL);
277 ret = GST_VAAPI_ENCODER_BUFFER_INFO(
278 g_object_new(GST_TYPE_VAAPI_ENCODER_BUFFER_INFO,
282 ret->encoder = g_object_ref(encoder);
287 gst_vaapi_encoder_buffer_info_class_init(
288 GstVaapiEncoderBufferInfoClass *klass
291 GObjectClass * const obj_class = G_OBJECT_CLASS(klass);
293 obj_class->finalize = gst_vaapi_encoder_buffer_info_finalize;
297 gst_vaapi_base_encoder_set_frame_notify(
298 GstVaapiBaseEncoder *encoder,
302 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
303 priv->buffer_notify_flag = flag;
307 gst_vaapi_base_encoder_set_va_profile(
308 GstVaapiBaseEncoder *encoder,
312 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
313 priv->profile = profile;
318 gst_vaapi_base_encoder_set_input_format(
319 GstVaapiBaseEncoder* encoder,
323 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
324 priv->format = format;
328 gst_vaapi_base_encoder_set_notify_status(
329 GstVaapiBaseEncoder *encoder,
330 GstVaapiBaseEncoderNotifyStatus func,
334 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
336 priv->notify_status = func;
337 priv->user_data = user_data;
342 gst_vaapi_base_encoder_set_buffer_sharing(
343 GstVaapiBaseEncoder *encoder,
344 gboolean is_buffer_sharing
347 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
349 priv->buffer_sharing_flag = is_buffer_sharing;
353 default_validate_encoder_parameters(
354 GstVaapiBaseEncoder *encoder
357 if (!ENCODER_WIDTH(encoder) ||
358 !ENCODER_HEIGHT(encoder) ||
359 !ENCODER_FPS(encoder)) {
366 base_encoder_alloc_coded_buffers(
367 GstVaapiBaseEncoder *base_encoder,
368 GstVaapiContext *context
371 GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
373 VAContextID context_id;
374 VAStatus va_status = VA_STATUS_SUCCESS;
377 guint32 buffer_size =
378 (ENCODER_WIDTH(base_encoder) * ENCODER_HEIGHT(base_encoder) * 400) /
381 ENCODER_ASSERT(context);
382 ENCODER_ASSERT(priv->idle_buf_queue);
383 ENCODER_ASSERT(!priv->coded_bufs);
385 va_dpy = ENCODER_VA_DISPLAY(base_encoder);
386 context_id = gst_vaapi_context_get_id(context);
388 priv->coded_bufs = (VABufferID*)
389 g_malloc0(priv->coded_buf_num * sizeof(priv->coded_bufs[0]));
391 for (i = 0; i < priv->coded_buf_num; i++) {
392 va_status = vaCreateBuffer(va_dpy,
394 VAEncCodedBufferType,
397 &priv->coded_bufs[i]);
398 if (VA_STATUS_SUCCESS != va_status)
401 ENCODER_CHECK_STATUS(VA_STATUS_SUCCESS == va_status,
403 "create coded buffer failed.");
405 /* init queue idle_buf_queue */
406 GST_VAAPI_BASE_ENCODER_LOCK(base_encoder);
407 for (i = 0; i < priv->coded_buf_num; i++) {
408 g_queue_push_head(priv->idle_buf_queue, &priv->coded_bufs[i]);
410 GST_VAAPI_BASE_ENCODER_UNLOCK(base_encoder);
418 release_coded_buffers(GstVaapiBaseEncoder *base_encoder)
420 VAStatus va_status = VA_STATUS_SUCCESS;
421 GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
422 GstVaapiDisplay *display = ENCODER_DISPLAY(base_encoder);
423 guint32 available_buf_count = priv->coded_buf_num;
424 GstVaapiEncoderBufferInfo *info;
427 ENCODER_ASSERT(display);
428 VAAPI_UNUSED_ARG(va_status);
429 VADisplay va_dpy = gst_vaapi_display_get_display(display);
431 /* wait clear all available coded buffers */
432 GST_VAAPI_BASE_ENCODER_LOCK(base_encoder);
433 if (available_buf_count) {
434 while (!g_queue_is_empty(priv->busy_buf_queue)) {
435 info = (GstVaapiEncoderBufferInfo*)g_queue_pop_head(priv->busy_buf_queue);
436 g_object_unref(info);
438 while(!g_queue_is_empty(priv->idle_buf_queue)) {
439 g_queue_pop_head(priv->idle_buf_queue);
440 available_buf_count--;
443 GST_VAAPI_BASE_ENCODER_UNLOCK(base_encoder);
444 ENCODER_ASSERT(available_buf_count == 0);
446 for (i = 0; i < priv->coded_buf_num; i++) {
447 va_status = vaDestroyBuffer(va_dpy, priv->coded_bufs[i]);
450 return ENCODER_NO_ERROR;
454 gst_vaapi_base_encoder_close_default(GstVaapiEncoder* encoder)
456 GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
457 GstVaapiBaseEncoderClass *base_class =
458 GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
459 GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
460 EncoderStatus ret = ENCODER_NO_ERROR;
462 /* release buffers first */
463 priv->need_flush = FALSE;
465 if (base_class->release_resource) {
466 base_class->release_resource(base_encoder);
468 release_coded_buffers(base_encoder);
469 priv->frame_count = 0;
475 gst_vaapi_base_encoder_open_default(
476 GstVaapiEncoder* encoder,
477 GstVaapiContext **context
480 GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
481 GstVaapiBaseEncoderClass *base_class =
482 GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
483 GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
484 GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
486 GstVaapiContext *out_context = NULL;
488 EncoderStatus ret = ENCODER_NO_ERROR;
489 gboolean check_attri_ret = TRUE;
490 /*check and set default values*/
491 if (base_class->validate_attributes) {
492 check_attri_ret = base_class->validate_attributes(base_encoder);
494 check_attri_ret = default_validate_encoder_parameters(base_encoder);
496 ENCODER_CHECK_STATUS(check_attri_ret,
497 ENCODER_PARAMETER_ERR,
498 "vaapi encoder paramerter error.");
499 ENCODER_CHECK_STATUS(VA_INVALID_PROFILE != priv->profile,
501 "vaapi encoder profile not set.");
503 ENCODER_ASSERT(ENCODER_DISPLAY(encoder));
505 out_context = gst_vaapi_context_new(display,
506 gst_vaapi_profile(priv->profile),
507 gst_vaapi_entrypoint(VAEntrypointEncSlice),
508 ENCODER_RATE_CONTROL(encoder),
509 ENCODER_WIDTH(encoder),
510 ENCODER_HEIGHT(encoder),
511 GST_VAAPI_ENCODER_SURFACE_COUNT);
512 ENCODER_CHECK_STATUS(out_context,
514 "gst_vaapi_context_new failed.");
515 ENCODER_CHECK_STATUS(VA_INVALID_ID != GST_VAAPI_OBJECT_ID(out_context),
517 "gst_vaapi_context_new failed.");
519 if (base_class->pre_alloc_resource) {
520 ENCODER_CHECK_STATUS(
521 base_class->pre_alloc_resource(base_encoder, out_context),
523 "encoder <pre_alloc_resource> failed."
526 ENCODER_CHECK_STATUS(
527 base_encoder_alloc_coded_buffers(base_encoder, out_context),
529 "encoder <base_encoder_alloc_coded_buffers> failed."
531 *context = out_context;
533 return ENCODER_NO_ERROR;
537 if (ENCODER_NO_ERROR != ret) {
538 gst_vaapi_base_encoder_close_default(encoder);
540 g_object_unref(out_context);
547 query_encoding_status(
548 GstVaapiBaseEncoder *base_encoder,
549 GstVaapiSurface *buffer_surface
552 EncoderStatus ret = ENCODER_NO_ERROR;
553 GstVaapiSurfaceStatus surface_status;
555 ENCODER_CHECK_STATUS(gst_vaapi_surface_sync(buffer_surface),
557 "gst_vaapi_surface_sync failed.");
559 ENCODER_CHECK_STATUS(
560 gst_vaapi_surface_query_status(buffer_surface, &surface_status),
562 "gst_vaapi_surface_query_status failed."
564 if (GST_VAAPI_SURFACE_STATUS_SKIPPED & surface_status) {
565 ENCODER_LOG_ERROR("frame skipped"); /* not sure continue or not */
568 return ENCODER_NO_ERROR;
575 get_buf_list_size(VACodedBufferSegment *buf_list)
579 size += buf_list->size;
580 buf_list = (VACodedBufferSegment*)buf_list->next;
586 move_buf_list_to_buf(
587 VACodedBufferSegment *buf_list,
592 guint left_size = max_len;
594 while (buf_list && left_size) {
595 if (buf_list->size <= left_size)
596 cur_size = buf_list->size;
598 cur_size = left_size;
599 memcpy(data, buf_list->buf, cur_size);
601 buf_list = (VACodedBufferSegment*)buf_list->next;
602 left_size -= cur_size;
604 return max_len - left_size;
608 gst_vaapi_base_encoder_get_coded_buffer(
609 GstVaapiEncoder* base,
613 GstVaapiBaseEncoder *encoder = GST_VAAPI_BASE_ENCODER(base);
614 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
615 GstVaapiBaseEncoderClass *klass =
616 GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
617 GstVaapiEncoderBufferInfo* info;
619 VACodedBufferSegment *buf_list = NULL;
620 GstBuffer* buffer = NULL;
623 while((info = pop_busy_buffer_info(encoder)) == NULL){
624 ret = ENCODER_NO_BUSY_BUF;
625 if (!priv->notify_status ||
626 !priv->notify_status(encoder, ret, priv->user_data))
629 ret = ENCODER_NO_ERROR;
631 ENCODER_CHECK_STATUS(
632 info->id && *info->id != VA_INVALID_ID,
634 "get invalid buffer info"
637 ENCODER_CHECK_STATUS(
638 gst_vaapi_encoder_buffer_info_map(info, (void**)&buf_list),
640 "vaMapBuffer failed");
642 buf_size = get_buf_list_size(buf_list);
643 ENCODER_CHECK_STATUS(
647 buffer = gst_buffer_new_and_alloc(buf_size);
648 GST_BUFFER_SIZE(buffer) = move_buf_list_to_buf(
650 GST_BUFFER_DATA(buffer),
653 if (priv->buffer_notify_flag && klass->notify_buffer) {
654 klass->notify_buffer(
656 GST_BUFFER_DATA(buffer),
657 GST_BUFFER_SIZE(buffer));
660 if (klass->wrap_buffer) {
661 GstBuffer *new_buf = klass->wrap_buffer(encoder, buffer);
662 gst_buffer_unref(buffer);
667 GST_BUFFER_TIMESTAMP(buffer) = info->timestamp;
668 GST_BUFFER_DURATION(buffer) = info->duration;
670 GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
672 FPS_CALCULATION(vaapiencode);
678 gst_vaapi_encoder_buffer_info_unmap(info);
679 g_object_unref(info);
684 static GstVaapiVideoBuffer *
686 GstVaapiBaseEncoder* encoder,
690 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
691 GstBuffer *video_buffer;
693 if (priv->buffer_sharing_flag)
694 video_buffer = (GstBuffer *)buf->data;
698 if (GST_VAAPI_IS_VIDEO_BUFFER(video_buffer))
699 return GST_VAAPI_VIDEO_BUFFER(video_buffer);
704 gst_vaapi_base_encoder_encode_default(
705 GstVaapiEncoder* base,
709 GstVaapiBaseEncoder* encoder = GST_VAAPI_BASE_ENCODER(base);
710 GstVaapiBaseEncoderClass *base_class =
711 GST_VAAPI_BASE_ENCODER_GET_CLASS(encoder);
712 GstVaapiBaseEncoderPrivate *priv = encoder->priv;
713 GstVaapiDisplay *display = ENCODER_DISPLAY(encoder);
714 GstVaapiContext *context = ENCODER_CONTEXT(encoder);
715 EncoderStatus ret = ENCODER_NO_ERROR;
716 gboolean is_key = FALSE;
717 VABufferID* coded_buf = NULL;
718 GstVaapiSurface *buffer_surface = NULL;
719 gboolean is_prepared_buffer = FALSE;
721 ENCODER_ASSERT(display && context);
724 GstVaapiVideoBuffer *video_buffer = NULL;
726 ENCODER_CHECK_STATUS(pic || base_class->prepare_next_input_buffer,
728 "Need a picture to encode");
730 priv->need_flush = TRUE;
733 if (base_class->prepare_next_input_buffer) {
734 GstBuffer* tmp_buf = NULL;
735 ret = base_class->prepare_next_input_buffer(encoder,
739 priv->need_flush = FALSE;
740 if (ret != ENCODER_NO_ERROR || !tmp_buf)
743 is_prepared_buffer = TRUE;
747 video_buffer = _get_video_buffer(encoder, pic);
748 ENCODER_CHECK_STATUS(
751 "vaapi encoder doesn't has video buffer");
753 buffer_surface = gst_vaapi_video_buffer_get_surface(video_buffer);
755 while ((coded_buf = pop_idle_buffer_id(encoder)) == NULL) {
756 ret = ENCODER_NO_IDLE_BUF;
757 if (!priv->notify_status ||
758 !priv->notify_status(encoder, ret, priv->user_data))
761 ret = ENCODER_NO_ERROR;
764 ret = base_class->render_frame(encoder,
769 /* prepare failed, push back */
770 if (ENCODER_NO_ERROR != ret) {
771 push_idle_buffer_id(encoder, coded_buf);
773 ENCODER_CHECK_STATUS(ENCODER_NO_ERROR == ret,
775 "base_prepare_encoding failed");
777 /*query surface result*/
778 ret = query_encoding_status(encoder, buffer_surface);
779 if (ENCODER_NO_ERROR != ret) {
783 /* Push coded buffer to another task */
784 GstVaapiEncoderBufferInfo* info = gst_vaapi_encoder_buffer_info_new(encoder);
785 info->id = coded_buf;
786 info->timestamp = GST_BUFFER_TIMESTAMP(pic);
787 info->duration = GST_BUFFER_DURATION(pic);
788 info->is_key = is_key;
789 push_busy_buffer_info(encoder, info);
793 if (is_prepared_buffer) {
795 gst_buffer_unref(pic);
797 buffer_surface = NULL;
803 if (ret < ENCODER_NO_ERROR && base_class->encode_frame_failed) {
804 base_class->encode_frame_failed(encoder, video_buffer);
806 if (pic && is_prepared_buffer)
807 gst_buffer_unref(pic);
814 base_put_raw_buffer_to_surface(GstVaapiBaseEncoder *base_encoder,
815 GstVaapiDisplay *display,
817 GstVaapiSurface *surface)
819 EncoderStatus ret = ENCODER_NO_ERROR;
820 GstVaapiImage *image;
821 GstVaapiImageFormat image_format;
822 guint8 *y_src = NULL, *u_src = NULL, *v_src = NULL;
823 guint8 *y_dst = NULL, *u_dst = NULL, *v_dst = NULL;
824 int y_size = 0, u_size = 0;
825 int row = 0, col = 0;
826 guint32 plane_count = 0;
827 guint32 image_width = 0, image_height = 0;
828 guint32 pitchy = 0, pitchu = 0, pitchv = 0;
829 GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
831 ENCODER_ASSERT(display);
832 VAAPI_UNUSED_ARG(pitchv);
833 VAAPI_UNUSED_ARG(v_dst);
835 image = gst_vaapi_surface_derive_image(surface);
836 gst_vaapi_image_map(image);
838 image_format = gst_vaapi_image_get_format(image);
839 image_width = gst_vaapi_image_get_width(image);
840 image_height = gst_vaapi_image_get_height(image);
842 /* copy buffer to surface */
843 ENCODER_ASSERT(GST_BUFFER_SIZE(raw_pic) >= y_size + (y_size>>1));
845 y_size = ENCODER_WIDTH(base_encoder) * ENCODER_HEIGHT(base_encoder);
846 u_size = ((ENCODER_WIDTH(base_encoder)+1) >> 1) * ((ENCODER_HEIGHT(base_encoder)+1) >> 1);
848 y_src = GST_BUFFER_DATA(raw_pic);
849 u_src = y_src + y_size;
850 v_src = u_src + u_size;
852 plane_count = gst_vaapi_image_get_plane_count(image);
853 y_dst = gst_vaapi_image_get_plane(image, 0);
854 u_dst = gst_vaapi_image_get_plane(image, 1);
855 pitchy = gst_vaapi_image_get_pitch(image, 0);
856 pitchu = gst_vaapi_image_get_pitch(image, 1);
858 if (plane_count > 2) {
859 v_dst = gst_vaapi_image_get_plane(image, 2);
860 pitchv = gst_vaapi_image_get_pitch(image, 2);
863 /* copy from avcenc.c*/
865 for (row = 0; row < image_height; row++) {
866 memcpy(y_dst, y_src, image_width);
868 y_src += ENCODER_WIDTH(base_encoder);
871 if (GST_VAAPI_IMAGE_NV12 == image_format) { /* UV plane */
872 if (GST_VAAPI_IMAGE_I420 == priv->format) {
873 for (row = 0; row < image_height / 2; row++) {
874 for (col = 0; col < image_width / 2; col++) {
875 u_dst[col * 2] = u_src[col];
876 u_dst[col * 2 + 1] = v_src[col];
880 u_src += (ENCODER_WIDTH(base_encoder)>>1);
881 v_src += (ENCODER_WIDTH(base_encoder)>>1);
883 } else if (GST_VAAPI_IMAGE_NV12 == priv->format){
884 for (row = 0; row < image_height / 2; row++) {
885 memcpy(u_dst, u_src, image_width);
886 u_src += ENCODER_WIDTH(base_encoder);
893 /* FIXME: fix this later */
898 g_object_unref(image);
905 gst_vaapi_base_encoder_flush_default(
906 GstVaapiEncoder* encoder
909 GstVaapiBaseEncoder* base_encoder = GST_VAAPI_BASE_ENCODER(encoder);
910 EncoderStatus ret = ENCODER_NO_ERROR;
911 GstVaapiBaseEncoderPrivate *priv = base_encoder->priv;
913 priv->frame_count = 0;
914 priv->need_flush = TRUE;
915 /*do we need destroy priv->seq_parameter? */
923 gst_vaapi_base_encoder_finalize(GObject *object)
925 /*free private buffers*/
926 GstVaapiEncoder *encoder = GST_VAAPI_ENCODER(object);
927 GstVaapiBaseEncoderPrivate *priv =
928 GST_VAAPI_BASE_ENCODER_GET_PRIVATE(object);
930 if (gst_vaapi_encoder_get_state(encoder) != VAAPI_ENC_NULL) {
931 gst_vaapi_encoder_uninitialize(encoder);
934 g_static_rec_mutex_free(&priv->mutex);
935 if (priv->idle_buf_queue)
936 g_queue_free(priv->idle_buf_queue);
938 if (priv->busy_buf_queue)
939 g_queue_free(priv->busy_buf_queue);
941 G_OBJECT_CLASS(gst_vaapi_base_encoder_parent_class)->finalize(object);
945 gst_vaapi_base_encoder_init(GstVaapiBaseEncoder *encoder)
947 GstVaapiBaseEncoderPrivate *priv =
948 GST_VAAPI_BASE_ENCODER_GET_PRIVATE(encoder);
949 ENCODER_ASSERT(priv);
950 encoder->priv = priv;
952 /* init private values*/
954 priv->profile= VA_INVALID_PROFILE;
955 priv->frame_count = 0;
956 priv->buffer_sharing_flag = FALSE;
957 priv->buffer_notify_flag = FALSE;
959 priv->coded_bufs = NULL;
960 priv->coded_buf_num = DEFAULT_VA_CODEDBUF_NUM;
961 priv->idle_buf_queue = g_queue_new();
962 priv->busy_buf_queue = g_queue_new();
963 g_static_rec_mutex_init(&priv->mutex);
965 priv->notify_status = NULL;
966 priv->user_data = NULL;
968 priv->need_flush = FALSE;
972 gst_vaapi_base_encoder_class_init(GstVaapiBaseEncoderClass *klass)
974 GObjectClass * const object_class = G_OBJECT_CLASS(klass);
975 GstVaapiEncoderClass * const encoder_class = GST_VAAPI_ENCODER_CLASS(klass);
976 g_type_class_add_private(klass, sizeof(GstVaapiBaseEncoderPrivate));
978 GST_DEBUG_CATEGORY_INIT (gst_vaapi_base_encoder_debug,
979 "gst_vaapi_base_encoder",
981 "gst_vaapi_base_encoder element");
983 object_class->finalize = gst_vaapi_base_encoder_finalize;
985 encoder_class->open = gst_vaapi_base_encoder_open_default;
986 encoder_class->close = gst_vaapi_base_encoder_close_default;
987 encoder_class->encode = gst_vaapi_base_encoder_encode_default;
988 encoder_class->flush = gst_vaapi_base_encoder_flush_default;
989 encoder_class->get_buf = gst_vaapi_base_encoder_get_coded_buffer;
990 encoder_class->get_codec_data = NULL;
992 /* user defined functions*/
993 klass->validate_attributes = NULL;
994 klass->pre_alloc_resource = NULL;
995 klass->release_resource = NULL;
996 klass->prepare_next_input_buffer = NULL;
997 klass->render_frame = NULL;
998 klass->notify_buffer = NULL;
999 klass->wrap_buffer = NULL;
1000 klass->encode_frame_failed = NULL;
1003 object_class->set_property = gst_vaapi_base_encoder_set_property;
1004 object_class->get_property = gst_vaapi_base_encoder_get_property;