Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3769 Serge 1
/*
2
 * Copyright (C) 2006-2012 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 "Software"),
6
 * to deal in the Software without restriction, including without limitation
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 * and/or sell copies of the Software, and to permit persons to whom the
9
 * Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice (including the next
12
 * paragraph) shall be included in all copies or substantial portions of the
13
 * Software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 */
23
 
24
#include "sysdeps.h"
25
#include 
26
#include "intel_batchbuffer.h"
27
#include "i965_decoder_utils.h"
28
#include "i965_drv_video.h"
29
#include "i965_defines.h"
30
 
31
/* Set reference surface if backing store exists */
32
static inline int
33
set_ref_frame(
34
    struct i965_driver_data *i965,
35
    GenFrameStore           *ref_frame,
36
    VASurfaceID              va_surface
37
)
38
{
39
    struct object_surface *obj_surface;
40
 
41
    if (va_surface == VA_INVALID_ID)
42
        return 0;
43
 
44
    obj_surface = SURFACE(va_surface);
45
    if (!obj_surface || !obj_surface->bo)
46
        return 0;
47
 
48
    ref_frame->surface_id = va_surface;
49
    return 1;
50
}
51
 
52
/* Check wether codec layer incorrectly fills in slice_vertical_position */
53
int
54
mpeg2_wa_slice_vertical_position(
55
    struct decode_state           *decode_state,
56
    VAPictureParameterBufferMPEG2 *pic_param
57
)
58
{
59
    unsigned int i, j, mb_height, vpos, last_vpos = 0;
60
 
61
    /* Assume progressive sequence if we got a progressive frame */
62
    if (pic_param->picture_coding_extension.bits.progressive_frame)
63
        return 0;
64
 
65
    /* Wait for a field coded picture */
66
    if (pic_param->picture_coding_extension.bits.picture_structure == MPEG_FRAME)
67
        return -1;
68
 
69
    assert(decode_state && decode_state->slice_params);
70
 
71
    mb_height = (pic_param->vertical_size + 31) / 32;
72
 
73
    for (j = 0; j < decode_state->num_slice_params; j++) {
74
        struct buffer_store * const buffer_store =
75
            decode_state->slice_params[j];
76
 
77
        for (i = 0; i < buffer_store->num_elements; i++) {
78
            VASliceParameterBufferMPEG2 * const slice_param =
79
                ((VASliceParameterBufferMPEG2 *)buffer_store->buffer) + i;
80
 
81
            vpos = slice_param->slice_vertical_position;
82
            if (vpos >= mb_height || vpos == last_vpos + 2) {
83
                WARN_ONCE("codec layer incorrectly fills in MPEG-2 slice_vertical_position. Workaround applied\n");
84
                return 1;
85
            }
86
            last_vpos = vpos;
87
        }
88
    }
89
    return 0;
90
}
91
 
92
/* Build MPEG-2 reference frames array */
93
void
94
mpeg2_set_reference_surfaces(
95
    VADriverContextP               ctx,
96
    GenFrameStore                  ref_frames[MAX_GEN_REFERENCE_FRAMES],
97
    struct decode_state           *decode_state,
98
    VAPictureParameterBufferMPEG2 *pic_param
99
)
100
{
101
    struct i965_driver_data * const i965 = i965_driver_data(ctx);
102
    VASurfaceID va_surface;
103
    unsigned pic_structure, is_second_field, n = 0;
104
 
105
    pic_structure = pic_param->picture_coding_extension.bits.picture_structure;
106
    is_second_field = pic_structure != MPEG_FRAME &&
107
        !pic_param->picture_coding_extension.bits.is_first_field;
108
 
109
    ref_frames[0].surface_id = VA_INVALID_ID;
110
 
111
    /* Reference frames are indexed by frame store ID  (0:top, 1:bottom) */
112
    switch (pic_param->picture_coding_type) {
113
    case MPEG_P_PICTURE:
114
        if (is_second_field && pic_structure == MPEG_BOTTOM_FIELD) {
115
            va_surface = decode_state->current_render_target;
116
            n += set_ref_frame(i965, &ref_frames[n], va_surface);
117
        }
118
        va_surface = pic_param->forward_reference_picture;
119
        n += set_ref_frame(i965, &ref_frames[n], va_surface);
120
        break;
121
 
122
    case MPEG_B_PICTURE:
123
        va_surface = pic_param->forward_reference_picture;
124
        n += set_ref_frame(i965, &ref_frames[n], va_surface);
125
        va_surface = pic_param->backward_reference_picture;
126
        n += set_ref_frame(i965, &ref_frames[n], va_surface);
127
        break;
128
    }
129
 
130
    while (n != 2)
131
        ref_frames[n++].surface_id = ref_frames[0].surface_id;
132
 
133
    if (pic_param->picture_coding_extension.bits.progressive_frame)
134
        return;
135
 
136
    ref_frames[2].surface_id = VA_INVALID_ID;
137
 
138
    /* Bottom field pictures used as reference */
139
    switch (pic_param->picture_coding_type) {
140
    case MPEG_P_PICTURE:
141
        if (is_second_field && pic_structure == MPEG_TOP_FIELD) {
142
            va_surface = decode_state->current_render_target;
143
            n += set_ref_frame(i965, &ref_frames[n], va_surface);
144
        }
145
        va_surface = pic_param->forward_reference_picture;
146
        n += set_ref_frame(i965, &ref_frames[n], va_surface);
147
        break;
148
 
149
    case MPEG_B_PICTURE:
150
        va_surface = pic_param->forward_reference_picture;
151
        n += set_ref_frame(i965, &ref_frames[n], va_surface);
152
        va_surface = pic_param->backward_reference_picture;
153
        n += set_ref_frame(i965, &ref_frames[n], va_surface);
154
        break;
155
    }
156
 
157
    while (n != 4)
158
        ref_frames[n++].surface_id = ref_frames[2].surface_id;
159
}
160
 
