Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/*
2
 *	Xing VBR tagging for LAME.
3
 *
4
 *	Copyright (c) 1999 A.L. Faber
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Library General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
14
 * Library General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Library General Public
17
 * License along with this library; if not, write to the
18
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
 * Boston, MA 02111-1307, USA.
20
 */
21
 
22
/* $Id: VbrTag.c,v 1.20 2001/02/27 09:59:16 robert Exp $ */
23
 
24
#ifdef HAVE_CONFIG_H
25
# include <config.h>
26
#endif
27
 
28
#include "machine.h"
29
#if defined(__riscos__) && defined(FPA10)
30
#include	"ymath.h"
31
#else
32
#include	<math.h>
33
#endif
34
#include "VbrTag.h"
35
#include "version.h"
36
#include "bitstream.h"
37
#include "VbrTag.h"
38
#include	<assert.h>
39
 
40
#ifdef WITH_DMALLOC
41
#include <dmalloc.h>
42
#endif
43
 
44
 
45
#ifdef _DEBUG
46
/*  #define DEBUG_VBRTAG */
47
#endif
48
 
49
/*
50
//    4 bytes for Header Tag
51
//    4 bytes for Header Flags
52
//  100 bytes for entry (NUMTOCENTRIES)
53
//    4 bytes for FRAME SIZE
54
//    4 bytes for STREAM_SIZE
55
//    4 bytes for VBR SCALE. a VBR quality indicator: 0=best 100=worst
56
//   20 bytes for LAME tag.  for example, "LAME3.12 (beta 6)"
57
// ___________
58
//  140 bytes
59
*/
60
#define VBRHEADERSIZE (NUMTOCENTRIES+4+4+4+4+4)
61
 
62
/* the size of the Xing header (MPEG1 and MPEG2) in kbps */
63
#define XING_BITRATE1 128
64
#define XING_BITRATE2  64
65
#define XING_BITRATE25 32
66
 
67
 
68
 
69
const static char	VBRTag[]={"Xing"};
70
const int SizeOfEmptyFrame[2][2]=
71
{
72
	{17,9},
73
	{32,17},
74
};
75
 
76
 
77
/***********************************************************************
78
 *  Robert Hegemann 2001-01-17
79
 ***********************************************************************/
80
 
81
void addVbr(VBR_seek_info_t * v, int bitrate)
82
{
83
    int i;
84
 
85
    v->sum += bitrate;
86
    v->seen ++;
87
 
88
    if (v->seen < v->want) {
89
        return;
90
    }
91
 
92
    if (v->pos < v->size) {
93
        v->bag[v->pos] = v->sum;
94
        v->pos ++;
95
        v->seen = 0;
96
    }
97
    if (v->pos == v->size) {
98
        for (i = 1; i < v->size; i += 2) {
99
            v->bag[i/2] = v->bag[i]; 
100
        }
101
        v->want *= 2;
102
        v->pos  /= 2;
103
    }
104
}
105
 
106
void Xing_seek_table(VBR_seek_info_t * v, unsigned char *t)
107
{
108
    int i, index;
109
    int seek_point;
110
 
111
    if (v->pos <= 0)
112
        return;
113
 
114
    for (i = 1; i < NUMTOCENTRIES; ++i) {
115
        float j = i/(float)NUMTOCENTRIES, act, sum;
116
        index = (int)(floor(j * v->pos));
117
        if (index > v->pos-1)
118
            index = v->pos-1;
119
        act = v->bag[index];
120
        sum = v->sum;
121
        seek_point = (int)(256. * act / sum);
122
        if (seek_point > 255)
123
            seek_point = 255;
124
        t[i] = seek_point;
125
    }
126
}
127
 
128
#if 0
129
void print_seeking(unsigned char *t)
130
{
131
    int i;
132
 
133
    printf("seeking table ");
134
    for (i = 0; i < NUMTOCENTRIES; ++i) {
135
        printf(" %d ", t[i]);
136
    }
137
    printf("\n");
138
}
139
#endif
140
 
141
 
142
 
