~ubuntu-branches/ubuntu/trusty/vdpau-video/trusty-proposed

« back to all changes in this revision

Viewing changes to src/vdpau_video.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Mejia
  • Date: 2010-02-12 14:58:28 UTC
  • Revision ID: james.westby@ubuntu.com-20100212145828-f0q1g7qzq03din26
Tags: upstream-0.6.3
ImportĀ upstreamĀ versionĀ 0.6.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  vdpau_video.c - VDPAU backend for VA API
 
3
 *
 
4
 *  vdpau-video (C) 2009-2010 Splitted-Desktop Systems
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program 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
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 
19
 */
 
20
 
 
21
#include "sysdeps.h"
 
22
#include "vdpau_video.h"
 
23
#include "vdpau_video_x11.h"
 
24
#include "vdpau_decode.h"
 
25
#include "vdpau_subpic.h"
 
26
#include "vdpau_mixer.h"
 
27
#include "utils.h"
 
28
 
 
29
#define DEBUG 1
 
30
#include "debug.h"
 
31
 
 
32
 
 
33
/* Define wait delay (in microseconds) for vaSyncSurface() implementation
 
34
   with polling. */
 
35
#define VDPAU_SYNC_DELAY 5000
 
36
 
 
37
// Translates VA API chroma format to VdpChromaType
 
38
static VdpChromaType get_VdpChromaType(int format)
 
39
{
 
40
    switch (format) {
 
41
    case VA_RT_FORMAT_YUV420: return VDP_CHROMA_TYPE_420;
 
42
    case VA_RT_FORMAT_YUV422: return VDP_CHROMA_TYPE_422;
 
43
    case VA_RT_FORMAT_YUV444: return VDP_CHROMA_TYPE_444;
 
44
    }
 
45
    ASSERT(format);
 
46
    return (VdpChromaType)-1;
 
47
}
 
48
 
 
49
 
 
50
/* ====================================================================== */
 
51
/* === VA API Implementation with VDPAU                               === */
 
52
/* ====================================================================== */
 
53
 
 
54
// Returns the maximum dimensions supported by the VDPAU implementation for that profile
 
55
static inline VdpBool
 
56
get_max_surface_size(
 
57
    vdpau_driver_data_t *driver_data,
 
58
    VdpDecoderProfile    profile,
 
59
    uint32_t            *pmax_width,
 
60
    uint32_t            *pmax_height
 
61
)
 
62
{
 
63
    VdpBool is_supported = VDP_FALSE;
 
64
    VdpStatus vdp_status;
 
65
    uint32_t max_level, max_references, max_width, max_height;
 
66
 
 
67
    vdp_status = vdpau_decoder_query_capabilities(driver_data,
 
68
                                                  driver_data->vdp_device,
 
69
                                                  profile,
 
70
                                                  &is_supported,
 
71
                                                  &max_level,
 
72
                                                  &max_references,
 
73
                                                  &max_width,
 
74
                                                  &max_height);
 
75
 
 
76
    if (pmax_width)
 
77
        *pmax_width = 0;
 
78
    if (pmax_height)
 
79
        *pmax_height = 0;
 
80
 
 
81
    if (vdp_status != VDP_STATUS_OK || !is_supported)
 
82
        return VDP_FALSE;
 
83
 
 
84
    if (pmax_width)
 
85
        *pmax_width = max_width;
 
86
    if (max_height)
 
87
        *pmax_height = max_height;
 
88
 
 
89
    return VDP_TRUE;
 
90
}
 
91
 
 
92
// vaGetConfigAttributes
 
93
VAStatus
 
94
vdpau_GetConfigAttributes(
 
95
    VADriverContextP    ctx,
 
96
    VAProfile           profile,
 
97
    VAEntrypoint        entrypoint,
 
98
    VAConfigAttrib     *attrib_list,
 
99
    int                 num_attribs
 
100
)
 
101
{
 
102
    int i;
 
103
 
 
104
    for (i = 0; i < num_attribs; i++) {
 
105
        switch (attrib_list[i].type) {
 
106
        case VAConfigAttribRTFormat:
 
107
            attrib_list[i].value = VA_RT_FORMAT_YUV420;
 
108
            break;
 
109
        default:
 
110
            attrib_list[i].value = VA_ATTRIB_NOT_SUPPORTED;
 
111
            break;
 
112
        }
 
113
    }
 
114
 
 
115
    return VA_STATUS_SUCCESS;
 
116
}
 
117
 
 
118
static VAStatus
 
119
vdpau_update_attribute(object_config_p obj_config, VAConfigAttrib *attrib)
 
120
{
 
121
    int i;
 
122
 
 
123
    /* Check existing attrbiutes */
 
124
    for (i = 0; obj_config->attrib_count < i; i++) {
 
125
        if (obj_config->attrib_list[i].type == attrib->type) {
 
126
            /* Update existing attribute */
 
127
            obj_config->attrib_list[i].value = attrib->value;
 
128
            return VA_STATUS_SUCCESS;
 
129
        }
 
130
    }
 
131
    if (obj_config->attrib_count < VDPAU_MAX_CONFIG_ATTRIBUTES) {
 
132
        i = obj_config->attrib_count;
 
133
        obj_config->attrib_list[i].type = attrib->type;
 
134
        obj_config->attrib_list[i].value = attrib->value;
 
135
        obj_config->attrib_count++;
 
136
        return VA_STATUS_SUCCESS;
 
137
    }
 
138
    return VA_STATUS_ERROR_MAX_NUM_EXCEEDED;
 
139
}
 
