...
 
Commits (56)
This diff is collapsed.
This diff is collapsed.
common @ dd9d4031
Subproject commit 48a5d85ebf4a0bad1c997c83100f710fe2154fbf
Subproject commit dd9d4031075713cf37c656ce639b6d60d6f9dde3
# gstreamer-vaapi package version number
m4_define([gst_vaapi_major_version], [1])
m4_define([gst_vaapi_minor_version], [12])
m4_define([gst_vaapi_micro_version], [0])
m4_define([gst_vaapi_nano_version], [0])
m4_define([gst_vaapi_micro_version], [5])
m4_define([gst_vaapi_nano_version], [0])
m4_define([gst_vaapi_version],
[gst_vaapi_major_version.gst_vaapi_minor_version.gst_vaapi_micro_version])
m4_if(gst_vaapi_nano_version, [0], [],
......@@ -16,9 +16,9 @@ dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0
dnl - interfaces added -> increment AGE
dnl - interfaces removed -> AGE = 0
# gstreamer-vaapi library (libtool) version number
m4_define([gst_vaapi_lt_current], [1200])
m4_define([gst_vaapi_lt_current], [1205])
m4_define([gst_vaapi_lt_revision], [0])
m4_define([gst_vaapi_lt_age], [1200])
m4_define([gst_vaapi_lt_age], [1205])
# glib version number
m4_define([glib_version], [2.40])
......@@ -484,7 +484,7 @@ dnl -- VA-API --
dnl ---------------------------------------------------------------------------
dnl Core API
PKG_CHECK_MODULES([LIBVA], [libva >= $VAAPI_REQ libva < 0.99.0])
PKG_CHECK_MODULES([LIBVA], [libva >= $VAAPI_REQ libva != 0.99.0])
VA_VERSION_STR=`$PKG_CONFIG --modversion libva`
VA_DRIVERS_PATH=`$PKG_CONFIG --variable=driverdir libva`
AC_DEFINE_UNQUOTED([VA_DRIVERS_PATH], ["$VA_DRIVERS_PATH"],
......
This diff is collapsed.
......@@ -37,6 +37,12 @@
#define vaAssociateSubpicture vaAssociateSubpicture2
#endif
#if VA_CHECK_VERSION(1,0,0)
#define VA_ENC_PACKED_HEADER_H264_SEI VAEncPackedHeaderRawData
#else
#define VA_ENC_PACKED_HEADER_H264_SEI VAEncPackedHeaderH264_SEI
#endif
/* Compatibility glue with VA-API 0.34 */
#if VA_CHECK_VERSION(0,34,0)
# include <va/va_compat.h>
......
......@@ -1182,10 +1182,8 @@ gst_vaapi_decoder_update_caps (GstVaapiDecoder * decoder, GstCaps * caps)
if (!decoder_caps)
return FALSE;
if (gst_caps_is_always_compatible (caps, decoder_caps)) {
set_caps (decoder, caps);
return TRUE;
}
if (gst_caps_is_always_compatible (caps, decoder_caps))
return set_caps (decoder, caps);
profile = gst_vaapi_profile_from_caps (caps);
if (profile == GST_VAAPI_PROFILE_UNKNOWN)
......@@ -1194,8 +1192,11 @@ gst_vaapi_decoder_update_caps (GstVaapiDecoder * decoder, GstCaps * caps)
if (codec == 0)
return FALSE;
if (codec == decoder->codec) {
set_caps (decoder, caps);
return TRUE;
if (set_caps (decoder, caps)) {
return
gst_vaapi_decoder_decode_codec_data (decoder) ==
GST_VAAPI_DECODER_STATUS_SUCCESS;
}
}
return FALSE;
......
......@@ -1278,6 +1278,8 @@ gst_vaapi_decoder_h264_reset (GstVaapiDecoder * base_decoder)
g_free (priv->prev_frames);
priv->prev_frames = NULL;
priv->prev_frames_alloc = 0;
gst_vaapi_parser_info_h264_replace (&priv->active_pps, NULL);
gst_vaapi_parser_info_h264_replace (&priv->active_sps, NULL);
priv->profile = GST_VAAPI_PROFILE_UNKNOWN;
priv->entrypoint = GST_VAAPI_ENTRYPOINT_VLD;
......@@ -3184,7 +3186,7 @@ fill_picture_gaps (GstVaapiDecoderH264 * decoder, GstVaapiPictureH264 * picture,
return TRUE;
prev_frame = priv->prev_ref_frames[picture->base.voc];
g_assert (prev_frame != NULL);
g_assert (prev_frame != NULL && prev_frame->buffers[0] != NULL);
prev_picture = gst_vaapi_picture_ref (prev_frame->buffers[0]);
gst_vaapi_picture_ref (picture);
......@@ -3218,10 +3220,7 @@ fill_picture_gaps (GstVaapiDecoderH264 * decoder, GstVaapiPictureH264 * picture,
break;
/* Create new picture */
if (prev_picture)
lost_picture = gst_vaapi_picture_h264_new_clone (prev_picture);
else
lost_picture = gst_vaapi_picture_h264_new (decoder);
lost_picture = gst_vaapi_picture_h264_new_clone (prev_picture);
if (!lost_picture)
goto error_allocate_picture;
......@@ -3782,9 +3781,15 @@ fill_picture (GstVaapiDecoderH264 * decoder, GstVaapiPictureH264 * picture)
COPY_FIELD (sps, bit_depth_luma_minus8);
COPY_FIELD (sps, bit_depth_chroma_minus8);
COPY_FIELD (sps, num_ref_frames);
if (pic_param->num_ref_frames == 0)
pic_param->num_ref_frames = priv->dpb_size;
#if !VA_CHECK_VERSION(1,0,0)
/* Deprecate H.264 baseline profile and FMO support */
COPY_FIELD (pps, num_slice_groups_minus1);
COPY_FIELD (pps, slice_group_map_type);
COPY_FIELD (pps, slice_group_change_rate_minus1);
#endif
COPY_FIELD (pps, pic_init_qp_minus26);
COPY_FIELD (pps, pic_init_qs_minus26);
COPY_FIELD (pps, chroma_qp_index_offset);
......@@ -4310,6 +4315,9 @@ gst_vaapi_decoder_h264_decode_codec_data (GstVaapiDecoder * base_decoder,
GstH264ParserResult result;
guint i, ofs, num_sps, num_pps;
if (!priv->is_opened)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
unit.parsed_info = NULL;
if (buf_size < 7)
......
......@@ -717,8 +717,10 @@ dpb_find_lowest_poc (GstVaapiDecoderH265 * decoder,
GstVaapiPictureH265 *const picture = priv->dpb[i]->buffer;
if (picture && !picture->output_needed)
continue;
if (!found_picture || found_picture->poc > picture->poc)
found_picture = picture, found_index = i;
if (picture && (!found_picture || found_picture->poc > picture->poc)) {
found_picture = picture;
found_index = i;
}
}
if (found_picture_ptr)
......@@ -2651,6 +2653,9 @@ gst_vaapi_decoder_h265_decode_codec_data (GstVaapiDecoder *
guint num_nal_arrays, num_nals;
guint i, j, ofs;
if (!priv->is_opened)
return GST_VAAPI_DECODER_STATUS_SUCCESS;
unit.parsed_info = NULL;
if (buf_size < 23)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
......@@ -2664,7 +2669,12 @@ gst_vaapi_decoder_h265_decode_codec_data (GstVaapiDecoder *
num_nal_arrays = buf[22];
ofs = 23;
for (i = 0; i < num_nal_arrays; i++) {
if (ofs + 1 > buf_size)
return GST_VAAPI_DECODER_STATUS_ERROR_NO_DATA;
num_nals = GST_READ_UINT16_BE (buf + ofs + 1);
/* the max number of nals is GST_H265_MAX_PPS_COUNT (64) */
if (num_nals > 64)
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
ofs += 3;
for (j = 0; j < num_nals; j++) {
......
......@@ -900,6 +900,8 @@ decode_packet (GstVaapiDecoderMpeg4 * decoder, GstMpeg4Packet packet)
if (first_slice) {
status = decode_slice (decoder, _data, video_packet.size, FALSE);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
first_slice = FALSE;
} else {
_data += video_packet.offset;
......@@ -909,9 +911,13 @@ decode_packet (GstVaapiDecoderMpeg4 * decoder, GstMpeg4Packet packet)
gst_mpeg4_parse_video_packet_header (&priv->packet_hdr,
&priv->vol_hdr, &priv->vop_hdr, &priv->sprite_trajectory, _data,
_data_size);
if (ret != GST_MPEG4_PARSER_OK)
return GST_VAAPI_DECODER_STATUS_ERROR_BITSTREAM_PARSER;
status =
decode_slice (decoder, _data + priv->packet_hdr.size / 8,
video_packet.size - priv->packet_hdr.size / 8, TRUE);
if (status != GST_VAAPI_DECODER_STATUS_SUCCESS)
return status;
}
_data += video_packet.size;
......
......@@ -153,7 +153,7 @@ gst_vaapi_encoder_properties_get_default (const GstVaapiEncoderClass * klass)
GST_VAAPI_ENCODER_PROP_KEYFRAME_PERIOD,
g_param_spec_uint ("keyframe-period",
"Keyframe Period",
"Maximal distance between two keyframes (0: auto-calculate)", 1, 300,
"Maximal distance between two keyframes (0: auto-calculate)", 0, 300,
30, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/**
......@@ -1055,6 +1055,7 @@ gst_vaapi_encoder_init_properties (GstVaapiEncoder * encoder)
NULL) != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return FALSE;
}
return TRUE;
}
......
......@@ -1506,7 +1506,7 @@ add_packed_sei_header (GstVaapiEncoderH264 * encoder,
data_bit_size = GST_BIT_WRITER_BIT_SIZE (&bs);
data = GST_BIT_WRITER_DATA (&bs);
packed_sei_param.type = VAEncPackedHeaderH264_SEI;
packed_sei_param.type = VA_ENC_PACKED_HEADER_H264_SEI;
packed_sei_param.bit_length = data_bit_size;
packed_sei_param.has_emulation_bytes = 0;
......@@ -1782,7 +1782,6 @@ fill_sequence (GstVaapiEncoderH264 * encoder, GstVaapiEncSequence * sequence)
seq_param->level_idc = encoder->level_idc;
seq_param->intra_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
seq_param->intra_idr_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
seq_param->ip_period = 1 + encoder->num_bframes;
seq_param->ip_period = seq_param->intra_period > 1 ?
(1 + encoder->num_bframes) : 0;
seq_param->bits_per_second = encoder->bitrate_bits;
......@@ -2325,7 +2324,7 @@ ensure_bitrate (GstVaapiEncoderH264 * encoder)
if (!encoder->use_dct8x8)
bits_per_mb += (bits_per_mb * 10) / 100;
factor = encoder->mb_width * encoder->mb_height * bits_per_mb;
factor = (guint64) encoder->mb_width * encoder->mb_height * bits_per_mb;
base_encoder->bitrate =
gst_util_uint64_scale (factor, GST_VAAPI_ENCODER_FPS_N (encoder),
GST_VAAPI_ENCODER_FPS_D (encoder)) / 1000;
......
......@@ -180,8 +180,8 @@ h265_get_log2_max_pic_order_cnt (guint num)
}
if (ret <= 4)
ret = 4;
else if (ret > 10)
ret = 10;
else if (ret > 16)
ret = 16;
/* must be greater than 4 */
return ret;
}
......@@ -1452,7 +1452,6 @@ fill_sequence (GstVaapiEncoderH265 * encoder, GstVaapiEncSequence * sequence)
seq_param->intra_period = GST_VAAPI_ENCODER_KEYFRAME_PERIOD (encoder);
seq_param->intra_idr_period = encoder->idr_period;
seq_param->ip_period = 1 + encoder->num_bframes;
seq_param->ip_period = seq_param->intra_period > 1 ?
(1 + encoder->num_bframes) : 0;
seq_param->bits_per_second = encoder->bitrate_bits;
......@@ -1880,8 +1879,10 @@ ensure_bitrate (GstVaapiEncoderH265 * encoder)
if (!base_encoder->bitrate) {
/* Fixme: Provide better estimation */
/* Using a 1/6 compression ratio */
/* 12 bits per pixel fro yuv420 */
guint64 factor = encoder->luma_width * encoder->luma_height * 12 / 6;
/* 12 bits per pixel for YUV420 */
guint64 factor;
factor = (guint64) encoder->luma_width * encoder->luma_height * 12 / 6;
base_encoder->bitrate =
gst_util_uint64_scale (factor, GST_VAAPI_ENCODER_FPS_N (encoder),
GST_VAAPI_ENCODER_FPS_D (encoder)) / 1000;
......
......@@ -74,7 +74,8 @@ gst_vaapi_encoder_vp9_ref_pic_mode_type (void)
"mode-0"},
{GST_VAAPI_ENCODER_VP9_REF_PIC_MODE_1,
"Use last three frames for prediction (n:Last n-1:Gold n-2:Alt)",
"mode-1"}
"mode-1"},
{0, NULL, NULL},
};
gtype = g_enum_register_static ("GstVaapiEncoderVP9RefPicMode", values);
......
......@@ -98,7 +98,7 @@ gst_vaapi_object_new (const GstVaapiObjectClass * klass,
if (sub_size > 0)
memset (((guchar *) object) + sizeof (*object), 0, sub_size);
if (klass && klass->init)
if (klass->init)
klass->init (object);
return object;
}
......
......@@ -94,8 +94,10 @@ static const GstVaapiProfileMap gst_vaapi_profiles[] = {
{GST_VAAPI_PROFILE_H263_BASELINE, VAProfileH263Baseline,
"video/x-h263, variant=itu, h263version=h263", "baseline"},
#endif
#if !VA_CHECK_VERSION(1,0,0)
{GST_VAAPI_PROFILE_H264_BASELINE, VAProfileH264Baseline,
"video/x-h264", "baseline"},
#endif
#if VA_CHECK_VERSION(0,31,1)
{GST_VAAPI_PROFILE_H264_CONSTRAINED_BASELINE,
VAProfileH264ConstrainedBaseline,
......
......@@ -46,15 +46,43 @@
#define STRCASE(x) case x: return STRINGIFY(x)
#if VA_CHECK_VERSION (0,40,0)
static void
gst_vaapi_log (const char *message)
static gchar *
strip_msg (const char *message)
{
gchar *msg;
msg = g_strdup (message);
if (!msg)
return NULL;
return g_strstrip (msg);
}
#if VA_CHECK_VERSION (1,0,0)
static void
gst_vaapi_err (void *data, const char *message)
{
gchar *msg;
msg = strip_msg (message);
if (!msg)
return;
GST_ERROR ("%s", msg);
g_free (msg);
}
#endif
static void
gst_vaapi_log (
#if VA_CHECK_VERSION (1,0,0)
void *data,
#endif
const char *message)
{
gchar *msg;
msg = strip_msg (message);
if (!msg)
return;
g_strchomp (msg);
GST_INFO ("%s", msg);
g_free (msg);
}
......@@ -66,7 +94,10 @@ vaapi_initialize (VADisplay dpy)
gint major_version, minor_version;
VAStatus status;
#if VA_CHECK_VERSION (0,40,0)
#if VA_CHECK_VERSION (1,0,0)
vaSetErrorCallback (dpy, gst_vaapi_err, NULL);
vaSetInfoCallback (dpy, gst_vaapi_log, NULL);
#elif VA_CHECK_VERSION (0,40,0)
vaSetInfoCallback (gst_vaapi_log);
#endif
......@@ -175,7 +206,9 @@ string_of_VAProfile (VAProfile profile)
MAP (H263Baseline);
MAP (H264ConstrainedBaseline);
#endif
#if !VA_CHECK_VERSION(1,0,0)
MAP (H264Baseline);
#endif
MAP (H264Main);
MAP (H264High);
#if VA_CHECK_VERSION(0,35,2)
......
......@@ -1083,11 +1083,15 @@ egl_context_new_wrapped (EglDisplay * display, EGLContext gl_context)
args.display = display;
args.config = config;
args.gl_parent_context = gl_context;
args.context = NULL;
success = egl_display_run (display, (EglContextRunFunc) do_egl_context_new,
&args);
egl_object_unref (config);
if (!success)
return NULL;
if (args.context)
args.context->base.is_wrapped = TRUE;
return args.context;
}
......
......@@ -1163,7 +1163,7 @@ GstVaapiGLApi
gl_get_current_api (guint * major, guint * minor)
{
const gchar *version;
gint maj, min, n;
gint maj, min, n, sret;
GstVaapiGLApi ret = (1 << 31);
while (ret != GST_VAAPI_GL_API_NONE) {
......@@ -1181,7 +1181,9 @@ gl_get_current_api (guint * major, guint * minor)
if (n < 13)
goto next;
sscanf (&version[10], "%d.%d", &maj, &min);
sret = sscanf (&version[10], "%d.%d", &maj, &min);
if (sret != 2)
goto next;
if (maj <= 0 || min < 0)
goto next;
......@@ -1196,7 +1198,9 @@ gl_get_current_api (guint * major, guint * minor)
goto next;
} else {
sscanf (version, "%d.%d", &maj, &min);
sret = sscanf (version, "%d.%d", &maj, &min);
if (sret != 2)
goto next;
if (maj <= 0 || min < 0)
goto next;
......
......@@ -185,6 +185,11 @@ gst_vaapi_window_wayland_sync (GstVaapiWindow * window)
if (wl_display_flush (wl_display) < 0)
goto error;
if (g_atomic_int_get (&priv->num_frames_pending) == 0) {
wl_display_cancel_read (wl_display);
return TRUE;
}
again:
if (gst_poll_wait (priv->poll, GST_CLOCK_TIME_NONE) < 0) {
int saved_errno = errno;
......@@ -381,14 +386,16 @@ frame_done (FrameState * frame)
GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (frame->window);
g_atomic_int_set (&frame->done, TRUE);
g_atomic_pointer_compare_and_exchange (&priv->last_frame, frame, NULL);
return g_atomic_int_dec_and_test (&priv->num_frames_pending);
if (g_atomic_pointer_compare_and_exchange (&priv->last_frame, frame, NULL))
return g_atomic_int_dec_and_test (&priv->num_frames_pending);
return FALSE;
}
static void
frame_done_callback (void *data, struct wl_callback *callback, uint32_t time)
{
frame_done (data);
if (!frame_done (data))
GST_INFO ("cannot remove last frame because it didn't match or empty");
}
static const struct wl_callback_listener frame_callback_listener = {
......@@ -401,7 +408,8 @@ frame_release_callback (void *data, struct wl_buffer *wl_buffer)
FrameState *const frame = data;
if (!frame->done)
frame_done (frame);
if (!frame_done (frame))
GST_INFO ("cannot remove last frame because it didn't match or empty");
wl_buffer_destroy (wl_buffer);
frame_state_free (frame);
}
......
......@@ -37,6 +37,7 @@
#include "gstvaapipixmap_priv.h"
#include "gstvaapidisplay_x11.h"
#include "gstvaapidisplay_x11_priv.h"
#include "gstvaapisurface_priv.h"
#include "gstvaapiutils.h"
#include "gstvaapiutils_x11.h"
......@@ -463,9 +464,15 @@ conversion:
gst_vaapi_window_vpp_convert_internal (window, surface, NULL, NULL,
flags);
if (G_LIKELY (vpp_surface)) {
GstVaapiRectangle vpp_src_rect;
surface_id = GST_VAAPI_OBJECT_ID (vpp_surface);
vpp_src_rect.x = vpp_src_rect.y = 0;
vpp_src_rect.width = GST_VAAPI_SURFACE_WIDTH (vpp_surface);
vpp_src_rect.height = GST_VAAPI_SURFACE_HEIGHT (vpp_surface);
status =
gst_vaapi_window_x11_put_surface (window, surface_id, src_rect,
gst_vaapi_window_x11_put_surface (window, surface_id, &vpp_src_rect,
dst_rect, flags);
ret = vaapi_check_status (status, "vaPutSurface()");
......
......@@ -60,7 +60,7 @@ plugin_add_dependencies (GstPlugin * plugin)
"DISPLAY", "WAYLAND_DISPLAY", NULL
};
const gchar *kernel_paths[] = { "/dev/dri", NULL };
const gchar *kernel_names[] = { "card", "render" };
const gchar *kernel_names[] = { "card", "render", NULL };
/* features get updated upon changes in /dev/dri/card* */
gst_plugin_add_dependency (plugin, NULL, kernel_paths, kernel_names,
......
......@@ -967,7 +967,8 @@ gst_vaapidecode_reset (GstVaapiDecode * decode, GstCaps * caps,
return TRUE;
}
}
return gst_vaapi_decoder_reset (decode->decoder);
return (gst_vaapi_decoder_reset (decode->decoder) ==
GST_VAAPI_DECODER_STATUS_SUCCESS);
}
return gst_vaapidecode_create (decode, caps);
......@@ -1070,6 +1071,8 @@ gst_vaapidecode_set_format (GstVideoDecoder * vdec, GstVideoCodecState * state)
if (!gst_vaapi_decode_input_state_replace (decode, state))
return TRUE;
if (gst_vaapidecode_drain (vdec) == GST_FLOW_ERROR)
return FALSE;
if (!gst_vaapidecode_update_sink_caps (decode, state->caps))
return FALSE;
if (!gst_vaapi_plugin_base_set_caps (plugin, decode->sinkpad_caps, NULL))
......
......@@ -552,6 +552,22 @@ set_codec_state (GstVaapiEncode * encode, GstVideoCodecState * state)
return TRUE;
}
static gboolean
gst_vaapiencode_drain (GstVaapiEncode * encode)
{
GstVaapiEncoderStatus status;
if (!encode->encoder)
return TRUE;
status = gst_vaapi_encoder_flush (encode->encoder);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return FALSE;
gst_vaapiencode_purge (encode);
return TRUE;
}
static gboolean
gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state)
{
......@@ -567,6 +583,9 @@ gst_vaapiencode_set_format (GstVideoEncoder * venc, GstVideoCodecState * state)
state->caps, NULL))
return FALSE;
if (!gst_vaapiencode_drain (encode))
return FALSE;
if (encode->input_state)
gst_video_codec_state_unref (encode->input_state);
encode->input_state = gst_video_codec_state_ref (state);
......@@ -763,17 +782,14 @@ static gboolean
gst_vaapiencode_flush (GstVideoEncoder * venc)
{
GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (venc);
GstVaapiEncoderStatus status;
if (!encode->encoder)
return FALSE;
GST_LOG_OBJECT (encode, "flushing");
status = gst_vaapi_encoder_flush (encode->encoder);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
if (!gst_vaapiencode_drain (encode))
return FALSE;
gst_vaapiencode_purge (encode);
gst_vaapi_encoder_replace (&encode->encoder, NULL);
if (!ensure_encoder (encode))
......@@ -878,6 +894,7 @@ gst_vaapiencode_init_properties (GstVaapiEncode * encode)
return FALSE;
g_ptr_array_add (encode->prop_values, prop_value);
}
g_ptr_array_unref (props);
return TRUE;
}
......
......@@ -281,7 +281,7 @@ _h265_byte_stream_next_nal (guint8 * buffer, guint32 len, guint32 * nal_size)
guint32 flag = 0xFFFFFFFF;
guint32 nal_start_len = 0;
g_assert (len >= 0 && buffer && nal_size);
g_assert (len != 0U && buffer && nal_size);
if (len < 3) {
*nal_size = len;
nal_start = (len ? buffer : NULL);
......
......@@ -819,14 +819,28 @@ gst_vaapi_plugin_base_propose_allocation (GstVaapiPluginBase * plugin,
if (!caps)
goto error_no_caps;
if (!ensure_sinkpad_buffer_pool (plugin, caps))
return FALSE;
if (need_pool) {
if (!ensure_sinkpad_buffer_pool (plugin, caps))
return FALSE;
gst_query_add_allocation_pool (query, plugin->sinkpad_buffer_pool,
plugin->sinkpad_buffer_size, BUFFER_POOL_SINK_MIN_BUFFERS, 0);
gst_query_add_allocation_param (query, plugin->sinkpad_allocator, NULL);
}
/* Set sinkpad allocator as the last allocation param.
*
* If there's none, set system's allocator first and VAAPI allocator
* second
*/
if (gst_query_get_n_allocation_params (query) == 0) {
GstAllocator *allocator;
allocator = gst_allocator_find (GST_ALLOCATOR_SYSMEM);
gst_query_add_allocation_param (query, allocator, NULL);
gst_object_unref (allocator);
}
gst_query_add_allocation_param (query, plugin->sinkpad_allocator, NULL);
gst_query_add_allocation_meta (query, GST_VAAPI_VIDEO_META_API_TYPE, NULL);
gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
return TRUE;
......@@ -1174,16 +1188,14 @@ gst_vaapi_plugin_base_create_gl_context (GstVaapiPluginBase * plugin)
GstGLContext *gl_other_context, *gl_context = NULL;
GstGLDisplay *gl_display;
gst_gl_ensure_element_data (plugin, (GstGLDisplay **) & plugin->gl_display,
(GstGLContext **) & plugin->gl_other_context);
if (!gst_gl_ensure_element_data (plugin,
(GstGLDisplay **) & plugin->gl_display,
(GstGLContext **) & plugin->gl_other_context))
goto no_valid_gl_display;
gl_display = (GstGLDisplay *) plugin->gl_display;
if (!gl_display ||
gst_gl_display_get_handle_type (gl_display) == GST_GL_DISPLAY_TYPE_ANY) {
gst_object_replace (&plugin->gl_display, NULL);
gst_object_replace (&plugin->gl_other_context, NULL);
return NULL;
}
if (gst_gl_display_get_handle_type (gl_display) == GST_GL_DISPLAY_TYPE_ANY)
goto no_valid_gl_display;
gl_other_context = (GstGLContext *) plugin->gl_other_context;
GST_INFO_OBJECT (plugin, "creating a new GstGL context");
......@@ -1202,6 +1214,14 @@ gst_vaapi_plugin_base_create_gl_context (GstVaapiPluginBase * plugin)
GST_OBJECT_UNLOCK (gl_display);
return GST_OBJECT_CAST (gl_context);
/* ERRORS */
no_valid_gl_display:
{
gst_object_replace (&plugin->gl_display, NULL);
gst_object_replace (&plugin->gl_other_context, NULL);
return NULL;
}
#else
return NULL;
#endif
......
......@@ -180,8 +180,7 @@ gst_vaapi_create_display_from_gl_context (GstObject * gl_context_object)
#if USE_X11 && GST_GL_HAVE_WINDOW_X11
if (!display_type)
display_type = GST_VAAPI_DISPLAY_TYPE_X11;
#endif
#if USE_WAYLAND && GST_GL_HAVE_WINDOW_WAYLAND
#elif USE_WAYLAND && GST_GL_HAVE_WINDOW_WAYLAND
if (!display_type)
display_type = GST_VAAPI_DISPLAY_TYPE_WAYLAND;
#endif
......@@ -425,8 +424,7 @@ set_video_template_caps (GstCaps * caps)
gst_structure_set (structure,
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
"pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL);
}
GstCaps *
......
......@@ -305,8 +305,13 @@ gst_vaapipostproc_start (GstBaseTransform * trans)
ds_reset (&postproc->deinterlace_state);
if (!gst_vaapi_plugin_base_open (GST_VAAPI_PLUGIN_BASE (postproc)))
return FALSE;
if (!gst_vaapipostproc_ensure_filter (postproc))
g_mutex_lock (&postproc->postproc_lock);
if (!gst_vaapipostproc_ensure_filter (postproc)) {
g_mutex_unlock (&postproc->postproc_lock);
return FALSE;
}
g_mutex_unlock (&postproc->postproc_lock);
return TRUE;
}
......@@ -612,7 +617,7 @@ gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf,
GstBuffer *fieldbuf;
GstVaapiDeinterlaceMethod deint_method;
guint flags, deint_flags;
gboolean tff, deint, deint_refs, deint_changed;
gboolean tff, deint, deint_refs, deint_changed, discont;
const GstVideoCropMeta *crop_meta;
GstVaapiRectangle *crop_rect = NULL;
GstVaapiRectangle tmp_rect;
......@@ -636,6 +641,7 @@ gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf,
timestamp = GST_BUFFER_TIMESTAMP (inbuf);
tff = GST_BUFFER_FLAG_IS_SET (inbuf, GST_VIDEO_BUFFER_FLAG_TFF);
discont = GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DISCONT);
deint = should_deinterlace_buffer (postproc, inbuf);
/* Drop references if deinterlacing conditions changed */
......@@ -718,6 +724,11 @@ gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf,
GST_BUFFER_TIMESTAMP (fieldbuf) = timestamp;
GST_BUFFER_DURATION (fieldbuf) = postproc->field_duration;
if (discont) {
GST_BUFFER_FLAG_SET (fieldbuf, GST_BUFFER_FLAG_DISCONT);
discont = FALSE;
}
ret = gst_pad_push (trans->srcpad, fieldbuf);
if (ret != GST_FLOW_OK)
goto error_push_buffer;
......@@ -768,6 +779,10 @@ gst_vaapipostproc_process_vpp (GstBaseTransform * trans, GstBuffer * inbuf,
else {
GST_BUFFER_TIMESTAMP (outbuf) = timestamp + postproc->field_duration;
GST_BUFFER_DURATION (outbuf) = postproc->field_duration;
if (discont) {
GST_BUFFER_FLAG_SET (fieldbuf, GST_BUFFER_FLAG_DISCONT);
discont = FALSE;
}
}
if (deint && deint_refs)
......@@ -1430,6 +1445,7 @@ gst_vaapipostproc_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstVaapiPostproc *const postproc = GST_VAAPIPOSTPROC (object);
gboolean do_reconf = FALSE;
g_mutex_lock (&postproc->postproc_lock);
switch (prop_id) {
......@@ -1437,11 +1453,19 @@ gst_vaapipostproc_set_property (GObject * object,
postproc->format = g_value_get_enum (value);
break;
case PROP_WIDTH:
{
guint prev_width = postproc->width;
postproc->width = g_value_get_uint (value);
do_reconf = (prev_width != postproc->width);
break;
}
case PROP_HEIGHT:
{
guint prev_height = postproc->height;
postproc->height = g_value_get_uint (value);
do_reconf = (prev_height != postproc->height);
break;
}
case PROP_FORCE_ASPECT_RATIO:
postproc->keep_aspect = g_value_get_boolean (value);
break;
......@@ -1489,7 +1513,7 @@ gst_vaapipostproc_set_property (GObject * object,
}
g_mutex_unlock (&postproc->postproc_lock);
if (check_filter_update (postproc))
if (do_reconf || check_filter_update (postproc))
gst_base_transform_reconfigure_src (GST_BASE_TRANSFORM (postproc));
}
......@@ -1869,8 +1893,12 @@ cb_channels_init (GstVaapiPostproc * postproc)
if (postproc->cb_channels)
return;
if (!gst_vaapipostproc_ensure_filter (postproc))
g_mutex_lock (&postproc->postproc_lock);
if (!gst_vaapipostproc_ensure_filter (postproc)) {
g_mutex_unlock (&postproc->postproc_lock);
return;
}
g_mutex_unlock (&postproc->postproc_lock);
filter_ops = postproc->filter_ops ? g_ptr_array_ref (postproc->filter_ops)
: gst_vaapi_filter_get_operations (postproc->filter);
......
......@@ -256,8 +256,10 @@ _fixate_frame_size (GstVaapiPostproc * postproc, GstVideoInfo * vinfo,
/* Might have failed but try to keep the DAR nonetheless by
* adjusting the PAR */
if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, h, set_w,
&to_par_n, &to_par_d))
&to_par_n, &to_par_d)) {
gst_structure_free (tmp);
goto overflow_error;
}
if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
......@@ -328,8 +330,10 @@ _fixate_frame_size (GstVaapiPostproc * postproc, GstVideoInfo * vinfo,
/* Might have failed but try to keep the DAR nonetheless by
* adjusting the PAR */
if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, w,
&to_par_n, &to_par_d))
&to_par_n, &to_par_d)) {
gst_structure_free (tmp);
goto overflow_error;
}
if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
......@@ -439,8 +443,10 @@ _fixate_frame_size (GstVaapiPostproc * postproc, GstVideoInfo * vinfo,
gst_structure_get_int (tmp, "width", &set_w);
if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, set_w,
&to_par_n, &to_par_d))
&to_par_n, &to_par_d)) {
gst_structure_free (tmp);
goto overflow_error;
}
if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
......@@ -551,6 +557,30 @@ overflow_error:
}
}
static gboolean
_set_multiview_mode (GstVaapiPostproc * postproc, GstVideoInfo * vinfo,
GstStructure * outs)
{
const gchar *caps_str;
caps_str =
gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
(vinfo));
if (!caps_str)
return TRUE;
gst_structure_set (outs, "multiview-mode", G_TYPE_STRING, caps_str,
"multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
GST_VIDEO_INFO_MULTIVIEW_FLAGS (vinfo), GST_FLAG_SET_MASK_EXACT, NULL);
if (GST_VIDEO_INFO_VIEWS (vinfo) > 1) {
gst_structure_set (outs, "views", G_TYPE_INT, GST_VIDEO_INFO_VIEWS (vinfo),
NULL);
}
return TRUE;
}
static gboolean
_set_colorimetry (GstVaapiPostproc * postproc, GstVideoFormat format,
GstStructure * outs)
......@@ -670,6 +700,7 @@ _get_preferred_caps (GstVaapiPostproc * postproc, GstVideoInfo * vinfo,
goto fixate_failed;
if (!_fixate_frame_rate (postproc, vinfo, structure))
goto fixate_failed;
_set_multiview_mode (postproc, vinfo, structure);
if (f == GST_VAAPI_CAPS_FEATURE_SYSTEM_MEMORY)
_set_colorimetry (postproc, format, structure);
......
......@@ -588,6 +588,7 @@ gst_vaapisink_video_overlay_set_event_handling (GstVideoOverlay * overlay,
{
GstVaapiSink *const sink = GST_VAAPISINK (overlay);
sink->handle_events = handle_events;
gst_vaapisink_set_event_handling (sink, handle_events);
}
......@@ -934,7 +935,6 @@ gst_vaapisink_set_event_handling (GstVaapiSink * sink, gboolean handle_events)
return;
GST_OBJECT_LOCK (sink);
sink->handle_events = handle_events;
if (handle_events && !sink->event_thread) {
/* Setup our event listening thread */
GST_DEBUG ("starting xevent thread");
......@@ -1253,8 +1253,7 @@ gst_vaapisink_get_caps_impl (GstBaseSink * base_sink)
GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VAAPI_SURFACE
"," GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
"{ ENCODED, NV12, I420, YV12 }");
GstCapsFeatures *const features = gst_caps_features_new
(GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL);
GstCapsFeatures *features;
if (!GST_VAAPI_PLUGIN_BASE_DISPLAY (sink))
return gst_static_pad_template_get_caps (&gst_vaapisink_sink_factory);
......@@ -1269,6 +1268,8 @@ gst_vaapisink_get_caps_impl (GstBaseSink * base_sink)
gst_caps_append (out_caps, gst_caps_copy (raw_caps));
feature_caps = gst_caps_copy (raw_caps);
features = gst_caps_features_new
(GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL);
gst_caps_set_features (feature_caps, 0, features);
gst_caps_append (out_caps, feature_caps);
......
......@@ -107,11 +107,14 @@ fill_video_alignment (GstVaapiVideoBufferPool * pool, GstVideoAlignment * align)
{
GstVideoInfo *const vip = &pool->priv->alloc_info;
guint i;
gint nth_bit;
gst_video_alignment_reset (align);
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (vip); i++)
align->stride_align[i] =
(1U << g_bit_nth_lsf (GST_VIDEO_INFO_PLANE_STRIDE (vip, i), 0)) - 1;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (vip); i++) {
nth_bit = g_bit_nth_lsf (GST_VIDEO_INFO_PLANE_STRIDE (vip, i), 0);
if (nth_bit >= 0)
align->stride_align[i] = (1U << nth_bit) - 1;
}
}
static const gchar **
......@@ -168,7 +171,10 @@ gst_vaapi_video_buffer_pool_set_config (GstBufferPool * pool,
if (allocator) {
const GstVideoInfo *alloc_vinfo =
gst_allocator_get_vaapi_video_info (allocator, &surface_alloc_flags);
vinfo_changed = gst_video_info_changed (alloc_vinfo, &new_vip);
if (!alloc_vinfo)
vinfo_changed = TRUE;
else
vinfo_changed = gst_video_info_changed (alloc_vinfo, &new_vip);
}
if (vinfo_changed && allocator && priv->use_dmabuf_memory) {
......
......@@ -169,8 +169,6 @@ gst_vaapi_video_memory_sync (GstVaapiVideoMemory * mem);
#define GST_VAAPI_IS_VIDEO_ALLOCATOR(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_VAAPI_TYPE_VIDEO_ALLOCATOR))
#define GST_VAAPI_VIDEO_ALLOCATOR_NAME "GstVaapiVideoAllocator"
/**
* GstVaapiVideoAllocator:
*
......
......@@ -25,6 +25,56 @@
</GitRepository>
</repository>
<release>
<Version>
<revision>1.12.5</revision>
<branch>1.12</branch>
<name></name>
<created>2018-03-28</created>
<file-release rdf:resource="https://gstreamer.freedesktop.org/src/gstreamer-vaapi/gstreamer-vaapi-1.12.5.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.12.4</revision>
<branch>1.12</branch>
<name></name>
<created>2017-12-07</created>
<file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer-vaapi/gstreamer-vaapi-1.12.4.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.12.3</revision>
<branch>1.12</branch>
<name></name>
<created>2017-09-18</created>
<file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer-vaapi/gstreamer-vaapi-1.12.3.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.12.2</revision>
<branch>1.12</branch>
<name></name>
<created>2017-07-14</created>
<file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer-vaapi/gstreamer-vaapi-1.12.2.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.12.1</revision>
<branch>1.12</branch>
<name></name>
<created>2017-06-20</created>
<file-release rdf:resource="http://gstreamer.freedesktop.org/src/gstreamer-vaapi/gstreamer-vaapi-1.12.1.tar.xz" />
</Version>
</release>
<release>
<Version>
<revision>1.12.0</revision>
......
project('gstreamer-vaapi', 'c',
version : '1.12.0',
version : '1.12.5',
meson_version : '>= 0.36.0',
default_options : [ 'warning_level=1',
'buildtype=debugoptimized' ])
......@@ -15,6 +15,7 @@ else
gst_version_nano = 0
endif
libva_req = ['>= 0.30.4', '!= 0.99.0']
glib_req = '>= 2.40.0'
gst_req = '>= @0@.@1@.0'.format(gst_version_major, gst_version_minor)
......@@ -37,7 +38,7 @@ gstcodecparsers_dep = dependency('gstreamer-codecparsers-1.0', version : gst_req
gstgl_dep = dependency('gstreamer-gl-1.0', version : gst_req,
fallback : ['gst-plugins-bad', 'gstgl_dep'], required: false)
gmodule_dep = dependency('gmodule-2.0', required: false)
libva_dep = dependency('libva', version: ['>= 0.30.4', '< 0.99.0'])
libva_dep = dependency('libva', version: libva_req)
libva_drm_dep = dependency('libva-drm', version: '>= 0.33.0', required: false)
libva_wayland_dep = dependency('libva-wayland', version: '>= 0.33.0', required: false)
......@@ -47,17 +48,24 @@ libudev_dep = dependency('libudev', required: false)
egl_dep = dependency('egl', required: false)
gl_dep = dependency('gl', required: false)
glesv2_dep = dependency('glesv2', required: false)
glesv3_dep = dependency('glesv3', required: false)
libdl_dep = cc.find_library('dl', rqeuired: false)
libdl_dep = cc.find_library('dl', required: false)
wayland_client_dep = dependency('wayland-client', required: false)
x11_dep = dependency('x11', required: false)
xrandr_dep = dependency('xrandr', required: false)
xrender_dep = dependency('xrender', required: false)
GLES_VERSION_MASK = 0
GLES_VERSION_MASK += gl_dep.found() ? 1 : 0
GLES_VERSION_MASK += glesv2_dep.found() ? 4 : 0
GLES_VERSION_MASK += glesv3_dep.found() ? 8 : 0
GLES_VERSION_MASK = gl_dep.found() ? 1 : 0
if glesv2_dep.found()
if (cc.has_header('GLES2/gl2.h', dependencies: glesv2_dep) and
cc.has_header('GLES2/gl2ext.h', dependencies: glesv2_dep))
GLES_VERSION_MASK += 4
endif
if (cc.has_header('GLES3/gl3.h', dependencies: glesv2_dep) and
cc.has_header('GLES3/gl3ext.h', dependencies: glesv2_dep) and
cc.has_header('GLES2/gl2ext.h', dependencies: glesv2_dep))
GLES_VERSION_MASK += 8
endif
endif
USE_ENCODERS = libva_dep.version().version_compare('>= 0.34.0') and get_option('with_encoders') != 'no'
USE_H265_DECODER = cc.has_header('va/va_dec_hevc.h', dependencies: libva_dep, prefix: '#include <va/va.h>')
......@@ -102,7 +110,7 @@ cdata.set10('HAVE_XRANDR', xrandr_dep.found())
cdata.set10('HAVE_XRENDER', xrender_dep.found())
cdata.set10('USE_VA_VPP', true)
cdata.set10('USE_GST_GL_HELPERS', gstgl_dep.found())
cdata.set('GLES_VERSION_MASK', GLES_VERSION_MASK)
cdata.set('USE_GLES_VERSION_MASK', GLES_VERSION_MASK)
runcmd = run_command('pkg-config', '--variable=driverdir', 'libva')
if runcmd.returncode() == 0
cdata.set('VA_DRIVERS_PATH', '"@0@"'.format(runcmd.stdout().strip()))
......
noinst_PROGRAMS = \
test-vaapisink \
test-vaapipostproc \
$(NULL)
TEST_CFLAGS = \
......@@ -17,4 +18,8 @@ test_vaapisink_SOURCES = test-vaapisink.c
test_vaapisink_CFLAGS = $(TEST_CFLAGS)
test_vaapisink_LDADD = $(TEST_LIBS)
test_vaapipostproc_SOURCES = test-vaapipostproc.c
test_vaapipostproc_CFLAGS = $(TEST_CFLAGS)
test_vaapipostproc_LDADD = $(TEST_LIBS)
-include $(top_srcdir)/git.mk
/*
* test-vaapipostproc.c - Testsuite for VAAPI Postprocessor
*
* Copyright (C) 2017 Intel Corporation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <gst/gst.h>
#include <gst/base/gstbasetransform.h>
typedef struct _CustomData
{
GstElement *pipeline;
GstElement *postproc;
GMainLoop *loop;
} AppData;
static gboolean
_check_passthrough_mode (gpointer user_data)
{
gboolean ret;
AppData *data = (AppData *) user_data;
ret = gst_base_transform_is_passthrough (GST_BASE_TRANSFORM (data->postproc));
if (ret)
gst_println ("Now this pipeline is on passthrough mode");
else
gst_println ("Now this pipeline is NOT on passthrough mode");
return FALSE;
}
static void
set_contrast (AppData * data)
{
static gfloat value = 1.0;
value = value == 1.0 ? 0.5 : 1.0;
g_object_set (data->postproc, "contrast", value, NULL);
gst_println ("contrast value is changed to %f", value);
g_timeout_add (300, _check_passthrough_mode, data);
}
static void
change_size (AppData * data)
{
static gint i = 0;
if (i == 0) {
g_object_set (data->postproc, "width", 1280, "height", 720, NULL);
gst_println ("frame size is changed to 1280x720");
i++;
} else {
g_object_set (data->postproc, "width", 0, "height", 0, NULL);
gst_println ("frame size is changed to default");
i = 0;
}
g_timeout_add (300, _check_passthrough_mode, data);
}
/* Process keyboard input */
static gboolean
handle_keyboard (GIOChannel * source, GIOCondition cond, AppData * data)
{
gchar *str = NULL;
if (g_io_channel_read_line (source, &str, NULL, NULL,
NULL) != G_IO_STATUS_NORMAL) {
return TRUE;
}
switch (g_ascii_tolower (str[0])) {
case 's':{
set_contrast (data);
break;
}
case 'c':{
change_size (data);
break;
}
case 'q':
g_main_loop_quit (data->loop);
break;
default:
break;
}
g_free (str);
return TRUE;
}
int
main (int argc, char *argv[])
{
AppData data = { 0, };
GstStateChangeReturn ret;
GIOChannel *io_stdin;
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Print usage map */
gst_println ("USAGE: Choose one of the following options, then press enter:\n"
" 's' to set contrast\n" " 'c' to change size\n" " 'q' to quit\n");
data.pipeline =
gst_parse_launch
("videotestsrc name=src ! vaapih264enc ! vaapih264dec ! vaapipostproc name=postproc ! vaapisink",
NULL);
data.postproc = gst_bin_get_by_name (GST_BIN (data.pipeline), "postproc");
/* Add a keyboard watch so we get notified of keystrokes */
io_stdin = g_io_channel_unix_new (fileno (stdin));
g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc) handle_keyboard, &data);
/* Start playing */
ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
g_printerr ("Unable to set the pipeline to the playing state.\n");
gst_object_unref (data.pipeline);
return -1;
}
g_timeout_add (300, _check_passthrough_mode, &data);
/* Create a GLib Main Loop and set it to run */
data.loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (data.loop);
/* Free resources */
g_main_loop_unref (data.loop);
g_io_channel_unref (io_stdin);
gst_element_set_state (data.pipeline, GST_STATE_NULL);
gst_object_unref (data.postproc);
gst_object_unref (data.pipeline);
return 0;
}