~ubuntu-branches/ubuntu/vivid/gstreamer-vaapi/vivid

« back to all changes in this revision

Viewing changes to gst/vaapi/gstvaapipostproc.c

  • Committer: Package Import Robot
  • Author(s): Vincent Cheng
  • Date: 2014-08-06 23:56:00 UTC
  • mfrom: (0.1.4 sid) (1.1.3)
  • Revision ID: package-import@ubuntu.com-20140806235600-fg1kcmiu67k315q5
Tags: 0.5.9-2
* Remove spurious build-deps: libva-drm1, libavcodec-dev. (Closes: #757283)
* Drop Build-Depends-Indep and build docs unconditionally on all archs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  gstvaapipostproc.c - VA-API video postprocessing
3
3
 *
4
 
 *  Copyright (C) 2012-2013 Intel Corporation
 
4
 *  Copyright (C) 2012-2014 Intel Corporation
5
5
 *    Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
6
6
 *
7
7
 *  This library is free software; you can redistribute it and/or
34
34
 
35
35
#include "gstvaapipostproc.h"
36
36
#include "gstvaapipluginutil.h"
37
 
#include "gstvaapivideocontext.h"
38
37
#include "gstvaapivideobuffer.h"
39
38
#if GST_CHECK_VERSION(1,0,0)
40
39
#include "gstvaapivideobufferpool.h"
89
88
        GST_PAD_ALWAYS,
90
89
        GST_STATIC_CAPS(gst_vaapipostproc_src_caps_str));
91
90
 
92
 
/* GstImplementsInterface interface */
93
 
#if !GST_CHECK_VERSION(1,0,0)
94
 
static gboolean
95
 
gst_vaapipostproc_implements_interface_supported(
96
 
    GstImplementsInterface *iface,
97
 
    GType                   type
98
 
)
99
 
{
100
 
    return (type == GST_TYPE_VIDEO_CONTEXT);
101
 
}
102
 
 
103
 
static void
104
 
gst_vaapipostproc_implements_iface_init(GstImplementsInterfaceClass *iface)
105
 
{
106
 
    iface->supported = gst_vaapipostproc_implements_interface_supported;
107
 
}
108
 
#endif
109
 
 
110
 
/* GstVideoContext interface */
111
 
#if !GST_CHECK_VERSION(1,1,0)
112
 
static void
113
 
gst_vaapipostproc_set_video_context(
114
 
    GstVideoContext *context,
115
 
    const gchar     *type,
116
 
    const GValue    *value
117
 
)
118
 
{
119
 
    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(context);
120
 
 
121
 
    gst_vaapi_set_display(type, value, &postproc->display);
122
 
 
123
 
    if (postproc->uploader)
124
 
        gst_vaapi_uploader_ensure_display(postproc->uploader, postproc->display);
125
 
}
126
 
 
127
 
static void
128
 
gst_video_context_interface_init(GstVideoContextInterface *iface)
129
 
{
130
 
    iface->set_context = gst_vaapipostproc_set_video_context;
131
 
}
132
 
 
133
 
#define GstVideoContextClass GstVideoContextInterface
134
 
#endif
135
 
 
136
91
G_DEFINE_TYPE_WITH_CODE(
137
92
    GstVaapiPostproc,
138
93
    gst_vaapipostproc,
139
94
    GST_TYPE_BASE_TRANSFORM,
140
 
#if !GST_CHECK_VERSION(1,0,0)
141
 
    G_IMPLEMENT_INTERFACE(GST_TYPE_IMPLEMENTS_INTERFACE,
142
 
                          gst_vaapipostproc_implements_iface_init);
143
 
#endif
144
 
#if !GST_CHECK_VERSION(1,1,0)
145
 
    G_IMPLEMENT_INTERFACE(GST_TYPE_VIDEO_CONTEXT,
146
 
                          gst_video_context_interface_init)
147
 
#endif
148
 
    )
 
95
    GST_VAAPI_PLUGIN_BASE_INIT_INTERFACES)
149
96
 
150
97
enum {
151
98
    PROP_0,
158
105
    PROP_DEINTERLACE_METHOD,
159
106
    PROP_DENOISE,
160
107
    PROP_SHARPEN,
 
108
    PROP_HUE,
 
109
    PROP_SATURATION,
 
110
    PROP_BRIGHTNESS,
 
111
    PROP_CONTRAST,
161
112
};
162
113
 
163
114
#define DEFAULT_FORMAT                  GST_VIDEO_FORMAT_ENCODED
254
205
    return NULL;
255
206
}
256
207
 
257
 
#if GST_CHECK_VERSION(1,1,0)
258
 
static void
259
 
gst_vaapipostproc_set_context(GstElement *element, GstContext *context)
260
 
{
261
 
    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(element);
262
 
    GstVaapiDisplay *display = NULL;
263
 
 
264
 
    if (gst_vaapi_video_context_get_display(context, &display)) {
265
 
        GST_INFO_OBJECT(element, "set display %p", display);
266
 
        gst_vaapi_display_replace(&postproc->display, display);
267
 
    }
268
 
}
269
 
#endif
270
 
 
271
208
static inline gboolean
272
209
gst_vaapipostproc_ensure_display(GstVaapiPostproc *postproc)
273
210
{
274
 
    return gst_vaapi_ensure_display(postproc, GST_VAAPI_DISPLAY_TYPE_ANY,
275
 
        &postproc->display);
 
211
    return gst_vaapi_plugin_base_ensure_display(GST_VAAPI_PLUGIN_BASE(postproc));
276
212
}
277
213
 