140
 
 
141
// vaDestroyConfig
 
142
VAStatus vdpau_DestroyConfig(VADriverContextP ctx, VAConfigID config_id)
 
143
{
 
144
    VDPAU_DRIVER_DATA_INIT;
 
145
 
 
146
    object_config_p obj_config = VDPAU_CONFIG(config_id);
 
147
    ASSERT(obj_config);
 
148
    if (obj_config == NULL)
 
149
        return VA_STATUS_ERROR_INVALID_CONFIG;
 
150
 
 
151
    object_heap_free(&driver_data->config_heap, (object_base_p)obj_config);
 
152
    return VA_STATUS_SUCCESS;
 
153
}
 
154
 
 
155
// vaCreateConfig
 
156
VAStatus
 
157
vdpau_CreateConfig(
 
158
    VADriverContextP    ctx,
 
159
    VAProfile           profile,
 
160
    VAEntrypoint        entrypoint,
 
161
    VAConfigAttrib     *attrib_list,
 
162
    int                 num_attribs,
 
163
    VAConfigID         *config_id
 
164
)
 
165
{
 
166
    VDPAU_DRIVER_DATA_INIT;
 
167
 
 
168
    VAStatus va_status;
 
169
    int configID;
 
170
    object_config_p obj_config;
 
171
    int i;
 
172
 
 
173
    /* Validate profile and entrypoint */
 
174
    switch (profile) {
 
175
    case VAProfileMPEG2Simple:
 
176
    case VAProfileMPEG2Main:
 
177
        if (entrypoint == VAEntrypointVLD)
 
178
            va_status = VA_STATUS_SUCCESS;
 
179
        else
 
180
            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
 
181
        break;
 
182
    case VAProfileMPEG4Simple:
 
183
    case VAProfileMPEG4AdvancedSimple:
 
184
    case VAProfileMPEG4Main:
 
185
        if (entrypoint == VAEntrypointVLD)
 
186
            va_status = VA_STATUS_SUCCESS;
 
187
        else
 
188
            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
 
189
        break;
 
190
    case VAProfileH264Baseline:
 
191
    case VAProfileH264Main:
 
192
    case VAProfileH264High:
 
193
        if (entrypoint == VAEntrypointVLD)
 
194
            va_status = VA_STATUS_SUCCESS;
 
195
        else
 
196
            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
 
197
        break;
 
198
    case VAProfileVC1Simple:
 
199
    case VAProfileVC1Main:
 
200
    case VAProfileVC1Advanced:
 
201
        if (entrypoint == VAEntrypointVLD)
 
202
            va_status = VA_STATUS_SUCCESS;
 
203
        else
 
204
            va_status = VA_STATUS_ERROR_UNSUPPORTED_ENTRYPOINT;
 
205
        break;
 
206
    default:
 
207
        va_status = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
 
208
        break;
 
209
    }
 
210
 
 
211
    if (va_status != VA_STATUS_SUCCESS)
 
212
        return va_status;
 
213
 
 
214
    configID = object_heap_allocate(&driver_data->config_heap);
 
215
    if ((obj_config = VDPAU_CONFIG(configID)) == NULL)
 
216
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
217
 
 
218
    obj_config->profile = profile;
 
219
    obj_config->entrypoint = entrypoint;
 
220
    obj_config->attrib_list[0].type = VAConfigAttribRTFormat;
 
221
    obj_config->attrib_list[0].value = VA_RT_FORMAT_YUV420;
 
222
    obj_config->attrib_count = 1;
 
223
 
 
224
    for(i = 0; i < num_attribs; i++) {
 
225
        va_status = vdpau_update_attribute(obj_config, &attrib_list[i]);
 
226
        if (va_status != VA_STATUS_SUCCESS) {
 
227
            vdpau_DestroyConfig(ctx, configID);
 
228
            return va_status;
 
229
        }
 
230
    }
 
231
 
 
232
    if (config_id)
 
233
        *config_id = configID;
 
234
 
 
235
    return va_status;
 
236
}
 
237
 
 
238
// vaQueryConfigAttributes
 
239
VAStatus
 
240
vdpau_QueryConfigAttributes(
 
241
    VADriverContextP    ctx,
 
242
    VAConfigID          config_id,
 
243
    VAProfile          *profile,
 
244
    VAEntrypoint       *entrypoint,
 
245
    VAConfigAttrib     *attrib_list,
 
246
    int                *num_attribs
 
247
)
 
248
{
 
249
    VDPAU_DRIVER_DATA_INIT;
 
250
 
 
251
    VAStatus va_status = VA_STATUS_SUCCESS;
 
252
    object_config_p obj_config;
 
253
    int i;
 
254
 
 
255
    obj_config = VDPAU_CONFIG(config_id);
 
256
    ASSERT(obj_config);
 
257
    if (obj_config == NULL)
 
258
        return VA_STATUS_ERROR_INVALID_CONFIG;
 
259
 
 
260
    if (profile)
 
261
        *profile = obj_config->profile;
 
262
 
 
263
    if (entrypoint)
 
264
        *entrypoint = obj_config->entrypoint;
 
265
 
 
266
    if (num_attribs)
 
267
        *num_attribs =  obj_config->attrib_count;
 
268
 
 
269
    if (attrib_list) {
 
270
        for (i = 0; i < obj_config->attrib_count; i++)
 
271
            attrib_list[i] = obj_config->attrib_list[i];
 
272
    }
 
273
 
 
274
    return va_status;
 
275
}
 
