Subversion Repositories eduke32

Rev

Rev 8711 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1933 helixhorne 1
/* ANM file replacement with VP8 video */
2
 
4320 hendricks2 3
#ifdef USE_LIBVPX
4
 
6074 hendricks2 5
#include "compat.h"
1933 helixhorne 6
 
7
#include "compat.h"
8
#include "baselayer.h"
9
#include "build.h"
6656 pogokeen 10
#include "glad/glad.h"
6056 hendricks2 11
#include "cache1d.h"
1933 helixhorne 12
 
5197 hendricks2 13
#undef UNUSED
1933 helixhorne 14
#define VPX_CODEC_DISABLE_COMPAT 1
15
#include <vpx/vpx_decoder.h>
16
#include <vpx/vp8dx.h>
17
#include "animvpx.h"
18
 
19
const char *animvpx_read_ivf_header_errmsg[] = {
20
    "All OK",
21
    "couldn't read 32-byte IVF header",
22
    "magic mismatch, not an IVF file",
23
    "unrecognized IVF version, expected 0",
24
    "only VP8 video stream supported",
25
    "invalid framerate numerator or denominator after correction, must not be 0",
26
};
27
 
3644 helixhorne 28
EDUKE32_STATIC_ASSERT(sizeof(animvpx_ivf_header_t) == 32);
29
 
7359 hendricks2 30
int32_t animvpx_read_ivf_header(buildvfs_kfd inhandle, animvpx_ivf_header_t *hdr)
1933 helixhorne 31
{
3131 helixhorne 32
    int32_t err;
1933 helixhorne 33
 
34
    if (kread(inhandle, hdr, sizeof(animvpx_ivf_header_t)) != sizeof(animvpx_ivf_header_t))
35
        return 1;  // "couldn't read header"
36
 
3131 helixhorne 37
    err = animvpx_check_header(hdr);
38
    if (err)
39
        return err;
1933 helixhorne 40
 
41
    hdr->hdrlen = B_LITTLE16(hdr->hdrlen);
42
 
43
    hdr->width = B_LITTLE16(hdr->width);
44
    hdr->height = B_LITTLE16(hdr->height);
45
    hdr->fpsnumer = B_LITTLE16(hdr->fpsnumer);
46
    hdr->fpsdenom = B_LITTLE16(hdr->fpsdenom);
47
 
48
    hdr->numframes = B_LITTLE32(hdr->numframes);
49
 
3110 helixhorne 50
    // the rest is based on vpxdec.c --> file_is_ivf()
1933 helixhorne 51
 
52
    if (hdr->fpsnumer < 1000)
53
    {
3131 helixhorne 54
        // NOTE: We got rid of the 1/(2*fps) correction from libvpx's vpxdec.c,
6056 hendricks2 55
        // users are encouraged to use the "ivfrate" utility instead
1933 helixhorne 56
 
57
        if (hdr->fpsdenom==0 || hdr->fpsnumer==0)
58
            return 5;  // "invalid framerate numerator or denominator"
3110 helixhorne 59
 
3131 helixhorne 60
        initprintf("animvpx: rate is %d frames / %d seconds (%.03f fps).\n",
3110 helixhorne 61
                   hdr->fpsnumer, hdr->fpsdenom, (double)hdr->fpsnumer/hdr->fpsdenom);
1933 helixhorne 62
    }
63
    else
64
    {
3131 helixhorne 65
        double fps = (hdr->fpsdenom==0) ? 0.0 : (double)hdr->fpsnumer/hdr->fpsdenom;
3110 helixhorne 66
 
67
        initprintf("animvpx: set rate to 30 fps (header says %d frames / %d seconds = %.03f fps).\n",
68
                   hdr->fpsnumer, hdr->fpsdenom, fps);
69
 
1933 helixhorne 70
        /* Don't know FPS for sure, and don't have readahead code
71
         * (yet?), so just default to 30fps.
72
         */
73
        hdr->fpsnumer = 30;
74
        hdr->fpsdenom = 1;
75
    }
76
 
77
    return 0;
78
}
79
 