278
214
static gboolean
280
216
{
281
217
    if (!gst_vaapipostproc_ensure_display(postproc))
282
218
        return FALSE;
283
 
 
284
 
    if (!postproc->uploader) {
285
 
        postproc->uploader = gst_vaapi_uploader_new(postproc->display);
286
 
        if (!postproc->uploader)
287
 
            return FALSE;
288
 
    }
289
 
 
290
 
    if (!gst_vaapi_uploader_ensure_display(postproc->uploader,
291
 
            postproc->display))
292
 
        return FALSE;
293
 
    return TRUE;
294
 
}
295
 
 
296
 
static gboolean
297
 
gst_vaapipostproc_ensure_uploader_caps(GstVaapiPostproc *postproc)
298
 
{
299
 
#if !GST_CHECK_VERSION(1,0,0)
300
 
    if (postproc->is_raw_yuv && !gst_vaapi_uploader_ensure_caps(
301
 
            postproc->uploader, postproc->sinkpad_caps, NULL))
302
 
        return FALSE;
303
 
#endif
 
219
    if (!gst_vaapi_plugin_base_ensure_uploader(GST_VAAPI_PLUGIN_BASE(postproc)))
 
220
        return FALSE;
304
221
    return TRUE;
305
222
}
306
223
 
313
230
    if (!gst_vaapipostproc_ensure_display(postproc))
314
231
        return FALSE;
315
232
 
316
 
    postproc->filter = gst_vaapi_filter_new(postproc->display);
 
233
    postproc->filter = gst_vaapi_filter_new(
 
234
        GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc));
317
235
    if (!postproc->filter)
318
236
        return FALSE;
319
237
    return TRUE;
338
256
static gboolean
339
257
gst_vaapipostproc_create(GstVaapiPostproc *postproc)
340
258
{
 
259
    if (!gst_vaapi_plugin_base_open(GST_VAAPI_PLUGIN_BASE(postproc)))
 
260
        return FALSE;
341
261
    if (!gst_vaapipostproc_ensure_display(postproc))
342
262
        return FALSE;
343
263
    if (!gst_vaapipostproc_ensure_uploader(postproc))
344
264
        return FALSE;
345
 
    if (!gst_vaapipostproc_ensure_uploader_caps(postproc))
346
 
        return FALSE;
347
265
    if (gst_vaapipostproc_ensure_filter(postproc))
348
266
        postproc->use_vpp = TRUE;
349
267
    return TRUE;
369
287
gst_vaapipostproc_destroy(GstVaapiPostproc *postproc)
370
288
{
371
289
    ds_reset(&postproc->deinterlace_state);
372
 
#if GST_CHECK_VERSION(1,0,0)
373
 
    g_clear_object(&postproc->sinkpad_buffer_pool);
374
 
#endif
375
 
    g_clear_object(&postproc->uploader);
376
290
    gst_vaapipostproc_destroy_filter(postproc);
377
 
    gst_vaapi_display_replace(&postproc->display, NULL);
378
291
 
379
292
    gst_caps_replace(&postproc->allowed_sinkpad_caps, NULL);
380
 
    gst_caps_replace(&postproc->sinkpad_caps, NULL);
381
293
    gst_caps_replace(&postproc->allowed_srcpad_caps, NULL);
382
 
    gst_caps_replace(&postproc->srcpad_caps,  NULL);
 
294
    gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(postproc));
383
295
}
384
296
 
385
297
static gboolean
388
300
    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
389
301
 
390
302
    ds_reset(&postproc->deinterlace_state);
 
303
    if (!gst_vaapi_plugin_base_open(GST_VAAPI_PLUGIN_BASE(postproc)))
 
304
        return FALSE;
391
305
    if (!gst_vaapipostproc_ensure_display(postproc))
392
306
        return FALSE;
393
307
    return TRUE;
399
313
    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
400
314
 
401
315
    ds_reset(&postproc->deinterlace_state);
402
 
    gst_vaapi_display_replace(&postproc->display, NULL);
 
316
    gst_vaapi_plugin_base_close(GST_VAAPI_PLUGIN_BASE(postproc));
403
317
    return TRUE;
404
318
}
405
319
 
406
320
static gboolean
407
 
is_interlaced_buffer(GstVaapiPostproc *postproc, GstBuffer *buf)
 
321
should_deinterlace_buffer(GstVaapiPostproc *postproc, GstBuffer *buf)
408
322
{
409
 
    if (!(postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE))
 
323
    if (!(postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) ||
 
324
        postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_DISABLED)
410
325
        return FALSE;
411
326
 
 
327
    if (postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_INTERLACED)
 
328
        return TRUE;
 
329
 
 
330
    g_assert(postproc->deinterlace_mode == GST_VAAPI_DEINTERLACE_MODE_AUTO);
 
331
 
412
332
    switch (GST_VIDEO_INFO_INTERLACE_MODE(&postproc->sinkpad_info)) {
 
333
    case GST_VIDEO_INTERLACE_MODE_INTERLEAVED:
 
334
        return TRUE;
 
335
    case GST_VIDEO_INTERLACE_MODE_PROGRESSIVE:
 
336
        return FALSE;
413
337
    case GST_VIDEO_INTERLACE_MODE_MIXED:
414
338
#if GST_CHECK_VERSION(1,0,0)
415
 
        if (!GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_FLAG_INTERLACED))
416
 
            return FALSE;
 
339
        if (GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_FLAG_INTERLACED))
 
340
            return TRUE;
417
341
#else
418
 
        if (GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_PROGRESSIVE))
419
 
            return FALSE;
 
