Windows2003-3790/enduser/netmeeting/av/codecs/dec/dech261/audio.c
2020-09-30 16:53:55 +02:00

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);
}