Search
lxdream.org :: lxdream/src/pvr2/yuv.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/pvr2/yuv.c
changeset 736:a02d1475ccfd
prev677:3ee62740ff8f
author nkeynes
date Fri May 29 18:47:05 2015 +1000 (8 years ago)
permissions -rw-r--r--
last change Fix test case
file annotate diff log raw
nkeynes@281
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@281
     3
 *
nkeynes@281
     4
 * YUV420 and YUV422 decoding
nkeynes@281
     5
 *
nkeynes@281
     6
 * Copyright (c) 2005 Nathan Keynes.
nkeynes@281
     7
 *
nkeynes@281
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@281
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@281
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@281
    11
 * (at your option) any later version.
nkeynes@281
    12
 *
nkeynes@281
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@281
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@281
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@281
    16
 * GNU General Public License for more details.
nkeynes@281
    17
 */
nkeynes@281
    18
#include "dream.h"
nkeynes@282
    19
#include "asic.h"
nkeynes@282
    20
#include "pvr2/pvr2.h"
nkeynes@677
    21
#include "pvr2/pvr2mmio.h"
nkeynes@281
    22
nkeynes@281
    23
#define YUV420_BLOCK_SIZE 384
nkeynes@282
    24
#define YUV422_BLOCK_SIZE 512
nkeynes@281
    25
nkeynes@282
    26
#define FORMAT_YUV420 0
nkeynes@282
    27
#define FORMAT_YUV422 1
nkeynes@282
    28
nkeynes@282
    29
nkeynes@282
    30
static int yuv_block_size[2] = { YUV420_BLOCK_SIZE, YUV422_BLOCK_SIZE };
nkeynes@282
    31
nkeynes@282
    32
struct yuv_state {
nkeynes@282
    33
    uint32_t target;
nkeynes@674
    34
    uint32_t width;
nkeynes@674
    35
    uint32_t height;
nkeynes@674
    36
    uint32_t input_format;
nkeynes@429
    37
    unsigned char data[512];
nkeynes@674
    38
    uint32_t data_length;
nkeynes@674
    39
    uint32_t x, y;
nkeynes@282
    40
} pvr2_yuv_state;
nkeynes@282
    41
nkeynes@282
    42
/**
nkeynes@282
    43
 * Transformation table for yuv420.
nkeynes@282
    44
 */
nkeynes@282
    45
uint16_t yuv420_lut[512] = { 0, 128, 64, 129, 1, 130, 65, 131, 2, 132, 66, 133, 3, 134, 67, 135, 4, 192, 68, 193, 5, 194, 69, 195, 6, 196, 70, 197, 7, 198, 71, 199,
nkeynes@736
    46
        0, 136, 64, 137, 1, 138, 65, 139, 2, 140, 66, 141, 3, 142, 67, 143, 4, 200, 68, 201, 5, 202, 69, 203, 6, 204, 70, 205, 7, 206, 71, 207,
nkeynes@736
    47
        8, 144, 72, 145, 9, 146, 73, 147, 10, 148, 74, 149, 11, 150, 75, 151, 12, 208, 76, 209, 13, 210, 77, 211, 14, 212, 78, 213, 15, 214, 79, 215,
nkeynes@736
    48
        8, 152, 72, 153, 9, 154, 73, 155, 10, 156, 74, 157, 11, 158, 75, 159, 12, 216, 76, 217, 13, 218, 77, 219, 14, 220, 78, 221, 15, 222, 79, 223,
nkeynes@736
    49
        16, 160, 80, 161, 17, 162, 81, 163, 18, 164, 82, 165, 19, 166, 83, 167, 20, 224, 84, 225, 21, 226, 85, 227, 22, 228, 86, 229, 23, 230, 87, 231,
nkeynes@736
    50
        16, 168, 80, 169, 17, 170, 81, 171, 18, 172, 82, 173, 19, 174, 83, 175, 20, 232, 84, 233, 21, 234, 85, 235, 22, 236, 86, 237, 23, 238, 87, 239,
nkeynes@736
    51
        24, 176, 88, 177, 25, 178, 89, 179, 26, 180, 90, 181, 27, 182, 91, 183, 28, 240, 92, 241, 29, 242, 93, 243, 30, 244, 94, 245, 31, 246, 95, 247,
nkeynes@736
    52
        24, 184, 88, 185, 25, 186, 89, 187, 26, 188, 90, 189, 27, 190, 91, 191, 28, 248, 92, 249, 29, 250, 93, 251, 30, 252, 94, 253, 31, 254, 95, 255,
nkeynes@736
    53
        32, 256, 96, 257, 33, 258, 97, 259, 34, 260, 98, 261, 35, 262, 99, 263, 36, 320, 100, 321, 37, 322, 101, 323, 38, 324, 102, 325, 39, 326, 103, 327,
nkeynes@736
    54
        32, 264, 96, 265, 33, 266, 97, 267, 34, 268, 98, 269, 35, 270, 99, 271, 36, 328, 100, 329, 37, 330, 101, 331, 38, 332, 102, 333, 39, 334, 103, 335,
nkeynes@736
    55
        40, 272, 104, 273, 41, 274, 105, 275, 42, 276, 106, 277, 43, 278, 107, 279, 44, 336, 108, 337, 45, 338, 109, 339, 46, 340, 110, 341, 47, 342, 111, 343,
nkeynes@736
    56
        40, 280, 104, 281, 41, 282, 105, 283, 42, 284, 106, 285, 43, 286, 107, 287, 44, 344, 108, 345, 45, 346, 109, 347, 46, 348, 110, 349, 47, 350, 111, 351,
nkeynes@736
    57
        48, 288, 112, 289, 49, 290, 113, 291, 50, 292, 114, 293, 51, 294, 115, 295, 52, 352, 116, 353, 53, 354, 117, 355, 54, 356, 118, 357, 55, 358, 119, 359,
nkeynes@736
    58
        48, 296, 112, 297, 49, 298, 113, 299, 50, 300, 114, 301, 51, 302, 115, 303, 52, 360, 116, 361, 53, 362, 117, 363, 54, 364, 118, 365, 55, 366, 119, 367,
nkeynes@736
    59
        56, 304, 120, 305, 57, 306, 121, 307, 58, 308, 122, 309, 59, 310, 123, 311, 60, 368, 124, 369, 61, 370, 125, 371, 62, 372, 126, 373, 63, 374, 127, 375,
nkeynes@736
    60
        56, 312, 120, 313, 57, 314, 121, 315, 58, 316, 122, 317, 59, 318, 123, 319, 60, 376, 124, 377, 61, 378, 125, 379, 62, 380, 126, 381, 63, 382, 127, 383 };
