#include <string.h>
#include <X11/Xlib.h>
+#include <gst/video/videocontext.h>
#include "gst/vaapi/gstvaapivideobuffer.h"
#include "gst/vaapi/gstvaapisurfacepool.h"
#include "gstvaapih263encode.h"
#include "gstvaapimpeg4encode.h"
#include "gstvaapibaseencoder.h"
+#include "gstvaapipluginutil.h"
+#if USE_VAAPI_GLX
+#include <gst/vaapi/gstvaapivideobuffer_glx.h>
+#define gst_vaapi_video_buffer_new(display) \
+ gst_vaapi_video_buffer_glx_new(GST_VAAPI_DISPLAY_GLX(display))
+#endif
/* gst_debug
GST_DEBUG_CATEGORY_STATIC (gst_vaapi_encode_debug)
typedef struct _GstVaapiEncodePrivate GstVaapiEncodePrivate;
-GST_BOILERPLATE(
+#define GstVideoContextClass GstVideoContextInterface
+GST_BOILERPLATE_WITH_INTERFACE(
GstVaapiEncode,
gst_vaapi_encode,
GstElement,
- GST_TYPE_ELEMENT);
+ GST_TYPE_ELEMENT,
+ GstVideoContext,
+ GST_TYPE_VIDEO_CONTEXT,
+ gst_video_context);
+
enum {
PROP_0,
static char* _encode_dump_caps(GstCaps *cpas);
+/* context(display) interface */
+static void
+gst_vaapi_encode_set_video_context(GstVideoContext *context, const gchar *type,
+ const GValue *value)
+{
+ GstVaapiEncode *encode = GST_VAAPI_ENCODE (context);
+ GstVaapiDisplay *display = NULL;
+ gst_vaapi_set_display (type, value, &display);
+ gst_vaapi_encoder_set_display(encode->encoder, display);
+}
+
+static gboolean
+gst_video_context_supported (GstVaapiEncode *decode, GType iface_type)
+{
+ return (iface_type == GST_TYPE_VIDEO_CONTEXT);
+}
+
+static void
+gst_video_context_interface_init(GstVideoContextInterface *iface)
+{
+ iface->set_context = gst_vaapi_encode_set_video_context;
+}
+
+static gboolean
+gst_vaapi_encode_query (GstPad *pad, GstQuery *query) {
+ GstVaapiEncode *encode = GST_VAAPI_ENCODE (gst_pad_get_parent_element (pad));
+ gboolean res;
+
+ if (encode->encoder && gst_vaapi_reply_to_query(query, ENCODER_DISPLAY(encode->encoder)))
+ res = TRUE;
+ else
+ res = gst_pad_query_default (pad, query);
+
+ g_object_unref (encode);
+ return res;
+}
+
/*gst fix functions*/
static void
gst_pad_set_bufferalloc_function(encode->sinkpad, gst_vaapi_encode_buffer_alloc);
/*gst_pad_set_event_function(encode->sinkpad, gst_vaapi_encode_sink_event); */
/*gst_pad_use_fixed_caps(encode->sinkpad);*/
+ gst_pad_set_query_function(encode->sinkpad, gst_vaapi_encode_query);
gst_element_add_pad(GST_ELEMENT(encode), encode->sinkpad);
/* src pad */
gst_pad_use_fixed_caps(encode->srcpad);
/*gst_pad_set_event_function(encode->srcpad, gst_vaapi_encode_src_event);*/
+ gst_pad_set_query_function(encode->sinkpad, gst_vaapi_encode_query);
gst_element_add_pad(GST_ELEMENT(encode), encode->srcpad);
}
gst_vaapi_encode_set_caps(GstPad *sink_pad, GstCaps *caps)
{
GstVaapiEncode *encode = GST_VAAPI_ENCODE(GST_OBJECT_PARENT(sink_pad));
- GstStructure *structure;
+ GstStructure *structure = NULL, *src_struct = NULL;
gint width = 0, height = 0;
gint fps_n = 0, fps_d = 0;
- const GValue *fps_value = NULL;
+ const GValue *fps_value = NULL, *format_value;
+ guint32 format = 0;
+ gboolean ret = TRUE;
+ EncoderStatus encoder_ret = ENCODER_NO_ERROR;
+
encode->sinkpad_caps = caps;
gst_caps_ref(caps);
ENCODER_LOG_INFO("gst_vaapi_encode_set_caps,\n%s", _encode_dump_caps(caps));
fps_d = gst_value_get_fraction_denominator (fps_value);
encode->encoder->frame_rate = fps_n/fps_d;
}
- return TRUE;
+ format_value = gst_structure_get_value (structure, "format");
+ if (format_value && GST_IS_H264ENCODE(encode)) {
+ ENCODER_CHECK_STATUS(format_value && GST_TYPE_FOURCC == G_VALUE_TYPE(format_value),
+ FALSE, "1st buffer caps' format type is not fourcc.");
+ format = gst_value_get_fourcc (format_value);
+ if (format) {
+ gst_vaapi_base_encoder_set_input_format(GST_VAAPI_BASE_ENCODER(encode->encoder), format);
+ }
+ }
+
+ /*set src pad caps*/
+ if (encode->srcpad_caps) {
+ gst_caps_unref(encode->srcpad_caps);
+ }
+ encode->srcpad_caps = gst_caps_copy(gst_pad_get_pad_template_caps(encode->srcpad));
+ src_struct = gst_caps_get_structure(encode->srcpad_caps, 0);
+ gst_structure_set(src_struct, "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
+
+ /*set display and initialize encoder*/
+ ENCODER_CHECK_STATUS(gst_vaapi_ensure_display(encode, &ENCODER_DISPLAY(encode->encoder)),
+ FALSE, "encoder ensure display failed on setting caps.")
+ encoder_ret = gst_vaapi_encoder_initialize(encode->encoder);
+ ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret,
+ FALSE, "gst_vaapi_encoder_initialize failed.");
+ encoder_ret = gst_vaapi_encoder_open(encode->encoder, NULL);
+ ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret,
+ FALSE, "gst_vaapi_encoder_open failed.");
+end:
+ return ret;
}
static GstCaps *
ENCODER_ASSERT(encode && encode->encoder);
if (encode->first_sink_frame) {
/* get first buffer caps and set encoder values */
- GstStructure *recv_struct, *src_struct;
- GstCaps *recv_caps = GST_BUFFER_CAPS(buf);
- gint width, height;
- GValue const *framerate, *format_value;
- gint fps_n, fps_d;
- guint32 format;
- GstVaapiSurfacePool *surface_pool = NULL;
-
- ENCODER_LOG_INFO("gst_vaapi_encode_chain 1st recv-buffer caps,\n%s", _encode_dump_caps(recv_caps));
-
- recv_struct = gst_caps_get_structure (recv_caps, 0);
- ENCODER_CHECK_STATUS(NULL != recv_caps, GST_FLOW_ERROR, "gst_vaapi_encode_chain, 1st buffer didn't have detailed caps.");
- if (gst_structure_get_int (recv_struct, "width", &width)) {
- encode->encoder->width = width;
- }
- if (gst_structure_get_int (recv_struct, "height", &height)) {
- encode->encoder->height = height;
- }
- framerate = gst_structure_get_value (recv_struct, "framerate");
- if (framerate) {
- fps_n = gst_value_get_fraction_numerator (framerate);
- fps_d = gst_value_get_fraction_denominator (framerate);
- encode->encoder->frame_rate = fps_n/fps_d;
- }
- format_value = gst_structure_get_value (recv_struct, "format");
- if (format_value && GST_IS_H264ENCODE(encode)) {
- ENCODER_CHECK_STATUS(format_value && GST_TYPE_FOURCC == G_VALUE_TYPE(format_value),
- GST_FLOW_ERROR, "1st buffer caps' format type is not fourcc.");
- format = gst_value_get_fourcc (format_value);
- if (format) {
- gst_vaapi_base_encoder_set_input_format(GST_VAAPI_BASE_ENCODER(encode->encoder), format);
- }
- }
-
- /*set src pad caps*/
- if (encode->srcpad_caps) {
- gst_caps_unref(encode->srcpad_caps);
- }
- encode->srcpad_caps = gst_caps_copy(gst_pad_get_pad_template_caps(encode->srcpad));
- src_struct = gst_caps_get_structure(encode->srcpad_caps, 0);
- gst_structure_set(src_struct, "width", G_TYPE_INT, width,
- "height", G_TYPE_INT, height,
- "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL);
-
- /*set display and initialize encoder*/
if (GST_VAAPI_IS_VIDEO_BUFFER(buf)) {
- GstVaapiDisplay *display = NULL;
GstVaapiVideoBuffer *video_buffer = GST_VAAPI_VIDEO_BUFFER(buf);
ENCODER_ASSERT(video_buffer);
- display = gst_vaapi_video_buffer_get_display(video_buffer);
-
- #ifdef _MRST_
- surface_pool = GST_VAAPI_SURFACE_POOL(gst_vaapi_video_buffer_get_surface_pool(video_buffer));
- #endif
- if (display) {
- ENCODER_CHECK_STATUS(gst_vaapi_encoder_set_display(encode->encoder,display)
- , GST_FLOW_ERROR, "set display failed in gst_vaapi_encode_chain.");
- }
+ ENCODER_ASSERT(gst_vaapi_video_buffer_get_display(video_buffer) == ENCODER_DISPLAY(encode->encoder));
}
- encoder_ret = gst_vaapi_encoder_initialize(encode->encoder);
- ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret, GST_FLOW_ERROR, "gst_vaapi_encoder_initialize failed.");
- #ifdef _MRST_
- encoder_ret = gst_vaapi_encoder_open(encode->encoder, surface_pool);
- #else
- VAAPI_UNUSED_ARG(surface_pool);
- encoder_ret = gst_vaapi_encoder_open(encode->encoder, NULL);
- #endif
- ENCODER_CHECK_STATUS (ENCODER_NO_ERROR == encoder_ret, GST_FLOW_ERROR, "gst_vaapi_encoder_open failed.");
-
encode->first_sink_frame = FALSE;
}
while (out_buffers) {
tmp_buffer = out_buffers->data;
out_buffers = g_list_remove(out_buffers, tmp_buffer);
- /*out_buffers = g_list_next(out_buffers);*/
if (encode->first_src_frame) {
GstBuffer *codec_data = NULL;
ENCODER_ASSERT(encode->srcpad_caps);
}
if (!structure || gst_structure_has_name(structure, "video/x-vaapi-surface")) {
ENCODER_ASSERT(encode->encoder);
- display = gst_vaapi_encoder_get_display(encode->encoder);
- if (!display) {
- gst_vaapi_encoder_initialize(encode->encoder);
- display = gst_vaapi_encoder_get_display(encode->encoder);
- ENCODER_CHECK_STATUS(display, GST_FLOW_ERROR, "gst_vaapi_encoder_get_display failed in gst_vaapi_encode_buffer_alloc.");
- }
+ ENCODER_CHECK_STATUS(gst_vaapi_ensure_display(encode, &ENCODER_DISPLAY(encode->encoder)),
+ GST_FLOW_ERROR, "encoder ensure display failed.")
+ display = ENCODER_DISPLAY(encode->encoder);
buffer = gst_vaapi_video_buffer_new(display);
} else { /* video/x-raw-yuv */
buffer = gst_buffer_new_and_alloc(size);
ret = GST_FLOW_OK;
end:
- if (display) {
- g_object_unref(display);
- }
return ret;
}
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)
{