Revision d62bf5d4 libavformat/mp3enc.c

View differences:

libavformat/mp3enc.c
27 27
#include "libavutil/avstring.h"
28 28
#include "libavutil/intreadwrite.h"
29 29
#include "libavutil/opt.h"
30
#include "libavcodec/mpegaudiodata.h"
31
#include "libavcodec/mpegaudiodecheader.h"
32
#include "libavformat/avio_internal.h"
30 33

  
31 34
static int id3v1_set_string(AVFormatContext *s, const char *key,
32 35
                            uint8_t *buf, int buf_size)
......
127 130
    return len + ID3v2_HEADER_SIZE;
128 131
}
129 132

  
130
static int mp3_write_trailer(struct AVFormatContext *s)
133
static int mp2_write_trailer(struct AVFormatContext *s)
131 134
{
132 135
    uint8_t buf[ID3v1_TAG_SIZE];
133 136

  
......
150 153
    CODEC_ID_NONE,
151 154
    NULL,
152 155
    ff_raw_write_packet,
153
    mp3_write_trailer,
156
    mp2_write_trailer,
154 157
};
155 158
#endif
156 159

  
157 160
#if CONFIG_MP3_MUXER
161
#define VBR_NUM_BAGS 400
162
#define VBR_TOC_SIZE 100
158 163
typedef struct MP3Context {
159 164
    const AVClass *class;
160 165
    int id3v2_version;
166
    struct xing_header {
167
        int64_t offset;
168
        int32_t frames;
169
        int32_t size;
170
        /* following lame's "VbrTag.c". */
171
        struct xing_toc {
172
            uint32_t want;
173
            uint32_t seen;
174
            uint32_t pos;
175
            uint64_t sum;
176
            uint64_t bag[VBR_NUM_BAGS];
177
        } toc;
178
    } xing_header;
161 179
} MP3Context;
162 180

  
163 181
static const AVOption options[] = {
......
188 206
    return -1;
189 207
}
190 208

  
209
static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}};
210
static const uint32_t XING = MKBETAG('X', 'i', 'n', 'g');
211
#ifdef FILTER_VBR_HEADERS
212
static const uint32_t INFO = MKBETAG('I', 'n', 'f', 'o');
213
static const uint32_t VBRI = MKBETAG('V', 'B', 'R', 'I');
214
#endif
215

  
216
/*
217
 * Write an empty XING header and initialize respective data.
218
 */
219
static int mp3_write_xing(AVFormatContext *s)
220
{
221
    AVCodecContext   *codec = s->streams[0]->codec;
222
    MP3Context       *mp3 = s->priv_data;
223
    int              bitrate_idx = 3;
224
    int64_t          xing_offset;
225
    int32_t          mask, header;
226
    MPADecodeHeader  c;
227
    int              srate_idx, i, channels;
228
    int              needed;
229

  
230
    for (i = 0; i < FF_ARRAY_ELEMS(ff_mpa_freq_tab); i++)
231
        if (ff_mpa_freq_tab[i] == codec->sample_rate) {
232
            srate_idx = i;
233
            break;
234
        }
235
    if (i == FF_ARRAY_ELEMS(ff_mpa_freq_tab)) {
236
        av_log(s, AV_LOG_ERROR, "Unsupported sample rate.\n");
237
        return -1;
238
    }
239

  
240
    switch (codec->channels) {
241
    case 1:  channels = MPA_MONO;                                          break;
242
    case 2:  channels = MPA_STEREO;                                        break;
243
    default: av_log(s, AV_LOG_ERROR, "Unsupported number of channels.\n"); return -1;
244
    }
245

  
246
    /* dummy MPEG audio header */
247
    header  =  0xff                                  << 24; // sync
248
    header |= (0x7 << 5 | 0x3 << 3 | 0x1 << 1 | 0x1) << 16; // sync/mpeg-1/layer 3/no crc*/
249
    header |= (srate_idx << 2) <<  8;
250
    header |= channels << 6;
251

  
252
    for (;;) {
253
        if (15 == bitrate_idx)
254
            return -1;
255

  
256
        mask = (bitrate_idx << 4) <<  8;
257
        header |= mask;
258
        ff_mpegaudio_decode_header(&c, header);
259
        xing_offset=xing_offtbl[c.lsf == 1][c.nb_channels == 1];
260
        needed = 4              // header
261
               + xing_offset
262
               + 4              // xing tag
263
               + 4              // frames/size/toc flags
264
               + 4              // frames
265
               + 4              // size
266
               + VBR_TOC_SIZE;  // toc
267

  
268
        if (needed <= c.frame_size)
269
            break;
270

  
271
        header &= ~mask;
272
        ++bitrate_idx;
273
    }
274

  
275
    avio_wb32(s->pb, header);
276
    ffio_fill(s->pb, 0, xing_offset);
277
    avio_wb32(s->pb, XING);
278
    avio_wb32(s->pb, 0x01 | 0x02 | 0x04);  // frames/size/toc
279

  
280
    mp3->xing_header.offset = avio_tell(s->pb);
281
    mp3->xing_header.size = c.frame_size;
282
    mp3->xing_header.toc.want=1;
283
    mp3->xing_header.toc.seen=0;
284
    mp3->xing_header.toc.pos=0;
285
    mp3->xing_header.toc.sum=0;
286

  
287
    avio_wb32(s->pb, 0);  // frames
288
    avio_wb32(s->pb, 0);  // size
289

  
290
    // toc
291
    for (i = 0; i < VBR_TOC_SIZE; ++i)
292
        avio_w8(s->pb, (uint8_t)(255 * i / VBR_TOC_SIZE));
293

  
294
    ffio_fill(s->pb, 0, c.frame_size - needed);
295
    avio_flush(s->pb);
296

  
297
    return 0;
298
}
299

  
300
/*
301
 * Add a frame to XING data.
302
 * Following lame's "VbrTag.c".
303
 */