nkeynes@282
    61
nkeynes@293
    62
/**
nkeynes@293
    63
 * Transformation table for YUV422 inputs
nkeynes@293
    64
 */
nkeynes@293
    65
uint16_t yuv422_lut[512] = { 0, 128, 64, 129, 1, 130, 65, 131, 2, 132, 66, 133, 3, 134, 67, 135, 4, 192, 68, 193, 5, 194, 69, 195, 6, 196, 70, 197, 7, 198, 71, 199,
nkeynes@736
    66
        8, 136, 72, 137, 9, 138, 73, 139, 10, 140, 74, 141, 11, 142, 75, 143, 12, 200, 76, 201, 13, 202, 77, 203, 14, 204, 78, 205, 15, 206, 79, 207,
nkeynes@736
    67
        16, 144, 80, 145, 17, 146, 81, 147, 18, 148, 82, 149, 19, 150, 83, 151, 20, 208, 84, 209, 21, 210, 85, 211, 22, 212, 86, 213, 23, 214, 87, 215,
nkeynes@736
    68
        24, 152, 88, 153, 25, 154, 89, 155, 26, 156, 90, 157, 27, 158, 91, 159, 28, 216, 92, 217, 29, 218, 93, 219, 30, 220, 94, 221, 31, 222, 95, 223,
nkeynes@736
    69
        32, 160, 96, 161, 33, 162, 97, 163, 34, 164, 98, 165, 35, 166, 99, 167, 36, 224, 100, 225, 37, 226, 101, 227, 38, 228, 102, 229, 39, 230, 103, 231,
nkeynes@736
    70
        40, 168, 104, 169, 41, 170, 105, 171, 42, 172, 106, 173, 43, 174, 107, 175, 44, 232, 108, 233, 45, 234, 109, 235, 46, 236, 110, 237, 47, 238, 111, 239,
nkeynes@736
    71
        48, 176, 112, 177, 49, 178, 113, 179, 50, 180, 114, 181, 51, 182, 115, 183, 52, 240, 116, 241, 53, 242, 117, 243, 54, 244, 118, 245, 55, 246, 119, 247,
nkeynes@736
    72
        56, 184, 120, 185, 57, 186, 121, 187, 58, 188, 122, 189, 59, 190, 123, 191, 60, 248, 124, 249, 61, 250, 125, 251, 62, 252, 126, 253, 63, 254, 127, 255,
nkeynes@736
    73
        256, 384, 320, 385, 257, 386, 321, 387, 258, 388, 322, 389, 259, 390, 323, 391, 260, 448, 324, 449, 261, 450, 325, 451, 262, 452, 326, 453, 263, 454, 327, 455,
nkeynes@736
    74
        264, 392, 328, 393, 265, 394, 329, 395, 266, 396, 330, 397, 267, 398, 331, 399, 268, 456, 332, 457, 269, 458, 333, 459, 270, 460, 334, 461, 271, 462, 335, 463,
nkeynes@736
    75
        272, 400, 336, 401, 273, 402, 337, 403, 274, 404, 338, 405, 275, 406, 339, 407, 276, 464, 340, 465, 277, 466, 341, 467, 278, 468, 342, 469, 279, 470, 343, 471,
nkeynes@736
    76
        280, 408, 344, 409, 281, 410, 345, 411, 282, 412, 346, 413, 283, 414, 347, 415, 284, 472, 348, 473, 285, 474, 349, 475, 286, 476, 350, 477, 287, 478, 351, 479,
nkeynes@736
    77
        288, 416, 352, 417, 289, 418, 353, 419, 290, 420, 354, 421, 291, 422, 355, 423, 292, 480, 356, 481, 293, 482, 357, 483, 294, 484, 358, 485, 295, 486, 359, 487,
nkeynes@736
    78
        296, 424, 360, 425, 297, 426, 361, 427, 298, 428, 362, 429, 299, 430, 363, 431, 300, 488, 364, 489, 301, 490, 365, 491, 302, 492, 366, 493, 303, 494, 367, 495,
nkeynes@736
    79
        304, 432, 368, 433, 305, 434, 369, 435, 306, 436, 370, 437, 307, 438, 371, 439, 308, 496, 372, 497, 309, 498, 373, 499, 310, 500, 374, 501, 311, 502, 375, 503,
nkeynes@736
    80
        312, 440, 376, 441, 313, 442, 377, 443, 314, 444, 378, 445, 315, 446, 379, 447, 316, 504, 380, 505, 317, 506, 381, 507, 318, 508, 382, 509, 319, 510, 383, 511 };
