586 lines
21 KiB
C
586 lines
21 KiB
C
/*
|
|
* @DEC_COPYRIGHT@
|
|
*/
|
|
/*
|
|
* HISTORY
|
|
* $Log: slib_audio.c,v $
|
|
* Revision 1.1.6.14 1996/12/13 18:19:06 Hans_Graves
|
|
* Added initialization of AudioPTimeBase.
|
|
* [1996/12/13 18:07:26 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.13 1996/12/04 22:34:30 Hans_Graves
|
|
* Make AC3 detection in audio streams more accurate.
|
|
* [1996/12/04 22:19:21 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.12 1996/11/18 23:07:34 Hans_Graves
|
|
* Make use of presentation timestamps. Make seeking time-based.
|
|
* [1996/11/18 22:47:36 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.11 1996/11/11 18:21:06 Hans_Graves
|
|
* Added AC3 support for multiplexed streams.
|
|
* [1996/11/11 18:00:25 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.10 1996/11/08 21:51:04 Hans_Graves
|
|
* Added AC3 support. Better seperation of stream types.
|
|
* [1996/11/08 21:28:01 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.9 1996/10/28 17:32:30 Hans_Graves
|
|
* MME-1402, 1431, 1435: Timestamp related changes.
|
|
* [1996/10/28 17:23:01 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.8 1996/10/15 17:34:11 Hans_Graves
|
|
* Added MPEG-2 Program Stream support. Fix MPEG-2 not skipping audio.
|
|
* [1996/10/15 17:31:11 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.7 1996/09/29 22:19:39 Hans_Graves
|
|
* Removed SLIB_MODE_DECOMPRESS_QUERY.
|
|
* [1996/09/29 21:33:10 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.6 1996/09/25 19:16:46 Hans_Graves
|
|
* Added SLIB_INTERNAL define.
|
|
* [1996/09/25 19:01:51 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.5 1996/09/18 23:46:37 Hans_Graves
|
|
* Use slibSetMaxInput under MPEG
|
|
* [1996/09/18 22:03:03 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.4 1996/05/24 12:39:52 Hans_Graves
|
|
* Disable debugging printfs
|
|
* [1996/05/24 12:39:37 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.3 1996/05/23 18:46:37 Hans_Graves
|
|
* Merge fixes MME-1292, MME-1293, and MME-1304.
|
|
* [1996/05/23 18:45:22 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.2 1996/05/10 21:17:20 Hans_Graves
|
|
* Fix calculation of audio lengths (NT)
|
|
* [1996/05/10 20:44:27 Hans_Graves]
|
|
*
|
|
* Revision 1.1.4.4 1996/04/22 15:04:53 Hans_Graves
|
|
* Added slibValidateAudioParams()
|
|
* [1996/04/22 14:43:35 Hans_Graves]
|
|
*
|
|
* Revision 1.1.4.3 1996/04/01 16:23:14 Hans_Graves
|
|
* NT porting
|
|
* [1996/04/01 16:15:58 Hans_Graves]
|
|
*
|
|
* Revision 1.1.4.2 1996/03/29 22:21:33 Hans_Graves
|
|
* Added MPEG/JPEG/H261_SUPPORT ifdefs
|
|
* [1996/03/29 21:56:58 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.12 1996/02/21 22:52:45 Hans_Graves
|
|
* Fixed MPEG 2 systems stuff
|
|
* [1996/02/21 22:51:03 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.11 1996/02/19 18:03:56 Hans_Graves
|
|
* Fixed a number of MPEG related bugs
|
|
* [1996/02/19 17:57:40 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.10 1996/02/13 18:47:48 Hans_Graves
|
|
* Added slibSkipAudio()
|
|
* [1996/02/13 18:41:27 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.9 1996/02/07 23:23:56 Hans_Graves
|
|
* Added SEEK_EXACT. Fixed most frame counting problems.
|
|
* [1996/02/07 23:20:31 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.8 1996/02/02 17:36:03 Hans_Graves
|
|
* Enhanced audio info. Cleaned up API
|
|
* [1996/02/02 17:29:46 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.7 1996/01/31 14:50:39 Hans_Graves
|
|
* Renamed SLIB_TYPE_WAVE to SLIB_TYPE_PCM_WAVE
|
|
* [1996/01/31 14:50:27 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.6 1996/01/15 16:26:29 Hans_Graves
|
|
* Added MPEG 1 Audio compression support
|
|
* [1996/01/15 15:46:07 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.5 1996/01/11 16:17:31 Hans_Graves
|
|
* Added MPEG II Systems decode support
|
|
* [1996/01/11 16:12:35 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.4 1996/01/08 16:41:32 Hans_Graves
|
|
* Added MPEG II decoding support
|
|
* [1996/01/08 15:53:05 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.3 1995/11/09 23:14:06 Hans_Graves
|
|
* Added MPEG audio decompression
|
|
* [1995/11/09 23:08:41 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.2 1995/11/06 18:47:55 Hans_Graves
|
|
* First time under SLIB
|
|
* [1995/11/06 18:36:03 Hans_Graves]
|
|
*
|
|
* $EndLog$
|
|
*/
|
|
/*****************************************************************************
|
|
** Copyright (c) Digital Equipment Corporation, 1995 **
|
|
** **
|
|
** All Rights Reserved. Unpublished rights reserved under the copyright **
|
|
** laws of the United States. **
|
|
** **
|
|
** The software contained on this media is proprietary to and embodies **
|
|
** the confidential technology of Digital Equipment Corporation. **
|
|
** Possession, use, duplication or dissemination of the software and **
|
|
** media is authorized only pursuant to a valid written license from **
|
|
** Digital Equipment Corporation. **
|
|
** **
|
|
** RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. **
|
|
** Government is subject to restrictions as set forth in Subparagraph **
|
|
** (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. **
|
|
******************************************************************************/
|
|
/*
|
|
#define _SLIBDEBUG_
|
|
*/
|
|
|
|
#define SLIB_INTERNAL
|
|
#include "slib.h"
|
|
#include "mpeg.h"
|
|
#include "avi.h"
|
|
#ifdef AC3_SUPPORT
|
|
#include "ac3.h"
|
|
#endif /* AC3_SUPPORT */
|
|
|
|
#ifdef _SLIBDEBUG_
|
|
#define _DEBUG_ 1 /* detailed debuging statements */
|
|
#define _VERBOSE_ 1 /* show progress */
|
|
#define _VERIFY_ 1 /* verify correct operation */
|
|
#define _WARN_ 1 /* warnings about strange behavior */
|
|
#endif
|
|
|
|
#ifdef AC3_SUPPORT
|
|
SlibBoolean_t slibParseAC3Header(SlibInfo_t *Info, SlibPin_t *srcpin,
|
|
unsigned char *buf, unsigned dword size,
|
|
int *channels, int *sps, int *bps)
|
|
{
|
|
/*
|
|
* Initial cut at parameters -
|
|
* Update later using header parsing - ***tfm***
|
|
*/
|
|
Info->AudioBitRate = 256000;
|
|
*channels = 2;
|
|
*sps = 48000;
|
|
*bps = 16;
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("AC3: bitrate=%d channels=%d sps=%d bps=%s\n",
|
|
Info->AudioBitRate, channels, sps, bps) );
|
|
return(TRUE);
|
|
}
|
|
#endif /* AC3_SUPPORT */
|
|
|
|
void SlibUpdateAudioInfo(SlibInfo_t *Info)
|
|
{
|
|
int channels=2, sps=44100, bps=16;
|
|
SlibTime_t ptime=SLIB_TIME_NONE;
|
|
_SlibDebug(_DEBUG_, printf("SlibUpdateAudioInfo()\n") );
|
|
|
|
if (SlibTypeIsVideoOnly(Info->Type)) /* no audio? */
|
|
return;
|
|
if (Info->Mode == SLIB_MODE_COMPRESS)
|
|
{
|
|
switch (Info->Type)
|
|
{
|
|
case SLIB_TYPE_G723:
|
|
//Initialize some info
|
|
sps = 8000;
|
|
bps = 16;
|
|
channels =1;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else if (Info->Mode == SLIB_MODE_DECOMPRESS)
|
|
{
|
|
SlibPin_t *srcpin;
|
|
unsigned char *buf;
|
|
unsigned dword size;
|
|
|
|
switch (Info->Type)
|
|
{
|
|
case SLIB_TYPE_RIFF: /* might be WAVE format */
|
|
case SLIB_TYPE_PCM_WAVE: /* might be WAVE format */
|
|
srcpin=slibGetPin(Info, SLIB_DATA_COMPRESSED);
|
|
buf = slibSearchBuffersOnPin(Info, srcpin,
|
|
NULL, &size, RIFF_WAVE, 4, FALSE);
|
|
if (buf)
|
|
{
|
|
Info->Type = SLIB_TYPE_PCM_WAVE;
|
|
buf = slibSearchBuffersOnPin(Info, srcpin,
|
|
NULL, &size, RIFF_FORMAT, 4, FALSE);
|
|
if (buf)
|
|
{
|
|
dword datasize=((int)buf[3]<<24) | (int)buf[2]<<16 |
|
|
(int)buf[1]<<8 | (int)buf[0];
|
|
WAVE_format fmt;
|
|
|
|
_SlibDebug(_DEBUG_,
|
|
printf("datasize=%d\n", datasize);
|
|
printf("%02X %02X %02X %02X\n", buf[0], buf[1], buf[2], buf[3]);
|
|
printf("WAVE: SamplesPerSec=%d BitsPerSample=%d Channels=%d\n",
|
|
sps, bps, channels) );
|
|
buf+=4; /* skip size */
|
|
memcpy(&fmt, buf, sizeof(fmt));
|
|
channels = fmt.nChannels;
|
|
sps = fmt.nSamplesPerSec;
|
|
if (datasize<sizeof(WAVE_format)) /* not PCM */
|
|
bps = 8;
|
|
else
|
|
bps = fmt.wBitsPerSample;
|
|
if ((sps*channels*bps)>800)
|
|
Info->AudioLength = (qword)(Info->FileSize*10L)/
|
|
(qword)((sps*channels*bps)/800);
|
|
if ((srcpin=slibLoadPin(Info, SLIB_DATA_AUDIO))==NULL)
|
|
return;
|
|
Info->AudioType=SLIB_TYPE_PCM;
|
|
}
|
|
else
|
|
return; /* couldn't find format */
|
|
}
|
|
break;
|
|
|
|
#ifdef MPEG_SUPPORT
|
|
case SLIB_TYPE_MPEG1_AUDIO:
|
|
case SLIB_TYPE_MPEG_SYSTEMS:
|
|
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
|
|
case SLIB_TYPE_MPEG_TRANSPORT:
|
|
case SLIB_TYPE_MPEG_PROGRAM:
|
|
slibSetMaxInput(Info, 1000*1024);
|
|
if ((srcpin=slibLoadPin(Info, SLIB_DATA_AUDIO))==NULL)
|
|
{
|
|
_SlibDebug(_DEBUG_ || _WARN_,
|
|
printf("SlibUpdateAudioInfo() no audio data found\n") );
|
|
if ((srcpin=slibLoadPin(Info, SLIB_DATA_PRIVATE))==NULL)
|
|
{
|
|
Info->AudioStreams = 0;
|
|
_SlibDebug(_DEBUG_ || _WARN_,
|
|
printf("SlibUpdateAudioInfo() no private data found\n") );
|
|
slibSetMaxInput(Info, 0); /* no limit to input data */
|
|
return;
|
|
}
|
|
buf=slibGetBufferFromPin(Info, srcpin, &size, NULL);
|
|
if (buf && size>=4)
|
|
{
|
|
_SlibDebug(_DEBUG_,
|
|
printf("AC3 Audio Head: %02X %02X %02X %02X\n",
|
|
buf[0], buf[1], buf[2], buf[3]));
|
|
/* check for AC3 sync code, may be reverse ordered */
|
|
if ((buf[0]==0x0B && buf[1]==0x77) ||
|
|
(buf[2]==0x0B && buf[3]==0x77) ||
|
|
(buf[0]==0x77 && buf[1]==0x0B) ||
|
|
(buf[2]==0x77 && buf[3]==0x0B))
|
|
{
|
|
Info->AudioType=SLIB_TYPE_AC3_AUDIO;
|
|
_SlibDebug(_DEBUG_, printf("AC3 Audio Sync Word found\n") );
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Info->AudioType==SLIB_TYPE_UNKNOWN ||
|
|
Info->AudioType==SLIB_TYPE_MPEG1_AUDIO)
|
|
{
|
|
/* search for MPEG audio sync word */
|
|
buf = NULL;
|
|
slibSetMaxInput(Info, 10*1024); /* don't search too much */
|
|
do {
|
|
buf = slibSearchBuffersOnPin(Info, srcpin, buf, &size,
|
|
0xFF, 1, FALSE);
|
|
} while (buf && (*buf&0xF0) != 0xF0);
|
|
slibSetMaxInput(Info, 0); /* no limit to input data */
|
|
if (buf)
|
|
{
|
|
const char *mode_names[4] =
|
|
{ "stereo", "j-stereo", "dual-ch", "single-ch" };
|
|
const char *layer_names[4] = { "?", "I", "II", "III" };
|
|
const int mpeg_freq[4] = {44100, 48000, 32000, 0};
|
|
const int bitrate[4][15] = {
|
|
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
|
|
{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
|
|
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
|
|
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}
|
|
};
|
|
int bitrate_index, layer, mode, freq_index;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("MPEG Audio Head: %02X %02X %02X %02X\n",
|
|
buf[0], buf[1], buf[2], buf[3]));
|
|
if ((*buf & 0xF0)==0xF0)
|
|
{
|
|
layer = 4-((*buf>>1) & 0x03);
|
|
buf++; size--;
|
|
bitrate_index = *buf >> 4;
|
|
freq_index = (*buf>>2) & 0x03;
|
|
buf++; size--;
|
|
mode = *buf >> 6;
|
|
|
|
Info->AudioBitRate = bitrate[layer][bitrate_index]*1000;
|
|
channels = mode==3 ? 1 : 2;
|
|
sps = mpeg_freq[freq_index];
|
|
bps = 16;
|
|
if (Info->AudioBitRate>100)
|
|
Info->AudioLength = (qword)(Info->FileSize*80L)/
|
|
(qword)(Info->AudioBitRate/100);
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("layer=%d bitrate=%d(%d) mode=%s freq(%d)=%d\n",
|
|
layer, bitrate[layer][bitrate_index], bitrate_index,
|
|
mode_names[mode], freq_index, mpeg_freq[freq_index]) );
|
|
if (layer<=2 && Info->AudioBitRate>0 &&
|
|
Info->AudioBitRate<10000000) /* valid header */
|
|
Info->AudioType=SLIB_TYPE_MPEG1_AUDIO;
|
|
else
|
|
Info->AudioBitRate=0;
|
|
}
|
|
}
|
|
}
|
|
if (Info->AudioType==SLIB_TYPE_UNKNOWN ||
|
|
Info->AudioType==SLIB_TYPE_AC3_AUDIO)
|
|
{
|
|
#ifdef AC3_SUPPORT
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("Searching for AC-3 on %s\n", srcpin->name) );
|
|
/* Search for AC-3 sync word */
|
|
slibSetMaxInput(Info, 1000*1024);
|
|
buf = slibSearchBuffersOnPin(Info, srcpin, NULL, &size,
|
|
AC3_SYNC_WORD_REV, AC3_SYNC_WORD_LEN/8, FALSE);
|
|
slibSetMaxInput(Info, 0); /* no limit to input data */
|
|
if (buf) /* found sync word */
|
|
{
|
|
Info->AudioType=SLIB_TYPE_AC3_AUDIO;
|
|
_SlibDebug(_VERBOSE_, printf("AC3\n"));
|
|
slibParseAC3Header(Info, srcpin, buf, size,
|
|
&channels, &sps, &bps);
|
|
if (srcpin->ID==SLIB_DATA_PRIVATE)
|
|
{
|
|
/* the private data pin now become the audio pin */
|
|
slibRenamePin(Info, SLIB_DATA_PRIVATE, SLIB_DATA_AUDIO,
|
|
"Audio");
|
|
/* audio will be pulled from PRIVATE packets */
|
|
Info->AudioMainStream=MPEG_PRIVATE_STREAM1_BASE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
slibRemovePin(Info, SLIB_DATA_AUDIO);
|
|
return;
|
|
}
|
|
#else /* !AC3_SUPPORT */
|
|
slibRemovePin(Info, SLIB_DATA_AUDIO);
|
|
return;
|
|
#endif /* !AC3_SUPPORT */
|
|
}
|
|
break;
|
|
#endif /* MPEG_SUPPORT */
|
|
#ifdef AC3_SUPPORT
|
|
case SLIB_TYPE_AC3_AUDIO:
|
|
slibSetMaxInput(Info, 1000*1024);
|
|
if ((srcpin=slibLoadPin(Info, SLIB_DATA_AUDIO))==NULL)
|
|
{
|
|
Info->AudioStreams = 0;
|
|
_SlibDebug(_DEBUG_ || _WARN_,
|
|
printf("SlibUpdateAudioInfo() no audio data found\n") );
|
|
slibSetMaxInput(Info, 0);
|
|
return;
|
|
}
|
|
|
|
/* buf = slibGetBufferFromPin(Info, srcpin, &size, NULL); */
|
|
|
|
/* Search for AC-3 sync word */
|
|
buf = slibSearchBuffersOnPin(Info, srcpin, NULL, &size,
|
|
AC3_SYNC_WORD_REV, AC3_SYNC_WORD_LEN/8, FALSE);
|
|
slibSetMaxInput(Info, 0);
|
|
if (buf)
|
|
{
|
|
slibParseAC3Header(Info, srcpin, buf, size,
|
|
&channels, &sps, &bps);
|
|
if (Info->AudioBitRate>100)
|
|
Info->AudioLength = (qword)(Info->FileSize*80L)/
|
|
(qword)(Info->AudioBitRate/100);
|
|
}
|
|
else
|
|
{
|
|
slibRemovePin(Info, SLIB_DATA_AUDIO);
|
|
return;
|
|
}
|
|
Info->AudioType=SLIB_TYPE_AC3_AUDIO;
|
|
break;
|
|
#endif /* AC3_SUPPORT */
|
|
#ifdef G723_SUPPORT
|
|
case SLIB_TYPE_G723:
|
|
slibSetMaxInput(Info, 1000*1024);
|
|
if ((srcpin=slibLoadPin(Info, SLIB_DATA_AUDIO))==NULL)
|
|
{
|
|
Info->AudioStreams = 0;
|
|
_SlibDebug(_DEBUG_ || _WARN_,
|
|
printf("SlibUpdateAudioInfo() no audio data found\n") );
|
|
slibSetMaxInput(Info, 0);
|
|
return;
|
|
}
|
|
slibSetMaxInput(Info, 0);
|
|
buf = slibPeekBufferOnPin(Info, srcpin, &size, NULL);
|
|
if (buf)
|
|
{
|
|
/* we need to parse the G.723 frame header to
|
|
* get the actual bitrate
|
|
*/
|
|
if(buf[0] & 0x1) /* read the rate bit in the G.723 frame header */
|
|
Info->AudioBitRate=5333;
|
|
else
|
|
Info->AudioBitRate=6400;
|
|
if (Info->AudioBitRate>0)
|
|
Info->AudioLength = (qword)(Info->FileSize*80L)/
|
|
(qword)(Info->AudioBitRate/100);
|
|
}
|
|
else
|
|
{
|
|
slibRemovePin(Info, SLIB_DATA_AUDIO);
|
|
return;
|
|
}
|
|
//Initialize some info
|
|
sps = 8000;
|
|
bps = 16;
|
|
channels =1;
|
|
Info->AudioType=SLIB_TYPE_G723;
|
|
break;
|
|
#endif /*G723_SUPPORT*/
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
Info->AudioStreams = 1;
|
|
if (SlibTypeHasTimeStamps(Info->Type))
|
|
{
|
|
ptime=slibGetNextTimeOnPin(Info, slibGetPin(Info, SLIB_DATA_AUDIO), 100*1024);
|
|
if (SlibTimeIsValid(ptime))
|
|
Info->AudioPTimeBase=ptime;
|
|
}
|
|
/* round sample rate to nearest valid rate */
|
|
if (sps<=8000)
|
|
sps=8000;
|
|
else if (sps<=11025)
|
|
sps=11025;
|
|
else if (sps<=22050)
|
|
sps=22050;
|
|
else if (sps<=32000)
|
|
sps=32000;
|
|
else if (sps<=44100)
|
|
sps=44100;
|
|
Info->SamplesPerSec = sps;
|
|
Info->BitsPerSample = bps;
|
|
Info->Channels = channels;
|
|
if (Info->CompAudioFormat==NULL)
|
|
Info->CompAudioFormat=(WAVEFORMATEX *)ScAlloc(sizeof(WAVEFORMATEX));
|
|
if (Info->CompAudioFormat!=NULL)
|
|
{
|
|
Info->CompAudioFormat->wFormatTag = WAVE_FORMAT_PCM;
|
|
Info->CompAudioFormat->nChannels = (WORD)channels;
|
|
Info->CompAudioFormat->wBitsPerSample = (WORD)bps;
|
|
Info->CompAudioFormat->nSamplesPerSec = sps;
|
|
Info->CompAudioFormat->nBlockAlign = bps>>3 * channels;
|
|
Info->CompAudioFormat->nAvgBytesPerSec =
|
|
Info->CompAudioFormat->nBlockAlign * sps;
|
|
}
|
|
if (Info->AudioFormat==NULL)
|
|
Info->AudioFormat=(WAVEFORMATEX *)ScAlloc(sizeof(WAVEFORMATEX));
|
|
if (Info->AudioFormat!=NULL)
|
|
{
|
|
Info->AudioFormat->wFormatTag = WAVE_FORMAT_PCM;
|
|
Info->AudioFormat->nChannels = (WORD)channels;
|
|
Info->AudioFormat->wBitsPerSample = (WORD)bps;
|
|
Info->AudioFormat->nSamplesPerSec = sps;
|
|
Info->AudioFormat->nBlockAlign = (bps>>3) * channels;
|
|
Info->AudioFormat->nAvgBytesPerSec =
|
|
Info->AudioFormat->nBlockAlign * sps;
|
|
}
|
|
}
|
|
|
|
SlibTime_t slibSkipAudio(SlibInfo_t *Info, SlibStream_t stream,
|
|
SlibTime_t timems)
|
|
{
|
|
dword timeskipped=0, samples=0, frames=0;
|
|
SlibPin_t *srcpin;
|
|
if (Info->AudioStreams<=0)
|
|
return(0);
|
|
srcpin=slibLoadPin(Info, SLIB_DATA_AUDIO);
|
|
if (!srcpin)
|
|
return(0);
|
|
_SlibDebug(_VERBOSE_, printf("slibSkipAudio(stream=%d, %d ms)\n",
|
|
stream,timems) );
|
|
switch (Info->AudioType)
|
|
{
|
|
#ifdef MPEG_SUPPORT
|
|
case SLIB_TYPE_MPEG1_AUDIO:
|
|
{
|
|
unsigned char *buf, *bufstart;
|
|
unsigned dword size, sps, channels, layer;
|
|
static const int layer_samples[4] = {384, 384, 1152, 1152};
|
|
static const int mpeg_freq[4] = {44100, 48000, 32000, 0};
|
|
while (timeskipped<timems)
|
|
{
|
|
do {
|
|
bufstart=buf=slibSearchBuffersOnPin(Info, srcpin, NULL, &size,
|
|
0xFF, 1, TRUE);
|
|
_SlibDebug(_WARN_ && size==0, printf("SkipAudio() size=0\n"));
|
|
if (!bufstart)
|
|
return(timeskipped);
|
|
if ((buf[0]&0xF0)==0xF0 && buf[0]!=0xFF)
|
|
break;
|
|
else
|
|
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
|
|
} while (1);
|
|
frames++;
|
|
layer = 4-((*buf>>1) & 0x03);
|
|
buf++; size--;
|
|
if (!size)
|
|
{
|
|
SlibFreeBuffer(bufstart);
|
|
bufstart=buf=slibGetBufferFromPin(Info, srcpin, &size, NULL);
|
|
if (!bufstart)
|
|
return(timeskipped);
|
|
}
|
|
sps = mpeg_freq[(*buf>>2) & 0x03];
|
|
buf++; size--;
|
|
if (!size)
|
|
{
|
|
SlibFreeBuffer(bufstart);
|
|
bufstart=buf=slibGetBufferFromPin(Info, srcpin, &size, NULL);
|
|
if (!bufstart)
|
|
return(timeskipped);
|
|
}
|
|
channels = (*buf >> 6)==3 ? 1 : 2;
|
|
buf++; size--;
|
|
samples+=layer_samples[layer];
|
|
if (sps)
|
|
timeskipped=(1000*samples)/sps;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("samples=%d timeskipped=%d\n", samples, timeskipped));
|
|
if (size)
|
|
{
|
|
SlibAllocSubBuffer(buf, size);
|
|
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
|
|
}
|
|
SlibFreeBuffer(bufstart);
|
|
}
|
|
}
|
|
break;
|
|
#endif /* MPEG_SUPPORT */
|
|
#ifdef AC3_SUPPORT
|
|
case SLIB_TYPE_AC3_AUDIO:
|
|
/* For better audio/video synchronization - add Dolby AC-3 support here */
|
|
break;
|
|
#endif /* AC3_SUPPORT */
|
|
default:
|
|
break;
|
|
}
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("slibSkipAudio() frames=%d samples=%d timeskipped=%d ms\n",
|
|
frames, samples, timeskipped));
|
|
return(timeskipped);
|
|
}
|
|
|
|
|
|
SlibStatus_t slibValidateAudioParams(SlibInfo_t *Info)
|
|
{
|
|
return(SlibErrorNone);
|
|
}
|
|
|