Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5361 serge 1
/*
2
 * Copyright © 2010 Intel Corporation
3
 *
4
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 * copy of this software and associated documentation files (the
6
 * "Software"), to deal in the Software without restriction, including
7
 * without limitation the rights to use, copy, modify, merge, publish,
8
 * distribute, sub license, and/or sell copies of the Software, and to
9
 * permit persons to whom the Software is furnished to do so, subject to
10
 * the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the
13
 * next paragraph) shall be included in all copies or substantial portions
14
 * of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
19
 * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
20
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors:
25
 *    Zhou Chang 
26
 *
27
 */
28
 
29
#include 
30
#include 
31
#include 
32
#include 
33
 
34
#include "intel_batchbuffer.h"
35
#include "intel_driver.h"
36
 
37
#include "i965_defines.h"
38
#include "i965_drv_video.h"
39
#include "i965_encoder.h"
40
#include "gen6_vme.h"
41
#include "gen6_mfc.h"
42
 
43
extern Bool gen6_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
44
extern Bool gen6_vme_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
45
extern Bool gen7_mfc_context_init(VADriverContextP ctx, struct intel_encoder_context *encoder_context);
46
 
47
static VAStatus
48
intel_encoder_check_yuv_surface(VADriverContextP ctx,
49
                                VAProfile profile,
50
                                struct encode_state *encode_state,
51
                                struct intel_encoder_context *encoder_context)
52
{
53
    struct i965_driver_data *i965 = i965_driver_data(ctx);
54
    struct i965_surface src_surface, dst_surface;
55
    struct object_surface *obj_surface;
56
    VAStatus status;
57
    VARectangle rect;
58
 
59
    /* releae the temporary surface */
60
    if (encoder_context->is_tmp_id) {
61
        i965_DestroySurfaces(ctx, &encoder_context->input_yuv_surface, 1);
62
        encode_state->input_yuv_object = NULL;
63
    }
64
 
65
    encoder_context->is_tmp_id = 0;
66
    obj_surface = SURFACE(encode_state->current_render_target);
67
    assert(obj_surface && obj_surface->bo);
68
 
69
    if (!obj_surface || !obj_surface->bo)
70
        return VA_STATUS_ERROR_INVALID_PARAMETER;
71
 
72
    if (obj_surface->fourcc == VA_FOURCC_NV12) {
73
        unsigned int tiling = 0, swizzle = 0;
74
 
75
        dri_bo_get_tiling(obj_surface->bo, &tiling, &swizzle);
76
 
77
        if (tiling == I915_TILING_Y) {
78
            encoder_context->input_yuv_surface = encode_state->current_render_target;
79
            encode_state->input_yuv_object = obj_surface;
80
            return VA_STATUS_SUCCESS;
81
        }
82
    }
83
 
84
    rect.x = 0;
85
    rect.y = 0;
86
    rect.width = obj_surface->orig_width;
87
    rect.height = obj_surface->orig_height;
88
 
89
    src_surface.base = (struct object_base *)obj_surface;
90
    src_surface.type = I965_SURFACE_TYPE_SURFACE;
91
    src_surface.flags = I965_SURFACE_FLAG_FRAME;
92
 
93
    status = i965_CreateSurfaces(ctx,
94
                                 obj_surface->orig_width,
95
                                 obj_surface->orig_height,
96
                                 VA_RT_FORMAT_YUV420,
97
                                 1,
98
                                 &encoder_context->input_yuv_surface);
99
    assert(status == VA_STATUS_SUCCESS);
100
 
101
    if (status != VA_STATUS_SUCCESS)
102
        return status;
103
 
104
    obj_surface = SURFACE(encoder_context->input_yuv_surface);
105
    encode_state->input_yuv_object = obj_surface;
106
    assert(obj_surface);
107
    i965_check_alloc_surface_bo(ctx, obj_surface, 1, VA_FOURCC_NV12, SUBSAMPLE_YUV420);
108
 
109
    dst_surface.base = (struct object_base *)obj_surface;
110
    dst_surface.type = I965_SURFACE_TYPE_SURFACE;
111
    dst_surface.flags = I965_SURFACE_FLAG_FRAME;
112
 
113
    status = i965_image_processing(ctx,
114
                                   &src_surface,
115
                                   &rect,
116
                                   &dst_surface,
117
                                   &rect);
118
    assert(status == VA_STATUS_SUCCESS);
119
 
120
    encoder_context->is_tmp_id = 1;
121
 
122
    return VA_STATUS_SUCCESS;
123
}
124
 
