root/liboggz/trunk/src/liboggz/metric_internal.c

Revision 3801, 6.2 kB (checked in by conrad, 2 weeks ago)

metric_internal: add a custom metric for Dirac. This moves the Dirac
granulepos handling (specifically the shift of (iframe+pframe)>>9)
to where it is more generally used for converting granulepos to time.
Now oggz merge and oggz sort seem to handle Dirac; please test.

Line 
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 static ogg_int64_t
38 oggz_metric_dirac (OGGZ * oggz, long serialno,
39                    ogg_int64_t granulepos, void * user_data)
40 {
41   oggz_stream_t * stream;
42   ogg_int64_t iframe, pframe;
43   ogg_uint32_t pt;
44   ogg_uint16_t dist;
45   ogg_uint16_t delay;
46   ogg_int64_t dt;
47   ogg_int64_t units;
48
49   stream = oggz_get_stream (oggz, serialno);
50   if (stream == NULL) return -1;
51
52   iframe = granulepos >> stream->granuleshift;
53   pframe = granulepos - (iframe << stream->granuleshift);
54   pt = (iframe + pframe) >> 9;
55   delay = pframe >> 9;
56   dt = (int64_t)pt - delay;
57
58   units = dt * stream->granulerate_d / stream->granulerate_n;
59
60 #ifdef DEBUG
61   printf ("oggz_..._granuleshift: serialno %010ld Got frame or field %lld (%lld + %lld): %lld units\n",
62           serialno, dt, iframe, pframe, units);
63 #endif
64
65   return units;
66 }
67
68 static ogg_int64_t
69 oggz_metric_default_granuleshift (OGGZ * oggz, long serialno,
70                                   ogg_int64_t granulepos, void * user_data)
71 {
72   oggz_stream_t * stream;
73   ogg_int64_t iframe, pframe;
74   ogg_int64_t units;
75
76   stream = oggz_get_stream (oggz, serialno);
77   if (stream == NULL) return -1;
78
79   iframe = granulepos >> stream->granuleshift;
80   pframe = granulepos - (iframe << stream->granuleshift);
81   granulepos = (iframe + pframe);
82
83   units = granulepos * stream->granulerate_d / stream->granulerate_n;
84
85 #ifdef DEBUG
86   printf ("oggz_..._granuleshift: serialno %010ld Got frame %lld (%lld + %lld): %lld units\n",
87           serialno, granulepos, iframe, pframe, units);
88 #endif
89
90   return units;
91 }
92
93 static ogg_int64_t
94 oggz_metric_default_linear (OGGZ * oggz, long serialno, ogg_int64_t granulepos,
95                             void * user_data)
96 {
97   oggz_stream_t * stream;
98
99   stream = oggz_get_stream (oggz, serialno);
100   if (stream == NULL) return -1;
101
102   return (stream->granulerate_d * granulepos / stream->granulerate_n);
103 }
104
105 static int
106 oggz_metric_update (OGGZ * oggz, long serialno)
107 {
108   oggz_stream_t * stream;
109
110   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
111
112   stream = oggz_get_stream (oggz, serialno);
113   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
114
115   /* we divide by the granulerate, ie. mult by gr_d/gr_n, so ensure
116    * numerator is non-zero */
117   if (stream->granulerate_n == 0) {
118     stream->granulerate_n= 1;
119     stream->granulerate_d = 0;
120   }
121
122   if (stream->granuleshift == 0) {
123     return oggz_set_metric_internal (oggz, serialno,
124                                      oggz_metric_default_linear,
125                                      NULL, 1);
126   } else if (oggz_stream_get_content (oggz, serialno) == OGGZ_CONTENT_DIRAC) {
127     return oggz_set_metric_internal (oggz, serialno,
128                                      oggz_metric_dirac,
129                                      NULL, 1);
130   } else {
131     return oggz_set_metric_internal (oggz, serialno,
132                                      oggz_metric_default_granuleshift,
133                                      NULL, 1);
134   }
135 }
136
137 int
138 oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift)
139 {
140   oggz_stream_t * stream;
141
142   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
143
144   stream = oggz_get_stream (oggz, serialno);
145   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
146
147   stream->granuleshift = granuleshift;
148
149   return oggz_metric_update (oggz, serialno);
150 }
151
152 int
153 oggz_get_granuleshift (OGGZ * oggz, long serialno)
154 {
155   oggz_stream_t * stream;
156
157   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
158
159   stream = oggz_get_stream (oggz, serialno);
160   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
161
162   return stream->granuleshift;
163 }
164
165 int
166 oggz_set_granulerate (OGGZ * oggz, long serialno,
167                       ogg_int64_t granule_rate_numerator,
168                       ogg_int64_t granule_rate_denominator)
169 {
170   oggz_stream_t * stream;
171
172   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
173
174   stream = oggz_get_stream (oggz, serialno);
175   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
176
177   stream->granulerate_n = granule_rate_numerator;
178   stream->granulerate_d = granule_rate_denominator;
179
180   return oggz_metric_update (oggz, serialno);
181 }
182
183 int
184 oggz_get_granulerate (OGGZ * oggz, long serialno,
185                       ogg_int64_t * granulerate_n,
186                       ogg_int64_t * granulerate_d)
187 {
188   oggz_stream_t * stream;
189
190   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
191
192   stream = oggz_get_stream (oggz, serialno);
193   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
194
195   *granulerate_n = stream->granulerate_n;
196   *granulerate_d = stream->granulerate_d / OGGZ_AUTO_MULT;
197
198   return 0;
199 }
200
201 /** DEPRECATED **/
202 int
203 oggz_set_metric_linear (OGGZ * oggz, long serialno,
204                         ogg_int64_t granule_rate_numerator,
205                         ogg_int64_t granule_rate_denominator)
206 {
207   oggz_stream_t * stream;
208
209   if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
210
211   stream = oggz_get_stream (oggz, serialno);
212   if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
213
214   stream->granulerate_n = granule_rate_numerator;
215   stream->granulerate_d = granule_rate_denominator;
216   stream->granuleshift = 0;
217
218   return oggz_metric_update (oggz, serialno);
219 }
220
Note: See TracBrowser for help on using the browser.