80
////////// CODEC STUFF //////////
81
static void get_codec_error(animvpx_codec_ctx *codec)
82
{
83
    codec->errmsg_detail = vpx_codec_error_detail(&codec->codec);
84
    codec->errmsg = vpx_codec_error(&codec->codec);
85
}
86
 
87
// no checks for double-init!
7359 hendricks2 88
int32_t animvpx_init_codec(const animvpx_ivf_header_t *info, buildvfs_kfd inhandle, animvpx_codec_ctx *codec)
1933 helixhorne 89
{
90
    vpx_codec_dec_cfg_t cfg;
91
 
92
    cfg.threads = 1;
93
    cfg.w = info->width;
94
    cfg.h = info->height;
95
 
96
    codec->width = info->width;
97
    codec->height = info->height;
98
 
99
    //
100
    codec->inhandle = inhandle;
7079 terminx 101
    codec->pic = (uint8_t *)Xcalloc(info->width*info->height,4);
1933 helixhorne 102
 
103
    codec->compbuflen = codec->compbufallocsiz = 0;
104
    codec->compbuf = NULL;
105
 
106
    codec->iter = NULL;
107
 
108
    if (codec->pic == NULL)
109
    {
110
        codec->initstate = -1;
111
        return 1;
112
    }
113
 
114
    if (vpx_codec_dec_init(&codec->codec, &vpx_codec_vp8_dx_algo, &cfg, 0))
115
    {
116
        get_codec_error(codec);
117
        codec->initstate = -1;
118
        return 1;
119
    }
120
 
121
    codec->initstate = 1;
122
    codec->decstate = 0;
123
 
124
    codec->errmsg_detail = codec->errmsg = NULL;
125
 
2832 helixhorne 126
    codec->numframes = 0;
127
    Bmemset(codec->sumtimes, 0, sizeof(codec->sumtimes));
128
    Bmemset(codec->maxtimes, 0, sizeof(codec->maxtimes));
129
 
1933 helixhorne 130
    return 0;
131
}
132
 
133
int32_t animvpx_uninit_codec(animvpx_codec_ctx *codec)
134
{
135
    if (codec->initstate <= 0)
136
        return 2;
137
 
5352 hendricks2 138
    DO_FREE_AND_NULL(codec->pic);
1933 helixhorne 139
 
140
    if (vpx_codec_destroy(&codec->codec))
141
    {
142
        get_codec_error(codec);
143
        codec->initstate = -2;
144
        return 1;
145
    }
146
 
147
    codec->initstate = 0;
148
 
149
    return 0;
150
}
151
 
152
////////// FRAME RETRIEVAL //////////
153
 
154
// read one IVF/VP8 frame, which may code multiple "picture-frames"
7359 hendricks2 155
static int32_t animvpx_read_frame(buildvfs_kfd inhandle, uint8_t **bufptr, uint32_t *bufsizptr, uint32_t *bufallocsizptr)
1933 helixhorne 156
{
157
#pragma pack(push,1)
158
    struct { uint32_t framesiz; uint64_t timestamp; } hdr;
159
#pragma pack(pop)
160
 
161
    if (kread(inhandle, &hdr, sizeof(hdr)) != sizeof(hdr))
162
        return 1;
163
 
164
    if (hdr.framesiz == 0)
165
        return 6;  // must be 6, see animvpx_nextpic_errmsg[]
166
 
167
//    OSD_Printf("frame size: %u\n", hdr.framesiz);
168
 
169
    if (!*bufptr)
170
    {
7079 terminx 171
        *bufptr = (uint8_t *)Xmalloc(hdr.framesiz);
1933 helixhorne 172
        if (!*bufptr)
173
            return 2;
174
        *bufallocsizptr = hdr.framesiz;
175
    }
176
    else if (*bufallocsizptr < hdr.framesiz)
177
    {
7079 terminx 178
        *bufptr = (uint8_t *)Xrealloc(*bufptr, hdr.framesiz);
1933 helixhorne 179
        if (!*bufptr)
180
            return 2;
181
        *bufallocsizptr = hdr.framesiz;
182
    }
183
 
184
    *bufsizptr = hdr.framesiz;
185
 
186
    if (kread(inhandle, *bufptr, hdr.framesiz) != (signed)hdr.framesiz)
187
        return 3;
188
 
189
    return 0;
190
}
191
 
