Git init
[external/libtheora.git] / tests / granulepos_theora.c
1 /********************************************************************
2  *                                                                  *
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.       *
7  *                                                                  *
8  * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
9  * by the Xiph.Org Foundation http://www.xiph.org/                  *
10  *                                                                  *
11  ********************************************************************
12
13   function: routines for validating encoder granulepos generation
14   last mod: $Id: granulepos_theora.c 16503 2009-08-22 18:14:02Z giles $
15
16  ********************************************************************/
17
18 #include <stdlib.h>
19 #include <theora/theora.h>
20 #include <math.h>
21
22 #include "tests.h"
23
24 static int ilog(unsigned int v){
25   int ret=0;
26   while(v){
27     ret++;
28     v>>=1;
29   }
30   return(ret);
31 }
32
33 static int
34 granulepos_test_encode (int frequency, int auto_p)
35 {
36   theora_info ti;
37   theora_state th;
38   int result;
39   int frame, tframe, keyframe, keydist;
40   int shift;
41   double rate, ttime;
42   yuv_buffer yuv;
43   unsigned char *framedata;
44   ogg_packet op;
45   long long int last_granule = -1;
46
47 /*  INFO ("+ Initializing theora_info struct"); */
48   theora_info_init (&ti);
49
50   ti.width = 32;
51   ti.height = 32;
52   ti.frame_width = ti.width;
53   ti.frame_height = ti.frame_height;
54   ti.offset_x = 0;
55   ti.offset_y = 0;
56   ti.fps_numerator = 16;
57   ti.fps_denominator = 1;
58   ti.aspect_numerator = 1;
59   ti.aspect_denominator = 1;
60   ti.colorspace = OC_CS_UNSPECIFIED;
61   ti.pixelformat = OC_PF_420;
62   ti.target_bitrate = 0;
63   ti.quality = 16;
64
65   ti.dropframes_p = 0;
66   ti.quick_p = 1;
67
68   /* check variations of automatic or forced keyframe choice */
69   ti.keyframe_auto_p = auto_p;
70   /* check with variations of the maximum gap */
71   ti.keyframe_frequency = frequency;
72   ti.keyframe_frequency_force = frequency;
73
74   ti.keyframe_data_target_bitrate = ti.target_bitrate * 1.5;
75   ti.keyframe_auto_threshold = 80;
76   ti.keyframe_mindistance = MIN(8, frequency);
77   ti.noise_sensitivity = 1;
78
79 /*  INFO ("+ Initializing theora_state for encoding"); */
80   result = theora_encode_init (&th, &ti);
81   if (result == OC_DISABLED) {
82     INFO ("+ Clearing theora_state");
83     theora_clear (&th);
84   } else if (result < 0) {
85     FAIL ("negative return code initializing encoder");
86   }
87
88 /*  INFO ("+ Setting up dummy 4:2:0 frame data"); */
89   framedata = calloc(ti.height, ti.width);
90   yuv.y_width = ti.width;
91   yuv.y_height = ti.height;
92   yuv.y_stride = ti.width;
93   yuv.y = framedata;
94   yuv.uv_width = ti.width / 2;
95   yuv.uv_height = ti.width / 2;
96   yuv.uv_stride = ti.width;
97   yuv.u = framedata;
98   yuv.v = framedata;
99
100   INFO ("+ Checking granulepos generation");
101   shift = theora_granule_shift(&ti);
102   rate = (double)ti.fps_denominator/ti.fps_numerator;
103   for (frame = 0; frame < frequency * 2 + 1; frame++) {
104     result = theora_encode_YUVin (&th, &yuv);
105     if (result < 0) {
106       printf("theora_encode_YUVin() returned %d\n", result);
107       FAIL ("negative error code submitting frame for compression");
108     }
109     theora_encode_packetout (&th, frame >= frequency * 2, &op);
110     if ((long long int)op.granulepos < last_granule)
111       FAIL ("encoder returned a decreasing granulepos value");
112     last_granule = op.granulepos;
113     keyframe = op.granulepos >> shift;
114     keydist = op.granulepos - (keyframe << shift);
115     tframe = theora_granule_frame (&th, op.granulepos);
116     ttime = theora_granule_time(&th, op.granulepos);
117 #if DEBUG
118     printf("++ frame %d granulepos %lld %d:%d %d %.3lfs\n", 
119         frame, (long long int)op.granulepos, keyframe, keydist,
120         tframe, theora_granule_time (&th, op.granulepos));
121 #endif
122     if ((keyframe + keydist) != frame + 1)
123       FAIL ("encoder granulepos does not map to the correct frame number");
124     if (tframe != frame)
125       FAIL ("theora_granule_frame returned incorrect results");
126     if (fabs(rate*(frame+1) - ttime) > 1.0e-6)
127       FAIL ("theora_granule_time returned incorrect results");
128   }
129
130   /* clean up */
131 /*  INFO ("+ Freeing dummy frame data"); */
132   free (framedata);
133
134 /*  INFO ("+ Clearing theora_info struct"); */
135   theora_info_clear (&ti);
136
137 /*  INFO ("+ Clearing theora_state"); */
138   theora_clear (&th);
139
140   return 0;
141 }
142
143 int main(int argc, char *argv[])
144 {
145
146   granulepos_test_encode (1, 1);
147   granulepos_test_encode (2, 1);
148   granulepos_test_encode (3, 1);
149   granulepos_test_encode (4, 1);
150   granulepos_test_encode (8, 1);
151   granulepos_test_encode (64, 1);
152
153   exit (0);
154 }