276
 
 
277
// Add subpicture association to surface
 
278
// NOTE: the subpicture owns the SubpictureAssociation object
 
279
int surface_add_association(
 
280
    object_surface_p            obj_surface,
 
281
    SubpictureAssociationP      assoc
 
282
)
 
283
{
 
284
    /* Check that we don't already have this association */
 
285
    if (obj_surface->assocs) {
 
286
        unsigned int i;
 
287
        for (i = 0; i < obj_surface->assocs_count; i++) {
 
288
            if (obj_surface->assocs[i] == assoc)
 
289
                return 0;
 
290
            if (obj_surface->assocs[i]->surface == assoc->surface) {
 
291
                /* XXX: this should not happen, but replace it in the interim */
 
292
                ASSERT(obj_surface->assocs[i]->surface != assoc->surface);
 
293
                obj_surface->assocs[i] = assoc;
 
294
                return 0;
 
295
            }
 
296
        }
 
297
    }
 
298
 
 
299
    /* Check that we have not reached the maximum subpictures capacity yet */
 
300
    if (obj_surface->assocs_count >= VDPAU_MAX_SUBPICTURES)
 
301
        return -1;
 
302
 
 
303
    /* Append this subpicture association */
 
304
    SubpictureAssociationP *assocs;
 
305
    assocs = realloc_buffer(&obj_surface->assocs,
 
306
                            &obj_surface->assocs_count_max,
 
307
                            1 + obj_surface->assocs_count,
 
308
                            sizeof(obj_surface->assocs[0]));
 
309
    if (!assocs)
 
310
        return -1;
 
311
 
 
312
    assocs[obj_surface->assocs_count++] = assoc;
 
313
    return 0;
 
314
}
 
315
 
 
316
// Remove subpicture association from surface
 
317
// NOTE: the subpicture owns the SubpictureAssociation object
 
318
int surface_remove_association(
 
319
    object_surface_p            obj_surface,
 
320
    SubpictureAssociationP      assoc
 
321
)
 
322
{
 
323
    if (!obj_surface->assocs || obj_surface->assocs_count == 0)
 
324
        return -1;
 
325
 
 
326
    unsigned int i;
 
327
    const unsigned int last = obj_surface->assocs_count - 1;
 
328
    for (i = 0; i <= last; i++) {
 
329
        if (obj_surface->assocs[i] == assoc) {
 
330
            /* Swap with the last subpicture */
 
331
            obj_surface->assocs[i] = obj_surface->assocs[last];
 
332
            obj_surface->assocs[last] = NULL;
 
333
            obj_surface->assocs_count--;
 
334
            return 0;
 
335
        }
 
336
    }
 
337
    return -1;
 
338
}
 
339
 
 
340
// vaDestroySurfaces
 
341
VAStatus
 
342
vdpau_DestroySurfaces(
 
343
    VADriverContextP    ctx,
 
344
    VASurfaceID        *surface_list,
 
345
    int                 num_surfaces
 
346
)
 
347
{
 
348
    VDPAU_DRIVER_DATA_INIT;
 
349
 
 
350
    int i, j, n;
 
351
    for (i = num_surfaces - 1; i >= 0; i--) {
 
352
        object_surface_p obj_surface = VDPAU_SURFACE(surface_list[i]);
 
353
        ASSERT(obj_surface);
 
354
 
 
355
        if (obj_surface->vdp_surface != VDP_INVALID_HANDLE) {
 
356
            vdpau_video_surface_destroy(driver_data, obj_surface->vdp_surface);
 
357
            obj_surface->vdp_surface = VDP_INVALID_HANDLE;
 
358
        }
 
359
 
 
360
        for (j = 0; j < obj_surface->output_surfaces_count; j++) {
 
361
            output_surface_unref(driver_data, obj_surface->output_surfaces[j]);
 
362
            obj_surface->output_surfaces[j] = NULL;
 
363
        }
 
364
        free(obj_surface->output_surfaces);
 
365
        obj_surface->output_surfaces_count = 0;
 
366
        obj_surface->output_surfaces_count_max = 0;
 
367
 
 
368
        if (obj_surface->video_mixer) {
 
369
            video_mixer_unref(driver_data, obj_surface->video_mixer);
 
370
            obj_surface->video_mixer = NULL;
 
371
        }
 
372
 
 
373
        if (obj_surface->assocs) {
 
374
            object_subpicture_p obj_subpicture;
 
375
            VAStatus status;
 
376
            const unsigned int n_assocs = obj_surface->assocs_count;
 
377
 
 
378
            for (j = 0, n = 0; j < n_assocs; j++) {
 
379
                SubpictureAssociationP const assoc = obj_surface->assocs[0];
 
380
                if (!assoc)
 
381
                    continue;
 
382
                obj_subpicture = VDPAU_SUBPICTURE(assoc->subpicture);
 
383
                ASSERT(obj_subpicture);
 
384
                if (!obj_subpicture)
 
385
                    continue;
 
386
                status = subpicture_deassociate_1(obj_subpicture, obj_surface);
 
387
                if (status == VA_STATUS_SUCCESS)
 
388
                    ++n;
 
389
            }
 
390
            if (n != n_assocs)
 
391
                vdpau_error_message("vaDestroySurfaces(): surface 0x%08x still "
 
392
                                    "has %d subpictures associated to it\n",
 
393
                                    obj_surface->base.id, n_assocs - n);
 
394
            free(obj_surface->assocs);
 
395
            obj_surface->assocs = NULL;
 
396
        }
 
397
        obj_surface->assocs_count = 0;
 
398
        obj_surface->assocs_count_max = 0;
 
399
 
 
400
        object_heap_free(&driver_data->surface_heap, (object_base_p)obj_surface);
 
401
    }
 
402
    return VA_STATUS_SUCCESS;
 
403
}
 