192
const char *animvpx_nextpic_errmsg[] = {
193
    "All OK",
194
    "INTERNAL ERROR, animvpx_codec_ctx not initalized!",
195
    "OUT OF MEMORY",
196
    "couldn't read whole frame",
197
    "decoder error, couldn't decode frame",
198
    "picture dimension mismatch",
199
    "INTERNAL ERROR: read 0 frame length",
200
    "Failed getting corruption status (VP8D_GET_FRAME_CORRUPTED)"
201
};
202
 
203
// retrieves one picture-frame from the stream
204
//  pic format:  lines of [Y U V 0] pixels
205
//  *picptr==NULL means EOF has been reached
3341 helixhorne 206
#ifdef DEBUGGINGAIDS
207
ATTRIBUTE_OPTIMIZE("O1")
208
#else
209
ATTRIBUTE_OPTIMIZE("O3")
2042 helixhorne 210
#endif
1933 helixhorne 211
int32_t animvpx_nextpic(animvpx_codec_ctx *codec, uint8_t **picptr)
212
{
213
    int32_t ret, corrupted;
214
    vpx_image_t *img;
215
 
2832 helixhorne 216
    int32_t t[3];
217
 
1933 helixhorne 218
    if (codec->initstate <= 0)  // not inited or error
219
        return 1;
220
 
6828 terminx 221
    t[0] = timerGetTicks();
2832 helixhorne 222
 
1933 helixhorne 223
    if (codec->decstate == 0)  // first time / begin
224
    {
225
read_ivf_frame:
226
        corrupted = 0;
227
 
228
        ret = animvpx_read_frame(codec->inhandle, &codec->compbuf, &codec->compbuflen,
229
                                 &codec->compbufallocsiz);
230
        if (ret == 1)
231
        {
232
            // reached EOF
233
            *picptr = NULL;
234
            codec->decstate = 2;
235
            return 0;
236
        }
237
        else if (ret == 2 || ret == 3 || ret == 6)
238
        {
239
            *picptr = NULL;
240
            codec->decstate = -1;
241
            return ret;
242
        }
243
        // ^^^ keep in sync with all animvpx_read_frame() errors!
244
 
245
        // codec->compbuf now contains one IVF/VP8 frame
246
        codec->decstate = 1;
247
 
248
        // decode it!
249
        if (vpx_codec_decode(&codec->codec, codec->compbuf, codec->compbuflen, NULL, 0))
250
        {
251
            get_codec_error(codec);
252
            codec->decstate = -2;
253
            return 4;
254
        }
255
 
3026 helixhorne 256
// Compilation fix for Debian 6.0 (squeeze), which doesn't have
257
// VP8D_GET_FRAME_CORRUPTED.
258
// LibVPX doesn't seem to have a version #define, so we use the
259
// following one to determine conditional compilation.
260
#ifdef VPX_CODEC_CAP_ERROR_CONCEALMENT
1933 helixhorne 261
        if (vpx_codec_control(&codec->codec, VP8D_GET_FRAME_CORRUPTED, &corrupted))
262
        {
263
            get_codec_error(codec);
264
            codec->decstate = -2;
265
            return 7;
266
        }
3026 helixhorne 267
#endif
1933 helixhorne 268
        if (corrupted)
269
            OSD_Printf("warning: corrupted frame!\n");
270
    }
271
 
272
    img = vpx_codec_get_frame(&codec->codec, &codec->iter);
273
    if (img == NULL)
274
    {
275
        codec->iter = NULL;  // !
276
        goto read_ivf_frame;
277
    }
278
 
279
    if (img->d_w != codec->width || img->d_h != codec->height)
280
    {
281
        codec->decstate = -1;
282
        return 5;
283
    }
284
 
6828 terminx 285
    t[1] = timerGetTicks();
2832 helixhorne 286
 
4998 terminx 287
    uint8_t *const dstpic = codec->pic;
1933 helixhorne 288
 
4998 terminx 289
    uint8_t const *const yplane = img->planes[VPX_PLANE_Y];
290
    uint8_t const *const uplane = img->planes[VPX_PLANE_U];
291
    uint8_t const *const vplane = img->planes[VPX_PLANE_V];
2241 helixhorne 292
 
4998 terminx 293
    const int32_t ystride = img->stride[VPX_PLANE_Y];
294
    const int32_t ustride = img->stride[VPX_PLANE_U];
295
    const int32_t vstride = img->stride[VPX_PLANE_V];
2241 helixhorne 296
 
4998 terminx 297
    if (glinfo.glsl) /*** 3 planes --> packed conversion ***/
298
    {
5257 hendricks2 299
        vec2u_t const dim = { img->d_w, img->d_h };
2241 helixhorne 300
 
5257 hendricks2 301
        for (unsigned int y = 0; y < dim.y; y += 2)
2830 helixhorne 302
        {
5257 hendricks2 303
            unsigned int const y1 = y + 1;
304
            unsigned int const wy = dim.x * y;
305
            unsigned int const wy1 = dim.x * y1;
5244 terminx 306
 
5257 hendricks2 307
            for (unsigned int x = 0; x < dim.x; x += 2)
2241 helixhorne 308
            {
4998 terminx 309
                uint8_t u = uplane[ustride * (y >> 1) + (x >> 1)];
310
                uint8_t v = vplane[vstride * (y >> 1) + (x >> 1)];
2830 helixhorne 311
 
5244 terminx 312
                dstpic[(wy + x) << 2] = yplane[ystride * y + x];
313
                dstpic[(wy + x + 1) << 2] = yplane[ystride * y + x + 1];
314
                dstpic[(wy1 + x) << 2] = yplane[ystride * y1 + x];
315
                dstpic[(wy1 + x + 1) << 2] = yplane[ystride * y1 + x + 1];
2830 helixhorne 316
 
5244 terminx 317
                dstpic[((wy + x) << 2) + 1] = u;
318
                dstpic[((wy + x + 1) << 2) + 1] = u;
319
                dstpic[((wy1 + x) << 2) + 1] = u;
320
                dstpic[((wy1 + x + 1) << 2) + 1] = u;
2830 helixhorne 321
 
5244 terminx 322
                dstpic[((wy + x) << 2) + 2] = v;
323
                dstpic[((wy + x + 1) << 2) + 2] = v;
324
                dstpic[((wy1 + x) << 2) + 2] = v;
325
                dstpic[((wy1 + x + 1) << 2) + 2] = v;
2241 helixhorne 326
            }
2830 helixhorne 327
        }
2241 helixhorne 328
    }
4998 terminx 329
    else /*** 3 planes --> packed conversion (RGB) ***/
330
    {
331
        int i = 0;
2241 helixhorne 332
 
4998 terminx 333
        for (unsigned int imgY = 0; imgY < img->d_h; imgY++)
334
        {
335
            for (unsigned int imgX = 0; imgX < img->d_w; imgX++)
336
            {
337
                uint8_t const y = yplane[imgY * ystride + imgX];
338
                uint8_t const u = uplane[(imgY >> 1) * ustride + (imgX >> 1)];
339
                uint8_t const v = vplane[(imgY >> 1) * vstride + (imgX >> 1)];
340
 
341
                int const c = y - 16;
342
                int const d = (u + -128);
343
                int const e = (v + -128);
344
                int const c298 = c * 298;
345
 
346
                dstpic[i + 0] = (uint8_t)clamp((c298 + 409 * e - -128) >> 8, 0, 255);
347
                dstpic[i + 1] = (uint8_t)clamp((c298 - 100 * d - 208 * e - -128) >> 8, 0, 255);
348
                dstpic[i + 2] = (uint8_t)clamp((c298 + 516 * d - -128) >> 8, 0, 255);
349
 
350
                i += 3;
351
            }
352
        }
353
    }
354
 
6828 terminx 355
    t[2] = timerGetTicks();
2832 helixhorne 356
 
357
    codec->sumtimes[0] += t[1]-t[0];
358
    codec->sumtimes[1] += t[2]-t[1];
359
 
360
    codec->maxtimes[0] = max(codec->maxtimes[0], t[1]-t[0]);
361
    codec->maxtimes[1] = max(codec->maxtimes[0], t[2]-t[1]);
362
 
1933 helixhorne 363
    *picptr = codec->pic;
364
    return 0;
365
}
366
 