161
/* Generate flat scaling matrices for H.264 decoding */
162
void
163
avc_gen_default_iq_matrix(VAIQMatrixBufferH264 *iq_matrix)
164
{
165
    /* Flat_4x4_16 */
166
    memset(&iq_matrix->ScalingList4x4, 16, sizeof(iq_matrix->ScalingList4x4));
167
 
168
    /* Flat_8x8_16 */
169
    memset(&iq_matrix->ScalingList8x8, 16, sizeof(iq_matrix->ScalingList8x8));
170
}
171
 
172
/* Get first macroblock bit offset for BSD, minus EPB count (AVC) */
173
/* XXX: slice_data_bit_offset does not account for EPB */
174
unsigned int
175
avc_get_first_mb_bit_offset(
176
    dri_bo                     *slice_data_bo,
177
    VASliceParameterBufferH264 *slice_param,
178
    unsigned int                mode_flag
179
)
180
{
181
    unsigned int slice_data_bit_offset = slice_param->slice_data_bit_offset;
182
 
183
    if (mode_flag == ENTROPY_CABAC)
184
        slice_data_bit_offset = ALIGN(slice_data_bit_offset, 0x8);
185
    return slice_data_bit_offset;
186
}
187
 
188
/* Get first macroblock bit offset for BSD, with EPB count (AVC) */
189
/* XXX: slice_data_bit_offset does not account for EPB */
190
unsigned int
191
avc_get_first_mb_bit_offset_with_epb(
192
    dri_bo                     *slice_data_bo,
193
    VASliceParameterBufferH264 *slice_param,
194
    unsigned int                mode_flag
195
)
196
{
197
    unsigned int in_slice_data_bit_offset = slice_param->slice_data_bit_offset;
198
    unsigned int out_slice_data_bit_offset;
199
    unsigned int i, j, n, buf_size, data_size, header_size;
200
    uint8_t *buf;
201
    int ret;
202
 
203
    header_size = slice_param->slice_data_bit_offset / 8;
204
    data_size   = slice_param->slice_data_size - slice_param->slice_data_offset;
205
    buf_size    = (header_size * 3 + 1) / 2; // Max possible header size (x1.5)
206
    if (buf_size > data_size)
207
        buf_size = data_size;
208
 
209
    buf = alloca(buf_size);
210
    ret = dri_bo_get_subdata(
211
        slice_data_bo, slice_param->slice_data_offset,
212
        buf_size, buf
213
    );
214
    assert(ret == 0);
215
 
216
    for (i = 2, j = 2, n = 0; i < buf_size && j < header_size; i++, j++) {
217
        if (buf[i] == 0x03 && buf[i - 1] == 0x00 && buf[i - 2] == 0x00)
218
            i += 2, j++, n++;
219
    }
220
    out_slice_data_bit_offset = in_slice_data_bit_offset + n * 8;
221
 
222
    if (mode_flag == ENTROPY_CABAC)
223
        out_slice_data_bit_offset = ALIGN(out_slice_data_bit_offset, 0x8);
224
    return out_slice_data_bit_offset;
225
}
226
 
