mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-17 16:35:45 -04:00
Initial community commit
This commit is contained in:
410
Src/libvp6/corelibs/sal/generic/circlebuffer.c
Normal file
410
Src/libvp6/corelibs/sal/generic/circlebuffer.c
Normal file
@ -0,0 +1,410 @@
|
||||
|
||||
|
||||
#include "circlebuffer.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* memory copy */
|
||||
#include "duck_mem.h"
|
||||
|
||||
|
||||
/* this is just a debugging trick so that we can "see" the free space */
|
||||
void* circleread_memcpy(void* dst, void* src, int64_t count);
|
||||
void* circleread_memcpy(void* dst, void* src, int64_t count)
|
||||
{
|
||||
return duck_memcpy64(dst, src, count);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void CircleReport(const CircleBuffer_t* cb, const char* title)
|
||||
{
|
||||
printf("-----(%s)------\n", title);
|
||||
printf("max Size cb = %ld\n", cb->bufSize);
|
||||
printf("fills at = %ld\n", cb->bufSize * cb->percent / 100 );
|
||||
printf("Current amount = %ld, level = %ld\n", cb->count, cb->count * 100 / cb->bufSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ForwardBuffer(CircleBuffer_t* cb, int64_t len)
|
||||
{
|
||||
if (len >= (int64_t)cb->count)
|
||||
return -1;
|
||||
|
||||
if ( (cb->head + len) < cb->bufSize )
|
||||
cb->head += (int)len;
|
||||
|
||||
else
|
||||
cb->head = (int)len - (cb->bufSize - cb->head);
|
||||
|
||||
cb->count -= (int)len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int RewindBuffer(CircleBuffer_t* cb, int64_t len)
|
||||
{
|
||||
if (len >= (int64_t)(cb->bufSize - cb->count) )
|
||||
return -1; /* not enough history in buffer ! */
|
||||
|
||||
if (cb->head <= (size_t)len)
|
||||
{
|
||||
if (cb->wrapped == 0)
|
||||
return -1;
|
||||
|
||||
cb->head = cb->bufSize - ((int)len - cb->head);
|
||||
cb->count += (int)len;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cb->head -= (int)len;
|
||||
cb->count += (int)len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void destroyCircleBuffer(CircleBuffer_t* cb)
|
||||
{
|
||||
assert(cb);
|
||||
if (cb->buffer)
|
||||
free(cb->buffer);
|
||||
|
||||
if (cb->maxChunk)
|
||||
free(cb->maxChunk);
|
||||
}
|
||||
|
||||
|
||||
int resetCircleBuffer(CircleBuffer_t* cb)
|
||||
{
|
||||
cb->count = 0;
|
||||
cb->bytesConsumed = 0;
|
||||
cb->wrapped = 0;
|
||||
cb->starvedBytes = 0;
|
||||
cb->starvedRequests = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int initCircleBuffer(
|
||||
CircleBuffer_t* cb,
|
||||
size_t countRecords,
|
||||
int percent,
|
||||
size_t maxChunk,
|
||||
FuncLock_t lock,
|
||||
FuncLock_t unlock
|
||||
)
|
||||
{
|
||||
assert(cb);
|
||||
|
||||
cb->buffer = (unsigned char * ) calloc(1, countRecords);
|
||||
|
||||
cb->maxChunk = (unsigned char *) calloc(1, maxChunk);
|
||||
cb->maxChunkLen = maxChunk;
|
||||
|
||||
if (cb->buffer)
|
||||
{
|
||||
cb->head = cb->count = 0;
|
||||
cb->balance = 0;
|
||||
cb->bufSize = countRecords;
|
||||
cb->bytesConsumed = 0;
|
||||
cb->muted = false;
|
||||
cb->percent = percent;
|
||||
cb->wrapped = 0;
|
||||
cb->lock = lock;
|
||||
cb->unlock = unlock;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1; /* error */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* return zero if plenty of room and success */
|
||||
/*-------------------------------------------*/
|
||||
/* free space nested in the middle of the buffer is consider endSpace */
|
||||
/* and when free space nested in middle, startSpace is considered to be zero */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int addToCircleBuffer(CircleBuffer_t* cb, void* data, size_t requestSpace)
|
||||
{
|
||||
int64_t freeSpace; /* count total free space in buffer */
|
||||
int64_t head = cb->head; /* offset start of valid data */
|
||||
int64_t tail = (cb->head + cb->count) % cb->bufSize; /* offest first free byte after valid data */
|
||||
int64_t endSpace;
|
||||
|
||||
freeSpace = cb->bufSize - cb->count;
|
||||
|
||||
/* if not enough room to do the add */
|
||||
/*----------------------------------*/
|
||||
if (requestSpace > freeSpace)
|
||||
{
|
||||
assert(0);
|
||||
return CB_FULL;
|
||||
}
|
||||
|
||||
|
||||
endSpace = cb->bufSize - tail;
|
||||
|
||||
if (tail >= head && requestSpace > endSpace) /* additional data write will wrap */
|
||||
{
|
||||
duck_memcpy64(&cb->buffer[tail], data, endSpace);
|
||||
duck_memcpy64(
|
||||
cb->buffer,
|
||||
(unsigned char *)data+endSpace,
|
||||
requestSpace - endSpace);
|
||||
}
|
||||
else /* existing data wrapped around from end of buffer through beginning of buffer. */
|
||||
{
|
||||
memcpy(&cb->buffer[tail], data, requestSpace);
|
||||
}
|
||||
|
||||
cb->count += requestSpace;
|
||||
cb->balance += 1;
|
||||
|
||||
return 0; /* -1 will mean error,m zero is OK */
|
||||
}
|
||||
|
||||
/* get info need so we can write direct as in memcpy into the circle buffer */
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void FreeWrapless(const CircleBuffer_t* cb, void* handle, int64_t* sizeWrapless)
|
||||
{
|
||||
int64_t tail = (cb->head + cb->count) % cb->bufSize;
|
||||
|
||||
if ((cb->head + cb->count) < cb->bufSize)
|
||||
{
|
||||
*((void **) handle) = &cb->buffer[tail];
|
||||
*sizeWrapless = (cb->bufSize -(cb->head + cb->count));
|
||||
}
|
||||
else
|
||||
{
|
||||
*((void **) handle) = &cb->buffer[tail];
|
||||
*sizeWrapless = (cb->bufSize - cb->count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Please clone this sucker from readFromCircleBuffer */
|
||||
int accessCircleBuffer(CircleBuffer_t* cb, void* handle1, size_t requestSize)
|
||||
{
|
||||
int64_t head = cb->head;
|
||||
int64_t tail = (cb->head + cb->count) % cb->bufSize;
|
||||
void** handle = (void **) handle1;
|
||||
void* dest = *handle;
|
||||
|
||||
if (requestSize <= 0)
|
||||
{
|
||||
return requestSize;
|
||||
}
|
||||
|
||||
if (cb->count < requestSize)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (tail > head) /* the data does not wrap ! */
|
||||
{
|
||||
*handle = &cb->buffer[head];
|
||||
}
|
||||
else /* the current data does wrap */
|
||||
{
|
||||
/* but our read does not wrap */
|
||||
if (head + requestSize < cb->bufSize)
|
||||
{
|
||||
*handle = &cb->buffer[head];
|
||||
}
|
||||
else if (head + requestSize == cb->bufSize)
|
||||
{
|
||||
*handle = &cb->buffer[head];
|
||||
}
|
||||
else /* our read will wrap ! */
|
||||
{
|
||||
int64_t temp = cb->bufSize - head;
|
||||
dest = cb->maxChunk;
|
||||
|
||||
assert(cb->maxChunkLen >= requestSize);
|
||||
|
||||
circleread_memcpy(
|
||||
dest,
|
||||
&cb->buffer[head],
|
||||
temp);
|
||||
circleread_memcpy(
|
||||
((unsigned char *) dest) + temp,
|
||||
cb->buffer,
|
||||
requestSize - temp);
|
||||
*handle = dest;
|
||||
}
|
||||
}
|
||||
|
||||
cb->head = (cb->head + requestSize) % cb->bufSize;
|
||||
cb->count -= requestSize;
|
||||
|
||||
cb->bytesConsumed += requestSize;
|
||||
cb->balance -= 1;
|
||||
|
||||
return requestSize; /* records (16 bit or maybe other in future) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* return count read , or -1 if not enough data */
|
||||
/*----------------------------------------------*/
|
||||
int readFromCircleBuffer(CircleBuffer_t* cb, void* dest, size_t requestSize)
|
||||
{
|
||||
int64_t head = cb->head;
|
||||
int64_t tail = (cb->head + cb->count) % cb->bufSize;
|
||||
|
||||
if (cb->count < requestSize)
|
||||
{
|
||||
requestSize = cb->count; /* Give them what we have */
|
||||
}
|
||||
|
||||
if (requestSize <= 0)
|
||||
{
|
||||
return (int)requestSize;
|
||||
}
|
||||
|
||||
if (tail > head) /* the data does not wrap ! */
|
||||
{
|
||||
circleread_memcpy(dest, &cb->buffer[head], requestSize);
|
||||
}
|
||||
else /* the current data does wrap */
|
||||
{
|
||||
/* but our read does not wrap */
|
||||
if (head + requestSize < cb->bufSize)
|
||||
{
|
||||
circleread_memcpy(dest, &cb->buffer[head], requestSize);
|
||||
}
|
||||
else if (head + requestSize == cb->bufSize)
|
||||
{
|
||||
circleread_memcpy(dest, &cb->buffer[head], requestSize);
|
||||
memset(&cb->buffer[head], 0, (size_t)requestSize); /* optional, debug */
|
||||
}
|
||||
else /* our read will wrap ! */
|
||||
{
|
||||
int64_t temp = cb->bufSize - head;
|
||||
circleread_memcpy(
|
||||
dest,
|
||||
&cb->buffer[head],
|
||||
temp);
|
||||
circleread_memcpy(
|
||||
((unsigned char *) dest) + temp,
|
||||
cb->buffer,
|
||||
requestSize - temp);
|
||||
}
|
||||
}
|
||||
|
||||
cb->head = (cb->head + requestSize) % cb->bufSize;
|
||||
cb->count -= requestSize;
|
||||
|
||||
cb->bytesConsumed += requestSize;
|
||||
cb->balance -= 1;
|
||||
|
||||
return (int)requestSize; /* records (16 bit or maybe other in future) */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void testCircleBuffer()
|
||||
{
|
||||
CircleBuffer_t temp;
|
||||
size_t bufSize = 256;
|
||||
const size_t maxInput = 256*3;
|
||||
size_t count = 0;
|
||||
size_t t;
|
||||
int i;
|
||||
const int maxRandom = 32;
|
||||
size_t chunkOut = 30;
|
||||
|
||||
CircleRecord_t data[256*3];
|
||||
|
||||
initCircleBuffer(&temp, bufSize, 75, 256, 0, 0);
|
||||
|
||||
/* who cares ... take the default seed value. */
|
||||
while (count < maxInput || temp.count > chunkOut)
|
||||
{
|
||||
t = rand();
|
||||
|
||||
/* for whatever reason this seems to be a 16 bit random number */
|
||||
t = t / ( 2 << (16 - 7) ) ;
|
||||
|
||||
for(i = 0; i < (int)t; i++)
|
||||
{
|
||||
data[i] = (unsigned char ) ( count + i );
|
||||
}
|
||||
|
||||
if (
|
||||
((temp.bufSize - temp.count) >= t*sizeof(short)+1) &&
|
||||
(count < (maxInput - maxRandom))
|
||||
) /* add 1 to keep buffer being completely filled */
|
||||
{
|
||||
int64_t tail = (temp.head + temp.count) % temp.bufSize;
|
||||
addToCircleBuffer(&temp, data, t);
|
||||
printf("Add to buffer count = %ld. head = %ld, tail = %ld\n", t, temp.head, tail);
|
||||
count += t;
|
||||
}
|
||||
else /* not enough space in buffer, try to empty some out */
|
||||
{
|
||||
int r;
|
||||
r = readFromCircleBuffer(&temp, data, chunkOut);
|
||||
|
||||
if (r >= 0)
|
||||
{
|
||||
int64_t tail = (temp.head + temp.count) % temp.bufSize;
|
||||
for(i = 0; i < r; i++)
|
||||
printf("%ld ", data[i]);
|
||||
|
||||
printf("\nRead from buffer. head = %ld, tail = %ld\n", temp.head, tail);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} /* while we have not accumulated a large eough test ... */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int CirclePercent(CircleBuffer_t* cb)
|
||||
{
|
||||
return (int)(cb->count * 100 / cb->bufSize);
|
||||
}
|
||||
|
||||
int CircleAtLevel(CircleBuffer_t* cb)
|
||||
{
|
||||
return (int)(cb->count * 100 / cb->bufSize) >= cb->percent;
|
||||
}
|
||||
|
||||
int CircleOverLevel(CircleBuffer_t* cb)
|
||||
{
|
||||
return (int)(cb->count * 100 / cb->bufSize) > cb->percent;
|
||||
}
|
99
Src/libvp6/corelibs/sal/generic/circlebuffer.h
Normal file
99
Src/libvp6/corelibs/sal/generic/circlebuffer.h
Normal file
@ -0,0 +1,99 @@
|
||||
|
||||
#if !defined(_circlebuffer_h)
|
||||
#define _circlebuffer_h
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
typedef __int64 int64_t;
|
||||
#elif defined(__POWERPC) || defined(__APPLE)
|
||||
#include <ppc/types.h>
|
||||
#else
|
||||
typedef long long int64_t;
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#pragma bool on
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
typedef unsigned char CircleRecord_t;
|
||||
|
||||
|
||||
|
||||
typedef void (*FuncLock_t)() ;
|
||||
|
||||
/* assume that assert, alerts, messages to go off before this ever is allowed to fill */
|
||||
/*------------------------------------------------------------------------------------*/
|
||||
typedef struct CircleBuf_tt
|
||||
{
|
||||
size_t head; /* points to start of usable data in buffer */
|
||||
size_t count;
|
||||
size_t bufSize;
|
||||
int64_t bytesConsumed;
|
||||
size_t recordSize;
|
||||
size_t userData; /* might store actual recordsize */
|
||||
int balance;
|
||||
CircleRecord_t* buffer; /* 10 seconds of 16 bit stereo nice quality */
|
||||
unsigned char* maxChunk;
|
||||
size_t maxChunkLen;
|
||||
int percent; /* level where buffer considered stable */
|
||||
int wrapped; /* non-zero if data has wrapped at least once */
|
||||
int muted;
|
||||
|
||||
FuncLock_t lock; /* in case there could be competition for any members */
|
||||
FuncLock_t unlock; /* in case there could be competition for any members */
|
||||
|
||||
int starvedBytes; /* how many bytes we had to "conjure up" because we were empty (debug) */
|
||||
int starvedRequests; /* how many request we honored when we have been in a starved state (debug) */
|
||||
|
||||
} CircleBuffer_t;
|
||||
|
||||
|
||||
void testCircleBuffer(void);
|
||||
void destroyCircleBuffer(CircleBuffer_t* cb);
|
||||
int initCircleBuffer(CircleBuffer_t* cb, size_t size, int percent, size_t maxChunk, FuncLock_t lock, FuncLock_t unlock);
|
||||
int addToCircleBuffer(CircleBuffer_t* cb, void* data, size_t count);
|
||||
int readFromCircleBuffer(CircleBuffer_t* cb, void* dest, size_t count);
|
||||
int accessCircleBuffer(CircleBuffer_t* cb, void* dest, size_t count);
|
||||
void FreeWrapless(const CircleBuffer_t* cb, void* handle, size_t* sizeWrapless);
|
||||
int resetCircleBuffer(CircleBuffer_t* cb);
|
||||
int RewindBuffer(CircleBuffer_t* cb, int64_t len);
|
||||
int ForwardBuffer(CircleBuffer_t* cb, int64_t len);
|
||||
|
||||
|
||||
|
||||
void CircleReport(const CircleBuffer_t* cb, const char* title);
|
||||
|
||||
|
||||
|
||||
int CirclePercent(CircleBuffer_t* cb);
|
||||
|
||||
int CircleAtLevel(CircleBuffer_t* cb);
|
||||
|
||||
int CircleOverLevel(CircleBuffer_t* cb);
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
CB_NOERR = 0, /* OK */
|
||||
CB_FULL = -1, /* Buffer overflow */
|
||||
CB_MAX_LEVEL = -2, /* Buffer is over target full level (percent) */
|
||||
CB_MIN_LEVEL = -3, /* Buffer is under target min level (percent) */
|
||||
CB_EMPTY = -4 /* Buffer is empty */
|
||||
} CB_Err_t;
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
130
Src/libvp6/corelibs/sal/generic/duck_io.c
Normal file
130
Src/libvp6/corelibs/sal/generic/duck_io.c
Normal file
@ -0,0 +1,130 @@
|
||||
/***********************************************\
|
||||
??? duck_io.c
|
||||
\***********************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include "duck_io.h"
|
||||
#include "duck_io_http.h"
|
||||
#include "duck_io_file.h"
|
||||
#include "duck_hfb.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#define MAKE_FOUR_CC(b1, b2, b3, b4 ) \
|
||||
((b4 << 24) | (b3 << 16) | (b2 << 8) | (b1 << 0))
|
||||
|
||||
int duck_readFinished(int han, int flag)
|
||||
{
|
||||
(void)han;
|
||||
(void)flag;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
bool g_isHttp = false;
|
||||
|
||||
int duck_open(const char *name, unsigned long userData)
|
||||
{
|
||||
if (strstr(name, "http://"))
|
||||
return duck_open_http(name, userData);
|
||||
else
|
||||
return duck_open_file(name, userData);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void duck_close(int handle)
|
||||
{
|
||||
unsigned long schemeCC = *((unsigned long *) handle);
|
||||
|
||||
if (schemeCC == MAKE_FOUR_CC('h','t','t','p'))
|
||||
duck_close_http(handle);
|
||||
else if (schemeCC == MAKE_FOUR_CC('f','i','l','e'))
|
||||
duck_close_file(handle);
|
||||
else
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
int duck_read(int handle,unsigned char *buffer,int bytes)
|
||||
{
|
||||
unsigned long schemeCC = *((unsigned long *) handle);
|
||||
|
||||
if (schemeCC == MAKE_FOUR_CC('h','t','t','p'))
|
||||
return duck_read_http(handle, buffer, bytes);
|
||||
else if (schemeCC == MAKE_FOUR_CC('f','i','l','e'))
|
||||
return duck_read_file(handle, buffer, bytes);
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int duck_read_blocking(int handle,unsigned char *buffer,int bytes)
|
||||
{
|
||||
unsigned long schemeCC = *((unsigned long *) handle);
|
||||
|
||||
if (schemeCC == MAKE_FOUR_CC('h','t','t','p'))
|
||||
return duck_read_blocking_http(handle, buffer, bytes);
|
||||
else if (schemeCC == MAKE_FOUR_CC('f','i','l','e'))
|
||||
return duck_read_file(handle, buffer, bytes);
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int64_t duck_seek(int handle,int64_t offset,int origin)
|
||||
{
|
||||
|
||||
unsigned long schemeCC = *((unsigned long *) handle);
|
||||
|
||||
if (schemeCC == MAKE_FOUR_CC('h','t','t','p'))
|
||||
return duck_seek_http(handle, offset, origin);
|
||||
else if (schemeCC == MAKE_FOUR_CC('f','i','l','e'))
|
||||
return duck_seek_file(handle, offset, origin);
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int duck_name(int handle, char name[], size_t maxLen)
|
||||
{
|
||||
unsigned long schemeCC = *((unsigned long *) handle);
|
||||
|
||||
if (schemeCC == MAKE_FOUR_CC('h','t','t','p'))
|
||||
return duck_name_http(handle, name, maxLen);
|
||||
else if (schemeCC == MAKE_FOUR_CC('f','i','l','e'))
|
||||
return duck_name_file(handle, name, maxLen);
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t duck_available_data(int handle)
|
||||
{
|
||||
unsigned long schemeCC = *((unsigned long *) handle);
|
||||
|
||||
if (schemeCC == MAKE_FOUR_CC('h','t','t','p'))
|
||||
return duck_available_data_http(handle);
|
||||
else if (schemeCC == MAKE_FOUR_CC('f','i','l','e'))
|
||||
return duck_available_data_file(handle);
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
}
|
224
Src/libvp6/corelibs/sal/generic/duck_io_file.c
Normal file
224
Src/libvp6/corelibs/sal/generic/duck_io_file.c
Normal file
@ -0,0 +1,224 @@
|
||||
/***********************************************\
|
||||
??? duck_io.c
|
||||
\***********************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include "duck_io_file.h"
|
||||
#include "duck_hfb.h"
|
||||
#include "duck_io.h"
|
||||
#include "duck_mem.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//int read_count;
|
||||
|
||||
#define MAKE_FOUR_CC(b1, b2, b3, b4 ) \
|
||||
((b4 << 24) | (b3 << 16) | (b2 << 8) | (b1 << 0))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned long scheme; /* contains FILE */
|
||||
#if defined(_WIN32)
|
||||
int fileDescriptor; /* used to be the handle */
|
||||
#else
|
||||
FILE* fileDescriptor; /* used to be the handle */
|
||||
#endif
|
||||
char fname[512];
|
||||
int64_t fileLength;
|
||||
char errorString[256];
|
||||
SAL_ERR lastErrorCode;
|
||||
|
||||
} FileScheme_t;
|
||||
|
||||
|
||||
/* Add the decoration to avoid name collisions in the case where we want to include */
|
||||
/* a forking version of duck_io that calls duck_io_file or duck_io_http */
|
||||
/* The user of this service should not need to compile and link all three files */
|
||||
/* duck_io (abstract forker) duck_io_file and duck_io_http. */
|
||||
#define DECORATE(x) x##_file
|
||||
|
||||
|
||||
/* Sets an error code and message */
|
||||
static int SetError(int handle, SAL_ERR code, const char* appendMsg)
|
||||
{
|
||||
FileScheme_t* fileObj = (FileScheme_t *) handle;
|
||||
|
||||
const char* decode = SalErrText(code);
|
||||
if (decode)
|
||||
{
|
||||
strcpy(fileObj->errorString, decode);
|
||||
fileObj->lastErrorCode = code;
|
||||
if (appendMsg)
|
||||
{
|
||||
strcat(fileObj->errorString, " : ");
|
||||
strcat(fileObj->errorString, appendMsg);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
return SAL_ERROR; // DEFAULT ERROR
|
||||
}
|
||||
|
||||
|
||||
int DECORATE(duck_open)(const char *name, unsigned long userData)
|
||||
{
|
||||
FileScheme_t* const fileObj = (FileScheme_t *) duck_calloc(1,sizeof(FileScheme_t), DMEM_GENERAL);
|
||||
const ReOpen_t* const openData = (ReOpen_t*) userData;
|
||||
|
||||
fileObj->scheme = MAKE_FOUR_CC('f','i','l','e');
|
||||
|
||||
assert(name);
|
||||
assert(strlen(name) < sizeof(fileObj->fname));
|
||||
strcpy(fileObj->fname,name);
|
||||
|
||||
#if defined(_WIN32)
|
||||
fileObj->fileDescriptor = _open(name, _O_RDONLY | _O_BINARY);
|
||||
|
||||
if(fileObj->fileDescriptor == -1)
|
||||
return SetError((int)fileObj, SAL_ERR_FILE_OPEN_FAILED, 0);
|
||||
#else
|
||||
fileObj->fileDescriptor = fopen(name, "rb");
|
||||
|
||||
if(fileObj->fileDescriptor == 0)
|
||||
return SetError((int)fileObj, SAL_ERR_FILE_OPEN_FAILED, 0);;
|
||||
#endif
|
||||
|
||||
fileObj->fileLength = duck_seek((int) fileObj, 0, SEEK_END);
|
||||
|
||||
duck_seek((int) fileObj, 0, SEEK_SET);
|
||||
|
||||
if(openData)
|
||||
duck_seek_file((int) fileObj, openData->offset, SEEK_SET);
|
||||
|
||||
return (int)fileObj;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void DECORATE(duck_close)(int handle)
|
||||
{
|
||||
FileScheme_t* fileObj = (FileScheme_t *) handle;
|
||||
|
||||
#if defined(_WIN32)
|
||||
_close(fileObj->fileDescriptor);
|
||||
#else
|
||||
fclose(fileObj->fileDescriptor);
|
||||
#endif
|
||||
|
||||
if (fileObj)
|
||||
{
|
||||
duck_free(fileObj);
|
||||
fileObj = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int DECORATE(duck_read_blocking)(int handle,unsigned char *buffer,int bytes)
|
||||
{
|
||||
return DECORATE(duck_read)(handle, buffer, bytes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int DECORATE(duck_read)(int handle,unsigned char *buffer,int bytes)
|
||||
{
|
||||
int x;
|
||||
FileScheme_t* fileObj = (FileScheme_t *) handle;
|
||||
|
||||
if (buffer == NULL){
|
||||
duck_seek_file((int ) fileObj->fileDescriptor,bytes,SEEK_CUR);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
#if defined(_WIN32)
|
||||
x = _read(fileObj->fileDescriptor, buffer, (unsigned int) bytes);
|
||||
if (x == -1L)
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
#else
|
||||
x = fread(buffer, sizeof(char) , (size_t) bytes, fileObj->fileDescriptor);
|
||||
if (x < bytes)
|
||||
{
|
||||
assert(x == bytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return x ;
|
||||
}
|
||||
|
||||
|
||||
int64_t DECORATE(duck_seek)(int handle, int64_t offset, int origin)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
int64_t tellNo = 0;
|
||||
FileScheme_t* fileObj = (FileScheme_t *) handle;
|
||||
|
||||
_lseeki64(fileObj->fileDescriptor,offset,origin);
|
||||
|
||||
tellNo = _telli64(fileObj->fileDescriptor);
|
||||
|
||||
return tellNo ;
|
||||
#else
|
||||
int64_t tellNo = 0;
|
||||
FileScheme_t* fileObj = 0;
|
||||
assert(sizeof(off_t) == sizeof(int64_t));
|
||||
fileObj = (FileScheme_t *) handle;
|
||||
|
||||
fseeko(fileObj->fileDescriptor,(off_t) offset,origin);
|
||||
|
||||
tellNo = (int64_t) ftello(fileObj->fileDescriptor);
|
||||
|
||||
return tellNo ;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
int DECORATE(duck_name)(int handle, char fname[], size_t maxLen)
|
||||
{
|
||||
FileScheme_t* fileObj = (FileScheme_t *) handle;
|
||||
|
||||
if (strlen(fileObj->fname) < maxLen)
|
||||
strcpy(fname, fileObj->fname);
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t DECORATE(duck_available_data)(int handle)
|
||||
{
|
||||
FileScheme_t* fileObj = (FileScheme_t *) handle;
|
||||
#if defined(_WIN32)
|
||||
return fileObj->fileLength - _telli64(fileObj->fileDescriptor);
|
||||
#else
|
||||
return fileObj->fileLength - (int64_t) ftello(fileObj->fileDescriptor);
|
||||
#endif
|
||||
}
|
902
Src/libvp6/corelibs/sal/generic/duck_io_http.c
Normal file
902
Src/libvp6/corelibs/sal/generic/duck_io_http.c
Normal file
@ -0,0 +1,902 @@
|
||||
/***********************************************\
|
||||
??? duck_io.c
|
||||
\***********************************************/
|
||||
#ifdef _WIN32
|
||||
#pragma warning(push,3)
|
||||
#endif
|
||||
|
||||
#include "duck_io_http.h"
|
||||
#include "duck_mem.h"
|
||||
#include "on2_timer.h"
|
||||
#include "circlebuffer.h"
|
||||
#include "duck_io.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
extern "C" {
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <sstream>
|
||||
#include <limits.h>
|
||||
|
||||
|
||||
#define DEFAULT_CBSIZE 512 * 1024
|
||||
|
||||
#define DECORATE(x) x##_http
|
||||
|
||||
|
||||
|
||||
int duck_sal_fill(void * handle, bool blocking, size_t maxFill);
|
||||
|
||||
|
||||
//#include "debug.h" // This can be removed
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(pop)
|
||||
#pragma warning(disable:4706) /* assignment in conditional expression */
|
||||
#pragma warning(disable:4514) /* matt made me do it */
|
||||
const char i64Fmt[] = "%I64d";
|
||||
#else
|
||||
const char i64Fmt[] = "%lld";
|
||||
int WSAGetLastError()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAKE_FOUR_CC(b1, b2, b3, b4 ) \
|
||||
((b4 << 24) | (b3 << 16) | (b2 << 8) | (b1 << 0))
|
||||
|
||||
typedef struct _DuckHttp_temp
|
||||
{
|
||||
unsigned long scheme;
|
||||
std::string url;
|
||||
std::string urlExtended;
|
||||
|
||||
#if defined(_WIN32)
|
||||
SOCKET socket;
|
||||
#else
|
||||
int socket;
|
||||
#endif
|
||||
|
||||
SAL_ERR lastErrorCode;
|
||||
std::ostringstream errorString;
|
||||
|
||||
|
||||
|
||||
/* milliseconds to wait before disconnecting from server */
|
||||
unsigned int timeOut;
|
||||
|
||||
/* Assuming 2k is the max size of an http header */
|
||||
char httpHeader[2 * 1024];
|
||||
|
||||
int64_t contentLen; // Size of the movie
|
||||
int headerSize; // Size of the http header
|
||||
int xtraData; // Amout of movie data recv'd from the http header recv
|
||||
int64_t totalRead; // Position in file
|
||||
CircleBuffer_t cBuffer;
|
||||
int cbSize; // Circular buffer size
|
||||
|
||||
} DuckHttp_t;
|
||||
|
||||
|
||||
|
||||
/* Returns size of movie as parsed from the http header */
|
||||
int64_t duck_content_len(void* handle)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
if (httpObj == 0)
|
||||
return -1;
|
||||
|
||||
return httpObj->contentLen;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void* duck_get_buffer(void *handle)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
return (void *) &httpObj->cBuffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Checks to see if any errors occured in recv */
|
||||
int isDataAvailable(int bytesReceived)
|
||||
{
|
||||
(void ) bytesReceived; // for warning supression
|
||||
|
||||
#ifdef WIN32
|
||||
if (WSAGetLastError() == 10035) // No data is available right now, try again later
|
||||
return 0;
|
||||
#else
|
||||
|
||||
int x = errno;
|
||||
|
||||
if(x == EAGAIN)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (x == 0)
|
||||
{
|
||||
assert(bytesReceived != -1);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Sets an error code and message */
|
||||
static int SetError(DuckHttp_t* httpObj, SAL_ERR code, const char* appendMsg)
|
||||
{
|
||||
const char* decode = SalErrText(code);
|
||||
if (decode)
|
||||
{
|
||||
httpObj->errorString.str("");
|
||||
httpObj->errorString << decode;
|
||||
httpObj->lastErrorCode = code;
|
||||
if (appendMsg)
|
||||
httpObj->errorString << " : " << appendMsg;
|
||||
return code;
|
||||
}
|
||||
|
||||
return SAL_ERROR; // Default error
|
||||
}
|
||||
|
||||
|
||||
static int64_t http_atoi(const char* str)
|
||||
{
|
||||
int64_t temp = 0;
|
||||
size_t len = 0;
|
||||
|
||||
while(str[len] >= '0' && str[len] <= '9')
|
||||
len++;
|
||||
|
||||
for(size_t i = 0; i < len; i++)
|
||||
temp = temp * 10 + (str[i] - '0');
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Parses url for a parameter */
|
||||
inline bool get_url_parameter(const std::string url, std::string& parameter)
|
||||
{
|
||||
|
||||
std::string temp = url;
|
||||
size_t strPos;
|
||||
|
||||
strPos = temp.find(parameter.c_str());
|
||||
|
||||
if (strPos == std::string::npos)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = temp.substr(strPos + parameter.length() + 1);
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
for(i = 0; i < temp.length(); i++)
|
||||
{
|
||||
if (temp[i] == '&')
|
||||
temp[i] = '\0';
|
||||
}
|
||||
|
||||
parameter = temp.c_str();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if !defined(__cplusplus)
|
||||
#error
|
||||
#endif
|
||||
|
||||
char* duck_init_http(char *url)
|
||||
{
|
||||
std::string strTime = "timeout";
|
||||
std::string strBuff = "buffer";
|
||||
|
||||
DuckHttp_t* httpObj = new (DuckHttp_t);
|
||||
assert(httpObj);
|
||||
|
||||
httpObj->scheme = MAKE_FOUR_CC('h','t','t','p');
|
||||
|
||||
httpObj->urlExtended = url;
|
||||
|
||||
if (get_url_parameter(url, strTime))
|
||||
sscanf(strTime.c_str(),"%d", &httpObj->timeOut);
|
||||
else
|
||||
httpObj->timeOut = INT_MAX; // Wait "forever" is default
|
||||
|
||||
if (get_url_parameter(url, strBuff))
|
||||
{
|
||||
sscanf(strBuff.c_str(), "%d", &httpObj->cbSize);
|
||||
// Convert kilobytes into bytes
|
||||
httpObj->cbSize *= 1024;
|
||||
}
|
||||
else
|
||||
httpObj->cbSize = DEFAULT_CBSIZE;
|
||||
|
||||
for(size_t i = 0; i < strlen(url); i++)
|
||||
{
|
||||
if (url[i] == '?')
|
||||
url[i] = '\0';
|
||||
}
|
||||
|
||||
httpObj->url = url;
|
||||
httpObj->contentLen = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2,2), &wsaData))
|
||||
{
|
||||
std::ostringstream temp;
|
||||
temp << " : " << WSAGetLastError();
|
||||
SetError(httpObj,SAL_ERR_WSASTARTUP,temp.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (char *) httpObj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Might need to reduce timeout after initial buffering */
|
||||
/*------------------------------------------------------*/
|
||||
void duck_http_timeout(int handle, unsigned long milliseconds)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
httpObj->timeOut = milliseconds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int DECORATE(duck_open)(const char* src, unsigned long userData)
|
||||
{
|
||||
|
||||
struct sockaddr_in sa_in;
|
||||
struct sockaddr* const psa = (struct sockaddr*)&sa_in;
|
||||
struct hostent* host;
|
||||
std::ostringstream buf1;
|
||||
unsigned short port = 0;
|
||||
int input;
|
||||
char* endOfHttpHeader = "\r\n\r\n";
|
||||
char* strContentLen = "Content-Length: ";
|
||||
char* strPos;
|
||||
on2Timer start;
|
||||
(void) userData;
|
||||
unsigned long block = 1;
|
||||
DuckHttp_t* httpObj;
|
||||
|
||||
ReOpen_t* reOpenData = (ReOpen_t*) userData;
|
||||
|
||||
if(reOpenData == 0 || reOpenData->blocking || reOpenData->offset == 0)
|
||||
httpObj = (DuckHttp_t *) duck_init_http((char *) src);
|
||||
else
|
||||
httpObj = (DuckHttp_t *) src;
|
||||
|
||||
|
||||
if(!reOpenData) // if we're not doing a re-open
|
||||
httpObj->totalRead = 0;
|
||||
else
|
||||
httpObj->totalRead = reOpenData->offset;
|
||||
|
||||
|
||||
std::stringbuf path;
|
||||
std::stringbuf server;
|
||||
std::istringstream is(httpObj->url);
|
||||
|
||||
is.ignore(strlen("http://"), '\0');
|
||||
|
||||
// Check if a port is specified
|
||||
for(size_t i = strlen("http://"); i < httpObj->url.length(); i++)
|
||||
{
|
||||
if(httpObj->url[i] == ':')
|
||||
{
|
||||
port = 1;
|
||||
break;
|
||||
} else if(httpObj->url[i] == '/') break;
|
||||
}
|
||||
|
||||
if(port)
|
||||
{
|
||||
std::stringbuf strPort;
|
||||
|
||||
is.get(server,':');/* get the server */
|
||||
is.ignore(1, '\0');
|
||||
is.get(strPort, '/');
|
||||
port = (unsigned short)http_atoi(strPort.str().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
is.get(server,'/');/* get the server */
|
||||
|
||||
port = 80; // default http port
|
||||
}
|
||||
|
||||
assert(server.str().length() > 0);
|
||||
|
||||
is.ignore(1, '\0'); /* get the path */
|
||||
is.get(path, '\0');
|
||||
|
||||
/* Wrap up the send message */
|
||||
buf1 << "GET " << "/" << path.str() << " HTTP/1.1 " << "\r\n";
|
||||
buf1 << "Host:" << server.str().c_str() << "\r\n" ;
|
||||
|
||||
if (reOpenData)
|
||||
{
|
||||
char number[64];
|
||||
sprintf(number, i64Fmt, reOpenData->offset);
|
||||
buf1 << "Range: bytes=" << number << "-" ;
|
||||
buf1 << " \r\n" ;
|
||||
}
|
||||
buf1 << "\r\n";
|
||||
|
||||
if ((httpObj->socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_SOCKET_CREATE\n");
|
||||
SetError(httpObj,SAL_ERR_SOCKET_CREATE, 0);
|
||||
duck_exit_http((int)httpObj);
|
||||
return SAL_ERR_SOCKET_CREATE;
|
||||
}
|
||||
|
||||
sa_in.sin_family = AF_INET;
|
||||
sa_in.sin_port = htons(port);
|
||||
|
||||
if (!(host = gethostbyname(server.str().c_str())))
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_RESOLVING_HOSTNAME\n");
|
||||
SetError(httpObj,SAL_ERR_RESOLVING_HOSTNAME,0);
|
||||
duck_exit_http((int)httpObj);
|
||||
return SAL_ERR_RESOLVING_HOSTNAME;
|
||||
}
|
||||
|
||||
duck_memcpy(&sa_in.sin_addr, host->h_addr_list[0], sizeof(struct in_addr));
|
||||
|
||||
if (connect(httpObj->socket, psa, sizeof(sa_in) ) != 0)
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_SERVER_CONNECTION\n");
|
||||
SetError(httpObj,SAL_ERR_SERVER_CONNECTION,0);
|
||||
duck_exit_http((int)httpObj);
|
||||
return SAL_ERR_SERVER_CONNECTION;
|
||||
}
|
||||
|
||||
/* connected */
|
||||
|
||||
if (send(httpObj->socket, buf1.str().c_str(), strlen(buf1.str().c_str()), 0) < 0)
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_SENDING_DATA\n");
|
||||
SetError(httpObj,SAL_ERR_SENDING_DATA,0);
|
||||
duck_exit_http((int)httpObj);
|
||||
return SAL_ERR_SENDING_DATA;
|
||||
}
|
||||
|
||||
|
||||
on2Timer_Init(&start);
|
||||
on2Timer_Start(&start);
|
||||
|
||||
duck_memset(httpObj->httpHeader, 0, sizeof(httpObj->httpHeader));
|
||||
|
||||
/* Get the HTTP header EMH 2-14-03 */
|
||||
/* Assuming we get all the header info in the 1st good recv */
|
||||
do
|
||||
{
|
||||
unsigned long delta = on2Timer_GetCurrentElapsedMilli(&start);
|
||||
|
||||
if (delta > httpObj->timeOut)
|
||||
{
|
||||
return SetError(httpObj,SAL_ERR_CONNECTION_TIMEOUT,0);
|
||||
}
|
||||
|
||||
input = recv(httpObj->socket, httpObj->httpHeader, sizeof(httpObj->httpHeader), 0);
|
||||
} while (!strstr(httpObj->httpHeader, endOfHttpHeader));
|
||||
|
||||
#ifdef _WIN32
|
||||
ioctlsocket(httpObj->socket, FIONBIO, &block); /* Set the socket to non-blocking */
|
||||
#else
|
||||
if (ioctl(httpObj->socket, FIONBIO, &block)) /* Set the socket to non-blocking */
|
||||
{
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
strPos = strstr(httpObj->httpHeader, endOfHttpHeader);
|
||||
|
||||
strPos += strlen(endOfHttpHeader);
|
||||
|
||||
httpObj->headerSize = (int)strPos - (int)httpObj->httpHeader;
|
||||
|
||||
httpObj->xtraData = input - httpObj->headerSize; // Amount of GOOD data grabbed with the HTTP header
|
||||
|
||||
if (strstr(httpObj->httpHeader, "404") && strstr(httpObj->httpHeader, "Not Found"))
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_404_FILE_NOT_FOUND\n");
|
||||
SetError(httpObj,SAL_ERR_404_FILE_NOT_FOUND,0);
|
||||
duck_exit_http((int)httpObj);
|
||||
return SAL_ERR_404_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
strPos = strstr(httpObj->httpHeader, strContentLen);
|
||||
|
||||
if (!strPos)
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_PARSING_HTTP_HEADER\n");
|
||||
SetError(httpObj,SAL_ERR_PARSING_HTTP_HEADER,0);
|
||||
duck_exit_http((int)httpObj);
|
||||
return SAL_ERR_PARSING_HTTP_HEADER;
|
||||
}
|
||||
|
||||
strPos += strlen(strContentLen);
|
||||
|
||||
if((*strPos >= '0') && (*strPos <= '9'))
|
||||
{
|
||||
httpObj->contentLen = http_atoi(strPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_PARSING_CONTENT_LEN\n");
|
||||
SetError(httpObj,SAL_ERR_PARSING_CONTENT_LEN,0);
|
||||
duck_exit_http((int)httpObj);
|
||||
return SAL_ERR_PARSING_CONTENT_LEN;
|
||||
}
|
||||
|
||||
|
||||
int rv;
|
||||
|
||||
rv = initCircleBuffer(&httpObj->cBuffer, httpObj->cbSize, 75,
|
||||
httpObj->cbSize/4, /* max chunk */ 0, 0);
|
||||
|
||||
if (rv < 0)
|
||||
assert(0);
|
||||
|
||||
addToCircleBuffer(&httpObj->cBuffer,
|
||||
httpObj->httpHeader + httpObj->headerSize,
|
||||
(size_t) httpObj->xtraData);
|
||||
|
||||
bool blocking = true;
|
||||
/*
|
||||
// Block only if we're not doing a re-open
|
||||
userData ? blocking = false : blocking = true;
|
||||
*/
|
||||
if(reOpenData)
|
||||
blocking = (reOpenData->blocking != 0);
|
||||
|
||||
if (duck_sal_fill((void *) httpObj, blocking, 0) < 0)
|
||||
{
|
||||
fprintf(stderr, "duck_open: SAL_ERR_RECEIVING_DATA\n");
|
||||
duck_close_http((int)httpObj);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (int) httpObj;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void DECORATE(duck_close)(int handle)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
#if defined(_WIN32)
|
||||
closesocket(httpObj->socket); // Close the old socket
|
||||
#else
|
||||
close(httpObj->socket);
|
||||
#endif
|
||||
destroyCircleBuffer(&httpObj->cBuffer);
|
||||
|
||||
duck_exit_http(handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void duck_exit_http(int handle)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
//delete httpObj->cBuffer;
|
||||
delete httpObj;
|
||||
|
||||
#ifdef _WIN32
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Read data off of the socket directly into the circular buffer */
|
||||
inline int recv_circular (void* handle, size_t maxBytes)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
int bytesRead = 0;
|
||||
int totalRead = 0;
|
||||
|
||||
|
||||
size_t tail = (httpObj->cBuffer.head + httpObj->cBuffer.count) % httpObj->cBuffer.bufSize;
|
||||
size_t head = httpObj->cBuffer.head;
|
||||
size_t freeSpace = httpObj->cBuffer.bufSize - httpObj->cBuffer.count;
|
||||
size_t endSpace = httpObj->cBuffer.bufSize - tail;
|
||||
size_t least;
|
||||
|
||||
if (tail >= head && maxBytes > endSpace) /* additional data write will wrap */
|
||||
{
|
||||
/* try to fill to end of buffer */
|
||||
bytesRead = recv(httpObj->socket, (char*)httpObj->cBuffer.buffer + tail, (int)endSpace, 0);
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
if (isDataAvailable((int)bytesRead) == 0)
|
||||
return 0; // Try again later...
|
||||
else
|
||||
return (int)bytesRead; // Error
|
||||
}
|
||||
|
||||
totalRead += bytesRead;
|
||||
httpObj->cBuffer.count += bytesRead;
|
||||
maxBytes -= bytesRead;
|
||||
|
||||
freeSpace = httpObj->cBuffer.bufSize - httpObj->cBuffer.count;
|
||||
|
||||
if((size_t)bytesRead < maxBytes && (size_t)bytesRead == endSpace) /* filled to end and more to read */
|
||||
{
|
||||
httpObj->cBuffer.wrapped = 1;
|
||||
least = (maxBytes < freeSpace) ? maxBytes : freeSpace;
|
||||
bytesRead = recv(httpObj->socket, (char *)httpObj->cBuffer.buffer, (int)least, 0);
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
if (isDataAvailable((int)bytesRead) == 0)
|
||||
return 0; // Try again later...
|
||||
else
|
||||
return (int)bytesRead; // Error
|
||||
}
|
||||
|
||||
totalRead += bytesRead;
|
||||
httpObj->cBuffer.count += bytesRead;
|
||||
}
|
||||
}
|
||||
else /* existing data wrapped around from end of buffer through beginning of buffer. */
|
||||
{
|
||||
if (tail < head)
|
||||
httpObj->cBuffer.wrapped = 1;
|
||||
least = (maxBytes < freeSpace) ? maxBytes : freeSpace;
|
||||
bytesRead = recv(httpObj->socket, (char*)httpObj->cBuffer.buffer + tail, (int)least, 0);
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
if (isDataAvailable((int)bytesRead) == 0)
|
||||
return 0; // Try again later...
|
||||
else
|
||||
return (int)bytesRead; // Error
|
||||
}
|
||||
|
||||
totalRead += bytesRead;
|
||||
httpObj->cBuffer.count += bytesRead;
|
||||
}
|
||||
return (int)totalRead;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Re-charge the circular buffer */
|
||||
int duck_sal_fill(void * handle, bool blocking, size_t maxFill)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
on2Timer start;
|
||||
int bytesRead = 0;
|
||||
int totalRead = 0;
|
||||
|
||||
int fillLevel = httpObj->cBuffer.bufSize * httpObj->cBuffer.percent / 100;
|
||||
int fillSpace = fillLevel - httpObj->cBuffer.count;
|
||||
|
||||
if(maxFill)
|
||||
{
|
||||
// Charge twice as much as was read
|
||||
maxFill *=2;
|
||||
// Take the lesser of the two
|
||||
fillSpace = ((int)maxFill < fillSpace) ? maxFill : fillSpace;
|
||||
}
|
||||
|
||||
on2Timer_Init ( &start );
|
||||
on2Timer_Start ( &start );
|
||||
|
||||
while ((httpObj->cBuffer.count < (size_t)fillLevel) && ((int)httpObj->cBuffer.count < httpObj->contentLen))
|
||||
{
|
||||
unsigned long delta = on2Timer_GetCurrentElapsedMilli(&start);
|
||||
|
||||
if (delta > httpObj->timeOut)
|
||||
{
|
||||
std::ostringstream temp;
|
||||
temp << "Bytes received = " << totalRead;
|
||||
//return -1;
|
||||
return SetError(httpObj, SAL_ERR_CONNECTION_TIMEOUT, temp.str().c_str());
|
||||
}
|
||||
bytesRead = recv_circular(handle, fillSpace);
|
||||
|
||||
|
||||
#if defined(__APPLE__) || defined(__POWERPC__)
|
||||
if (bytesRead == 0 && blocking) /* please give some time to the SOCKET thread / OS . */
|
||||
usleep(1000*2);
|
||||
#endif
|
||||
|
||||
if (bytesRead < 0)
|
||||
{
|
||||
std::ostringstream temp;
|
||||
temp << " : WSAGetLastError = " << WSAGetLastError();
|
||||
SetError(httpObj,SAL_ERR_SERVER_CONNECTION,temp.str().c_str());
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
totalRead += bytesRead;
|
||||
|
||||
if (blocking == 0) /* we only want one recv done */
|
||||
return totalRead;
|
||||
|
||||
}
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int DECORATE(duck_read)(int handle,unsigned char *buffer, int bytes)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
int input;
|
||||
|
||||
if (bytes < 0)
|
||||
return -1;
|
||||
|
||||
assert(httpObj);
|
||||
assert(buffer);
|
||||
|
||||
input = readFromCircleBuffer(&httpObj->cBuffer, buffer, bytes);
|
||||
|
||||
if (input >= 1)
|
||||
{
|
||||
httpObj->totalRead += input;
|
||||
}
|
||||
|
||||
bool blocking = false;
|
||||
|
||||
if (duck_sal_fill((void *)handle, blocking, bytes) < 0)
|
||||
{
|
||||
return -1; // The socket probably disconnected
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int DECORATE(duck_read_blocking)(int handle,unsigned char *buffer, int bytes)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
int input;
|
||||
int amountRead = 0;
|
||||
|
||||
if (bytes < 0)
|
||||
return -1;
|
||||
|
||||
assert(httpObj);
|
||||
assert(buffer);
|
||||
|
||||
while (amountRead < bytes)
|
||||
{
|
||||
input = readFromCircleBuffer(
|
||||
&httpObj->cBuffer,
|
||||
buffer + amountRead,
|
||||
bytes - amountRead);
|
||||
|
||||
if (input < 0)
|
||||
return input;
|
||||
else
|
||||
{
|
||||
amountRead += input;
|
||||
httpObj->totalRead += input;
|
||||
}
|
||||
|
||||
bool blocking = false;
|
||||
|
||||
if (duck_sal_fill((void *)handle, blocking, bytes) < 0)
|
||||
{
|
||||
return -1; // The socket probably disconnected
|
||||
}
|
||||
}
|
||||
return amountRead;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t DECORATE(duck_seek)(int handle, int64_t offset,int origin)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
//printf("seeking to offset = %ld, origin = %ld\n", offset, origin);
|
||||
|
||||
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
fprintf(stderr, "Trying to seek backwards with offset = %d\n", offset);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (origin == SEEK_END)
|
||||
{
|
||||
fprintf(stderr, "SEEK_END is not supported\n", offset);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
if (origin == SEEK_SET)
|
||||
{
|
||||
if ( offset > httpObj->totalRead &&
|
||||
ForwardBuffer(&httpObj->cBuffer, (offset - httpObj->totalRead)) == 0
|
||||
) /* forward small jump */
|
||||
{
|
||||
// We've eaten away at the buffer so re-charge it.
|
||||
duck_sal_fill((void *)handle, false, (int)(offset - httpObj->totalRead));
|
||||
httpObj->totalRead = offset;
|
||||
return httpObj->totalRead;
|
||||
}
|
||||
|
||||
else if ( offset < httpObj->totalRead &&
|
||||
RewindBuffer(&httpObj->cBuffer, (httpObj->totalRead - offset)) == 0
|
||||
) /* backwards small jump */
|
||||
{
|
||||
httpObj->totalRead = offset;
|
||||
return httpObj->totalRead;
|
||||
}
|
||||
|
||||
else
|
||||
httpObj->totalRead = offset;
|
||||
}
|
||||
|
||||
|
||||
if (origin == SEEK_CUR)
|
||||
{
|
||||
if (!offset) // They just want the current pos
|
||||
return httpObj->totalRead;
|
||||
|
||||
httpObj->totalRead += offset;
|
||||
|
||||
if(ForwardBuffer(&httpObj->cBuffer, offset) == 0)
|
||||
{
|
||||
duck_sal_fill((void *)handle, false, (size_t)offset); // We've eaten away at the buffer so re-charge it.
|
||||
return httpObj->totalRead;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
closesocket(httpObj->socket); // Close the old socket
|
||||
#else
|
||||
close(httpObj->socket);
|
||||
#endif
|
||||
|
||||
destroyCircleBuffer(&httpObj->cBuffer);
|
||||
|
||||
ReOpen_t openData;
|
||||
openData.offset = httpObj->totalRead;
|
||||
openData.blocking = 0;
|
||||
|
||||
// Reconnect to http server
|
||||
if( duck_open_http((char* )handle, (unsigned long)&openData) < 0)
|
||||
{
|
||||
char err[256];
|
||||
SAL_ERR errCode;
|
||||
duck_sal_error_http((void*)handle, &errCode, err, sizeof(err));
|
||||
assert(0);
|
||||
return -1;
|
||||
}
|
||||
return httpObj->totalRead;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int64_t duck_tell(int handle)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
return httpObj->totalRead;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Return the amount of data in the circular buffer */
|
||||
int duck_sal_buff_percent(void* handle)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
return 100 * httpObj->cBuffer.count / httpObj->cBuffer.bufSize;
|
||||
}
|
||||
|
||||
|
||||
int64_t DECORATE(duck_available_data)(int handle)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
return httpObj->cBuffer.count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Checks the last error */
|
||||
int DECORATE(duck_sal_error)(void* handle, SAL_ERR* lastErrorCode, char buffer[], size_t maxLen)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
*lastErrorCode = httpObj->lastErrorCode;
|
||||
|
||||
if (httpObj->errorString.str().length() <= maxLen)
|
||||
{
|
||||
strcpy(buffer, httpObj->errorString.str().c_str());
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
int DECORATE(duck_name)(int handle, char url[], size_t maxLen)
|
||||
{
|
||||
DuckHttp_t* httpObj = (DuckHttp_t *) handle;
|
||||
|
||||
if (httpObj->urlExtended.length() <= maxLen)
|
||||
strcpy(url, httpObj->urlExtended.c_str());
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
110
Src/libvp6/corelibs/sal/generic/on2_timer.c
Normal file
110
Src/libvp6/corelibs/sal/generic/on2_timer.c
Normal file
@ -0,0 +1,110 @@
|
||||
#include "on2_timer.h"
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#if defined( WIN32 )
|
||||
const unsigned long MAX_BEFORE_ROLLOVER = (1000 * 60 * 60 * 24);
|
||||
#else
|
||||
const unsigned long MAX_BEFORE_ROLLOVER = 0xFFFFFFFF;
|
||||
#endif
|
||||
|
||||
// full day in milliseconds
|
||||
const unsigned long kDuckFullDayMilli = 86400000;
|
||||
|
||||
|
||||
void
|
||||
on2Timer_Init ( on2Timer* pTimer )
|
||||
{
|
||||
pTimer->elapsedMilli = 0;
|
||||
pTimer->baseMilli = 0;
|
||||
}
|
||||
|
||||
/* The DeInit function was in danger of trying to free statically allocated timers goofy */
|
||||
|
||||
|
||||
unsigned long
|
||||
on2Timer_Start ( on2Timer* pTimer )
|
||||
{
|
||||
pTimer->baseMilli = on2Timer_GetCurrentTimeMilli();
|
||||
pTimer->elapsedMilli = 0;
|
||||
return pTimer->baseMilli;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
on2Timer_Stop ( on2Timer* pTimer )
|
||||
{
|
||||
unsigned long currentMilli = on2Timer_GetCurrentTimeMilli();
|
||||
|
||||
if(currentMilli >= pTimer->baseMilli)
|
||||
{
|
||||
pTimer->elapsedMilli = currentMilli - pTimer->baseMilli;
|
||||
return pTimer->elapsedMilli;
|
||||
}
|
||||
// rollover condition, get milli before rollover, add to current milli
|
||||
// I think if there is a rollover during timing on win32 this will cause a crash
|
||||
// when the addition of currentMilli and rollMilli results in overflowing the size of
|
||||
// and unsigned long int
|
||||
else
|
||||
{
|
||||
unsigned long rollMilli = MAX_BEFORE_ROLLOVER - pTimer->baseMilli;
|
||||
pTimer->elapsedMilli = currentMilli + rollMilli;
|
||||
return pTimer->elapsedMilli;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long
|
||||
on2Timer_GetCurrentElapsedMilli ( on2Timer* pTimer )
|
||||
{
|
||||
unsigned long currentMilli = on2Timer_GetCurrentTimeMilli();
|
||||
|
||||
if(currentMilli >= pTimer->baseMilli)
|
||||
{
|
||||
return ( currentMilli - pTimer->baseMilli );
|
||||
}
|
||||
// rollover condition, get milli before rollover, add to current milli
|
||||
else
|
||||
{
|
||||
unsigned long rollMilli = MAX_BEFORE_ROLLOVER - pTimer->baseMilli;
|
||||
return ( currentMilli + rollMilli );
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long
|
||||
on2Timer_GetCurrentTimeSeconds ()
|
||||
{
|
||||
unsigned long currentMilli = on2Timer_GetCurrentTimeMilli();
|
||||
return currentMilli / 1000;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
on2Timer_GetCurrentTimeMilli ()
|
||||
{
|
||||
#if !defined(WIN32)
|
||||
unsigned long currentMilli;
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
gettimeofday ( &tv, &tz );
|
||||
currentMilli = (tv.tv_sec * 1000) + (tv.tv_usec/1000);
|
||||
return currentMilli;
|
||||
#else
|
||||
return timeGetTime();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
on2Timer_Sleep( int msec )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Sleep( msec );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
85
Src/libvp6/corelibs/sal/generic/on2_timer.h
Normal file
85
Src/libvp6/corelibs/sal/generic/on2_timer.h
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef _ON2_TIMER_H_
|
||||
#define _ON2_TIMER_H_
|
||||
|
||||
/************************************************************************/
|
||||
/* on2Timer: cross-platform timer, works on win32 and linux so far */
|
||||
/* started: August 14, 2001 */
|
||||
/* codemonkey: TJF */
|
||||
/************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct on2Timer_ {
|
||||
unsigned long baseMilli;
|
||||
unsigned long elapsedMilli;
|
||||
} on2Timer;
|
||||
|
||||
|
||||
|
||||
|
||||
/****************************************************************/
|
||||
/* void on2Timer_Init ( on2Timer* pTimer ) */
|
||||
/* initialize an allocated timer's members to 0 */
|
||||
/****************************************************************/
|
||||
void on2Timer_Init ( on2Timer* pTimer );
|
||||
|
||||
/****************************************************************/
|
||||
/* unsigned long on2Timer_Start ( on2Timer* pTimer ) */
|
||||
/* start a timer: sets baseTime to currentTime in milliseconds */
|
||||
/****************************************************************/
|
||||
unsigned long on2Timer_Start ( on2Timer* pTimer );
|
||||
|
||||
/****************************************************************/
|
||||
/* unsigned long on2Timer_Stop ( on2Timer* pTimer ) */
|
||||
/* stop a timer: sets elapsed time and accounts for rollover */
|
||||
/****************************************************************/
|
||||
unsigned long on2Timer_Stop ( on2Timer* pTimer );
|
||||
|
||||
/********************************************************************************/
|
||||
/* unsigned long on2Timer_GetCurrentElapsedMilli ( on2Timer* pTimer ) */
|
||||
/* get current elapsed time: returns elapsed time and accounts for rollover */
|
||||
/********************************************************************************/
|
||||
unsigned long on2Timer_GetCurrentElapsedMilli ( on2Timer* pTimer );
|
||||
|
||||
/********************************************************************************/
|
||||
/* unsigned long on2Timer_GetMilliBeforeRollover ( unsigned long baseMilli ) */
|
||||
/* returns milliseconds elapsed since rollover occurred */
|
||||
/********************************************************************************/
|
||||
unsigned long on2Timer_GetMilliBeforeRollover ( unsigned long baseMilli );
|
||||
|
||||
/****************************************************************/
|
||||
/* unsigned long on2Timer_GetCurrentTimeSeconds ( void ) */
|
||||
/* returns seconds since midnight */
|
||||
/****************************************************************/
|
||||
unsigned long on2Timer_GetCurrentTimeSeconds ( void );
|
||||
|
||||
/****************************************************************/
|
||||
/* unsigned long on2Timer_GetCurrentTimeMilli ( void ) */
|
||||
/* returns milliseconds since midnight */
|
||||
/****************************************************************/
|
||||
unsigned long on2Timer_GetCurrentTimeMilli ( void );
|
||||
|
||||
/****************************************************************/
|
||||
/* void on2Timer_DeInit ( on2Timer* pTimer ); */
|
||||
/* on2_free's a pointer to a on2Timer struct, for the lazy ;-) */
|
||||
/****************************************************************/
|
||||
void on2Timer_DeInit ( on2Timer* pTimer );
|
||||
|
||||
/****************************************************************/
|
||||
/* void on2Timer_Sleep ( int msec ); */
|
||||
/* Sleeps for the passed in number of milliseconds */
|
||||
/****************************************************************/
|
||||
int on2Timer_Sleep( int msec );
|
||||
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _ON2_TIMER_H_ */
|
228
Src/libvp6/corelibs/sal/sal.vcproj
Normal file
228
Src/libvp6/corelibs/sal/sal.vcproj
Normal file
@ -0,0 +1,228 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="sal"
|
||||
ProjectGUID="{7C45701D-CD78-4C6A-A551-C62952E163A6}"
|
||||
TargetFrameworkVersion="131072"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
InlineFunctionExpansion="1"
|
||||
AdditionalIncludeDirectories="..\include,..\..\include"
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
StringPooling="true"
|
||||
RuntimeLibrary="0"
|
||||
EnableFunctionLevelLinking="true"
|
||||
PrecompiledHeaderFile=".\..\..\..\ObjectCode\sal\Release/sal.pch"
|
||||
AssemblerListingLocation="..\..\..\ObjectCode\sal\Release/"
|
||||
ObjectFile="..\..\..\ObjectCode\sal\Release/"
|
||||
ProgramDataBaseFileName="..\..\..\ObjectCode\sal\Release/"
|
||||
WarningLevel="3"
|
||||
SuppressStartupBanner="true"
|
||||
CompileAs="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="NDEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="4"
|
||||
InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
|
||||
UseOfMFC="0"
|
||||
ATLMinimizesCRunTimeLibraryUsage="false"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\include,..\..\include"
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
PrecompiledHeaderFile=".\..\..\..\ObjectCode\sal\debug/sal.pch"
|
||||
AssemblerListingLocation="..\..\..\ObjectCode\sal\debug/"
|
||||
ObjectFile="..\..\..\ObjectCode\sal\debug/"
|
||||
ProgramDataBaseFileName="..\..\..\ObjectCode\sal\debug/"
|
||||
WarningLevel="4"
|
||||
SuppressStartupBanner="true"
|
||||
DebugInformationFormat="4"
|
||||
CompileAs="0"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
PreprocessorDefinitions="_DEBUG"
|
||||
Culture="1033"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
SuppressStartupBanner="true"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="win32"
|
||||
>
|
||||
<File
|
||||
RelativePath="win32\duck_io32.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="win32\duck_mem.c"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="2"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions=""
|
||||
BasicRuntimeChecks="3"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="generic"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
106
Src/libvp6/corelibs/sal/win32/duck_io.c
Normal file
106
Src/libvp6/corelibs/sal/win32/duck_io.c
Normal file
@ -0,0 +1,106 @@
|
||||
/***********************************************\
|
||||
??? duck_io.c
|
||||
\***********************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include "duck_io.h"
|
||||
#include "duck_hfb.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
int read_count;
|
||||
|
||||
|
||||
int duck_readFinished(int han, int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int duck_open(const char *name, unsigned long userData)
|
||||
{
|
||||
int f;
|
||||
FILE *fp;
|
||||
unsigned long x;
|
||||
|
||||
read_count = 0;
|
||||
|
||||
fp = fopen(name, "rb");
|
||||
|
||||
if (!fp)
|
||||
assert(0);
|
||||
|
||||
x = (unsigned long ) fp;
|
||||
|
||||
/* high bit is set, the cast is a bad idea ! */
|
||||
if (x & 0x90000000)
|
||||
assert(0);
|
||||
|
||||
f = (int ) x;
|
||||
|
||||
return f;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void duck_close(int handle)
|
||||
{
|
||||
fclose((FILE *) handle);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static long totalRead = 0;
|
||||
static long tellNo = 0;
|
||||
long duck_read(int handle,unsigned char *buffer,long bytes)
|
||||
{
|
||||
int x;
|
||||
|
||||
|
||||
if (buffer == NULL){
|
||||
duck_seek(handle,bytes,SEEK_CUR);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
tellNo = ftell((FILE *) handle);
|
||||
|
||||
if (bytes == 0)
|
||||
return 0;
|
||||
|
||||
|
||||
x = fread(buffer,sizeof(char) ,bytes, (FILE *) handle);
|
||||
|
||||
|
||||
if (feof((FILE *) handle) && (x != (int ) bytes))
|
||||
return -1;
|
||||
|
||||
|
||||
totalRead += x;
|
||||
|
||||
if (x == -1L)
|
||||
assert(0);
|
||||
|
||||
return x ;
|
||||
}
|
||||
|
||||
|
||||
long duck_seek(int handle,long offset,int origin)
|
||||
{
|
||||
long x = fseek((FILE *) handle,offset,origin);
|
||||
|
||||
tellNo = ftell((FILE *) handle);
|
||||
|
||||
return tellNo ;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
70
Src/libvp6/corelibs/sal/win32/duck_io32.c
Normal file
70
Src/libvp6/corelibs/sal/win32/duck_io32.c
Normal file
@ -0,0 +1,70 @@
|
||||
/***********************************************\
|
||||
??? duck_io.c
|
||||
\***********************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "duck_io.h"
|
||||
|
||||
int duck_open(const char *name, unsigned long userData)
|
||||
{
|
||||
char filename[255];
|
||||
(void) userData;
|
||||
|
||||
if(name[strlen(name)-4] != '.') { /*no extension, try .AVI */
|
||||
sprintf(filename,"%s.AVI",name);
|
||||
//f = open(filename,O_BINARY|O_RDONLY);
|
||||
//return(f);
|
||||
}else
|
||||
strcpy(filename,name);
|
||||
//return(open(filename,O_BINARY|O_RDONLY));
|
||||
return (int)CreateFile(filename,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
|
||||
}
|
||||
|
||||
void duck_close(int handle)
|
||||
{
|
||||
//close(handle);
|
||||
CloseHandle((void *)handle);
|
||||
}
|
||||
|
||||
long duck_read(int handle,unsigned char *buffer,long bytes)
|
||||
{
|
||||
DWORD bytesRead;
|
||||
|
||||
if (buffer == NULL){
|
||||
duck_seek(handle,bytes,SEEK_CUR);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
ReadFile((void *)handle,buffer,bytes,&bytesRead,NULL);
|
||||
//return(read(handle,buffer,bytes));
|
||||
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
int64_t duck_seek(int handle,int64_t offset,int origin)
|
||||
{
|
||||
//return(lseek(handle,offset,origin));
|
||||
return(SetFilePointer((HANDLE) handle,(LONG)offset,NULL,origin));
|
||||
}
|
||||
|
||||
int duck_readFinished(int han, int flag)
|
||||
{
|
||||
(void)han; // not used;
|
||||
(void)flag; // not used;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void set_iofuncs()
|
||||
{
|
||||
|
||||
// HFB_Setopen(duck_open);
|
||||
// HFB_Setclose(duck_close);
|
||||
// HFB_Setread(duck_read);
|
||||
// HFB_Setseek(duck_seek);
|
||||
}
|
132
Src/libvp6/corelibs/sal/win32/duck_mem.c
Normal file
132
Src/libvp6/corelibs/sal/win32/duck_mem.c
Normal file
@ -0,0 +1,132 @@
|
||||
/***********************************************\
|
||||
??? duck_mem.c
|
||||
\***********************************************/
|
||||
|
||||
#pragma warning(disable:4786)
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <dos.h>
|
||||
#include <time.h>
|
||||
#include <malloc.h>
|
||||
#include "duck_mem.h"
|
||||
#include "duck_io.h"
|
||||
//#include "duck_hfb.h"
|
||||
#include "duck_dxl.h"
|
||||
|
||||
//#define CHECK_MEM
|
||||
|
||||
#ifdef CHECK_MEM
|
||||
#include <map>
|
||||
#include "debug.h"
|
||||
#endif
|
||||
|
||||
#ifdef CHECK_MEM
|
||||
struct comp
|
||||
{
|
||||
bool operator()(void* v1, void* v2) const
|
||||
{
|
||||
return v1 < v2;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CHECK_MEM
|
||||
std::map<void*, size_t, struct comp> pointers;
|
||||
int g_allocs = 0;
|
||||
int g_frees = 0;
|
||||
#endif
|
||||
|
||||
void *duck_memmove( void *dst, const void *src, size_t length )
|
||||
{
|
||||
return memmove(dst, src, length);
|
||||
}
|
||||
|
||||
void *duck_malloc(size_t size, dmemType foo)
|
||||
{
|
||||
void *temp = malloc(size);
|
||||
|
||||
#ifdef CHECK_MEM
|
||||
g_allocs++;
|
||||
TRACE("a=%d\t%d\n", g_allocs, (int)temp);
|
||||
pointers[temp] = size;
|
||||
#endif
|
||||
return temp;
|
||||
}
|
||||
|
||||
void *duck_memset( void *dest, int c, size_t count )
|
||||
{
|
||||
return((void *) memset(dest, c, count));
|
||||
}
|
||||
|
||||
void *duck_calloc(size_t n,size_t size, dmemType foo)
|
||||
{
|
||||
void *temp = calloc(n, size);
|
||||
|
||||
#ifdef CHECK_MEM
|
||||
g_allocs++;
|
||||
TRACE("a=%d\t%d\n", g_allocs, (int)temp);
|
||||
pointers[temp] = size;
|
||||
#endif
|
||||
return temp;
|
||||
}
|
||||
|
||||
void duck_free(void *old_blk)
|
||||
{
|
||||
#ifdef CHECK_MEM
|
||||
g_frees++;
|
||||
TRACE("f=%d\t%d\n", g_frees, (int)old_blk);
|
||||
if(!pointers.erase(old_blk))
|
||||
assert(0);
|
||||
#endif
|
||||
free(old_blk);
|
||||
}
|
||||
|
||||
void* duck_realloc(void *src, size_t newSize, size_t oldSize)
|
||||
{
|
||||
void *temp;
|
||||
if(newSize <= oldSize)
|
||||
return src;
|
||||
|
||||
#ifdef CHECK_MEM
|
||||
temp = duck_malloc(newSize, DMEM_GENERAL);
|
||||
duck_memcpy(temp, src, oldSize);
|
||||
duck_free(src);
|
||||
#else
|
||||
temp = realloc(src, newSize);
|
||||
#endif
|
||||
return temp;
|
||||
}
|
||||
|
||||
void *duck_memcpy(void *dest, const void *source, size_t length)
|
||||
{
|
||||
return memcpy(dest,source,length);
|
||||
}
|
||||
|
||||
void *duck_memcpy64(void *dest, const void *source, int64_t length)
|
||||
{
|
||||
/* Not fully 64 bit compliant */
|
||||
return memcpy(dest,source,(size_t)length);
|
||||
}
|
||||
|
||||
|
||||
int duck_strcmp(const char *one, const char *two)
|
||||
{
|
||||
return strcmp(one, two);
|
||||
}
|
||||
|
||||
void set_memfuncs()
|
||||
{
|
||||
#if defined(DXV_DLL)
|
||||
DXV_Setmalloc(malloc);
|
||||
DXV_Setcalloc(calloc);
|
||||
DXV_Setfree(free);
|
||||
#endif
|
||||
|
||||
#if defined(HFB_DLL)
|
||||
HFB_Setmalloc(malloc);
|
||||
HFB_Setcalloc(calloc);
|
||||
HFB_Setfree(free);
|
||||
#endif
|
||||
}
|
19
Src/libvp6/corelibs/sal/win32/duck_str.c
Normal file
19
Src/libvp6/corelibs/sal/win32/duck_str.c
Normal file
@ -0,0 +1,19 @@
|
||||
/***********************************************\
|
||||
??? duck_io.c
|
||||
\***********************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "duck_io.h"
|
||||
#include "duck_hfb.h"
|
||||
|
||||
int duck_strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user