404
 
 
405
// vaCreateSurfaces
 
406
VAStatus
 
407
vdpau_CreateSurfaces(
 
408
    VADriverContextP    ctx,
 
409
    int                 width,
 
410
    int                 height,
 
411
    int                 format,
 
412
    int                 num_surfaces,
 
413
    VASurfaceID         *surfaces
 
414
)
 
415
{
 
416
    VDPAU_DRIVER_DATA_INIT;
 
417
 
 
418
    VAStatus va_status = VA_STATUS_SUCCESS;
 
419
    VdpVideoSurface vdp_surface = VDP_INVALID_HANDLE;
 
420
    VdpChromaType vdp_chroma_type = get_VdpChromaType(format);
 
421
    VdpStatus vdp_status;
 
422
    int i;
 
423
 
 
424
    /* We only support one format */
 
425
    if (format != VA_RT_FORMAT_YUV420)
 
426
        return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT;
 
427
 
 
428
    for (i = 0; i < num_surfaces; i++) {
 
429
        vdp_status = vdpau_video_surface_create(driver_data,
 
430
                                                driver_data->vdp_device,
 
431
                                                vdp_chroma_type,
 
432
                                                width, height,
 
433
                                                &vdp_surface);
 
434
        if (vdp_status != VDP_STATUS_OK) {
 
435
            va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
 
436
            break;
 
437
        }
 
438
 
 
439
        int va_surface = object_heap_allocate(&driver_data->surface_heap);
 
440
        object_surface_p obj_surface;
 
441
        if ((obj_surface = VDPAU_SURFACE(va_surface)) == NULL) {
 
442
            va_status = VA_STATUS_ERROR_ALLOCATION_FAILED;
 
443
            break;
 
444
        }
 
445
        obj_surface->va_context                 = VA_INVALID_ID;
 
446
        obj_surface->va_surface_status          = VASurfaceReady;
 
447
        obj_surface->vdp_surface                = vdp_surface;
 
448
        obj_surface->width                      = width;
 
449
        obj_surface->height                     = height;
 
450
        obj_surface->assocs                     = NULL;
 
451
        obj_surface->assocs_count               = 0;
 
452
        obj_surface->assocs_count_max           = 0;
 
453
        obj_surface->vdp_chroma_type            = vdp_chroma_type;
 
454
        obj_surface->output_surfaces            = NULL;
 
455
        obj_surface->output_surfaces_count      = 0;
 
456
        obj_surface->output_surfaces_count_max  = 0;
 
457
        obj_surface->video_mixer                = NULL;
 
458
        surfaces[i]                             = va_surface;
 
459
        vdp_surface                             = VDP_INVALID_HANDLE;
 
460
    }
 
461
 
 
462
    /* Error recovery */
 
463
    if (va_status != VA_STATUS_SUCCESS) {
 
464
        if (vdp_surface != VDP_INVALID_HANDLE)
 
465
            vdpau_video_surface_destroy(driver_data, vdp_surface);
 
466
        vdpau_DestroySurfaces(ctx, surfaces, i);
 
467
    }
 
468
 
 
469
    return va_status;
 
470
}
 
471
 
 
472
// vaDestroyContext
 
473
VAStatus vdpau_DestroyContext(VADriverContextP ctx, VAContextID context)
 
474
{
 
475
    VDPAU_DRIVER_DATA_INIT;
 
476
    int i;
 
477
 
 
478
    object_context_p obj_context = VDPAU_CONTEXT(context);
 
479
    ASSERT(obj_context);
 
480
    if (obj_context == NULL)
 
481
        return VA_STATUS_ERROR_INVALID_CONTEXT;
 
482
 
 
483
    if (obj_context->gen_slice_data) {
 
484
        free(obj_context->gen_slice_data);
 
485
        obj_context->gen_slice_data = NULL;
 
486
        obj_context->gen_slice_data_size = 0;
 
487
        obj_context->gen_slice_data_size_max = 0;
 
488
    }
 
489
 
 
490
    if (obj_context->vdp_bitstream_buffers) {
 
491
        free(obj_context->vdp_bitstream_buffers);
 
492
        obj_context->vdp_bitstream_buffers = NULL;
 
493
        obj_context->vdp_bitstream_buffers_count = 0;
 
494
        obj_context->vdp_bitstream_buffers_count_max = 0;
 
495
    }
 
496
 
 
497
    if (obj_context->vdp_video_surfaces) {
 
498
        for (i = 0; i < obj_context->num_render_targets; i++) {
 
499
            VdpVideoSurface surface = obj_context->vdp_video_surfaces[i];
 
500
            if (surface != VDP_INVALID_HANDLE) {
 
501
                vdpau_video_surface_destroy(driver_data, surface);
 
502
                obj_context->vdp_video_surfaces[i] = VDP_INVALID_HANDLE;
 
503
            }
 
504
        }
 
505
        free(obj_context->vdp_video_surfaces);
 
506
        obj_context->vdp_video_surfaces = NULL;
 
507
    }
 
508
 
 
509
    if (obj_context->vdp_decoder != VDP_INVALID_HANDLE) {
 
510
        vdpau_decoder_destroy(driver_data, obj_context->vdp_decoder);
 
511
        obj_context->vdp_decoder = VDP_INVALID_HANDLE;
 
512
    }
 
513
 
 
514
    if (obj_context->dead_buffers) {
 
515
        free(obj_context->dead_buffers);
 
516
        obj_context->dead_buffers = NULL;
 
517
    }
 
518
 
 
519
    if (obj_context->render_targets) {
 
520
        free(obj_context->render_targets);
 
521
        obj_context->render_targets = NULL;
 
522
    }
 
523
 
 
524
    obj_context->context_id             = -1;
 
525
    obj_context->config_id              = -1;
 
526
    obj_context->current_render_target  = VA_INVALID_SURFACE;
 
527
    obj_context->picture_width          = 0;
 
528
    obj_context->picture_height         = 0;
 
529
    obj_context->num_render_targets     = 0;
 
530
    obj_context->flags                  = 0;
 
531
    obj_context->dead_buffers_count     = 0;
 
532
    obj_context->dead_buffers_count_max = 0;
 
533
 
 
534
    object_heap_free(&driver_data->context_heap, (object_base_p)obj_context);
 
535
    return VA_STATUS_SUCCESS;
 
536
}
 