367
 
368
/////////////// DRAWING! ///////////////
1943 helixhorne 369
static GLuint texname = 0;
1933 helixhorne 370
static int32_t texuploaded;
371
 
5526 hendricks2 372
#ifdef USE_GLEXT
1933 helixhorne 373
// YUV->RGB conversion fragment shader adapted from
374
// http://www.fourcc.org/fccyvrgb.php: "Want some sample code?"
375
// direct link: http://www.fourcc.org/source/YUV420P-OpenGL-GLSLang.c
5540 terminx 376
static const char *fragprog_src =
1933 helixhorne 377
    "#version 120\n"
378
 
379
    "uniform sampler2D tex;\n"
380
 
381
    "void main(void) {\n"
382
 
383
    "  float r,g,b,y,u,v;\n"
384
    "  vec3 yuv;\n"
385
 
386
    "  yuv = texture2D(tex, gl_TexCoord[0].st).rgb;\n"
387
    "  y = yuv.r;\n"
388
    "  u = yuv.g;\n"
389
    "  v = yuv.b;\n"
390
 
391
    "  y = 1.1643*(y-0.0625);\n"
392
    "  u = u-0.5;\n"
393
    "  v = v-0.5;\n"
394
 
395
    "  r = y + 1.5958*v;\n"
396
    "  g = y - 0.39173*u - 0.81290*v;\n"
