2771 lines
87 KiB
C
2771 lines
87 KiB
C
/*
|
|
* @DEC_COPYRIGHT@
|
|
*/
|
|
/*
|
|
* HISTORY
|
|
* $Log: sc_buf.c,v $
|
|
* Revision 1.1.8.4 1996/12/12 20:54:41 Hans_Graves
|
|
* Fixed reading of last odd bits.
|
|
* [1996/12/12 20:54:05 Hans_Graves]
|
|
*
|
|
* Revision 1.1.8.3 1996/11/13 16:10:46 Hans_Graves
|
|
* Tom's changes to ScBSGetBitsW() and ScBSSeekAlignStopBeforeW().
|
|
* [1996/11/13 15:57:34 Hans_Graves]
|
|
*
|
|
* Revision 1.1.8.2 1996/11/08 21:50:32 Hans_Graves
|
|
* Added ScBSGetBitsW(), ScBSSkipBitsW() and sc_BSLoadDataWordW() for AC3.
|
|
* [1996/11/08 21:25:52 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.4 1996/04/17 16:38:33 Hans_Graves
|
|
* Correct some type casting to support 64-bit buffers under NT
|
|
* [1996/04/17 16:36:08 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.3 1996/04/15 21:08:37 Hans_Graves
|
|
* Declare mask and imask as ScBitString_t
|
|
* [1996/04/15 21:06:32 Hans_Graves]
|
|
*
|
|
* Revision 1.1.6.2 1996/04/01 16:23:05 Hans_Graves
|
|
* Replace File I/O with ScFile calls
|
|
* [1996/04/01 16:22:27 Hans_Graves]
|
|
*
|
|
* Revision 1.1.4.7 1996/02/19 14:29:25 Bjorn_Engberg
|
|
* Enable FILTER_SUPPORT for NT, so Mview can play audio.
|
|
* This is only until we port the MPEG Systems code to NT.
|
|
* [1996/02/19 14:29:07 Bjorn_Engberg]
|
|
*
|
|
* Revision 1.1.4.6 1996/02/01 17:15:48 Hans_Graves
|
|
* Added FILTER_SUPPORT ifdef; disabled it
|
|
* [1996/02/01 17:13:29 Hans_Graves]
|
|
*
|
|
* Revision 1.1.4.5 1996/01/08 16:41:12 Hans_Graves
|
|
* Remove NT compiler warnings, and minor fixes for NT.
|
|
* [1996/01/08 14:14:10 Hans_Graves]
|
|
*
|
|
* Revision 1.1.4.3 1995/11/06 18:47:37 Hans_Graves
|
|
* Added support for small buffer: 1-7 bytes
|
|
* [1995/11/06 18:46:49 Hans_Graves]
|
|
*
|
|
* Revision 1.1.4.2 1995/09/13 14:51:34 Hans_Graves
|
|
* Added ScBufQueueGetHeadExt() and ScBufQueueAddExt().
|
|
* [1995/09/13 14:47:11 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.18 1995/08/30 19:37:49 Hans_Graves
|
|
* Fixed compiler warning about #else and #elif.
|
|
* [1995/08/30 19:36:15 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.17 1995/08/29 22:17:04 Hans_Graves
|
|
* Disabled debugging statements.
|
|
* [1995/08/29 22:11:38 Hans_Graves]
|
|
*
|
|
* PTT 00938 - MPEG Seg Faulting fixes, Repositioning problem.
|
|
* [1995/08/29 22:04:06 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.16 1995/08/14 19:40:24 Hans_Graves
|
|
* Added Flush routines. Some optimization.
|
|
* [1995/08/14 18:40:33 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.15 1995/08/02 15:26:58 Hans_Graves
|
|
* Fixed writing bitstreams directly to files.
|
|
* [1995/08/02 14:11:00 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.14 1995/07/28 20:58:37 Hans_Graves
|
|
* Initialized all variables in callback messages.
|
|
* [1995/07/28 20:52:04 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.13 1995/07/28 17:36:04 Hans_Graves
|
|
* Fixed END_BUFFER callback from GetNextBuffer()
|
|
* [1995/07/28 17:31:30 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.12 1995/07/27 18:28:52 Hans_Graves
|
|
* Fixed buffer queues in PutData and StoreDataWord.
|
|
* [1995/07/27 18:23:30 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.11 1995/07/27 12:20:35 Hans_Graves
|
|
* Renamed SvErrorClientAbort to SvErrorClientEnd
|
|
* [1995/07/27 12:19:12 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.10 1995/07/21 17:40:59 Hans_Graves
|
|
* Renamed Callback related stuff. Added DataType.
|
|
* [1995/07/21 17:26:48 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.9 1995/07/17 22:01:27 Hans_Graves
|
|
* Added Callback call in PutData().
|
|
* [1995/07/17 21:50:49 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.8 1995/07/12 19:48:21 Hans_Graves
|
|
* Added Queue debugging statements.
|
|
* [1995/07/12 19:30:37 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.7 1995/07/07 20:11:23 Hans_Graves
|
|
* Fixed ScBSGetBit() so it returns the bit.
|
|
* [1995/07/07 20:07:27 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.6 1995/06/27 13:54:17 Hans_Graves
|
|
* Added ScBSCreateFromNet() and STREAM_USE_NET cases.
|
|
* [1995/06/27 13:27:38 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.5 1995/06/21 18:37:56 Hans_Graves
|
|
* Added ScBSPutBytes()
|
|
* [1995/06/21 18:37:08 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.4 1995/06/15 21:17:55 Hans_Graves
|
|
* Changed return type for GetBits() and PeekBits() to ScBitString_t. Added some debug statements.
|
|
* [1995/06/15 20:40:54 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.3 1995/06/09 18:33:28 Hans_Graves
|
|
* Fixed up some problems with Bitstream reads from Buffer Queues
|
|
* [1995/06/09 16:27:50 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.2 1995/05/31 18:07:25 Hans_Graves
|
|
* Inclusion in new SLIB location.
|
|
* [1995/05/31 16:05:37 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.3 1995/04/17 18:41:05 Hans_Graves
|
|
* Added ScBSPutBits, BSStoreWord, and BSPutData functions
|
|
* [1995/04/17 18:40:44 Hans_Graves]
|
|
*
|
|
* Revision 1.1.2.2 1995/04/07 18:22:55 Hans_Graves
|
|
* Bitstream and Buffer Queue functions pulled from Sv sources.
|
|
* Added functionality and cleaned up API.
|
|
* [1995/04/07 18:21:58 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. **
|
|
******************************************************************************/
|
|
/*
|
|
** Bitstream and queue routines
|
|
**
|
|
** Note: For reading, "BS->shift" refers to the number of bits stored across
|
|
** BS->OutBuff and BS->InBuff
|
|
*/
|
|
/*
|
|
#define _SLIBDEBUG_
|
|
*/
|
|
|
|
#include "SC.h"
|
|
#include "SC_err.h"
|
|
#include <string.h>
|
|
#ifdef WIN32
|
|
#include <io.h>
|
|
#include <windows.h>
|
|
#include <assert.h>
|
|
#endif
|
|
|
|
#ifdef _SLIBDEBUG_
|
|
#include <stdio.h>
|
|
#define _DEBUG_ 0 /* detailed debuging statements */
|
|
#define _VERBOSE_ 0 /* show progress */
|
|
#define _VERIFY_ 1 /* verify correct operation */
|
|
#define _WARN_ 1 /* warnings about strange behavior */
|
|
#define _QUEUE_ 0 /* show queue progress */
|
|
#define _DUMP_ 0 /* dump out buffer data in hex */
|
|
|
|
int _debug_getbits=TRUE;
|
|
long _debug_start=0, _debug_stop=0;
|
|
#endif
|
|
|
|
#define USE_FAST_SEEK 0 /* fast seeking for words in the bistream */
|
|
|
|
#define FILTER_SUPPORT 0 /* data filtering callback support */
|
|
|
|
#ifdef __VMS
|
|
#define USE_MASK_TABLES
|
|
#else
|
|
#define USE_MASK_TABLES
|
|
#endif
|
|
|
|
#ifdef USE_MASK_TABLES
|
|
/* to mask the n least significant bits of an integer */
|
|
#if SC_BITBUFFSZ == 64
|
|
const static ScBitString_t mask[65] =
|
|
{
|
|
(ScBitString_t)0x0000000000000000,(ScBitString_t)0x0000000000000001,
|
|
(ScBitString_t)0x0000000000000003,(ScBitString_t)0x0000000000000007,
|
|
(ScBitString_t)0x000000000000000f,(ScBitString_t)0x000000000000001f,
|
|
(ScBitString_t)0x000000000000003f,(ScBitString_t)0x000000000000007f,
|
|
(ScBitString_t)0x00000000000000ff,(ScBitString_t)0x00000000000001ff,
|
|
(ScBitString_t)0x00000000000003ff,(ScBitString_t)0x00000000000007ff,
|
|
(ScBitString_t)0x0000000000000fff,(ScBitString_t)0x0000000000001fff,
|
|
(ScBitString_t)0x0000000000003fff,(ScBitString_t)0x0000000000007fff,
|
|
(ScBitString_t)0x000000000000ffff,(ScBitString_t)0x000000000001ffff,
|
|
(ScBitString_t)0x000000000003ffff,(ScBitString_t)0x000000000007ffff,
|
|
(ScBitString_t)0x00000000000fffff,(ScBitString_t)0x00000000001fffff,
|
|
(ScBitString_t)0x00000000003fffff,(ScBitString_t)0x00000000007fffff,
|
|
(ScBitString_t)0x0000000000ffffff,(ScBitString_t)0x0000000001ffffff,
|
|
(ScBitString_t)0x0000000003ffffff,(ScBitString_t)0x0000000007ffffff,
|
|
(ScBitString_t)0x000000000fffffff,(ScBitString_t)0x000000001fffffff,
|
|
(ScBitString_t)0x000000003fffffff,(ScBitString_t)0x000000007fffffff,
|
|
(ScBitString_t)0x00000000ffffffff,(ScBitString_t)0x00000001ffffffff,
|
|
(ScBitString_t)0x00000003ffffffff,(ScBitString_t)0x00000007ffffffff,
|
|
(ScBitString_t)0x0000000fffffffff,(ScBitString_t)0x0000001fffffffff,
|
|
(ScBitString_t)0x0000003fffffffff,(ScBitString_t)0x0000007fffffffff,
|
|
(ScBitString_t)0x000000ffffffffff,(ScBitString_t)0x000001ffffffffff,
|
|
(ScBitString_t)0x000003ffffffffff,(ScBitString_t)0x000007ffffffffff,
|
|
(ScBitString_t)0x00000fffffffffff,(ScBitString_t)0x00001fffffffffff,
|
|
(ScBitString_t)0x00003fffffffffff,(ScBitString_t)0x00007fffffffffff,
|
|
(ScBitString_t)0x0000ffffffffffff,(ScBitString_t)0x0001ffffffffffff,
|
|
(ScBitString_t)0x0003ffffffffffff,(ScBitString_t)0x0007ffffffffffff,
|
|
(ScBitString_t)0x000fffffffffffff,(ScBitString_t)0x001fffffffffffff,
|
|
(ScBitString_t)0x003fffffffffffff,(ScBitString_t)0x007fffffffffffff,
|
|
(ScBitString_t)0x00ffffffffffffff,(ScBitString_t)0x01ffffffffffffff,
|
|
(ScBitString_t)0x03ffffffffffffff,(ScBitString_t)0x07ffffffffffffff,
|
|
(ScBitString_t)0x0fffffffffffffff,(ScBitString_t)0x1fffffffffffffff,
|
|
(ScBitString_t)0x3fffffffffffffff,(ScBitString_t)0x7fffffffffffffff,
|
|
(ScBitString_t)0xffffffffffffffff
|
|
};
|
|
/* inverse mask */
|
|
const static ScBitString_t imask[65] =
|
|
{
|
|
(ScBitString_t)0xffffffffffffffff,(ScBitString_t)0xfffffffffffffffe,
|
|
(ScBitString_t)0xfffffffffffffffc,(ScBitString_t)0xfffffffffffffff8,
|
|
(ScBitString_t)0xfffffffffffffff0,(ScBitString_t)0xffffffffffffffe0,
|
|
(ScBitString_t)0xffffffffffffffc0,(ScBitString_t)0xffffffffffffff80,
|
|
(ScBitString_t)0xffffffffffffff00,(ScBitString_t)0xfffffffffffffe00,
|
|
(ScBitString_t)0xfffffffffffffc00,(ScBitString_t)0xfffffffffffff800,
|
|
(ScBitString_t)0xfffffffffffff000,(ScBitString_t)0xffffffffffffe000,
|
|
(ScBitString_t)0xffffffffffffc000,(ScBitString_t)0xffffffffffff8000,
|
|
(ScBitString_t)0xffffffffffff0000,(ScBitString_t)0xfffffffffffe0000,
|
|
(ScBitString_t)0xfffffffffffc0000,(ScBitString_t)0xfffffffffff80000,
|
|
(ScBitString_t)0xfffffffffff00000,(ScBitString_t)0xffffffffffe00000,
|
|
(ScBitString_t)0xffffffffffc00000,(ScBitString_t)0xffffffffff800000,
|
|
(ScBitString_t)0xffffffffff000000,(ScBitString_t)0xfffffffffe000000,
|
|
(ScBitString_t)0xfffffffffc000000,(ScBitString_t)0xfffffffff8000000,
|
|
(ScBitString_t)0xfffffffff0000000,(ScBitString_t)0xffffffffe0000000,
|
|
(ScBitString_t)0xffffffffc0000000,(ScBitString_t)0xffffffff80000000,
|
|
(ScBitString_t)0xffffffff00000000,(ScBitString_t)0xfffffffe00000000,
|
|
(ScBitString_t)0xfffffffc00000000,(ScBitString_t)0xfffffff800000000,
|
|
(ScBitString_t)0xfffffff000000000,(ScBitString_t)0xffffffe000000000,
|
|
(ScBitString_t)0xffffffc000000000,(ScBitString_t)0xffffff8000000000,
|
|
(ScBitString_t)0xffffff0000000000,(ScBitString_t)0xfffffe0000000000,
|
|
(ScBitString_t)0xfffffc0000000000,(ScBitString_t)0xfffff80000000000,
|
|
(ScBitString_t)0xfffff00000000000,(ScBitString_t)0xffffe00000000000,
|
|
(ScBitString_t)0xffffc00000000000,(ScBitString_t)0xffff800000000000,
|
|
(ScBitString_t)0xffff000000000000,(ScBitString_t)0xfffe000000000000,
|
|
(ScBitString_t)0xfffc000000000000,(ScBitString_t)0xfff8000000000000,
|
|
(ScBitString_t)0xfff0000000000000,(ScBitString_t)0xffe0000000000000,
|
|
(ScBitString_t)0xffc0000000000000,(ScBitString_t)0xff80000000000000,
|
|
(ScBitString_t)0xff00000000000000,(ScBitString_t)0xfe00000000000000,
|
|
(ScBitString_t)0xfc00000000000000,(ScBitString_t)0xf800000000000000,
|
|
(ScBitString_t)0xf000000000000000,(ScBitString_t)0xe000000000000000,
|
|
(ScBitString_t)0xc000000000000000,(ScBitString_t)0x8000000000000000,
|
|
(ScBitString_t)0x0000000000000000
|
|
};
|
|
#else
|
|
const static ScBitString_t mask[33] =
|
|
{
|
|
0x00000000,0x00000001,0x00000003,0x00000007,
|
|
0x0000000f,0x0000001f,0x0000003f,0x0000007f,
|
|
0x000000ff,0x000001ff,0x000003ff,0x000007ff,
|
|
0x00000fff,0x00001fff,0x00003fff,0x00007fff,
|
|
0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
|
|
0x000fffff,0x001fffff,0x003fffff,0x007fffff,
|
|
0x00ffffff,0x01ffffff,0x03ffffff,0x07ffffff,
|
|
0x0fffffff,0x1fffffff,0x3fffffff,0x7fffffff,
|
|
0xffffffff
|
|
};
|
|
/* inverse mask */
|
|
const static ScBitString_t imask[33] =
|
|
{
|
|
0xffffffff,0xfffffffe,0xfffffffc,0xfffffff8,
|
|
0xfffffff0,0xffffffe0,0xffffffc0,0xffffff80,
|
|
0xffffff00,0xfffffe00,0xfffffc00,0xfffff800,
|
|
0xfffff000,0xffffe000,0xffffc000,0xffff8000,
|
|
0xffff0000,0xfffe0000,0xfffc0000,0xfff80000,
|
|
0xfff00000,0xffe00000,0xffc00000,0xff800000,
|
|
0xff000000,0xfe000000,0xfc000000,0xf8000000,
|
|
0xf0000000,0xe0000000,0xc0000000,0x80000000,
|
|
0x00000000
|
|
};
|
|
#endif
|
|
#endif USE_MASK_TABLES
|
|
/*********************** Bitstream/Buffer Management *************************/
|
|
/*
|
|
** sc_GetNextBuffer()
|
|
** Release current buffer and return info about buffer at head of queue
|
|
** Callbacks are made to 1) release old buffer and 2) ask for more buffers
|
|
*/
|
|
static u_char *sc_GetNextBuffer(ScBitstream_t *BS, int *BufSize)
|
|
{
|
|
u_char *Data;
|
|
int Size;
|
|
ScCallbackInfo_t CB;
|
|
ScQueue_t *Q=BS->Q;
|
|
|
|
_SlibDebug(_VERBOSE_, printf("sc_GetNextBuffer(Q=%p)\n", Q) );
|
|
if (ScBufQueueGetNum(Q))
|
|
{
|
|
/*
|
|
** Get pointer to current buffer so we can release it with a callback
|
|
*/
|
|
ScBufQueueGetHead(Q, &Data, &Size);
|
|
|
|
/*
|
|
** Remove current buffer from head of queue, replacing it with next in line
|
|
*/
|
|
ScBufQueueRemove(Q);
|
|
|
|
/*
|
|
** Make callback to client to tell that old buffer can be reused.
|
|
** Client may tell us to abort processing. If so, return 0 for BufSize.
|
|
*/
|
|
if (BS->Callback && Data) {
|
|
CB.Message = CB_RELEASE_BUFFER;
|
|
CB.Data = Data;
|
|
CB.DataSize = Size;
|
|
CB.DataUsed = Size;
|
|
CB.DataType = BS->DataType;
|
|
CB.UserData = BS->UserData;
|
|
CB.Action = CB_ACTION_CONTINUE;
|
|
(*(BS->Callback))(BS->Sch, &CB, NULL);
|
|
_SlibDebug(_DEBUG_,
|
|
printf("Callback: RELEASE_BUFFER. Addr = 0x%x, Client response = %d\n",
|
|
CB.Data, CB.Action) );
|
|
if (CB.Action == CB_ACTION_END)
|
|
{
|
|
*BufSize = 0;
|
|
return(NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
** If there's no more buffers in queue, make a callback telling client.
|
|
** Hopefully, client will call ScAddBuffer to add one or more buffers.
|
|
** If not, or if client tells us to abort, return 0 for BufSize.
|
|
*/
|
|
if (!ScBufQueueGetNum(Q)) {
|
|
if (BS->Callback) {
|
|
CB.Message = CB_END_BUFFERS;
|
|
CB.Data = NULL;
|
|
CB.DataSize = 0;
|
|
CB.DataUsed = 0;
|
|
CB.DataType = BS->DataType;
|
|
CB.UserData = BS->UserData;
|
|
CB.Action = CB_ACTION_CONTINUE;
|
|
(*(BS->Callback))(BS->Sch, &CB, NULL);
|
|
if (CB.Action == CB_ACTION_END)
|
|
{
|
|
_SlibDebug(_DEBUG_,
|
|
printf("sc_GetNextBuffer() CB.Action = CB_ACTION_END\n") );
|
|
*BufSize = 0;
|
|
return(NULL);
|
|
}
|
|
else
|
|
_SlibDebug(_VERBOSE_, printf("sc_GetNextBuffer() CB.Action = %d\n",
|
|
CB.Action) );
|
|
}
|
|
if (!ScBufQueueGetNum(Q)) {
|
|
_SlibDebug(_DEBUG_, printf("sc_GetNextBuffer() no more buffers\n") );
|
|
*BufSize = 0;
|
|
return(NULL);
|
|
}
|
|
}
|
|
|
|
/*
|
|
** Get & return pointer & size of new current buffer
|
|
*/
|
|
ScBufQueueGetHead(Q, &Data, BufSize);
|
|
_SlibDebug(_VERBOSE_, printf("New buffer: Addr = 0x%p, size = %d\n",
|
|
Data, *BufSize) );
|
|
return(Data);
|
|
}
|
|
|
|
/*************************** Bitstream Management ***************************/
|
|
/* Name: ScBSSetFilter
|
|
** Purpose: Set the callback used to filter out data from the Bitstream
|
|
*/
|
|
ScStatus_t ScBSSetFilter(ScBitstream_t *BS,
|
|
int (*Callback)(ScBitstream_t *))
|
|
{
|
|
if (!BS)
|
|
return(ScErrorBadPointer);
|
|
BS->FilterCallback=Callback;
|
|
BS->FilterBit=BS->CurrentBit;
|
|
BS->InFilterCallback=FALSE;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
/* Name: ScBSCreate
|
|
** Purpose: Open a Bitstream (no data source)
|
|
*/
|
|
ScStatus_t ScBSCreate(ScBitstream_t **BS)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("ScBSCreate()\n"));
|
|
|
|
if ((*BS = (ScBitstream_t *)ScAlloc(sizeof(ScBitstream_t))) == NULL)
|
|
return(ScErrorMemory);
|
|
|
|
(*BS)->DataSource = STREAM_USE_NULL;
|
|
(*BS)->Mode='r';
|
|
(*BS)->Q=NULL;
|
|
(*BS)->Callback=NULL;
|
|
(*BS)->FilterCallback=NULL;
|
|
(*BS)->FilterBit=0;
|
|
(*BS)->InFilterCallback=FALSE;
|
|
(*BS)->Sch=0;
|
|
(*BS)->DataType=0;
|
|
(*BS)->UserData=NULL;
|
|
(*BS)->FileFd=0;
|
|
(*BS)->RdBuf=NULL;
|
|
(*BS)->RdBufSize=0;
|
|
(*BS)->RdBufAllocated=FALSE;
|
|
(*BS)->shift=0;
|
|
(*BS)->CurrentBit=0;
|
|
(*BS)->buff=0;
|
|
(*BS)->buffstart=0;
|
|
(*BS)->buffp=0;
|
|
(*BS)->bufftop=0;
|
|
(*BS)->OutBuff = 0;
|
|
(*BS)->InBuff = 0;
|
|
(*BS)->Flush = FALSE;
|
|
(*BS)->EOI = FALSE;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
/* Name: ScBSCreateFromBuffer
|
|
** Purpose: Open a Bitstream using a single Buffer as a data source
|
|
*/
|
|
ScStatus_t ScBSCreateFromBuffer(ScBitstream_t **BS, u_char *Buffer,
|
|
unsigned int BufSize)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("ScBSCreateFromBuffer()\n") );
|
|
if (!Buffer)
|
|
return(ScErrorBadPointer);
|
|
if (BufSize <= 0)
|
|
return(ScErrorBadArgument);
|
|
if (ScBSCreate(BS) != ScErrorNone)
|
|
return (ScErrorMemory);
|
|
|
|
(*BS)->DataSource = STREAM_USE_BUFFER;
|
|
(*BS)->RdBuf=Buffer;
|
|
(*BS)->RdBufSize=BufSize;
|
|
(*BS)->RdBufAllocated=FALSE;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
/* Name: ScBSCreateFromBufferQueue
|
|
** Purpose: Open a Bitstream using a Buffer Queue as a data source
|
|
*/
|
|
ScStatus_t ScBSCreateFromBufferQueue(ScBitstream_t **BS, ScHandle_t Sch,
|
|
int DataType, ScQueue_t *Q,
|
|
int (*Callback)(ScHandle_t,ScCallbackInfo_t *, void *),
|
|
void *UserData)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("ScBSCreateFromBufferQueue()\n") );
|
|
if (!Q)
|
|
return(ScErrorNullStruct);
|
|
if (!Callback)
|
|
return(ScErrorBadPointer);
|
|
if (ScBSCreate(BS) != ScErrorNone)
|
|
return (ScErrorMemory);
|
|
|
|
(*BS)->DataSource = STREAM_USE_QUEUE;
|
|
(*BS)->Q=Q;
|
|
(*BS)->Callback=Callback;
|
|
(*BS)->Sch=Sch;
|
|
(*BS)->DataType=DataType;
|
|
(*BS)->UserData=UserData;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
|
|
/* Name: ScBSCreateFromFile
|
|
** Purpose: Open a Bitstream using a file as a data source
|
|
*/
|
|
ScStatus_t ScBSCreateFromFile(ScBitstream_t **BS, int FileFd,
|
|
u_char *Buffer, int BufSize)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("ScBSCreateFromFile()\n") );
|
|
|
|
if (BufSize < SC_BITBUFFSZ)
|
|
return(ScErrorBadArgument);
|
|
if (FileFd < 0)
|
|
return(ScErrorBadArgument);
|
|
|
|
if (ScBSCreate(BS) != ScErrorNone)
|
|
return (ScErrorMemory);
|
|
|
|
(*BS)->DataSource = STREAM_USE_FILE;
|
|
(*BS)->FileFd=FileFd;
|
|
if (Buffer==NULL) /* if no buffer provided, alloc one */
|
|
{
|
|
if (((*BS)->RdBuf=(u_char *)ScAlloc(BufSize))==NULL)
|
|
{
|
|
ScFree(*BS);
|
|
*BS=NULL;
|
|
return (ScErrorMemory);
|
|
}
|
|
(*BS)->RdBufAllocated=TRUE;
|
|
}
|
|
else
|
|
{
|
|
(*BS)->RdBufAllocated=FALSE;
|
|
(*BS)->RdBuf=Buffer;
|
|
}
|
|
(*BS)->RdBufSize=BufSize;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
/* Name: ScBSCreateFromNet
|
|
** Purpose: Open a Bitstream using a network socket as a data source
|
|
*/
|
|
ScStatus_t ScBSCreateFromNet(ScBitstream_t **BS, int SocketFd,
|
|
u_char *Buffer, int BufSize)
|
|
{
|
|
ScStatus_t stat;
|
|
_SlibDebug(_VERBOSE_, printf("ScBSCreateFromNet(SocketFd=%d)\n", SocketFd) );
|
|
stat=ScBSCreateFromFile(BS, SocketFd, Buffer, BufSize);
|
|
if (stat!=NoErrors)
|
|
return(stat);
|
|
(*BS)->DataSource = STREAM_USE_NET;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
/* Name: ScBSCreateFromDevice
|
|
** Purpose: Open a Bitstream using a device (i.e. WAVE_MAPPER)
|
|
*/
|
|
ScStatus_t ScBSCreateFromDevice(ScBitstream_t **BS, int device)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("ScBSCreateFromBuffer()\n") );
|
|
if (ScBSCreate(BS) != ScErrorNone)
|
|
return (ScErrorMemory);
|
|
|
|
(*BS)->DataSource = STREAM_USE_DEVICE;
|
|
(*BS)->Device=device;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
|
|
/*
|
|
** Name: ScBSSeekToPosition()
|
|
** Purpose: Position the bitstream to a specific byte offset.
|
|
*/
|
|
ScStatus_t ScBSSeekToPosition(ScBitstream_t *BS, unsigned long pos)
|
|
{
|
|
#ifndef SEEK_SET
|
|
#define SEEK_SET 0
|
|
#endif
|
|
ScCallbackInfo_t CB;
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("ScBSSeekToPosition(pos=%d 0x%X) from %d (0x%X)\n",
|
|
pos, pos, ScBSBytePosition(BS),ScBSBytePosition(BS)) );
|
|
BS->shift=0;
|
|
BS->OutBuff = 0;
|
|
BS->InBuff = 0;
|
|
switch (BS->DataSource)
|
|
{
|
|
case STREAM_USE_BUFFER:
|
|
if (pos==0)
|
|
{
|
|
if (BS->Mode=='w')
|
|
{
|
|
BS->buff = BS->RdBuf;
|
|
BS->bufftop = BS->RdBufSize;
|
|
}
|
|
else
|
|
{
|
|
BS->buff = 0;
|
|
BS->bufftop = 0;
|
|
}
|
|
BS->buffp=0;
|
|
BS->EOI = FALSE;
|
|
}
|
|
else if (pos>=BS->buffstart && pos<(BS->buffstart+BS->bufftop))
|
|
{
|
|
BS->buffp=pos-BS->buffstart;
|
|
BS->EOI = FALSE;
|
|
}
|
|
else
|
|
BS->EOI = TRUE;
|
|
break;
|
|
case STREAM_USE_QUEUE:
|
|
if (pos>=BS->buffstart && pos<(BS->buffstart+BS->bufftop) && pos>0)
|
|
{
|
|
BS->buffp=pos-BS->buffstart;
|
|
BS->EOI = FALSE;
|
|
}
|
|
else /* use callback to reset buffer position */
|
|
{
|
|
int datasize;
|
|
/* Release the current buffer */
|
|
if (BS->Callback && BS->buff)
|
|
{
|
|
CB.Message = CB_RELEASE_BUFFER;
|
|
CB.Data = BS->buff;
|
|
CB.DataSize = BS->bufftop;
|
|
CB.DataUsed = BS->buffp;
|
|
CB.DataType = BS->DataType;
|
|
CB.UserData = BS->UserData;
|
|
CB.Action = CB_ACTION_CONTINUE;
|
|
(*(BS->Callback))(BS->Sch, &CB, NULL);
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("Callback: RELEASE_BUFFER. Addr = 0x%x, Client response = %d\n",
|
|
CB.Data, CB.Action) );
|
|
}
|
|
/* Remove all buffers from queue */
|
|
while (ScBufQueueGetNum(BS->Q))
|
|
{
|
|
ScBufQueueGetHead(BS->Q, &CB.Data, &datasize);
|
|
ScBufQueueRemove(BS->Q);
|
|
if (BS->Callback && CB.Data)
|
|
{
|
|
CB.Message = CB_RELEASE_BUFFER;
|
|
CB.DataSize = datasize;
|
|
CB.DataUsed = 0;
|
|
CB.DataType = BS->DataType;
|
|
CB.UserData = BS->UserData;
|
|
CB.Action = CB_ACTION_CONTINUE;
|
|
(*(BS->Callback))(BS->Sch, &CB, NULL);
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("Callback: RELEASE_BUFFER. Addr = 0x%x, Client response = %d\n",
|
|
CB.Data, CB.Action) );
|
|
}
|
|
}
|
|
BS->buffp=0;
|
|
BS->buff=NULL;
|
|
if (CB.Action == CB_ACTION_END)
|
|
{
|
|
BS->EOI = TRUE;
|
|
return(ScErrorClientEnd);
|
|
}
|
|
else
|
|
{
|
|
BS->buffstart=pos;
|
|
BS->bufftop=0;
|
|
BS->EOI = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
case STREAM_USE_FILE:
|
|
/*
|
|
** check if the desired position is within the
|
|
** current buffer
|
|
*/
|
|
if (pos>=BS->buffstart && pos<(BS->buffstart+BS->bufftop))
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("pos is in BS->buff, BS->bufftop=%d\n",
|
|
BS->bufftop) );
|
|
BS->buffp=pos-BS->buffstart;
|
|
BS->EOI = FALSE;
|
|
}
|
|
/* otherwise seek to it */
|
|
else if (ScFileSeek(BS->FileFd, pos)==NoErrors)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("seek(%d 0x%X)\n",pos,pos) );
|
|
BS->buffstart=pos;
|
|
BS->bufftop=0;
|
|
BS->buffp=0;
|
|
BS->EOI = FALSE;
|
|
}
|
|
else
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("seek(%d 0x%X) failed\n",pos,pos) );
|
|
BS->buffstart=0;
|
|
BS->bufftop=0;
|
|
BS->buffp=0;
|
|
BS->EOI = TRUE;
|
|
}
|
|
break;
|
|
default:
|
|
BS->buffstart=0;
|
|
BS->EOI = FALSE;
|
|
}
|
|
BS->CurrentBit=pos<<3;
|
|
_SlibDebug(_VERBOSE_, printf("ScBSSeekToPosition() done\n") );
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSReset()
|
|
** Purpose: Reset the bitstream back to the beginning.
|
|
*/
|
|
ScStatus_t ScBSReset(ScBitstream_t *BS)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("ScBSReset()\n") );
|
|
BS->EOI=FALSE;
|
|
if (BS->DataSource==STREAM_USE_FILE)
|
|
{
|
|
/*
|
|
** for files always empty buffer and seek to beginning
|
|
** just in case the file descriptor was used for something else
|
|
*/
|
|
_SlibDebug(_VERBOSE_, printf("seek(0)\n") );
|
|
ScFileSeek(BS->FileFd, 0);
|
|
BS->bufftop=0; /* empty buffer */
|
|
BS->buffp=0;
|
|
BS->buffstart=0;
|
|
}
|
|
BS->Flush=FALSE;
|
|
return(ScBSSeekToPosition(BS, 0));
|
|
}
|
|
|
|
/*
|
|
** Name: sc_BSGetData()
|
|
** Purpose: Set the bitstream pointer to the next buffer in the buffer
|
|
** queue, or if we're using simple file IO, read from the file.
|
|
** Returns: TRUE if data read
|
|
** FALSE if none read (EOI)
|
|
*/
|
|
static u_int sc_BSGetData(ScBitstream_t *BS)
|
|
{
|
|
int BufSize;
|
|
|
|
_SlibDebug(_VERBOSE_, printf("sc_BSGetData\n") );
|
|
BS->buffp = 0;
|
|
if (BS->EOI)
|
|
{
|
|
BS->buff = NULL;
|
|
BS->bufftop = 0;
|
|
return(FALSE);
|
|
}
|
|
switch (BS->DataSource)
|
|
{
|
|
case STREAM_USE_BUFFER:
|
|
if (BS->buff == BS->RdBuf)
|
|
{
|
|
BS->buff = NULL;
|
|
BS->bufftop = 0;
|
|
}
|
|
else
|
|
{
|
|
BS->buff = BS->RdBuf;
|
|
BS->bufftop = BS->RdBufSize;
|
|
}
|
|
break;
|
|
case STREAM_USE_QUEUE:
|
|
BS->buffstart+=BS->bufftop;
|
|
_SlibDebug(_VERIFY_ && BS->buffstart<(BS->CurrentBit/8),
|
|
printf("ScBSGetData() QUEUE buffstart(%d/0x%X) < currentbyte(%d/0x%X)\n",
|
|
BS->buffstart, BS->buffstart, BS->CurrentBit/8, BS->CurrentBit/8);
|
|
return(FALSE) );
|
|
BS->buff = sc_GetNextBuffer(BS, &BufSize);
|
|
BS->bufftop = BufSize;
|
|
break;
|
|
case STREAM_USE_NET:
|
|
case STREAM_USE_NET_UDP:
|
|
case STREAM_USE_FILE:
|
|
BS->buff = BS->RdBuf;
|
|
BS->buffstart+=BS->bufftop;
|
|
_SlibDebug(_VERIFY_ && BS->buffstart<(BS->CurrentBit/8),
|
|
printf("ScBSGetData() FILE buffstart(%d/0x%X) < currentbyte(%d/0x%X)\n",
|
|
BS->buffstart, BS->buffstart, BS->CurrentBit/8, BS->CurrentBit/8);
|
|
return(FALSE) );
|
|
BufSize = ScFileRead(BS->FileFd, BS->buff, BS->RdBufSize);
|
|
if (BufSize<0)
|
|
BS->bufftop = 0;
|
|
else
|
|
BS->bufftop = BufSize;
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("%d bytes read from fd %d: BytePosition=%d (0x%X) RdBufSize=%d\n buffstart=%d (0x%X)",
|
|
BS->bufftop,BS->FileFd,ScBSBytePosition(BS),
|
|
ScBSBytePosition(BS),BS->RdBufSize,
|
|
BS->buffstart,BS->buffstart) );
|
|
break;
|
|
case STREAM_USE_NULL:
|
|
BS->buff = NULL;
|
|
BS->bufftop =10240;
|
|
BS->buffstart+=10240;
|
|
break;
|
|
}
|
|
_SlibDebug(_DUMP_ && BS->buff && BS->bufftop &&
|
|
BS->DataSource==STREAM_USE_QUEUE,
|
|
printf("sc_BSGetData():\n");
|
|
ScDumpChar(BS->buff, BS->bufftop, BS->buffstart);
|
|
if (BS->bufftop>0x8000) /* show end of buffer */
|
|
ScDumpChar(BS->buff+BS->bufftop-0x500, 0x500,
|
|
BS->buffstart+BS->bufftop-0x500) );
|
|
|
|
if (BS->buff && BS->bufftop)
|
|
return(TRUE);
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
/*
|
|
** Name: sc_BSPutData()
|
|
** Purpose: Set the bitstream pointer to the next buffer in the buffer
|
|
** queue, or if we're using simple file IO, read from the file.
|
|
*/
|
|
static ScStatus_t sc_BSPutData(ScBitstream_t *BS)
|
|
{
|
|
ScStatus_t stat;
|
|
int written;
|
|
|
|
_SlibDebug(_VERBOSE_, printf("sc_BSPutData\n") );
|
|
BS->Flush=FALSE;
|
|
switch (BS->DataSource)
|
|
{
|
|
case STREAM_USE_BUFFER:
|
|
stat=ScErrorEndBitstream;
|
|
break;
|
|
case STREAM_USE_QUEUE:
|
|
if (BS->Callback)
|
|
{
|
|
ScCallbackInfo_t CB;
|
|
if (BS->buff)
|
|
{
|
|
_SlibDebug(_VERBOSE_, printf("Callback CB_RELEASE_BUFFERS\n"));
|
|
CB.Message = CB_RELEASE_BUFFER;
|
|
CB.Data = BS->buff;
|
|
CB.DataSize = BS->buffp;
|
|
CB.DataUsed = CB.DataSize;
|
|
CB.DataType = BS->DataType;
|
|
CB.UserData = BS->UserData;
|
|
CB.Action = CB_ACTION_CONTINUE;
|
|
(*BS->Callback)(BS->Sch, &CB, NULL);
|
|
BS->buff = 0;
|
|
BS->bufftop = 0;
|
|
BS->buffp=0;
|
|
if (CB.Action == CB_ACTION_END)
|
|
return(ScErrorClientEnd);
|
|
}
|
|
else
|
|
BS->bufftop = 0;
|
|
if (!BS->Q)
|
|
stat=ScErrorEndBitstream;
|
|
else
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("Callback CB_END_BUFFERS\n") );
|
|
CB.Message = CB_END_BUFFERS;
|
|
CB.Data = NULL;
|
|
CB.DataSize = 0;
|
|
CB.DataUsed = 0;
|
|
CB.DataType = BS->DataType;
|
|
CB.UserData = BS->UserData;
|
|
CB.Action = CB_ACTION_CONTINUE;
|
|
(*BS->Callback)(BS->Sch, &CB, NULL);
|
|
if (CB.Action != CB_ACTION_CONTINUE ||
|
|
ScBufQueueGetNum(BS->Q)==0)
|
|
stat=ScErrorEndBitstream;
|
|
else
|
|
{
|
|
int size;
|
|
ScBufQueueGetHead(BS->Q, &BS->buff, &size);
|
|
BS->bufftop=size;
|
|
ScBufQueueRemove(BS->Q);
|
|
if (!BS->buff || size<=0)
|
|
stat=ScErrorEndBitstream;
|
|
else
|
|
stat=NoErrors;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BS->buff = 0;
|
|
BS->bufftop = 0;
|
|
}
|
|
BS->buffp=0;
|
|
break;
|
|
case STREAM_USE_FILE:
|
|
case STREAM_USE_NET:
|
|
case STREAM_USE_NET_UDP:
|
|
if (BS->buffp>0)
|
|
{
|
|
written=ScFileWrite(BS->FileFd, BS->buff, BS->buffp);
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("%d bytes written to fd %d (buffer=%d bytes)\n",
|
|
written, BS->FileFd, BS->buffp) );
|
|
_SlibDebug(_DUMP_,
|
|
printf("sc_BSPutData():\n");
|
|
ScDumpChar(BS->buff, BS->buffp, BS->buffstart));
|
|
if (written<(int)BS->buffp)
|
|
{
|
|
BS->buff = BS->RdBuf;
|
|
BS->buffp=0;
|
|
BS->bufftop=0;
|
|
stat=ScErrorEndBitstream;
|
|
}
|
|
else
|
|
{
|
|
BS->buff = BS->RdBuf;
|
|
BS->buffp=0;
|
|
BS->bufftop = BS->RdBufSize;
|
|
stat=NoErrors;
|
|
}
|
|
}
|
|
break;
|
|
case STREAM_USE_NULL:
|
|
BS->buff = NULL;
|
|
BS->buffp=0;
|
|
BS->bufftop = 10240;
|
|
break;
|
|
default:
|
|
stat=ScErrorEndBitstream;
|
|
}
|
|
|
|
return(stat);
|
|
}
|
|
|
|
/*
|
|
** Name: sc_BSLoadDataWord
|
|
** Purpose: Copy a longword from the bitstream buffer into local working buffer
|
|
*/
|
|
ScStatus_t sc_BSLoadDataWord(ScBitstream_t *BS)
|
|
{
|
|
int i, bcount;
|
|
register ScBitBuff_t InBuff;
|
|
const int shift=BS->shift;
|
|
const u_int buffp=BS->buffp;
|
|
register u_char *buff=BS->buff+buffp;
|
|
|
|
_SlibDebug(_DEBUG_,
|
|
printf("sc_BSLoadDataWord(BS=%p) shift=%d bit=%d byte=%d (0x%X)\n",
|
|
BS, BS->shift, BS->CurrentBit, BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
/* If we have plenty of room, use fast path */
|
|
if (BS->bufftop - buffp >= SC_BITBUFFSZ/8)
|
|
{
|
|
#if SC_BITBUFFSZ == 64
|
|
InBuff=(ScBitBuff_t)buff[7];
|
|
InBuff|=(ScBitBuff_t)buff[6]<<8;
|
|
InBuff|=(ScBitBuff_t)buff[5]<<16;
|
|
InBuff|=(ScBitBuff_t)buff[4]<<24;
|
|
InBuff|=(ScBitBuff_t)buff[3]<<32;
|
|
InBuff|=(ScBitBuff_t)buff[2]<<40;
|
|
InBuff|=(ScBitBuff_t)buff[1]<<48;
|
|
InBuff|=(ScBitBuff_t)buff[0]<<56;
|
|
_SlibDebug(_VERIFY_ && (u_char)((InBuff>>24)&0xFF)!=buff[4],
|
|
printf("sc_BSLoadDataWord(BS=%p) InBuff>>24(%X)!=buff[4](%X)\n",
|
|
BS, (InBuff>>24)&0xFF, buff[4]) );
|
|
_SlibDebug(_VERIFY_ && (u_char)(InBuff>>56)!=buff[0],
|
|
printf("sc_BSLoadDataWord(BS=%p) InBuff>>56(%X)!=buff[0](%X)\n",
|
|
BS, (InBuff>>56), buff[0]) );
|
|
#elif SC_BITBUFFSZ == 32
|
|
InBuff=(ScBitBuff_t)buff[3];
|
|
InBuff|=(ScBitBuff_t)buff[2]<<8;
|
|
InBuff|=(ScBitBuff_t)buff[1]<<16;
|
|
InBuff|=(ScBitBuff_t)buff[0]<<24;
|
|
_SlibDebug(_VERIFY_ && (InBuff>>24)!=buff[0],
|
|
printf("sc_BSLoadDataWord(BS=%p) InBuff>>24(%X)!=buff[0](%X)\n",
|
|
BS, InBuff>>24, buff[0]) );
|
|
#else
|
|
printf("SC_BITBUFFSZ <> 32\n");
|
|
for (InBuff=0, i = SC_BITBUFFSZ/8; i > 0; i--, buff++)
|
|
InBuff = (InBuff << 8) | (ScBitBuff_t)*buff;
|
|
#endif
|
|
BS->buffp=buffp+SC_BITBUFFSZ/8;
|
|
bcount = SC_BITBUFFSZ/8;
|
|
}
|
|
/* Near or at end of buffer */
|
|
else
|
|
{
|
|
/* Get remaining bytes */
|
|
bcount = BS->bufftop - buffp;
|
|
for (InBuff=0, i = bcount; i > 0; i--, buff++)
|
|
InBuff = (InBuff << 8) | (ScBitBuff_t)*buff;
|
|
BS->buffp=buffp+bcount;
|
|
/* Attempt to get more data - if successful, shuffle rest of bytes */
|
|
if (sc_BSGetData(BS))
|
|
{
|
|
BS->EOI = FALSE;
|
|
i = (SC_BITBUFFSZ/8) - bcount;
|
|
if (i>(int)BS->bufftop)
|
|
{
|
|
_SlibDebug(_WARN_,
|
|
printf("ScBSLoadDataWord() Got small buffer. Expected %d bytes got %d bytes.\n",
|
|
i, BS->bufftop) );
|
|
i=BS->bufftop;
|
|
bcount+=i;
|
|
while (i > 0)
|
|
{
|
|
InBuff = (InBuff << 8) | (ScBitBuff_t)BS->buff[BS->buffp++];
|
|
i--;
|
|
}
|
|
InBuff<<=SC_BITBUFFSZ-(bcount*8);
|
|
}
|
|
else
|
|
{
|
|
bcount = SC_BITBUFFSZ/8;
|
|
while (i > 0)
|
|
{
|
|
InBuff = (InBuff << 8) | (ScBitBuff_t)BS->buff[BS->buffp++];
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
else if (bcount==0)
|
|
BS->EOI = TRUE;
|
|
else
|
|
InBuff <<= SC_BITBUFFSZ-bcount*8;
|
|
}
|
|
|
|
_SlibDebug(_VERIFY_ && BS->shift>SC_BITBUFFSZ,
|
|
printf("sc_BSLoadDataWord(BS=%p) shift (%d) > SC_BITBUFFSZ (%d)\n",
|
|
BS, BS->shift, SC_BITBUFFSZ) );
|
|
if (!shift) /* OutBuff is empty */
|
|
{
|
|
BS->OutBuff = InBuff;
|
|
BS->InBuff = 0;
|
|
BS->shift=bcount*8;
|
|
}
|
|
else if (shift<SC_BITBUFFSZ)
|
|
{
|
|
BS->OutBuff |= InBuff >> shift;
|
|
BS->InBuff = InBuff << (SC_BITBUFFSZ-shift);
|
|
BS->shift=shift+(bcount*8);
|
|
}
|
|
else /* shift == SC_BITBUFFSZ - OutBuff is full */
|
|
{
|
|
BS->InBuff = InBuff;
|
|
BS->shift=bcount*8;
|
|
}
|
|
_SlibDebug(_VERIFY_,
|
|
if (BS->shift<SC_BITBUFFSZ)
|
|
{
|
|
if (BS->OutBuff & (SC_BITBUFFMASK>>BS->shift))
|
|
printf("sc_BSLoadDataWord(BS=%p) Non-zero bits to right of OutBuff: shift=%d\n", BS, BS->shift);
|
|
else if (BS->InBuff)
|
|
printf("sc_BSLoadDataWord(BS=%p) Non-zero bits in InBuff: shift=%d\n",
|
|
BS, BS->shift);
|
|
}
|
|
else if (BS->InBuff&(SC_BITBUFFMASK>>(BS->shift-SC_BITBUFFSZ)))
|
|
printf("sc_BSLoadDataWord(BS=%p) Non-zero bits to right of InBuff: shift=%d\n", BS->shift);
|
|
if ((BS->CurrentBit%8) && !(BS->shift%8))
|
|
printf("sc_BSLoadDataWord(BS=%p) CurrentBit (%d) and shift (%d) not aligned.\n", BS, BS->CurrentBit, BS->shift);
|
|
if ((BS->CurrentBit+BS->shift)/8!=BS->buffstart+BS->buffp)
|
|
{
|
|
printf("sc_BSLoadDataWord(BS=%p) (CurrentBit+shift)/8 (%d) <> buffstart+buffp (%d)\n", BS, (BS->CurrentBit+BS->shift)/8, BS->buffstart+BS->buffp);
|
|
BS->EOI = TRUE;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
);
|
|
return(NoErrors);
|
|
}
|
|
/*
|
|
** Name: sc_BSLoadDataWordW
|
|
** Purpose: Copy a longword from the bitstream buffer into local working buffer
|
|
** ** This version operates a word at a time for Dolby **
|
|
*/
|
|
ScStatus_t sc_BSLoadDataWordW(ScBitstream_t *BS)
|
|
{
|
|
int i, wcount;
|
|
register ScBitBuff_t InBuff;
|
|
const int shift=BS->shift;
|
|
const u_int buffp=BS->buffp;
|
|
register u_short *buff=(u_short *)BS->buff+(buffp/2);
|
|
|
|
_SlibDebug(_DEBUG_,
|
|
printf("sc_BSLoadDataWord(BS=%p) shift=%d bit=%d byte=%d (0x%X)\n",
|
|
BS, BS->shift, BS->CurrentBit, BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
/* If we have plenty of room, use fast path */
|
|
if (BS->bufftop - buffp >= SC_BITBUFFSZ/8)
|
|
{
|
|
#if SC_BITBUFFSZ == 64
|
|
InBuff=(ScBitBuff_t)buff[3];
|
|
InBuff|=(ScBitBuff_t)buff[2]<<16;
|
|
InBuff|=(ScBitBuff_t)buff[1]<<32;
|
|
InBuff|=(ScBitBuff_t)buff[0]<<48;
|
|
_SlibDebug(_VERIFY_ && (InBuff>>24)&0xFFFF!=buff[4],
|
|
printf("sc_BSLoadDataWord(BS=%p) InBuff>>24(%X)!=buff[0](%X)\n",
|
|
BS, (InBuff>>24)&0xFF, buff[4]) );
|
|
_SlibDebug(_VERIFY_ && (InBuff>>56)!=buff[0],
|
|
printf("sc_BSLoadDataWord(BS=%p) InBuff>>56(%X)!=buff[0](%X)\n",
|
|
BS, (InBuff>>56), buff[0]) );
|
|
#elif SC_BITBUFFSZ == 32
|
|
InBuff=(ScBitBuff_t)buff[1];
|
|
InBuff|=(ScBitBuff_t)buff[0]<<16;
|
|
_SlibDebug(_VERIFY_ && (InBuff>>16)!=buff[0],
|
|
printf("sc_BSLoadDataWord(BS=%p) InBuff>>24(%X)!=buff[0](%X)\n",
|
|
BS, InBuff>>24, buff[0]) );
|
|
#else
|
|
printf("SC_BITBUFFSZ <> 32\n");
|
|
for (InBuff=0, i = SC_BITBUFFSZ/16; i > 0; i--, buff++)
|
|
InBuff = (InBuff << 16) | (ScBitBuff_t)*buff;
|
|
#endif
|
|
BS->buffp=buffp+SC_BITBUFFSZ/8;
|
|
wcount = SC_BITBUFFSZ/16;
|
|
}
|
|
/* Near or at end of buffer */
|
|
else
|
|
{
|
|
/* Get remaining bytes */
|
|
wcount = (BS->bufftop - buffp)/2;
|
|
for (InBuff=0, i = wcount; i > 0; i--, buff++)
|
|
InBuff = (InBuff << 16) | (ScBitBuff_t)*buff;
|
|
BS->buffp=buffp+wcount*2;
|
|
/* Attempt to get more data - if successful, shuffle rest of bytes */
|
|
if (sc_BSGetData(BS))
|
|
{
|
|
int wordp=BS->buffp/2; /* Pointer is stored as a byte count, but we need words */
|
|
|
|
BS->EOI = FALSE;
|
|
i = (SC_BITBUFFSZ/16) - wcount;
|
|
if (i>(int)BS->bufftop)
|
|
{
|
|
_SlibDebug(_WARN_,
|
|
printf("ScBSLoadDataWord() Got small buffer. Expected %d words got %d words.\n",
|
|
i, BS->bufftop) );
|
|
i=BS->bufftop;
|
|
wcount+=i;
|
|
while (i >= 0)
|
|
{
|
|
InBuff = (InBuff << 16) | (ScBitBuff_t)((u_short *)BS->buff)[wordp++];
|
|
i--;
|
|
}
|
|
InBuff<<=SC_BITBUFFSZ-(wcount*16);
|
|
}
|
|
else
|
|
{
|
|
wcount = SC_BITBUFFSZ/16;
|
|
while (i > 0)
|
|
{
|
|
InBuff = (InBuff << 16) | (ScBitBuff_t)((u_short *)BS->buff)[wordp++];
|
|
i--;
|
|
}
|
|
}
|
|
BS->buffp=wordp*2;
|
|
}
|
|
else
|
|
BS->EOI = TRUE;
|
|
}
|
|
_SlibDebug(_VERIFY_ && BS->shift>SC_BITBUFFSZ,
|
|
printf("sc_BSLoadDataWordW(BS=%p) shift (%d) > SC_BITBUFFSZ (%d)\n",
|
|
BS, BS->shift, SC_BITBUFFSZ) );
|
|
if (!shift) /* OutBuff is empty */
|
|
{
|
|
BS->OutBuff = InBuff;
|
|
BS->InBuff = 0;
|
|
BS->shift=wcount*16;
|
|
}
|
|
else if (shift<SC_BITBUFFSZ)
|
|
{
|
|
BS->OutBuff |= InBuff >> shift;
|
|
BS->InBuff = InBuff << (SC_BITBUFFSZ-shift);
|
|
BS->shift=shift+(wcount*16);
|
|
}
|
|
else /* shift == SC_BITBUFFSZ - OutBuff is full */
|
|
{
|
|
BS->InBuff = InBuff;
|
|
BS->shift=wcount*16;
|
|
}
|
|
_SlibDebug(_VERIFY_,
|
|
if (BS->shift<SC_BITBUFFSZ)
|
|
{
|
|
if (BS->OutBuff & (SC_BITBUFFMASK>>BS->shift))
|
|
printf("sc_BSLoadDataWord(BS=%p) Non-zero bits to right of OutBuff: shift=%d\n", BS, BS->shift);
|
|
else if (BS->InBuff)
|
|
printf("sc_BSLoadDataWord(BS=%p) Non-zero bits in InBuff: shift=%d\n",
|
|
BS, BS->shift);
|
|
}
|
|
else if (BS->InBuff&(SC_BITBUFFMASK>>(BS->shift-SC_BITBUFFSZ)))
|
|
printf("sc_BSLoadDataWord(BS=%p) Non-zero bits to right of InBuff: shift=%d\n", BS->shift);
|
|
if ((BS->CurrentBit%8) && !(BS->shift%8))
|
|
printf("sc_BSLoadDataWord(BS=%p) CurrentBit (%d) and shift (%d) not aligned.\n", BS, BS->CurrentBit, BS->shift);
|
|
if ((BS->CurrentBit+BS->shift)/8!=BS->buffstart+BS->buffp)
|
|
{
|
|
printf("sc_BSLoadDataWord(BS=%p) (CurrentBit+shift)/8 (%d) <> buffstart+buffp (%d)\n", BS, (BS->CurrentBit+BS->shift)/8, BS->buffstart+BS->buffp);
|
|
BS->EOI = TRUE;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
);
|
|
return(NoErrors);
|
|
}
|
|
|
|
/*
|
|
** Name: sc_BSStoreDataWord
|
|
** Purpose: Copy a longword from the local working buffer to the
|
|
** bitstream buffer
|
|
*/
|
|
ScStatus_t sc_BSStoreDataWord(ScBitstream_t *BS, ScBitBuff_t OutBuff)
|
|
{
|
|
int i, bcount, shift=SC_BITBUFFSZ-8;
|
|
ScStatus_t stat=NoErrors;
|
|
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("sc_BSStoreDataWord(0x%lX 0x%lX) buffp=%d\n",
|
|
OutBuff>>32, OutBuff&0xFFFFFFFF, BS->buffp) );
|
|
if (BS->EOI)
|
|
return(ScErrorEndBitstream);
|
|
if (!BS->buff || BS->bufftop<=0)
|
|
{
|
|
if (BS->DataSource==STREAM_USE_QUEUE)
|
|
{
|
|
if (BS->Callback && BS->Q)
|
|
{
|
|
ScCallbackInfo_t CB;
|
|
_SlibDebug(_DEBUG_, printf("Callback CB_END_BUFFERS\n") );
|
|
CB.Message = CB_END_BUFFERS;
|
|
CB.Data = NULL;
|
|
CB.DataSize = 0;
|
|
CB.DataUsed = 0;
|
|
CB.DataType = BS->DataType;
|
|
CB.UserData = BS->UserData;
|
|
CB.Action = CB_ACTION_CONTINUE;
|
|
(*BS->Callback)(BS->Sch, &CB, NULL);
|
|
if (CB.Action != CB_ACTION_CONTINUE || ScBufQueueGetNum(BS->Q)==0)
|
|
{
|
|
BS->EOI = TRUE;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
else
|
|
{
|
|
int size;
|
|
ScBufQueueGetHead(BS->Q, &BS->buff, &size);
|
|
BS->bufftop=size;
|
|
ScBufQueueRemove(BS->Q);
|
|
if (!BS->buff || size<=0)
|
|
{
|
|
BS->EOI = TRUE;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
BS->EOI = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
BS->EOI = TRUE;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
}
|
|
else if (BS->RdBuf)
|
|
{
|
|
BS->buff=BS->RdBuf;
|
|
BS->bufftop=BS->RdBufSize;
|
|
}
|
|
}
|
|
bcount = BS->bufftop - BS->buffp;
|
|
/* If we have plenty of room, use fast path */
|
|
if (bcount >= SC_BITBUFFSZ>>3) {
|
|
u_char *buff=BS->buff+BS->buffp;
|
|
#if SC_BITBUFFSZ == 64
|
|
buff[0]=(unsigned char)(OutBuff>>56);
|
|
buff[1]=(unsigned char)(OutBuff>>48);
|
|
buff[2]=(unsigned char)(OutBuff>>40);
|
|
buff[3]=(unsigned char)(OutBuff>>32);
|
|
buff[4]=(unsigned char)(OutBuff>>24);
|
|
buff[5]=(unsigned char)(OutBuff>>16);
|
|
buff[6]=(unsigned char)(OutBuff>>8);
|
|
buff[7]=(unsigned char)OutBuff;
|
|
#elif SC_BITBUFFSZ == 32
|
|
buff[0]=(unsigned char)(OutBuff>>24);
|
|
buff[1]=(unsigned char)(OutBuff>>16);
|
|
buff[2]=(unsigned char)(OutBuff>>8);
|
|
buff[3]=(unsigned char)OutBuff;
|
|
#else
|
|
for (bcount = SC_BITBUFFSZ/8; bcount; shift-=8, bcount--, buff++)
|
|
*buff=(Buff>>shift)&0xFF;
|
|
#endif
|
|
BS->buffp+=SC_BITBUFFSZ/8;
|
|
if (BS->Flush && sc_BSPutData(BS)!=NoErrors)
|
|
BS->EOI=TRUE;
|
|
}
|
|
else /* Near end of buffer */
|
|
{
|
|
/* Fill up current buffer */
|
|
for (i=0; i<bcount; shift-=8, i++)
|
|
BS->buff[BS->buffp++]=(unsigned char)(OutBuff>>shift);
|
|
/* Commit the buffer */
|
|
if ((stat=sc_BSPutData(BS))==NoErrors)
|
|
{
|
|
/* Successful, so copy rest of bytes to new buffer */
|
|
bcount = (SC_BITBUFFSZ>>3) - bcount;
|
|
for (i=0; i<bcount; shift-=8, i++)
|
|
BS->buff[BS->buffp++]=(unsigned char)(OutBuff>>shift);
|
|
}
|
|
else
|
|
BS->EOI=TRUE;
|
|
}
|
|
BS->Mode='w';
|
|
return(stat);
|
|
}
|
|
|
|
/*
|
|
** ScBSSkipBits()
|
|
** Skip a certain number of bits
|
|
**
|
|
*/
|
|
ScStatus_t ScBSSkipBits(ScBitstream_t *BS, u_int length)
|
|
{
|
|
register u_int skipbytes, skipbits;
|
|
register int shift;
|
|
_SlibDebug(_DEBUG_, printf("ScBSSkipBits(%d): Byte offset = 0x%X\n",length,
|
|
ScBSBytePosition(BS)) );
|
|
_SlibDebug(_WARN_ && length==0,
|
|
printf("ScBSSkipBits(%d) length==0\n", length) );
|
|
_SlibDebug(_WARN_ && length>SC_BITBUFFSZ,
|
|
printf("ScBSSkipBits(%d) length > SC_BITBUFFSZ (%d)\n",
|
|
length, SC_BITBUFFSZ) );
|
|
if (length<=SC_BITBUFFSZ)
|
|
ScBSPreLoad(BS, length);
|
|
if ((shift=BS->shift)>0)
|
|
{
|
|
if (length<=(u_int)shift) /* all the bits are already in OutBuff & InBuff */
|
|
{
|
|
if (length==SC_BITBUFFSZ)
|
|
{
|
|
BS->OutBuff=BS->InBuff;
|
|
BS->InBuff=0;
|
|
}
|
|
else
|
|
{
|
|
BS->OutBuff=(BS->OutBuff<<length)|(BS->InBuff>>(SC_BITBUFFSZ-length));
|
|
BS->InBuff<<=length;
|
|
}
|
|
BS->CurrentBit+=length;
|
|
BS->shift=shift-length;
|
|
return(NoErrors);
|
|
}
|
|
else /* discard all the bits in OutBuff & InBuff */
|
|
{
|
|
length-=shift;
|
|
BS->OutBuff=BS->InBuff=0;
|
|
BS->CurrentBit+=shift;
|
|
BS->shift=0;
|
|
}
|
|
}
|
|
_SlibDebug(_VERIFY_ && (BS->shift || BS->CurrentBit%8),
|
|
printf("ScBSSkipBits() Bad Alignment - shift=%d CurrentBit=%d\n",
|
|
BS->shift, BS->CurrentBit) );
|
|
|
|
skipbytes=length>>3;
|
|
skipbits=length%8;
|
|
_SlibDebug(_WARN_ && skipbits,
|
|
printf("ScBSSkipBits() Skipping odd amount: skipbytes=%d skipbits=%d\n",
|
|
skipbytes, skipbits) );
|
|
if (BS->EOI)
|
|
return(ScErrorEndBitstream);
|
|
while (skipbytes>=(BS->bufftop - BS->buffp))
|
|
{
|
|
/* discard current block of data */
|
|
BS->CurrentBit+=(BS->bufftop - BS->buffp)<<3;
|
|
skipbytes-=BS->bufftop - BS->buffp;
|
|
BS->buffp=0;
|
|
/* get another block */
|
|
if (sc_BSGetData(BS))
|
|
BS->EOI = FALSE;
|
|
else
|
|
{
|
|
BS->EOI = TRUE;
|
|
BS->shift=0;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
}
|
|
if (skipbytes)
|
|
{
|
|
/* skip forward in current block of data */
|
|
BS->buffp+=skipbytes;
|
|
BS->CurrentBit+=skipbytes<<3;
|
|
}
|
|
if (skipbits)
|
|
{
|
|
/* skip odd number of bits - between 0 and 7 bits */
|
|
ScBSPreLoad(BS, skipbits);
|
|
BS->OutBuff<<=skipbits;
|
|
BS->CurrentBit += skipbits;
|
|
BS->shift-=skipbits;
|
|
}
|
|
return(NoErrors);
|
|
}
|
|
|
|
|
|
/*
|
|
** ScBSSkipBitsW()
|
|
** Skip a certain number of bits
|
|
** ** Dolby version **
|
|
*/
|
|
ScStatus_t ScBSSkipBitsW(ScBitstream_t *BS, u_int length)
|
|
{
|
|
register u_int skipwords, skipbits;
|
|
register int shift;
|
|
_SlibDebug(_DEBUG_, printf("ScBSSkipBitsW(%d): Byte offset = 0x%X\n",length,
|
|
ScBSBytePosition(BS)) );
|
|
_SlibDebug(_WARN_ && length==0,
|
|
printf("ScBSSkipBitsW(%d) length==0\n", length) );
|
|
_SlibDebug(_WARN_ && length>SC_BITBUFFSZ,
|
|
printf("ScBSSkipBits(%d) length > SC_BITBUFFSZ (%d)\n",
|
|
length, SC_BITBUFFSZ) );
|
|
if (length<=SC_BITBUFFSZ)
|
|
ScBSPreLoadW(BS, length);
|
|
if ((shift=BS->shift)>0)
|
|
{
|
|
if (length<=(u_int)shift) /* all the bits are already in OutBuff & InBuff */
|
|
{
|
|
if (length==SC_BITBUFFSZ)
|
|
{
|
|
BS->OutBuff=BS->InBuff;
|
|
BS->InBuff=0;
|
|
}
|
|
else
|
|
{
|
|
BS->OutBuff=(BS->OutBuff<<length)|(BS->InBuff>>(SC_BITBUFFSZ-length));
|
|
BS->InBuff<<=length;
|
|
}
|
|
BS->CurrentBit+=length;
|
|
BS->shift=shift-length;
|
|
return(NoErrors);
|
|
}
|
|
else /* discard all the bits in OutBuff & InBuff */
|
|
{
|
|
length-=shift;
|
|
BS->OutBuff=BS->InBuff=0;
|
|
BS->CurrentBit+=shift;
|
|
BS->shift=0;
|
|
}
|
|
}
|
|
_SlibDebug(_VERIFY_ && (BS->shift || BS->CurrentBit%8),
|
|
printf("ScBSSkipBitsW() Bad Alignment - shift=%d CurrentBit=%d\n",
|
|
BS->shift, BS->CurrentBit) );
|
|
|
|
skipwords=length>>4;
|
|
skipbits=length%16;
|
|
_SlibDebug(_WARN_ && skipbits,
|
|
printf("ScBSSkipBitsW() Skipping odd amount: skipwords=%d skipbits=%d\n",
|
|
skipwords, skipbits) );
|
|
if (BS->EOI)
|
|
return(ScErrorEndBitstream);
|
|
while (skipwords>=(BS->bufftop - BS->buffp)/2)
|
|
{
|
|
/* discard current block of data */
|
|
BS->CurrentBit+=((BS->bufftop - BS->buffp)/2)<<4;
|
|
skipwords-=(BS->bufftop - BS->buffp)/2;
|
|
BS->buffp=0;
|
|
/* get another block */
|
|
if (sc_BSGetData(BS))
|
|
BS->EOI = FALSE;
|
|
else
|
|
{
|
|
BS->EOI = TRUE;
|
|
BS->shift=0;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
}
|
|
if (skipwords)
|
|
{
|
|
/* skip forward in current block of data */
|
|
BS->buffp+=skipwords*2;
|
|
BS->CurrentBit+=skipwords<<4;
|
|
}
|
|
if (skipbits)
|
|
{
|
|
/* skip odd number of bits - between 0 and 7 bits */
|
|
ScBSPreLoadW(BS, skipbits);
|
|
BS->OutBuff<<=skipbits;
|
|
BS->CurrentBit += skipbits;
|
|
BS->shift-=skipbits;
|
|
}
|
|
return(NoErrors);
|
|
}
|
|
|
|
|
|
/*
|
|
** ScBSSkipBytes()
|
|
** Skip a certain number of bytes
|
|
**
|
|
*/
|
|
ScStatus_t ScBSSkipBytes(ScBitstream_t *BS, u_int length)
|
|
{
|
|
return(ScBSSkipBits(BS, length<<3));
|
|
}
|
|
|
|
|
|
/*
|
|
** ScBSPeekBits()
|
|
** Return the next length bits from the bitstream without
|
|
** removing them.
|
|
*/
|
|
ScBitString_t ScBSPeekBits(ScBitstream_t *BS, u_int length)
|
|
{
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSPeekBits(%d): Byte offset = 0x%X OutBuff=0x%lX\n",length,
|
|
ScBSBytePosition(BS),BS->OutBuff) );
|
|
_SlibDebug(_VERIFY_ && length>SC_BITBUFFSZ,
|
|
printf("ScBSPeekBits(%d) length > SC_BITBUFFSZ\n", length) );
|
|
_SlibDebug(_WARN_ && length==0,
|
|
printf("ScBSPeekBits(%d) length==0\n", length) );
|
|
if (length==0)
|
|
return(0);
|
|
ScBSPreLoad(BS, length);
|
|
_SlibDebug(_VERIFY_ && BS->shift<length,
|
|
printf("ScBSPeekBits(%d) shift (%d) < length (%d) at byte pos %d (0x%X)\n",
|
|
length, BS->shift, length, BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
if (length == SC_BITBUFFSZ)
|
|
return(BS->OutBuff);
|
|
else
|
|
return(BS->OutBuff >> (SC_BITBUFFSZ-length));
|
|
}
|
|
|
|
|
|
/*
|
|
** ScBSPeekBit()
|
|
** Return the next bit from the bitstream without
|
|
** removing it.
|
|
*/
|
|
int ScBSPeekBit(ScBitstream_t *BS)
|
|
{
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSPeekBit(): Byte offset = 0x%X OutBuff=0x%lX\n",
|
|
ScBSBytePosition(BS),BS->OutBuff) );
|
|
ScBSPreLoad(BS, 1);
|
|
return((int)(BS->OutBuff >> (SC_BITBUFFSZ-1)));
|
|
}
|
|
|
|
|
|
/*
|
|
** ScBSPeekBytes()
|
|
** Return the next length bytes from the bitstream without
|
|
** removing them.
|
|
*/
|
|
ScBitString_t ScBSPeekBytes(ScBitstream_t *BS, u_int length)
|
|
{
|
|
if (length==0)
|
|
return(0);
|
|
length*=8;
|
|
ScBSPreLoad(BS, length);
|
|
if (length == SC_BITBUFFSZ)
|
|
return(BS->OutBuff);
|
|
else
|
|
return(BS->OutBuff >> (SC_BITBUFFSZ-length));
|
|
}
|
|
|
|
/*
|
|
** ScBSGetBytes()
|
|
** Return the next length bytes from the bitstream
|
|
*/
|
|
ScStatus_t ScBSGetBytes(ScBitstream_t *BS, u_char *buffer, u_int length,
|
|
u_int *ret_length)
|
|
{
|
|
int i, shift;
|
|
unsigned int offset=0;
|
|
_SlibDebug(_VERBOSE_, printf("ScBSGetBytes(%d): Byte offset = 0x%X\n",
|
|
length, ScBSBytePosition(BS)) );
|
|
_SlibDebug(_WARN_ && length==0,
|
|
printf("ScBSGetBytes(%d) length==0\n", length) );
|
|
|
|
if (BS->EOI)
|
|
{
|
|
*ret_length=0;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
if (length<(SC_BITBUFFSZ>>3))
|
|
{
|
|
while (offset<length && !BS->EOI)
|
|
{
|
|
*(buffer+offset)=(unsigned char)ScBSGetBits(BS,8);
|
|
offset++;
|
|
}
|
|
*ret_length=offset;
|
|
if (BS->EOI)
|
|
return(ScErrorEndBitstream);
|
|
else
|
|
return(ScErrorNone);
|
|
}
|
|
else if (BS->bufftop>0)
|
|
{
|
|
ScBSByteAlign(BS);
|
|
shift=BS->shift;
|
|
/* remove bytes already in OutBuff and InBuff */
|
|
for (i=0; shift>0 && offset<length; i++, shift-=8, offset++)
|
|
{
|
|
*(buffer+offset)=(unsigned char)(BS->OutBuff>>(SC_BITBUFFSZ-8));
|
|
if (shift<=SC_BITBUFFSZ) /* only bits in OutBuff */
|
|
BS->OutBuff <<= 8;
|
|
else
|
|
{
|
|
BS->OutBuff=(BS->OutBuff<<8)|(BS->InBuff>>(SC_BITBUFFSZ-8));
|
|
BS->InBuff<<=8;
|
|
}
|
|
}
|
|
BS->shift=shift;
|
|
BS->CurrentBit+=i*8;
|
|
}
|
|
while (offset<length)
|
|
{
|
|
i=BS->bufftop-BS->buffp;
|
|
if (offset+i>length)
|
|
i=length-offset;
|
|
memcpy(buffer+offset, BS->buff+BS->buffp, i);
|
|
offset+=i;
|
|
BS->buffp+=i;
|
|
BS->CurrentBit+=i<<3;
|
|
_SlibDebug(_VERIFY_,
|
|
if ((BS->CurrentBit+BS->shift)/8!=BS->buffstart+BS->buffp)
|
|
{
|
|
printf("ScBSGetBytes() (CurrentBit+shift)/8 (%d) <> buffstart+buffp (%d)\n", (BS->CurrentBit+BS->shift)/8, BS->buffstart+BS->buffp);
|
|
BS->EOI = TRUE;
|
|
return(ScErrorEndBitstream);
|
|
} );
|
|
if (offset<length)
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI = TRUE;
|
|
*ret_length=offset;
|
|
return(ScErrorEndBitstream);
|
|
}
|
|
}
|
|
*ret_length=offset;
|
|
return(ScErrorNone);
|
|
}
|
|
|
|
/*
|
|
** ScBSGetBits()
|
|
** Return the next length bits from the bitstream
|
|
*/
|
|
ScBitString_t ScBSGetBits(ScBitstream_t *BS, u_int length)
|
|
{
|
|
ScBitString_t val;
|
|
|
|
_SlibDebug(_DEBUG_ && _debug_getbits,
|
|
printf("ScBSGetBits(%d): Byte offset = 0x%X shift=%d ",
|
|
length, ScBSBytePosition(BS), BS->shift) );
|
|
_SlibDebug(_VERIFY_ && length>SC_BITBUFFSZ,
|
|
printf("ScBSPeekBits(%d) length > SC_BITBUFFSZ\n", length) );
|
|
_SlibDebug(_WARN_ && length==0,
|
|
printf("ScBSGetBits(%d) length==0\n", length) );
|
|
|
|
#if FILTER_SUPPORT
|
|
if (BS->FilterCallback && BS->InFilterCallback==FALSE
|
|
&& BS->FilterBit<(BS->CurrentBit+length))
|
|
{
|
|
const int tmp=BS->FilterBit-BS->CurrentBit;
|
|
BS->InFilterCallback=TRUE;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("FilterCallback at bitpos=0x%X bytepos=0x%X GetBits(%d/%d)\n",
|
|
ScBSBitPosition(BS), ScBSBytePosition(BS),
|
|
tmp, length-tmp) );
|
|
if (tmp>0)
|
|
{
|
|
length-=tmp;
|
|
val=ScBSGetBits(BS,tmp)<<length;
|
|
}
|
|
else
|
|
val=0;
|
|
_SlibDebug(_VERIFY_ && (BS->FilterBit != BS->CurrentBit),
|
|
printf("ScBSGetBits() FilterCallback not at FilterBit (%d) CurrentBit=%d\n", BS->FilterBit, BS->CurrentBit) );
|
|
|
|
BS->FilterBit=(BS->FilterCallback)(BS);
|
|
BS->InFilterCallback=FALSE;
|
|
}
|
|
else
|
|
val=0;
|
|
if (!length)
|
|
return(val);
|
|
#else
|
|
if (!length)
|
|
return(0);
|
|
#endif
|
|
ScBSPreLoad(BS, length);
|
|
if (BS->shift<length) /* End of Input - ran out of bits */
|
|
{
|
|
#if FILTER_SUPPORT
|
|
val |= BS->OutBuff >> (SC_BITBUFFSZ-length); /* return whatever's there */
|
|
#else
|
|
val = BS->OutBuff >> (SC_BITBUFFSZ-length); /* return whatever's there */
|
|
#endif
|
|
BS->shift=0;
|
|
BS->OutBuff=0;
|
|
return(val);
|
|
}
|
|
else
|
|
{
|
|
_SlibDebug(_VERIFY_ && BS->shift<length,
|
|
printf("ScBSGetBits(%d) shift (%d) < length (%d) at byte pos %d (0x%X)\n",
|
|
length, BS->shift, length, BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
if (length!=SC_BITBUFFSZ)
|
|
{
|
|
const ScBitBuff_t OutBuff=BS->OutBuff;
|
|
const ScBitString_t InBuff=BS->InBuff;
|
|
const int shift=BS->shift;
|
|
#if FILTER_SUPPORT
|
|
val |= OutBuff >> (SC_BITBUFFSZ-length);
|
|
#else
|
|
val = OutBuff >> (SC_BITBUFFSZ-length);
|
|
#endif
|
|
BS->OutBuff=(OutBuff<<length)|(InBuff>>(SC_BITBUFFSZ-length));
|
|
BS->InBuff = InBuff<<length;
|
|
BS->shift=shift-length;
|
|
BS->CurrentBit += length;
|
|
}
|
|
else /* length == SC_BITBUFFSZ */
|
|
{
|
|
val = BS->OutBuff;
|
|
BS->OutBuff = BS->InBuff;
|
|
BS->InBuff = 0;
|
|
BS->shift-=SC_BITBUFFSZ;
|
|
BS->CurrentBit += SC_BITBUFFSZ;
|
|
}
|
|
}
|
|
_SlibDebug(_DEBUG_ && _debug_getbits, printf(" Return 0x%lX\n",val) );
|
|
return(val);
|
|
}
|
|
|
|
/*
|
|
** ScBSGetBitsW()
|
|
** Return the next length bits from the bitstream
|
|
*/
|
|
ScBitString_t ScBSGetBitsW(ScBitstream_t *BS, u_int length)
|
|
{
|
|
ScBitString_t val;
|
|
|
|
_SlibDebug(_DEBUG_ && _debug_getbits,
|
|
printf("ScBSGetBitsW(%d): Byte offset = 0x%X shift=%d ",
|
|
length, ScBSBytePosition(BS), BS->shift) );
|
|
_SlibDebug(_VERIFY_ && length>SC_BITBUFFSZ,
|
|
printf("ScBSPeekBits(%d) length > SC_BITBUFFSZ\n", length) );
|
|
_SlibDebug(_WARN_ && length==0,
|
|
printf("ScBSGetBitsW(%d) length==0\n", length) );
|
|
|
|
#if FILTER_SUPPORT
|
|
if (BS->FilterCallback && BS->InFilterCallback==FALSE
|
|
&& BS->FilterBit<(BS->CurrentBit+length))
|
|
{
|
|
const int tmp=BS->FilterBit-BS->CurrentBit;
|
|
BS->InFilterCallback=TRUE;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("FilterCallback at bitpos=0x%X bytepos=0x%X GetBits(%d/%d)\n",
|
|
ScBSBitPosition(BS), ScBSBytePosition(BS),
|
|
tmp, length-tmp) );
|
|
if (tmp>0)
|
|
{
|
|
length-=tmp;
|
|
val=ScBSGetBitsW(BS,tmp)<<length;
|
|
}
|
|
else
|
|
val=0;
|
|
_SlibDebug(_VERIFY_ && (BS->FilterBit != BS->CurrentBit),
|
|
printf("ScBSGetBits() FilterCallback not at FilterBit (%d) CurrentBit=%d\n", BS->FilterBit, BS->CurrentBit) );
|
|
|
|
BS->FilterBit=(BS->FilterCallback)(BS);
|
|
BS->InFilterCallback=FALSE;
|
|
}
|
|
else
|
|
val=0;
|
|
if (!length)
|
|
return(val);
|
|
#else
|
|
if (!length)
|
|
return(0);
|
|
#endif
|
|
ScBSPreLoadW(BS, length);
|
|
if (BS->shift<length) /* End of Input - ran out of bits */
|
|
{
|
|
#if FILTER_SUPPORT
|
|
val |= BS->OutBuff >> (SC_BITBUFFSZ-length); /* return whatever's there */
|
|
#else
|
|
val = BS->OutBuff >> (SC_BITBUFFSZ-length); /* return whatever's there */
|
|
#endif
|
|
BS->shift=0;
|
|
BS->OutBuff=0;
|
|
return(val);
|
|
}
|
|
else
|
|
{
|
|
_SlibDebug(_VERIFY_ && BS->shift<length,
|
|
printf("ScBSGetBits(%d) shift (%d) < length (%d) at byte pos %d (0x%X)\n",
|
|
length, BS->shift, length, BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
if (length!=SC_BITBUFFSZ)
|
|
{
|
|
const ScBitBuff_t OutBuff=BS->OutBuff;
|
|
const ScBitString_t InBuff=BS->InBuff;
|
|
const int shift=BS->shift;
|
|
#if FILTER_SUPPORT
|
|
val |= OutBuff >> (SC_BITBUFFSZ-length);
|
|
#else
|
|
val = OutBuff >> (SC_BITBUFFSZ-length);
|
|
#endif
|
|
BS->OutBuff=(OutBuff<<length)|(InBuff>>(SC_BITBUFFSZ-length));
|
|
BS->InBuff = InBuff<<length;
|
|
BS->shift=shift-length;
|
|
BS->CurrentBit += length;
|
|
}
|
|
else /* length == SC_BITBUFFSZ */
|
|
{
|
|
val = BS->OutBuff;
|
|
BS->OutBuff = BS->InBuff;
|
|
BS->InBuff = 0;
|
|
BS->shift-=SC_BITBUFFSZ;
|
|
BS->CurrentBit += SC_BITBUFFSZ;
|
|
}
|
|
}
|
|
_SlibDebug(_DEBUG_ && _debug_getbits, printf(" Return 0x%lX\n",val) );
|
|
return(val);
|
|
}
|
|
|
|
|
|
/*
|
|
** ScBSGetBit()
|
|
** Put a single bit onto the bitstream
|
|
*/
|
|
int ScBSGetBit(ScBitstream_t *BS)
|
|
{
|
|
int val;
|
|
_SlibDebug(_DEBUG_ && _debug_getbits,
|
|
printf("ScBSGetBit(): Byte offset = 0x%X shift=%d ",
|
|
ScBSBytePosition(BS), BS->shift) );
|
|
|
|
#if FILTER_SUPPORT
|
|
if (BS->FilterCallback && BS->InFilterCallback==FALSE
|
|
&& BS->FilterBit==BS->CurrentBit)
|
|
{
|
|
BS->InFilterCallback=TRUE;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("FilterCallback at bitpos=0x%X bytepos=0x%X\n",
|
|
ScBSBitPosition(BS), ScBSBytePosition(BS)) );
|
|
BS->FilterBit=(BS->FilterCallback)(BS);
|
|
BS->InFilterCallback=FALSE;
|
|
}
|
|
#endif
|
|
|
|
ScBSPreLoad(BS, 1);
|
|
if (!BS->EOI)
|
|
{
|
|
const ScBitBuff_t OutBuff=BS->OutBuff;
|
|
val=(int)(OutBuff>>(SC_BITBUFFSZ-1));
|
|
if (--BS->shift>=SC_BITBUFFSZ)
|
|
{
|
|
const ScBitBuff_t InBuff=BS->InBuff;
|
|
BS->OutBuff = (OutBuff<<1)|(InBuff >> (SC_BITBUFFSZ-1));
|
|
BS->InBuff = InBuff<<1;
|
|
}
|
|
else
|
|
BS->OutBuff = OutBuff<<1;
|
|
BS->CurrentBit++;
|
|
}
|
|
else
|
|
val=0;
|
|
_SlibDebug(_DEBUG_ && _debug_getbits, printf(" Return 0x%lX\n",val) );
|
|
return(val);
|
|
}
|
|
|
|
/*
|
|
** ScBSPutBits()
|
|
** Put a number of bits onto the bitstream
|
|
*/
|
|
ScStatus_t ScBSPutBits(ScBitstream_t *BS, ScBitString_t bits, u_int length)
|
|
{
|
|
ScStatus_t stat;
|
|
const int newshift=BS->shift+length;
|
|
|
|
if (length<SC_BITBUFFSZ)
|
|
bits &= ((ScBitString_t)1<<length)-1;
|
|
_SlibDebug(_DEBUG_, printf("ScBSPutBits(0x%lX, %d): Byte offset = 0x%X ",
|
|
bits, length, ScBSBytePosition(BS)) );
|
|
_SlibDebug(_VERIFY_&&length<SC_BITBUFFSZ && bits>=((ScBitString_t)1<<length),
|
|
printf("ScBSPutBits(%d): bits (0x%X) to large\n", length, bits) );
|
|
if (!length)
|
|
return(NoErrors);
|
|
else if (newshift < SC_BITBUFFSZ)
|
|
{
|
|
BS->OutBuff=(BS->OutBuff<<length) | bits;
|
|
BS->shift=newshift;
|
|
stat=NoErrors;
|
|
}
|
|
else if (newshift == SC_BITBUFFSZ)
|
|
{
|
|
stat=sc_BSStoreDataWord(BS, (BS->OutBuff<<length)|bits);
|
|
BS->OutBuff=0;
|
|
BS->shift=0;
|
|
}
|
|
else
|
|
{
|
|
const int bitsavail=SC_BITBUFFSZ-BS->shift;
|
|
const int bitsleft=length-bitsavail;
|
|
const ScBitString_t outbits=bits>>bitsleft;
|
|
_SlibDebug(_DEBUG_, printf("ScBSPutBits(%d) Storing 0x%lX\n",
|
|
length, (BS->OutBuff<<bitsavail)|outbits) );
|
|
stat=sc_BSStoreDataWord(BS, (BS->OutBuff<<bitsavail)|outbits);
|
|
_SlibDebug(_VERIFY_ && (bitsavail<=0 || bitsleft>=SC_BITBUFFSZ),
|
|
printf("ScBSPutBits(%d) bad bitsleft (%d)\n",
|
|
bitsleft) );
|
|
_SlibDebug(_VERIFY_ && (bitsavail<=0 || bitsavail>=SC_BITBUFFSZ),
|
|
printf("ScBSPutBits(%d) bad bitsavail (%d)\n", bitsavail) );
|
|
#if 1
|
|
BS->OutBuff=bits & (((ScBitBuff_t)1<<bitsleft)-1);
|
|
#else
|
|
BS->OutBuff=bits-(outbits<<bitsleft);
|
|
#endif
|
|
BS->shift=bitsleft;
|
|
}
|
|
BS->CurrentBit += length;
|
|
return(stat);
|
|
}
|
|
|
|
/*
|
|
** ScBSPutBytes()
|
|
** Put a number of bits onto the bitstream
|
|
*/
|
|
ScStatus_t ScBSPutBytes(ScBitstream_t *BS, u_char *buffer, u_int length)
|
|
{
|
|
ScStatus_t stat=NoErrors;
|
|
_SlibDebug(_VERIFY_, printf("ScBSPutBytes(length=%d): Byte offset = 0x%X ",
|
|
length, ScBSBytePosition(BS)) );
|
|
|
|
while (stat==NoErrors && length>0)
|
|
{
|
|
stat=ScBSPutBits(BS, (ScBitString_t)*buffer, 8);
|
|
buffer++;
|
|
length--;
|
|
}
|
|
return(stat);
|
|
}
|
|
|
|
/*
|
|
** ScBSPutBit()
|
|
** Put a single bit onto the bitstream
|
|
*/
|
|
ScStatus_t ScBSPutBit(ScBitstream_t *BS, char bit)
|
|
{
|
|
ScStatus_t stat;
|
|
const int shift=BS->shift;
|
|
|
|
_SlibDebug(_DEBUG_, printf("ScBSPutBit(0x%lX): Byte offset = 0x%X ",
|
|
bit, ScBSBytePosition(BS)) );
|
|
_SlibDebug(_VERIFY_ && bit>1, printf("ScBSPutBit(): bit>1") );
|
|
if (shift < (SC_BITBUFFSZ-1))
|
|
{
|
|
BS->OutBuff<<=1;
|
|
if (bit)
|
|
BS->OutBuff|=1;
|
|
BS->shift=shift+1;
|
|
stat=NoErrors;
|
|
}
|
|
else if (shift == SC_BITBUFFSZ-1)
|
|
{
|
|
if (bit)
|
|
stat=sc_BSStoreDataWord(BS, (BS->OutBuff<<1)+1);
|
|
else
|
|
stat=sc_BSStoreDataWord(BS, BS->OutBuff<<1);
|
|
BS->OutBuff=0;
|
|
BS->shift=0;
|
|
}
|
|
else
|
|
{
|
|
_SlibDebug(_DEBUG_, printf("BS Storing(0x%lX)\n", BS->OutBuff) );
|
|
stat=sc_BSStoreDataWord(BS, BS->OutBuff);
|
|
BS->OutBuff=bit;
|
|
BS->shift=1;
|
|
}
|
|
BS->CurrentBit++;
|
|
return(stat);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSGetBitsVarLen()
|
|
** Purpose: Return bits from the bitstream. # bits depends on table
|
|
*/
|
|
int ScBSGetBitsVarLen(ScBitstream_t *BS, const int *table, int len)
|
|
{
|
|
int index, lookup;
|
|
|
|
index=(int)ScBSPeekBits(BS, len);
|
|
lookup = table[index];
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSGetBitsVarLen(len=%d): Byte offset=0x%X table[%d]=0x%X Return=%d\n",
|
|
len, ScBSBytePosition(BS), index, lookup, lookup >> 6) );
|
|
ScBSGetBits(BS, lookup & 0x3F);
|
|
return(lookup >> 6);
|
|
}
|
|
|
|
|
|
#ifndef ScBSBitPosition
|
|
/* Now is a macro in SC.h */
|
|
/*
|
|
** Name: ScBSBitPosition()
|
|
** Purpose: Return the absolute bit position in the stream
|
|
*/
|
|
long ScBSBitPosition(ScBitstream_t *BS)
|
|
{
|
|
return(BS->CurrentBit);
|
|
}
|
|
#endif
|
|
|
|
#ifndef ScBSBytePosition
|
|
/* Now is a macro in SC.h */
|
|
/*
|
|
** Name: ScBSBytePosition()
|
|
** Purpose: Return the absolute byte position in the stream
|
|
*/
|
|
long ScBSBytePosition(ScBitstream_t *BS)
|
|
{
|
|
return(BS->CurrentBit>>3);
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
** Name: ScBSSeekAlign()
|
|
** Purpose: Seeks for a byte aligned word in the bit stream
|
|
** and places the bit stream pointer right after its
|
|
** found position.
|
|
** Return: Returns TRUE if the sync was found otherwise it returns FALSE.
|
|
*/
|
|
int ScBSSeekAlign(ScBitstream_t *BS, ScBitString_t seek_word, int word_len)
|
|
{
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("ScBSSeekAlign(BS=%p, seek_word=0x%x, word_len=%d)\n",
|
|
BS, seek_word, word_len) );
|
|
_SlibDebug(_VERIFY_ && !word_len,
|
|
printf("ScBSSeekAlign(BS=%p) word_len=0\n", BS) );
|
|
|
|
ScBSByteAlign(BS)
|
|
_SlibDebug(_VERIFY_, _debug_start=BS->CurrentBit );
|
|
|
|
#if USE_FAST_SEEK
|
|
if (word_len%8==0 && word_len<=32 && !BS->EOI) /* do a fast seek */
|
|
{
|
|
unsigned char *buff, nextbyte;
|
|
const unsigned char byte1=(seek_word>>(word_len-8))&0xFF;
|
|
int bytesinbuff;
|
|
seek_word-=((ScBitString_t)byte1)<<word_len;
|
|
word_len-=8;
|
|
_SlibDebug(_VERIFY_ && seek_word >= (ScBitString_t)1<<word_len,
|
|
printf("ScBSSeekAlign(BS=%p) shift (%d) <> 0\n", BS, BS->shift) );
|
|
if (BS->buffp>=(BS->shift/8)) /* empty OutBuff & InBuff */
|
|
{
|
|
BS->shift=0;
|
|
BS->OutBuff=0;
|
|
BS->InBuff=0;
|
|
BS->buffp-=BS->shift/8;
|
|
}
|
|
else while (BS->shift) /* search whats in OutBuff & InBuff first */
|
|
{
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSSeekAlign() Fast searching OutBuff & InBuff\n") );
|
|
nextbyte=BS->OutBuff>>(SC_BITBUFFSZ-8);
|
|
BS->shift-=8;
|
|
BS->OutBuff=(BS->OutBuff<<8)|(BS->InBuff>>(SC_BITBUFFSZ-8));
|
|
BS->InBuff<<=8;
|
|
BS->CurrentBit+=8;
|
|
if (nextbyte==byte1
|
|
&& (word_len==0 || ScBSPeekBits(BS, word_len)==seek_word))
|
|
{
|
|
/* found seek_word in buffer */
|
|
ScBSSkipBits(BS, word_len);
|
|
return(!BS->EOI);
|
|
}
|
|
}
|
|
_SlibDebug(_VERIFY_ && BS->shift,
|
|
printf("ScBSSeekAlign(BS=%p) shift (%d) <> 0\n", BS, BS->shift) );
|
|
_SlibDebug(_VERIFY_ && BS->OutBuff,
|
|
printf("ScBSSeekAlign(BS=%p) OutBuff (0x%lX) <> 0\n", BS, BS->OutBuff) );
|
|
_SlibDebug(_VERIFY_ && BS->InBuff,
|
|
printf("ScBSSeekAlign(BS=%p) InBuff (0x%lX) <> 0\n", BS, BS->InBuff) );
|
|
|
|
bytesinbuff=BS->bufftop-BS->buffp;
|
|
if (bytesinbuff<=0) /* Get more data if all out */
|
|
{
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
buff=BS->buff+BS->buffp;
|
|
switch (word_len/8)
|
|
{
|
|
case 0: /* word length = 1 byte */
|
|
while (1)
|
|
{
|
|
if (*buff++==byte1)
|
|
{
|
|
BS->buffp=buff-BS->buff;
|
|
BS->CurrentBit=(BS->buffstart+BS->buffp)*8;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSSeekAlign() Found %X at pos %d (0x%X)\n",
|
|
byte1, BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
_SlibDebug(_VERIFY_ && BS->buff[BS->buffp-1]!=byte1,
|
|
printf("ScBSSeekAlign() bad position for buffp\n") );
|
|
return(TRUE);
|
|
}
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
_SlibDebug(_VERIFY_ && bytesinbuff<=0,
|
|
printf("ScBSSeekAlign() bytesinbuff (%d)<=0\n", bytesinbuff) );
|
|
}
|
|
break;
|
|
case 1: /* word length = 2 bytes */
|
|
{
|
|
const unsigned char byte2=seek_word&0xFF;
|
|
while (1)
|
|
{
|
|
if (*buff++==byte1)
|
|
{
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
if (*buff++==byte2)
|
|
{
|
|
BS->buffp=buff-BS->buff;
|
|
BS->CurrentBit=(BS->buffstart+BS->buffp)*8;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSSeekAlign() Found %X %X at pos %d (0x%X)\n",
|
|
byte1, byte2, BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
_SlibDebug(_VERIFY_ && BS->buff[BS->buffp-1]!=byte2,
|
|
printf("ScBSSeekAlign() bad position for buffp\n") );
|
|
return(TRUE);
|
|
}
|
|
}
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
_SlibDebug(_VERIFY_ && bytesinbuff<=0,
|
|
printf("ScBSSeekAlign() bytesinbuff (%d)<=0\n", bytesinbuff) );
|
|
}
|
|
}
|
|
break;
|
|
case 2: /* word length = 3 bytes */
|
|
{
|
|
const unsigned char byte2=(seek_word>>8)&0xFF;
|
|
const unsigned char byte3=seek_word&0xFF;
|
|
while (1)
|
|
{
|
|
if (*buff++==byte1)
|
|
{
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
if (*buff++==byte2)
|
|
{
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
if (*buff++==byte3)
|
|
{
|
|
BS->buffp=buff-BS->buff;
|
|
BS->CurrentBit=(BS->buffstart+BS->buffp)*8;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSSeekAlign() Found %X %X %X at pos %d (0x%X)\n",
|
|
byte1, byte2, byte3,
|
|
BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
_SlibDebug(_VERIFY_ && BS->buff[BS->buffp-1]!=byte3,
|
|
printf("ScBSSeekAlign() bad position for buffp\n") );
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
_SlibDebug(_VERIFY_ && bytesinbuff<=0,
|
|
printf("ScBSSeekAlign() bytesinbuff (%d)<=0\n", bytesinbuff) );
|
|
}
|
|
}
|
|
break;
|
|
case 3: /* word length = 4 bytes */
|
|
{
|
|
const unsigned char byte2=(seek_word>>16)&0xFF;
|
|
const unsigned char byte3=(seek_word>>8)&0xFF;
|
|
const unsigned char byte4=seek_word&0xFF;
|
|
while (1)
|
|
{
|
|
if (*buff++==byte1)
|
|
{
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
if (*buff++==byte2)
|
|
{
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
if (*buff++==byte3)
|
|
{
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
if (*buff++==byte4)
|
|
{
|
|
BS->buffp=buff-BS->buff;
|
|
BS->CurrentBit=(BS->buffstart+BS->buffp)*8;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSSeekAlign() Found %X %X %X %X at pos %d (0x%X)\n",
|
|
byte1, byte2, byte3, byte4,
|
|
BS->CurrentBit/8, BS->CurrentBit/8) );
|
|
_SlibDebug(_VERIFY_ && BS->buff[BS->buffp-1]!=byte4,
|
|
printf("ScBSSeekAlign() bad position for buffp\n") );
|
|
return(TRUE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ((--bytesinbuff)==0)
|
|
{
|
|
BS->CurrentBit=(BS->buffstart+buff-BS->buff)*8;
|
|
if (!sc_BSGetData(BS))
|
|
{
|
|
BS->EOI=TRUE;
|
|
return(FALSE);
|
|
}
|
|
buff=BS->buff;
|
|
bytesinbuff=BS->bufftop;
|
|
}
|
|
_SlibDebug(_VERIFY_ && bytesinbuff<=0,
|
|
printf("ScBSSeekAlign() bytesinbuff (%d)<=0\n", bytesinbuff) );
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
_SlibDebug(_VERIFY_,
|
|
printf("ScBSSeekAlign() Bad fast word length %d\n", word_len) );
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{ /* a slow seek */
|
|
ScBitString_t val;
|
|
const ScBitString_t maxi = ((ScBitString_t)1 << word_len)-(ScBitString_t)1;
|
|
val = ScBSGetBits(BS, word_len);
|
|
_SlibDebug(_DEBUG_, _debug_getbits=FALSE );
|
|
while ((val&maxi)!=seek_word && !BS->EOI)
|
|
val = (val<<8)|ScBSGetBits(BS, 8);
|
|
_SlibDebug(_DEBUG_, _debug_getbits=TRUE );
|
|
}
|
|
_SlibDebug(_WARN_,
|
|
_debug_stop=BS->CurrentBit;
|
|
if ((_debug_stop-_debug_start)>word_len)
|
|
printf("ScBSSeekAlign() Moved %d bits (%d bytes) byte pos 0x%X->0x%X\n",
|
|
_debug_stop-_debug_start, (_debug_stop-_debug_start)/8,
|
|
_debug_start/8, _debug_stop/8)
|
|
);
|
|
|
|
_SlibDebug(_DEBUG_, printf("ScBSSeekAlign() Exit with %s\n",
|
|
BS->EOI ? "FALSE" : "TRUE") );
|
|
return(!BS->EOI);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSSeekAlignStopAt()
|
|
** Purpose: Seeks for a byte aligned word in the bit stream
|
|
** and places the bit stream pointer right after its
|
|
** found position.
|
|
** Searches only until end_byte_pos is reached.
|
|
** Return: Returns TRUE if the word was found otherwise it returns FALSE.
|
|
*/
|
|
int ScBSSeekAlignStopAt(ScBitstream_t *BS, ScBitString_t seek_word,
|
|
int word_len, unsigned long end_byte_pos)
|
|
{
|
|
ScBSPosition_t end_bit_pos=end_byte_pos<<3;
|
|
ScBitString_t val;
|
|
const ScBitString_t maxi = ((ScBitString_t)1 << word_len) - 1;
|
|
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("ScBSSeekAlignStopAt(seek_word=0x%x, word_len=%d, end=%d)\n",
|
|
seek_word, word_len, end_byte_pos) );
|
|
if (ScBSBytePosition(BS)>=end_byte_pos)
|
|
return(FALSE);
|
|
|
|
ScBSByteAlign(BS)
|
|
if (ScBSBytePosition(BS)>=end_byte_pos)
|
|
return(FALSE);
|
|
if ((BS->CurrentBit+word_len)>end_bit_pos)
|
|
{
|
|
ScBSSkipBits(BS, (unsigned int)(end_bit_pos-BS->CurrentBit));
|
|
return(FALSE);
|
|
}
|
|
val = ScBSGetBits(BS, word_len);
|
|
_SlibDebug(_DEBUG_, _debug_getbits=FALSE );
|
|
while ((val&maxi)!=seek_word && !BS->EOI)
|
|
{
|
|
if ((BS->CurrentBit+word_len)>end_bit_pos)
|
|
{
|
|
ScBSSkipBits(BS, (unsigned int)(end_bit_pos-BS->CurrentBit));
|
|
_SlibDebug(_DEBUG_, _debug_getbits=TRUE );
|
|
return(FALSE);
|
|
}
|
|
val <<= 8;
|
|
val |= ScBSGetBits(BS, 8);
|
|
}
|
|
_SlibDebug(_DEBUG_, _debug_getbits=TRUE );
|
|
|
|
_SlibDebug(_DEBUG_, printf("ScBSSeekAlignStopAt() Exit with %s\n",
|
|
BS->EOI ? "FALSE" : "TRUE") );
|
|
return(!BS->EOI);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSSeekAlignStopBefore()
|
|
** Purpose: Seeks for a byte aligned word in the bit stream,
|
|
** if found, places the bit stream pointer right at the beginning
|
|
** of the word.
|
|
** Return: Returns TRUE if the word was found otherwise it returns FALSE.
|
|
*/
|
|
int ScBSSeekAlignStopBefore(ScBitstream_t *BS, ScBitString_t seek_word,
|
|
int word_len)
|
|
{
|
|
const int iword_len=SC_BITBUFFSZ-word_len;
|
|
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("ScBSSeekAlignStopBefore(seek_word=0x%x, word_len=%d)\n",
|
|
seek_word, word_len) );
|
|
_SlibDebug(_VERIFY_ && !word_len,
|
|
printf("ScBSSeekAlignStopBefore() word_len=0\n") );
|
|
|
|
ScBSByteAlign(BS)
|
|
_SlibDebug(_VERIFY_, _debug_start=BS->CurrentBit );
|
|
_SlibDebug(_DEBUG_, _debug_getbits=FALSE );
|
|
/* make sure there's at least word_len bits in OutBuff */
|
|
ScBSPreLoad(BS, word_len);
|
|
while ((BS->OutBuff>>iword_len)!=seek_word && !BS->EOI)
|
|
{
|
|
ScBSSkipBits(BS, 8);
|
|
ScBSPreLoad(BS, word_len);
|
|
}
|
|
_SlibDebug(_DEBUG_, _debug_getbits=TRUE );
|
|
_SlibDebug(_WARN_,
|
|
_debug_stop=BS->CurrentBit;
|
|
if ((_debug_stop-_debug_start)>word_len)
|
|
printf("ScBSSeekAlignStopBefore() Moved %d bits (%d bytes) byte pos 0x%X->0x%X\n",
|
|
_debug_stop-_debug_start, (_debug_stop-_debug_start)/8,
|
|
_debug_start/8, _debug_stop/8)
|
|
);
|
|
|
|
_SlibDebug(_DEBUG_, printf("ScBSSeekAlignStopBefore() Exit with %s\n",
|
|
BS->EOI ? "FALSE" : "TRUE") );
|
|
return(!BS->EOI);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSSeekStopBefore()
|
|
** Purpose: Seeks for a word in the bit stream,
|
|
** if found, places the bit stream pointer right at the beginning
|
|
** of the word.
|
|
** Return: Returns TRUE if the word was found otherwise it returns FALSE.
|
|
*/
|
|
int ScBSSeekStopBefore(ScBitstream_t *BS, ScBitString_t seek_word,
|
|
int word_len)
|
|
{
|
|
const int iword_len=SC_BITBUFFSZ-word_len;
|
|
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("ScBSSeekStopBefore(seek_word=0x%x, word_len=%d)\n",
|
|
seek_word, word_len) );
|
|
_SlibDebug(_VERIFY_ && !word_len,
|
|
printf("ScBSSeekStopBefore() word_len=0\n") );
|
|
|
|
_SlibDebug(_VERIFY_, _debug_start=BS->CurrentBit );
|
|
_SlibDebug(_DEBUG_, _debug_getbits=FALSE );
|
|
/* make sure there's at least word_len bits in OutBuff */
|
|
ScBSPreLoad(BS, word_len);
|
|
while ((BS->OutBuff>>iword_len)!=seek_word && !BS->EOI)
|
|
{
|
|
ScBSSkipBits(BS, 1);
|
|
ScBSPreLoad(BS, word_len);
|
|
}
|
|
_SlibDebug(_DEBUG_, _debug_getbits=TRUE );
|
|
_SlibDebug(_WARN_,
|
|
_debug_stop=BS->CurrentBit;
|
|
if ((_debug_stop-_debug_start)>word_len)
|
|
printf("ScBSSeekAlignStopBefore() Moved %d bits (%d bytes) byte pos 0x%X->0x%X\n",
|
|
_debug_stop-_debug_start, (_debug_stop-_debug_start)/8,
|
|
_debug_start/8, _debug_stop/8)
|
|
);
|
|
|
|
_SlibDebug(_DEBUG_, printf("ScBSSeekStopBefore() Exit with %s\n",
|
|
BS->EOI ? "FALSE" : "TRUE") );
|
|
return(!BS->EOI);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSSeekAlignStopBeforeW()
|
|
** Purpose: Seeks for a byte aligned word in the bit stream,
|
|
** if found, places the bit stream pointer right at the beginning
|
|
** of the word.
|
|
** Return: Returns TRUE if the word was found otherwise it returns FALSE.
|
|
**
|
|
** NB: This version uses Dolby style word loading for bitstream
|
|
*/
|
|
int ScBSSeekAlignStopBeforeW(ScBitstream_t *BS, ScBitString_t seek_word,
|
|
int word_len)
|
|
{
|
|
const int iword_len=SC_BITBUFFSZ-word_len;
|
|
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("ScBSSeekAlignStopBeforeW(seek_word=0x%x, word_len=%d)\n",
|
|
seek_word, word_len) );
|
|
_SlibDebug(_VERIFY_ && !word_len,
|
|
printf("ScBSSeekAlignStopBeforeW() word_len=0\n") );
|
|
|
|
ScBSByteAlign(BS)
|
|
_SlibDebug(_VERIFY_, _debug_start=BS->CurrentBit );
|
|
_SlibDebug(_DEBUG_, _debug_getbits=FALSE );
|
|
/* make sure there's at least word_len bits in OutBuff */
|
|
ScBSPreLoadW(BS, word_len);
|
|
while ((BS->OutBuff>>iword_len)!=seek_word && !BS->EOI)
|
|
{
|
|
ScBSSkipBitsW(BS, 8);
|
|
ScBSPreLoadW(BS, word_len);
|
|
}
|
|
_SlibDebug(_DEBUG_, _debug_getbits=TRUE );
|
|
_SlibDebug(_WARN_,
|
|
_debug_stop=BS->CurrentBit;
|
|
if ((_debug_stop-_debug_start)>word_len)
|
|
printf("ScBSSeekAlignStopBeforeW() Moved %d bits (%d bytes) byte pos 0x%X->0x%X\n",
|
|
_debug_stop-_debug_start, (_debug_stop-_debug_start)/8,
|
|
_debug_start/8, _debug_stop/8)
|
|
);
|
|
|
|
_SlibDebug(_DEBUG_, printf("ScBSSeekAlignStopBeforeW() Exit with %s\n",
|
|
BS->EOI ? "FALSE" : "TRUE") );
|
|
return(!BS->EOI);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSGetBytesStopBefore()
|
|
** Purpose: Gets all the bytes until seek_word (byte aligned)
|
|
** is encountered.
|
|
** Searches only until 'length' bytes are read.
|
|
** Return: Returns TRUE if the word was found otherwise it returns FALSE.
|
|
*/
|
|
int ScBSGetBytesStopBefore(ScBitstream_t *BS, u_char *buffer, u_int length,
|
|
u_int *ret_length, ScBitString_t seek_word,
|
|
int word_len)
|
|
{
|
|
unsigned long offset=0;
|
|
const int iword_len=SC_BITBUFFSZ-word_len;
|
|
|
|
_SlibDebug(_VERBOSE_,
|
|
printf("ScBSGetBytesStopBefore(seek_word=0x%x, word_len=%d)\n",
|
|
seek_word, word_len) );
|
|
ScBSByteAlign(BS)
|
|
ScBSPreLoad(BS, word_len);
|
|
while ((BS->OutBuff>>iword_len) != seek_word &&
|
|
offset<length && !BS->EOI)
|
|
{
|
|
*buffer = (unsigned char)ScBSGetBits(BS, 8);
|
|
buffer++;
|
|
offset++;
|
|
ScBSPreLoad(BS, word_len);
|
|
}
|
|
|
|
*ret_length=offset;
|
|
_SlibDebug(_DEBUG_,
|
|
printf("ScBSGetBytesStopBefore(ret_length=%d) Exit with %s\n",
|
|
*ret_length, (BS->EOI||offset>=length) ? "FALSE" : "TRUE") );
|
|
if (BS->EOI || offset>=length)
|
|
return(FALSE);
|
|
else
|
|
return(TRUE);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSFlush()
|
|
** Purpose: Flushes data from the buffers
|
|
*/
|
|
ScStatus_t ScBSFlush(ScBitstream_t *BS)
|
|
{
|
|
ScStatus_t stat=NoErrors;
|
|
_SlibDebug(_VERBOSE_, printf("ScBSFlush() In\n") );
|
|
if (!BS)
|
|
return(ScErrorBadPointer);
|
|
|
|
if ((BS->Mode=='w' || BS->Mode=='b') && BS->buffp>0)
|
|
{
|
|
if (BS->shift>0) /* some remaining bits in internal buffers */
|
|
{
|
|
/* byte align last bits */
|
|
ScBSAlignPutBits(BS);
|
|
if (BS->buffp>=BS->bufftop)
|
|
stat=sc_BSPutData(BS);
|
|
/* Copy the remaining bytes in OutBuff to the current buffer */
|
|
while (BS->shift>0 && BS->buffp<BS->bufftop)
|
|
{
|
|
BS->shift-=8;
|
|
BS->buff[BS->buffp++]=(unsigned char)(BS->OutBuff>>BS->shift);
|
|
}
|
|
stat=sc_BSPutData(BS);
|
|
if (BS->shift>0) /* still some bytes left */
|
|
{
|
|
while (BS->shift>0 && BS->buffp<BS->bufftop)
|
|
{
|
|
BS->shift-=8;
|
|
BS->buff[BS->buffp++]=(unsigned char)(BS->OutBuff>>BS->shift);
|
|
}
|
|
stat=sc_BSPutData(BS);
|
|
}
|
|
}
|
|
else
|
|
stat=sc_BSPutData(BS);
|
|
}
|
|
ScBSReset(BS); /* release and re-initialize buffer pointers */
|
|
_SlibDebug(_VERBOSE_, printf("ScBSFlush() Out\n") );
|
|
return(stat);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSResetCounters()
|
|
** Purpose: Resets the bit position counters to zero
|
|
*/
|
|
ScStatus_t ScBSResetCounters(ScBitstream_t *BS)
|
|
{
|
|
if (!BS)
|
|
return(ScErrorBadPointer);
|
|
BS->CurrentBit=0;
|
|
return(NoErrors);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSFlushSoon()
|
|
** Purpose: Flushes data from the buffers at the next
|
|
** 32 or 64 bit boundary
|
|
*/
|
|
ScStatus_t ScBSFlushSoon(ScBitstream_t *BS)
|
|
{
|
|
ScStatus_t stat=NoErrors;
|
|
_SlibDebug(_VERBOSE_, printf("ScBSFlushSoon()\n") );
|
|
if (!BS)
|
|
return(ScErrorBadPointer);
|
|
|
|
if (BS->Mode=='w' || BS->Mode=='b')
|
|
BS->Flush=TRUE;
|
|
return(stat);
|
|
}
|
|
|
|
/*
|
|
** Name: ScBSDestroy()
|
|
** Purpose: Destroys a bitstream (Closes and frees associated memory)
|
|
** created using ScBSCreateFromBufferQueue() or
|
|
** ScBSCreateFromFile()
|
|
*/
|
|
ScStatus_t ScBSDestroy(ScBitstream_t *BS)
|
|
{
|
|
ScStatus_t stat=NoErrors;
|
|
_SlibDebug(_VERBOSE_, printf("ScBSDestroy\n") );
|
|
if (!BS)
|
|
return(ScErrorBadPointer);
|
|
|
|
/* We won't flush automatically
|
|
if (BS->Mode=='w' || BS->Mode=='b')
|
|
ScBSFlush(BS);
|
|
*/
|
|
if (BS->RdBufAllocated)
|
|
ScFree(BS->RdBuf);
|
|
ScFree(BS);
|
|
return(stat);
|
|
}
|
|
|
|
/*********************** Buffer/Image Queue Management ***********************/
|
|
/* */
|
|
/* ScBufQueueCreate() - Create a buffer queue */
|
|
/* ScBufQueueDestroy() - Destroy a buffer queue */
|
|
/* ScBufQueueAdd() - Add a buffer to tail of a queue */
|
|
/* ScBufQueueRemove() - Remove the buffer at the head of a queue */
|
|
/* ScBufQueueGetNum() - Return number of buffers in a queue */
|
|
/* ScBufQueueGetHead() - Return info about buffer at head of a queue */
|
|
/* */
|
|
/*****************************************************************************/
|
|
|
|
|
|
ScStatus_t ScBufQueueCreate(ScQueue_t **Q)
|
|
{
|
|
if ((*Q = (ScQueue_t *)ScAlloc(sizeof(ScQueue_t))) == NULL)
|
|
return(ScErrorMemory);
|
|
(*Q)->NumBufs = 0;
|
|
(*Q)->head = (*Q)->tail = NULL;
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueCreate() Q=%p\n",*Q) );
|
|
return(NoErrors);
|
|
}
|
|
|
|
ScStatus_t ScBufQueueDestroy(ScQueue_t *Q)
|
|
{
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueDestroy(Q=%p)\n",Q) );
|
|
if (!Q)
|
|
return(ScErrorBadArgument);
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueDestroy()\n") );
|
|
|
|
while (ScBufQueueGetNum(Q))
|
|
ScBufQueueRemove(Q);
|
|
|
|
ScFree(Q);
|
|
return(NoErrors);
|
|
}
|
|
|
|
ScStatus_t ScBufQueueAdd(ScQueue_t *Q, u_char *Data, int Size)
|
|
{
|
|
struct ScBuf_s *b;
|
|
|
|
if (!Q)
|
|
return(ScErrorBadPointer);
|
|
|
|
if ((b = (struct ScBuf_s *)ScAlloc(sizeof(struct ScBuf_s))) == NULL)
|
|
return(ScErrorMemory);
|
|
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueAdd(Q=%p, Data=0x%p, Size=%d)\n",
|
|
Q,Data,Size) );
|
|
b->Data = Data;
|
|
b->Size = Size;
|
|
b->Prev = NULL;
|
|
|
|
if (!Q->tail)
|
|
Q->tail = Q->head = b;
|
|
else {
|
|
Q->tail->Prev = b;
|
|
Q->tail = b;
|
|
}
|
|
Q->NumBufs++;
|
|
return(NoErrors);
|
|
}
|
|
|
|
ScStatus_t ScBufQueueAddExt(ScQueue_t *Q, u_char *Data, int Size, int Type)
|
|
{
|
|
struct ScBuf_s *b;
|
|
|
|
if (!Q)
|
|
return(ScErrorBadPointer);
|
|
|
|
if ((b = (struct ScBuf_s *)ScAlloc(sizeof(struct ScBuf_s))) == NULL)
|
|
return(ScErrorMemory);
|
|
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueAdd(Q=%p, Data=0x%p, Size=%d)\n",
|
|
Q,Data,Size) );
|
|
b->Data = Data;
|
|
b->Size = Size;
|
|
b->Type = Type;
|
|
b->Prev = NULL;
|
|
|
|
if (!Q->tail)
|
|
Q->tail = Q->head = b;
|
|
else {
|
|
Q->tail->Prev = b;
|
|
Q->tail = b;
|
|
}
|
|
Q->NumBufs++;
|
|
return(NoErrors);
|
|
}
|
|
|
|
ScStatus_t ScBufQueueRemove(ScQueue_t *Q)
|
|
{
|
|
struct ScBuf_s *head;
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueRemove(Q=%p)\n",Q) );
|
|
|
|
if (!Q)
|
|
return(ScErrorBadPointer);
|
|
|
|
if (!(head = Q->head))
|
|
return(ScErrorBadQueueEmpty);
|
|
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueRemove() Data=%p Size=%d\n",
|
|
Q->head->Data,Q->head->Size) );
|
|
Q->head = head->Prev;
|
|
if (!Q->head)
|
|
Q->tail = NULL;
|
|
Q->NumBufs--;
|
|
ScFree(head);
|
|
return(NoErrors);
|
|
}
|
|
|
|
int ScBufQueueGetNum(ScQueue_t *Q)
|
|
{
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueGetNum(Q=%p) num=%d\n",
|
|
Q, Q ? Q->NumBufs : 0) );
|
|
return(Q ? Q->NumBufs : 0);
|
|
}
|
|
|
|
ScStatus_t ScBufQueueGetHead(ScQueue_t *Q, u_char **Data, int *Size)
|
|
{
|
|
if (!Q || !Q->head) {
|
|
if (Data) *Data = NULL;
|
|
if (Size) *Size = 0;
|
|
return(NoErrors);
|
|
}
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueGetHead() Data=%p Size=%d\n",
|
|
Q->head->Data,Q->head->Size) );
|
|
if (Data) *Data = Q->head->Data;
|
|
if (Size) *Size = Q->head->Size;
|
|
return(NoErrors);
|
|
}
|
|
|
|
ScStatus_t ScBufQueueGetHeadExt(ScQueue_t *Q, u_char **Data, int *Size,
|
|
int *Type)
|
|
{
|
|
if (!Q || !Q->head) {
|
|
if (Data) *Data = NULL;
|
|
if (Size) *Size = 0;
|
|
if (Type) *Type = 0;
|
|
return(NoErrors);
|
|
}
|
|
_SlibDebug(_QUEUE_, printf("ScBufQueueGetHeadExt() Data=%p Size=%d Type=%d\n",
|
|
Q->head->Data,Q->head->Size,Q->head->Type) );
|
|
if (Data) *Data = Q->head->Data;
|
|
if (Size) *Size = Q->head->Size;
|
|
if (Type) *Type = Q->head->Type;
|
|
return(NoErrors);
|
|
}
|
|
|