537
 
 
538
// vaCreateContext
 
539
VAStatus
 
540
vdpau_CreateContext(
 
541
    VADriverContextP    ctx,
 
542
    VAConfigID          config_id,
 
543
    int                 picture_width,
 
544
    int                 picture_height,
 
545
    int                 flag,
 
546
    VASurfaceID        *render_targets,
 
547
    int                 num_render_targets,
 
548
    VAContextID        *context
 
549
)
 
550
{
 
551
    VDPAU_DRIVER_DATA_INIT;
 
552
 
 
553
    if (context)
 
554
        *context = VA_INVALID_ID;
 
555
 
 
556
    object_config_p obj_config;
 
557
    if ((obj_config = VDPAU_CONFIG(config_id)) == NULL)
 
558
        return VA_STATUS_ERROR_INVALID_CONFIG;
 
559
 
 
560
    /* XXX: validate flag */
 
561
 
 
562
    VdpDecoderProfile vdp_profile;
 
563
    uint32_t max_width, max_height;
 
564
    int i;
 
565
    vdp_profile = get_VdpDecoderProfile(obj_config->profile);
 
566
    if (!get_max_surface_size(driver_data, vdp_profile, &max_width, &max_height))
 
567
        return VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
 
568
    if (picture_width > max_width || picture_height > max_height)
 
569
        return VA_STATUS_ERROR_RESOLUTION_NOT_SUPPORTED;
 
570
 
 
571
    VAContextID context_id = object_heap_allocate(&driver_data->context_heap);
 
572
    if (context_id == VA_INVALID_ID)
 
573
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
574
 
 
575
    object_context_p obj_context = VDPAU_CONTEXT(context_id);
 
576
    ASSERT(obj_context);
 
577
    if (!obj_context)
 
578
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
579
    if (context)
 
580
        *context = context_id;
 
581
 
 
582
    obj_context->context_id             = context_id;
 
583
    obj_context->config_id              = config_id;
 
584
    obj_context->current_render_target  = VA_INVALID_SURFACE;
 
585
    obj_context->picture_width          = picture_width;
 
586
    obj_context->picture_height         = picture_height;
 
587
    obj_context->num_render_targets     = num_render_targets;
 
588
    obj_context->flags                  = flag;
 
589
    obj_context->max_ref_frames         = -1;
 
590
    obj_context->render_targets         = (VASurfaceID *)
 
591
        calloc(num_render_targets, sizeof(VASurfaceID));
 
592
    obj_context->dead_buffers           = NULL;
 
593
    obj_context->dead_buffers_count     = 0;
 
594
    obj_context->dead_buffers_count_max = 0;
 
595
    obj_context->vdp_codec              = get_VdpCodec(vdp_profile);
 
596
    obj_context->vdp_profile            = vdp_profile;
 
597
    obj_context->vdp_decoder            = VDP_INVALID_HANDLE;
 
598
    obj_context->vdp_video_surfaces     = (VdpVideoSurface *)
 
599
        calloc(num_render_targets, sizeof(VdpVideoSurface));
 
600
    obj_context->gen_slice_data = NULL;
 
601
    obj_context->gen_slice_data_size = 0;
 
602
    obj_context->gen_slice_data_size_max = 0;
 
603
    obj_context->vdp_bitstream_buffers = NULL;
 
604
    obj_context->vdp_bitstream_buffers_count = 0;
 
605
    obj_context->vdp_bitstream_buffers_count_max = 0;
 
606
    obj_context->ref_frames_count       = 0;
 
607
    for (i = 0; i < ARRAY_ELEMS(obj_context->ref_frames); i++)
 
608
        obj_context->ref_frames[i]      = VA_INVALID_SURFACE;
 
609
 
 
610
    if (obj_context->render_targets == NULL || obj_context->vdp_video_surfaces == NULL) {
 
611
        vdpau_DestroyContext(ctx, context_id);
 
612
        return VA_STATUS_ERROR_ALLOCATION_FAILED;
 
613
    }
 
614
 
 
615
    for (i = 0; i < num_render_targets; i++) {
 
616
        object_surface_t *obj_surface;
 
617
        if ((obj_surface = VDPAU_SURFACE(render_targets[i])) == NULL) {
 
618
            vdpau_DestroyContext(ctx, context_id);
 
619
            return VA_STATUS_ERROR_INVALID_SURFACE;
 
620
        }
 
621
        obj_context->render_targets[i] = render_targets[i];
 
622
        obj_context->vdp_video_surfaces[i] = obj_surface->vdp_surface;
 
623
        /* XXX: assume we can only associate a surface to a single context */
 
624
        ASSERT(obj_surface->va_context == VA_INVALID_ID);
 
625
        obj_surface->va_context = context_id;
 
626
    }
 
627
    return VA_STATUS_SUCCESS;
 
628
}
 
