History

mp3dec: move XING/Info and VBRI parsing into their own functions

Alessandro Ghedini committed 12 years ago

Commit fbd8e041 parent ae43c101 file · +58 −35Browse files

Unified · Split

libavformat/mp3dec.c+58−35
@@ -39,6 +39,9 @@ · 38 unmodified lines
39 39
40typedef struct MP3DecContext {40typedef struct MP3DecContext {
41 int xing_toc;41 int xing_toc;
42 unsigned frames; /* Total number of frames in file */
43 unsigned size; /* Total number of bytes in the stream */
44 int is_cbr;
42} MP3DecContext;45} MP3DecContext;
43 46
44/* mp3 read */47/* mp3 read */
@@ -125,18 +128,60 @@ static void read_xing_toc(AVFormatContext *s, int64_t filesize, int64_t duration · 80 unmodified lines
125 mp3->xing_toc = 1;128 mp3->xing_toc = 1;
126}129}
127 130
131
132static void mp3_parse_info_tag(AVFormatContext *s, AVStream *st,
133 MPADecodeHeader *c, uint32_t spf)
134{
135 uint32_t v;
136 MP3DecContext *mp3 = s->priv_data;
137 const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
138
139 /* Check for Xing / Info tag */
140 avio_skip(s->pb, xing_offtbl[c->lsf == 1][c->nb_channels == 1]);
141 v = avio_rb32(s->pb);
142 mp3->is_cbr = v == MKBETAG('I', 'n', 'f', 'o');
143 if (v == MKBETAG('X', 'i', 'n', 'g') || mp3->is_cbr) {
144 v = avio_rb32(s->pb);
145 if (v & XING_FLAG_FRAMES)
146 mp3->frames = avio_rb32(s->pb);
147 if (v & XING_FLAG_SIZE)
148 mp3->size = avio_rb32(s->pb);
149 if (v & XING_FLAG_TOC && mp3->frames)
150 read_xing_toc(s, mp3->size,
151 av_rescale_q(mp3->frames,
152 (AVRational){spf, c->sample_rate},
153 st->time_base));
154 }
155}
156
157static void mp3_parse_vbri_tag(AVFormatContext *s, AVStream *st, int64_t base)
158{
159 uint32_t v;
160 MP3DecContext *mp3 = s->priv_data;
161
162 /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */
163 avio_seek(s->pb, base + 4 + 32, SEEK_SET);
164 v = avio_rb32(s->pb);
165 if (v == MKBETAG('V', 'B', 'R', 'I')) {
166 /* Check tag version */
167 if (avio_rb16(s->pb) == 1) {
168 /* skip delay and quality */
169 avio_skip(s->pb, 4);
170 mp3->size = avio_rb32(s->pb);
171 mp3->frames = avio_rb32(s->pb);
172 }
173 }
174}
175
128/**176/**
129 * Try to find Xing/Info/VBRI tags and compute duration from info therein177 * Try to find Xing/Info/VBRI tags and compute duration from info therein
130 */178 */
131static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)179static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base)
132{180{
133 uint32_t v, spf;181 uint32_t v, spf;
134 unsigned frames = 0; /* Total number of frames in file */
135 unsigned size = 0; /* Total number of bytes in the stream */
136 const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
137 MPADecodeHeader c;182 MPADecodeHeader c;
138 int vbrtag_size = 0;183 int vbrtag_size = 0;
139 int is_cbr;184 MP3DecContext *mp3 = s->priv_data;
140 185
141 v = avio_rb32(s->pb);186 v = avio_rb32(s->pb);
142 if(ff_mpa_check_header(v) < 0)187 if(ff_mpa_check_header(v) < 0)
@@ -149,45 +194,23 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) · 6 unmodified lines
149 194
150 spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */195 spf = c.lsf ? 576 : 1152; /* Samples per frame, layer 3 */
151 196
152 /* Check for Xing / Info tag */197 mp3->frames = 0;
153 avio_skip(s->pb, xing_offtbl[c.lsf == 1][c.nb_channels == 1]);198 mp3->size = 0;
154 v = avio_rb32(s->pb);
155 is_cbr = v == MKBETAG('I', 'n', 'f', 'o');
156 if (v == MKBETAG('X', 'i', 'n', 'g') || is_cbr) {
157 v = avio_rb32(s->pb);
158 if(v & XING_FLAG_FRAMES)
159 frames = avio_rb32(s->pb);
160 if(v & XING_FLAG_SIZE)
161 size = avio_rb32(s->pb);
162 if (v & XING_FLAG_TOC && frames)
163 read_xing_toc(s, size, av_rescale_q(frames, (AVRational){spf, c.sample_rate},
164 st->time_base));
165 }
166 199
167 /* Check for VBRI tag (always 32 bytes after end of mpegaudio header) */200 mp3_parse_info_tag(s, st, &c, spf);
168 avio_seek(s->pb, base + 4 + 32, SEEK_SET);201 mp3_parse_vbri_tag(s, st, base);
169 v = avio_rb32(s->pb);
170 if(v == MKBETAG('V', 'B', 'R', 'I')) {
171 /* Check tag version */
172 if(avio_rb16(s->pb) == 1) {
173 /* skip delay and quality */
174 avio_skip(s->pb, 4);
175 size = avio_rb32(s->pb);
176 frames = avio_rb32(s->pb);
177 }
178 }
179 202
180 if(!frames && !size)203 if (!mp3->frames && !mp3->size)
181 return -1;204 return -1;
182 205
183 /* Skip the vbr tag frame */206 /* Skip the vbr tag frame */
184 avio_seek(s->pb, base + vbrtag_size, SEEK_SET);207 avio_seek(s->pb, base + vbrtag_size, SEEK_SET);
185 208
186 if(frames)209 if (mp3->frames)
187 st->duration = av_rescale_q(frames, (AVRational){spf, c.sample_rate},210 st->duration = av_rescale_q(mp3->frames, (AVRational){spf, c.sample_rate},
188 st->time_base);211 st->time_base);
189 if (size && frames && !is_cbr)212 if (mp3->size && mp3->frames && !mp3->is_cbr)
190 st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf);213 st->codec->bit_rate = av_rescale(mp3->size, 8 * c.sample_rate, mp3->frames * (int64_t)spf);
191 214
192 return 0;215 return 0;
193}216}

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