143
/****************************************************************************
144
 * AddVbrFrame: Add VBR entry, used to fill the VBR the TOC entries
145
 * Paramters:
146
 *	nStreamPos: how many bytes did we write to the bitstream so far
147
 *				(in Bytes NOT Bits)
148
 ****************************************************************************
149
*/
150
void AddVbrFrame(lame_global_flags *gfp)
151
{
152
    lame_internal_flags *gfc = gfp->internal_flags;
153
 
154
    int kbps = bitrate_table[gfp->version][gfc->bitrate_index];
155
 
156
    if (gfc->VBR_seek_table.bag == NULL) {
157
        gfc->VBR_seek_table.sum  = 0;
158
        gfc->VBR_seek_table.seen = 0;
159
        gfc->VBR_seek_table.want = 1;
160
        gfc->VBR_seek_table.pos  = 0;
161
        gfc->VBR_seek_table.bag  = malloc (400*sizeof(int));
162
        if (gfc->VBR_seek_table.bag != NULL) {
163
            gfc->VBR_seek_table.size = 400;
164
        }
165
        else {
166
            gfc->VBR_seek_table.size = 0;
167
            ERRORF (gfc,"Error: can't allocate VbrFrames buffer\n");
168
            return;
169
        }   
170
    }
171
    addVbr(&gfc->VBR_seek_table, kbps);
172
    gfp->nVbrNumFrames++;
173
}
174
 
175
 
176
/*-------------------------------------------------------------*/
177
static int ExtractI4(unsigned char *buf)
178
{
179
	int x;
180
	/* big endian extract */
181
	x = buf[0];
182
	x <<= 8;
183
	x |= buf[1];
184
	x <<= 8;
185
	x |= buf[2];
186
	x <<= 8;
187
	x |= buf[3];
188
	return x;
189
}
190
 
191
void CreateI4(unsigned char *buf, int nValue)
192
{
193
        /* big endian create */
194
	buf[0]=(nValue>>24)&0xff;
195
	buf[1]=(nValue>>16)&0xff;
196
	buf[2]=(nValue>> 8)&0xff;
197
	buf[3]=(nValue    )&0xff;
198
}
199
 
200
 
201
/*-------------------------------------------------------------*/
202
/* Same as GetVbrTag below, but only checks for the Xing tag.
203
   requires buf to contain only 40 bytes */
204
/*-------------------------------------------------------------*/
205
int CheckVbrTag(unsigned char *buf)
206
{
207
	int			h_id, h_mode, h_sr_index;
208
 
209
	/* get selected MPEG header data */
210
	h_id       = (buf[1] >> 3) & 1;
211
	h_sr_index = (buf[2] >> 2) & 3;
212
	h_mode     = (buf[3] >> 6) & 3;
213
 
214
	/*  determine offset of header */
215
	if( h_id )
216
	{
217
                /* mpeg1 */
218
		if( h_mode != 3 )	buf+=(32+4);
219
		else				buf+=(17+4);
220
	}
221
	else
222
	{
223
                /* mpeg2 */
224
		if( h_mode != 3 ) buf+=(17+4);
225
		else              buf+=(9+4);
226
	}
227
 
228
	if( buf[0] != VBRTag[0] ) return 0;    /* fail */
229
	if( buf[1] != VBRTag[1] ) return 0;    /* header not found*/
230
	if( buf[2] != VBRTag[2] ) return 0;
231
	if( buf[3] != VBRTag[3] ) return 0;
232
	return 1;
233
}
234
 
