Revision dc4b78d9 libavcodec/vp3.c

View differences:

libavcodec/vp3.c
2144 2144
}
2145 2145

  
2146 2146
/*
2147
 * Perform the final rendering for a particular slice of data.
2148
 * The slice number ranges from 0..(macroblock_height - 1).
2149
 */
2150
static void render_slice(Vp3DecodeContext *s, int slice)
2151
{
2152
    int x, y;
2153
    int m, n;
2154
    int i;  /* indicates current fragment */
2155
    int16_t *dequantizer;
2156
    DCTELEM __align16 block[64];
2157
    unsigned char *output_plane;
2158
    unsigned char *last_plane;
2159
    unsigned char *golden_plane;
2160
    int stride;
2161
    int motion_x = 0xdeadbeef, motion_y = 0xdeadbeef;
2162
    int upper_motion_limit, lower_motion_limit;
2163
    int motion_halfpel_index;
2164
    uint8_t *motion_source;
2165
    int plane;
2166
    int plane_width;
2167
    int plane_height;
2168
    int slice_height;
2169
    int current_macroblock_entry = slice * s->macroblock_width * 6;
2170

  
2171
    if (slice >= s->macroblock_height)
2172
        return;
2173

  
2174
    for (plane = 0; plane < 3; plane++) {
2175

  
2176
        /* set up plane-specific parameters */
2177
        if (plane == 0) {
2178
            output_plane = s->current_frame.data[0];
2179
            last_plane = s->last_frame.data[0];
2180
            golden_plane = s->golden_frame.data[0];
2181
            stride = s->current_frame.linesize[0];
2182
            if (!s->flipped_image) stride = -stride;
2183
            upper_motion_limit = 7 * s->current_frame.linesize[0];
2184
            lower_motion_limit = s->height * s->current_frame.linesize[0] + s->width - 8;
2185
            y = slice * FRAGMENT_PIXELS * 2;
2186
            plane_width = s->width;
2187
            plane_height = s->height;
2188
            slice_height = y + FRAGMENT_PIXELS * 2;
2189
            i = s->macroblock_fragments[current_macroblock_entry + 0];
2190
        } else if (plane == 1) {
2191
            output_plane = s->current_frame.data[1];
2192
            last_plane = s->last_frame.data[1];
2193
            golden_plane = s->golden_frame.data[1];
2194
            stride = s->current_frame.linesize[1];
2195
            if (!s->flipped_image) stride = -stride;
2196
            upper_motion_limit = 7 * s->current_frame.linesize[1];
2197
            lower_motion_limit = (s->height / 2) * s->current_frame.linesize[1] + (s->width / 2) - 8;
2198
            y = slice * FRAGMENT_PIXELS;
2199
            plane_width = s->width / 2;
2200
            plane_height = s->height / 2;
2201
            slice_height = y + FRAGMENT_PIXELS;
2202
            i = s->macroblock_fragments[current_macroblock_entry + 4];
2203
        } else {
2204
            output_plane = s->current_frame.data[2];
2205
            last_plane = s->last_frame.data[2];
2206
            golden_plane = s->golden_frame.data[2];
2207
            stride = s->current_frame.linesize[2];
2208
            if (!s->flipped_image) stride = -stride;
2209
            upper_motion_limit = 7 * s->current_frame.linesize[2];
2210
            lower_motion_limit = (s->height / 2) * s->current_frame.linesize[2] + (s->width / 2) - 8;
2211
            y = slice * FRAGMENT_PIXELS;
2212
            plane_width = s->width / 2;
2213
            plane_height = s->height / 2;
2214
            slice_height = y + FRAGMENT_PIXELS;
2215
            i = s->macroblock_fragments[current_macroblock_entry + 5];
2216
        }
2217
    
2218
        if(ABS(stride) > 2048)
2219
            return; //various tables are fixed size
2220

  
2221
        /* for each fragment row in the slice (both of them)... */
2222
        for (; y < slice_height; y += 8) {
2223

  
2224
            /* for each fragment in a row... */
2225
            for (x = 0; x < plane_width; x += 8, i++) {
2226

  
2227
                if ((i < 0) || (i >= s->fragment_count)) {
2228
                    av_log(s->avctx, AV_LOG_ERROR, "  vp3:render_slice(): bad fragment number (%d)\n", i);
2229
                    return;
2230
                }
2231

  
2232
                /* transform if this block was coded */
2233
                if ((s->all_fragments[i].coding_method != MODE_COPY) &&
2234
                    !((s->avctx->flags & CODEC_FLAG_GRAY) && plane)) {
2235

  
2236
                    if ((s->all_fragments[i].coding_method == MODE_USING_GOLDEN) ||
2237
                        (s->all_fragments[i].coding_method == MODE_GOLDEN_MV))
2238
                        motion_source= golden_plane;
2239
                    else 
2240
                        motion_source= last_plane;
2241

  
2242
                    motion_source += s->all_fragments[i].first_pixel;
2243
                    motion_halfpel_index = 0;
2244

  
2245
                    /* sort out the motion vector if this fragment is coded
2246
                     * using a motion vector method */
2247
                    if ((s->all_fragments[i].coding_method > MODE_INTRA) &&
2248
                        (s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) {
2249
                        int src_x, src_y;
2250
                        motion_x = s->all_fragments[i].motion_x;
2251
                        motion_y = s->all_fragments[i].motion_y;
2252
                        if(plane){
2253
                            motion_x= (motion_x>>1) | (motion_x&1);
2254
                            motion_y= (motion_y>>1) | (motion_y&1);
2255
                        }
2256

  
2257
                        src_x= (motion_x>>1) + x;
2258
                        src_y= (motion_y>>1) + y;
2259
                        if ((motion_x == 127) || (motion_y == 127))
2260
                            av_log(s->avctx, AV_LOG_ERROR, " help! got invalid motion vector! (%X, %X)\n", motion_x, motion_y);
2261

  
2262
                        motion_halfpel_index = motion_x & 0x01;
2263
                        motion_source += (motion_x >> 1);
2264

  
2265
                        motion_halfpel_index |= (motion_y & 0x01) << 1;
2266
                        motion_source += ((motion_y >> 1) * stride);
2267

  
2268
                        if(src_x<0 || src_y<0 || src_x + 9 >= plane_width || src_y + 9 >= plane_height){
2269
                            uint8_t *temp= s->edge_emu_buffer;
2270
                            if(stride<0) temp -= 9*stride;
2271
                            else temp += 9*stride;
2272

  
2273
                            ff_emulated_edge_mc(temp, motion_source, stride, 9, 9, src_x, src_y, plane_width, plane_height);
2274
                            motion_source= temp;
2275
                        }
2276
                    }
2277
                
2278

  
2279
                    /* first, take care of copying a block from either the
2280
                     * previous or the golden frame */
2281
                    if (s->all_fragments[i].coding_method != MODE_INTRA) {
2282
                        /* Note, it is possible to implement all MC cases with 
2283
                           put_no_rnd_pixels_l2 which would look more like the 
2284
                           VP3 source but this would be slower as 
2285
                           put_no_rnd_pixels_tab is better optimzed */
2286
                        if(motion_halfpel_index != 3){
2287
                            s->dsp.put_no_rnd_pixels_tab[1][motion_halfpel_index](
2288
                                output_plane + s->all_fragments[i].first_pixel,
2289
                                motion_source, stride, 8);
2290
                        }else{
2291
                            int d= (motion_x ^ motion_y)>>31; // d is 0 if motion_x and _y have the same sign, else -1
2292
                            s->dsp.put_no_rnd_pixels_l2[1](
2293
                                output_plane + s->all_fragments[i].first_pixel,
2294
                                motion_source - d, 
2295
                                motion_source + stride + 1 + d, 
2296
                                stride, 8);
2297
                        }
2298
                        dequantizer = s->inter_dequant;
2299
                    }else{
2300
                        if (plane == 0)
2301
                            dequantizer = s->intra_y_dequant;
2302
                        else
2303
                            dequantizer = s->intra_c_dequant;
2304
                    }
2305

  
2306
                    /* dequantize the DCT coefficients */
2307
                    debug_idct("fragment %d, coding mode %d, DC = %d, dequant = %d:\n", 
2308
                        i, s->all_fragments[i].coding_method, 
2309
                        DC_COEFF(i), dequantizer[0]);
2310

  
2311
                    if(s->avctx->idct_algo==FF_IDCT_VP3){
2312
                        Coeff *coeff= s->coeffs + i;
2313
                        memset(block, 0, sizeof(block));
2314
                        while(coeff->next){
2315
                            block[coeff->index]= coeff->coeff * dequantizer[coeff->index];
2316
                            coeff= coeff->next;
2317
                        }
2318
                    }else{
2319
                        Coeff *coeff= s->coeffs + i;
2320
                        memset(block, 0, sizeof(block));
2321
                        while(coeff->next){
2322
                            block[coeff->index]= (coeff->coeff * dequantizer[coeff->index] + 2)>>2;
2323
                            coeff= coeff->next;
2324
                        }
2325
                    }
2326

  
2327
                    /* invert DCT and place (or add) in final output */
2328
                
2329
                    if (s->all_fragments[i].coding_method == MODE_INTRA) {
2330
                        if(s->avctx->idct_algo!=FF_IDCT_VP3)
2331
                            block[0] += 128<<3;
2332
                        s->dsp.idct_put(
2333
                            output_plane + s->all_fragments[i].first_pixel,
2334
                            stride,
2335
                            block);
2336
                    } else {
2337
                        s->dsp.idct_add(
2338
                            output_plane + s->all_fragments[i].first_pixel,
2339
                            stride,
2340
                            block);
2341
                    }
2342

  
2343
                    debug_idct("block after idct_%s():\n",
2344
                        (s->all_fragments[i].coding_method == MODE_INTRA)?
2345
                        "put" : "add");
2346
                    for (m = 0; m < 8; m++) {
2347
                        for (n = 0; n < 8; n++) {
2348
                            debug_idct(" %3d", *(output_plane + 
2349
                                s->all_fragments[i].first_pixel + (m * stride + n)));
2350
                        }
2351
                        debug_idct("\n");
2352
                    }
2353
                    debug_idct("\n");
2354

  
2355
                } else {
2356

  
2357
                    /* copy directly from the previous frame */
2358
                    s->dsp.put_pixels_tab[1][0](
2359
                        output_plane + s->all_fragments[i].first_pixel,
2360
                        last_plane + s->all_fragments[i].first_pixel,
2361
                        stride, 8);
2362

  
2363
                }
2364
            }
2365
        }
2366
    }
2367

  
2368
    /* future loop filter logic goes here... */
2369
    /* algorithm: 
2370
     *   if (slice != 0) 
2371
     *     run filter on 1st row of Y slice
2372
     *     run filter on U slice
2373
     *     run filter on V slice
2374
     *   run filter on 2nd row of Y slice
2375
     */
2376

  
2377
     /* this looks like a good place for slice dispatch... */
2378
     /* algorithm:
2379
      *   if (slice > 0)
2380
      *     dispatch (slice - 1);
2381
      *   if (slice == s->macroblock_height - 1)
2382
      *     dispatch (slice);  // handle last slice
2383
      */
2384

  
2385
    emms_c();
2386
}
2387

  
2388
/*
2147 2389
 * This function performs the final rendering of each fragment's data
2148 2390
 * onto the output frame.
2149 2391
 */
......
2774 3016
    Vp3DecodeContext *s = avctx->priv_data;
2775 3017
    GetBitContext gb;
2776 3018
    static int counter = 0;
3019
    int i;
2777 3020

  
2778 3021
    init_get_bits(&gb, buf, buf_size * 8);
2779 3022
    
......
2917 3160
    {START_TIMER
2918 3161

  
2919 3162
    reverse_dc_prediction(s, 0, s->fragment_width, s->fragment_height);
2920
    STOP_TIMER("reverse_dc_prediction")}
2921
    {START_TIMER
2922
    render_fragments(s, 0, s->width, s->height, 0);
2923
    STOP_TIMER("render_fragments")}
2924

  
2925 3163
    if ((avctx->flags & CODEC_FLAG_GRAY) == 0) {
2926 3164
        reverse_dc_prediction(s, s->u_fragment_start,
2927 3165
            s->fragment_width / 2, s->fragment_height / 2);
2928 3166
        reverse_dc_prediction(s, s->v_fragment_start,
2929 3167
            s->fragment_width / 2, s->fragment_height / 2);
3168
    }
3169
    STOP_TIMER("reverse_dc_prediction")}
3170
    {START_TIMER
3171

  
3172
#if 1
3173
    for (i = 0; i < s->macroblock_height; i++)
3174
        render_slice(s, i);
3175
#else
3176
    render_fragments(s, 0, s->width, s->height, 0);
3177
    if ((avctx->flags & CODEC_FLAG_GRAY) == 0) {
2930 3178
        render_fragments(s, s->u_fragment_start, s->width / 2, s->height / 2, 1);
2931 3179
        render_fragments(s, s->v_fragment_start, s->width / 2, s->height / 2, 2);
2932 3180
    } else {
2933 3181
        memset(s->current_frame.data[1], 0x80, s->width * s->height / 4);
2934 3182
        memset(s->current_frame.data[2], 0x80, s->width * s->height / 4);
2935 3183
    }
3184
#endif
3185
    STOP_TIMER("render_fragments")}
2936 3186

  
2937 3187
    {START_TIMER
2938 3188
    apply_loop_filter(s);

Also available in: Unified diff