Subversion Repositories eduke32

Rev

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