1 /*
2 Copyright (C) 2003 Commonwealth Scientific and Industrial Research
3 Organisation (CSIRO) Australia
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
9 - Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
12 - Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 - Neither the name of CSIRO Australia nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include "config.h"
34
35 #include "oggz_private.h"
36
37 #include "oggz/oggz_stream.h"
38
39 static ogg_int64_t
oggz_metric_dirac(OGGZ * oggz,long serialno,ogg_int64_t granulepos,void * user_data)40 oggz_metric_dirac (OGGZ * oggz, long serialno,
41 ogg_int64_t granulepos, void * user_data)
42 {
43 oggz_stream_t * stream;
44 ogg_int64_t iframe, pframe;
45 ogg_uint32_t pt;
46 ogg_uint16_t dist;
47 ogg_uint16_t delay;
48 ogg_int64_t dt;
49 ogg_int64_t units;
50
51 stream = oggz_get_stream (oggz, serialno);
52 if (stream == NULL) return -1;
53
54 iframe = granulepos >> stream->granuleshift;
55 pframe = granulepos - (iframe << stream->granuleshift);
56 pt = (iframe + pframe) >> 9;
57 delay = pframe >> 9;
58 dt = (ogg_int64_t)pt - delay;
59
60 units = dt * stream->granulerate_d / stream->granulerate_n;
61
62 #ifdef DEBUG
63 printf ("oggz_..._granuleshift: serialno %010lu Got frame or field %lld (%lld + %lld): %lld units\n",
64 serialno, dt, iframe, pframe, units);
65 #endif
66
67 return units;
68 }
69
70 static ogg_int64_t
oggz_metric_default_granuleshift(OGGZ * oggz,long serialno,ogg_int64_t granulepos,void * user_data)71 oggz_metric_default_granuleshift (OGGZ * oggz, long serialno,
72 ogg_int64_t granulepos, void * user_data)
73 {
74 oggz_stream_t * stream;
75 ogg_int64_t iframe, pframe;
76 ogg_int64_t units;
77
78 stream = oggz_get_stream (oggz, serialno);
79 if (stream == NULL) return -1;
80
81 iframe = granulepos >> stream->granuleshift;
82 pframe = granulepos - (iframe << stream->granuleshift);
83 granulepos = iframe + pframe;
84 if (granulepos > 0) granulepos -= stream->first_granule;
85
86 units = granulepos * stream->granulerate_d / stream->granulerate_n;
87
88 #ifdef DEBUG
89 printf ("oggz_..._granuleshift: serialno %010lu Got frame %lld (%lld + %lld): %lld units\n",
90 serialno, granulepos, iframe, pframe, units);
91 #endif
92
93 return units;
94 }
95
96 static ogg_int64_t
oggz_metric_default_linear(OGGZ * oggz,long serialno,ogg_int64_t granulepos,void * user_data)97 oggz_metric_default_linear (OGGZ * oggz, long serialno, ogg_int64_t granulepos,
98 void * user_data)
99 {
100 oggz_stream_t * stream;
101
102 stream = oggz_get_stream (oggz, serialno);
103 if (stream == NULL) return -1;
104
105 return (stream->granulerate_d * granulepos / stream->granulerate_n);
106 }
107
108 static int
oggz_metric_update(OGGZ * oggz,long serialno)109 oggz_metric_update (OGGZ * oggz, long serialno)
110 {
111 oggz_stream_t * stream;
112
113 if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
114
115 stream = oggz_get_stream (oggz, serialno);
116 if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
117
118 /* we divide by the granulerate, ie. mult by gr_d/gr_n, so ensure
119 * numerator is non-zero */
120 if (stream->granulerate_n == 0) {
121 stream->granulerate_n= 1;
122 stream->granulerate_d = 0;
123 }
124
125 if (stream->granuleshift == 0) {
126 return oggz_set_metric_internal (oggz, serialno,
127 oggz_metric_default_linear,
128 NULL, 1);
129 } else if (oggz_stream_get_content (oggz, serialno) == OGGZ_CONTENT_DIRAC) {
130 return oggz_set_metric_internal (oggz, serialno,
131 oggz_metric_dirac,
132 NULL, 1);
133 } else {
134 return oggz_set_metric_internal (oggz, serialno,
135 oggz_metric_default_granuleshift,
136 NULL, 1);
137 }
138 }
139
140 int
oggz_set_granuleshift(OGGZ * oggz,long serialno,int granuleshift)141 oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift)
142 {
143 oggz_stream_t * stream;
144
145 if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
146
147 stream = oggz_get_stream (oggz, serialno);
148 if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
149
150 stream->granuleshift = granuleshift;
151
152 return oggz_metric_update (oggz, serialno);
153 }
154
155 int
oggz_get_granuleshift(OGGZ * oggz,long serialno)156 oggz_get_granuleshift (OGGZ * oggz, long serialno)
157 {
158 oggz_stream_t * stream;
159
160 if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
161
162 stream = oggz_get_stream (oggz, serialno);
163 if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
164
165 return stream->granuleshift;
166 }
167
168 int
oggz_set_granulerate(OGGZ * oggz,long serialno,ogg_int64_t granule_rate_numerator,ogg_int64_t granule_rate_denominator)169 oggz_set_granulerate (OGGZ * oggz, long serialno,
170 ogg_int64_t granule_rate_numerator,
171 ogg_int64_t granule_rate_denominator)
172 {
173 oggz_stream_t * stream;
174
175 if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
176
177 stream = oggz_get_stream (oggz, serialno);
178 if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
179
180 stream->granulerate_n = granule_rate_numerator;
181 stream->granulerate_d = granule_rate_denominator;
182
183 return oggz_metric_update (oggz, serialno);
184 }
185
186 int
oggz_get_granulerate(OGGZ * oggz,long serialno,ogg_int64_t * granulerate_n,ogg_int64_t * granulerate_d)187 oggz_get_granulerate (OGGZ * oggz, long serialno,
188 ogg_int64_t * granulerate_n,
189 ogg_int64_t * granulerate_d)
190 {
191 oggz_stream_t * stream;
192
193 if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
194
195 stream = oggz_get_stream (oggz, serialno);
196 if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
197
198 *granulerate_n = stream->granulerate_n;
199 *granulerate_d = stream->granulerate_d / OGGZ_AUTO_MULT;
200
201 return 0;
202 }
203
204 int
oggz_set_first_granule(OGGZ * oggz,long serialno,ogg_int64_t first_granule)205 oggz_set_first_granule (OGGZ * oggz, long serialno,
206 ogg_int64_t first_granule)
207 {
208 oggz_stream_t * stream;
209
210 if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
211
212 stream = oggz_get_stream (oggz, serialno);
213 if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
214
215 stream->first_granule = first_granule;
216
217 return oggz_metric_update (oggz, serialno);
218 }
219
220 /** DEPRECATED **/
221 int
oggz_set_metric_linear(OGGZ * oggz,long serialno,ogg_int64_t granule_rate_numerator,ogg_int64_t granule_rate_denominator)222 oggz_set_metric_linear (OGGZ * oggz, long serialno,
223 ogg_int64_t granule_rate_numerator,
224 ogg_int64_t granule_rate_denominator)
225 {
226 oggz_stream_t * stream;
227
228 if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
229
230 stream = oggz_get_stream (oggz, serialno);
231 if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
232
233 stream->granulerate_n = granule_rate_numerator;
234 stream->granulerate_d = granule_rate_denominator;
235 stream->granuleshift = 0;
236
237 return oggz_metric_update (oggz, serialno);
238 }
239
240