629
 
 
630
// Query surface status
 
631
VAStatus
 
632
query_surface_status(
 
633
    vdpau_driver_data_t *driver_data,
 
634
    object_surface_p     obj_surface,
 
635
    VASurfaceStatus     *status
 
636
)
 
637
{
 
638
    VAStatus va_status = VA_STATUS_SUCCESS;
 
639
 
 
640
    if (obj_surface->va_surface_status == VASurfaceDisplaying) {
 
641
        unsigned int i, num_output_surfaces_displaying = 0;
 
642
        for (i = 0; i < obj_surface->output_surfaces_count; i++) {
 
643
            object_output_p obj_output = obj_surface->output_surfaces[i];
 
644
            ASSERT(obj_output);
 
645
            if (!obj_output)
 
646
                return VA_STATUS_ERROR_INVALID_SURFACE;
 
647
 
 
648
            VdpOutputSurface vdp_output_surface;
 
649
            vdp_output_surface = obj_output->vdp_output_surfaces[(obj_output->current_output_surface + VDPAU_MAX_OUTPUT_SURFACES - 1) % VDPAU_MAX_OUTPUT_SURFACES];
 
650
            if (vdp_output_surface == VDP_INVALID_HANDLE)
 
651
                continue;
 
652
 
 
653
            VdpPresentationQueueStatus vdp_queue_status;
 
654
            VdpTime vdp_dummy_time;
 
655
            VdpStatus vdp_status;
 
656
            vdp_status = vdpau_presentation_queue_query_surface_status(
 
657
                driver_data,
 
658
                obj_output->vdp_flip_queue,
 
659
                vdp_output_surface,
 
660
                &vdp_queue_status,
 
661
                &vdp_dummy_time
 
662
            );
 
663
            va_status = vdpau_get_VAStatus(driver_data, vdp_status);
 
664
 
 
665
            if (vdp_queue_status != VDP_PRESENTATION_QUEUE_STATUS_VISIBLE)
 
666
                ++num_output_surfaces_displaying;
 
667
        }
 
668
 
 
669
        if (num_output_surfaces_displaying == 0)
 
670
            obj_surface->va_surface_status = VASurfaceReady;
 
671
    }
 
672
 
 
673
    if (status)
 
674
        *status = obj_surface->va_surface_status;
 
675
 
 
676
    return va_status;
 
677
}
 
678
 
 
679
// vaQuerySurfaceStatus
 
680
VAStatus
 
681
vdpau_QuerySurfaceStatus(
 
682
    VADriverContextP    ctx,
 
683
    VASurfaceID         render_target,
 
684
    VASurfaceStatus    *status
 
685
)
 
686
{
 
687
    VDPAU_DRIVER_DATA_INIT;
 
688
 
 
689
    object_surface_p obj_surface = VDPAU_SURFACE(render_target);
 
690
    ASSERT(obj_surface);
 
691
    if (obj_surface == NULL)
 
692
        return VA_STATUS_ERROR_INVALID_SURFACE;
 
693
 
 
694
    return query_surface_status(driver_data, obj_surface, status);
 
695
}
 
696
 
 
697
// Wait for the surface to complete pending operations
 
698
VAStatus
 
699
sync_surface(
 
700
    vdpau_driver_data_t *driver_data,
 
701
    object_surface_p     obj_surface
 
702
)
 
703
{
 
704
    /* VDPAU only supports status interface for in-progress display */
 
705
    /* XXX: polling is bad but there currently is no alternative */
 
706
    for (;;) {
 
707
        VASurfaceStatus va_surface_status;
 
708
        VAStatus va_status = query_surface_status(driver_data,
 
709
                                                  obj_surface,
 
710
                                                  &va_surface_status);
 
711
 
 
712
        if (va_status != VA_STATUS_SUCCESS)
 
713
            return va_status;
 
714
 
 
715
        if (va_surface_status != VASurfaceDisplaying)
 
716
            break;
 
717
        delay_usec(VDPAU_SYNC_DELAY);
 
718
    }
 
719
    return VA_STATUS_SUCCESS;
 
720
}
 
721
 
 
722
// vaSyncSurface
 
723
VAStatus
 
724
vdpau_SyncSurface2(
 
725
    VADriverContextP    ctx,
 
726
    VASurfaceID         render_target
 
727
)
 