342
        if (!GST_BUFFER_FLAG_IS_SET(buf, GST_VIDEO_BUFFER_PROGRESSIVE))
 
343
            return TRUE;
420
344
#endif
421
345
        break;
422
346
    default:
 
347
        GST_ERROR("unhandled \"interlace-mode\", disabling deinterlacing" );
423
348
        break;
424
349
    }
425
 
    return TRUE;
 
350
    return FALSE;
426
351
}
427
352
 
428
353
static GstBuffer *
437
362
        goto error_create_buffer;
438
363
 
439
364
#if !GST_CHECK_VERSION(1,0,0)
440
 
    gst_buffer_set_caps(outbuf, postproc->srcpad_caps);
 
365
    gst_buffer_set_caps(outbuf, GST_VAAPI_PLUGIN_BASE_SRC_PAD_CAPS(postproc));
441
366
#endif
442
367
    return outbuf;
443
368
 
522
447
    GstVaapiDeinterlaceMethod deint_method;
523
448
    guint flags, deint_flags;
524
449
    gboolean tff, deint, deint_refs, deint_changed;
 
450
    GstVaapiRectangle *crop_rect = NULL;
 
451
#if GST_CHECK_VERSION(1,0,0)
 
452
    GstVaapiRectangle tmp_rect;
 
453
#endif
525
454
 
526
455
    /* Validate filters */
527
456
    if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_FORMAT) &&
534
463
        return GST_FLOW_NOT_SUPPORTED;
535
464
 
536
465
    if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SHARPEN) &&
537
 
        !gst_vaapi_filter_set_denoising_level(postproc->filter,
 
466
        !gst_vaapi_filter_set_sharpening_level(postproc->filter,
538
467
            postproc->sharpen_level))
539
468
        return GST_FLOW_NOT_SUPPORTED;
540
469
 
 
470
    if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_HUE) &&
 
471
        !gst_vaapi_filter_set_hue(postproc->filter,
 
472
            postproc->hue))
 
473
        return GST_FLOW_NOT_SUPPORTED;
 
474
 
 
475
    if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_SATURATION) &&
 
476
        !gst_vaapi_filter_set_saturation(postproc->filter,
 
477
            postproc->saturation))
 
478
        return GST_FLOW_NOT_SUPPORTED;
 
479
 
 
480
    if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS) &&
 
481
        !gst_vaapi_filter_set_brightness(postproc->filter,
 
482
            postproc->brightness))
 
483
        return GST_FLOW_NOT_SUPPORTED;
 
484
 
 
485
    if ((postproc->flags & GST_VAAPI_POSTPROC_FLAG_CONTRAST) &&
 
486
        !gst_vaapi_filter_set_contrast(postproc->filter,
 
487
            postproc->contrast))
 
488
        return GST_FLOW_NOT_SUPPORTED;
 
489
 
541
490
    inbuf_meta = gst_buffer_get_vaapi_video_meta(inbuf);
542
491
    if (!inbuf_meta)
543
492
        goto error_invalid_buffer;
544
493
    inbuf_surface = gst_vaapi_video_meta_get_surface(inbuf_meta);
545
494
 
 
495
#if GST_CHECK_VERSION(1,0,0)
 
496
    GstVideoCropMeta * const crop_meta =
 
497
        gst_buffer_get_video_crop_meta(inbuf);
 
498
    if (crop_meta) {
 
499
        crop_rect = &tmp_rect;
 
500
        crop_rect->x = crop_meta->x;
 
501
        crop_rect->y = crop_meta->y;
 
502
        crop_rect->width = crop_meta->width;
 
503
        crop_rect->height = crop_meta->height;
 
504
    }
 
505
#endif
 
506
    if (!crop_rect)
 
507
        crop_rect = (GstVaapiRectangle *)
 
508
            gst_vaapi_video_meta_get_render_rect(inbuf_meta);
 
509
 
546
510
    timestamp  = GST_BUFFER_TIMESTAMP(inbuf);
547
511
    tff        = GST_BUFFER_FLAG_IS_SET(inbuf, GST_VIDEO_BUFFER_FLAG_TFF);
548
 
    deint      = is_interlaced_buffer(postproc, inbuf);
 
512
    deint      = should_deinterlace_buffer(postproc, inbuf);
549
513
 
550
514
    /* Drop references if deinterlacing conditions changed */
551
515
    deint_changed = deint != ds->deint;
552
516
    if (deint_changed || (ds->num_surfaces > 0 && tff != ds->tff))
553
517
        ds_reset(ds);
 
518
 
 
519
    deint_method = postproc->deinterlace_method;
 
520
    deint_refs = deint_method_is_advanced(deint_method);
 
521
    if (deint_refs) {
 
522
        GstBuffer * const prev_buf = ds_get_buffer(ds, 0);
 
523
        GstClockTime prev_pts, pts = GST_BUFFER_TIMESTAMP(inbuf);
 
524
        /* Reset deinterlacing state when there is a discontinuity */
 
525
        if (prev_buf && (prev_pts = GST_BUFFER_TIMESTAMP(prev_buf)) != pts) {
 
526
            const GstClockTimeDiff pts_diff = GST_CLOCK_DIFF(prev_pts, pts);
 
527
            if (pts_diff < 0 || (postproc->field_duration > 0 &&
 
528
                    pts_diff > postproc->field_duration * 2))
 
529
                ds_reset(ds);
 
530
        }
 
531
    }
 
532
 
554
533
    ds->deint = deint;
555
534
    ds->tff = tff;
556
535
 
557
536
    flags = gst_vaapi_video_meta_get_render_flags(inbuf_meta) &