125
static VAStatus
126
intel_encoder_check_misc_parameter(VADriverContextP ctx,
127
                                  struct encode_state *encode_state,
128
                                  struct intel_encoder_context *encoder_context)
129
{
130
 
131
    if (encode_state->misc_param[VAEncMiscParameterTypeQualityLevel] &&
132
        encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer) {
133
        VAEncMiscParameterBuffer* pMiscParam = (VAEncMiscParameterBuffer*)encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer;
134
        VAEncMiscParameterBufferQualityLevel* param_quality_level = (VAEncMiscParameterBufferQualityLevel*)pMiscParam->data;
135
        encoder_context->quality_level = param_quality_level->quality_level;
136
 
137
        if (encoder_context->quality_level == 0)
138
            encoder_context->quality_level = ENCODER_DEFAULT_QUALITY;
139
        else if (encoder_context->quality_level > encoder_context->quality_range)
140
            goto error;
141
   }
142
 
143
    return VA_STATUS_SUCCESS;
144
 
145
error:
146
    return VA_STATUS_ERROR_INVALID_PARAMETER;
147
}
148
 
149
static VAStatus
150
intel_encoder_check_avc_parameter(VADriverContextP ctx,
151
                                  struct encode_state *encode_state,
152
                                  struct intel_encoder_context *encoder_context)
153
{
154
    struct i965_driver_data *i965 = i965_driver_data(ctx);
155
    struct object_surface *obj_surface;
156
    struct object_buffer *obj_buffer;
157
    VAEncPictureParameterBufferH264 *pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
158
    int i;
159
 
160
    assert(!(pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID));
161
 
162
    if (pic_param->CurrPic.flags & VA_PICTURE_H264_INVALID)
163
        goto error;
164
 
165
    obj_surface = SURFACE(pic_param->CurrPic.picture_id);
166
    assert(obj_surface); /* It is possible the store buffer isn't allocated yet */
167
 
168
    if (!obj_surface)
169
        goto error;
170
 
171
    encode_state->reconstructed_object = obj_surface;
172
    obj_buffer = BUFFER(pic_param->coded_buf);
173
    assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo);
174
 
175
    if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
176
        goto error;
177
 
178
    encode_state->coded_buf_object = obj_buffer;
179
 
180
    for (i = 0; i < 16; i++) {
181
        if (pic_param->ReferenceFrames[i].flags & VA_PICTURE_H264_INVALID ||
182
            pic_param->ReferenceFrames[i].picture_id == VA_INVALID_SURFACE)
183
            break;
184
        else {
185
            obj_surface = SURFACE(pic_param->ReferenceFrames[i].picture_id);
186
            assert(obj_surface);
187
 
188
            if (!obj_surface)
189
                goto error;
190
 
191
            if (obj_surface->bo)
192
                encode_state->reference_objects[i] = obj_surface;
193
            else
194
                encode_state->reference_objects[i] = NULL; /* FIXME: Warning or Error ??? */
195
        }
196
    }
197
 
198
    for ( ; i < 16; i++)
199
        encode_state->reference_objects[i] = NULL;
200
 
201
    return VA_STATUS_SUCCESS;
202
 
203
error:
204
    return VA_STATUS_ERROR_INVALID_PARAMETER;
205
}
206
 
207
static VAStatus
208
intel_encoder_check_mpeg2_parameter(VADriverContextP ctx,
209
                                    struct encode_state *encode_state,
210
                                    struct intel_encoder_context *encoder_context)
