Statistics
| Branch: | Revision:

ffmpeg / libavcodec / mpegvideo_xvmc.c @ 36c5204d

History | View | Annotate | Download (9.81 KB)

1
/*
2
 * XVideo Motion Compensation
3
 * Copyright (c) 2003 Ivan Kalvachev
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21

    
22
#include <limits.h>
23

    
24
//avcodec include
25
#include "avcodec.h"
26
#include "dsputil.h"
27
#include "mpegvideo.h"
28

    
29
#undef NDEBUG
30
#include <assert.h>
31

    
32
#include "xvmc.h"
33

    
34
//set s->block
35
void ff_xvmc_init_block(MpegEncContext *s)
36
{
37
    struct xvmc_render_state * render;
38
    render = (struct xvmc_render_state*)s->current_picture.data[2];
39
    assert(render);
40
    if (!render || render->magic != AV_XVMC_RENDER_MAGIC) {
41
        assert(0);
42
        return;//make sure that this is a render packet
43
    }
44
    s->block = (DCTELEM *)(render->data_blocks + render->next_free_data_block_num * 64);
45
}
46

    
47
void ff_xvmc_pack_pblocks(MpegEncContext *s, int cbp)
48
{
49
    int i,j;
50
    const int mb_block_count = 4 + (1 << s->chroma_format);
51

    
52
    j = 0;
53
    cbp <<= 12-mb_block_count;
54
    for (i = 0; i < mb_block_count; i++) {
55
        if (cbp & (1 << 11))
56
            s->pblocks[i] = (short *)(&s->block[j++]);
57
        else
58
            s->pblocks[i] = NULL;
59
        cbp+=cbp;
60
    }
61
}
62

    
63
//These functions should be called on every new field and/or frame.
64
//They should be safe if they are called a few times for the same field!
65
int ff_xvmc_field_start(MpegEncContext*s, AVCodecContext *avctx)
66
{
67
    struct xvmc_render_state * render, * last, * next;
68

    
69
    assert(avctx);
70

    
71
    render = (struct xvmc_render_state*)s->current_picture.data[2];
72
    assert(render);
73
    if (!render || render->magic != AV_XVMC_RENDER_MAGIC)
74
        return -1;//make sure that this is render packet
75

    
76
    render->picture_structure = s->picture_structure;
77
    render->flags             = s->first_field ? 0 : XVMC_SECOND_FIELD;
78

    
79
//make sure that all data is drawn by XVMC_end_frame
80
    assert(render->filled_mv_blocks_num == 0);
81

    
82
    render->p_future_surface = NULL;
83
    render->p_past_surface   = NULL;
84

    
85
    switch(s->pict_type){
86
        case  FF_I_TYPE:
87
            return 0;// no prediction from other frames
88
        case  FF_B_TYPE:
89
            next = (struct xvmc_render_state*)s->next_picture.data[2];
90
            assert(next);
91
            if (!next)
92
                return -1;
93
            if (next->magic != AV_XVMC_RENDER_MAGIC)
94
                return -1;
95
            render->p_future_surface = next->p_surface;
96
            //no return here, going to set forward prediction
97
        case  FF_P_TYPE:
98
            last = (struct xvmc_render_state*)s->last_picture.data[2];
99
            if (!last)// && !s->first_field)
100
                last = render;//predict second field from the first
101
            if (last->magic != AV_XVMC_RENDER_MAGIC)
102
                return -1;
103
            render->p_past_surface = last->p_surface;
104
            return 0;
105
    }
106

    
107
return -1;
108
}
109

    
110
void ff_xvmc_field_end(MpegEncContext *s)
111
{
112
    struct xvmc_render_state * render;
113
    render = (struct xvmc_render_state*)s->current_picture.data[2];
114
    assert(render);
115

    
116
    if (render->filled_mv_blocks_num > 0)
117
        ff_draw_horiz_band(s,0,0);
118
}
119

    
120
void ff_xvmc_decode_mb(MpegEncContext *s)
121
{
122
    XvMCMacroBlock * mv_block;
123
    struct xvmc_render_state * render;
124
    int i,cbp,blocks_per_mb;
125

    
126
    const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;
127

    
128

    
129
    if (s->encoding) {
130
        av_log(s->avctx, AV_LOG_ERROR, "XVMC doesn't support encoding!!!\n");
131
        return;
132
    }
133

    
134
   //from MPV_decode_mb(),
135
    /* update DC predictors for P macroblocks */