227
static inline uint8_t
228
get_ref_idx_state_1(const VAPictureH264 *va_pic, unsigned int frame_store_id)
229
{
230
    const unsigned int is_long_term =
231
        !!(va_pic->flags & VA_PICTURE_H264_LONG_TERM_REFERENCE);
232
    const unsigned int is_top_field =
233
        !!(va_pic->flags & VA_PICTURE_H264_TOP_FIELD);
234
    const unsigned int is_bottom_field =
235
        !!(va_pic->flags & VA_PICTURE_H264_BOTTOM_FIELD);
236
 
237
    return ((is_long_term                         << 6) |
238
            ((is_top_field ^ is_bottom_field ^ 1) << 5) |
239
            (frame_store_id                       << 1) |
240
            ((is_top_field ^ 1) & is_bottom_field));
241
}
242
 
243
/* Fill in Reference List Entries (Gen5+: ILK, SNB, IVB) */
244
void
245
gen5_fill_avc_ref_idx_state(
246
    uint8_t             state[32],
247
    const VAPictureH264 ref_list[32],
248
    unsigned int        ref_list_count,
249
    const GenFrameStore frame_store[MAX_GEN_REFERENCE_FRAMES]
250
)
251
{
252
    unsigned int i, n, frame_idx;
253
 
254
    for (i = 0, n = 0; i < ref_list_count; i++) {
255
        const VAPictureH264 * const va_pic = &ref_list[i];
256
 
257
        if (va_pic->flags & VA_PICTURE_H264_INVALID)
258
            continue;
259
 
260
        for (frame_idx = 0; frame_idx < MAX_GEN_REFERENCE_FRAMES; frame_idx++) {
261
            const GenFrameStore * const fs = &frame_store[frame_idx];
262
            if (fs->surface_id != VA_INVALID_ID &&
263
                fs->surface_id == va_pic->picture_id) {
264
                assert(frame_idx == fs->frame_store_id);
265
                break;
266
            }
267
        }
268
        assert(frame_idx < MAX_GEN_REFERENCE_FRAMES);
269
        state[n++] = get_ref_idx_state_1(va_pic, frame_idx);
270
    }
271
 
272
    for (; n < 32; n++)
273
        state[n] = 0xff;
274
}
275
 
276
/* Emit Reference List Entries (Gen6+: SNB, IVB) */
277
static void
278
gen6_send_avc_ref_idx_state_1(
279
    struct intel_batchbuffer         *batch,
280
    unsigned int                      list,
281
    const VAPictureH264              *ref_list,
282
    unsigned int                      ref_list_count,
283
    const GenFrameStore               frame_store[MAX_GEN_REFERENCE_FRAMES]
284
)
285
{
286
    uint8_t ref_idx_state[32];
287
 
288
    BEGIN_BCS_BATCH(batch, 10);
289
    OUT_BCS_BATCH(batch, MFX_AVC_REF_IDX_STATE | (10 - 2));
290
    OUT_BCS_BATCH(batch, list);
291
    gen5_fill_avc_ref_idx_state(
292
        ref_idx_state,
293
        ref_list, ref_list_count,
294
        frame_store
295
    );
296
    intel_batchbuffer_data(batch, ref_idx_state, sizeof(ref_idx_state));
297
    ADVANCE_BCS_BATCH(batch);
298
}
299
 
300
void
301
gen6_send_avc_ref_idx_state(
302
    struct intel_batchbuffer         *batch,
303
    const VASliceParameterBufferH264 *slice_param,
304
    const GenFrameStore               frame_store[MAX_GEN_REFERENCE_FRAMES]
305
)
306
{
307
    if (slice_param->slice_type == SLICE_TYPE_I ||
308
        slice_param->slice_type == SLICE_TYPE_SI)
309
        return;
310
 
311
    /* RefPicList0 */
312
    gen6_send_avc_ref_idx_state_1(
313
        batch, 0,
314
        slice_param->RefPicList0, slice_param->num_ref_idx_l0_active_minus1 + 1,
315
        frame_store
316
    );
317
 
318
    if (slice_param->slice_type != SLICE_TYPE_B)
319
        return;
320
 
321
    /* RefPicList1 */
322
    gen6_send_avc_ref_idx_state_1(
323
        batch, 1,
324
        slice_param->RefPicList1, slice_param->num_ref_idx_l1_active_minus1 + 1,
325
        frame_store
326
    );
327
}