nkeynes@282
    81
nkeynes@282
    82
/**
nkeynes@282
    83
 * Input is 8x8 U, 8x8 V, 8x8 Y00, 8x8 Y01, 8x8 Y10, 8x8 Y11, 8 bits each,
nkeynes@282
    84
 * for a total of 384 bytes.
nkeynes@282
    85
 * Output is UVYV = 32 bits = 2 horizontal pixels, 8x16 = 512 bytes
nkeynes@282
    86
 */
nkeynes@429
    87
void pvr2_decode_yuv420( unsigned char *dest, unsigned char *src )
nkeynes@281
    88
{
nkeynes@282
    89
    int i;
nkeynes@282
    90
    for( i=0; i<512; i++ ) {
nkeynes@736
    91
        dest[i] = src[yuv420_lut[i]];
nkeynes@282
    92
    }
nkeynes@282
    93
}
nkeynes@282
    94
nkeynes@429
    95
void pvr2_decode_yuv422( unsigned char *dest, unsigned char *src )
nkeynes@282
    96
{
nkeynes@293
    97
    int i;
nkeynes@293
    98
    for( i=0; i<512; i++ ) {
nkeynes@736
    99
        dest[i] = src[yuv422_lut[i]];
nkeynes@293
   100
    }
nkeynes@281
   101
}
nkeynes@281
   102
nkeynes@281
   103
/**
nkeynes@282
   104
 * Process a single macroblock of YUV data and write it out to 
nkeynes@282
   105
 * texture vram.
nkeynes@281
   106
 */
nkeynes@429
   107
void pvr2_yuv_process_block( unsigned char *data )
nkeynes@281
   108
{
nkeynes@429
   109
    unsigned char output[512];
nkeynes@282
   110
nkeynes@282
   111
    if( pvr2_yuv_state.input_format == FORMAT_YUV420 ) {
nkeynes@736
   112
        pvr2_decode_yuv420( output, data );
nkeynes@282
   113
    } else {
nkeynes@736
   114
        pvr2_decode_yuv422( output, data );
nkeynes@282
   115
    }
nkeynes@736
   116
nkeynes@282
   117
    uint32_t target = pvr2_yuv_state.target + 
nkeynes@736
   118
    (pvr2_yuv_state.y * pvr2_yuv_state.width * 512) +
nkeynes@736
   119
    (pvr2_yuv_state.x * 32);
nkeynes@282
   120
nkeynes@282
   121
    pvr2_vram64_write_stride( target, output, 32, pvr2_yuv_state.width*32, 16 );
nkeynes@282
   122
    if( ++pvr2_yuv_state.x >= pvr2_yuv_state.width ) {
nkeynes@736
   123
        pvr2_yuv_state.x = 0;
nkeynes@736
   124
        pvr2_yuv_state.y++;
nkeynes@736
   125
        if( pvr2_yuv_state.y >= pvr2_yuv_state.height ) {
nkeynes@736
   126
            asic_event( EVENT_PVR_YUV_DONE );
nkeynes@736
   127
            pvr2_yuv_state.y = 0;
nkeynes@736
   128
        }
nkeynes@282
   129
    }
nkeynes@736
   130
nkeynes@282
   131
    MMIO_WRITE( PVR2, YUV_COUNT, MMIO_READ( PVR2, YUV_COUNT ) + 1 );
nkeynes@282
   132
}
nkeynes@282
   133