304
static void mp3_xing_add_frame(AVFormatContext *s, AVPacket *pkt, MPADecodeHeader *c)
305
{
306
    MP3Context  *mp3 = s->priv_data;
307
    struct xing_header *xing_header = &mp3->xing_header;
308
    struct xing_toc *toc = &xing_header->toc;
309
    int i;
310

  
311
    ++xing_header->frames;
312
    xing_header->size += pkt->size;
313
    toc->sum += c->bit_rate / 1000;
314

  
315
    if (toc->want == ++toc->seen) {
316
        toc->bag[toc->pos] = toc->sum;
317

  
318
        if (VBR_NUM_BAGS == ++toc->pos) {
319
            /* shrink table to half size by throwing away each second bag. */
320
            for (i = 1; i < VBR_NUM_BAGS; i += 2)
321
                toc->bag[i >> 1] = toc->bag[i];
322

  
323
            /* double wanted amount per bag. */
324
            toc->want <<= 1;
325
            /* adjust current position to half of table size. */
326
            toc->pos >>= 1;
327
        }
328

  
329
        toc->seen = 0;
330
    }
331
}
332

  
333
static void mp3_fix_xing(AVFormatContext *s)
334
{
335
    MP3Context  *mp3 = s->priv_data;
336
    struct xing_header *xing_header = &mp3->xing_header;
337
    struct xing_toc *toc = &xing_header->toc;
338
    double scale = (double)toc->pos / (double)VBR_TOC_SIZE;
339
    int i;
340

  
341
    avio_flush(s->pb);
342
    avio_seek(s->pb, xing_header->offset, SEEK_SET);
343
    avio_wb32(s->pb, xing_header->frames);
344
    avio_wb32(s->pb, xing_header->size);
345

  
346
    avio_w8(s->pb, 0);  // first toc entry has to be zero.
347

  
348
    for (i = 1; i < VBR_TOC_SIZE; ++i) {
349
        int j = (int)floor(scale * i);
350
        int seek_point = (int)floor(256.0 * toc->bag[j] / toc->sum);
351

  
352
        avio_w8(s->pb, (uint8_t)(seek_point < 256 ? seek_point : 255));
353
    }
354

  
355
    avio_flush(s->pb);
356
    avio_seek(s->pb, 0, SEEK_END);
357
}
358

  
191 359
/**
192 360
 * Write an ID3v2 header at beginning of stream
193 361
 */
......
236 404
    id3v2_put_size(s, totlen);
237 405
    avio_seek(s->pb, cur_pos, SEEK_SET);
238 406

  
407
    if (s->pb->seekable)
408
        mp3_write_xing(s);
409

  
410
    return 0;
411
}
412

  
413
static int mp3_write_packet(AVFormatContext *s, AVPacket *pkt)
414
{
415
    if (! pkt || ! pkt->data || pkt->size < 4)
416
        return ff_raw_write_packet(s, pkt);
417
    else {
418
        MP3Context  *mp3 = s->priv_data;
419
        MPADecodeHeader c;
420
#ifdef FILTER_VBR_HEADERS
421
        int base;
422
#endif
423

  
424
        ff_mpegaudio_decode_header(&c, AV_RB32(pkt->data));
425

  
426
#ifdef FILTER_VBR_HEADERS
427
        /* filter out XING and INFO headers. */
428
        base = 4 + xing_offtbl[c.lsf == 1][c.nb_channels == 1];
429

  
430
        if (base + 4 <= pkt->size) {
431
            uint32_t v = AV_RB32(pkt->data + base);
432

  
433
            if (XING == v || INFO == v)
434
                return 0;
435
        }
436

  
437
        /* filter out VBRI headers. */
438
        base = 4 + 32;
439

  
440
        if (base + 4 <= pkt->size && VBRI == AV_RB32(pkt->data + base))
441
            return 0;
442
#endif
443

  
444
        if (0 < mp3->xing_header.offset)
445
            mp3_xing_add_frame(s, pkt, &c);
446

  
447
        return ff_raw_write_packet(s, pkt);
448
    }
449
}
450

  
451
static int mp3_write_trailer(AVFormatContext *s)
452
{
453
    MP3Context  *mp3 = s->priv_data;
454
    int ret=mp2_write_trailer(s);
455

  
456
    if (ret < 0)
457
        return ret;
458

  
459
    if (0 < mp3->xing_header.offset)
460
        mp3_fix_xing(s);
461

  
239 462
    return 0;
240 463
}
241 464

  
......
248 471
    CODEC_ID_MP3,
249 472
    CODEC_ID_NONE,
250 473
    mp3_write_header,
251
    ff_raw_write_packet,
474
    mp3_write_packet,
252 475
    mp3_write_trailer,
253 476
    AVFMT_NOTIMESTAMPS,
254 477
    .priv_class = &mp3_muxer_class,

Also available in: Unified diff