/* * @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 #endif #include #ifdef _SHM_ #include /* 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 *)addressaddress+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 *)addressaddress+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 *)addressaddress+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 *)addressaddress+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 *)addressaddress+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 || totallen1, 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) { 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, 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; iVideoStreams; 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; iAudioStreams; 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->DataSizeDataSizeIOError && ((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; lenBytesProcessed+=size; Info->BytesSincePack+=size; Info->PacketCount++; } } else if (!flush && (atime>0 || vtime>0) && (atime+300SystemTimeStamp && vtime+300SystemTimeStamp)) { /* we're not able to keep the bitrate low enough */ /* increase the Mux rate */ dword oldrate=Info->TotalBitRate; SlibTime_t mintime=(vtime0 && vtime>0) mintime=(vtimeTotalBitRate=(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->DataSizeDataSizeDataSize, 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) || ptimestampVideoPTimeBase) { Info->VideoPTimeBase=ptimestamp; _SlibDebug(_PARSE_ || _TIMECODE_, printf("slibParseMpeg1Systems() VideoPTimeBase=%ld\n", Info->VideoPTimeBase)); } } else if (packettype==Info->AudioMainStream) { if (!SlibTimeIsValid(Info->AudioPTimeBase) || ptimestampAudioPTimeBase) { 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) || ptimestampVideoPTimeBase)) { 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) || ptimestampAudioPTimeBase)) { 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_lenVideoPID<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)sizedbg, "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 (size0) 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 (size0) 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 (sizeFileBufSize) 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)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 && bytesreadname) ); /* check the last loaded buffer first */ tmpbuf=pin->BuffersTail; if (tmpbuf && lastbuffer>=tmpbuf->address && lastbufferaddress+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 && lastbufferaddress+tmpbuf->size) { tmpbuf=tmpbuf->next; if (tmpbuf) { _SlibDebug(_WARN_ && lastbuffer>=tmpbuf->address && lastbufferaddress+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); }