136
    if (!s->mb_intra) {
137
        s->last_dc[0] =
138
        s->last_dc[1] =
139
        s->last_dc[2] =  128 << s->intra_dc_precision;
140
    }
141

    
142
   //MC doesn't skip blocks
143
    s->mb_skipped = 0;
144

    
145

    
146
   // Do I need to export quant when I could not perform postprocessing?
147
   // Anyway, it doesn't hurt.
148
    s->current_picture.qscale_table[mb_xy] = s->qscale;
149

    
150
//START OF XVMC specific code
151
    render = (struct xvmc_render_state*)s->current_picture.data[2];
152
    assert(render);
153
    assert(render->magic==AV_XVMC_RENDER_MAGIC);
154
    assert(render->mv_blocks);
155

    
156
    //take the next free macroblock
157
    mv_block = &render->mv_blocks[render->start_mv_blocks_num +
158
                                  render->filled_mv_blocks_num ];
159

    
160
    mv_block->x        = s->mb_x;
161
    mv_block->y        = s->mb_y;
162
    mv_block->dct_type = s->interlaced_dct;//XVMC_DCT_TYPE_FRAME/FIELD;
163
    if (s->mb_intra) {
164
        mv_block->macroblock_type = XVMC_MB_TYPE_INTRA;//no MC, all done
165
    } else {
166
        mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN;
167

    
168
        if (s->mv_dir & MV_DIR_FORWARD) {
169
            mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD;
170
            //pmv[n][dir][xy]=mv[dir][n][xy]
171
            mv_block->PMV[0][0][0] = s->mv[0][0][0];
172
            mv_block->PMV[0][0][1] = s->mv[0][0][1];
173
            mv_block->PMV[1][0][0] = s->mv[0][1][0];
174
            mv_block->PMV[1][0][1] = s->mv[0][1][1];
175
        }
176
        if (s->mv_dir & MV_DIR_BACKWARD) {
177
            mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD;
178
            mv_block->PMV[0][1][0] = s->mv[1][0][0];
179
            mv_block->PMV[0][1][1] = s->mv[1][0][1];
180
            mv_block->PMV[1][1][0] = s->mv[1][1][0];
181
            mv_block->PMV[1][1][1] = s->mv[1][1][1];
182
        }
183

    
184
        switch(s->mv_type){
185
            case  MV_TYPE_16X16:
186
                mv_block->motion_type = XVMC_PREDICTION_FRAME;
187
                break;
188
            case  MV_TYPE_16X8:
189
                mv_block->motion_type = XVMC_PREDICTION_16x8;
190
                break;
191
            case  MV_TYPE_FIELD:
192
                mv_block->motion_type = XVMC_PREDICTION_FIELD;
193
                if (s->picture_structure == PICT_FRAME) {
194
                    mv_block->PMV[0][0][1] <<= 1;
195
                    mv_block->PMV[1][0][1] <<= 1;
196
                    mv_block->PMV[0][1][1] <<= 1;
197
                    mv_block->PMV[1][1][1] <<= 1;
198
                }
199
                break;
200
            case  MV_TYPE_DMV:
201
                mv_block->motion_type = XVMC_PREDICTION_DUAL_PRIME;
202
                if (s->picture_structure == PICT_FRAME) {
203

    
204
                    mv_block->PMV[0][0][0] = s->mv[0][0][0];//top from top
205
                    mv_block->PMV[0][0][1] = s->mv[0][0][1]<<1;
206

    
207
                    mv_block->PMV[0][1][0] = s->mv[0][0][0];//bottom from bottom
208
                    mv_block->PMV[0][1][1] = s->mv[0][0][1]<<1;
209

    
210
                    mv_block->PMV[1][0][0] = s->mv[0][2][0];//dmv00, top from bottom
211
                    mv_block->PMV[1][0][1] = s->mv[0][2][1]<<1;//dmv01
212

    
213
                    mv_block->PMV[1][1][0] = s->mv[0][3][0];//dmv10, bottom from top
214
                    mv_block->PMV[1][1][1] = s->mv[0][3][1]<<1;//dmv11
215

    
216
                } else {
217
                    mv_block->PMV[0][1][0] = s->mv[0][2][0];//dmv00
218
                    mv_block->PMV[0][1][1] = s->mv[0][2][1];//dmv01
219
                }
220
                break;
221
            default:
222
                assert(0);
223
        }
224

    
225
        mv_block->motion_vertical_field_select = 0;
226

    
227
//set correct field references
228
        if (s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8) {
229
            mv_block->motion_vertical_field_select |= s->field_select[0][0];
230
            mv_block->motion_vertical_field_select |= s->field_select[1][0]<<1;
231
            mv_block->motion_vertical_field_select |= s->field_select[0][1]<<2;
232
            mv_block->motion_vertical_field_select |= s->field_select[1][1]<<3;
233
        }
234
    }//!intra