211
{
212
    struct i965_driver_data *i965 = i965_driver_data(ctx);
213
    VAEncPictureParameterBufferMPEG2 *pic_param = (VAEncPictureParameterBufferMPEG2 *)encode_state->pic_param_ext->buffer;
214
    struct object_surface *obj_surface;
215
    struct object_buffer *obj_buffer;
216
    int i = 0;
217
 
218
    obj_surface = SURFACE(pic_param->reconstructed_picture);
219
    assert(obj_surface); /* It is possible the store buffer isn't allocated yet */
220
 
221
    if (!obj_surface)
222
        goto error;
223
 
224
    encode_state->reconstructed_object = obj_surface;
225
    obj_buffer = BUFFER(pic_param->coded_buf);
226
    assert(obj_buffer && obj_buffer->buffer_store && obj_buffer->buffer_store->bo);
227
 
228
    if (!obj_buffer || !obj_buffer->buffer_store || !obj_buffer->buffer_store->bo)
229
        goto error;
230
 
231
    encode_state->coded_buf_object = obj_buffer;
232
 
233
    if (pic_param->picture_type == VAEncPictureTypeIntra) {
234
    } else if (pic_param->picture_type == VAEncPictureTypePredictive) {
235
        assert(pic_param->forward_reference_picture != VA_INVALID_SURFACE);
236
        obj_surface = SURFACE(pic_param->forward_reference_picture);
237
        assert(obj_surface && obj_surface->bo);
238
 
239
        if (!obj_surface || !obj_surface->bo)
240
            goto error;
241
 
242
        encode_state->reference_objects[i++] = obj_surface;
243
    } else if (pic_param->picture_type == VAEncPictureTypeBidirectional) {
244
        assert(pic_param->forward_reference_picture != VA_INVALID_SURFACE);
245
        obj_surface = SURFACE(pic_param->forward_reference_picture);
246
        assert(obj_surface && obj_surface->bo);
247
 
248
        if (!obj_surface || !obj_surface->bo)
249
            goto error;
250
 
251
        encode_state->reference_objects[i++] = obj_surface;
252
 
253
        assert(pic_param->backward_reference_picture != VA_INVALID_SURFACE);
254
        obj_surface = SURFACE(pic_param->backward_reference_picture);
255
        assert(obj_surface && obj_surface->bo);
256
 
257
        if (!obj_surface || !obj_surface->bo)
258
            goto error;
259
 
260
        encode_state->reference_objects[i++] = obj_surface;
261
    } else
262
        goto error;
263
 
264
    for ( ; i < 16; i++)
265
        encode_state->reference_objects[i] = NULL;
266
 
267
    return VA_STATUS_SUCCESS;
268
 
269
error:
270
    return VA_STATUS_ERROR_INVALID_PARAMETER;
271
}
272
 
273
static VAStatus
274
intel_encoder_sanity_check_input(VADriverContextP ctx,
275
                                 VAProfile profile,
276
                                 struct encode_state *encode_state,
277
                                 struct intel_encoder_context *encoder_context)
278
{
279
    VAStatus vaStatus;
280
 
281
    switch (profile) {
282
    case VAProfileH264ConstrainedBaseline:
283
    case VAProfileH264Main:
284
    case VAProfileH264High:
285
    case VAProfileH264MultiviewHigh:
286
    case VAProfileH264StereoHigh:
287
        vaStatus = intel_encoder_check_avc_parameter(ctx, encode_state, encoder_context);
288
        break;
289
 
290
    case VAProfileMPEG2Simple:
291
    case VAProfileMPEG2Main:
292
        vaStatus = intel_encoder_check_mpeg2_parameter(ctx, encode_state, encoder_context);
293
        break;
294
 
295
    default:
296
        vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE;
297
        break;
298
    }
299
 
300
    if (vaStatus != VA_STATUS_SUCCESS)
301
        goto out;
302
 
303
    vaStatus = intel_encoder_check_yuv_surface(ctx, profile, encode_state, encoder_context);
304
 
305
    if (vaStatus == VA_STATUS_SUCCESS)
306
        vaStatus = intel_encoder_check_misc_parameter(ctx, encode_state, encoder_context);
307
 
308
out:
309
    return vaStatus;
310
}
311
 
312
static VAStatus
313
intel_encoder_end_picture(VADriverContextP ctx,
314
                          VAProfile profile,
315
                          union codec_state *codec_state,
316
                          struct hw_context *hw_context)
317
{
318
    struct intel_encoder_context *encoder_context = (struct intel_encoder_context *)hw_context;
319
    struct encode_state *encode_state = &codec_state->encode;
320
    VAStatus vaStatus;
321
 
322
    vaStatus = intel_encoder_sanity_check_input(ctx, profile, encode_state, encoder_context);
323
 
324
    if (vaStatus != VA_STATUS_SUCCESS)
325
        return vaStatus;
326
 
327
    encoder_context->mfc_brc_prepare(encode_state, encoder_context);
328
 
329
    vaStatus = encoder_context->vme_pipeline(ctx, profile, encode_state, encoder_context);
330
 
331
    if (vaStatus == VA_STATUS_SUCCESS)
332
        encoder_context->mfc_pipeline(ctx, profile, encode_state, encoder_context);
333
    return VA_STATUS_SUCCESS;
334
}
335
 
