You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
720 lines
18 KiB
720 lines
18 KiB
/*
|
|
* tcscan.c
|
|
*
|
|
* Copyright (C) Thomas Oestreich - June 2001
|
|
*
|
|
* This file is part of transcode, a video stream processing tool
|
|
*
|
|
* transcode is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
*
|
|
* transcode is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#undef TCF_DEBUG
|
|
|
|
#include "transcode.h"
|
|
#include "tcinfo.h"
|
|
|
|
#include "libtc/xio.h"
|
|
#include "libtc/ratiocodes.h"
|
|
#include "ioaux.h"
|
|
#include "tc.h"
|
|
#include "avilib/avilib.h"
|
|
#include <math.h>
|
|
|
|
#define EXE "tcscan"
|
|
|
|
int verbose=TC_QUIET;
|
|
|
|
int tc_get_mp3_header(unsigned char* hbuf, int* chans, int* srate, int *bitrate);
|
|
#define tc_decode_mp3_header(hbuf) tc_get_mp3_header(hbuf, NULL, NULL, NULL)
|
|
|
|
void import_exit(int code)
|
|
{
|
|
if(verbose & TC_DEBUG)
|
|
tc_log_msg(EXE, "(pid=%d) exit (code %d)", (int) getpid(), code);
|
|
exit(code);
|
|
}
|
|
|
|
#define CHUNK_SIZE 4096
|
|
|
|
static int min=0, max=0;
|
|
|
|
static void check (int v)
|
|
{
|
|
|
|
if (v > max) {
|
|
max = v;
|
|
} else if (v < min) {
|
|
min = v;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* from ac3scan.c */
|
|
|
|
static int get_ac3_bitrate(uint8_t *ptr)
|
|
{
|
|
static const int bitrates[] = {
|
|
32, 40, 48, 56,
|
|
64, 80, 96, 112,
|
|
128, 160, 192, 224,
|
|
256, 320, 384, 448,
|
|
512, 576, 640
|
|
};
|
|
int ratecode = (ptr[2] & 0x3E) >> 1;
|
|
if (ratecode < sizeof(bitrates)/sizeof(*bitrates))
|
|
return bitrates[ratecode];
|
|
return -1;
|
|
}
|
|
|
|
static int get_ac3_samplerate(uint8_t *ptr)
|
|
{
|
|
static const int samplerates[] = {48000, 44100, 32000, -1};
|
|
return samplerates[ptr[2]>>6];
|
|
}
|
|
|
|
static int get_ac3_framesize(uint8_t *ptr)
|
|
{
|
|
int bitrate = get_ac3_bitrate(ptr);
|
|
int samplerate = get_ac3_samplerate(ptr);
|
|
if (bitrate < 0 || samplerate < 0)
|
|
return -1;
|
|
return bitrate * 96000 / samplerate + (samplerate==44100 ? ptr[2]&1 : 0);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* enc_bitrate: Print bitrate information about the source data.
|
|
*
|
|
* Parameters:
|
|
* frames: Number of frames in the source.
|
|
* fps: Frames per second of the source.
|
|
* abitrate: Audio bitrate (bits per second).
|
|
* discsize: User-specified disc size in bytes, or 0 for none.
|
|
* Return value:
|
|
* None.
|
|
*/
|
|
|
|
static void enc_bitrate(long frames, double fps, int abitrate, double discsize)
|
|
{
|
|
static const int defsize[] = {650, 700, 1300, 1400};
|
|
long time;
|
|
double audiosize, videosize, vbitrate;
|
|
|
|
if (frames <= 0 || fps <= 0.0)
|
|
return;
|
|
time = frames / fps;
|
|
audiosize = (double)abitrate/8 * time;
|
|
|
|
/* Print basic source information */
|
|
printf("[%s] V: %ld frames, %ld sec @ %.3f fps\n",
|
|
EXE, frames, time, fps);
|
|
printf("[%s] A: %.2f MB @ %d kbps\n",
|
|
EXE, audiosize/(1024*1024), abitrate/1000);
|
|
|
|
/* Print recommended bitrates for user-specified or default disc sizes */
|
|
if (discsize) {
|
|
videosize = discsize - audiosize;
|
|
vbitrate = videosize / time * 8;
|
|
printf("USER CDSIZE: %4d MB | V: %6.1f MB @ %.1f kbps\n",
|
|
(int)floor(discsize/(1024*1024)), videosize/(1024*1024),
|
|
vbitrate/1024);
|
|
} else {
|
|
int i;
|
|
for (i = 0; i < sizeof(defsize) / sizeof(*defsize); i++) {
|
|
videosize = defsize[i]*1024*1024 - audiosize;
|
|
vbitrate = videosize / time * 8;
|
|
printf("USER CDSIZE: %4d MB | V: %6.1f MB @ %.1f kbps\n",
|
|
defsize[i], videosize/(1024*1024),
|
|
vbitrate/1024);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
|
|
/* ------------------------------------------------------------
|
|
*
|
|
* print a usage/version message
|
|
*
|
|
* ------------------------------------------------------------*/
|
|
|
|
void version(void)
|
|
{
|
|
/* print id string to stderr */
|
|
fprintf(stderr, "%s (%s v%s) (C) 2001-2003 Thomas Oestreich,"
|
|
" 2003-2010 Transcode Team\n",
|
|
EXE, PACKAGE, VERSION);
|
|
}
|
|
|
|
|
|
static void usage(int status)
|
|
{
|
|
version();
|
|
|
|
fprintf(stderr,"\nUsage: %s [options]\n", EXE);
|
|
|
|
fprintf(stderr," -i file input file name [stdin]\n");
|
|
fprintf(stderr," -x codec source codec\n");
|
|
fprintf(stderr," -e r[,b[,c]] PCM audio stream parameter [%d,%d,%d]\n", RATE, BITS, CHANNELS);
|
|
fprintf(stderr," -f rate,frc frame rate [%.3f][,frc]\n", PAL_FPS);
|
|
fprintf(stderr," -w num estimate bitrate for num frames\n");
|
|
fprintf(stderr," -b bitrate audio encoder bitrate kBits/s [%d]\n", ABITRATE);
|
|
fprintf(stderr," -c cdsize user defined CD size in MB [0]\n");
|
|
fprintf(stderr," -d mode verbosity mode\n");
|
|
fprintf(stderr," -v print version\n");
|
|
|
|
exit(status);
|
|
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------------------
|
|
*
|
|
* scan stream
|
|
*
|
|
* ------------------------------------------------------------*/
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
|
|
info_t ipipe;
|
|
|
|
long stream_stype = TC_STYPE_UNKNOWN;
|
|
|
|
long magic = TC_MAGIC_UNKNOWN;
|
|
|
|
FILE *in_file;
|
|
|
|
int n=0, ch;
|
|
char *codec=NULL, *name=NULL;
|
|
|
|
int bytes_per_sec, bytes_read, bframes=0;
|
|
|
|
uint64_t total=0;
|
|
|
|
int a_rate=RATE, a_bits=BITS, chan=CHANNELS;
|
|
|
|
int on=1;
|
|
short *s;
|
|
|
|
char buffer[CHUNK_SIZE];
|
|
|
|
double fps=PAL_FPS, frames, fmin, fmax, vol=0.0;
|
|
|
|
int frc;
|
|
|
|
int pseudo_frame_size=0;
|
|
|
|
int ac_bytes=0, frame_size, bitrate=ABITRATE;
|
|
|
|
float rbytes;
|
|
|
|
uint32_t i=0, j=0;
|
|
uint16_t sync_word = 0;
|
|
double cdsize = 0.0;
|
|
|
|
//proper initialization
|
|
memset(&ipipe, 0, sizeof(info_t));
|
|
|
|
libtc_init(&argc, &argv);
|
|
|
|
while ((ch = getopt(argc, argv, "c:b:e:i:vx:f:d:w:?h")) != -1) {
|
|
|
|
switch (ch) {
|
|
case 'c':
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
cdsize = atof(optarg) * (1024*1024); /* MB -> bytes */
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
verbose = atoi(optarg);
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
|
|
if (3 != sscanf(optarg,"%d,%d,%d", &a_rate, &a_bits, &chan)) {
|
|
tc_log_error(EXE, "invalid pcm parameter set for option -e");
|
|
usage(EXIT_FAILURE);
|
|
}
|
|
|
|
if(a_rate > RATE || a_rate <= 0) {
|
|
tc_log_error(EXE, "invalid pcm parameter 'rate' for option -e");
|
|
usage(EXIT_FAILURE);
|
|
}
|
|
|
|
if(!(a_bits == 16 || a_bits == 8)) {
|
|
tc_log_error(EXE, "invalid pcm parameter 'bits' for option -e");
|
|
usage(EXIT_FAILURE);
|
|
}
|
|
|
|
if(!(chan == 0 || chan == 1 || chan == 2)) {
|
|
tc_log_error(EXE, "invalid pcm parameter 'channels' for option -e");
|
|
usage(EXIT_FAILURE);
|
|
}
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
name = optarg;
|
|
break;
|
|
|
|
case 'x':
|
|
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
codec = optarg;
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
n = sscanf(optarg,"%lf,%d", &fps, &frc);
|
|
|
|
if (n == 2 && (frc > 0 && frc <= 0x10))
|
|
tc_frc_code_to_value(frc, &fps);
|
|
|
|
if(fps<=0) {
|
|
tc_log_error(EXE,"invalid frame rate for option -f");
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
bframes = atoi(optarg);
|
|
|
|
if(bframes <=0) {
|
|
tc_log_error(EXE,"invalid parameter for option -w");
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
if(optarg[0]=='-') usage(EXIT_FAILURE);
|
|
bitrate = atoi(optarg);
|
|
|
|
if(bitrate < 0) {
|
|
tc_log_error(EXE,"invalid bitrate for option -b");
|
|
exit(1);
|
|
}
|
|
break;
|
|
|
|
|
|
case 'v':
|
|
version();
|
|
exit(0);
|
|
break;
|
|
|
|
case 'h':
|
|
usage(EXIT_SUCCESS);
|
|
default:
|
|
usage(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
ac_init(AC_ALL);
|
|
|
|
/* ------------------------------------------------------------
|
|
*
|
|
* fill out defaults for info structure
|
|
*
|
|
* ------------------------------------------------------------*/
|
|
|
|
// simple bitrate calculator
|
|
if(bframes) {
|
|
enc_bitrate(bframes, fps, bitrate*1000, cdsize);
|
|
exit(0);
|
|
}
|
|
|
|
// assume defaults
|
|
if(name==NULL) stream_stype=TC_STYPE_STDIN;
|
|
|
|
// no autodetection yet
|
|
if(codec==NULL && name == NULL) {
|
|
tc_log_error(EXE, "invalid codec %s", codec);
|
|
usage(EXIT_FAILURE);
|
|
}
|
|
|
|
if(codec==NULL) codec="";
|
|
|
|
// do not try to mess with the stream
|
|
if(stream_stype!=TC_STYPE_STDIN) {
|
|
|
|
if(tc_file_check(name)) exit(1);
|
|
|
|
if((ipipe.fd_in = xio_open(name, O_RDONLY))<0) {
|
|
tc_log_perror(EXE, "open file");
|
|
exit(1);
|
|
}
|
|
|
|
magic = fileinfo(ipipe.fd_in, 0);
|
|
|
|
} else ipipe.fd_in = STDIN_FILENO;
|
|
|
|
|
|
/* ------------------------------------------------------------
|
|
*
|
|
* AC3 stream
|
|
*
|
|
* ------------------------------------------------------------*/
|
|
|
|
if(strcmp(codec,"ac3")==0 || magic==TC_MAGIC_AC3) {
|
|
|
|
|
|
for(;;) {
|
|
|
|
for(;;) {
|
|
|
|
if (tc_pread(ipipe.fd_in, buffer, 1) !=1) {
|
|
tc_log_perror(EXE, "ac3 sync frame scan failed");
|
|
goto ac3_summary;
|
|
}
|
|
|
|
sync_word = (sync_word << 8) + (uint8_t) buffer[0];
|
|
|
|
++i;
|
|
|
|
if(sync_word == 0x0b77) break;
|
|
}
|
|
|
|
i=i-2;
|
|
|
|
if (tc_pread(ipipe.fd_in, buffer, 3) !=3) {
|
|
tc_log_perror(EXE, "ac3 header read failed");
|
|
goto ac3_summary;
|
|
}
|
|
|
|
if((frame_size = 2*get_ac3_framesize(buffer)) < 1) {
|
|
tc_log_warn(EXE, "ac3 framesize %d invalid - frame broken?", frame_size);
|
|
goto more;
|
|
}
|
|
|
|
//FIXME: I assume that a single AC3 frame contains 6kB PCM bytes
|
|
|
|
rbytes = (float) SIZE_PCM_FRAME/1024/6 * frame_size;
|
|
pseudo_frame_size = (int) rbytes;
|
|
bitrate = get_ac3_bitrate(buffer);
|
|
|
|
printf("[%s] [%05d] offset %06d (%06d) %04d bytes, bitrate %03d kBits/s\n", EXE, n++, i, j, frame_size, bitrate);
|
|
|
|
// read the rest
|
|
|
|
ac_bytes = frame_size-5;
|
|
|
|
if(ac_bytes>CHUNK_SIZE) {
|
|
tc_log_error(EXE, "Oops, no buffer space framesize %d", ac_bytes);
|
|
exit(1);
|
|
}
|
|
|
|
if ((bytes_read=tc_pread(ipipe.fd_in, buffer, ac_bytes)) != ac_bytes) {
|
|
tc_log_warn(EXE, "error reading ac3 frame (%d/%d)", bytes_read, ac_bytes);
|
|
break;
|
|
}
|
|
|
|
more:
|
|
|
|
i+=frame_size;
|
|
j=i;
|
|
}
|
|
|
|
ac3_summary:
|
|
|
|
vol = (double) (n * 1024 * 6)/4/RATE;
|
|
|
|
printf("[%s] valid AC3 frames=%d, estimated clip length=%.2f seconds\n", EXE, n, vol);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
*
|
|
* PCM stream
|
|
*
|
|
* ------------------------------------------------------------*/
|
|
|
|
if(strcmp(codec,"pcm")==0) {
|
|
|
|
while(on) {
|
|
|
|
if( (bytes_read = tc_pread(ipipe.fd_in, buffer, CHUNK_SIZE)) != CHUNK_SIZE) on = 0;
|
|
|
|
total += (uint64_t) bytes_read;
|
|
|
|
s=(short *) buffer;
|
|
|
|
for(n=0; n<bytes_read>>1; ++n) {
|
|
check((int) (*s));
|
|
s++;
|
|
}
|
|
}
|
|
|
|
bytes_per_sec = a_rate * (a_bits/8) * chan;
|
|
|
|
frames = (fps*((double)total)/bytes_per_sec);
|
|
|
|
fmin = -((double) min)/SHRT_MAX;
|
|
fmax = ((double) max)/SHRT_MAX;
|
|
|
|
if(min==0 || max == 0) exit(0);
|
|
|
|
vol = (fmin<fmax) ? 1./fmax : 1./fmin;
|
|
|
|
printf("[%s] audio frames=%.2f, estimated clip length=%.2f seconds\n", EXE, frames, frames/fps);
|
|
printf("[%s] (min/max) amplitude=(%.3f/%.3f), suggested volume rescale=%.3f\n", EXE, -fmin, fmax, vol);
|
|
|
|
enc_bitrate((long) frames, fps, bitrate*1000, cdsize);
|
|
|
|
return(0);
|
|
}
|
|
|
|
if(strcmp(codec,"mp3")==0 || magic == TC_MAGIC_MP3) {
|
|
|
|
char header[4];
|
|
int framesize = 0;
|
|
int chunks = 0;
|
|
int srate=0 , chans=0, bitrate=0;
|
|
unsigned long bitrate_add = 0;
|
|
off_t pos=0;
|
|
double ms = 0;
|
|
char bitrate_buf[TC_BUF_MIN];
|
|
|
|
min = 500;
|
|
max = 0;
|
|
|
|
pos = lseek(ipipe.fd_in, 0, SEEK_CUR);
|
|
// find mp3 header
|
|
while ((total += read(ipipe.fd_in, header, 4))) {
|
|
if ( (framesize = tc_get_mp3_header (header, &chans, &srate, &bitrate)) > 0) {
|
|
break;
|
|
}
|
|
pos++;
|
|
lseek(ipipe.fd_in, pos, SEEK_SET);
|
|
}
|
|
tc_log_msg(EXE, "POS %lld", (long long)pos);
|
|
|
|
// Example for _1_ mp3 chunk
|
|
//
|
|
// fps = 25
|
|
// framesize = 480 bytes
|
|
// bitrate = 160 kbit/s == 20 kbytes/s == 20480 bytes/s == 819.20 bytes / frame
|
|
//
|
|
// 480 bytes = 480/20480 s/bytes = .0234 s = 23.4 ms
|
|
//
|
|
// ms = (framesize*1000*8)/(bitrate*1000);
|
|
// why 1000 and not 1024?
|
|
// correct? yes! verified with "cat file.mp3|mpg123 -w /dev/null -v -" -- tibit
|
|
|
|
while (on) {
|
|
if ( (bytes_read = read(ipipe.fd_in, buffer, framesize-4)) != framesize-4) {
|
|
on = 0;
|
|
} else {
|
|
total += bytes_read;
|
|
while ((total += read(ipipe.fd_in, header, 4))) {
|
|
|
|
//tc_log_msg(EXE, "%x %x %x %x", header[0]&0xff, header[1]&0xff, header[2]&0xff, header[3]&0xff);
|
|
|
|
if ( (framesize = tc_get_mp3_header (header, &chans, &srate, &bitrate)) < 0) {
|
|
tc_log_warn(EXE, "corrupt mp3 file?");
|
|
on = 0;
|
|
break;
|
|
} else {
|
|
|
|
/*
|
|
tc_log_msg(EXE, "Found new header (%d) (framesize = %d) chan(%d) srate(%d) bitrate(%d)",
|
|
chunks, framesize, chans, srate, bitrate);
|
|
*/
|
|
|
|
bitrate_add += bitrate;
|
|
check(bitrate);
|
|
ms += (framesize*8)/(bitrate);
|
|
++chunks;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
if (min != max)
|
|
tc_snprintf(bitrate_buf, sizeof(bitrate_buf), "(%d-%d)", min, max);
|
|
else
|
|
tc_snprintf(bitrate_buf, sizeof(bitrate_buf), "(cbr)");
|
|
printf("[%s] MPEG-1 layer-3 stream. Info: -e %d,%d,%d\n", EXE,
|
|
srate, 16, chans);
|
|
printf("[%s] Found %d MP3 chunks. Average bitrate is %3.2f kbps %s\n", EXE,
|
|
chunks, (double)bitrate_add/chunks, bitrate_buf);
|
|
printf("[%s] AVI overhead will be max. %d*(8+16) = %d bytes (%dk)\n", EXE,
|
|
chunks, chunks*8+chunks*16, (chunks*8+chunks*16)/1024);
|
|
printf("[%s] Estimated time is %.0f ms (%02d:%02d:%02d.%02d)\n", EXE,
|
|
ms,
|
|
(int)(ms/1000.0/60.0/60.0),
|
|
(int)(ms/1000.0/60.0)%60,
|
|
(int)(ms/1000)%60,
|
|
(int)(ms)%(1000));
|
|
return(0);
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
*
|
|
* MPEG program stream
|
|
*
|
|
* ------------------------------------------------------------*/
|
|
|
|
if(strcmp(codec, "mpeg2")==0 || strcmp(codec, "mpeg")==0 || strcmp(codec, "vob")==0 || magic==TC_MAGIC_VOB || magic==TC_MAGIC_M2V) {
|
|
|
|
in_file = fdopen(ipipe.fd_in, "r");
|
|
|
|
scan_pes(verbose, in_file);
|
|
|
|
return(0);
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
*
|
|
* AVI
|
|
*
|
|
* ------------------------------------------------------------*/
|
|
|
|
if(magic==TC_MAGIC_AVI || TC_MAGIC_WAV) {
|
|
|
|
if(name!=NULL) AVI_scan(name);
|
|
|
|
return(0);
|
|
}
|
|
|
|
|
|
tc_log_error(EXE, "unable to handle codec/filetype %s", codec);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
// from mencoder
|
|
//----------------------- mp3 audio frame header parser -----------------------
|
|
|
|
static int tabsel_123[2][3][16] = {
|
|
{ {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0},
|
|
{0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0},
|
|
{0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0} },
|
|
|
|
{ {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,0},
|
|
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0},
|
|
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,0} }
|
|
};
|
|
static long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 };
|
|
|
|
/*
|
|
* return frame size or -1 (bad frame)
|
|
*/
|
|
int tc_get_mp3_header(unsigned char* hbuf, int* chans, int* srate, int *bitrate){
|
|
int stereo, ssize, crc, lsf, mpeg25, framesize;
|
|
int padding, bitrate_index, sampling_frequency;
|
|
unsigned long newhead =
|
|
hbuf[0] << 24 |
|
|
hbuf[1] << 16 |
|
|
hbuf[2] << 8 |
|
|
hbuf[3];
|
|
|
|
|
|
#if 1
|
|
// head_check:
|
|
if( (newhead & 0xffe00000) != 0xffe00000 ||
|
|
(newhead & 0x0000fc00) == 0x0000fc00){
|
|
//tc_log_warn(EXE, "head_check failed");
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
if((4-((newhead>>17)&3))!=3){
|
|
//tc_log_warn(EXE, "not layer-3");
|
|
return -1;
|
|
}
|
|
|
|
if( newhead & ((long)1<<20) ) {
|
|
lsf = (newhead & ((long)1<<19)) ? 0x0 : 0x1;
|
|
mpeg25 = 0;
|
|
} else {
|
|
lsf = 1;
|
|
mpeg25 = 1;
|
|
}
|
|
|
|
if(mpeg25)
|
|
sampling_frequency = 6 + ((newhead>>10)&0x3);
|
|
else
|
|
sampling_frequency = ((newhead>>10)&0x3) + (lsf*3);
|
|
|
|
if(sampling_frequency>8){
|
|
tc_log_warn(EXE, "invalid sampling_frequency");
|
|
return -1; // valid: 0..8
|
|
}
|
|
|
|
crc = ((newhead>>16)&0x1)^0x1;
|
|
bitrate_index = ((newhead>>12)&0xf);
|
|
padding = ((newhead>>9)&0x1);
|
|
// fr->extension = ((newhead>>8)&0x1);
|
|
// fr->mode = ((newhead>>6)&0x3);
|
|
// fr->mode_ext = ((newhead>>4)&0x3);
|
|
// fr->copyright = ((newhead>>3)&0x1);
|
|
// fr->original = ((newhead>>2)&0x1);
|
|
// fr->emphasis = newhead & 0x3;
|
|
|
|
stereo = ( (((newhead>>6)&0x3)) == 3) ? 1 : 2;
|
|
|
|
if(!bitrate_index){
|
|
tc_log_warn(EXE, "Free format not supported.");
|
|
return -1;
|
|
}
|
|
|
|
if(lsf)
|
|
ssize = (stereo == 1) ? 9 : 17;
|
|
else
|
|
ssize = (stereo == 1) ? 17 : 32;
|
|
if(crc) ssize += 2;
|
|
|
|
framesize = tabsel_123[lsf][2][bitrate_index] * 144000;
|
|
if (bitrate) *bitrate = tabsel_123[lsf][2][bitrate_index];
|
|
|
|
if(!framesize){
|
|
tc_log_warn(EXE, "invalid framesize/bitrate_index");
|
|
return -1; // valid: 1..14
|
|
}
|
|
|
|
framesize /= freqs[sampling_frequency]<<lsf;
|
|
framesize += padding;
|
|
|
|
// if(framesize<=0 || framesize>MAXFRAMESIZE) return FALSE;
|
|
if(srate) *srate = freqs[sampling_frequency];
|
|
if(chans) *chans = stereo;
|
|
|
|
return framesize;
|
|
}
|
|
|
|
#include "libtc/static_xio.h"
|