235
//time to handle data blocks;
236
    mv_block->index = render->next_free_data_block_num;
237

    
238
    blocks_per_mb = 6;
239
    if (s->chroma_format >= 2) {
240
        blocks_per_mb = 4 + (1 << s->chroma_format);
241
    }
242

    
243
//  calculate cbp
244
    cbp = 0;
245
    for (i = 0; i < blocks_per_mb; i++) {
246
        cbp += cbp;
247
        if (s->block_last_index[i] >= 0)
248
            cbp++;
249
    }
250

    
251
    if (s->flags & CODEC_FLAG_GRAY) {
252
        if (s->mb_intra) {//intra frames are always full chroma block
253
            for (i = 4; i < blocks_per_mb; i++) {
254
                memset(s->pblocks[i],0,sizeof(short)*8*8);//so we need to clear them
255
                if (!render->unsigned_intra)
256
                    s->pblocks[i][0] = 1 << 10;
257
            }
258
        } else {
259
            cbp &= 0xf << (blocks_per_mb - 4);
260
            blocks_per_mb = 4;//luminance blocks only
261
        }
262
    }
263
    mv_block->coded_block_pattern = cbp;
264
    if (cbp == 0)
265
        mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN;
266

    
267
    for (i = 0; i < blocks_per_mb; i++) {
268
        if (s->block_last_index[i] >= 0) {
269
            // I do not have unsigned_intra MOCO to test, hope it is OK.
270
            if (s->mb_intra && (render->idct || !render->idct && !render->unsigned_intra))
271
                s->pblocks[i][0] -= 1 << 10;
272
            if (!render->idct) {
273
                s->dsp.idct(s->pblocks[i]);
274
                //!!TODO!clip!!!
275
            }
276
//copy blocks only if the codec doesn't support pblocks reordering
277
            if (s->avctx->xvmc_acceleration == 1) {
278
                memcpy(&render->data_blocks[render->next_free_data_block_num*64],
279
                       s->pblocks[i],sizeof(short)*8*8);
280
            }
281
            render->next_free_data_block_num++;
282
        }
283
    }
284
    render->filled_mv_blocks_num++;
285

    
286
    assert(render->filled_mv_blocks_num     <= render->total_number_of_mv_blocks);
287
    assert(render->next_free_data_block_num <= render->total_number_of_data_blocks);
288

    
289

    
290
    if (render->filled_mv_blocks_num >= render->total_number_of_mv_blocks)
291
        ff_draw_horiz_band(s,0,0);
292
}