397
    "  b = y + 2.017*u;\n"
398
 
399
    "  gl_FragColor = vec4(r,g,b,1.0);\n"
400
    "}\n";
5526 hendricks2 401
#endif
1933 helixhorne 402
 
6552 hendricks2 403
void animvpx_setup_glstate(int32_t animvpx_flags)
1933 helixhorne 404
{
5526 hendricks2 405
#ifdef USE_GLEXT
4998 terminx 406
    if (glinfo.glsl)
407
    {
408
        GLint gli;
6656 pogokeen 409
        GLuint FSHandle, PHandle;
4998 terminx 410
        static char logbuf[512];
1933 helixhorne 411
 
4998 terminx 412
        // first, compile the fragment shader
413
        /* Set up program objects. */
6656 pogokeen 414
        PHandle = glCreateProgram();
415
        FSHandle = glCreateShader(GL_FRAGMENT_SHADER);
1933 helixhorne 416
 
4998 terminx 417
        /* Compile the shader. */
6656 pogokeen 418
        glShaderSource(FSHandle, 1, (const GLchar **)&fragprog_src, NULL);
419
        glCompileShader(FSHandle);
1933 helixhorne 420
 
4998 terminx 421
        /* Print the compilation log. */
6656 pogokeen 422
        glGetShaderiv(FSHandle, GL_COMPILE_STATUS, &gli);
423
        glGetShaderInfoLog(FSHandle, sizeof(logbuf), NULL, logbuf);
4998 terminx 424
        if (logbuf[0])
425
            OSD_Printf("animvpx compile log: %s\n", logbuf);
1933 helixhorne 426
 
4998 terminx 427
        /* Create a complete program object. */
6656 pogokeen 428
        glAttachShader(PHandle, FSHandle);
429
        glLinkProgram(PHandle);
1933 helixhorne 430
 
4998 terminx 431
        /* And print the link log. */
6656 pogokeen 432
        glGetProgramInfoLog(PHandle, sizeof(logbuf), NULL, logbuf);
4998 terminx 433
        if (logbuf[0])
434
            OSD_Printf("animvpx link log: %s\n", logbuf);
1933 helixhorne 435
 
4998 terminx 436
        /* Finally, use the program. */
8713 terminx 437
        polymost_useShaderProgram(PHandle);
4998 terminx 438
    }
5526 hendricks2 439
#endif
1933 helixhorne 440
 
441
    ////////// GL STATE //////////
442
 
8711 terminx 443
    glViewport(0,0,xdim,ydim);
1933 helixhorne 444
 
6656 pogokeen 445
    glMatrixMode(GL_MODELVIEW);
446
    glLoadIdentity();
1933 helixhorne 447
 
6656 pogokeen 448
    glMatrixMode(GL_PROJECTION);
449
    glLoadIdentity();
1933 helixhorne 450
 
6656 pogokeen 451
    glMatrixMode(GL_TEXTURE);
452
    glLoadIdentity();
1933 helixhorne 453
 
6656 pogokeen 454
//    glPushAttrib(GL_ENABLE_BIT);
455
    glDisable(GL_ALPHA_TEST);
456
    glDisable(GL_DEPTH_TEST);
457
    glDisable(GL_BLEND);
458
    glDisable(GL_CULL_FACE);
1933 helixhorne 459
 
5526 hendricks2 460
#ifdef USE_GLEXT
6656 pogokeen 461
    glActiveTexture(GL_TEXTURE0);
5526 hendricks2 462
#endif
6656 pogokeen 463
    glGenTextures(1, &texname);
464
    glBindTexture(GL_TEXTURE_2D, texname);
1933 helixhorne 465
 
6656 pogokeen 466
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
467
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glinfo.clamptoedge?GL_CLAMP_TO_EDGE:GL_CLAMP);
6552 hendricks2 468
    if ((animvpx_flags & CUTSCENE_TEXTUREFILTER && gltexfiltermode == TEXFILTER_ON) || animvpx_flags & CUTSCENE_FORCEFILTER ||
469
    (!(animvpx_flags & CUTSCENE_TEXTUREFILTER) && !(animvpx_flags & CUTSCENE_FORCENOFILTER))) // if no flags, then use filter for IVFs