728
{
 
729
    VDPAU_DRIVER_DATA_INIT;
 
730
 
 
731
    object_surface_p obj_surface = VDPAU_SURFACE(render_target);
 
732
    ASSERT(obj_surface);
 
733
    if (!obj_surface)
 
734
        return VA_STATUS_ERROR_INVALID_SURFACE;
 
735
 
 
736
    /* Assume that this shouldn't be called before vaEndPicture() */
 
737
    object_context_p obj_context = VDPAU_CONTEXT(obj_surface->va_context);
 
738
    if (obj_context) {
 
739
        ASSERT(obj_context->current_render_target != obj_surface->base.id);
 
740
        if (obj_context->current_render_target == obj_surface->base.id)
 
741
            return VA_STATUS_ERROR_INVALID_CONTEXT;
 
742
    }
 
743
 
 
744
    return sync_surface(driver_data, obj_surface);
 
745
}
 
746
 
 
747
VAStatus
 
748
vdpau_SyncSurface3(
 
749
    VADriverContextP    ctx,
 
750
    VAContextID         context,
 
751
    VASurfaceID         render_target
 
752
)
 
753
{
 
754
    VDPAU_DRIVER_DATA_INIT;
 
755
 
 
756
    object_surface_p obj_surface = VDPAU_SURFACE(render_target);
 
757
    ASSERT(obj_surface);
 
758
    if (!obj_surface)
 
759
        return VA_STATUS_ERROR_INVALID_SURFACE;
 
760
 
 
761
    /* Assume that this shouldn't be called before vaEndPicture() */
 
762
    object_context_p obj_context = VDPAU_CONTEXT(context);
 
763
    if (obj_context) {
 
764
        ASSERT(obj_context->current_render_target != obj_surface->base.id);
 
765
        if (obj_context->current_render_target == obj_surface->base.id)
 
766
            return VA_STATUS_ERROR_INVALID_CONTEXT;
 
767
    }
 
768
 
 
769
    return sync_surface(driver_data, obj_surface);
 
770
}
 
771
 
 
772
// Ensure VA Display Attributes are initialized
 
773
static int ensure_display_attributes(vdpau_driver_data_t *driver_data)
 
774
{
 
775
    VADisplayAttribute *attr;
 
776
 
 
777
    if (driver_data->va_display_attrs_count > 0)
 
778
        return 0;
 
779
 
 
780
    memset(driver_data->va_display_attrs_mtime, 0, sizeof(driver_data->va_display_attrs_mtime));
 
781
 
 
782
    attr = &driver_data->va_display_attrs[0];
 
783
 
 
784
    attr->type      = VADisplayAttribDirectSurface;
 
785
    attr->value     = 0; /* VdpVideoSurface is copied into VdpOutputSurface */
 
786
    attr->min_value = attr->value;
 
787
    attr->max_value = attr->value;
 
788
    attr->flags     = VA_DISPLAY_ATTRIB_GETTABLE;
 
789
    attr++;
 
790
 
 
791
    attr->type      = VADisplayAttribBrightness;
 
792
    attr->value     = 0;
 
793
    attr->min_value = -100;
 
794
    attr->max_value = 100;
 
795
    attr->flags     = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
 
796
    attr++;
 
797
 
 
798
    attr->type      = VADisplayAttribContrast;
 
799
    attr->value     = 0;
 
800
    attr->min_value = -100;
 
801
    attr->max_value = 100;
 
802
    attr->flags     = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
 
803
    attr++;
 
804
 
 
805
    attr->type      = VADisplayAttribHue;
 
806
    attr->value     = 0;
 
807
    attr->min_value = -100;
 
808
    attr->max_value = 100;
 
809
    attr->flags     = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
 
810
    attr++;
 
811
 
 
812
    attr->type      = VADisplayAttribSaturation;
 
813
    attr->value     = 0;
 
814
    attr->min_value = -100;
 
815
    attr->max_value = 100;
 
816
    attr->flags     = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
 
817
    attr++;
 
818
 
 
819
    attr->type      = VADisplayAttribBackgroundColor;
 
820
    attr->value     = 0;
 
821
    attr->min_value = 0;
 
822
    attr->max_value = 0xffffff;
 
823
    attr->flags     = VA_DISPLAY_ATTRIB_GETTABLE|VA_DISPLAY_ATTRIB_SETTABLE;
 
824
    attr++;
 
825
 
 
826
    driver_data->va_display_attrs_count = attr - driver_data->va_display_attrs;
 
827
    ASSERT(driver_data->va_display_attrs_count <= VDPAU_MAX_DISPLAY_ATTRIBUTES);
 
828
    return 0;
 
829
}
 
830
 
 
831
// Look up for the specified VA display attribute
 
832
static VADisplayAttribute *
 
833
get_display_attribute(
 
834
    vdpau_driver_data_t *driver_data,
 
835
    VADisplayAttribType  type
 
836
)
 
837
{
 
838
    if (ensure_display_attributes(driver_data) < 0)
 
839
        return NULL;
 
840
 
 
841
    unsigned int i;
 
842
    for (i = 0; i < driver_data->va_display_attrs_count; i++) {
 
843
        if (driver_data->va_display_attrs[i].type == type)
 
844
            return &driver_data->va_display_attrs[i];
 
845
    }
 
846
    return NULL;
 
847
}
 
848
 
 
849
// vaQueryDisplayAttributes
 
850
VAStatus
 
851
vdpau_QueryDisplayAttributes(
 
852
    VADriverContextP    ctx,
 
853
    VADisplayAttribute *attr_list,
 
854
    int                *num_attributes
 
855
)
 