235
int GetVbrTag(VBRTAGDATA *pTagData,  unsigned char *buf)
236
{
237
	int			i, head_flags;
238
	int			h_bitrate,h_id, h_mode, h_sr_index;
239
 
240
	/* get Vbr header data */
241
	pTagData->flags = 0;
242
 
243
	/* get selected MPEG header data */
244
	h_id       = (buf[1] >> 3) & 1;
245
	h_sr_index = (buf[2] >> 2) & 3;
246
	h_mode     = (buf[3] >> 6) & 3;
247
        h_bitrate  = ((buf[2]>>4)&0xf);
248
	h_bitrate = bitrate_table[h_id][h_bitrate];
249
 
250
 
251
	/*  determine offset of header */
252
	if( h_id )
253
	{
254
                /* mpeg1 */
255
		if( h_mode != 3 )	buf+=(32+4);
256
		else				buf+=(17+4);
257
	}
258
	else
259
	{
260
                /* mpeg2 */
261
		if( h_mode != 3 ) buf+=(17+4);
262
		else              buf+=(9+4);
263
	}
264
 
265
	if( buf[0] != VBRTag[0] ) return 0;    /* fail */
266
	if( buf[1] != VBRTag[1] ) return 0;    /* header not found*/
267
	if( buf[2] != VBRTag[2] ) return 0;
268
	if( buf[3] != VBRTag[3] ) return 0;
269
 
270
	buf+=4;
271
 
272
	pTagData->h_id = h_id;
273
	pTagData->samprate = samplerate_table[h_id][h_sr_index];
274
 
275
	if( h_id == 0 )
276
		pTagData->samprate >>= 1;
277
 
278
	head_flags = pTagData->flags = ExtractI4(buf); buf+=4;      /* get flags */
279
 
280
	if( head_flags & FRAMES_FLAG )
281
	{
282
		pTagData->frames   = ExtractI4(buf); buf+=4;
283
	}
284
 
285
	if( head_flags & BYTES_FLAG )
286
	{
287
		pTagData->bytes = ExtractI4(buf); buf+=4;
288
	}
289
 
290
	if( head_flags & TOC_FLAG )
291
	{
292
		if( pTagData->toc != NULL )
293
		{
294
			for(i=0;i<NUMTOCENTRIES;i++)
295
				pTagData->toc[i] = buf[i];
296
		}
297
		buf+=NUMTOCENTRIES;
298
	}
299
 
300
	pTagData->vbr_scale = -1;
301
 
302
	if( head_flags & VBR_SCALE_FLAG )
303
	{
304
		pTagData->vbr_scale = ExtractI4(buf); buf+=4;
305
	}
306
 
307
	pTagData->headersize = 
308
	  ((h_id+1)*72000*h_bitrate) / pTagData->samprate;
309
 
310
 
311
#ifdef DEBUG_VBRTAG
312
	DEBUGF("\n\n********************* VBR TAG INFO *****************\n");
313
	DEBUGF("tag         :%s\n",VBRTag);
314
	DEBUGF("head_flags  :%d\n",head_flags);
315
	DEBUGF("bytes       :%d\n",pTagData->bytes);
316
	DEBUGF("frames      :%d\n",pTagData->frames);
317
	DEBUGF("VBR Scale   :%d\n",pTagData->vbr_scale);
318
	DEBUGF("toc:\n");
319
	if( pTagData->toc != NULL )
320
	{
321
		for(i=0;i<NUMTOCENTRIES;i++)
322
		{
323
			if( (i%10) == 0 ) DEBUGF("\n");
324
			DEBUGF(" %3d", (int)(pTagData->toc[i]));
325
		}
326
	}
327
	DEBUGF("\n***************** END OF VBR TAG INFO ***************\n");
328
#endif
329
	return 1;       /* success */
330
}
331
 
332
 
333
/****************************************************************************
334
 * InitVbrTag: Initializes the header, and write empty frame to stream
335
 * Paramters:
336
 *				fpStream: pointer to output file stream
337
 *				nMode	: Channel Mode: 0=STEREO 1=JS 2=DS 3=MONO
338
 ****************************************************************************
339
*/
340
int InitVbrTag(lame_global_flags *gfp)
341
{
342
	int nMode,SampIndex;
343
	lame_internal_flags *gfc = gfp->internal_flags;
344
#define MAXFRAMESIZE 576
345
	//	u_char pbtStreamBuffer[MAXFRAMESIZE];
346
	nMode = gfp->mode;
347
	SampIndex = gfc->samplerate_index;
348
 
349
 
350
	/* Clear Frame position array variables */
351
	gfp->pVbrFrames=NULL;
352
	gfp->nVbrNumFrames=0;
353
	gfp->nVbrFrameBufferSize=0;
354
 
355
 
356
	/* Clear stream buffer */
357
	//	memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer));
358
 
359
 
360
 
361
	/* Reserve the proper amount of bytes */
362
	if (nMode==3)
363
	{
364
		gfp->nZeroStreamSize=SizeOfEmptyFrame[gfp->version][1]+4;
365
	}
366
	else
367
	{
368
		gfp->nZeroStreamSize=SizeOfEmptyFrame[gfp->version][0]+4;
369
	}
370
 
371
	/*
372
	// Xing VBR pretends to be a 48kbs layer III frame.  (at 44.1kHz).
373
        // (at 48kHz they use 56kbs since 48kbs frame not big enough for
374
        // table of contents)
375
	// let's always embed Xing header inside a 64kbs layer III frame.
376
	// this gives us enough room for a LAME version string too.
377
	// size determined by sampling frequency (MPEG1)
378
	// 32kHz:    216 bytes@48kbs    288bytes@ 64kbs
379
	// 44.1kHz:  156 bytes          208bytes@64kbs     (+1 if padding = 1)
380
	// 48kHz:    144 bytes          192
381
	//
382
	// MPEG 2 values are the same since the framesize and samplerate
383
        // are each reduced by a factor of 2.
384
	*/
385
	{
386
	int i,bitrate,tot;
387
	if (1==gfp->version) {
388
	  bitrate = XING_BITRATE1;
389
	} else {
390
	  if (gfp->out_samplerate < 16000 )
391
	    bitrate = XING_BITRATE25;
392
	  else
393
	    bitrate = XING_BITRATE2;
394
	}
395
	gfp->TotalFrameSize= 
396
	  ((gfp->version+1)*72000*bitrate) / gfp->out_samplerate;
397
	tot = (gfp->nZeroStreamSize+VBRHEADERSIZE);
398
	tot += 20;  /* extra 20 bytes for LAME & version string */
399
 
400
	assert(gfp->TotalFrameSize >= tot );
401
	assert(gfp->TotalFrameSize <= MAXFRAMESIZE );
402
 
403
	for (i=0; i<gfp->TotalFrameSize; ++i)
404
	  add_dummy_byte(gfp,0);
405
	}
406
 
407
	/* Success */
408
	return 0;
409
}
410
 