558
 
        ~(GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD|
559
 
          GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD);
 
537
        ~GST_VAAPI_PICTURE_STRUCTURE_MASK;
560
538
 
561
539
    /* First field */
562
 
    deint_method = postproc->deinterlace_method;
563
 
    deint_refs = deint_method_is_advanced(deint_method);
564
540
    if (postproc->flags & GST_VAAPI_POSTPROC_FLAG_DEINTERLACE) {
565
541
        fieldbuf = create_output_buffer(postproc);
566
542
        if (!fieldbuf)
601
577
                goto error_op_deinterlace;
602
578
        }
603
579
 
 
580
        gst_vaapi_filter_set_cropping_rectangle(postproc->filter, crop_rect);
604
581
        status = gst_vaapi_filter_process(postproc->filter, inbuf_surface,
605
582
            outbuf_surface, flags);
606
583
        if (status != GST_VAAPI_FILTER_STATUS_SUCCESS)
639
616
                 postproc->filter, deint_method, 0))
640
617
        goto error_op_deinterlace;
641
618
 
 
619
    gst_vaapi_filter_set_cropping_rectangle(postproc->filter, crop_rect);
642
620
    status = gst_vaapi_filter_process(postproc->filter, inbuf_surface,
643
621
        outbuf_surface, flags);
644
622
    if (status != GST_VAAPI_FILTER_STATUS_SUCCESS)
715
693
 
716
694
    timestamp  = GST_BUFFER_TIMESTAMP(inbuf);
717
695
    tff        = GST_BUFFER_FLAG_IS_SET(inbuf, GST_VIDEO_BUFFER_FLAG_TFF);
718
 
    deint      = is_interlaced_buffer(postproc, inbuf);
 
696
    deint      = should_deinterlace_buffer(postproc, inbuf);
719
697
 
720
698
    flags = gst_vaapi_video_meta_get_render_flags(meta) &
721
 
        ~(GST_VAAPI_PICTURE_STRUCTURE_TOP_FIELD|
722
 
          GST_VAAPI_PICTURE_STRUCTURE_BOTTOM_FIELD);
 
699
        ~GST_VAAPI_PICTURE_STRUCTURE_MASK;
723
700
 
724
701
    /* First field */
725
702
    fieldbuf = create_output_buffer(postproc);
849
826
    deinterlace = is_deinterlace_enabled(postproc, &vi);
850
827
    if (deinterlace)
851
828
        postproc->flags |= GST_VAAPI_POSTPROC_FLAG_DEINTERLACE;
852
 
    postproc->field_duration = gst_util_uint64_scale(
853
 
        GST_SECOND, GST_VIDEO_INFO_FPS_D(&vi),
854
 
        (1 + deinterlace) * GST_VIDEO_INFO_FPS_N(&vi));
 
829
    postproc->field_duration = GST_VIDEO_INFO_FPS_N(&vi) > 0 ?
 
830
        gst_util_uint64_scale(GST_SECOND, GST_VIDEO_INFO_FPS_D(&vi),
 
831
            (1 + deinterlace) * GST_VIDEO_INFO_FPS_N(&vi)) : 0;
855
832
 
856
833
    postproc->is_raw_yuv = GST_VIDEO_INFO_IS_YUV(&vi);
857
 
#if !GST_CHECK_VERSION(1,0,0)
858
 
    if (postproc->is_raw_yuv) {
859
 
        /* Ensure the uploader is set up for upstream allocated buffers */
860
 
        GstVaapiUploader * const uploader = postproc->uploader;
861
 
        if (!gst_vaapi_uploader_ensure_display(uploader, postproc->display))
862
 
            return FALSE;
863
 
        if (!gst_vaapi_uploader_ensure_caps(uploader, caps, NULL))
864
 
            return FALSE;
865
 
    }
866
 
#endif
867
834
    return TRUE;
868
835
}
869
836
 
912
879
 
913
880
    /* Append YUV caps */