nkeynes@282
   134
/**
nkeynes@282
   135
 * Receive data from the SH4, usually via DMA. This method is mainly responsible
nkeynes@282
   136
 * for buffering the data into macroblock chunks and then passing it on to the
nkeynes@282
   137
 * real processing
nkeynes@282
   138
 */
nkeynes@429
   139
void pvr2_yuv_write( unsigned char *data, uint32_t length )
nkeynes@282
   140
{
nkeynes@282
   141
    int block_size = yuv_block_size[pvr2_yuv_state.input_format];
nkeynes@282
   142
nkeynes@282
   143
    if( pvr2_yuv_state.data_length != 0 ) { /* Append to existing data */
nkeynes@736
   144
        int tmp = MIN( length, block_size - pvr2_yuv_state.data_length );
nkeynes@736
   145
        memcpy( pvr2_yuv_state.data + pvr2_yuv_state.data_length, 
nkeynes@736
   146
                data, tmp );
nkeynes@736
   147
        pvr2_yuv_state.data_length += tmp;
nkeynes@736
   148
        data += tmp;
nkeynes@736
   149
        length -= tmp;
nkeynes@736
   150
        if( pvr2_yuv_state.data_length == block_size ) {
nkeynes@736
   151
            pvr2_yuv_process_block( pvr2_yuv_state.data );
nkeynes@736
   152
        }
nkeynes@282
   153
    }
nkeynes@282
   154
nkeynes@282
   155
    while( length >= block_size ) {
nkeynes@736
   156
        pvr2_yuv_process_block( data );
nkeynes@736
   157
        data += block_size;
nkeynes@736
   158
        length -= block_size;
nkeynes@282
   159
    }
nkeynes@736
   160
nkeynes@282
   161
    if( length != 0 ) { /* Save the left over data */
nkeynes@736
   162
        memcpy( pvr2_yuv_state.data, data, length );
nkeynes@736
   163
        pvr2_yuv_state.data_length = length;
nkeynes@281
   164
    }
nkeynes@281
   165
}
nkeynes@281
   166
nkeynes@284
   167
void pvr2_yuv_init( uint32_t target )
nkeynes@281
   168
{
nkeynes@282
   169
    pvr2_yuv_state.target = target;
nkeynes@282
   170
    pvr2_yuv_state.x = 0;
nkeynes@282
   171
    pvr2_yuv_state.y = 0;
nkeynes@282
   172
    pvr2_yuv_state.data_length = 0;
nkeynes@284
   173
    MMIO_WRITE( PVR2, YUV_COUNT, 0 );
nkeynes@284
   174
}
nkeynes@284
   175
nkeynes@284
   176
void pvr2_yuv_set_config( uint32_t config )
nkeynes@284
   177
{
nkeynes@284
   178
    pvr2_yuv_state.width = (config & 0x3f) + 1;
nkeynes@284
   179
    pvr2_yuv_state.height = ((config>>8) & 0x3f) +1;
nkeynes@284
   180
    pvr2_yuv_state.input_format = (config & 0x01000000) ? FORMAT_YUV422 : FORMAT_YUV420;
nkeynes@282
   181
    if( config & 0x00010000 ) {
nkeynes@736
   182
        pvr2_yuv_state.height *= pvr2_yuv_state.width;
nkeynes@736
   183
        pvr2_yuv_state.width = 1;
nkeynes@281
   184
    }
nkeynes@281
   185
}
nkeynes@293
   186
nkeynes@293
   187
void pvr2_yuv_save_state( FILE * f )
nkeynes@293
   188
{
nkeynes@293
   189
    fwrite( &pvr2_yuv_state, sizeof(pvr2_yuv_state), 1, f );
nkeynes@293
   190
}
nkeynes@293
   191
nkeynes@293
   192
int pvr2_yuv_load_state( FILE *f )
nkeynes@293
   193
{
nkeynes@293
   194
    if( fread( &pvr2_yuv_state, sizeof(pvr2_yuv_state), 1, f ) != 1 ) {
nkeynes@736
   195
        return 1;
nkeynes@293
   196
    } else {
nkeynes@736
   197
        return 0;
nkeynes@293
   198
    }
nkeynes@293
   199
}
.