1 /********************************************************************
3 * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
11 ********************************************************************
13 function: routines for validating encoder granulepos generation
14 last mod: $Id: granulepos.c 16503 2009-08-22 18:14:02Z giles $
16 ********************************************************************/
19 #include <theora/theoraenc.h>
24 static int ilog(unsigned int v){
34 granulepos_test_encode (int frequency)
39 int frame, tframe, keyframe, keydist;
43 unsigned char *framedata;
45 long long int last_granule = -1;
47 /* INFO ("+ Initializing th_info struct"); */
52 ti.pic_width = ti.frame_width;
53 ti.pic_height = ti.frame_height;
56 ti.fps_numerator = 16;
57 ti.fps_denominator = 1;
58 ti.aspect_numerator = 1;
59 ti.aspect_denominator = 1;
60 ti.colorspace = TH_CS_UNSPECIFIED;
61 ti.pixel_fmt = TH_PF_420;
63 ti.keyframe_granule_shift=ilog(frequency);
65 /* INFO ("+ Allocating encoder context"); */
66 te = th_encode_alloc(&ti);
68 INFO ("+ Clearing th_info");
70 FAIL ("negative return code initializing encoder");
73 /* INFO ("+ Setting up dummy 4:2:0 frame data"); */
74 framedata = calloc(ti.frame_height, ti.frame_width);
75 yuv[0].width = ti.frame_width;
76 yuv[0].height = ti.frame_height;
77 yuv[0].stride = ti.frame_width;
78 yuv[0].data = framedata;
79 yuv[1].width = ti.frame_width / 2;
80 yuv[1].height = ti.frame_width / 2;
81 yuv[1].stride = ti.frame_width;
82 yuv[1].data = framedata;
83 yuv[2].width = ti.frame_width / 2;
84 yuv[2].height = ti.frame_width / 2;
85 yuv[2].stride = ti.frame_width;
86 yuv[2].data = framedata;
88 INFO ("+ Checking granulepos generation");
89 shift = ti.keyframe_granule_shift;
90 rate = (double)ti.fps_denominator/ti.fps_numerator;
91 for (frame = 0; frame < frequency * 2 + 1; frame++) {
92 result = th_encode_ycbcr_in (te, yuv);
94 printf("th_encode_ycbcr_in() returned %d\n", result);
95 FAIL ("negative error code submitting frame for compression");
97 result = th_encode_packetout (te, frame >= frequency * 2, &op);
99 printf("th_encode_packetout() returned %d\n", result);
100 FAIL("failed to retrieve compressed frame");
102 if ((long long int)op.granulepos < last_granule)
103 FAIL ("encoder returned a decreasing granulepos value");
104 last_granule = op.granulepos;
105 keyframe = op.granulepos >> shift;
106 keydist = op.granulepos - (keyframe << shift);
107 tframe = th_granule_frame (te, op.granulepos);
108 ttime = th_granule_time(te, op.granulepos);
110 printf("++ frame %d granulepos %lld %d:%d %d %.3lfs\n",
111 frame, (long long int)op.granulepos, keyframe, keydist,
112 tframe, th_granule_time (te, op.granulepos));
114 /* granulepos stores the frame count */
115 if ((keyframe + keydist) != frame + 1)
116 FAIL ("encoder granulepos does not map to the correct frame number");
117 /* th_granule_frame() returns the frame index */
119 FAIL ("th_granule_frame() returned incorrect results");
120 /* th_granule_time() returns the end time */
121 if (fabs(rate*(frame+1) - ttime) > 1.0e-6)
122 FAIL ("th_granule_time() returned incorrect results");
126 /* INFO ("+ Freeing dummy frame data"); */
129 /* INFO ("+ Clearing th_info struct"); */
132 /* INFO ("+ Freeing encoder context"); */
138 int main(int argc, char *argv[])
141 granulepos_test_encode (1);
142 granulepos_test_encode (2);
143 granulepos_test_encode (3);
144 granulepos_test_encode (4);
145 granulepos_test_encode (8);
146 granulepos_test_encode (64);