914
881
    if (gst_vaapipostproc_ensure_uploader(postproc)) {
915
 
        yuv_caps = gst_vaapi_uploader_get_caps(postproc->uploader);
 
882
        yuv_caps = GST_VAAPI_PLUGIN_BASE_UPLOADER_CAPS(postproc);
916
883
        if (yuv_caps) {
917
884
            out_caps = gst_caps_make_writable(out_caps);
918
885
            gst_caps_append(out_caps, gst_caps_copy(yuv_caps));
926
893
    return TRUE;
927
894
}
928
895
 
929
 
/* Build list of supported formats */
930
 
static gboolean
931
 
build_format_list_value(GArray *formats, GValue *out_value)
932
 
{
933
 
    GValue v_format = { 0, };
934
 
    guint i;
935
 
#if GST_CHECK_VERSION(1,0,0)
936
 
    const gchar *str;
937
 
 
938
 
    g_value_init(out_value, GST_TYPE_LIST);
939
 
 
940
 
    g_value_init(&v_format, G_TYPE_STRING);
941
 
    g_value_set_string(&v_format, "encoded");
942
 
    gst_value_list_append_value(out_value, &v_format);
943
 
 
944
 
    for (i = 0; i < formats->len; i++) {
945
 
        GstVideoFormat const format =
946
 
            g_array_index(formats, GstVideoFormat, i);
947
 
 
948
 
        str = gst_vaapi_video_format_to_string(format);
949
 
        if (!str)
950
 
            continue;
951
 
        g_value_set_string(&v_format, str);
952
 
        gst_value_list_append_value(out_value, &v_format);
953
 
    }
954
 
#else
955
 
    guint32 fourcc;
956
 
 
957
 
    g_value_init(out_value, GST_TYPE_LIST);
958
 
    g_value_init(&v_format, GST_TYPE_FOURCC);
959
 
    for (i = 0; i < formats->len; i++) {
960
 
        GstVideoFormat const format =
961
 
            g_array_index(formats, GstVideoFormat, i);
962
 
 
963
 
        fourcc = gst_video_format_to_fourcc(format);
964
 
        if (!fourcc)
965
 
            continue;
966
 
        gst_value_set_fourcc(&v_format, fourcc);
967
 
        gst_value_list_append_value(out_value, &v_format);
968
 
    }
969
 
#endif
970
 
 
971
 
    g_value_unset(&v_format);
972
 
    return TRUE;
973
 
}
974
 
 
975
896
/* Fixup output caps so that to reflect the supported set of pixel formats */
976
897
static GstCaps *
977
898
expand_allowed_srcpad_caps(GstVaapiPostproc *postproc, GstCaps *caps)
978
899
{
979
 
    GValue value = { 0, };
 
900
    GValue value = G_VALUE_INIT, v_format = G_VALUE_INIT;
980
901
    guint i, num_structures;
981
902
    gboolean had_filter;
982
903
 
987
908
        goto cleanup;
988
909
 
989
910
    /* Reset "format" field for each structure */
990
 
    if (!build_format_list_value(postproc->filter_formats, &value))
 
911
    if (!gst_vaapi_value_set_format_list(&value, postproc->filter_formats))
991
912
        goto cleanup;
 
913
    if (gst_vaapi_value_set_format(&v_format, GST_VIDEO_FORMAT_ENCODED)) {
 
914
        gst_value_list_prepend_value(&value, &v_format);
 
915
        g_value_unset(&v_format);
 
916
    }
992
917
 
993
918
    num_structures = gst_caps_get_size(caps);
994
919
    for (i = 0; i < num_structures; i++) {
1180
1105
    return TRUE;
1181
1106
}
1182
1107
 
1183
 
static GstBuffer *
1184
 
get_source_buffer(GstVaapiPostproc *postproc, GstBuffer *inbuf)
1185
 
{
1186
 
    GstVaapiVideoMeta *meta;
1187
 
    GstBuffer *outbuf;
1188
 
#if GST_CHECK_VERSION(1,0,0)
1189
 
    GstVideoFrame src_frame, out_frame;
1190
 
#endif
1191
 
 
1192
 
    meta = gst_buffer_get_vaapi_video_meta(inbuf);
1193
 
    if (meta)
1194
 
        return gst_buffer_ref(inbuf);
1195
 
 
1196
 
#if GST_CHECK_VERSION(1,0,0)
1197
 
    if (!postproc->is_raw_yuv)
1198
 
        goto error_invalid_buffer;
1199
 
 
1200
 
    if (!postproc->sinkpad_buffer_pool)
1201
 
        goto error_no_pool;
1202
 
 
1203
 
    if (!gst_buffer_pool_set_active(postproc->sinkpad_buffer_pool, TRUE))
1204
 
        goto error_active_pool;
1205
 
 
1206
 
    outbuf = NULL;
1207
 
    if (gst_buffer_pool_acquire_buffer(postproc->sinkpad_buffer_pool,
1208
 
            &outbuf, NULL) != GST_FLOW_OK)
1209
 
        goto error_create_buffer;
1210
 
 
1211
 
    if (!gst_video_frame_map(&src_frame, &postproc->sinkpad_info, inbuf,
1212
 
            GST_MAP_READ))
1213
 
        goto error_map_src_buffer;
1214
 
 
1215
 
    if (!gst_video_frame_map(&out_frame, &postproc->sinkpad_info, outbuf,
1216
 
            GST_MAP_WRITE))
1217
 
        goto error_map_dst_buffer;
1218
 
 
1219
 
    if (!gst_video_frame_copy(&out_frame, &src_frame))
1220
 
        goto error_copy_buffer;
1221
 
 
1222
 
    gst_video_frame_unmap(&out_frame);
1223
 
    gst_video_frame_unmap(&src_frame);
1224
 
    gst_buffer_copy_into(outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
1225
 
    return outbuf;
1226
 
 
1227
 
    /* ERRORS */
1228
 
error_invalid_buffer:
1229
 
    {
1230
 
        GST_ERROR("failed to validate source buffer");
1231
 
        return NULL;
1232
 
    }
1233
 
error_no_pool:
1234
 
    {
1235
 
        GST_ERROR("no buffer pool was negotiated");
1236
 
        return NULL;
1237
 
    }
1238
 
error_active_pool:
1239
 
    {
1240
 
        GST_ERROR("failed to activate buffer pool");
1241
 
        return NULL;
1242
 
    }
1243
 
error_map_dst_buffer:
1244
 
    {
1245
 
        gst_video_frame_unmap(&src_frame);
1246
 
        // fall-through
1247
 
    }
1248
 
error_map_src_buffer:
1249
 
    {
1250
 
        GST_ERROR("failed to map buffer");
1251
 
        gst_buffer_unref(outbuf);
1252
 
        return NULL;
1253
 
    }
1254
 
#else
1255
 
    outbuf = gst_vaapi_uploader_get_buffer(postproc->uploader);
1256
 
    if (!outbuf)
1257
 
        goto error_create_buffer;
1258
 
    if (!gst_vaapi_uploader_process(postproc->uploader, inbuf, outbuf))
1259
 
        goto error_copy_buffer;
1260
 
 
1261
 
    gst_buffer_copy_metadata(outbuf, inbuf,
1262
 
        GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);
1263
 
    return outbuf;
1264
 
#endif
1265
 
 
1266
 
    /* ERRORS */
1267
 
error_create_buffer:
1268
 
    {
1269
 
        GST_ERROR("failed to create buffer");
1270
 
        return NULL;
1271
 
    }
1272
 
error_copy_buffer:
1273
 
    {
1274
 
        GST_ERROR("failed to upload buffer to VA surface");
1275
 
#if GST_CHECK_VERSION(1,0,0)
1276
 
        gst_video_frame_unmap(&out_frame);
1277
 
        gst_video_frame_unmap(&src_frame);
1278
 
#endif
1279
 
        gst_buffer_unref(outbuf);
1280
 
        return NULL;
1281
 
    }
1282
 
}
1283
 
 
1284
1108
static GstFlowReturn
1285
1109
gst_vaapipostproc_transform(GstBaseTransform *trans, GstBuffer *inbuf,
1286
1110
    GstBuffer *outbuf)
1289
1113
    GstBuffer *buf;
1290
1114
    GstFlowReturn ret;
1291
1115
 
1292
 
    buf = get_source_buffer(postproc, inbuf);
1293
 
    if (!buf)
 
1116
    ret = gst_vaapi_plugin_base_get_input_buffer(
 
1117
        GST_VAAPI_PLUGIN_BASE(postproc), inbuf, &buf);
 
1118
    if (ret != GST_FLOW_OK)
1294
1119
        return GST_FLOW_ERROR;
1295
1120
 
1296
1121
    ret = GST_FLOW_NOT_SUPPORTED;
1336
1161
}
1337
1162
 
1338
1163
static gboolean
1339
 
ensure_sinkpad_buffer_pool(GstVaapiPostproc *postproc, GstCaps *caps)
1340
 
{
1341
 
#if GST_CHECK_VERSION(1,0,0)
1342
 
    GstBufferPool *pool;
1343
 
    GstCaps *pool_caps;
1344
 
    GstStructure *config;
1345
 
    GstVideoInfo vi;
1346
 
    gboolean need_pool;
1347
 
 
1348
 
    if (!gst_vaapipostproc_ensure_display(postproc))
1349
 
        return FALSE;
1350
 
 
1351
 
    if (postproc->sinkpad_buffer_pool) {
1352
 
        config = gst_buffer_pool_get_config(postproc->sinkpad_buffer_pool);
1353
 
        gst_buffer_pool_config_get_params(config, &pool_caps, NULL, NULL, NULL);
1354
 
        need_pool = !gst_caps_is_equal(caps, pool_caps);
1355
 
        gst_structure_free(config);
1356
 
        if (!need_pool)
1357
 
            return TRUE;
1358
 
        g_clear_object(&postproc->sinkpad_buffer_pool);
1359
 
        postproc->sinkpad_buffer_size = 0;
1360
 
    }
1361
 
 
1362
 
    pool = gst_vaapi_video_buffer_pool_new(postproc->display);
1363
 
    if (!pool)
1364
 
        goto error_create_pool;
1365
 
 
1366
 
    gst_video_info_init(&vi);
1367
 
    gst_video_info_from_caps(&vi, caps);
1368
 
    if (GST_VIDEO_INFO_FORMAT(&vi) == GST_VIDEO_FORMAT_ENCODED) {
1369
 
        GST_DEBUG("assume sink pad buffer pool format is NV12");
1370
 
        gst_video_info_set_format(&vi, GST_VIDEO_FORMAT_NV12,
1371
 
            GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
1372
 
    }
1373
 
    postproc->sinkpad_buffer_size = vi.size;
1374
 
 
1375
 
    config = gst_buffer_pool_get_config(pool);
1376
 
    gst_buffer_pool_config_set_params(config, caps,
1377
 
        postproc->sinkpad_buffer_size, 0, 0);
1378
 
    gst_buffer_pool_config_add_option(config,
1379
 
        GST_BUFFER_POOL_OPTION_VAAPI_VIDEO_META);
1380
 
    gst_buffer_pool_config_add_option(config,
1381
 
        GST_BUFFER_POOL_OPTION_VIDEO_META);
1382
 
    if (!gst_buffer_pool_set_config(pool, config))
1383
 
        goto error_pool_config;
1384
 
    postproc->sinkpad_buffer_pool = pool;
1385
 
    return TRUE;
1386
 
 
1387
 
    /* ERRORS */
1388
 
error_create_pool:
1389
 
    {
1390
 
        GST_ERROR("failed to create buffer pool");
1391
 
        return FALSE;
1392
 
    }
1393
 
error_pool_config:
1394
 
    {
1395
 
        GST_ERROR("failed to reset buffer pool config");
1396
 
        gst_object_unref(pool);
1397
 
        return FALSE;
1398
 
    }
1399
 
#else
1400
 
    return TRUE;
1401
 
#endif
1402
 
}
1403
 
 
1404
 
static gboolean
1405
1164
ensure_srcpad_buffer_pool(GstVaapiPostproc *postproc, GstCaps *caps)
1406
1165
{
1407
1166
    GstVideoInfo vi;
1412
1171
    gst_video_info_set_format(&vi, postproc->format,
1413
1172
        GST_VIDEO_INFO_WIDTH(&vi), GST_VIDEO_INFO_HEIGHT(&vi));
1414
1173
 
1415
 
    if (!video_info_changed(&vi, &postproc->filter_pool_info))
 
1174
    if (postproc->filter_pool && !video_info_changed(&vi, &postproc->filter_pool_info))
1416
1175
        return TRUE;
1417
1176
    postproc->filter_pool_info = vi;
1418
1177
 
1419
 
    pool = gst_vaapi_surface_pool_new(postproc->display,
 
1178
    pool = gst_vaapi_surface_pool_new(GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc),
1420
1179
        &postproc->filter_pool_info);
1421
1180
    if (!pool)
1422
1181
        return FALSE;
1440
1199
 
1441
1200
    if (caps_changed) {
1442
1201
        gst_vaapipostproc_destroy(postproc);
1443
 
        gst_caps_replace(&postproc->sinkpad_caps, caps);
1444
 
        gst_caps_replace(&postproc->srcpad_caps, out_caps);
1445
1202
        if (!gst_vaapipostproc_create(postproc))
1446
1203
            return FALSE;
 
1204
        if (!gst_vaapi_plugin_base_set_caps(GST_VAAPI_PLUGIN_BASE(trans),
 
1205
                caps, out_caps))
 
1206
            return FALSE;
1447
1207
    }
1448
1208
 
1449
 
    if (!ensure_sinkpad_buffer_pool(postproc, caps))
1450
 
        return FALSE;
1451
1209
    if (!ensure_srcpad_buffer_pool(postproc, out_caps))
1452
1210
        return FALSE;
1453
1211
    return TRUE;
1461
1219
 
1462
1220
    GST_INFO_OBJECT(trans, "query type `%s'", GST_QUERY_TYPE_NAME(query));
1463
1221
 
1464
 
    if (gst_vaapi_reply_to_query(query, postproc->display)) {
1465
 
        GST_DEBUG("sharing display %p", postproc->display);
 
1222
    if (gst_vaapi_reply_to_query(query, GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc))) {
 
1223
        GST_DEBUG("sharing display %p", GST_VAAPI_PLUGIN_BASE_DISPLAY(postproc));
1466
1224
        return TRUE;
1467
1225
    }
1468
1226
 
1476
1234
    GstQuery *decide_query, GstQuery *query)
1477
1235
{
1478
1236
    GstVaapiPostproc * const postproc = GST_VAAPIPOSTPROC(trans);
1479
 
    GstCaps *caps = NULL;
1480
 
    gboolean need_pool;
 
1237
    GstVaapiPluginBase * const plugin = GST_VAAPI_PLUGIN_BASE(trans);
1481
1238
 
1482
1239
    /* Let vaapidecode allocate the video buffers */
1483
1240
    if (!postproc->is_raw_yuv)
1484
1241
        return FALSE;
1485
 
 
1486
 
    gst_query_parse_allocation(query, &caps, &need_pool);
1487
 
 
1488
 
    if (need_pool) {
1489
 
        if (!caps)
1490
 
            goto error_no_caps;
1491
 
        if (!ensure_sinkpad_buffer_pool(postproc, caps))
1492
 
            return FALSE;
1493
 
        gst_query_add_allocation_pool(query, postproc->sinkpad_buffer_pool,
1494
 
            postproc->sinkpad_buffer_size, 0, 0);
1495
 
    }
1496
 
 
1497
 
    gst_query_add_allocation_meta(query,
1498
 
        GST_VAAPI_VIDEO_META_API_TYPE, NULL);
1499
 
    gst_query_add_allocation_meta(query,
1500
 
        GST_VIDEO_META_API_TYPE, NULL);
1501
 
    gst_query_add_allocation_meta(query,
1502
 
        GST_VIDEO_CROP_META_API_TYPE, NULL);
1503
 
    gst_query_add_allocation_meta(query,
1504
 
        GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL);
 
1242
    if (!gst_vaapi_plugin_base_propose_allocation(plugin, query))
 
1243
        return FALSE;
1505
1244
    return TRUE;
1506
 
 
1507
 
    /* ERRORS */
1508
 
error_no_caps:
1509
 
    {
1510
 
        GST_ERROR("no caps specified");
1511
 
        return FALSE;
1512
 
    }
1513
1245
}
1514
1246
#endif
1515
1247
 
1520
1252
 
1521
1253
    gst_vaapipostproc_destroy(postproc);
1522
1254
 
 
1255
    gst_vaapi_plugin_base_finalize(GST_VAAPI_PLUGIN_BASE(postproc));
1523
1256
    G_OBJECT_CLASS(gst_vaapipostproc_parent_class)->finalize(object);
1524
1257
}
1525
1258
 
1560
1293
         postproc->sharpen_level = g_value_get_float(value);
1561
1294
         postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SHARPEN;
1562
1295
         break;
 
1296
    case PROP_HUE:
 
1297
        postproc->hue = g_value_get_float(value);
 
1298
        postproc->flags |= GST_VAAPI_POSTPROC_FLAG_HUE;
 
1299
        break;
 
1300
    case PROP_SATURATION:
 
1301
        postproc->saturation = g_value_get_float(value);
 
1302
        postproc->flags |= GST_VAAPI_POSTPROC_FLAG_SATURATION;
 
1303
        break;
 
1304
    case PROP_BRIGHTNESS:
 
1305
        postproc->brightness = g_value_get_float(value);
 
1306
        postproc->flags |= GST_VAAPI_POSTPROC_FLAG_BRIGHTNESS;
 
1307
        break;
 
1308
    case PROP_CONTRAST:
 
1309
        postproc->contrast = g_value_get_float(value);
 
1310
        postproc->flags |= GST_VAAPI_POSTPROC_FLAG_CONTRAST;
 
1311
        break;
1563
1312
    default:
1564
1313
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1565
1314
        break;
1601
1350
    case PROP_SHARPEN:
1602
1351
        g_value_set_float(value, postproc->sharpen_level);
1603
1352
        break;
 
1353
    case PROP_HUE:
 
1354
        g_value_set_float(value, postproc->hue);
 
1355
        break;
 
1356
    case PROP_SATURATION:
 
1357
        g_value_set_float(value, postproc->saturation);
 
1358
        break;
 
1359
    case PROP_BRIGHTNESS:
 
1360
        g_value_set_float(value, postproc->brightness);
 
1361
        break;
 
1362
    case PROP_CONTRAST:
 
1363
        g_value_set_float(value, postproc->contrast);
 
1364
        break;
1604
1365
    default:
1605
1366
        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
1606
1367
        break;
1620
1381
    GST_DEBUG_CATEGORY_INIT(gst_debug_vaapipostproc,
1621
1382
                            GST_PLUGIN_NAME, 0, GST_PLUGIN_DESC);
1622
1383
 
 
1384
    gst_vaapi_plugin_base_class_init(GST_VAAPI_PLUGIN_BASE_CLASS(klass));
 
1385
 
1623
1386
    object_class->finalize      = gst_vaapipostproc_finalize;
1624
1387
    object_class->set_property  = gst_vaapipostproc_set_property;
1625
1388
    object_class->get_property  = gst_vaapipostproc_get_property;
1638
1401
    trans_class->prepare_output_buffer =
1639
1402
        gst_vaapipostproc_prepare_output_buffer;
1640
1403
 
1641
 
#if GST_CHECK_VERSION(1,1,0)
1642
 
    element_class->set_context = gst_vaapipostproc_set_context;
1643
 
#endif
1644
 
 
1645
1404
    gst_element_class_set_static_metadata(element_class,
1646
1405
        "VA-API video postprocessing",
1647
1406
        "Filter/Converter/Video",
1716
1475
                           "Width",
1717
1476
                           "Forced output width",
1718
1477
                           0, G_MAXINT, 0,
1719
 
                           G_PARAM_READWRITE));
 
1478
                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1720
1479
 
1721
1480
    /**
1722
1481
     * GstVaapiPostproc:height:
1732
1491
                           "Height",
1733
1492
                           "Forced output height",
1734
1493
                           0, G_MAXINT, 0,
1735
 
                           G_PARAM_READWRITE));
 
1494
                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1736
1495
 
1737
1496
    /**
1738
1497
     * GstVaapiPostproc:force-aspect-ratio:
1748
1507
                              "Force aspect ratio",
1749
1508
                              "When enabled, scaling will respect original aspect ratio",
1750
1509
                              TRUE,
1751
 
                              G_PARAM_READWRITE));
 
1510
                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
1752
1511
 
1753
1512
    /**
1754
1513
     * GstVaapiPostproc:denoise:
1771
1530
        g_object_class_install_property(object_class,
1772
1531
            PROP_SHARPEN, filter_op->pspec);
1773
1532
 
 
1533
    /**
 
1534
     * GstVaapiPostproc:hue:
 
1535
     *
 
1536
     * The color hue, expressed as a float value. Range is -180.0 to
 
1537
     * 180.0. Default value is 0.0 and represents no modification.
 
1538
     */
 
1539
    filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_HUE);
 