470
    {
6656 pogokeen 471
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
472
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
6552 hendricks2 473
    }
474
    else
475
    {
6656 pogokeen 476
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
477
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6552 hendricks2 478
    }
1933 helixhorne 479
 
480
    texuploaded = 0;
481
    ////////////////////
482
 
6656 pogokeen 483
    glClearColor(0.0,0.0,0.0,1.0);
484
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
1933 helixhorne 485
}
486
 
487
void animvpx_restore_glstate(void)
488
{
5526 hendricks2 489
#ifdef USE_GLEXT
4998 terminx 490
    if (glinfo.glsl)
6776 pogokeen 491
    {
8713 terminx 492
        polymost_useShaderProgram(0);
6776 pogokeen 493
        polymost_resetProgram();
494
    }
5526 hendricks2 495
#endif
1933 helixhorne 496
 
6656 pogokeen 497
//    glPopAttrib();
1933 helixhorne 498
 
6656 pogokeen 499
    glDeleteTextures(1, &texname);
1943 helixhorne 500
    texname = 0;
1933 helixhorne 501
    texuploaded = 0;
502
}
503
 
6551 hendricks2 504
int32_t animvpx_render_frame(animvpx_codec_ctx *codec, double animvpx_aspect)
1933 helixhorne 505
{
6828 terminx 506
    int32_t t = timerGetTicks();
2832 helixhorne 507
 
1933 helixhorne 508
    if (codec->initstate <= 0)  // not inited or error
509
        return 1;
510
 
511
    if (codec->pic == NULL)
512
        return 2;  // shouldn't happen
513
 
4998 terminx 514
    int fmt = glinfo.glsl ? GL_RGBA : GL_RGB;
515
 
1933 helixhorne 516
    if (!texuploaded)
517
    {
6656 pogokeen 518
        glTexImage2D(GL_TEXTURE_2D, 0, fmt, codec->width,codec->height,
4998 terminx 519
                     0, fmt, GL_UNSIGNED_BYTE, codec->pic);
6656 pogokeen 520
        if (glGetError() != GL_NO_ERROR) return 1;
1933 helixhorne 521
        texuploaded = 1;
522
    }
523
    else
524
    {
6656 pogokeen 525
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, codec->width,codec->height,
4998 terminx 526
                        fmt, GL_UNSIGNED_BYTE, codec->pic);
6656 pogokeen 527
        if (glGetError() != GL_NO_ERROR) return 1;
1933 helixhorne 528
    }
