|
38 | 38 |
|
39 | 39 | /* Given an extension payload, advance data to the next extension and return the |
40 | 40 | length of the remaining extensions. */ |
41 | | -opus_int32 skip_extension(const unsigned char **data, opus_int32 len, opus_int32 *header_size) |
| 41 | +static opus_int32 skip_extension(const unsigned char **data, opus_int32 len, |
| 42 | + opus_int32 *header_size) |
42 | 43 | { |
43 | 44 | int id, L; |
44 | 45 | if (len==0) |
@@ -91,95 +92,114 @@ opus_int32 skip_extension(const unsigned char **data, opus_int32 len, opus_int32 |
91 | 92 | } |
92 | 93 | } |
93 | 94 |
|
94 | | -/* Count the number of extensions, excluding real padding and separators. */ |
95 | | -opus_int32 opus_packet_extensions_count(const unsigned char *data, opus_int32 len) |
96 | | -{ |
97 | | - opus_int32 curr_len; |
98 | | - opus_int32 count=0; |
99 | | - const unsigned char *curr_data = data; |
100 | | - |
| 95 | +void opus_extension_iterator_init(OpusExtensionIterator *iter, |
| 96 | + const unsigned char *data, opus_int32 len) { |
101 | 97 | celt_assert(len >= 0); |
102 | 98 | celt_assert(data != NULL || len == 0); |
| 99 | + iter->curr_data = iter->data = data; |
| 100 | + iter->curr_len = iter->len = len; |
| 101 | + iter->curr_frame = 0; |
| 102 | +} |
103 | 103 |
|
104 | | - curr_len = len; |
105 | | - while (curr_len > 0) |
106 | | - { |
| 104 | +/* Reset the iterator so it can start iterating again from the first |
| 105 | + extension. */ |
| 106 | +void opus_extension_iterator_reset(OpusExtensionIterator *iter) { |
| 107 | + iter->curr_data = iter->data; |
| 108 | + iter->curr_len = iter->len; |
| 109 | + iter->curr_frame = 0; |
| 110 | +} |
| 111 | + |
| 112 | +/* Return the next extension (excluding real padding and separators). */ |
| 113 | +int opus_extension_iterator_next(OpusExtensionIterator *iter, |
| 114 | + opus_extension_data *ext) { |
| 115 | + opus_int32 header_size; |
| 116 | + if (iter->curr_len < 0) { |
| 117 | + return OPUS_INVALID_PACKET; |
| 118 | + } |
| 119 | + while (iter->curr_len > 0) { |
| 120 | + const unsigned char *curr_data0; |
107 | 121 | int id; |
108 | | - opus_int32 header_size; |
109 | | - id = *curr_data>>1; |
110 | | - curr_len = skip_extension(&curr_data, curr_len, &header_size); |
111 | | - if (curr_len < 0) |
| 122 | + int L; |
| 123 | + curr_data0 = iter->curr_data; |
| 124 | + id = *curr_data0>>1; |
| 125 | + L = *curr_data0&1; |
| 126 | + iter->curr_len = skip_extension(&iter->curr_data, iter->curr_len, |
| 127 | + &header_size); |
| 128 | + if (iter->curr_len < 0) { |
112 | 129 | return OPUS_INVALID_PACKET; |
113 | | - if (id > 1) |
114 | | - count++; |
| 130 | + } |
| 131 | + celt_assert(iter->curr_data - iter->data == iter->len - iter->curr_len); |
| 132 | + if (id == 1) { |
| 133 | + if (L == 0) { |
| 134 | + iter->curr_frame++; |
| 135 | + } |
| 136 | + else { |
| 137 | + iter->curr_frame += curr_data0[1]; |
| 138 | + } |
| 139 | + if (iter->curr_frame >= 48) { |
| 140 | + iter->curr_len = -1; |
| 141 | + return OPUS_INVALID_PACKET; |
| 142 | + } |
| 143 | + } |
| 144 | + else if (id > 1) { |
| 145 | + if (ext != NULL) { |
| 146 | + ext->id = id; |
| 147 | + ext->frame = iter->curr_frame; |
| 148 | + ext->data = curr_data0 + header_size; |
| 149 | + ext->len = iter->curr_data - curr_data0 - header_size; |
| 150 | + } |
| 151 | + return 1; |
| 152 | + } |
115 | 153 | } |
| 154 | + return 0; |
| 155 | +} |
| 156 | + |
| 157 | +int opus_extension_iterator_find(OpusExtensionIterator *iter, |
| 158 | + opus_extension_data *ext, int id) { |
| 159 | + opus_extension_data curr_ext; |
| 160 | + int ret; |
| 161 | + for(;;) { |
| 162 | + ret = opus_extension_iterator_next(iter, &curr_ext); |
| 163 | + if (ret <= 0) { |
| 164 | + return ret; |
| 165 | + } |
| 166 | + if (curr_ext.id == id) { |
| 167 | + *ext = curr_ext; |
| 168 | + return ret; |
| 169 | + } |
| 170 | + } |
| 171 | +} |
| 172 | + |
| 173 | +/* Count the number of extensions, excluding real padding and separators. */ |
| 174 | +opus_int32 opus_packet_extensions_count(const unsigned char *data, opus_int32 len) |
| 175 | +{ |
| 176 | + OpusExtensionIterator iter; |
| 177 | + int count; |
| 178 | + opus_extension_iterator_init(&iter, data, len); |
| 179 | + for (count=0; opus_extension_iterator_next(&iter, NULL) > 0; count++); |
116 | 180 | return count; |
117 | 181 | } |
118 | 182 |
|
119 | 183 | /* Extract extensions from Opus padding (excluding real padding and separators) */ |
120 | 184 | opus_int32 opus_packet_extensions_parse(const unsigned char *data, opus_int32 len, opus_extension_data *extensions, opus_int32 *nb_extensions) |
121 | 185 | { |
122 | | - const unsigned char *curr_data; |
123 | | - opus_int32 curr_len; |
124 | | - int curr_frame=0; |
125 | | - opus_int32 count=0; |
126 | | - |
127 | | - celt_assert(len >= 0); |
128 | | - celt_assert(data != NULL || len == 0); |
| 186 | + OpusExtensionIterator iter; |
| 187 | + int count; |
| 188 | + int ret; |
129 | 189 | celt_assert(nb_extensions != NULL); |
130 | 190 | celt_assert(extensions != NULL || *nb_extensions == 0); |
131 | | - |
132 | | - curr_data = data; |
133 | | - curr_len = len; |
134 | | - while (curr_len > 0) |
135 | | - { |
136 | | - int id; |
137 | | - opus_int32 header_size; |
138 | | - opus_extension_data curr_ext; |
139 | | - id = *curr_data>>1; |
140 | | - if (id > 1) |
141 | | - { |
142 | | - curr_ext.id = id; |
143 | | - curr_ext.frame = curr_frame; |
144 | | - curr_ext.data = curr_data; |
145 | | - } else if (id == 1) |
146 | | - { |
147 | | - int L = *curr_data&1; |
148 | | - if (L==0) |
149 | | - curr_frame++; |
150 | | - else { |
151 | | - if (curr_len >= 2) |
152 | | - curr_frame += curr_data[1]; |
153 | | - /* Else we're at the end and it doesn't matter. */ |
154 | | - } |
155 | | - if (curr_frame >= 48) |
156 | | - { |
157 | | - *nb_extensions = count; |
158 | | - return OPUS_INVALID_PACKET; |
159 | | - } |
160 | | - } |
161 | | - curr_len = skip_extension(&curr_data, curr_len, &header_size); |
162 | | - /* printf("curr_len = %d, header_size = %d\n", curr_len, header_size); */ |
163 | | - if (curr_len < 0) |
164 | | - { |
165 | | - *nb_extensions = count; |
166 | | - return OPUS_INVALID_PACKET; |
167 | | - } |
168 | | - celt_assert(curr_data - data == len - curr_len); |
169 | | - if (id > 1) |
170 | | - { |
171 | | - if (count == *nb_extensions) |
172 | | - { |
173 | | - return OPUS_BUFFER_TOO_SMALL; |
174 | | - } |
175 | | - curr_ext.len = curr_data - curr_ext.data - header_size; |
176 | | - curr_ext.data += header_size; |
177 | | - extensions[count++] = curr_ext; |
| 191 | + opus_extension_iterator_init(&iter, data, len); |
| 192 | + for (count=0;; count++) { |
| 193 | + opus_extension_data ext; |
| 194 | + ret = opus_extension_iterator_next(&iter, &ext); |
| 195 | + if (ret <= 0) break; |
| 196 | + if (count == *nb_extensions) { |
| 197 | + return OPUS_BUFFER_TOO_SMALL; |
178 | 198 | } |
| 199 | + extensions[count] = ext; |
179 | 200 | } |
180 | | - celt_assert(curr_len == 0); |
181 | 201 | *nb_extensions = count; |
182 | | - return OPUS_OK; |
| 202 | + return ret; |
183 | 203 | } |
184 | 204 |
|
185 | 205 | opus_int32 opus_packet_extensions_generate(unsigned char *data, opus_int32 len, const opus_extension_data *extensions, opus_int32 nb_extensions, int pad) |
|
0 commit comments