History

mp3dec_ex: support vbr tag for mp3dec_load_buf

lieff committed 6 years ago

Commit fa4c2ef1 parent 32a3ae44 files · +109 −64Browse files

Unified · Split

4 files
  1. minimp3_ex.h +110 −65
  2. scripts/test_mode.sh +1 −1
  3. vectors/l3-nonstandard-sin1k0db_lame_vbrtag.bit +0 −0
  4. vectors/l3-nonstandard-sin1k0db_lame_vbrtag.pcm +0 −0
minimp3_ex.h+110−65
@@ -127,10 +127,52 @@ static void mp3dec_skip_id3(const uint8_t **pbuf, size_t *pbuf_size) · 126 unmodified lines
127 *pbuf_size = buf_size;127 *pbuf_size = buf_size;
128}128}
129 129
130static int mp3dec_check_vbrtag(const uint8_t *frame, int frame_size, uint32_t *frames, int *delay, int *padding)
131{
132 int i;
133 static const char g_xing_tag[4] = { 'X', 'i', 'n', 'g' };
134 static const char g_info_tag[4] = { 'I', 'n', 'f', 'o' };
135#define FRAMES_FLAG 1
136#define BYTES_FLAG 2
137#define TOC_FLAG 4
138#define VBR_SCALE_FLAG 8
139 /* TODO: skip side-info?
140 / Side info offsets afrer header:
141 / Mono Stereo
142 / MPEG1 17 32
143 / MPEG2 & 2.5 9 17*/
144 for (i = 5; i < frame_size - 36; i++)
145 {
146 const uint8_t *tag = frame + i;
147 if (memcmp(g_xing_tag, tag, 4) && memcmp(g_info_tag, tag, 4))
148 continue;
149 int flags = tag[7];
150 if (!((flags & FRAMES_FLAG)))
151 break;
152 tag += 8;
153 (*frames) = (uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
154 tag += 4;
155 if (flags & BYTES_FLAG)
156 tag += 4;
157 if (flags & TOC_FLAG)
158 tag += 100;
159 if (flags & VBR_SCALE_FLAG)
160 tag += 4;
161 tag += 21;
162 if (tag - frame + 2 >= frame_size)
163 break;
164 *delay = ((tag[0] << 4) | (tag[1] >> 4)) + (528 + 1);
165 *padding = (((tag[1] & 0xF) << 8) | tag[2]) - (528 + 1);
166 return 1;
167 }
168 return 0;
169}
170
130void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)171void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_file_info_t *info, MP3D_PROGRESS_CB progress_cb, void *user_data)
131{172{
173 uint64_t detected_samples = 0;
132 size_t orig_buf_size = buf_size;174 size_t orig_buf_size = buf_size;
133 mp3d_sample_t pcm[MINIMP3_MAX_SAMPLES_PER_FRAME];175 int to_skip = 0;
134 mp3dec_frame_info_t frame_info;176 mp3dec_frame_info_t frame_info;
135 memset(info, 0, sizeof(*info));177 memset(info, 0, sizeof(*info));
136 memset(&frame_info, 0, sizeof(frame_info));178 memset(&frame_info, 0, sizeof(frame_info));
@@ -138,33 +180,57 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 1 unmodified line
138 mp3dec_skip_id3(&buf, &buf_size);180 mp3dec_skip_id3(&buf, &buf_size);
139 if (!buf_size)181 if (!buf_size)
140 return;182 return;
141 /* try to make allocation size assumption by first frame */183 /* try to make allocation size assumption by first frame or vbr tag */
142 mp3dec_init(dec);184 mp3dec_init(dec);
143 int samples;185 int samples;
144 do186 do
145 {187 {
146 samples = mp3dec_decode_frame(dec, buf, MINIMP3_MIN(buf_size, (size_t)INT_MAX), pcm, &frame_info);188 uint32_t frames;
147 buf += frame_info.frame_bytes;189 int delay, padding, free_format_bytes = 0, frame_size = 0;
148 buf_size -= frame_info.frame_bytes;190 int i = mp3d_find_frame(buf, buf_size, &free_format_bytes, &frame_size);
149 if (samples)191 buf += i;
150 break;192 buf_size -= i;
151 } while (frame_info.frame_bytes);193 if (i && !frame_size)
152 if (!samples)194 continue;
153 return;195 if (!frame_size)
154 samples *= frame_info.channels;196 return;
155 size_t allocated = (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t) + MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t);197 const uint8_t *hdr = buf;
198 frame_info.channels = HDR_IS_MONO(hdr) ? 1 : 2;
199 frame_info.hz = hdr_sample_rate_hz(hdr);
200 frame_info.layer = 4 - HDR_GET_LAYER(hdr);
201 frame_info.bitrate_kbps = hdr_bitrate_kbps(hdr);
202 frame_info.frame_bytes = frame_size;
203 samples = hdr_frame_samples(hdr)*frame_info.channels;
204 if (mp3dec_check_vbrtag(hdr, frame_size, &frames, &delay, &padding))
205 {
206 padding *= frame_info.channels;
207 to_skip = delay*frame_info.channels;
208 detected_samples = samples*(uint64_t)frames;
209 if (detected_samples >= (uint64_t)to_skip)
210 detected_samples -= to_skip;
211 if (padding > 0 && detected_samples >= (uint64_t)padding)
212 detected_samples -= padding;
213 if (!detected_samples)
214 return;
215 buf += frame_size;
216 buf_size -= frame_size;
217 }
218 break;
219 } while(1);
220 size_t allocated = MINIMP3_MAX_SAMPLES_PER_FRAME*sizeof(mp3d_sample_t);
221 if (detected_samples)
222 allocated += detected_samples*sizeof(mp3d_sample_t);
223 else
224 allocated += (buf_size/frame_info.frame_bytes)*samples*sizeof(mp3d_sample_t);
156 info->buffer = (mp3d_sample_t*)malloc(allocated);225 info->buffer = (mp3d_sample_t*)malloc(allocated);
157 if (!info->buffer)226 if (!info->buffer)
158 return;227 return;
159 info->samples = samples;
160 memcpy(info->buffer, pcm, info->samples*sizeof(mp3d_sample_t));
161 /* save info */228 /* save info */
162 info->channels = frame_info.channels;229 info->channels = frame_info.channels;
163 info->hz = frame_info.hz;230 info->hz = frame_info.hz;
164 info->layer = frame_info.layer;231 info->layer = frame_info.layer;
165 size_t avg_bitrate_kbps = frame_info.bitrate_kbps;232 /* decode all frames */
166 size_t frames = 1;233 size_t avg_bitrate_kbps = 0, frames = 0;
167 /* decode rest frames */
168 int frame_bytes;234 int frame_bytes;
169 do235 do
170 {236 {
@@ -187,17 +253,28 @@ void mp3dec_load_buf(mp3dec_t *dec, const uint8_t *buf, size_t buf_size, mp3dec_ · 16 unmodified lines
187#else253#else
188 break;254 break;
189#endif255#endif
190 info->samples += samples*frame_info.channels;256 samples *= frame_info.channels;
257 if (to_skip)
258 {
259 size_t skip = MINIMP3_MIN(samples, to_skip);
260 to_skip -= skip;
261 samples -= skip;
262 memmove(info->buffer, info->buffer + skip, samples);
263 }
264 info->samples += samples;
191 avg_bitrate_kbps += frame_info.bitrate_kbps;265 avg_bitrate_kbps += frame_info.bitrate_kbps;
192 frames++;266 frames++;
193 if (progress_cb)267 if (progress_cb)
194 progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);268 progress_cb(user_data, orig_buf_size, orig_buf_size - buf_size, &frame_info);
195 }269 }
196 } while (frame_bytes);270 } while (frame_bytes);
271 if (detected_samples)
272 info->samples = detected_samples;
197 /* reallocate to normal buffer size */273 /* reallocate to normal buffer size */
198 if (allocated != info->samples*sizeof(mp3d_sample_t))274 if (allocated != info->samples*sizeof(mp3d_sample_t))
199 info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));275 info->buffer = (mp3d_sample_t*)realloc(info->buffer, info->samples*sizeof(mp3d_sample_t));
200 info->avg_bitrate_kbps = avg_bitrate_kbps/frames;276 if (frames)
277 info->avg_bitrate_kbps = avg_bitrate_kbps/frames;
201}278}
202 279
203size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)280size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB callback, void *user_data)
@@ -241,61 +318,29 @@ size_t mp3dec_iterate_buf(const uint8_t *buf, size_t buf_size, MP3D_ITERATE_CB c · 37 unmodified lines
241 318
242static int mp3dec_load_index(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, size_t offset, mp3dec_frame_info_t *info)319static int mp3dec_load_index(void *user_data, const uint8_t *frame, int frame_size, int free_format_bytes, size_t buf_size, size_t offset, mp3dec_frame_info_t *info)
243{320{
244 static const char g_xing_tag[4] = { 'X', 'i', 'n', 'g' };
245 static const char g_info_tag[4] = { 'I', 'n', 'f', 'o' };
246 mp3dec_frame_t *idx_frame;321 mp3dec_frame_t *idx_frame;
247 mp3dec_ex_t *dec = (mp3dec_ex_t *)user_data;322 mp3dec_ex_t *dec = (mp3dec_ex_t *)user_data;
248 if (!dec->index.frames && !dec->vbr_tag_found)323 if (!dec->index.frames && !dec->vbr_tag_found)
249 { /* detect VBR tag and try to avoid full scan */324 { /* detect VBR tag and try to avoid full scan */
250 int i;325 uint32_t frames;
326 int delay, padding;
251 dec->info = *info;327 dec->info = *info;
252 dec->start_offset = dec->offset = offset;328 dec->start_offset = dec->offset = offset;
253 dec->end_offset = offset + buf_size;329 dec->end_offset = offset + buf_size;
254 dec->free_format_bytes = free_format_bytes; /* should not change */330 dec->free_format_bytes = free_format_bytes; /* should not change */
255 /* TODO: skip side-info?331 if (mp3dec_check_vbrtag(frame, frame_size, &frames, &delay, &padding))
256 / Side info offsets afrer header:
257 / Mono Stereo
258 / MPEG1 17 32
259 / MPEG2 & 2.5 9 17*/
260 for (i = 5; i < frame_size - 36; i++)
261 {332 {
262 const uint8_t *tag = frame + i;333 padding *= info->channels;
263 if (!memcmp(g_xing_tag, tag, 4) || !memcmp(g_info_tag, tag, 4))334 dec->start_delay = dec->to_skip = delay*info->channels;
264 {335 dec->samples = hdr_frame_samples(frame)*info->channels*(uint64_t)frames;
265#define FRAMES_FLAG 1336 if (dec->samples >= (uint64_t)dec->start_delay)
266#define BYTES_FLAG 2337 dec->samples -= dec->start_delay;
267#define TOC_FLAG 4338 if (padding > 0 && dec->samples >= (uint64_t)padding)
268#define VBR_SCALE_FLAG 8339 dec->samples -= padding;
269 int flags = tag[7], delay, padding;340 dec->detected_samples = dec->samples;
270 uint32_t frames;341 dec->start_offset = dec->offset = offset + frame_size;
271 if (!((flags & FRAMES_FLAG)))342 dec->vbr_tag_found = 1;
272 break;343 return 1;
273 tag += 8;
274 frames = (uint32_t)(tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8) | tag[3];
275 tag += 4;
276 if (flags & BYTES_FLAG)
277 tag += 4;
278 if (flags & TOC_FLAG)
279 tag += 100;
280 if (flags & VBR_SCALE_FLAG)
281 tag += 4;
282 tag += 21;
283 if (tag - frame + 2 >= frame_size)
284 break;
285 delay = (((tag[0] << 4) | (tag[1] >> 4)) + (528 + 1))*info->channels;
286 padding = ((((tag[1] & 0xF) << 8) | tag[2]) - (528 + 1))*info->channels;
287
288 dec->start_delay = dec->to_skip = delay;
289 dec->samples = hdr_frame_samples(frame)*info->channels*(uint64_t)frames;
290 if (dec->samples >= (uint64_t)dec->start_delay)
291 dec->samples -= dec->start_delay;
292 if (padding > 0 && dec->samples >= (uint64_t)padding)
293 dec->samples -= padding;
294 dec->detected_samples = dec->samples;
295 dec->start_offset = dec->offset = offset + frame_size;
296 dec->vbr_tag_found = 1;
297 return 1;
298 }
299 }344 }
300 }345 }
301 if (dec->index.num_frames + 1 > dec->index.capacity)346 if (dec->index.num_frames + 1 > dec->index.capacity)
scripts/test_mode.sh+1−1
@@ -13,7 +13,7 @@ vectors/l3-sin1k0db.bit vectors/l3-test45.bit vectors/l3-test46.bit vectors/M2L3 · 12 unmodified lines
13vectors/M2L3_bitrate_22_all.bit vectors/M2L3_bitrate_24_all.bit vectors/M2L3_compl24.bit vectors/M2L3_noise.bit \13vectors/M2L3_bitrate_22_all.bit vectors/M2L3_bitrate_24_all.bit vectors/M2L3_compl24.bit vectors/M2L3_noise.bit \
14vectors/l3-nonstandard-id3v1.bit vectors/l3-nonstandard-id3v2.bit vectors/l1-fl1.bit vectors/l2-fl10.bit"14vectors/l3-nonstandard-id3v1.bit vectors/l3-nonstandard-id3v2.bit vectors/l1-fl1.bit vectors/l2-fl10.bit"
15if [ "$MODE" = "2" ]; then15if [ "$MODE" = "2" ]; then
16VECTORS+=" vectors/vbrtag/l3-nonstandard-sin1k0db_lame_tag.bit"16VECTORS+=" vectors/l3-nonstandard-sin1k0db_lame_vbrtag.bit"
17fi17fi
18 18
19set +e19set +e
vectors/l3-nonstandard-sin1k0db_lame_vbrtag.bitrenamed from vectors/vbrtag/l3-nonstandard-sin1k0db_lame_tag.bit+0−0

File renamed without changes.

vectors/l3-nonstandard-sin1k0db_lame_vbrtag.pcmrenamed from vectors/vbrtag/l3-nonstandard-sin1k0db_lame_tag.pcm+0−0

File renamed without changes.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t