856
{
 
857
    VDPAU_DRIVER_DATA_INIT;
 
858
 
 
859
    if (ensure_display_attributes(driver_data) < 0)
 
860
        return VA_STATUS_ERROR_OPERATION_FAILED;
 
861
 
 
862
    if (attr_list)
 
863
        memcpy(attr_list, driver_data->va_display_attrs,
 
864
               driver_data->va_display_attrs_count * sizeof(attr_list[0]));
 
865
 
 
866
    if (num_attributes)
 
867
        *num_attributes = driver_data->va_display_attrs_count;
 
868
 
 
869
    return VA_STATUS_SUCCESS;
 
870
}
 
871
 
 
872
// vaGetDisplayAttributes
 
873
VAStatus
 
874
vdpau_GetDisplayAttributes(
 
875
    VADriverContextP    ctx,
 
876
    VADisplayAttribute *attr_list,
 
877
    int                 num_attributes
 
878
)
 
879
{
 
880
    VDPAU_DRIVER_DATA_INIT;
 
881
 
 
882
    unsigned int i;
 
883
    for (i = 0; i < num_attributes; i++) {
 
884
        VADisplayAttribute * const dst_attr = &attr_list[i];
 
885
        VADisplayAttribute *src_attr;
 
886
 
 
887
        src_attr = get_display_attribute(driver_data, dst_attr->type);
 
888
        if (src_attr && (src_attr->flags & VA_DISPLAY_ATTRIB_GETTABLE) != 0) {
 
889
            dst_attr->min_value = src_attr->min_value;
 
890
            dst_attr->max_value = src_attr->max_value;
 
891
            dst_attr->value     = src_attr->value;
 
892
        }
 
893
        else
 
894
            dst_attr->flags    &= ~VA_DISPLAY_ATTRIB_GETTABLE;
 
895
    }
 
896
    return VA_STATUS_SUCCESS;
 
897
}
 
898
 
 
899
// vaSetDisplayAttributes
 
900
VAStatus
 
901
vdpau_SetDisplayAttributes(
 
902
    VADriverContextP    ctx,
 
903
    VADisplayAttribute *attr_list,
 
904
    int                 num_attributes
 
905
)
 
906
{
 
907
    VDPAU_DRIVER_DATA_INIT;
 
908
 
 
909
    unsigned int i;
 
910
    for (i = 0; i < num_attributes; i++) {
 
911
        VADisplayAttribute * const src_attr = &attr_list[i];
 
912
        VADisplayAttribute *dst_attr;
 
913
 
 
914
        dst_attr = get_display_attribute(driver_data, src_attr->type);
 
915
        if (!dst_attr)
 
916
            return VA_STATUS_ERROR_ATTR_NOT_SUPPORTED;
 
917
 
 
918
        if ((dst_attr->flags & VA_DISPLAY_ATTRIB_SETTABLE) != 0) {
 
919
            dst_attr->value = src_attr->value;
 
920
 
 
921
            static uint64_t mtime;
 
922
            const int display_attr_index = dst_attr - driver_data->va_display_attrs;
 
923
            ASSERT(display_attr_index < VDPAU_MAX_DISPLAY_ATTRIBUTES);
 
924
            driver_data->va_display_attrs_mtime[display_attr_index] = ++mtime;
 
925
        }
 
926
    }
 
927
    return VA_STATUS_SUCCESS;
 
928
}
 
929
 
 
930
// vaDbgCopySurfaceToBuffer (not a PUBLIC interface)
 
931
VAStatus
 
932
vdpau_DbgCopySurfaceToBuffer(
 
933
    VADriverContextP    ctx,
 
934
    VASurfaceID         surface,
 
935
    void              **buffer,
 
936
    unsigned int       *stride
 
937
)
 
938
{
 
939
    /* TODO */
 
940
    return VA_STATUS_ERROR_UNKNOWN;
 
941
}
 
942
 
 
943
#if VA_CHECK_VERSION(0,30,0)
 
944
// vaCreateSurfaceFromCIFrame
 
945
VAStatus
 
946
vdpau_CreateSurfaceFromCIFrame(
 
947
    VADriverContextP    ctx,
 
948
    unsigned long       frame_id,
 
949
    VASurfaceID        *surface
 
950
)
 
951
{
 
952
    /* TODO */
 
953
    return VA_STATUS_ERROR_UNKNOWN;
 
954
}
 
955
 
 
956
// vaCreateSurfaceFromV4L2Buf
 
957
VAStatus
 
958
vdpau_CreateSurfaceFromV4L2Buf(
 
959
    VADriverContextP    ctx,
 
960
    int                 v4l2_fd,
 
961
    struct v4l2_format *v4l2_fmt,
 
962
    struct v4l2_buffer *v4l2_buf,
 
963
    VASurfaceID        *surface
 
964
)
 
965
{
 
966
    /* TODO */
 
967
    return VA_STATUS_ERROR_UNKNOWN;
 
968
}
 
969
 
 
970
// vaCopySurfaceToBuffer
 
971
VAStatus
 
972
vdpau_CopySurfaceToBuffer(
 
973
    VADriverContextP    ctx,
 
974
    VASurfaceID         surface,
 
975
    unsigned int       *fourcc,
 
976
    unsigned int       *luma_stride,
 
977
    unsigned int       *chroma_u_stride,
 
978
    unsigned int       *chroma_v_stride,
 
979
    unsigned int       *luma_offset,
 
980
    unsigned int       *chroma_u_offset,
 
981
    unsigned int       *chroma_v_offset,
 
982
    void              **buffer
 
983
)
 
984
{
 
985
    /* TODO */
 
986
    return VA_STATUS_ERROR_UNKNOWN;
 
987
}
 
988
#endif