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

3923 lines
128 KiB
C

/*
* @DEC_COPYRIGHT@
*/
/*
* HISTORY
* $Log: slib_buffer.c,v $
* Revision 1.1.6.26 1996/12/13 18:19:07 Hans_Graves
* Check for valid pin pointer in slibGetNextTimeOnPin().
* [1996/12/13 18:08:27 Hans_Graves]
*
* Revision 1.1.6.25 1996/12/10 19:21:58 Hans_Graves
* Fix MPEG Systems encoding bug.
* [1996/12/10 19:15:33 Hans_Graves]
*
* Revision 1.1.6.24 1996/12/04 22:34:32 Hans_Graves
* Enable AC3 detection in PRIVATE packets.
* [1996/12/04 22:18:48 Hans_Graves]
*
* Revision 1.1.6.23 1996/12/03 23:15:16 Hans_Graves
* Fixed updating of offset value for buffers on pins.
* [1996/12/03 23:09:51 Hans_Graves]
*
* Revision 1.1.6.22 1996/12/03 00:08:33 Hans_Graves
* Handling of End Of Sequence points. Added PERCENT100 support.
* [1996/12/03 00:06:03 Hans_Graves]
*
* Revision 1.1.6.21 1996/11/18 23:07:36 Hans_Graves
* Make use of presentation timestamps. Make seeking time-based.
* [1996/11/18 22:47:40 Hans_Graves]
*
* Revision 1.1.6.20 1996/11/13 16:10:56 Hans_Graves
* Skip AC3 header in private packets.
* [1996/11/13 16:03:50 Hans_Graves]
*
* Revision 1.1.6.19 1996/11/11 18:21:07 Hans_Graves
* Added AC3 support for multiplexed streams.
* [1996/11/11 18:00:27 Hans_Graves]
*
* Revision 1.1.6.18 1996/11/08 21:51:06 Hans_Graves
* Added AC3 support. Fixed Program Stream demultiplexing.
* [1996/11/08 21:31:43 Hans_Graves]
*
* Revision 1.1.6.17 1996/10/31 21:58:09 Hans_Graves
* Turned of debugging code.
* [1996/10/31 21:57:56 Hans_Graves]
*
* Revision 1.1.6.16 1996/10/31 21:55:47 Hans_Graves
* Fix bad multiplexing when encoding to MPEG Systems.
* [1996/10/31 21:15:01 Hans_Graves]
*
* Revision 1.1.6.15 1996/10/29 17:04:59 Hans_Graves
* Add padding packets support for MPEG Systems Encoding.
* [1996/10/29 17:04:45 Hans_Graves]
*
* Revision 1.1.6.14 1996/10/28 17:32:32 Hans_Graves
* MME-1402, 1431, 1435: Timestamp related changes.
* [1996/10/28 17:23:03 Hans_Graves]
*
* Revision 1.1.6.13 1996/10/17 00:23:34 Hans_Graves
* Fix buffer problems after SlibQueryData() calls.
* [1996/10/17 00:19:14 Hans_Graves]
*
* Revision 1.1.6.12 1996/10/15 17:34:13 Hans_Graves
* Added MPEG-2 Program Stream support.
* [1996/10/15 17:30:30 Hans_Graves]
*
* Revision 1.1.6.11 1996/10/12 17:18:54 Hans_Graves
* Added parsing of Decode and Presentation timestamps with MPEG Transport.
* [1996/10/12 17:01:55 Hans_Graves]
*
* Revision 1.1.6.10 1996/10/03 19:14:24 Hans_Graves
* Added Presentation and Decoding timestamp support.
* [1996/10/03 19:10:38 Hans_Graves]
*
* Revision 1.1.6.9 1996/09/29 22:19:41 Hans_Graves
* Added debugging printf's
* [1996/09/29 21:30:27 Hans_Graves]
*
* Revision 1.1.6.8 1996/09/25 19:16:48 Hans_Graves
* Added SLIB_INTERNAL define.
* [1996/09/25 19:01:53 Hans_Graves]
*
* Revision 1.1.6.7 1996/09/18 23:46:48 Hans_Graves
* MPEG2 Systems parsing fixes. Added Audio presentation timestamps to MPEG1 Systems writing
* [1996/09/18 22:06:07 Hans_Graves]
*
* Revision 1.1.6.6 1996/08/09 20:51:48 Hans_Graves
* Fix callbacks with user buffers
* [1996/08/09 20:11:06 Hans_Graves]
*
* Revision 1.1.6.5 1996/07/19 02:11:13 Hans_Graves
* Added support for SLIB_MSG_BUFDONE with user buffers.
* [1996/07/19 02:02:53 Hans_Graves]
*
* Revision 1.1.6.4 1996/06/07 18:26:12 Hans_Graves
* Merge MME-01326. Encoded MPEG-1 Systems files now include Presentation timestamps
* [1996/06/07 17:54:11 Hans_Graves]
*
* Revision 1.1.6.3 1996/05/10 21:17:27 Hans_Graves
* Add Callback support.
* [1996/05/10 20:58:39 Hans_Graves]
*
* Revision 1.1.6.2 1996/05/07 19:56:22 Hans_Graves
* Added HUFF_SUPPORT.
* [1996/05/07 17:20:50 Hans_Graves]
*
* Revision 1.1.4.10 1996/05/02 17:10:35 Hans_Graves
* Better checking for NULL pointers in ParseMpeg2Systems(). Fixes MME-01234
* [1996/05/02 17:05:46 Hans_Graves]
*
* Revision 1.1.4.9 1996/04/24 22:33:46 Hans_Graves
* MPEG encoding bitrate fixups.
* [1996/04/24 22:27:13 Hans_Graves]
*
* Revision 1.1.4.8 1996/04/23 15:36:42 Hans_Graves
* Added MPEG 1 Systems packet recovery
* [1996/04/23 15:35:23 Hans_Graves]
*
* Revision 1.1.4.7 1996/04/19 21:52:24 Hans_Graves
* MPEG 1 Systems writing enhancements
* [1996/04/19 21:47:53 Hans_Graves]
*
* Revision 1.1.4.6 1996/04/01 19:07:54 Hans_Graves
* And some error checking
* [1996/04/01 19:04:37 Hans_Graves]
*
* Revision 1.1.4.5 1996/04/01 16:23:16 Hans_Graves
* NT porting
* [1996/04/01 16:16:00 Hans_Graves]
*
* Revision 1.1.4.4 1996/03/29 22:21:35 Hans_Graves
* Added MPEG/JPEG/H261_SUPPORT ifdefs
* [1996/03/29 21:57:01 Hans_Graves]
*
* Added MPEG-I Systems encoding support
* [1996/03/27 21:55:57 Hans_Graves]
*
* Revision 1.1.4.3 1996/03/12 16:15:52 Hans_Graves
* Changed hard coded File buffer size to param
* [1996/03/12 15:57:23 Hans_Graves]
*
* Revision 1.1.4.2 1996/03/08 18:46:46 Hans_Graves
* Increased Buffer size
* [1996/03/08 18:40:59 Hans_Graves]
*
* Revision 1.1.2.13 1996/02/23 22:17:09 Hans_Graves
* Fixed bad handling of large packets in ParseMpeg1()
* [1996/02/23 21:56:15 Hans_Graves]
*
* Revision 1.1.2.12 1996/02/21 22:52:46 Hans_Graves
* Fixed MPEG 2 systems stuff
* [1996/02/21 22:51:11 Hans_Graves]
*
* Revision 1.1.2.11 1996/02/19 20:09:29 Hans_Graves
* Debugging message clean-up
* [1996/02/19 20:08:34 Hans_Graves]
*
* Revision 1.1.2.10 1996/02/19 18:03:58 Hans_Graves
* Fixed a number of MPEG related bugs
* [1996/02/19 17:57:43 Hans_Graves]
*
* Revision 1.1.2.9 1996/02/13 18:47:50 Hans_Graves
* Fix some Seek related bugs
* [1996/02/13 18:40:40 Hans_Graves]
*
* Revision 1.1.2.8 1996/02/07 23:23:57 Hans_Graves
* Added SEEK_EXACT. Fixed most frame counting problems.
* [1996/02/07 23:20:34 Hans_Graves]
*
* Revision 1.1.2.7 1996/02/06 22:54:07 Hans_Graves
* Seek fix-ups. More accurate MPEG frame counts.
* [1996/02/06 22:45:02 Hans_Graves]
*
* Revision 1.1.2.6 1996/01/30 22:23:09 Hans_Graves
* Added AVI YUV support
* [1996/01/30 22:21:41 Hans_Graves]
*
* Revision 1.1.2.5 1996/01/15 16:26:31 Hans_Graves
* Reorganized Parsing, Added Wave file support
* [1996/01/15 15:46:56 Hans_Graves]
*
* Revision 1.1.2.4 1996/01/11 16:17:32 Hans_Graves
* Added MPEG II Systems decode support
* [1996/01/11 16:12:38 Hans_Graves]
*
* Revision 1.1.2.3 1996/01/08 16:41:34 Hans_Graves
* Added MPEG II decoding support
* [1996/01/08 15:53:07 Hans_Graves]
*
* Revision 1.1.2.2 1995/12/08 20:01:23 Hans_Graves
* Creation. Split off from slib_api.c
* [1995/12/08 19:57:18 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_
*/
#ifdef WIN32
#include <io.h>
#endif
#include <stdio.h>
#ifdef _SHM_
#include <sys/ipc.h> /* shared memory */
#endif
#define SLIB_INTERNAL
#include "slib.h"
#include "SC_err.h"
#include "mpeg.h"
#include "avi.h"
#ifdef _SLIBDEBUG_
#include "sc_debug.h"
#define _DEBUG_ 0 /* detailed debuging statements: if >1 more detail */
#define _VERBOSE_ 0 /* show progress */
#define _VERIFY_ 1 /* verify correct operation */
#define _WARN_ 1 /* warnings about strange behavior: 2=lower warnings */
#define _MEMORY_ 0 /* memory debugging: if >1 more detail */
#define _WRITE_ 0 /* data writing debugging */
#define _TIMECODE_ 0 /* timecode/timestamp debugging */
#define _PARSE_ 0 /* parsing debugging */
#endif
/************************** Memory Allocation ***********************/
typedef struct slibMemory_s {
unsigned char *address;
long shmid;
unsigned dword size;
int count;
ScBoolean_t user;
SlibInfo_t *sinfo;
void *uinfo; /* userdata */
struct slibMemory_s *next;
} slibMemory_t;
static slibMemory_t *_slibMemoryList = NULL;
static slibMemory_t *_slibMemoryListTail = NULL;
static dword _slibMemoryCount = 0;
static unsigned qword _slibMemoryUsed = 0L;
#ifdef WIN32
static HANDLE _slibMemoryMutex = NULL;
#define slibInitMemoryMutex() if (_slibMemoryMutex==NULL) \
_slibMemoryMutex=CreateMutex(NULL, FALSE, NULL)
#define slibFreeMemoryMutex() if (_slibMemoryMutex!=NULL) \
CloseHandle(_slibMemoryMutex); _slibMemoryMutex=NULL
#define slibEnterMemorySection() WaitForSingleObject(_slibMemoryMutex, 5000);
#define slibExitMemorySection() ReleaseMutex(_slibMemoryMutex)
#else
#define slibInitMemoryMutex()
#define slibFreeMemoryMutex()
#define slibEnterMemorySection()
#define slibExitMemorySection()
#endif
void slibDumpMemory()
{
if (_slibMemoryList)
{
slibMemory_t *tmpmem = _slibMemoryList;
while (tmpmem)
{
printf("address: %p size: %d count: %d user: %s\n",
tmpmem->address, tmpmem->size, tmpmem->count,
tmpmem->user ? "TRUE" : "FALSE");
tmpmem = tmpmem->next;
}
}
else
printf("No memory allocated\n");
}
unsigned qword SlibMemUsed()
{
return(_slibMemoryUsed);
}
void *SlibAllocBuffer(unsigned dword bytes)
{
unsigned char *address;
_SlibDebug(_MEMORY_,
printf("SlibAllocBuffer(%d) MemoryCount=%d Used=%d\n",
bytes, _slibMemoryCount, _slibMemoryUsed));
if (bytes<=0)
return(NULL);
address=ScAlloc(bytes);
if (address)
{
slibMemory_t *tmpmem = ScAlloc(sizeof(slibMemory_t));
if (!tmpmem)
{
ScFree(address);
return(NULL);
}
tmpmem->address = address;
tmpmem->shmid = -1;
tmpmem->size = bytes;
tmpmem->count = 1;
tmpmem->user = FALSE;
tmpmem->sinfo = NULL;
tmpmem->uinfo = NULL;
slibInitMemoryMutex();
slibEnterMemorySection();
tmpmem->next = _slibMemoryList;
if (_slibMemoryList == NULL)
_slibMemoryListTail = tmpmem;
_slibMemoryList = tmpmem;
_slibMemoryCount++;
_slibMemoryUsed+=bytes;
slibExitMemorySection();
}
_SlibDebug(_WARN_ && address==NULL,
printf("SlibAllocBuffer() couldn't alloc\n") );
return(address);
}
/*
** Name: SlibAllocBufferEx
** Desc: Allocate a buffer that is associated with a specific handle
*/
void *SlibAllocBufferEx(SlibHandle_t handle, unsigned dword bytes)
{
unsigned char *address;
_SlibDebug(_MEMORY_,
printf("SlibAllocBufferEx(%p, bytes=%d) MemoryCount=%d Used=%d\n",
handle, bytes, _slibMemoryCount, _slibMemoryUsed));
if (bytes<=0)
return(NULL);
address=ScAlloc(bytes);
if (address)
{
slibMemory_t *tmpmem = ScAlloc(sizeof(slibMemory_t));
if (!tmpmem)
{
ScFree(address);
return(NULL);
}
tmpmem->address = address;
tmpmem->shmid = -1;
tmpmem->size = bytes;
tmpmem->count = 1;
tmpmem->user = FALSE;
tmpmem->sinfo = handle;
tmpmem->uinfo = NULL;
slibInitMemoryMutex();
slibEnterMemorySection();
tmpmem->next = _slibMemoryList;
if (_slibMemoryList == NULL)
_slibMemoryListTail = tmpmem;
_slibMemoryList = tmpmem;
_slibMemoryCount++;
_slibMemoryUsed+=bytes;
slibExitMemorySection();
}
_SlibDebug(_WARN_ && address==NULL,
printf("SlibAllocBufferEx() couldn't alloc\n") );
return(address);
}
void *SlibAllocSharedBuffer(unsigned dword bytes, int *shmid)
{
unsigned char *address;
long id;
_SlibDebug(_MEMORY_, printf("SlibAllocSharedBuffer(%d)\n", bytes) );
if (bytes<=0)
return(NULL);
#ifdef _SHM_
id = shmget(IPC_PRIVATE, bytes, IPC_CREAT|0777);
if (id < 0)
return(NULL);
address = (unsigned char *)shmat(id, 0, 0);
if (address == ((caddr_t) -1))
return(NULL);
#else
address=(unsigned char *)ScPaMalloc(bytes);
id=0;
#endif
if (address)
{
slibMemory_t *tmpmem = ScAlloc(sizeof(slibMemory_t));
_SlibDebug((_MEMORY_||_WARN_) && (((unsigned dword)address)&0x03),
printf("SlibAllocSharedBuffer(%d) Unaligned address=%p shmid=%d\n",
bytes, address, id) );
if (!tmpmem)
{
#ifdef _SHM_
shmdt (address);
shmctl(id, IPC_RMID, 0);
#else
ScPaFree(address);
#endif
return(NULL);
}
tmpmem->address = address;
tmpmem->shmid = id;
_SlibDebug(_MEMORY_ && id>=0,
printf("SlibAllocSharedBuffer(%d) address=%p shmid=%d\n",
bytes, address, id) );
tmpmem->size = bytes;
tmpmem->count = 1;
tmpmem->user = FALSE;
tmpmem->sinfo = NULL;
tmpmem->uinfo = NULL;
slibInitMemoryMutex();
slibEnterMemorySection();
tmpmem->next = _slibMemoryList;
if (_slibMemoryList == NULL)
_slibMemoryListTail = tmpmem;
_slibMemoryList = tmpmem;
_slibMemoryCount++;
_slibMemoryUsed+=bytes;
slibExitMemorySection();
if (shmid)
*shmid = id;
}
return(address);
}
dword SlibGetSharedBufferID(void *address)
{
dword shmid=-1;
_SlibDebug(_MEMORY_,
printf("SlibGetSharedBufferID(%p) _slibMemoryCount=%d\n",
address, _slibMemoryCount));
slibEnterMemorySection();
if (_slibMemoryList)
{
slibMemory_t *tmpmem = _slibMemoryList;
while (tmpmem)
{
if ((unsigned char *)address>=tmpmem->address &&
(unsigned char *)address<tmpmem->address+tmpmem->size)
{
shmid=tmpmem->shmid;
break;
}
tmpmem = tmpmem->next;
}
}
slibExitMemorySection();
return(shmid);
}
/*
** Name: SlibValidBuffer
** Desc: Check if an address is in a SLIB allocated buffer.
*/
SlibBoolean_t SlibValidBuffer(void *address)
{
SlibBoolean_t isvalid=FALSE;
_SlibDebug(_MEMORY_,
printf("SlibValidBuffer(%p) _slibMemoryCount=%d\n",
address, _slibMemoryCount));
slibEnterMemorySection();
if (_slibMemoryList)
{
slibMemory_t *tmpmem = _slibMemoryList;
while (tmpmem)
{
if ((unsigned char *)address>=tmpmem->address &&
(unsigned char *)address<tmpmem->address+tmpmem->size)
{
isvalid=TRUE;
break;
}
tmpmem = tmpmem->next;
}
}
slibExitMemorySection();
return(isvalid);
}
SlibStatus_t SlibFreeBuffer(void *address)
{
_SlibDebug(_MEMORY_>1,
printf("SlibFreeBuffer(%p) MemoryCount=%d Used=%d\n",
address, _slibMemoryCount, _slibMemoryUsed));
slibEnterMemorySection();
if (_slibMemoryList)
{
slibMemory_t *tmpmem = _slibMemoryList;
slibMemory_t *lastmem = NULL;
while (tmpmem)
{
if ((unsigned char *)address>=tmpmem->address &&
(unsigned char *)address<tmpmem->address+tmpmem->size)
{
if (--tmpmem->count>0) /* memory was allocated more than once */
{
slibExitMemorySection();
return(SlibErrorNone);
}
_SlibDebug(_MEMORY_,
printf("SlibFreeBuffer(%p) final free: shmid=%d size=%d\n",
tmpmem->address, tmpmem->shmid, tmpmem->size) );
/* remove memory from mem list */
if (tmpmem == _slibMemoryList)
_slibMemoryList = tmpmem->next;
else
lastmem->next = tmpmem->next;
if (tmpmem == _slibMemoryListTail)
_slibMemoryListTail = lastmem;
/* now actually free the memory */
if (tmpmem->user)
{
if (tmpmem->sinfo && tmpmem->sinfo->SlibCB)
{
slibExitMemorySection();
_SlibDebug(_VERBOSE_,
printf("SlibFreeBuffer() SlibCB(SLIB_MSG_BUFDONE, %p, %d)\n",
tmpmem->address, tmpmem->size) );
tmpmem->user=FALSE;
(*(tmpmem->sinfo->SlibCB))((SlibHandle_t)tmpmem->sinfo,
SLIB_MSG_BUFDONE, (SlibCBParam1_t)tmpmem->address,
(SlibCBParam2_t)tmpmem->size,
tmpmem->uinfo?tmpmem->uinfo
:(void *)tmpmem->sinfo->SlibCBUserData);
slibEnterMemorySection();
}
}
else if (tmpmem->shmid < 0)
{
_SlibDebug(_MEMORY_, printf("SlibFreeBuffer() ScFree(%p) %d bytes\n",
tmpmem->address, tmpmem->size) );
ScFree(tmpmem->address);
}
else /* shared memory */
#ifdef _SHM_
{
_SlibDebug(_MEMORY_, printf("SlibFreeBuffer() shmdt(%p) %d bytes\n",
tmpmem->address, tmpmem->size) );
shmdt (tmpmem->address);
shmctl(tmpmem->shmid, IPC_RMID, 0);
}
#else
{
_SlibDebug(_MEMORY_,
printf("SlibFreeBuffer() ScPaFree(%p) %d bytes\n",
tmpmem->address, tmpmem->size) );
ScPaFree(tmpmem->address);
}
#endif
_slibMemoryCount--;
_slibMemoryUsed-=tmpmem->size;
ScFree(tmpmem);
slibExitMemorySection();
if (_slibMemoryList==NULL) /* last memory in list was freed */
{
slibFreeMemoryMutex();
}
return(SlibErrorNone);
}
lastmem = tmpmem;
_SlibDebug(_VERIFY_ && (tmpmem == tmpmem->next),
printf("SlibFreeBuffer() tmpmem == tmpmem->next\n");
return(SlibErrorMemory) );
_SlibDebug(_VERIFY_ && (tmpmem->next==_slibMemoryList),
printf("SlibFreeBuffer() tmpmem->next == _slibMemoryList\n");
return(SlibErrorMemory) );
tmpmem = tmpmem->next;
}
}
_SlibDebug(_WARN_, printf("SlibFreeBuffer(%p) couldn't free\n",address) );
slibExitMemorySection();
return(SlibErrorBadArgument);
}
/*
** Name: SlibFreeBuffers
** Purpose: Free all buffers associated with a handle.
** If handle==NULL free all memory.
*/
SlibStatus_t SlibFreeBuffers(SlibHandle_t handle)
{
_SlibDebug(_MEMORY_>1,
printf("SlibFreeBuffers() MemoryCount=%d Used=%d\n",
_slibMemoryCount, _slibMemoryUsed));
slibEnterMemorySection();
if (_slibMemoryList)
{
slibMemory_t *tmpmem = _slibMemoryList;
slibMemory_t *lastmem = NULL, *nextmem=NULL;
while (tmpmem)
{
nextmem = tmpmem->next;
if (handle==NULL || tmpmem->sinfo==handle)
{
_SlibDebug(_MEMORY_,
printf("SlibFreeBuffer(%p) final free: shmid=%d size=%d\n",
tmpmem->address, tmpmem->shmid, tmpmem->size) );
/* remove memory from mem list */
if (tmpmem == _slibMemoryList)
_slibMemoryList = tmpmem->next;
else
lastmem->next = tmpmem->next;
if (tmpmem == _slibMemoryListTail)
_slibMemoryListTail = lastmem;
/* now actually free the memory */
if (tmpmem->user)
{
if (tmpmem->sinfo && tmpmem->sinfo->SlibCB)
{
slibExitMemorySection();
_SlibDebug(_VERBOSE_,
printf("SlibFreeBuffer() SlibCB(SLIB_MSG_BUFDONE, %p, %d)\n",
tmpmem->address, tmpmem->size) );
tmpmem->user=FALSE;
(*(tmpmem->sinfo->SlibCB))((SlibHandle_t)tmpmem->sinfo,
SLIB_MSG_BUFDONE, (SlibCBParam1_t)tmpmem->address,
(SlibCBParam2_t)tmpmem->size,
tmpmem->uinfo?tmpmem->uinfo
:(void *)tmpmem->sinfo->SlibCBUserData);
slibEnterMemorySection();
}
}
else if (tmpmem->shmid < 0)
{
_SlibDebug(_MEMORY_, printf("SlibFreeBuffer() ScFree(%p) %d bytes\n",
tmpmem->address, tmpmem->size) );
ScFree(tmpmem->address);
}
else /* shared memory */
#ifdef _SHM_
{
_SlibDebug(_MEMORY_, printf("SlibFreeBuffer() shmdt(%p) %d bytes\n",
tmpmem->address, tmpmem->size) );
shmdt (tmpmem->address);
shmctl(tmpmem->shmid, IPC_RMID, 0);
}
#else
{
_SlibDebug(_MEMORY_,
printf("SlibFreeBuffer() ScPaFree(%p) %d bytes\n",
tmpmem->address, tmpmem->size) );
ScPaFree(tmpmem->address);
}
#endif
_slibMemoryCount--;
_slibMemoryUsed-=tmpmem->size;
ScFree(tmpmem);
if (_slibMemoryList==NULL) /* last memory in list was freed */
{
slibExitMemorySection();
slibFreeMemoryMutex();
return(SlibErrorNone);
}
}
lastmem = tmpmem;
_SlibDebug(_VERIFY_ && (tmpmem == nextmem),
printf("SlibFreeBuffer() tmpmem == tmpmem->next\n");
return(SlibErrorMemory) );
_SlibDebug(_VERIFY_ && (nextmem==_slibMemoryList),
printf("SlibFreeBuffer() tmpmem->next == _slibMemoryList\n");
return(SlibErrorMemory) );
tmpmem = nextmem;
}
}
slibExitMemorySection();
return(SlibErrorNone);
}
/*
** Name: SlibAllocSubBuffer
** Purpose: Allocate a subsection of a buffer.
*/
SlibStatus_t SlibAllocSubBuffer(void *address, unsigned dword bytes)
{
_SlibDebug(_MEMORY_>1, printf("SlibAllocSubBuffer() _slibMemoryCount=%d\n",
_slibMemoryCount) );
slibEnterMemorySection();
if (_slibMemoryList)
{
slibMemory_t *tmpmem = _slibMemoryList;
while (tmpmem)
{
if ((unsigned char *)address>=tmpmem->address &&
(unsigned char *)address<tmpmem->address+tmpmem->size)
{
if ((char *)address+bytes>tmpmem->address+tmpmem->size)
{
_SlibDebug(_VERIFY_,
printf("SlibAllocSubBuffer(bytes=%d) out of range by %d bytes\n",
bytes,(unsigned long)(tmpmem->address+tmpmem->size)
-(unsigned long)((char *)address+bytes)) );
slibExitMemorySection();
return(SlibErrorMemory);
}
tmpmem->count++;
slibExitMemorySection();
return(SlibErrorNone);
}
_SlibDebug(_VERIFY_ && (tmpmem == tmpmem->next),
printf("SlibAllocSubBuffer() tmpmem == tmpmem->next\n");
return(SlibErrorMemory) );
_SlibDebug(_VERIFY_ && (tmpmem->next==_slibMemoryList),
printf("SlibAllocSubBuffer() tmpmem->next == _slibMemoryList\n");
return(SlibErrorMemory) );
tmpmem = tmpmem->next;
}
}
_SlibDebug(_WARN_ && address==NULL,
printf("SlibAllocSubBuffer() couldn't alloc\n") );
slibExitMemorySection();
return(SlibErrorBadArgument);
}
/*
** Name: SlibManageUserBuffer
** Purpose: Add a user's buffer to the memory queue, in order to keep
** track of it.
*/
SlibStatus_t slibManageUserBuffer(SlibInfo_t *Info, void *address,
unsigned dword bytes, void *userdata)
{
_SlibDebug(_MEMORY_, printf("slibManageUserBuffer() _slibMemoryCount=%d\n",
_slibMemoryCount) );
slibEnterMemorySection();
if (_slibMemoryList)
{
slibMemory_t *tmpmem = _slibMemoryList;
while (tmpmem)
{
if ((unsigned char *)address>=tmpmem->address &&
(unsigned char *)address<tmpmem->address+tmpmem->size)
{
if ((char *)address+bytes>tmpmem->address+tmpmem->size)
{
_SlibDebug(_VERIFY_,
printf("SlibAllocSubBuffer(bytes=%d) out of range by %d bytes\n",
bytes,(unsigned long)(tmpmem->address+tmpmem->size)
-(unsigned long)((char *)address+bytes)) );
slibExitMemorySection();
return(SlibErrorMemory);
}
if (tmpmem->user == TRUE) /* already a user buffer */
tmpmem->count++;
else
tmpmem->user = TRUE;
if (Info)
tmpmem->sinfo=Info;
if (userdata)
tmpmem->uinfo = userdata;
_SlibDebug(_MEMORY_,
printf("slibManageUserBuffer() Allocated by SLIB: %p\n",
address) );
slibExitMemorySection();
return(SlibErrorNone);
}
tmpmem = tmpmem->next;
}
}
if (address)
{
slibMemory_t *tmpmem = ScAlloc(sizeof(slibMemory_t));
if (!tmpmem)
return(SlibErrorMemory);
tmpmem->address = address;
tmpmem->shmid = -1;
tmpmem->size = bytes;
tmpmem->count = 1; /* was not allocated by SLIB */
tmpmem->user = TRUE;
tmpmem->sinfo = Info;
tmpmem->uinfo = userdata;
tmpmem->next = _slibMemoryList;
if (_slibMemoryList == NULL)
_slibMemoryListTail = tmpmem;
_slibMemoryList = tmpmem;
_slibMemoryCount++;
_slibMemoryUsed+=bytes;
_SlibDebug(_MEMORY_,
printf("slibManageUserBuffer() New memory entry\n") );
slibExitMemorySection();
return(SlibErrorNone);
}
slibExitMemorySection();
return(SlibErrorBadArgument);
}
/************************** Internal Buffer Stuff ***********************/
#define _getbyte(var) \
if (top==bot) { \
var = *buf++; \
if (--bufsize==0) { \
if (discard) { \
SlibFreeBuffer(bufstart); \
buf=bufstart=slibGetBufferFromPin(Info, pin, &bufsize, NULL); \
} \
else \
buf=slibPeekNextBufferOnPin(Info, pin, buf-1, &bufsize, NULL); \
if (!buf) return(NULL); \
} \
} else var=sbyte[top++];
#define _storebyte(val) if (top==bot) {top=0; bot=1; sbyte[0]=val; } \
else sbyte[bot++]=val;
unsigned char *slibSearchBuffersOnPin(SlibInfo_t *Info, SlibPin_t *pin,
unsigned char *lastbuf, unsigned dword *size,
unsigned dword code, int codebytes,
ScBoolean_t discard)
{
unsigned char *buf, *bufstart;
unsigned char abyte, byte0, byte1, byte2, byte3, sbyte[16];
int bot, top;
unsigned dword bufsize;
_SlibDebug(_DEBUG_>1,
printf("slibSearchBuffersOnPin(%s, code=0x%08lX, codebytes=%d)\n",
pin->name, code, codebytes) );
if (!Info || !pin)
return(NULL);
for (top=codebytes-1; top>=0; top--)
{
sbyte[top]=code & 0xFF;
code>>=8;
}
byte0=sbyte[0];
byte1=sbyte[1];
byte2=sbyte[2];
byte3=sbyte[3];
top=bot=0;
if (lastbuf)
{
buf=bufstart=lastbuf;
bufsize=*size;
}
else if (discard)
{
buf=bufstart=slibGetBufferFromPin(Info, pin, &bufsize, NULL);
}
else
buf=slibPeekBufferOnPin(Info, pin, &bufsize, NULL);
if (!buf || codebytes<=0 || !bufsize)
{
_SlibDebug(_WARN_ && buf==lastbuf,
printf("slibSearchBuffersOnPin(%s) no search made\n",pin->name) );
return(buf);
}
/*
ScDumpChar(buf,bufsize,0);
*/
while (buf)
{
/*
printf("level=0 top=%d bot=%d\n", top, bot);
printf("buf=%p abyte=%d\n",buf, abyte);
*/
_getbyte(abyte);
if (abyte == byte0)
{
if (codebytes==1)
{
if (discard)
{ SlibAllocSubBuffer(buf, bufsize); SlibFreeBuffer(bufstart); }
*size=bufsize;
return(buf);
}
_getbyte(abyte);
if (abyte == byte1)
{
if (codebytes==2)
{
if (discard)
{ SlibAllocSubBuffer(buf, bufsize); SlibFreeBuffer(bufstart); }
*size=bufsize;
return(buf);
}
_getbyte(abyte);
if (abyte == byte2)
{
if (codebytes==3)
{
if (discard)
{ SlibAllocSubBuffer(buf, bufsize); SlibFreeBuffer(bufstart); }
*size=bufsize;
return(buf);
}
_getbyte(abyte);
if (abyte == byte3)
{
if (codebytes==4)
{
if (discard)
{ SlibAllocSubBuffer(buf, bufsize); SlibFreeBuffer(bufstart); }
*size=bufsize;
return(buf);
}
}
else
{
_storebyte(byte1);
_storebyte(byte2);
_storebyte(abyte);
}
}
else
{
_storebyte(byte1);
_storebyte(abyte);
}
}
else
_storebyte(abyte);
}
}
_SlibDebug(_DEBUG_, printf("slibSearchBuffersOnPin() Not found\n") );
return(NULL);
}
#define _getbyte2(var) \
if (top==bot) { \
var = *buf++; totallen++; \
if (--bufsize==0) { \
buf=slibPeekNextBufferOnPin(Info, pin, buf-1, &bufsize, NULL); \
if (!buf) { \
_SlibDebug(_VERBOSE_,printf("slibCountCodesOnPin() out (EOI)\n")); \
return(count); } \
} \
} else var=sbyte[top++];
/*
** Name: slibCountCodesOnPin
** Description: Count the occurrances of a particular code in a Pin's
** data stream.
** maxlen: 0 counts till end of data
** -1 counts buffers already loaded on pin
*/
dword slibCountCodesOnPin(SlibInfo_t *Info, SlibPin_t *pin,
unsigned dword code, int codebytes,
unsigned dword maxlen)
{
unsigned char *buf;
unsigned char abyte, byte0, byte1, byte2, byte3, sbyte[16];
int bot, top, count=0;
unsigned dword bufsize;
unsigned long totallen=0;
_SlibDebug((_DEBUG_||_WARN_) && (!pin || !pin->name),
printf("slibCountCodesOnPin() bad pin\n") );
if (!Info || !pin)
return(count);
_SlibDebug(_DEBUG_||_VERBOSE_,
printf("slibCountCodesOnPin(%s) in\n", pin->name) );
for (top=codebytes-1; top>=0; top--)
{
sbyte[top]=code & 0xFF;
code>>=8;
}
byte0=sbyte[0];
byte1=sbyte[1];
byte2=sbyte[2];
byte3=sbyte[3];
top=bot=0;
buf=slibPeekBufferOnPin(Info, pin, &bufsize, NULL);
if (!buf || codebytes<=0)
return(count);
while (buf && (maxlen<=0 || totallen<maxlen))
{
_getbyte2(abyte);
if (abyte == byte0)
{
if (codebytes==1)
{
count++;
top=bot=0;
continue;
}
_getbyte2(abyte);
if (abyte == byte1)
{
if (codebytes==2)
{
count++;
top=bot=0;
continue;
}
_getbyte2(abyte);
if (abyte == byte2)
{
if (codebytes==3)
{
count++;
top=bot=0;
continue;
}
_getbyte2(abyte);
if (abyte == byte3)
{
if (codebytes==4)
{
count++;
top=bot=0;
continue;
}
}
else
{
_storebyte(byte1);
_storebyte(byte2);
_storebyte(abyte);
}
}
else
{
_storebyte(byte1);
_storebyte(abyte);
}
}
else
_storebyte(abyte);
}
}
_SlibDebug(_VERBOSE_, printf("slibCountCodesOnPin() out\n") );
return(count);
}
/*
** Name: SlibGetBuffer
** Purpose: Read the next buffer from the data source.
*/
unsigned char *SlibGetBuffer(SlibInfo_t *Info, int pinid,
unsigned dword *psize, SlibTime_t *ptime)
{
unsigned char *address=NULL;
SlibPin_t *pin;
_SlibDebug(_DEBUG_>1, printf("SlibGetBuffer\n") );
if (!Info)
return(NULL);
if (!psize)
return(NULL);
pin=slibLoadPin(Info, pinid);
if (pin)
return(slibGetBufferFromPin(Info, pin, psize, ptime));
else
{
if (psize)
*psize=0;
if (ptime)
*ptime=SLIB_TIME_NONE;
_SlibDebug(_WARN_,
printf("SlibGetBuffer(pinid=%d) couldn't get\n",pinid) );
return(NULL);
}
}
/*
** Name: SlibPeekBuffer
** Purpose: Read the next buffer from the data source.
*/
unsigned char *SlibPeekBuffer(SlibInfo_t *Info, int pinid,
unsigned dword *psize, SlibTime_t *ptime)
{
unsigned char *address=NULL;
SlibPin_t *pin;
_SlibDebug(_DEBUG_>1, printf("SlibPeekBuffer\n") );
if (!Info)
return(NULL);
pin=slibLoadPin(Info, pinid);
if (pin)
return(slibPeekBufferOnPin(Info, pin, psize, ptime));
else
{
if (psize)
*psize=0;
if (ptime)
*ptime=SLIB_TIME_NONE;
_SlibDebug(_WARN_,
printf("SlibPeekBuffer(pinid=%d) couldn't peek\n",pinid) );
return(NULL);
}
}
/************************** Pins ***********************/
SlibBoolean_t slibPinOverflowing(SlibInfo_t *Info, SlibPin_t *pin)
{
if (pin==NULL)
return(TRUE);
/*
_SlibDebug(_WARN_ && pin->DataSize>(Info->OverflowSize*2)/3,
printf("Data almost overflowing: %d bytes\n", pin->DataSize) );
*/
return(pin->DataSize>(long)Info->OverflowSize ? TRUE : FALSE);
}
void slibRemovePins(SlibInfo_t *Info)
{
_SlibDebug(_VERBOSE_, printf("slibRemovePins()\n") );
while (Info->Pins)
slibRemovePin(Info, Info->Pins->ID);
}
void slibEmptyPins(SlibInfo_t *Info)
{
SlibPin_t *pin=Info->Pins;
_SlibDebug(_VERBOSE_, printf("slibEmptyPins()\n") );
while (pin)
{
slibEmptyPin(Info, pin->ID);
pin = pin->next;
}
}
SlibPin_t *slibGetPin(SlibInfo_t *Info, int pinid)
{
SlibPin_t *pin=Info->Pins;
while (pin)
{
if (pin->ID == pinid)
return(pin);
pin = pin->next;
}
return(NULL);
}
SlibPin_t *slibRenamePin(SlibInfo_t *Info, int oldpinid,
int newpinid, char *newname)
{
SlibPin_t *pin=Info->Pins;
pin=slibGetPin(Info, oldpinid);
if (pin==NULL) /* pin doesn't exist */
return(NULL);
/* if a pin with the new ID already exists, delete it */
slibRemovePin(Info, newpinid);
/* rename it */
pin->ID=newpinid;
if (newname)
strcpy(pin->name, newname);
return(pin);
}
SlibPin_t *slibAddPin(SlibInfo_t *Info, int pinid, char *name)
{
SlibPin_t *pin=Info->Pins, *newpin;
int i;
_SlibDebug(_DEBUG_||_VERBOSE_, printf("slibAddPin(%s)\n",name) );
while (pin)
{
if (pin->ID == pinid)
return(pin);
pin = pin->next;
}
if ((newpin = ScAlloc(sizeof(SlibPin_t)))==NULL)
return(NULL);
newpin->ID = pinid;
for (i=0; i<(sizeof(newpin->name)-1) && name && *name; i++)
newpin->name[i]=*name++;
newpin->name[i]=0;
newpin->next=Info->Pins;
newpin->Buffers=NULL;
newpin->BuffersTail=NULL;
newpin->BufferCount=0;
newpin->DataSize=0;
newpin->Offset=0;
Info->Pins = newpin;
Info->PinCount++;
return(newpin);
}
/*
** Name: slibAddBufferToPin
** Purpose: Add a buffer to data source buffer queue.
*/
SlibStatus_t slibAddBufferToPin(SlibPin_t *pin,
void *buffer, unsigned dword size, SlibTime_t time)
{
SlibBuffer_t *newbuf;
_SlibDebug(_DEBUG_,
printf("slibAddBufferToPin(%s, %d)\n", pin->name, size) );
_SlibDebug(_WARN_ && size==0,
printf("slibAddBufferToPin(%s, %p, size=%d)\n", pin->name, buffer, size) );
if (!pin || !buffer || !size)
return(SlibErrorBadArgument);
if ((newbuf = ScAlloc(sizeof(SlibBuffer_t)))==NULL)
return(SlibErrorMemory);
newbuf->address = buffer;
newbuf->size = size;
if (pin->BuffersTail)
newbuf->offset = pin->BuffersTail->offset+pin->BuffersTail->size;
else
newbuf->offset = pin->Offset;
newbuf->time = time;
newbuf->next = NULL;
if (pin->BuffersTail==NULL)
pin->Buffers=newbuf;
else
pin->BuffersTail->next=newbuf;
pin->BuffersTail = newbuf;
pin->BufferCount++;
pin->DataSize+=newbuf->size;
return(SlibErrorNone);
}
/*
** Name: slibInsertBufferOnPin
** Purpose: Add a buffer at the head of a data source's buffer queue.
*/
SlibStatus_t slibInsertBufferOnPin(SlibPin_t *pin, void *buffer,
unsigned dword size, SlibTime_t time)
{
SlibBuffer_t *newbuf;
_SlibDebug(_DEBUG_>1,
printf("slibInsertBufferOnPin(%s, size=%d)\n", pin->name, size) );
_SlibDebug((_WARN_ && !_DEBUG_) && size==0,
printf("slibInsertBufferOnPin(%s, size=%d)\n", pin->name, size) );
if (!pin || !buffer || !size)
return(SlibErrorBadArgument);
if ((newbuf = ScAlloc(sizeof(SlibBuffer_t)))==NULL)
return(SlibErrorMemory);
newbuf->address = buffer;
newbuf->size = size;
pin->Offset-=size;
newbuf->offset = pin->Offset;
newbuf->time = time;
newbuf->next = pin->Buffers;
pin->Buffers=newbuf;
if (pin->BuffersTail == NULL)
pin->BuffersTail = newbuf;
pin->BufferCount++;
pin->DataSize+=newbuf->size;
return(SlibErrorNone);
}
qword slibSkipDataOnPin(SlibInfo_t *Info, SlibPin_t *pin,
qword totalbytes)
{
qword skippedbytes=0;
_SlibDebug(_VERBOSE_ || 1, printf("slibSkipDataOnPin() in\n") );
if (pin && totalbytes>0)
{
qword startsize;
unsigned char *buf;
unsigned dword size;
SlibTime_t time, newtime;
startsize=pin->DataSize;
buf=slibGetBufferFromPin(Info, pin, &size, &time);
while (buf && skippedbytes+size<totalbytes)
{
skippedbytes+=size;
SlibFreeBuffer(buf);
buf=slibGetBufferFromPin(Info, pin, &size, &newtime);
if (newtime!=SLIB_TIME_NONE)
time=newtime;
}
if (buf && skippedbytes+size>=totalbytes)
{
size-=(unsigned dword)(totalbytes-skippedbytes);
if (size) /* put remainer of buffer back on pin */
{
SlibAllocSubBuffer(buf+totalbytes-skippedbytes, size);
slibInsertBufferOnPin(pin, buf+totalbytes-skippedbytes, size, time);
}
SlibFreeBuffer(buf);
skippedbytes=totalbytes;
}
_SlibDebug(_WARN_ && pin->DataSize+skippedbytes!=startsize,
printf("slibSkipDataOnPin() Skipped %d bytes, startsize=%d newsize=%d\n",
skippedbytes, startsize, pin->DataSize) );
}
_SlibDebug(_VERBOSE_ || 1, printf("slibSkipDataOnPin() out\n") );
return(skippedbytes);
}
unsigned dword slibFillBufferFromPin(SlibInfo_t *Info, SlibPin_t *pin,
unsigned char *fillbuf, unsigned dword bufsize,
SlibTime_t *ptime)
{
unsigned dword filledbytes=0;
if (pin && fillbuf)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time, nexttime=SLIB_TIME_NONE;
buf=slibGetBufferFromPin(Info, pin, &size, &time);
while (buf && size<bufsize)
{
memcpy(fillbuf, buf, size);
bufsize-=size;
filledbytes+=size;
fillbuf+=size;
SlibFreeBuffer(buf);
buf=slibGetBufferFromPin(Info, pin, &size, &nexttime);
if (time==SLIB_TIME_NONE)
time=nexttime;
}
if (buf && size>=bufsize)
{
memcpy(fillbuf, buf, bufsize);
size-=bufsize;
if (size) /* put remainer of buffer back on pin */
{
SlibAllocSubBuffer(buf+bufsize, size);
slibInsertBufferOnPin(pin, buf+bufsize, size, nexttime);
}
SlibFreeBuffer(buf);
filledbytes+=bufsize;
}
if (ptime)
*ptime=time;
}
return(filledbytes);
}
word slibGetWordFromPin(SlibInfo_t *Info, SlibPin_t *pin)
{
word value=0;
if (pin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
buf=slibGetBufferFromPin(Info, pin, &size, &time);
if (buf && size>=sizeof(value))
{
value=((int)buf[3]<<24) | (int)buf[2]<<16 |
(int)buf[1]<<8 | (int)buf[0];
size-=sizeof(value);
if (size) /* put remainer of buffer back on pin */
{
SlibAllocSubBuffer(buf+sizeof(value), size);
slibInsertBufferOnPin(pin, buf+sizeof(value), size, time);
}
SlibFreeBuffer(buf);
}
}
return(value);
}
dword slibGetDWordFromPin(SlibInfo_t *Info, SlibPin_t *pin)
{
dword value=0;
if (pin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
_SlibDebug(_VERBOSE_, printf("slibGetDWordFromPin(%s)\n", pin->name) );
buf=slibGetBufferFromPin(Info, pin, &size, &time);
if (buf && size>=sizeof(value))
{
value=((int)buf[3]<<24) | (int)buf[2]<<16 |
(int)buf[1]<<8 | (int)buf[0];
size-=sizeof(value);
if (size) /* put remainer of buffer back on pin */
{
SlibAllocSubBuffer(buf+sizeof(value), size);
slibInsertBufferOnPin(pin, buf+sizeof(value), size, time);
}
SlibFreeBuffer(buf);
}
}
return(value);
}
SlibStatus_t slibRemovePin(SlibInfo_t *Info, int pinid)
{
SlibPin_t *lastpin=NULL, *pin=Info->Pins;
SlibBuffer_t *lastbuf, *buf;
_SlibDebug(_VERBOSE_, printf("slibRemovePin(%d)\n", pinid) );
while (pin)
{
if (pin->ID == pinid)
{
if (lastpin)
lastpin->next = pin->next;
else
Info->Pins = pin->next;
buf=pin->Buffers;
while (buf)
{
if (buf->address)
SlibFreeBuffer(buf->address);
lastbuf=buf;
buf=lastbuf->next;
ScFree(lastbuf);
}
ScFree(pin);
Info->PinCount--;
return(TRUE);
}
lastpin = pin;
pin = pin->next;
}
return(FALSE);
}
SlibStatus_t slibEmptyPin(SlibInfo_t *Info, int pinid)
{
SlibPin_t *pin=Info->Pins;
SlibBuffer_t *lastbuf, *buf;
_SlibDebug(_DEBUG_ || _VERBOSE_, printf("slibEmptyPin(%d)\n",pinid) );
while (pin)
{
if (pin->ID == pinid)
{
buf=pin->Buffers;
while (buf)
{
pin->Offset+=buf->size;
if (buf->address)
if (SlibFreeBuffer(buf->address))
{
_SlibDebug(_WARN_,
printf("slibEmptyPin(%d) freeing buffer %p failed\n",
pinid, buf->address));
}
lastbuf=buf;
buf=buf->next;
ScFree(lastbuf);
}
pin->Buffers = NULL;
pin->BuffersTail = NULL;
pin->BufferCount = 0;
pin->DataSize = 0;
return(TRUE);
}
pin = pin->next;
}
_SlibDebug(_WARN_, printf("slibEmptyPin(%d) Unable to locate pin\n",pinid) );
return(FALSE);
}
SlibPin_t *slibLoadPin(SlibInfo_t *Info, int pinid)
{
SlibPin_t *pin;
_SlibDebug(_DEBUG_>1, printf("slibLoadPin(%d)\n",pinid) );
if ((pin=slibGetPin(Info, pinid))==NULL)
{
switch(pinid)
{
case SLIB_DATA_COMPRESSED: pin=slibAddPin(Info, pinid, "Input");
break;
case SLIB_DATA_VIDEO: pin=slibAddPin(Info, pinid, "Video");
break;
case SLIB_DATA_AUDIO: pin=slibAddPin(Info, pinid, "Audio");
break;
}
}
if (pin)
{
if (pin->Buffers)
return(pin);
else if (Info->Mode==SLIB_MODE_DECOMPRESS)
{
pin=slibPreLoadPin(Info, pin);
if (pin && pin->Buffers)
return(pin);
}
_SlibDebug(_WARN_,
if (Info->Mode!=SLIB_MODE_DECOMPRESS)
printf("slibLoadPin(%d) Mode is not SLIB_MODE_DECOMPRESS\n", pinid);
else
printf("slibLoadPin(%d) Unable to load pin\n", pinid));
return(NULL);
}
return(NULL);
}
qword slibDataOnPin(SlibInfo_t *Info, int pinid)
{
SlibPin_t *pin=slibGetPin(Info, pinid);
if (!pin || pin->Buffers==NULL)
return((qword)0);
else
return(pin->DataSize>0?pin->DataSize:(qword)1);
}
qword slibDataOnPins(SlibInfo_t *Info)
{
SlibPin_t *pin=Info->Pins;
qword totalbytes=(qword)0;
while (pin)
{
if (pin->DataSize>0)
totalbytes+=pin->DataSize;
pin = pin->next;
}
_SlibDebug(_VERBOSE_, printf("slibDataOnPins() returns %d\n", totalbytes) );
return(totalbytes);
}
/************************** Data Stream helper functions **************/
#ifdef MPEG_SUPPORT
#define PACKET_SIZE 0x8F0
#define PACKET_BUFFER_SIZE 0x8F0+50
#define BYTES_PER_PACK 0x1200
#define PTIME_ADJUST 300
#define AUDIOTIME_ADJUST 10
#endif
void slibValidateBitrates(SlibInfo_t *Info)
{
if (Info->Svh)
Info->VideoBitRate=(dword)SvGetParamInt(Info->Svh, SV_PARAM_BITRATE);
if (Info->Sah)
Info->AudioBitRate=(dword)SaGetParamInt(Info->Sah, SA_PARAM_BITRATE);
_SlibDebug(_VERBOSE_, printf("AudioBitRate=%d VideoBitRate=%d\n",
Info->AudioBitRate,Info->VideoBitRate) );
#ifdef MPEG_SUPPORT
if (Info->Type==SLIB_TYPE_MPEG_SYSTEMS ||
Info->Type==SLIB_TYPE_MPEG_SYSTEMS_MPEG2)
{
qword totalbitrate=Info->AudioBitRate+Info->VideoBitRate;
if (Info->Mode==SLIB_MODE_COMPRESS)
{
Info->KeySpacing=(int)SvGetParamInt(Info->Svh, SV_PARAM_KEYSPACING);
Info->SubKeySpacing=(int)SvGetParamInt(Info->Svh, SV_PARAM_SUBKEYSPACING);
}
totalbitrate+=(9*(totalbitrate/(PACKET_SIZE-3)))+ /* Packet headers */
(qword)(4*8*Info->FramesPerSec)+ /* Presentation timestamps */
(qword)(4*8*Info->FramesPerSec*10/ /* Decoding */
Info->SubKeySpacing); /* timestamps */
Info->MuxBitRate=(dword)(12*(totalbitrate/BYTES_PER_PACK));/*Pack Headers*/
}
#endif
Info->TotalBitRate=Info->AudioBitRate+Info->VideoBitRate+Info->MuxBitRate;
}
/************************** Data Stream Writers ***********************/
#ifdef MPEG_SUPPORT
static int slibCreateMpegPackHeader(unsigned char *buf,
unsigned qword sys_clock,
unsigned dword mux_rate)
{
buf[0]=0x00;
buf[1]=0x00;
buf[2]=0x01;
buf[3]=MPEG_PACK_START_BASE;
/* store system clock */
buf[4]=0x21|(unsigned char)(((sys_clock>>30)&0x07)<<1);
buf[5]=(unsigned char)(sys_clock>>22)&0xFF;
buf[6]=0x01|(unsigned char)((sys_clock>>14)&0xFE);
buf[7]=(unsigned char)((sys_clock>>7)&0xFF);
buf[8]=0x01|(unsigned char)((sys_clock<<1)&0xFE);
/* store mux rate */
buf[9]=0x80|(unsigned char)((mux_rate>>15)&0xEF);
buf[10]=(unsigned char)(mux_rate>>7)&0xFF;
buf[11]=0x01|(unsigned char)((mux_rate<<1)&0xFE);
return(12); /* bytes written */
}
/*
** Function: slibWriteMpeg1Systems()
** Descript: Writes out MPEG Video & Audio data conatined on Pins.
** Returns: TRUE if data was written, otherwise FALSE.
*/
static SlibBoolean_t slibWriteMpeg1Systems(SlibInfo_t *Info,
SlibBoolean_t flush)
{
SlibPin_t *audiopin, *videopin;
unsigned char *buf=NULL;
unsigned dword size=0, len;
unsigned char packet_data[PACKET_BUFFER_SIZE];
unsigned dword header_len;
SlibTime_t ptimestamp, dtimestamp, timediff=0;
SlibTime_t atime=SLIB_TIME_NONE, vtime=SLIB_TIME_NONE;
const unsigned dword std_audio_buf_size=Info->AudioBitRate ?
Info->AudioBitRate/8000 : 32;
const unsigned dword std_video_buf_size=Info->VideoBitRate ?
Info->VideoBitRate/25000 : 46;
int i;
_SlibDebug(_VERBOSE_||_WRITE_,
printf("slibWriteMpeg1Systems(flush=%d) BytesProcessed=%ld\n",
flush, Info->BytesProcessed) );
videopin = slibGetPin(Info, SLIB_DATA_VIDEO);
audiopin = slibGetPin(Info, SLIB_DATA_AUDIO);
if (!videopin && !audiopin)
return(FALSE);
if (!Info->HeaderProcessed || Info->BytesSincePack>=BYTES_PER_PACK)
{
/* mux_rate is in units of 50 bytes/s rounded up */
unsigned dword mux_rate=Info->TotalBitRate/(50*8)
+ ((Info->TotalBitRate%(50*8))?1:0);
Info->SystemTimeStamp=(Info->BytesProcessed*8000)/Info->TotalBitRate;
_SlibDebug(_VERBOSE_ || _WRITE_,
printf(" TotalBitRate=%d sys_clock=%d (%d ms) BytesSincePack=%d\n",
Info->TotalBitRate, Info->SystemTimeStamp*90,
Info->SystemTimeStamp, Info->BytesSincePack) );
len=slibCreateMpegPackHeader(packet_data,
Info->SystemTimeStamp*90, /* 90 Khz clock */
mux_rate);
if (slibPutBuffer(Info, packet_data, len)==SlibErrorNone)
{
Info->BytesProcessed+=len;
Info->BytesSincePack+=len;
if (Info->BytesSincePack>=BYTES_PER_PACK)
Info->BytesSincePack-=BYTES_PER_PACK;
}
}
if (!Info->HeaderProcessed)
{
if (!Info->IOError)
{
/* mux_rate is in units of 50 bytes/s rounded up */
unsigned dword mux_rate=Info->TotalBitRate/(50*8)
+ ((Info->TotalBitRate%(50*8))?1:0);
/******** systems header **********/
header_len=6+3*(Info->AudioStreams+Info->VideoStreams);
packet_data[0]=0x00;
packet_data[1]=0x00;
packet_data[2]=0x01;
packet_data[3]=(unsigned char)MPEG_SYSTEM_HEADER_START;
packet_data[4]=header_len>>8;
packet_data[5]=header_len & 0xFF;
packet_data[6]=0x80|((mux_rate>>15)&0xEF);
packet_data[7]=(mux_rate>>7)&0xFF;
packet_data[8]=0x01|((mux_rate<<1)&0xFE);
/* audio_bound(6 bits) + fixed_flag(1) + CSPS_falg(1) */
packet_data[9]=0x05;
/* sys_audio_lock_flag(1)+sys_video_lock_flag(1)+marker(1)+
video_bound(5 bits) */
packet_data[10]=0x80|0x40|0x20|0x01;
packet_data[11]=0xFF; /* reserved byte */
len=12;
for (i=0; i<Info->VideoStreams; i++)
{
packet_data[len++]=MPEG_VIDEO_STREAM_BASE+i;
packet_data[len++]=0xE0 | (std_video_buf_size>>8);
packet_data[len++]=std_video_buf_size & 0xFF;
}
for (i=0; i<Info->AudioStreams; i++)
{
packet_data[len++]=MPEG_AUDIO_STREAM_BASE+i;
packet_data[len++]=0xC0 | (std_audio_buf_size>>8);
packet_data[len++]=std_audio_buf_size & 0xFF;
}
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes of system header\n",
Info->Fd, len) );
if (slibPutBuffer(Info, packet_data, len)==SlibErrorNone)
{
Info->BytesProcessed+=len;
Info->BytesSincePack+=len;
}
}
Info->HeaderProcessed=TRUE;
}
atime=slibGetNextTimeOnPin(Info, audiopin, PACKET_SIZE-3);
vtime=slibGetNextTimeOnPin(Info, videopin, PACKET_SIZE-3);
if (SlibTimeIsInValid(atime))
atime=Info->LastAudioPTimeCode;
if (SlibTimeIsInValid(vtime))
vtime=Info->LastVideoPTimeCode;
if (!flush &&
(audiopin->DataSize<PACKET_SIZE-3 || videopin->DataSize<PACKET_SIZE-3))
return(TRUE); /* we need more data before writing */
if (!flush && audiopin && SlibTimeIsValid(atime) &&
videopin && SlibTimeIsValid(vtime))
timediff=atime-vtime-AUDIOTIME_ADJUST;
else
timediff=0;
/* write out complete Audio and/or Video packets */
while (!Info->IOError &&
((audiopin && timediff<=0 && audiopin->DataSize>=PACKET_SIZE-3) ||
(videopin && timediff>=0 && videopin->DataSize>=PACKET_SIZE-3)))
{
Info->SystemTimeStamp=(Info->BytesProcessed*8000)/Info->TotalBitRate;
_SlibDebug(_VERBOSE_ || _WRITE_,
printf(" TotalBitRate=%d sys_clock=%d (%d ms) BytesProcessed=%ld\n",
Info->TotalBitRate, Info->SystemTimeStamp*90,
Info->SystemTimeStamp, Info->BytesProcessed) );
if (Info->BytesSincePack>=BYTES_PER_PACK)
{
/* mux_rate is in units of 50 bytes/s rounded up */
unsigned dword mux_rate=Info->TotalBitRate/(50*8)
+ ((Info->TotalBitRate%(50*8))?1:0);
Info->SystemTimeStamp=(Info->BytesProcessed*8000)/Info->TotalBitRate;
_SlibDebug(_VERBOSE_ || _WRITE_,
printf(" TotalBitRate=%d sys_clock=%d (%d ms) mux_rate=%d BytesSincePack=%d\n",
Info->TotalBitRate, Info->SystemTimeStamp*90,
Info->SystemTimeStamp, mux_rate, Info->BytesSincePack) );
len=slibCreateMpegPackHeader(packet_data,
Info->SystemTimeStamp*90, /* 90 Khz clock */
mux_rate);
if (slibPutBuffer(Info, packet_data, len)==SlibErrorNone)
{
Info->BytesProcessed+=len;
Info->BytesSincePack+=len;
Info->BytesSincePack-=BYTES_PER_PACK;
}
}
if ((SlibTimeIsValid(atime) && atime-Info->SystemTimeStamp>300) ||
(SlibTimeIsValid(vtime) && vtime-Info->SystemTimeStamp>300))
{
/* we need a Padding packet */
_SlibDebug(_WRITE_||_TIMECODE_, printf("Padding\n") );
packet_data[0]=0x00;
packet_data[1]=0x00;
packet_data[2]=0x01;
packet_data[3]=MPEG_PADDING_STREAM_BASE;
packet_data[4]=PACKET_SIZE>>8; /* packet size - high byte */
packet_data[5]=PACKET_SIZE&0xFF; /* packet size - low byte */
packet_data[6]=0xFF;
packet_data[7]=0x0F; /* no presentation or time stamps */
size=PACKET_SIZE+6;
for (len=8; len<size; len++)
packet_data[len]=0xFF;
if (slibPutBuffer(Info, packet_data, size)==SlibErrorNone)
{
Info->BytesProcessed+=size;
Info->BytesSincePack+=size;
Info->PacketCount++;
}
}
else if (!flush && (atime>0 || vtime>0) &&
(atime+300<Info->SystemTimeStamp &&
vtime+300<Info->SystemTimeStamp))
{
/* we're not able to keep the bitrate low enough */
/* increase the Mux rate */
dword oldrate=Info->TotalBitRate;
SlibTime_t mintime=(vtime<atime) ? atime : vtime;
if (atime>0 && vtime>0)
mintime=(vtime<atime) ? vtime : atime;
Info->TotalBitRate=(dword)((Info->BytesProcessed*8000)/mintime);
if (Info->TotalBitRate==oldrate)
Info->TotalBitRate+=50*8;
Info->MuxBitRate=Info->TotalBitRate-Info->VideoBitRate-Info->AudioBitRate;
_SlibDebug(_WRITE_||_TIMECODE_,
printf("Bad Mux rate: atime=%ld vtime=%ld systime=%ld total=%ld -> %ld\n",
atime, vtime, Info->SystemTimeStamp, oldrate, Info->TotalBitRate) );
}
if (audiopin && timediff<=0 && audiopin->DataSize>=PACKET_SIZE-3)
{
packet_data[0]=0x00;
packet_data[1]=0x00;
packet_data[2]=0x01;
packet_data[3]=MPEG_AUDIO_STREAM_BASE;
packet_data[4]=PACKET_SIZE>>8; /* packet size - high byte */
packet_data[5]=PACKET_SIZE&0xFF; /* packet size - low byte */
/* 01 + STD_buffer_scale + STD_buffer_size[12..8] */
packet_data[6]=0x40 | 0x00 | (std_audio_buf_size>>8);
packet_data[7]=std_audio_buf_size & 0xFF;
ptimestamp=slibGetNextTimeOnPin(Info, audiopin, PACKET_SIZE-3);
if (SlibTimeIsValid(ptimestamp))
{
unsigned qword sys_clock=ptimestamp*90; /* 90 Khz clock */
_SlibDebug(_WRITE_||_TIMECODE_,
printf("LastAudioPTimeCode=%ld\n", Info->LastAudioPTimeCode) );
_SlibDebug(_WARN_ && (ptimestamp-(qword)Info->SystemTimeStamp>400 ||
(qword)Info->SystemTimeStamp-ptimestamp>400),
printf("Bad MuxRate(%d): SystemTimeStamp=%d ptimestamp=%d\n",
Info->SystemTimeStamp, ptimestamp) );
Info->LastAudioPTimeCode=ptimestamp;
sys_clock+=PTIME_ADJUST*90;
packet_data[8]=0x21|(unsigned char)(((sys_clock>>30)&0x07)<<1);
packet_data[9]=(unsigned char)(sys_clock>>22)&0xFF;
packet_data[10]=0x01|(unsigned char)((sys_clock>>14)&0xFE);
packet_data[11]=(unsigned char)((sys_clock>>7)&0xFF);
packet_data[12]=0x01|(unsigned char)((sys_clock<<1)&0xFE);
size=slibFillBufferFromPin(Info, audiopin, packet_data+13,
PACKET_SIZE-7, NULL);
size+=13;
}
else
{
packet_data[8]=0x0F; /* no presentation or time stamps */
size=slibFillBufferFromPin(Info, audiopin, packet_data+9,
PACKET_SIZE-3, NULL);
size+=9;
}
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes of audio\n", Info->Fd, size) );
if (slibPutBuffer(Info, packet_data, size)==SlibErrorNone)
{
Info->BytesProcessed+=size;
Info->BytesSincePack+=size;
Info->PacketCount++;
}
}
if (videopin && !Info->IOError && timediff>=0 &&
videopin->DataSize>=PACKET_SIZE-3)
{
packet_data[0]=0x00;
packet_data[1]=0x00;
packet_data[2]=0x01;
packet_data[3]=MPEG_VIDEO_STREAM_BASE;
packet_data[4]=PACKET_SIZE>>8; /* packet size - high byte */
packet_data[5]=PACKET_SIZE&0xFF; /* packet size - low byte */
/* 01 + STD_buffer_scale + STD_buffer_size[12..8] */
packet_data[6]=0x40 | 0x20 | (std_video_buf_size>>8);
packet_data[7]=std_video_buf_size & 0xFF;
/* store presentation time stamp */
ptimestamp=slibGetNextTimeOnPin(Info, videopin, PACKET_SIZE-3);
if (SlibTimeIsValid(ptimestamp))
{
unsigned qword sys_clock=ptimestamp*90; /* 90 Khz clock */
_SlibDebug(_WRITE_||_TIMECODE_,
printf("LastVideoPTimeCode=%ld LastVideoDTimeCode=%ld\n",
Info->LastVideoPTimeCode,
Info->LastVideoDTimeCode) );
if (SlibTimeIsInValid(Info->LastVideoDTimeCode))
dtimestamp=ptimestamp-(qword)(1000/Info->FramesPerSec);
else if (ptimestamp-Info->LastVideoPTimeCode>33*3)
dtimestamp=Info->LastVideoDTimeCode;
else
dtimestamp=SLIB_TIME_NONE;
Info->LastVideoPTimeCode=ptimestamp;
sys_clock+=PTIME_ADJUST*90;
packet_data[8]=(dtimestamp!=SLIB_TIME_NONE)?0x30:0x20;
packet_data[8]|=0x01|(unsigned char)(((sys_clock>>30)&0x07)<<1);
packet_data[9]=(unsigned char)(sys_clock>>22)&0xFF;
packet_data[10]=0x01|(unsigned char)((sys_clock>>14)&0xFE);
packet_data[11]=(unsigned char)((sys_clock>>7)&0xFF);
packet_data[12]=0x01|(unsigned char)((sys_clock<<1)&0xFE);
if (dtimestamp!=SLIB_TIME_NONE)
{
sys_clock=dtimestamp*90; /* 90 Khz clock */
Info->LastVideoDTimeCode=ptimestamp;
sys_clock+=PTIME_ADJUST*90;
packet_data[13]=0x01|(unsigned char)(((sys_clock>>30)&0x07)<<1);
packet_data[14]=(unsigned char)(sys_clock>>22)&0xFF;
packet_data[15]=0x01|(unsigned char)((sys_clock>>14)&0xFE);
packet_data[16]=(unsigned char)((sys_clock>>7)&0xFF);
packet_data[17]=0x01|(unsigned char)((sys_clock<<1)&0xFE);
size=slibFillBufferFromPin(Info, videopin, packet_data+18,
PACKET_SIZE-12, NULL);
size+=18;
}
else
{
size=slibFillBufferFromPin(Info, videopin, packet_data+13,
PACKET_SIZE-7, NULL);
size+=13;
}
}
else
{
packet_data[8]=0x0F; /* no presentation or time stamps */
size=slibFillBufferFromPin(Info, videopin, packet_data+9,
PACKET_SIZE-3, NULL);
size+=9;
}
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes of video\n", Info->Fd, size) );
if (slibPutBuffer(Info, packet_data, size)==SlibErrorNone)
{
Info->BytesProcessed+=size;
Info->BytesSincePack+=size;
Info->PacketCount++;
}
}
/* need to wait until we get enough data on both audio and video pin */
if (audiopin && videopin && !flush &&
(audiopin->DataSize<PACKET_SIZE-3 || videopin->DataSize<PACKET_SIZE-3))
{
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("atime=%d vtime=%ld audiodata=%d videodata=%d\n",
atime, vtime, audiopin->DataSize, videopin->DataSize) );
break;
}
/* recalculate time differences */
timediff=slibGetNextTimeOnPin(Info, audiopin, PACKET_SIZE-3);
if (SlibTimeIsValid(timediff)) atime=timediff;
timediff=slibGetNextTimeOnPin(Info, videopin, PACKET_SIZE-3);
if (SlibTimeIsValid(timediff)) vtime=timediff;
if (!flush && audiopin && SlibTimeIsValid(atime) &&
videopin && SlibTimeIsValid(vtime))
timediff=atime-vtime-AUDIOTIME_ADJUST;
else
timediff=0;
}
/* flushing: write out remained Audio and/or Video data */
if (flush && !Info->IOError)
{
if (audiopin && audiopin->DataSize)
{
packet_data[0]=0x00;
packet_data[1]=0x00;
packet_data[2]=0x01;
packet_data[3]=MPEG_AUDIO_STREAM_BASE;
packet_data[4]=(unsigned char)((audiopin->DataSize+3)>>8);
packet_data[5]=(unsigned char)((audiopin->DataSize+3)&0xFF);
packet_data[6]=0x40 | (std_audio_buf_size>>8);
packet_data[7]=std_audio_buf_size & 0xFF;
packet_data[8]=0x0F; /* no presentation or time stamps */
size=slibFillBufferFromPin(Info, audiopin, packet_data+9,
(unsigned long)audiopin->DataSize, NULL);
size+=9;
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes of audio (flush)\n", Info->Fd, size));
if (slibPutBuffer(Info, packet_data, size)==SlibErrorNone)
{
Info->BytesProcessed+=size;
Info->BytesSincePack+=size;
Info->PacketCount++;
}
}
if (videopin && videopin->DataSize && !Info->IOError)
{
packet_data[0]=0x00;
packet_data[1]=0x00;
packet_data[2]=0x01;
packet_data[3]=MPEG_VIDEO_STREAM_BASE;
packet_data[4]=(unsigned char)((videopin->DataSize+3)>>8);
packet_data[5]=(unsigned char)((videopin->DataSize+3)&0xFF);
packet_data[6]=0x60 | (std_video_buf_size>>8);
packet_data[7]=std_video_buf_size & 0xFF;
packet_data[8]=0x0F; /* no presentation or time stamps */
size=slibFillBufferFromPin(Info,videopin,packet_data+9,
(unsigned long)videopin->DataSize, NULL);
size+=9;
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes of video (flush)\n",
Info->Fd, size) );
if (slibPutBuffer(Info, packet_data, size)==SlibErrorNone)
{
Info->BytesProcessed+=size;
Info->BytesSincePack+=size;
Info->PacketCount++;
}
}
}
if (flush && !Info->IOError) /* write End-Of-Sequence code */
{
unsigned char sys_trailer[4] = { 0x00, 0x00, 0x01, 0xB9 };
if (slibPutBuffer(Info, sys_trailer, sizeof(sys_trailer))==SlibErrorNone)
{
Info->BytesProcessed+=sizeof(sys_trailer);
Info->BytesSincePack+=sizeof(sys_trailer);
}
}
return(TRUE);
}
#endif /* MPEG_SUPPORT */
#ifdef MPEG_SUPPORT
/*
** Function: slibWriteMpegAudio()
** Descript: Writes out MPEG Audio stream data contained on Audio Pin.
** Returns: TRUE if data was written, otherwise FALSE.
*/
static SlibBoolean_t slibWriteMpegAudio(SlibInfo_t *Info, SlibBoolean_t flush)
{
SlibPin_t *srcpin=NULL;
unsigned char *buf=NULL;
unsigned dword size=0;
_SlibDebug(_VERBOSE_, printf("slibWriteMpegAudio()\n") );
if ((srcpin = slibGetPin(Info, SLIB_DATA_AUDIO))==NULL)
return(FALSE);
while ((buf=slibGetBufferFromPin(Info, srcpin, &size, NULL))!=NULL)
{
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("==SlibErrorNone(%d) %d bytes\n", Info->Fd, size) );
if (slibPutBuffer(Info, buf, size)==SlibErrorNone)
Info->HeaderProcessed=TRUE;
}
return(TRUE);
}
#endif /* MPEG_SUPPORT */
#ifdef MPEG_SUPPORT
/*
** Function: slibWriteMpegVideo()
** Descript: Writes out MPEG Video stream data contained on Video Pin.
** Returns: TRUE if data was written, otherwise FALSE.
*/
static SlibBoolean_t slibWriteMpegVideo(SlibInfo_t *Info, SlibBoolean_t flush)
{
SlibPin_t *srcpin=NULL;
unsigned char *buf=NULL;
unsigned dword size=0;
_SlibDebug(_VERBOSE_, printf("slibWriteMpegVideo()\n") );
if ((srcpin = slibGetPin(Info, SLIB_DATA_VIDEO))==NULL)
return(FALSE);
while ((buf=slibGetBufferFromPin(Info, srcpin, &size, NULL))!=NULL)
{
if (slibPutBuffer(Info, buf, size)==SlibErrorNone)
Info->HeaderProcessed=TRUE;
}
return(TRUE);
}
#endif /* MPEG_SUPPORT */
#ifdef H261_SUPPORT
/*
** Function: slibWriteH261()
** Descript: Writes out H261 Video stream data contained on Video Pin.
** Returns: TRUE if data was written, otherwise FALSE.
*/
static SlibBoolean_t slibWriteH261(SlibInfo_t *Info, SlibBoolean_t flush)
{
SlibPin_t *srcpin=NULL;
unsigned char *buf=NULL;
unsigned dword size=0;
_SlibDebug(_VERBOSE_, printf("slibWriteH261()\n") );
if ((srcpin = slibGetPin(Info, SLIB_DATA_VIDEO))==NULL)
return(FALSE);
while ((buf=slibGetBufferFromPin(Info, srcpin, &size, NULL))!=NULL)
{
if (slibPutBuffer(Info, buf, size)==SlibErrorNone)
Info->HeaderProcessed=TRUE;
}
return(TRUE);
}
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
/*
** Function: slibWriteH263()
** Descript: Writes out H263 Video stream data contained on Video Pin.
** Returns: TRUE if data was written, otherwise FALSE.
*/
static SlibBoolean_t slibWriteH263(SlibInfo_t *Info, SlibBoolean_t flush)
{
SlibPin_t *srcpin=NULL;
unsigned char *buf=NULL;
unsigned dword size=0;
_SlibDebug(_VERBOSE_, printf("slibWriteH263()\n") );
if ((srcpin = slibGetPin(Info, SLIB_DATA_VIDEO))==NULL)
return(FALSE);
while ((buf=slibGetBufferFromPin(Info, srcpin, &size, NULL))!=NULL)
{
if (slibPutBuffer(Info, buf, size)==SlibErrorNone)
Info->HeaderProcessed=TRUE;
}
return(TRUE);
}
#endif /* H263_SUPPORT */
#ifdef HUFF_SUPPORT
/*
** Function: slibWriteSlibHuff()
** Descript: Writes out SLIB Huff Video stream data contained on Video Pin.
** Returns: TRUE if data was written, otherwise FALSE.
*/
static SlibBoolean_t slibWriteSlibHuff(SlibInfo_t *Info, SlibBoolean_t flush)
{
SlibPin_t *srcpin=NULL;
unsigned char *buf=NULL;
unsigned dword size=0;
_SlibDebug(_VERBOSE_, printf("slibWriteSlibHuff()\n") );
if ((srcpin = slibGetPin(Info, SLIB_DATA_VIDEO))==NULL)
return(FALSE);
if (!Info->HeaderProcessed)
{
if (!Info->IOError)
{
char header[] = { 'S','L','I','B','H','U','F','F' };
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes of header\n",
Info->Fd, sizeof(header)) );
slibPutBuffer(Info, header, sizeof(header));
}
Info->HeaderProcessed=TRUE;
}
while ((buf=slibGetBufferFromPin(Info, srcpin, &size, NULL))!=NULL)
{
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes\n", Info->Fd, size) );
slibPutBuffer(Info, buf, size);
}
return(TRUE);
}
#endif /* HUFF_SUPPORT */
#ifdef G723_SUPPORT
/*
** Function: slibWriteG723Audio()
** Descript: Writes out G723 Audio stream data contained on Audio Pin.
** Returns: TRUE if data was written, otherwise FALSE.
*/
static SlibBoolean_t slibWriteG723Audio(SlibInfo_t *Info, SlibBoolean_t flush)
{
SlibPin_t *srcpin=NULL;
unsigned char *buf=NULL;
unsigned dword size=0;
_SlibDebug(_VERBOSE_, printf("slibWriteG723Audio()\n") );
if ((srcpin = slibGetPin(Info, SLIB_DATA_AUDIO))==NULL)
return(FALSE);
//MVP: There is no header to write for G723 codec
//After successful first "Write" set the "headerProcessed to TRUE
if (!Info->HeaderProcessed)
{
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, NULL))!=NULL)
slibPutBuffer(Info, buf, size);
//Set Header processed flag to True
if (!Info->IOError)
Info->HeaderProcessed=TRUE;
}
while ((buf=slibGetBufferFromPin(Info, srcpin, &size, NULL))!=NULL)
slibPutBuffer(Info, buf, size);
return(TRUE);
}
#endif /* G723_SUPPORT */
/*
** Name: slibCommitBuffers
** Desc: Move buffers queued for output to there destination.
*/
SlibBoolean_t slibCommitBuffers(SlibInfo_t *Info, SlibBoolean_t flush)
{
SlibPin_t *srcpin=NULL;
unsigned char *buf=NULL;
unsigned dword size=0;
switch (Info->Type)
{
#ifdef H261_SUPPORT
case SLIB_TYPE_H261:
slibWriteH261(Info, flush);
break;
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
case SLIB_TYPE_H263:
slibWriteH263(Info, flush);
break;
#endif /* H263_SUPPORT */
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_VIDEO:
case SLIB_TYPE_MPEG2_VIDEO:
slibWriteMpegVideo(Info, flush);
break;
case SLIB_TYPE_MPEG1_AUDIO:
slibWriteMpegAudio(Info, flush);
break;
case SLIB_TYPE_MPEG_SYSTEMS:
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
slibWriteMpeg1Systems(Info, flush);
break;
#endif /* MPEG_SUPPORT */
#ifdef HUFF_SUPPORT
case SLIB_TYPE_SHUFF:
slibWriteSlibHuff(Info, flush);
break;
#endif /* HUFF_SUPPORT */
#ifdef G723_SUPPORT
case SLIB_TYPE_G723:
slibWriteG723Audio(Info, flush);
break;
#endif /* G723_SUPPORT */
default:
_SlibDebug(_VERBOSE_ || _WARN_,
printf("slibCommitBuffers() Unknown type\n") );
return(FALSE);
}
return(Info->IOError ? FALSE : TRUE);
}
/************************** Data Stream Parsers ***********************/
/*
** Function: slibParseWave()
** Descript: Parse Wave (RIFF) and add Audio data to Audio Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseWave(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_AUDIO);
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
if (Info->AudioTimeStamp==0)
{
/* Discard header data from Compressed Pin */
buf = slibSearchBuffersOnPin(Info, srcpin,
NULL, &size, RIFF_DATA, 4, TRUE);
if (buf)
{
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
slibGetDWordFromPin(Info, srcpin); /* discard Chunk size */
Info->AudioTimeStamp=1;
}
}
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
_SlibDebug(_DEBUG_, printf("slibParseWave() adding %d bytes\n", size));
slibAddBufferToPin(dstpin, buf, size, time);
return(TRUE);
}
}
return(FALSE);
}
#ifdef AC3_SUPPORT
/*
** Function: slibParseAC3Audio()
** Descript: Parse Dolby AC-3 Audio stream and add Audio data to Audio Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseAC3Audio(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
_SlibDebug(_DEBUG_, printf("slibParseMpegAudio()\n"));
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_AUDIO);
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
slibAddBufferToPin(dstpin, buf, size, time);
_SlibDebug(_DEBUG_, printf("slibParseAC3Audio() added %d bytes\n",
size));
return(TRUE);
}
}
return(FALSE);
}
#endif /* AC3_SUPPORT */
#ifdef MPEG_SUPPORT
/*
** Function: slibParseMpegAudio()
** Descript: Parse MPEG Audio stream and add Audio data to Audio Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseMpegAudio(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
_SlibDebug(_DEBUG_, printf("slibParseMpegAudio()\n"));
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_AUDIO);
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
slibAddBufferToPin(dstpin, buf, size, time);
_SlibDebug(_DEBUG_, printf("slibParseMpegAudio() added %d bytes\n",
size));
return(TRUE);
}
}
return(FALSE);
}
#endif /* MPEG_SUPPORT */
#ifdef MPEG_SUPPORT
/*
** Function: slibParseMpegVideo()
** Descript: Parse MPEG Video stream and add Video data to Video Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseMpegVideo(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
_SlibDebug(_DEBUG_, printf("slibParseMpegVideo()\n"));
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
slibAddBufferToPin(dstpin, buf, size, time);
_SlibDebug(_DEBUG_, printf("slibParseMpegVideo() added %d bytes\n",
size));
return(TRUE);
}
_SlibDebug(_DEBUG_,
printf("slibParseMpegVideo() couldn't get COMPRESSED data\n"));
}
_SlibDebug(_DEBUG_, printf("slibParseMpegVideo() pins not ready\n"));
return(FALSE);
}
#endif /* MPEG_SUPPORT */
#ifdef MPEG_SUPPORT
#define skipbytes(b) if (size<=b) { \
oldsize = size; SlibFreeBuffer(bufstart); \
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL); \
if (!buf) return(FALSE); \
buf+=b-oldsize; size-=b-oldsize; \
} else { buf+=b; size-=b; }
/*
** Function: slibParseMpeg1Sytems()
** Descript: Parse MPEG I Systems stream and add Video data to Video Pin
** and Audio to the Audio Pin.
** Returns: TRUE if data was added to fillpin, otherwise FALSE.
*/
SlibBoolean_t slibParseMpeg1Systems(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *fillpin)
{
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
_SlibDebug(_DEBUG_ || _PARSE_, printf("slibParseMpeg1Systems()\n"));
if (srcpin)
{
unsigned char abyte, packettype;
unsigned dword PacketLength;
unsigned char *buf, *bufstart=NULL;
unsigned dword size, oldsize;
SlibTime_t ptimestamp=SLIB_TIME_NONE;
SlibPin_t *dstpin;
while ((buf = bufstart = slibSearchBuffersOnPin(Info, srcpin, NULL,
&size, MPEG_START_CODE, MPEG_START_CODE_LEN/8, TRUE))!=NULL)
{
_SlibDebug(_VERIFY_ && size<1, printf("Insufficient bytes #1\n") );
packettype = *buf;
skipbytes(1);
if (packettype > 0xBB) /* it's a packet */
{
_SlibDebug(_DEBUG_||_PARSE_, printf("Found Packet size=%d\n", size));
PacketLength=(unsigned dword)(*buf<<8);
skipbytes(1);
PacketLength|=(unsigned dword)*buf;
skipbytes(1);
_SlibDebug(_DEBUG_||_PARSE_, printf(" PacketLength=%d\n",PacketLength));
while (*buf == 0xFF) /* Stuffing bytes */
{
skipbytes(1);
PacketLength--;
}
_SlibDebug(_VERIFY_ && size<1, printf("Insufficient bytes #3\n") );
abyte=*buf;
if ((abyte & 0xC0)==0x40) /* STD_buffer stuff */
{
skipbytes(2);
PacketLength-=2;
abyte=*buf;
}
_SlibDebug(_VERIFY_ && size<1, printf("Insufficient bytes #4\n") );
if ((abyte & 0xF0)==0x20 || (abyte & 0xF0)==0x30)
{
if (packettype!=Info->VideoMainStream &&
packettype!=Info->AudioMainStream)
{
skipbytes(5); /* skip Presentation Time Stamp */
PacketLength-=5;
if ((abyte & 0xF0)==0x30) /* skip Decoding timestamp */
{
skipbytes(5);
PacketLength-=5;
}
}
else
{
/* Presentation Time Stamp */
ptimestamp=(*buf)&0x0E; ptimestamp<<=7;
skipbytes(1);
ptimestamp|=(*buf); ptimestamp<<=8;
skipbytes(1);
ptimestamp|=(*buf)&0xFE; ptimestamp<<=7;
skipbytes(1);
ptimestamp|=(*buf); ptimestamp<<=7;
skipbytes(1);
ptimestamp|=(*buf)&0xFE;
skipbytes(1);
ptimestamp/=90;
if (packettype==Info->VideoMainStream)
{
if (!SlibTimeIsValid(Info->VideoPTimeBase) ||
ptimestamp<Info->VideoPTimeBase)
{
Info->VideoPTimeBase=ptimestamp;
_SlibDebug(_PARSE_ || _TIMECODE_,
printf("slibParseMpeg1Systems() VideoPTimeBase=%ld\n",
Info->VideoPTimeBase));
}
}
else if (packettype==Info->AudioMainStream)
{
if (!SlibTimeIsValid(Info->AudioPTimeBase) ||
ptimestamp<Info->AudioPTimeBase)
{
Info->AudioPTimeBase=ptimestamp;
_SlibDebug(_PARSE_ || _TIMECODE_,
printf("slibParseMpeg1Systems() AudioPTimeBase=%ld\n",
Info->AudioPTimeBase));
}
}
PacketLength-=5;
/* Decoding timestamp */
if ((abyte & 0xF0)==0x30)
{
SlibTime_t dtimestamp;
dtimestamp=(*buf)&0x0E; dtimestamp<<=7;
skipbytes(1);
dtimestamp|=(*buf); dtimestamp<<=8;
skipbytes(1);
dtimestamp|=(*buf)&0xFE; dtimestamp<<=7;
skipbytes(1);
dtimestamp|=(*buf); dtimestamp<<=7;
skipbytes(1);
dtimestamp|=(*buf)&0xFE;
skipbytes(1);
dtimestamp/=90;
if (packettype==Info->VideoMainStream)
{
_SlibDebug(_TIMECODE_,
printf("Video DTimeCode=%d\n", dtimestamp) );
Info->VideoDTimeCode=dtimestamp;
}
else if (packettype==Info->AudioMainStream)
{
_SlibDebug(_TIMECODE_,
printf("Audio DTimeCode=%d\n", dtimestamp) );
Info->AudioDTimeCode=dtimestamp;
}
PacketLength-=5;
}
}
}
else if (abyte != 0x0F)
{
_SlibDebug(_VERIFY_, printf("Last byte before data not 0x0F\n") );
/* add remaining buffer data back to input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
_SlibDebug(_VERIFY_, printf("Searching for next packet\n") );
continue; /* try to recover */
}
else
{
skipbytes(1);
PacketLength--;
}
if (packettype==Info->VideoMainStream)
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
else if (packettype==Info->AudioMainStream)
dstpin = slibGetPin(Info, SLIB_DATA_AUDIO);
else
dstpin = NULL;
if (dstpin && slibPinOverflowing(Info, dstpin))
{
slibPinPrepareReposition(Info, dstpin->ID);
_SlibDebug(_WARN_,
printf("Skipped data on Overflowing pin %s: time %d->",
dstpin->name, Info->VideoTimeStamp) );
if (dstpin->ID == SLIB_DATA_VIDEO)
{
dword frames=slibCountCodesOnPin(Info, dstpin,
MPEG_PICTURE_START, 4, Info->OverflowSize/2);
if (Info->FramesPerSec)
Info->VideoTimeStamp+=slibFrameToTime(Info, frames);
}
_SlibDebug(_WARN_,
printf("new videotime=%ld\n", Info->VideoTimeStamp) );
slibSkipDataOnPin(Info, dstpin, Info->OverflowSize/2);
slibPinFinishReposition(Info, dstpin->ID);
if (dstpin->ID == SLIB_DATA_VIDEO) /* move to key frame */
SlibSeek((SlibHandle_t *)Info, SLIB_STREAM_MAINVIDEO,
SLIB_SEEK_NEXT_KEY, 0);
}
if (dstpin && !slibPinOverflowing(Info, dstpin))
{
_SlibDebug(_DEBUG_>1, printf("Adding Packet %X\n", packettype) );
/* add the packet to the destination pin */
while (PacketLength>size)
{
_SlibDebug(_WARN_>1,
printf("PacketLength=%d but buffer is %d bytes\n",
PacketLength, size) );
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
printf("#1 size = %d\n", size));
if (size)
{
SlibAllocSubBuffer(buf, size);
slibAddBufferToPin(dstpin, buf, size, ptimestamp);
ptimestamp=SLIB_TIME_NONE;
PacketLength-=size;
}
SlibFreeBuffer(bufstart);
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
if (!buf)
return(fillpin==dstpin ? TRUE : FALSE);
}
if (PacketLength)
{
SlibAllocSubBuffer(buf, PacketLength);
slibAddBufferToPin(dstpin, buf, PacketLength, ptimestamp);
ptimestamp=SLIB_TIME_NONE;
size-=PacketLength;
buf+=PacketLength;
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
printf("#3 size = %d\n", size));
}
/* add remaining buffer data back to input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
if (fillpin==dstpin)
return(TRUE);
if (fillpin==NULL)
return(FALSE);
}
else /* dump the packet */
{
_SlibDebug(_WARN_ && dstpin,
printf("Dumping packet %X (Overflow)\n", packettype) );
_SlibDebug((_WARN_>1 && !dstpin)||packettype==Info->VideoMainStream
||packettype==Info->AudioMainStream,
printf("Dumping packet %X (No pin)\n", packettype) );
while (PacketLength>size)
{
PacketLength-=size;
SlibFreeBuffer(bufstart);
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
_SlibDebug(_VERIFY_ && !buf,
printf("Dumping Packet: no more buffers\n"));
if (buf==NULL)
return(FALSE);
}
buf+=PacketLength;
size-=PacketLength;
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
printf("#5 size = %d\n", size));
/* add remaining buffer data back to input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
ptimestamp=SLIB_TIME_NONE;
}
} /* packet */
else /* put buffer back on the input pin */
{
_SlibDebug(_DEBUG_, printf("Not a packet %X - putting back buffer\n",
packettype) );
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
printf("#6 size = %d\n", size));
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
}
} /* while */
}
return(FALSE);
}
#endif /* MPEG_SUPPORT */
#ifdef MPEG_SUPPORT
static SlibBoolean_t slibParsePESHeader(SlibInfo_t *Info, SlibPin_t *srcpin,
unsigned char **bufferstart, unsigned char **buffer,
unsigned dword *buffersize,
int *headerlen, unsigned dword *packetlen,
int *packettype, SlibTime_t *ptimestamp)
{
unsigned dword bytesprocessed=0;
unsigned dword PES_packet_length=0;
unsigned char *buf, *bufstart;
unsigned dword size, oldsize, header_len;
_SlibDebug(_DEBUG_||_VERBOSE_||_PARSE_, printf("slibParsePESHeader()\n"));
if (*buffer==NULL)
{
*packettype=0;
_SlibDebug(_VERIFY_,
buf=slibPeekBufferOnPin(Info, srcpin, &size, NULL);
if (buf && size>=8 && (buf[0]!=0x00 || buf[1]!=0x00 || buf[2]!=0x01))
ScDebugPrintf(Info->dbg,
"slibParsePESHeader() lost start code: %02X %02X %02X %02X %02X %02X %02X %02X\n",
buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7]) );
do {
size=0;
buf = bufstart = slibSearchBuffersOnPin(Info, srcpin, NULL,
&size, MPEG_START_CODE, MPEG_START_CODE_LEN/8, TRUE);
if (!buf) return(FALSE);
*packettype=*buf;
if (*packettype>0xBB) /* useful packet start code */
{
skipbytes(1); /* skip packettype */
break;
}
_SlibDebug(_DEBUG_||_PARSE_,
ScDebugPrintf(Info->dbg,
"slibParsePESHeader() skipping packettype=%02X\n", *packettype));
/* put buffer back on the input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
} while (1);
}
else
{
buf=*buffer;
bufstart=*bufferstart;
size=*buffersize;
_SlibDebug(_VERIFY_ && size<4, ScDebugPrintf(Info->dbg,"Insufficient bytes #5\n") );
if (buf[0]==0x00 && buf[1]==0x00 && buf[2]==0x01)
{
*packettype=buf[3];
if (*packettype>0xBB)
{
skipbytes(4); /* skip start code */
bytesprocessed+=4;
}
}
else
*packettype=0;
}
if (*packettype>0xBB) /* useful packet start code */
{
unsigned short PTS_DTS_flags;
_SlibDebug(_DEBUG_||_PARSE_,
printf("slibParsePESHeader() packettype=%02X\n", *packettype));
_SlibDebug(_VERIFY_ && size<4, ScDebugPrintf(Info->dbg,"Insufficient bytes #6\n") );
/* PES_packet_length */
PES_packet_length=((unsigned dword)buf[0])<<8;
skipbytes(1);
PES_packet_length|=buf[0];
skipbytes(1);
bytesprocessed+=2;
if (*packettype==MPEG_PROGRAM_STREAM ||
*packettype==MPEG_PADDING_STREAM_BASE ||
*packettype==MPEG_PRIVATE_STREAM2_BASE)
{
PTS_DTS_flags=0;
header_len=0;
_SlibDebug(_DEBUG_||_PARSE_,
ScDebugPrintf(Info->dbg,"PES Packet 0x%02X, Length=%d, Header Len=%d\n",
*packettype, PES_packet_length, header_len));
}
else
{
/* PES_packet_length-=18; */
/* PES header stuff */
_SlibDebug(_PARSE_ && size>4, ScDebugPrintf(Info->dbg,
"PES Packet 0x%02X, header stuff: 0x%02X %02X %02X %02X\n",
*packettype, buf[0], buf[1], buf[2], buf[3]));
skipbytes(1);
PTS_DTS_flags=buf[0]>>6;
skipbytes(1);
header_len=buf[0];/* get PES header len */
skipbytes(1); /* PES header len */
bytesprocessed+=3;
PES_packet_length-=3;
PES_packet_length-=header_len;
_SlibDebug(_DEBUG_||_PARSE_,
ScDebugPrintf(Info->dbg,
"PES Packet 0x%02X, Length=%d, Header Len=%d, PTS_DTS_flags=%d\n",
*packettype, PES_packet_length, header_len, PTS_DTS_flags ));
if (header_len>0 && (PTS_DTS_flags==2 || PTS_DTS_flags==3))
{
/* Presentation Time Stamp */
unsigned long timestamp;
timestamp=(*buf)&0x0E; timestamp<<=7;
skipbytes(1);
timestamp|=(*buf); timestamp<<=8;
skipbytes(1);
timestamp|=(*buf)&0xFE; timestamp<<=7;
skipbytes(1);
timestamp|=(*buf); timestamp<<=7;
skipbytes(1);
timestamp|=(*buf)&0xFE;
skipbytes(1);
timestamp/=90;
*ptimestamp = timestamp;
bytesprocessed+=5;
header_len-=5;
/* Decoding timestamp */
if (PTS_DTS_flags==3)
{
timestamp=(*buf)&0x0E; timestamp<<=7;
skipbytes(1);
timestamp|=(*buf); timestamp<<=8;
skipbytes(1);
timestamp|=(*buf)&0xFE; timestamp<<=7;
skipbytes(1);
timestamp|=(*buf); timestamp<<=7;
skipbytes(1);
timestamp|=(*buf)&0xFE;
skipbytes(1);
timestamp/=90;
if (*packettype==Info->VideoMainStream ||
(Info->Type==SLIB_TYPE_MPEG_TRANSPORT &&
*packettype>=MPEG_VIDEO_STREAM_START &&
*packettype<=MPEG_VIDEO_STREAM_END))
{
_SlibDebug(_TIMECODE_,
ScDebugPrintf(Info->dbg,"Video DTimeCode=%d\n",timestamp));
Info->VideoDTimeCode=timestamp;
}
else if (*packettype==Info->AudioMainStream ||
(Info->Type==SLIB_TYPE_MPEG_TRANSPORT &&
*packettype>=MPEG_AUDIO_STREAM_START &&
*packettype<=MPEG_AUDIO_STREAM_END))
{
_SlibDebug(_TIMECODE_,
ScDebugPrintf(Info->dbg,"Audio DTimeCode=%d\n",timestamp));
Info->AudioDTimeCode=timestamp;
}
bytesprocessed+=5;
header_len-=5;
}
}
}
if (header_len>0)
{
_SlibDebug(_PARSE_,
ScDebugPrintf(Info->dbg,"slibParsePESHeader() skipping header: %d bytes\n",
header_len));
while ((int)size<=header_len)
{
_SlibDebug(_PARSE_,
ScDebugPrintf(Info->dbg,"slibParsePESHeader() size=%d <= header_len=%d\n",
size, header_len));
SlibFreeBuffer(bufstart);
header_len-=size;
bytesprocessed+=size;
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
if (!buf) return(FALSE);
}
buf+=header_len;
_SlibDebug(_VERIFY_ && size<(unsigned dword)header_len,
ScDebugPrintf(Info->dbg,"Insufficient bytes\n") );
size-=header_len;
bytesprocessed+=header_len;
}
}
/* If this is private data containing AC3, skip private header */
if (*packettype==MPEG_PRIVATE_STREAM1_BASE && (size<=0 || *buf==0x80))
{
/* header = 4 bytes = Hex: 80 0X XX XX */
skipbytes(4);
bytesprocessed+=4;
PES_packet_length-=4;
}
*buffer=buf;
*bufferstart=bufstart;
*buffersize=size;
if (headerlen)
*headerlen=bytesprocessed;
if (packetlen)
*packetlen=PES_packet_length;
_SlibDebug(_PARSE_,
ScDebugPrintf(Info->dbg,"slibParsePESHeader() bytesprocessed=%d packetlen=%d\n",
bytesprocessed, PES_packet_length));
return(TRUE);
}
#endif /* MPEG_SUPPORT */
#ifdef MPEG_SUPPORT
/*
** Function: slibParseMpeg2Program()
** Descript: Parse MPEG II Program stream and add Video data to Video Pin
** and Audio to the Audio Pin.
** Returns: TRUE if data was added to fillpin, otherwise FALSE.
*/
SlibBoolean_t slibParseMpeg2Program(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *fillpin)
{
_SlibDebug(_DEBUG_||_PARSE_, ScDebugPrintf(Info->dbg,"slibParseMpeg2Program()\n"));
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (srcpin)
{
unsigned dword PacketLength;
unsigned char *buf, *bufstart=NULL;
unsigned dword size;
SlibTime_t ptimestamp = SLIB_TIME_NONE;
int header_len, packettype;
SlibPin_t *dstpin;
do {
buf=NULL;
if (!slibParsePESHeader(Info, srcpin, &bufstart, &buf, &size,
&header_len, &PacketLength, &packettype,
&ptimestamp))
{
_SlibDebug(_WARN_, ScDebugPrintf(Info->dbg,"slibParsePESHeader() failed\n") );
return(FALSE);
}
if (packettype)
{
if (packettype==Info->VideoMainStream)
{
_SlibDebug(_PARSE_,
ScDebugPrintf(Info->dbg,"slibParseMpeg2Program() VIDEO packet\n"));
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
if (SlibTimeIsValid(ptimestamp) &&
(!SlibTimeIsValid(Info->VideoPTimeBase) ||
ptimestamp<Info->VideoPTimeBase))
{
Info->VideoPTimeBase=ptimestamp;
_SlibDebug(_PARSE_ || _TIMECODE_,
ScDebugPrintf(Info->dbg,"slibParseMpeg2Program() VideoPTimeBase=%ld\n",
Info->VideoPTimeBase));
}
}
else if (packettype==Info->AudioMainStream)
{
_SlibDebug(_PARSE_,
ScDebugPrintf(Info->dbg,"slibParseMpeg2Program() AUDIO packet\n"));
dstpin = slibGetPin(Info, SLIB_DATA_AUDIO);
if (SlibTimeIsValid(ptimestamp) &&
(!SlibTimeIsValid(Info->AudioPTimeBase) ||
ptimestamp<Info->AudioPTimeBase))
{
Info->AudioPTimeBase=ptimestamp;
_SlibDebug(_PARSE_ || _TIMECODE_,
ScDebugPrintf(Info->dbg,"slibParseMpeg2Program() AudioPTimeBase=%ld\n",
Info->AudioPTimeBase));
}
}
else if (packettype==MPEG_PRIVATE_STREAM1_BASE)
{
_SlibDebug(_PARSE_, printf("slibParseMpeg2Program() PRIVATE packet\n"));
dstpin = slibGetPin(Info, SLIB_DATA_PRIVATE);
}
else
{
_SlibDebug(_PARSE_,
ScDebugPrintf(Info->dbg,
"slibParseMpeg2Program() unknown packet 0x%02X, %d bytes\n",
packettype, PacketLength));
dstpin = NULL;
}
if (dstpin && slibPinOverflowing(Info, dstpin))
{
slibPinPrepareReposition(Info, dstpin->ID);
_SlibDebug(_WARN_,
ScDebugPrintf(Info->dbg,"Skipped data on Overflowing pin %s: time %d->",
dstpin->name, Info->VideoTimeStamp) );
if (dstpin->ID == SLIB_DATA_VIDEO)
{
dword frames=slibCountCodesOnPin(Info, dstpin,
MPEG_PICTURE_START, 4, Info->OverflowSize/2);
if (Info->FramesPerSec)
Info->VideoTimeStamp+=slibFrameToTime(Info, frames);
}
_SlibDebug(_WARN_, ScDebugPrintf(Info->dbg,"%d\n", Info->VideoTimeStamp) );
slibSkipDataOnPin(Info, dstpin, Info->OverflowSize/2);
slibPinFinishReposition(Info, dstpin->ID);
if (dstpin->ID == SLIB_DATA_VIDEO) /* move to key frame */
SlibSeek((SlibHandle_t *)Info, SLIB_STREAM_MAINVIDEO,
SLIB_SEEK_NEXT_KEY, 0);
}
if (dstpin && !slibPinOverflowing(Info, dstpin))
{
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,"Adding Packet %X, %d bytes\n",
packettype, PacketLength) );
/* add the packet to the destination pin */
while (PacketLength>size)
{
_SlibDebug(_WARN_>1,
ScDebugPrintf(Info->dbg,"PacketLength=%d but buffer is %d bytes\n",
PacketLength, size) );
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
printf("#1 size = %d\n", size));
if (size)
{
SlibAllocSubBuffer(buf, size);
/* ScDumpChar(buf, size, 0); */
slibAddBufferToPin(dstpin, buf, size, ptimestamp);
ptimestamp=SLIB_TIME_NONE;
PacketLength-=size;
}
SlibFreeBuffer(bufstart);
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
if (!buf)
return(fillpin==dstpin ? TRUE : FALSE);
}
if (PacketLength)
{
SlibAllocSubBuffer(buf, PacketLength);
/* ScDumpChar(buf, PacketLength, 0); */
slibAddBufferToPin(dstpin, buf, PacketLength, ptimestamp);
ptimestamp=SLIB_TIME_NONE;
size-=PacketLength;
buf+=PacketLength;
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
ScDebugPrintf(Info->dbg,"#3 size = %d\n", size));
}
/* add remaining buffer data back to input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
if (fillpin==dstpin)
return(TRUE);
if (fillpin==NULL)
return(FALSE);
}
else /* dump the packet */
{
_SlibDebug(_WARN_ && dstpin,
ScDebugPrintf(Info->dbg,"Dumping packet %X (Overflow)\n", packettype) );
_SlibDebug((_WARN_>1 && !dstpin)||packettype==Info->VideoMainStream
||packettype==Info->AudioMainStream,
ScDebugPrintf(Info->dbg,"Dumping packet %X (No pin)\n", packettype) );
while (PacketLength>size)
{
PacketLength-=size;
SlibFreeBuffer(bufstart);
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
_SlibDebug(_VERIFY_ && !buf,
ScDebugPrintf(Info->dbg,"Dumping Packet: no more buffers\n"));
if (buf==NULL)
return(FALSE);
}
buf+=PacketLength;
size-=PacketLength;
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
ScDebugPrintf(Info->dbg,"#5 size = %d\n", size));
/* add remaining buffer data back to input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
}
} /* packet */
else /* put buffer back on the input pin */
{
_SlibDebug(_DEBUG_,
ScDebugPrintf(Info->dbg,"Not a packet %X - putting back buffer\n",
packettype) );
_SlibDebug(_VERIFY_ && Info->Fd>=0 && size>Info->FileBufSize,
ScDebugPrintf(Info->dbg,"#6 size = %d\n", size));
if (size)
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
}
} while (1);
}
return(FALSE);
}
#endif /* MPEG_SUPPORT */
#ifdef MPEG_SUPPORT
/*
** Function: slibParseMpeg2Transport()
** Descript: Parse MPEG II Systems stream and add Video data to Video Pin.
** Returns: TRUE if data was added to fillpin, otherwise FALSE.
*/
SlibBoolean_t slibParseMpeg2Transport(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *fillpin)
{
_SlibDebug(_DEBUG_, ScDebugPrintf(Info->dbg,"slibParseMpeg2Transport()\n"));
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (srcpin)
{
int pid, adapt_field, payload_len, header_len, packettype;
unsigned char *buf, *bufstart=NULL;
unsigned dword size, oldsize;
SlibPin_t *dstpin;
/* SlibTime_t ptimestamp=SLIB_TIME_NONE; */
while ((buf = bufstart = slibSearchBuffersOnPin(Info, srcpin, NULL,
&size, MPEG_TSYNC_CODE, MPEG_TSYNC_CODE_LEN/8, TRUE))!=NULL)
{
_SlibDebug(_VERIFY_ && size<2, ScDebugPrintf(Info->dbg,"Insufficient bytes #2\n") );
pid=(int)(buf[0]&0x1F)<<8 | (int)buf[1]; /* 13 bits for PID */
skipbytes(2);
_SlibDebug(_VERIFY_ && size<1, ScDebugPrintf(Info->dbg,"Insufficient bytes #3\n") );
adapt_field=(buf[0]>>4)&0x03; /* 2 bits for adapt_field */
skipbytes(1);
payload_len=184; /* PES are 184 bytes */
if (adapt_field == 2 || adapt_field == 3)
{
_SlibDebug(_VERIFY_ && size<1, ScDebugPrintf(Info->dbg,"Insufficient bytes #4\n") );
header_len=*buf;
skipbytes(1);
payload_len--;
if (header_len) /* skip adaptation_field */
{
while ((int)size<=header_len)
{
SlibFreeBuffer(bufstart);
header_len-=size;
payload_len-=size;
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
if (!buf) return(FALSE);
}
_SlibDebug(_VERIFY_ && size<(unsigned dword)header_len,
ScDebugPrintf(Info->dbg,"Insufficient bytes\n") );
buf+=header_len;
size-=header_len;
payload_len-=header_len;
}
}
if ((adapt_field == 1 || adapt_field == 3)
&& (Info->VideoPID<0 || Info->VideoPID==pid ||
Info->AudioPID<0 || Info->AudioPID==pid)) /* payload */
{
unsigned dword packet_len;
SlibTime_t ptimestamp = SLIB_TIME_NONE;
/* see if PES packet header */
if (slibParsePESHeader(Info, srcpin, &bufstart, &buf, &size,
&header_len, &packet_len, &packettype, &ptimestamp))
{
payload_len-=header_len;
_SlibDebug(_VERIFY_ && payload_len<0,
ScDebugPrintf(Info->dbg,"payload_len<header_len, header_len=%d\n",
header_len) );
if (pid!=MPEG_PID_NULL)
{
if (Info->VideoPID<0 && packettype>=MPEG_VIDEO_STREAM_START &&
packettype<=MPEG_VIDEO_STREAM_END)
{
_SlibDebug(_VERBOSE_,
ScDebugPrintf(Info->dbg,"Selecting Video PID %d\n", pid) );
Info->VideoPID=pid;
}
else if (Info->AudioPID<0 && packettype>=MPEG_AUDIO_STREAM_START &&
packettype<=MPEG_AUDIO_STREAM_END)
{
_SlibDebug(_VERBOSE_,
ScDebugPrintf(Info->dbg,"Selecting Audio PID %d\n", pid) );
Info->AudioPID=pid;
}
}
}
if (payload_len>0 && (Info->VideoPID==pid || Info->AudioPID==pid))
{
if (Info->VideoPID==pid)
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
else
dstpin = slibGetPin(Info, SLIB_DATA_AUDIO);
if (dstpin && slibPinOverflowing(Info, dstpin))
{
slibPinPrepareReposition(Info, dstpin->ID);
_SlibDebug(_WARN_,
ScDebugPrintf(Info->dbg,"Skipped data on Overflowing pin %s: time %d->",
dstpin->name, Info->VideoTimeStamp) );
if (dstpin->ID == SLIB_DATA_VIDEO)
{
dword frames=slibCountCodesOnPin(Info, dstpin,
MPEG_PICTURE_START, 4, Info->OverflowSize/2);
if (Info->FramesPerSec)
Info->VideoTimeStamp+=slibFrameToTime(Info, frames);
}
_SlibDebug(_WARN_, ScDebugPrintf(Info->dbg,"%d\n", Info->VideoTimeStamp) );
slibSkipDataOnPin(Info, dstpin, Info->OverflowSize/2);
slibPinFinishReposition(Info, dstpin->ID);
if (dstpin->ID == SLIB_DATA_VIDEO) /* move to key frame */
SlibSeek((SlibHandle_t *)Info, SLIB_STREAM_MAINVIDEO,
SLIB_SEEK_NEXT_KEY, 0);
}
if (dstpin && !slibPinOverflowing(Info, dstpin))
{
_SlibDebug(_DEBUG_>1,
ScDebugPrintf(Info->dbg,"Adding Packet: Head=%02X %02X %02X %02X\n",
buf[0], buf[1], buf[2], buf[3]) );
/* add the packet to the destination pin */
while ((int)size<payload_len)
{
_SlibDebug(_DEBUG_,
printf("payload_len=%d but buffer is %d bytes\n",
payload_len, size) );
if (size)
{
SlibAllocSubBuffer(buf, size);
slibAddBufferToPin(dstpin, buf, size, ptimestamp);
ptimestamp=SLIB_TIME_NONE;
payload_len-=size;
}
SlibFreeBuffer(bufstart);
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
if (!buf) return(fillpin==dstpin?TRUE:FALSE);
}
if (payload_len)
{
SlibAllocSubBuffer(buf, payload_len);
slibAddBufferToPin(dstpin, buf, payload_len, ptimestamp);
ptimestamp=SLIB_TIME_NONE;
size-=payload_len;
buf+=payload_len;
}
/* add remaining buffer data back to input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
_SlibDebug(_WARN_ && buf[0]!=MPEG_TSYNC_CODE,
ScDebugPrintf(Info->dbg,
"Next code not Transport Sync: %02X %02X %02X %02X\n",
buf[0], buf[1], buf[2], buf[3]) );
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
payload_len=0;
size=0;
if (fillpin==dstpin)
return(TRUE);
else if (fillpin==NULL)
return(FALSE);
continue;
}
_SlibDebug(_WARN_, ScDebugPrintf(Info->dbg,
"ParseMpeg2Transport() Data not added: payload_len=%d PID=%d\n",
payload_len, pid) );
}
}
if (payload_len>0) /* dump the payload */
{
if (payload_len>(int)size)
{
payload_len-=size;
SlibFreeBuffer(bufstart);
bufstart=slibGetBufferFromPin(Info, srcpin, &size, NULL);
if (!bufstart)
return(FALSE);
buf=bufstart+payload_len;
size-=payload_len;
}
else
{
buf+=payload_len;
size-=payload_len;
}
}
/* add remaining buffer data back to input pin */
if (size)
{
SlibAllocSubBuffer(buf, size);
_SlibDebug(_WARN_ && buf[0]!=MPEG_TSYNC_CODE,
ScDebugPrintf(Info->dbg,
"Next code not Transport Sync: %02X %02X %02X %02X\n",
buf[0], buf[1], buf[2], buf[3]) );
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
} /* while */
}
return(FALSE);
}
#endif /* MPEG_SUPPORT */
#ifdef H261_SUPPORT
/*
** Function: slibParseH261()
** Descript: Parse H.261 Video stream and add Video data to Video Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseH261(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
_SlibDebug(_DEBUG_, printf("slibParseH261()\n"));
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
slibAddBufferToPin(dstpin, buf, size, time);
return(TRUE);
}
}
return(FALSE);
}
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
/*
** Function: slibParseH261()
** Descript: Parse H.261 Video stream and add Video data to Video Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseH263(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
_SlibDebug(_DEBUG_, printf("slibParseH263()\n"));
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
if (Info->Type==SLIB_TYPE_RTP_H263)
{
word rtp_start, sequence_no;
dword sync_src, pay_start;
/* RTP header */
rtp_start=slibGetWordFromPin(Info, srcpin);
sequence_no=slibGetWordFromPin(Info, srcpin);
time=slibGetDWordFromPin(Info, srcpin);
sync_src=slibGetDWordFromPin(Info, srcpin);
/* RTP payload header */
pay_start=slibGetDWordFromPin(Info, srcpin);
if ((pay_start&0x80000000) == 0) /* Mode A */
{
size=Info->PacketSize-16;
buf=SlibAllocBuffer(size);
}
else if ((pay_start&0x40000000) == 0) /* Mode B */
{
dword pay_start2=slibGetDWordFromPin(Info, srcpin);
size=Info->PacketSize-20;
}
else /* Mode C */
{
dword pay_start2=slibGetDWordFromPin(Info, srcpin);
size=Info->PacketSize-20;
}
buf=SlibAllocBuffer(size);
if (buf==NULL) return(FALSE);
size=slibFillBufferFromPin(Info, srcpin, buf, size, NULL);
if (size)
slibAddBufferToPin(dstpin, buf, size, time);
}
else
{
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
slibAddBufferToPin(dstpin, buf, size, time);
return(TRUE);
}
}
}
return(FALSE);
}
#endif /* H263_SUPPORT */
#ifdef HUFF_SUPPORT
/*
** Function: slibParseSlibHuff()
** Descript: Parse SLIB Huffman Video stream and add Video data to Video Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseSlibHuff(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
_SlibDebug(_DEBUG_, printf("slibParseSlibHuff()\n"));
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
_SlibDebug(_VERBOSE_, printf("slibParseSlibHuff(%s)\n", srcpin->name) );
if (!Info->HeaderProcessed)
{
_SlibDebug(_VERBOSE_, printf("slibParseSlibHuff() Header\n") );
slibGetDWordFromPin(Info, srcpin); /* SLIB */
slibGetDWordFromPin(Info, srcpin); /* HUFF */
Info->HeaderProcessed=TRUE;
}
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
slibAddBufferToPin(dstpin, buf, size, time);
return(TRUE);
}
}
return(FALSE);
}
#endif /* HUFF_SUPPORT */
#ifdef G723_SUPPORT
/*
** Function: slibParseG723Audio()
** Descript: Parse G723 Audio stream and add Audio data to Audio Pin.
** Returns: TRUE if data was added to dstpin, otherwise FALSE.
*/
SlibBoolean_t slibParseG723Audio(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *dstpin)
{
_SlibDebug(_DEBUG_, printf("slibParseG723Audio()\n"));
if (!srcpin)
srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED);
if (!dstpin)
dstpin = slibGetPin(Info, SLIB_DATA_AUDIO);
if (srcpin && dstpin)
{
unsigned char *buf;
unsigned dword size;
SlibTime_t time;
if ((buf=slibGetBufferFromPin(Info, srcpin, &size, &time))!=NULL)
{
slibAddBufferToPin(dstpin, buf, size, time);
_SlibDebug(_DEBUG_, printf("slibParseG723Audio() added %d bytes\n",
size));
return(TRUE);
}
}
return(FALSE);
}
#endif /* G723_SUPPORT */
/*
** Function: slibParseAVI()
** Descript: Parse AVI data and add Video data to Video Pin.
** Returns: TRUE if data was added to fillpin, otherwise FALSE.
*/
SlibBoolean_t slibParseAVI(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *fillpin)
{
unsigned char *buf, *bufstart=NULL;
unsigned dword size;
SlibTime_t time=SLIB_TIME_NONE;
SlibPin_t *dstpin;
_SlibDebug(_DEBUG_, printf("slibParseAVI()\n") );
if (!srcpin && (srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED))==NULL)
return(FALSE);
/* only searching for video, for now */
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
do {
buf = bufstart = slibSearchBuffersOnPin(Info, srcpin, NULL, &size,
(('0'<<16) | ('0'<<8) | 'd'), 3, TRUE);
/* AVI_DIBcompressed or AVI_DIBbits */
if (buf==NULL || *buf=='c' || *buf=='b')
break;
/* put buffer back on input to be search again */
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
} while (buf);
if (buf && dstpin)
{
unsigned dword framesize;
buf++; /* skip 'c' or 'b' */
size--;
framesize=((int)buf[3]<<24)|((int)buf[2]<<16)|
((int)buf[1]<<8)|buf[0];
buf+=4;
size-=4;
if (framesize==0)
return(FALSE);
else if (size>=framesize)
{
SlibAllocSubBuffer(buf, framesize);
slibAddBufferToPin(dstpin, buf, framesize, time);
}
else
{
/* frame data crosses over into next buffer */
unsigned char *newbuf=SlibAllocBuffer(framesize);
slibAddBufferToPin(dstpin, newbuf, framesize, time);
_SlibDebug(_DEBUG_, printf("Copying in sections\n") );
do {
_SlibDebug(_DEBUG_,
printf("Copying %d bytes (framesize=%d)\n", size, framesize) );
memcpy(newbuf, buf, size);
newbuf+=size;
framesize-=size;
SlibFreeBuffer(bufstart);
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, &time);
if (buf==NULL)
return(FALSE);
} while (size<framesize);
if (framesize>0)
memcpy(newbuf, buf, framesize);
}
buf+=framesize;
size-=framesize;
if (size>0) /* add remaining data back onto src pin */
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
if (fillpin==dstpin)
return(TRUE);
}
else
_SlibDebug(_DEBUG_, printf("Failed to find JPEG frame\n") );
return(FALSE);
}
/*
** Function: slibParseRaster()
** Descript: Parse Sun Raster data and add Video data to Video Pin.
** Returns: TRUE if data was added to fillpin, otherwise FALSE.
*/
SlibBoolean_t slibParseRaster(SlibInfo_t *Info, SlibPin_t *srcpin,
SlibPin_t *fillpin)
{
unsigned char *buf, *bufstart=NULL;
unsigned dword size;
SlibTime_t time=SLIB_TIME_NONE;
SlibPin_t *dstpin;
_SlibDebug(_DEBUG_, printf("slibParseRaster()\n") );
if (!srcpin && (srcpin = slibLoadPin(Info, SLIB_DATA_COMPRESSED))==NULL)
return(FALSE);
/* only searching for video, for now */
dstpin = slibGetPin(Info, SLIB_DATA_VIDEO);
buf = bufstart = slibSearchBuffersOnPin(Info, srcpin, NULL, &size,
0x59a66a95, 4, TRUE);
if (buf && dstpin)
{
unsigned dword framesize;
buf+=28; /* skip header */
size-=28;
if (Info->CompVideoFormat)
framesize=Info->CompVideoFormat->biWidth*Info->CompVideoFormat->biHeight*3;
else
framesize=Info->Width*Info->Height*3;
if (size>=framesize)
{
SlibAllocSubBuffer(buf, framesize);
slibAddBufferToPin(dstpin, buf, framesize, time);
}
else
{
/* frame data crosses over into next buffer */
unsigned char *newbuf=SlibAllocBuffer(framesize);
slibAddBufferToPin(dstpin, newbuf, framesize, time);
_SlibDebug(_DEBUG_, printf("Copying in sections\n") );
do {
_SlibDebug(_DEBUG_,
printf("Copying %d bytes (framesize=%d)\n", size, framesize) );
memcpy(newbuf, buf, size);
newbuf+=size;
framesize-=size;
SlibFreeBuffer(bufstart);
buf=bufstart=slibGetBufferFromPin(Info, srcpin, &size, &time);
if (buf==NULL)
return(FALSE);
} while (size<framesize);
if (framesize>0)
memcpy(newbuf, buf, framesize);
}
buf+=framesize;
size-=framesize;
if (size>0) /* add remaining data back onto src pin */
{
SlibAllocSubBuffer(buf, size);
slibInsertBufferOnPin(srcpin, buf, size, SLIB_TIME_NONE);
}
SlibFreeBuffer(bufstart);
if (fillpin==dstpin)
return(TRUE);
}
else
_SlibDebug(_DEBUG_, printf("Failed to find Raster frame\n") );
return(FALSE);
}
/*
** Name: slibSetMaxInput
** Desc: Set the maximum number of bytes allowed to be input.
** Use maxbytes=0 for no limit.
*/
void slibSetMaxInput(SlibInfo_t *Info, unsigned dword maxbytes)
{
Info->MaxBytesInput=maxbytes;
if (maxbytes)
{
SlibPin_t *pin = slibGetPin(Info, SLIB_DATA_COMPRESSED);
if (pin)
Info->InputMarker=pin->Offset;
else
Info->MaxBytesInput=0;
}
}
/*
** Name: slibGetPinPosition
** Desc: Get the current byte position counter for a pin.
** Return: -1 if pin doesn't exist
*/
SlibPosition_t slibGetPinPosition(SlibInfo_t *Info, int pinid)
{
SlibPin_t *pin;
_SlibDebug(_DEBUG_>1, printf("slibGetPinPosition(pinid=%d)\n", pinid) );
if ((pin=slibGetPin(Info, pinid))!=NULL)
return(pin->Offset);
else
return((SlibPosition_t)-1);
}
/*
** Name: slibSetPinPosition
** Desc: Set the byte position counter for a pin.
** Called when seeking to a new offset.
** Return: old position
** -1 if pin doesn't exist
*/
SlibPosition_t slibSetPinPosition(SlibInfo_t *Info, int pinid,
SlibPosition_t pos)
{
SlibPin_t *pin;
SlibPosition_t oldpos;
_SlibDebug(_DEBUG_, printf("slibSetPinPosition(pinid=%d, pos=%ld)\n",
pinid, pos) );
if ((pin=slibGetPin(Info, pinid))!=NULL)
{
oldpos=pin->Offset;
pin->Offset=pos;
return(oldpos);
}
else
return((SlibPosition_t)-1);
}
/*
** Name: slibPreLoadPin
** Desc: Load a buffer onto a particular pin (try to get it from the
** appropriate source).
*/
SlibPin_t *slibPreLoadPin(SlibInfo_t *Info, SlibPin_t *pin)
{
unsigned char *buf, *bufstart=NULL;
unsigned dword size;
_SlibDebug(_DEBUG_, printf("slibPreLoadPin(%s)\n",pin->name) );
if (!pin || Info->Mode!=SLIB_MODE_DECOMPRESS)
return(NULL);
switch (pin->ID)
{
case SLIB_DATA_COMPRESSED:
_SlibDebug(_DEBUG_ && Info->MaxBytesInput,
printf("Offset=%d InputMarker=%d\n",
pin->Offset, Info->InputMarker) );
if (Info->MaxBytesInput &&
(pin->Offset-Info->InputMarker)>=Info->MaxBytesInput)
return(NULL);
if (Info->SlibCB) /* data source is an application callback */
{
SlibMessage_t result;
_SlibDebug(_VERBOSE_,
printf("slibPreLoadPin(%s) SlibCB(SLIB_MSG_ENDOFDATA)\n",
pin->name) );
result=(*(Info->SlibCB))((SlibHandle_t)Info,
SLIB_MSG_ENDOFDATA, (SlibCBParam1_t)0,
(SlibCBParam2_t)0, (void *)Info->SlibCBUserData);
switch (result)
{
case SLIB_MSG_CONTINUE:
return(pin);
case SLIB_MSG_ENDOFSTREAM:
case SLIB_MSG_ENDOFDATA:
case SLIB_MSG_BADPOSITION:
Info->IOError=TRUE;
break;
default:
return(NULL);
}
}
else if (Info->Fd>=0) /* data source is a file */
{
if ((buf=SlibAllocBuffer(Info->FileBufSize))==NULL)
return(NULL);
_SlibDebug(_VERBOSE_,
printf("slibPreLoadPin(%s) ScFileRead(%d, %d bytes)\n",
pin->name, Info->Fd, Info->FileBufSize) );
size = ScFileRead(Info->Fd, buf, Info->FileBufSize);
if (size<Info->FileBufSize)
Info->IOError=TRUE;
if (size <= 0)
{
SlibFreeBuffer(buf);
return(NULL);
}
else
{
slibAddBufferToPin(pin, buf, size, SLIB_TIME_NONE);
return(pin);
}
}
break;
case SLIB_DATA_AUDIO:
switch (Info->Type)
{
case SLIB_TYPE_PCM_WAVE:
if (slibParseWave(Info, NULL, pin))
return(pin);
break;
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_AUDIO:
if (slibParseMpegAudio(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_SYSTEMS:
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
if (slibParseMpeg1Systems(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_PROGRAM:
if (slibParseMpeg2Program(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_TRANSPORT:
if (slibParseMpeg2Transport(Info, NULL, pin))
return(pin);
break;
#endif /* MPEG_SUPPORT */
#ifdef AC3_SUPPORT
case SLIB_TYPE_AC3_AUDIO:
if (slibParseAC3Audio(Info, NULL, pin))
return(pin);
break;
#endif /* AC3_SUPPORT */
#ifdef G723_SUPPORT
case SLIB_TYPE_G723:
if (slibParseG723Audio(Info, NULL, pin))
return(pin);
break;
#endif /* G723_SUPPORT */
}
break;
case SLIB_DATA_VIDEO:
switch (Info->Type)
{
case SLIB_TYPE_AVI:
case SLIB_TYPE_YUV_AVI:
if (slibParseAVI(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_RASTER:
if (slibParseRaster(Info, NULL, pin))
return(pin);
break;
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG1_VIDEO:
case SLIB_TYPE_MPEG2_VIDEO:
if (slibParseMpegVideo(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_SYSTEMS:
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
if (slibParseMpeg1Systems(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_PROGRAM:
if (slibParseMpeg2Program(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_TRANSPORT:
if (slibParseMpeg2Transport(Info, NULL, pin))
return(pin);
break;
#endif /* MPEG_SUPPORT */
#ifdef H261_SUPPORT
case SLIB_TYPE_H261:
case SLIB_TYPE_RTP_H261:
if (slibParseH261(Info, NULL, pin))
return(pin);
break;
#endif /* H261_SUPPORT */
#ifdef H263_SUPPORT
case SLIB_TYPE_H263:
case SLIB_TYPE_RTP_H263:
if (slibParseH263(Info, NULL, pin))
return(pin);
break;
#endif /* H263_SUPPORT */
#ifdef JPEG_SUPPORT
case SLIB_TYPE_JPEG_AVI:
case SLIB_TYPE_MJPG_AVI:
if (slibParseAVI(Info, NULL, pin))
return(pin);
break;
#endif /* JPEG_SUPPORT */
#ifdef HUFF_SUPPORT
case SLIB_TYPE_SHUFF:
if (slibParseSlibHuff(Info, NULL, pin))
return(pin);
break;
#endif /* HUFF_SUPPORT */
}
break;
case SLIB_DATA_PRIVATE:
switch (Info->Type)
{
#ifdef MPEG_SUPPORT
case SLIB_TYPE_MPEG_SYSTEMS:
case SLIB_TYPE_MPEG_SYSTEMS_MPEG2:
if (slibParseMpeg1Systems(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_PROGRAM:
if (slibParseMpeg2Program(Info, NULL, pin))
return(pin);
break;
case SLIB_TYPE_MPEG_TRANSPORT:
if (slibParseMpeg2Transport(Info, NULL, pin))
return(pin);
break;
#endif /* MPEG_SUPPORT */
}
break;
}
return(NULL);
}
/*
** Name: slibPutBuffer
** Purpose: Send a buffer to the appropriate output.
*/
SlibStatus_t slibPutBuffer(SlibInfo_t *Info, unsigned char *buffer,
unsigned dword bufsize)
{
_SlibDebug(_VERBOSE_ || _WRITE_,
printf("slibPutBuffer(%d) %d bytes\n", Info->Fd, bufsize) );
if (bufsize==0)
return(SlibErrorNone);
if (Info->IOError || buffer==NULL)
return(SlibErrorWriting);
if (Info->Fd>=0) /* writing to a file */
{
if ((unsigned dword)ScFileWrite(Info->Fd, buffer, bufsize)<bufsize)
Info->IOError=TRUE;
if (SlibValidBuffer(buffer))
SlibFreeBuffer(buffer);
}
else if (Info->SlibCB) /* sending data back to app through a callback */
{
_SlibDebug(_WARN_,
printf("slibPutBuffer(%d) callbacks not yet supported\n") );
if (SlibValidBuffer(buffer))
SlibFreeBuffer(buffer);
}
else /* adding buffer to compress data pin */
{
unsigned char *bufptr=buffer;
SlibPin_t *pin=slibGetPin(Info, SLIB_DATA_COMPRESSED);
if (!SlibValidBuffer(bufptr))
{
/* we need to create a SLIB allocated buffer to copy the
* output to and then add to the compressed data pin
*/
bufptr=SlibAllocBuffer(bufsize);
if (!bufptr)
return(SlibErrorMemory);
memcpy(bufptr, buffer, bufsize);
}
if (slibAddBufferToPin(pin, bufptr, bufsize, SLIB_TIME_NONE)!=SlibErrorNone)
return(SlibErrorWriting);
}
return(SlibErrorNone);
}
/*
** Name: slibGetBufferFromPin
** Purpose: Read the next buffer from the data source.
*/
unsigned char *slibGetBufferFromPin(SlibInfo_t *Info, SlibPin_t *pin,
unsigned dword *size, SlibTime_t *time)
{
unsigned char *address=NULL;
_SlibDebug(_DEBUG_>1, printf("slibGetBufferFromPin(%s)\n", pin->name) );
if (slibLoadPin(Info, pin->ID) != NULL)
{
SlibBuffer_t *tmpbuf = pin->Buffers;
pin->Offset=tmpbuf->offset+tmpbuf->size;
if (tmpbuf->next == NULL)
pin->BuffersTail = NULL;
pin->Buffers = tmpbuf->next;
address=tmpbuf->address;
if (size)
*size = tmpbuf->size;
if (time)
*time = tmpbuf->time;
pin->BufferCount--;
pin->DataSize-=tmpbuf->size;
ScFree(tmpbuf);
}
else
{
_SlibDebug(_WARN_ && pin->DataSize,
printf("slibGetBufferFromPin() No more buffers on pin, yet DataSize=%d\n",
pin->DataSize) );
if (size)
*size = 0;
address=NULL;
}
return(address);
}
/*
** Name: slibGetBufferFromPin
** Purpose: Get a pointer to the next buffer on a pin, but don't
** remove it.
*/
unsigned char *slibPeekBufferOnPin(SlibInfo_t *Info, SlibPin_t *pin,
unsigned dword *psize, SlibTime_t *ptime)
{
_SlibDebug(_DEBUG_, printf("slibPeekBufferOnPin(%s)\n",pin->name) );
if (slibLoadPin(Info, pin->ID) != NULL)
{
if (psize)
*psize = pin->Buffers->size;
if (ptime)
*ptime = pin->Buffers->time;
return(pin->Buffers->address);
}
else
return(NULL);
}
/*
** Name: slibGetNextTimeOnPin
** Purpose: Get the next time on a pin.
*/
SlibTime_t slibGetNextTimeOnPin(SlibInfo_t *Info, SlibPin_t *pin,
unsigned dword maxbytes)
{
unsigned dword bytesread=0, size;
unsigned char *buf;
SlibTime_t timefound=SLIB_TIME_NONE;
_SlibDebug(_DEBUG_,
printf("slibGetNextTimeOnPin(%s)\n",pin?"NULL":pin->name) );
if (!pin)
return(SLIB_TIME_NONE);
buf=slibPeekBufferOnPin(Info, pin, &size, &timefound);
bytesread+=size;
while (buf && timefound==SLIB_TIME_NONE && bytesread<maxbytes)
{
buf=slibPeekNextBufferOnPin(Info, pin, buf, &size, &timefound);
bytesread+=size;
}
return(timefound);
}
/*
** Name: slibPeekNextBufferOnPin
** Purpose: Get a pointer to the next buffer on a pin after the buffer
** specified by "lastbuffer"; don't remove it.
*/
unsigned char *slibPeekNextBufferOnPin(SlibInfo_t *Info, SlibPin_t *pin,
unsigned char *lastbuffer,
unsigned dword *size, SlibTime_t *time)
{
unsigned char *address=NULL;
SlibBuffer_t *tmpbuf;
_SlibDebug(_DEBUG_, printf("slibPeekNextBufferOnPin(lastbuffer=%p,pin=%s)\n",
lastbuffer, pin->name) );
/* check the last loaded buffer first */
tmpbuf=pin->BuffersTail;
if (tmpbuf &&
lastbuffer>=tmpbuf->address && lastbuffer<tmpbuf->address+tmpbuf->size)
{
/* load a new buffer onto the pin */
slibPreLoadPin(Info, pin);
if (tmpbuf != pin->BuffersTail)
{
address=pin->BuffersTail->address;
if (size)
*size=pin->BuffersTail->size;
if (time)
*time=pin->BuffersTail->time;
return(address);
}
_SlibDebug(_WARN_, printf("slibPeekNextBufferOnPin() End of data\n") );
return(NULL);
}
/* search through all the buffers on the pin */
if (pin->Buffers==NULL)
slibPreLoadPin(Info, pin);
tmpbuf = pin->Buffers;
while (tmpbuf)
{
if (lastbuffer>=tmpbuf->address && lastbuffer<tmpbuf->address+tmpbuf->size)
{
tmpbuf=tmpbuf->next;
if (tmpbuf)
{
_SlibDebug(_WARN_ &&
lastbuffer>=tmpbuf->address && lastbuffer<tmpbuf->address+tmpbuf->size,
printf("slibPeekNextBufferOnPin() same addresses\n") );
if (size)
*size=tmpbuf->size;
if (time)
*time=tmpbuf->time;
return(tmpbuf->address);
}
else
{
_SlibDebug(_WARN_, printf("slibPeekNextBufferOnPin() End of bufs\n") );
return(NULL);
}
}
tmpbuf=tmpbuf->next;
}
_SlibDebug(_WARN_, printf("slibPeekNextBufferOnPin() address no found\n") );
return(NULL);
}