336
static void
337
intel_encoder_context_destroy(void *hw_context)
338
{
339
    struct intel_encoder_context *encoder_context = (struct intel_encoder_context *)hw_context;
340
 
341
    encoder_context->mfc_context_destroy(encoder_context->mfc_context);
342
    encoder_context->vme_context_destroy(encoder_context->vme_context);
343
    intel_batchbuffer_free(encoder_context->base.batch);
344
    free(encoder_context);
345
}
346
 
347
typedef Bool (* hw_init_func)(VADriverContextP, struct intel_encoder_context *);
348
 
349
static struct hw_context *
350
intel_enc_hw_context_init(VADriverContextP ctx,
351
                          struct object_config *obj_config,
352
                          hw_init_func vme_context_init,
353
                          hw_init_func mfc_context_init)
354
{
355
    struct intel_driver_data *intel = intel_driver_data(ctx);
356
    struct intel_encoder_context *encoder_context = calloc(1, sizeof(struct intel_encoder_context));
357
    int i;
358
 
359
    encoder_context->base.destroy = intel_encoder_context_destroy;
360
    encoder_context->base.run = intel_encoder_end_picture;
361
    encoder_context->base.batch = intel_batchbuffer_new(intel, I915_EXEC_RENDER, 0);
362
    encoder_context->input_yuv_surface = VA_INVALID_SURFACE;
363
    encoder_context->is_tmp_id = 0;
364
    encoder_context->rate_control_mode = VA_RC_NONE;
365
    encoder_context->quality_level = ENCODER_DEFAULT_QUALITY;
366
    encoder_context->quality_range = 1;
367
 
368
    switch (obj_config->profile) {
369
    case VAProfileMPEG2Simple:
370
    case VAProfileMPEG2Main:
371
        encoder_context->codec = CODEC_MPEG2;
372
        break;
373
 
374
    case VAProfileH264ConstrainedBaseline:
375
    case VAProfileH264Main:
376
    case VAProfileH264High:
377
        encoder_context->codec = CODEC_H264;
378
        encoder_context->quality_range = ENCODER_QUALITY_RANGE;
379
        break;
380
 
381
    case VAProfileH264StereoHigh:
382
    case VAProfileH264MultiviewHigh:
383
        encoder_context->codec = CODEC_H264_MVC;
384
        break;
385
 
386
    default:
387
        /* Never get here */
388
        assert(0);
389
        break;
390
    }
391
 
392
    for (i = 0; i < obj_config->num_attribs; i++) {
393
        if (obj_config->attrib_list[i].type == VAConfigAttribRateControl) {
394
            encoder_context->rate_control_mode = obj_config->attrib_list[i].value;
395
 
396
            if (encoder_context->codec == CODEC_MPEG2 &&
397
                encoder_context->rate_control_mode & VA_RC_CBR) {
398
                WARN_ONCE("Don't support CBR for MPEG-2 encoding\n");
399
                encoder_context->rate_control_mode &= ~VA_RC_CBR;
400
            }
401
 
402
            break;
403
        }
404
    }
405
 
406
    vme_context_init(ctx, encoder_context);
407
    assert(encoder_context->vme_context);
408
    assert(encoder_context->vme_context_destroy);
409
    assert(encoder_context->vme_pipeline);
410
 
411
    mfc_context_init(ctx, encoder_context);
412
    assert(encoder_context->mfc_context);
413
    assert(encoder_context->mfc_context_destroy);
414
    assert(encoder_context->mfc_pipeline);
415
 
416
    return (struct hw_context *)encoder_context;
417
}
418
 
419
struct hw_context *
420
gen6_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
421
{
422
    return intel_enc_hw_context_init(ctx, obj_config, gen6_vme_context_init, gen6_mfc_context_init);
423
}
424
 
425
struct hw_context *
426
gen7_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
427
{
428
 
429
    return intel_enc_hw_context_init(ctx, obj_config, gen7_vme_context_init, gen7_mfc_context_init);
430
}
431
 
432
struct hw_context *
433
gen75_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
434
{
435
    return intel_enc_hw_context_init(ctx, obj_config, gen75_vme_context_init, gen75_mfc_context_init);
436
}
437
 
438
struct hw_context *
439
gen8_enc_hw_context_init(VADriverContextP ctx, struct object_config *obj_config)
440
{
441
    return intel_enc_hw_context_init(ctx, obj_config, gen8_vme_context_init, gen8_mfc_context_init);
442
}
443