1540
    if (filter_op)
 
1541
        g_object_class_install_property(object_class,
 
1542
            PROP_HUE, filter_op->pspec);
 
1543
 
 
1544
    /**
 
1545
     * GstVaapiPostproc:saturation:
 
1546
     *
 
1547
     * The color saturation, expressed as a float value. Range is 0.0
 
1548
     * to 2.0. Default value is 1.0 and represents no modification.
 
1549
     */
 
1550
    filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_SATURATION);
 
1551
    if (filter_op)
 
1552
        g_object_class_install_property(object_class,
 
1553
            PROP_SATURATION, filter_op->pspec);
 
1554
 
 
1555
    /**
 
1556
     * GstVaapiPostproc:brightness:
 
1557
     *
 
1558
     * The color brightness, expressed as a float value. Range is -1.0
 
1559
     * to 1.0. Default value is 0.0 and represents no modification.
 
1560
     */
 
1561
    filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_BRIGHTNESS);
 
1562
    if (filter_op)
 
1563
        g_object_class_install_property(object_class,
 
1564
            PROP_BRIGHTNESS, filter_op->pspec);
 
1565
 
 
1566
    /**
 
1567
     * GstVaapiPostproc:contrast:
 
1568
     *
 
1569
     * The color contrast, expressed as a float value. Range is 0.0 to
 
1570
     * 2.0. Default value is 1.0 and represents no modification.
 
1571
     */
 
1572
    filter_op = find_filter_op(filter_ops, GST_VAAPI_FILTER_OP_CONTRAST);
 
1573
    if (filter_op)
 
1574
        g_object_class_install_property(object_class,
 
1575
            PROP_CONTRAST, filter_op->pspec);
 
1576
 
1774
1577
    g_ptr_array_unref(filter_ops);
1775
1578
}
1776
1579
 
1777
1580
static void
1778
1581
gst_vaapipostproc_init(GstVaapiPostproc *postproc)
1779
1582
{
 
1583
    gst_vaapi_plugin_base_init(GST_VAAPI_PLUGIN_BASE(postproc), GST_CAT_DEFAULT);
 
1584
 
1780
1585
    postproc->format                    = DEFAULT_FORMAT;
1781
1586
    postproc->deinterlace_mode          = DEFAULT_DEINTERLACE_MODE;
1782
1587
    postproc->deinterlace_method        = DEFAULT_DEINTERLACE_METHOD;