529
 
4998 terminx 530
    float vid_wbyh = ((float)codec->width)/codec->height;
6551 hendricks2 531
    if (animvpx_aspect > 0)
532
        vid_wbyh = animvpx_aspect;
4998 terminx 533
    float scr_wbyh = ((float)xdim)/ydim;
1933 helixhorne 534
 
4998 terminx 535
    float x=1.0, y=1.0;
1933 helixhorne 536
#if 1
4998 terminx 537
    // aspect correction by pillarboxing/letterboxing
538
    // TODO: fullscreen? can't assume square pixels there
539
    if (vid_wbyh != scr_wbyh)
540
    {
541
        if (vid_wbyh < scr_wbyh)
542
            x = vid_wbyh/scr_wbyh;
543
        else
544
            y = scr_wbyh/vid_wbyh;
545
    }
1933 helixhorne 546
#endif
6656 pogokeen 547
    glBegin(GL_QUADS);
1933 helixhorne 548
 
4998 terminx 549
    if (!glinfo.glsl)
6656 pogokeen 550
        glColor3f(1.0, 1.0, 1.0);
1933 helixhorne 551
 
6656 pogokeen 552
    glTexCoord2f(0.0,1.0);
553
    glVertex3f(-x, -y, 0.0);
1933 helixhorne 554
 
6656 pogokeen 555
    glTexCoord2f(0.0,0.0);
556
    glVertex3f(-x, y, 0.0);
1933 helixhorne 557
 
6656 pogokeen 558
    glTexCoord2f(1.0,0.0);
559
    glVertex3f(x, y, 0.0);
1933 helixhorne 560
 
6656 pogokeen 561
    glTexCoord2f(1.0,1.0);
562
    glVertex3f(x, -y, 0.0);
1933 helixhorne 563
 
6656 pogokeen 564
    glEnd();
4998 terminx 565
 
6828 terminx 566
    t = timerGetTicks()-t;
2832 helixhorne 567
    codec->sumtimes[2] += t;
568
    codec->maxtimes[2] = max(codec->maxtimes[2], t);
569
    codec->numframes++;
570
 
1933 helixhorne 571
    return 0;
572
}
2832 helixhorne 573
 
574
void animvpx_print_stats(const animvpx_codec_ctx *codec)
575
{
576
    if (codec->numframes != 0)
577
    {
578
        const int32_t *s = codec->sumtimes;
579
        const int32_t *m = codec->maxtimes;
580
        int32_t n = codec->numframes;
581
 
4998 terminx 582
        if (glinfo.glsl)
583
            initprintf("animvpx: GLSL mode\n");
584
 
2832 helixhorne 585
        initprintf("VP8 timing stats (mean, max) [ms] for %d frames:\n"
586
                   " read and decode frame: %.02f, %d\n"
587
                   " 3 planes -> packed conversion: %.02f, %d\n"
588
                   " upload and display: %.02f, %d\n",
589
                   n, (double)s[0]/n, m[0], (double)s[1]/n, m[1], (double)s[2]/n, m[2]);
590
    }
591
}
4320 hendricks2 592
 
593
#endif