diff options
Diffstat (limited to 'tests/granulepos.c')
-rw-r--r-- | tests/granulepos.c | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/tests/granulepos.c b/tests/granulepos.c new file mode 100644 index 0000000..a81dea8 --- /dev/null +++ b/tests/granulepos.c @@ -0,0 +1,149 @@ +/******************************************************************** + * * + * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * + * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: routines for validating encoder granulepos generation + last mod: $Id: granulepos.c 16503 2009-08-22 18:14:02Z giles $ + + ********************************************************************/ + +#include <stdlib.h> +#include <theora/theoraenc.h> +#include <math.h> + +#include "tests.h" + +static int ilog(unsigned int v){ + int ret=0; + while(v){ + ret++; + v>>=1; + } + return(ret); +} + +static int +granulepos_test_encode (int frequency) +{ + th_info ti; + th_enc_ctx *te; + int result; + int frame, tframe, keyframe, keydist; + int shift; + double rate, ttime; + th_ycbcr_buffer yuv; + unsigned char *framedata; + ogg_packet op; + long long int last_granule = -1; + +/* INFO ("+ Initializing th_info struct"); */ + th_info_init (&ti); + + ti.frame_width = 32; + ti.frame_height = 32; + ti.pic_width = ti.frame_width; + ti.pic_height = ti.frame_height; + ti.pic_x = 0; + ti.pic_y = 0; + ti.fps_numerator = 16; + ti.fps_denominator = 1; + ti.aspect_numerator = 1; + ti.aspect_denominator = 1; + ti.colorspace = TH_CS_UNSPECIFIED; + ti.pixel_fmt = TH_PF_420; + ti.quality = 16; + ti.keyframe_granule_shift=ilog(frequency); + +/* INFO ("+ Allocating encoder context"); */ + te = th_encode_alloc(&ti); + if (te == NULL) { + INFO ("+ Clearing th_info"); + th_info_clear(&ti); + FAIL ("negative return code initializing encoder"); + } + +/* INFO ("+ Setting up dummy 4:2:0 frame data"); */ + framedata = calloc(ti.frame_height, ti.frame_width); + yuv[0].width = ti.frame_width; + yuv[0].height = ti.frame_height; + yuv[0].stride = ti.frame_width; + yuv[0].data = framedata; + yuv[1].width = ti.frame_width / 2; + yuv[1].height = ti.frame_width / 2; + yuv[1].stride = ti.frame_width; + yuv[1].data = framedata; + yuv[2].width = ti.frame_width / 2; + yuv[2].height = ti.frame_width / 2; + yuv[2].stride = ti.frame_width; + yuv[2].data = framedata; + + INFO ("+ Checking granulepos generation"); + shift = ti.keyframe_granule_shift; + rate = (double)ti.fps_denominator/ti.fps_numerator; + for (frame = 0; frame < frequency * 2 + 1; frame++) { + result = th_encode_ycbcr_in (te, yuv); + if (result < 0) { + printf("th_encode_ycbcr_in() returned %d\n", result); + FAIL ("negative error code submitting frame for compression"); + } + result = th_encode_packetout (te, frame >= frequency * 2, &op); + if (result <= 0) { + printf("th_encode_packetout() returned %d\n", result); + FAIL("failed to retrieve compressed frame"); + } + if ((long long int)op.granulepos < last_granule) + FAIL ("encoder returned a decreasing granulepos value"); + last_granule = op.granulepos; + keyframe = op.granulepos >> shift; + keydist = op.granulepos - (keyframe << shift); + tframe = th_granule_frame (te, op.granulepos); + ttime = th_granule_time(te, op.granulepos); +#if DEBUG + printf("++ frame %d granulepos %lld %d:%d %d %.3lfs\n", + frame, (long long int)op.granulepos, keyframe, keydist, + tframe, th_granule_time (te, op.granulepos)); +#endif + /* granulepos stores the frame count */ + if ((keyframe + keydist) != frame + 1) + FAIL ("encoder granulepos does not map to the correct frame number"); + /* th_granule_frame() returns the frame index */ + if (tframe != frame) + FAIL ("th_granule_frame() returned incorrect results"); + /* th_granule_time() returns the end time */ + if (fabs(rate*(frame+1) - ttime) > 1.0e-6) + FAIL ("th_granule_time() returned incorrect results"); + } + + /* clean up */ +/* INFO ("+ Freeing dummy frame data"); */ + free(framedata); + +/* INFO ("+ Clearing th_info struct"); */ + th_info_clear(&ti); + +/* INFO ("+ Freeing encoder context"); */ + th_encode_free(te); + + return 0; +} + +int main(int argc, char *argv[]) +{ + + granulepos_test_encode (1); + granulepos_test_encode (2); + granulepos_test_encode (3); + granulepos_test_encode (4); + granulepos_test_encode (8); + granulepos_test_encode (64); + + exit (0); +} |