411
 
412
 
413
/****************************************************************************
414
 * PutVbrTag: Write final VBR tag to the file
415
 * Paramters:
416
 *				lpszFileName: filename of MP3 bit stream
417
 *				nVbrScale	: encoder quality indicator (0..100)
418
 ****************************************************************************
419
*/
420
int PutVbrTag(lame_global_flags *gfp,FILE *fpStream,int nVbrScale)
421
{
422
        lame_internal_flags * gfc = gfp->internal_flags;
423
 
424
	long lFileSize;
425
	int nStreamIndex;
426
	char abyte,bbyte;
427
	u_char		btToc[NUMTOCENTRIES];
428
	u_char pbtStreamBuffer[MAXFRAMESIZE];
429
	char str1[80];
430
        unsigned char id3v2Header[10];
431
        size_t id3v2TagSize;
432
 
433
        if (gfc->VBR_seek_table.pos <= 0)
434
		return -1;
435
 
436
 
437
	/* Clear stream buffer */
438
	memset(pbtStreamBuffer,0x00,sizeof(pbtStreamBuffer));
439
 
440
	/* Seek to end of file*/
441
	fseek(fpStream,0,SEEK_END);
442
 
443
	/* Get file size */
444
	lFileSize=ftell(fpStream);
445
 
446
	/* Abort if file has zero length. Yes, it can happen :) */
447
	if (lFileSize==0)
448
		return -1;
449
 
450
        /*
451
         * The VBR tag may NOT be located at the beginning of the stream.
452
         * If an ID3 version 2 tag was added, then it must be skipped to write
453
         * the VBR tag data.
454
         */
455
 
456
        /* seek to the beginning of the stream */
457
	fseek(fpStream,0,SEEK_SET);
458
        /* read 10 bytes in case there's an ID3 version 2 header here */
459
        fread(id3v2Header,1,sizeof id3v2Header,fpStream);
460
        /* does the stream begin with the ID3 version 2 file identifier? */
461
        if (!strncmp((char *)id3v2Header,"ID3",3)) {
462
          /* the tag size (minus the 10-byte header) is encoded into four
463
           * bytes where the most significant bit is clear in each byte */
464
          id3v2TagSize=(((id3v2Header[6] & 0x7f)<<21)
465
            | ((id3v2Header[7] & 0x7f)<<14)
466
            | ((id3v2Header[8] & 0x7f)<<7)
467
            | (id3v2Header[9] & 0x7f))
468
            + sizeof id3v2Header;
469
        } else {
470
          /* no ID3 version 2 tag in this stream */
471
          id3v2TagSize=0;
472
        }
473
 
474
	/* Seek to first real frame */
475
	fseek(fpStream,id3v2TagSize+gfp->TotalFrameSize,SEEK_SET);
476
 
477
	/* Read the header (first valid frame) */
478
	fread(pbtStreamBuffer,4,1,fpStream);
479
 
480
	/* the default VBR header. 48 kbps layer III, no padding, no crc */
481
	/* but sampling freq, mode andy copyright/copy protection taken */
482
	/* from first valid frame */
483
	pbtStreamBuffer[0]=(u_char) 0xff;
484
	abyte = (pbtStreamBuffer[1] & (char) 0xf1);
485
	{ int bitrate;
486
	if (1==gfp->version) {
487
	  bitrate = XING_BITRATE1;
488
	} else {
489
	  if (gfp->out_samplerate < 16000 )
490
	    bitrate = XING_BITRATE25;
491
	  else
492
	    bitrate = XING_BITRATE2;
493
	}
494
	  bbyte = 16*BitrateIndex(bitrate,gfp->version,gfp->out_samplerate);
495
	}
496
 
497
	/* Use as much of the info from the real frames in the
498
	 * Xing header:  samplerate, channels, crc, etc...
499
	 */ 
500
	if (gfp->version==1) {
501
	  /* MPEG1 */
502
	  pbtStreamBuffer[1]=abyte | (char) 0x0a;     /* was 0x0b; */
503
	  abyte = pbtStreamBuffer[2] & (char) 0x0d;   /* AF keep also private bit */
504
	  pbtStreamBuffer[2]=(char) bbyte | abyte;     /* 64kbs MPEG1 frame */
505
	}else{
506
	  /* MPEG2 */
507
	  pbtStreamBuffer[1]=abyte | (char) 0x02;     /* was 0x03; */
508
	  abyte = pbtStreamBuffer[2] & (char) 0x0d;   /* AF keep also private bit */
509
	  pbtStreamBuffer[2]=(char) bbyte | abyte;     /* 64kbs MPEG2 frame */
510
	}
511
 
512
 
513
	/*Seek to the beginning of the stream */
514
	fseek(fpStream,id3v2TagSize,SEEK_SET);
515
 
516
	/* Clear all TOC entries */
517
	memset(btToc,0,sizeof(btToc));
518
 
519
        Xing_seek_table (&gfc->VBR_seek_table, btToc);
520
        /* print_seeking (btToc); */
521
 
522
	/* Start writing the tag after the zero frame */
523
	nStreamIndex=gfp->nZeroStreamSize;
524
 
525
	/* Put Vbr tag */
526
	pbtStreamBuffer[nStreamIndex++]=VBRTag[0];
527
	pbtStreamBuffer[nStreamIndex++]=VBRTag[1];
528
	pbtStreamBuffer[nStreamIndex++]=VBRTag[2];
529
	pbtStreamBuffer[nStreamIndex++]=VBRTag[3];
530
 
531
	/* Put header flags */
532
	CreateI4(&pbtStreamBuffer[nStreamIndex],FRAMES_FLAG+BYTES_FLAG+TOC_FLAG+VBR_SCALE_FLAG);
533
	nStreamIndex+=4;
534
 
535
	/* Put Total Number of frames */
536
	CreateI4(&pbtStreamBuffer[nStreamIndex],gfp->nVbrNumFrames);
537
	nStreamIndex+=4;
538
 
539
	/* Put Total file size */
540
	CreateI4(&pbtStreamBuffer[nStreamIndex],(int)lFileSize);
541
	nStreamIndex+=4;
542
 
543
	/* Put TOC */
544
	memcpy(&pbtStreamBuffer[nStreamIndex],btToc,sizeof(btToc));
545
	nStreamIndex+=sizeof(btToc);
546
 
547
	/* Put VBR SCALE */
548
	CreateI4(&pbtStreamBuffer[nStreamIndex],nVbrScale);
549
	nStreamIndex+=4;
550
 
551
	/* Put LAME ID */
552
        sprintf ( str1, "LAME%s", get_lame_short_version () );
553
        strncpy ( (char*)pbtStreamBuffer + nStreamIndex, str1, 20 );
554
        nStreamIndex += 20;
555
 
556
 
557
#ifdef DEBUG_VBRTAG
558
{
559
	VBRTAGDATA TestHeader;
560
	GetVbrTag(&TestHeader,pbtStreamBuffer);
561
}
562
#endif
563
 
564
        /* Put it all to disk again */
565
	if (fwrite(pbtStreamBuffer,(unsigned int)gfp->TotalFrameSize,1,fpStream)!=1)
566
	{
567
		return -1;
568
	}
569
	/* Save to delete the frame buffer */
570
	free(gfp->pVbrFrames);
571
	gfp->pVbrFrames=NULL;
572
 
573
	return 0;       /* success */
574
}
575